blob: e794f0932db56305e8fad0e44286bfccf22aac15 [file] [log] [blame]
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001// Copyright 2006-2009 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "api.h"
31#include "arguments.h"
32#include "ic-inl.h"
33#include "stub-cache.h"
34
kasperl@chromium.org71affb52009-05-26 05:44:31 +000035namespace v8 {
36namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037
38// -----------------------------------------------------------------------
39// StubCache implementation.
40
41
42StubCache::Entry StubCache::primary_[StubCache::kPrimaryTableSize];
43StubCache::Entry StubCache::secondary_[StubCache::kSecondaryTableSize];
44
45void StubCache::Initialize(bool create_heap_objects) {
46 ASSERT(IsPowerOf2(kPrimaryTableSize));
47 ASSERT(IsPowerOf2(kSecondaryTableSize));
48 if (create_heap_objects) {
49 HandleScope scope;
50 Clear();
51 }
52}
53
54
55Code* StubCache::Set(String* name, Map* map, Code* code) {
56 // Get the flags from the code.
57 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
58
59 // Validate that the name does not move on scavenge, and that we
60 // can use identity checks instead of string equality checks.
61 ASSERT(!Heap::InNewSpace(name));
62 ASSERT(name->IsSymbol());
63
64 // The state bits are not important to the hash function because
65 // the stub cache only contains monomorphic stubs. Make sure that
66 // the bits are the least significant so they will be the ones
67 // masked out.
kasper.lund7276f142008-07-30 08:49:36 +000068 ASSERT(Code::ExtractICStateFromFlags(flags) == MONOMORPHIC);
69 ASSERT(Code::kFlagsICStateShift == 0);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000070
71 // Make sure that the code type is not included in the hash.
72 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
73
74 // Compute the primary entry.
75 int primary_offset = PrimaryOffset(name, flags, map);
76 Entry* primary = entry(primary_, primary_offset);
77 Code* hit = primary->value;
78
79 // If the primary entry has useful data in it, we retire it to the
80 // secondary cache before overwriting it.
81 if (hit != Builtins::builtin(Builtins::Illegal)) {
82 Code::Flags primary_flags = Code::RemoveTypeFromFlags(hit->flags());
83 int secondary_offset =
84 SecondaryOffset(primary->key, primary_flags, primary_offset);
85 Entry* secondary = entry(secondary_, secondary_offset);
86 *secondary = *primary;
87 }
88
89 // Update primary cache.
90 primary->key = name;
91 primary->value = code;
92 return code;
93}
94
95
lrn@chromium.org303ada72010-10-27 09:33:13 +000096MaybeObject* StubCache::ComputeLoadNonexistent(String* name,
97 JSObject* receiver) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +000098 ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties());
ricow@chromium.orgc9c80822010-04-21 08:22:37 +000099 // If no global objects are present in the prototype chain, the load
100 // nonexistent IC stub can be shared for all names for a given map
101 // and we use the empty string for the map cache in that case. If
102 // there are global objects involved, we need to check global
103 // property cells in the stub and therefore the stub will be
104 // specific to the name.
105 String* cache_name = Heap::empty_string();
106 if (receiver->IsGlobalObject()) cache_name = name;
107 JSObject* last = receiver;
108 while (last->GetPrototype() != Heap::null_value()) {
109 last = JSObject::cast(last->GetPrototype());
110 if (last->IsGlobalObject()) cache_name = name;
111 }
112 // Compile the stub that is either shared for all names or
113 // name specific if there are global objects involved.
114 Code::Flags flags =
115 Code::ComputeMonomorphicFlags(Code::LOAD_IC, NONEXISTENT);
116 Object* code = receiver->map()->FindInCodeCache(cache_name, flags);
117 if (code->IsUndefined()) {
118 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000119 { MaybeObject* maybe_code =
120 compiler.CompileLoadNonexistent(cache_name, receiver, last);
121 if (!maybe_code->ToObject(&code)) return maybe_code;
122 }
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000123 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), cache_name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000124 Object* result;
125 { MaybeObject* maybe_result =
126 receiver->UpdateMapCodeCache(cache_name, Code::cast(code));
127 if (!maybe_result->ToObject(&result)) return maybe_result;
128 }
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000129 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000130 return code;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000131}
132
133
lrn@chromium.org303ada72010-10-27 09:33:13 +0000134MaybeObject* StubCache::ComputeLoadField(String* name,
135 JSObject* receiver,
136 JSObject* holder,
137 int field_index) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000138 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000139 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000140 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000141 if (code->IsUndefined()) {
142 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000143 { MaybeObject* maybe_code =
144 compiler.CompileLoadField(receiver, holder, field_index, name);
145 if (!maybe_code->ToObject(&code)) return maybe_code;
146 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000147 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000148 Object* result;
149 { MaybeObject* maybe_result =
150 receiver->UpdateMapCodeCache(name, Code::cast(code));
151 if (!maybe_result->ToObject(&result)) return maybe_result;
152 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000153 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000154 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000155}
156
157
lrn@chromium.org303ada72010-10-27 09:33:13 +0000158MaybeObject* StubCache::ComputeLoadCallback(String* name,
159 JSObject* receiver,
160 JSObject* holder,
161 AccessorInfo* callback) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000162 ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000163 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000164 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000165 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000166 if (code->IsUndefined()) {
167 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000168 { MaybeObject* maybe_code =
169 compiler.CompileLoadCallback(name, receiver, holder, callback);
170 if (!maybe_code->ToObject(&code)) return maybe_code;
171 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000172 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000173 Object* result;
174 { MaybeObject* maybe_result =
175 receiver->UpdateMapCodeCache(name, Code::cast(code));
176 if (!maybe_result->ToObject(&result)) return maybe_result;
177 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000179 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000180}
181
182
lrn@chromium.org303ada72010-10-27 09:33:13 +0000183MaybeObject* StubCache::ComputeLoadConstant(String* name,
184 JSObject* receiver,
185 JSObject* holder,
186 Object* value) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000187 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188 Code::Flags flags =
189 Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000190 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000191 if (code->IsUndefined()) {
192 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000193 { MaybeObject* maybe_code =
194 compiler.CompileLoadConstant(receiver, holder, value, name);
195 if (!maybe_code->ToObject(&code)) return maybe_code;
196 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000197 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000198 Object* result;
199 { MaybeObject* maybe_result =
200 receiver->UpdateMapCodeCache(name, Code::cast(code));
201 if (!maybe_result->ToObject(&result)) return maybe_result;
202 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000203 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000204 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000205}
206
207
lrn@chromium.org303ada72010-10-27 09:33:13 +0000208MaybeObject* StubCache::ComputeLoadInterceptor(String* name,
209 JSObject* receiver,
210 JSObject* holder) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000211 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000213 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000214 if (code->IsUndefined()) {
215 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000216 { MaybeObject* maybe_code =
217 compiler.CompileLoadInterceptor(receiver, holder, name);
218 if (!maybe_code->ToObject(&code)) return maybe_code;
219 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000220 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000221 Object* result;
222 { MaybeObject* maybe_result =
223 receiver->UpdateMapCodeCache(name, Code::cast(code));
224 if (!maybe_result->ToObject(&result)) return maybe_result;
225 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000226 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000227 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000228}
229
230
lrn@chromium.org303ada72010-10-27 09:33:13 +0000231MaybeObject* StubCache::ComputeLoadNormal() {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000232 return Builtins::builtin(Builtins::LoadIC_Normal);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000233}
234
235
lrn@chromium.org303ada72010-10-27 09:33:13 +0000236MaybeObject* StubCache::ComputeLoadGlobal(String* name,
237 JSObject* receiver,
238 GlobalObject* holder,
239 JSGlobalPropertyCell* cell,
240 bool is_dont_delete) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000241 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000242 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000243 Object* code = receiver->map()->FindInCodeCache(name, flags);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000244 if (code->IsUndefined()) {
245 LoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000246 { MaybeObject* maybe_code = compiler.CompileLoadGlobal(receiver,
247 holder,
248 cell,
249 name,
250 is_dont_delete);
251 if (!maybe_code->ToObject(&code)) return maybe_code;
252 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000253 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000254 Object* result;
255 { MaybeObject* maybe_result =
256 receiver->UpdateMapCodeCache(name, Code::cast(code));
257 if (!maybe_result->ToObject(&result)) return maybe_result;
258 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000259 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000260 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000261}
262
263
lrn@chromium.org303ada72010-10-27 09:33:13 +0000264MaybeObject* StubCache::ComputeKeyedLoadField(String* name,
265 JSObject* receiver,
266 JSObject* holder,
267 int field_index) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000268 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000269 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000270 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000271 if (code->IsUndefined()) {
272 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000273 { MaybeObject* maybe_code =
274 compiler.CompileLoadField(name, receiver, holder, field_index);
275 if (!maybe_code->ToObject(&code)) return maybe_code;
276 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000277 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000278 Object* result;
279 { MaybeObject* maybe_result =
280 receiver->UpdateMapCodeCache(name, Code::cast(code));
281 if (!maybe_result->ToObject(&result)) return maybe_result;
282 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000283 }
284 return code;
285}
286
287
lrn@chromium.org303ada72010-10-27 09:33:13 +0000288MaybeObject* StubCache::ComputeKeyedLoadConstant(String* name,
289 JSObject* receiver,
290 JSObject* holder,
291 Object* value) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000292 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000293 Code::Flags flags =
294 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000295 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000296 if (code->IsUndefined()) {
297 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000298 { MaybeObject* maybe_code =
299 compiler.CompileLoadConstant(name, receiver, holder, value);
300 if (!maybe_code->ToObject(&code)) return maybe_code;
301 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000302 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000303 Object* result;
304 { MaybeObject* maybe_result =
305 receiver->UpdateMapCodeCache(name, Code::cast(code));
306 if (!maybe_result->ToObject(&result)) return maybe_result;
307 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000308 }
309 return code;
310}
311
312
lrn@chromium.org303ada72010-10-27 09:33:13 +0000313MaybeObject* StubCache::ComputeKeyedLoadInterceptor(String* name,
314 JSObject* receiver,
315 JSObject* holder) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000316 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000317 Code::Flags flags =
318 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000319 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000320 if (code->IsUndefined()) {
321 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000322 { MaybeObject* maybe_code =
323 compiler.CompileLoadInterceptor(receiver, holder, name);
324 if (!maybe_code->ToObject(&code)) return maybe_code;
325 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000326 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000327 Object* result;
328 { MaybeObject* maybe_result =
329 receiver->UpdateMapCodeCache(name, Code::cast(code));
330 if (!maybe_result->ToObject(&result)) return maybe_result;
331 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000332 }
333 return code;
334}
335
336
lrn@chromium.org303ada72010-10-27 09:33:13 +0000337MaybeObject* StubCache::ComputeKeyedLoadCallback(String* name,
338 JSObject* receiver,
339 JSObject* holder,
340 AccessorInfo* callback) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000341 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000342 Code::Flags flags =
343 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000344 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000345 if (code->IsUndefined()) {
346 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000347 { MaybeObject* maybe_code =
348 compiler.CompileLoadCallback(name, receiver, holder, callback);
349 if (!maybe_code->ToObject(&code)) return maybe_code;
350 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000351 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000352 Object* result;
353 { MaybeObject* maybe_result =
354 receiver->UpdateMapCodeCache(name, Code::cast(code));
355 if (!maybe_result->ToObject(&result)) return maybe_result;
356 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000357 }
358 return code;
359}
360
361
362
lrn@chromium.org303ada72010-10-27 09:33:13 +0000363MaybeObject* StubCache::ComputeKeyedLoadArrayLength(String* name,
364 JSArray* receiver) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000365 Code::Flags flags =
366 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000367 ASSERT(receiver->IsJSObject());
ricow@chromium.org65fae842010-08-25 15:26:24 +0000368 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000369 if (code->IsUndefined()) {
370 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000371 { MaybeObject* maybe_code = compiler.CompileLoadArrayLength(name);
372 if (!maybe_code->ToObject(&code)) return maybe_code;
373 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000374 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000375 Object* result;
376 { MaybeObject* maybe_result =
377 receiver->UpdateMapCodeCache(name, Code::cast(code));
378 if (!maybe_result->ToObject(&result)) return maybe_result;
379 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000380 }
381 return code;
382}
383
384
lrn@chromium.org303ada72010-10-27 09:33:13 +0000385MaybeObject* StubCache::ComputeKeyedLoadStringLength(String* name,
386 String* receiver) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000387 Code::Flags flags =
388 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000389 Map* map = receiver->map();
390 Object* code = map->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000391 if (code->IsUndefined()) {
392 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000393 { MaybeObject* maybe_code = compiler.CompileLoadStringLength(name);
394 if (!maybe_code->ToObject(&code)) return maybe_code;
395 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000396 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000397 Object* result;
398 { MaybeObject* maybe_result = map->UpdateCodeCache(name, Code::cast(code));
399 if (!maybe_result->ToObject(&result)) return maybe_result;
400 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000401 }
402 return code;
403}
404
405
lrn@chromium.org303ada72010-10-27 09:33:13 +0000406MaybeObject* StubCache::ComputeKeyedLoadFunctionPrototype(
407 String* name,
408 JSFunction* receiver) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000409 Code::Flags flags =
410 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000411 Object* code = receiver->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000412 if (code->IsUndefined()) {
413 KeyedLoadStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000414 { MaybeObject* maybe_code = compiler.CompileLoadFunctionPrototype(name);
415 if (!maybe_code->ToObject(&code)) return maybe_code;
416 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000417 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000418 Object* result;
419 { MaybeObject* maybe_result =
420 receiver->UpdateMapCodeCache(name, Code::cast(code));
421 if (!maybe_result->ToObject(&result)) return maybe_result;
422 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000423 }
424 return code;
425}
426
427
lrn@chromium.org303ada72010-10-27 09:33:13 +0000428MaybeObject* StubCache::ComputeStoreField(String* name,
429 JSObject* receiver,
430 int field_index,
431 Map* transition) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000432 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
433 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type);
434 Object* code = receiver->map()->FindInCodeCache(name, flags);
435 if (code->IsUndefined()) {
436 StoreStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000437 { MaybeObject* maybe_code =
438 compiler.CompileStoreField(receiver, field_index, transition, name);
439 if (!maybe_code->ToObject(&code)) return maybe_code;
440 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000441 PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000442 Object* result;
443 { MaybeObject* maybe_result =
444 receiver->UpdateMapCodeCache(name, Code::cast(code));
445 if (!maybe_result->ToObject(&result)) return maybe_result;
446 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000447 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000448 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000449}
450
451
lrn@chromium.org303ada72010-10-27 09:33:13 +0000452MaybeObject* StubCache::ComputeStoreNormal() {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000453 return Builtins::builtin(Builtins::StoreIC_Normal);
454}
455
456
lrn@chromium.org303ada72010-10-27 09:33:13 +0000457MaybeObject* StubCache::ComputeStoreGlobal(String* name,
458 GlobalObject* receiver,
459 JSGlobalPropertyCell* cell) {
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000460 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL);
461 Object* code = receiver->map()->FindInCodeCache(name, flags);
462 if (code->IsUndefined()) {
463 StoreStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000464 { MaybeObject* maybe_code =
465 compiler.CompileStoreGlobal(receiver, cell, name);
466 if (!maybe_code->ToObject(&code)) return maybe_code;
467 }
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000468 PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000469 Object* result;
470 { MaybeObject* maybe_result =
471 receiver->UpdateMapCodeCache(name, Code::cast(code));
472 if (!maybe_result->ToObject(&result)) return maybe_result;
473 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000474 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000475 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000476}
477
478
lrn@chromium.org303ada72010-10-27 09:33:13 +0000479MaybeObject* StubCache::ComputeStoreCallback(String* name,
480 JSObject* receiver,
481 AccessorInfo* callback) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000482 ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
483 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, CALLBACKS);
484 Object* code = receiver->map()->FindInCodeCache(name, flags);
485 if (code->IsUndefined()) {
486 StoreStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000487 { MaybeObject* maybe_code =
488 compiler.CompileStoreCallback(receiver, callback, name);
489 if (!maybe_code->ToObject(&code)) return maybe_code;
490 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000491 PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000492 Object* result;
493 { MaybeObject* maybe_result =
494 receiver->UpdateMapCodeCache(name, Code::cast(code));
495 if (!maybe_result->ToObject(&result)) return maybe_result;
496 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000497 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000498 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000499}
500
501
lrn@chromium.org303ada72010-10-27 09:33:13 +0000502MaybeObject* StubCache::ComputeStoreInterceptor(String* name,
503 JSObject* receiver) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000504 Code::Flags flags =
505 Code::ComputeMonomorphicFlags(Code::STORE_IC, INTERCEPTOR);
506 Object* code = receiver->map()->FindInCodeCache(name, flags);
507 if (code->IsUndefined()) {
508 StoreStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000509 { MaybeObject* maybe_code =
510 compiler.CompileStoreInterceptor(receiver, name);
511 if (!maybe_code->ToObject(&code)) return maybe_code;
512 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000513 PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000514 Object* result;
515 { MaybeObject* maybe_result =
516 receiver->UpdateMapCodeCache(name, Code::cast(code));
517 if (!maybe_result->ToObject(&result)) return maybe_result;
518 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000520 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000521}
522
523
lrn@chromium.org303ada72010-10-27 09:33:13 +0000524MaybeObject* StubCache::ComputeKeyedStoreField(String* name,
525 JSObject* receiver,
526 int field_index,
527 Map* transition) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000528 PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
529 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
530 Object* code = receiver->map()->FindInCodeCache(name, flags);
531 if (code->IsUndefined()) {
532 KeyedStoreStubCompiler compiler;
lrn@chromium.org303ada72010-10-27 09:33:13 +0000533 { MaybeObject* maybe_code =
534 compiler.CompileStoreField(receiver, field_index, transition, name);
535 if (!maybe_code->ToObject(&code)) return maybe_code;
536 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000537 PROFILE(CodeCreateEvent(
538 Logger::KEYED_STORE_IC_TAG, Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000539 Object* result;
540 { MaybeObject* maybe_result =
541 receiver->UpdateMapCodeCache(name, Code::cast(code));
542 if (!maybe_result->ToObject(&result)) return maybe_result;
543 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000544 }
545 return code;
546}
547
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000548#define CALL_LOGGER_TAG(kind, type) \
549 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000550
lrn@chromium.org303ada72010-10-27 09:33:13 +0000551MaybeObject* StubCache::ComputeCallConstant(int argc,
552 InLoopFlag in_loop,
553 Code::Kind kind,
554 String* name,
555 Object* object,
556 JSObject* holder,
557 JSFunction* function) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000558 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000559 InlineCacheHolderFlag cache_holder =
560 IC::GetCodeCacheForObject(object, holder);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000561 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000562
563 // Compute check type based on receiver/holder.
564 StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK;
565 if (object->IsString()) {
566 check = StubCompiler::STRING_CHECK;
567 } else if (object->IsNumber()) {
568 check = StubCompiler::NUMBER_CHECK;
569 } else if (object->IsBoolean()) {
570 check = StubCompiler::BOOLEAN_CHECK;
571 }
572
573 Code::Flags flags =
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000574 Code::ComputeMonomorphicFlags(kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000575 CONSTANT_FUNCTION,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000576 cache_holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000577 in_loop,
578 argc);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000579 Object* code = map_holder->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580 if (code->IsUndefined()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000581 // If the function hasn't been compiled yet, we cannot do it now
582 // because it may cause GC. To avoid this issue, we return an
583 // internal error which will make sure we do not update any
584 // caches.
585 if (!function->is_compiled()) return Failure::InternalError();
586 // Compile the stub - only create stubs for fully compiled functions.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000587 CallStubCompiler compiler(argc, in_loop, kind, cache_holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000588 { MaybeObject* maybe_code =
589 compiler.CompileCallConstant(object, holder, function, name, check);
590 if (!maybe_code->ToObject(&code)) return maybe_code;
591 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000592 ASSERT_EQ(flags, Code::cast(code)->flags());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000593 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
594 Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000595 Object* result;
596 { MaybeObject* maybe_result =
597 map_holder->UpdateMapCodeCache(name, Code::cast(code));
598 if (!maybe_result->ToObject(&result)) return maybe_result;
599 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000600 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000601 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000602}
603
604
lrn@chromium.org303ada72010-10-27 09:33:13 +0000605MaybeObject* StubCache::ComputeCallField(int argc,
606 InLoopFlag in_loop,
607 Code::Kind kind,
608 String* name,
609 Object* object,
610 JSObject* holder,
611 int index) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000612 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000613 InlineCacheHolderFlag cache_holder =
614 IC::GetCodeCacheForObject(object, holder);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000615 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000616
617 // TODO(1233596): We cannot do receiver map check for non-JS objects
618 // because they may be represented as immediates without a
619 // map. Instead, we check against the map in the holder.
620 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
621 object = holder;
622 }
623
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000624 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000625 FIELD,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000626 cache_holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000627 in_loop,
628 argc);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000629 Object* code = map_holder->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000630 if (code->IsUndefined()) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000631 CallStubCompiler compiler(argc, in_loop, kind, cache_holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000632 { MaybeObject* maybe_code =
633 compiler.CompileCallField(JSObject::cast(object),
634 holder,
635 index,
636 name);
637 if (!maybe_code->ToObject(&code)) return maybe_code;
638 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000639 ASSERT_EQ(flags, Code::cast(code)->flags());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000640 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
641 Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000642 Object* result;
643 { MaybeObject* maybe_result =
644 map_holder->UpdateMapCodeCache(name, Code::cast(code));
645 if (!maybe_result->ToObject(&result)) return maybe_result;
646 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000647 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000648 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000649}
650
651
lrn@chromium.org303ada72010-10-27 09:33:13 +0000652MaybeObject* StubCache::ComputeCallInterceptor(int argc,
653 Code::Kind kind,
654 String* name,
655 Object* object,
656 JSObject* holder) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000657 // Compute the check type and the map.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000658 InlineCacheHolderFlag cache_holder =
659 IC::GetCodeCacheForObject(object, holder);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000660 JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000661
662 // TODO(1233596): We cannot do receiver map check for non-JS objects
663 // because they may be represented as immediates without a
664 // map. Instead, we check against the map in the holder.
665 if (object->IsNumber() || object->IsBoolean() || object->IsString()) {
666 object = holder;
667 }
668
669 Code::Flags flags =
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000670 Code::ComputeMonomorphicFlags(kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000671 INTERCEPTOR,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000672 cache_holder,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000673 NOT_IN_LOOP,
674 argc);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000675 Object* code = map_holder->map()->FindInCodeCache(name, flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000676 if (code->IsUndefined()) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000677 CallStubCompiler compiler(argc, NOT_IN_LOOP, kind, cache_holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000678 { MaybeObject* maybe_code =
679 compiler.CompileCallInterceptor(JSObject::cast(object), holder, name);
680 if (!maybe_code->ToObject(&code)) return maybe_code;
681 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000682 ASSERT_EQ(flags, Code::cast(code)->flags());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000683 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
684 Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000685 Object* result;
686 { MaybeObject* maybe_result =
687 map_holder->UpdateMapCodeCache(name, Code::cast(code));
688 if (!maybe_result->ToObject(&result)) return maybe_result;
689 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000690 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000691 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000692}
693
694
lrn@chromium.org303ada72010-10-27 09:33:13 +0000695MaybeObject* StubCache::ComputeCallNormal(int argc,
696 InLoopFlag in_loop,
697 Code::Kind kind,
698 String* name,
699 JSObject* receiver) {
700 Object* code;
701 { MaybeObject* maybe_code = ComputeCallNormal(argc, in_loop, kind);
702 if (!maybe_code->ToObject(&code)) return maybe_code;
703 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000704 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000705}
706
707
lrn@chromium.org303ada72010-10-27 09:33:13 +0000708MaybeObject* StubCache::ComputeCallGlobal(int argc,
709 InLoopFlag in_loop,
710 Code::Kind kind,
711 String* name,
712 JSObject* receiver,
713 GlobalObject* holder,
714 JSGlobalPropertyCell* cell,
715 JSFunction* function) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000716 InlineCacheHolderFlag cache_holder =
717 IC::GetCodeCacheForObject(receiver, holder);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000718 JSObject* map_holder = IC::GetCodeCacheHolder(receiver, cache_holder);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000719 Code::Flags flags =
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000720 Code::ComputeMonomorphicFlags(kind,
721 NORMAL,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000722 cache_holder,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000723 in_loop,
724 argc);
ricow@chromium.org65fae842010-08-25 15:26:24 +0000725 Object* code = map_holder->map()->FindInCodeCache(name, flags);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000726 if (code->IsUndefined()) {
727 // If the function hasn't been compiled yet, we cannot do it now
728 // because it may cause GC. To avoid this issue, we return an
729 // internal error which will make sure we do not update any
730 // caches.
731 if (!function->is_compiled()) return Failure::InternalError();
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000732 CallStubCompiler compiler(argc, in_loop, kind, cache_holder);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000733 { MaybeObject* maybe_code =
734 compiler.CompileCallGlobal(receiver, holder, cell, function, name);
735 if (!maybe_code->ToObject(&code)) return maybe_code;
736 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000737 ASSERT_EQ(flags, Code::cast(code)->flags());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000738 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
739 Code::cast(code), name));
lrn@chromium.org303ada72010-10-27 09:33:13 +0000740 Object* result;
741 { MaybeObject* maybe_result =
742 map_holder->UpdateMapCodeCache(name, Code::cast(code));
743 if (!maybe_result->ToObject(&result)) return maybe_result;
744 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000745 }
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000746 return code;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000747}
748
749
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000750static Object* GetProbeValue(Code::Flags flags) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000751 // Use raw_unchecked... so we don't get assert failures during GC.
752 NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache();
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000753 int entry = dictionary->FindEntry(flags);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000754 if (entry != -1) return dictionary->ValueAt(entry);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000755 return Heap::raw_unchecked_undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000756}
757
758
lrn@chromium.org303ada72010-10-27 09:33:13 +0000759MUST_USE_RESULT static MaybeObject* ProbeCache(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000760 Object* probe = GetProbeValue(flags);
761 if (probe != Heap::undefined_value()) return probe;
762 // Seed the cache with an undefined value to make sure that any
763 // generated code object can always be inserted into the cache
764 // without causing allocation failures.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000765 Object* result;
766 { MaybeObject* maybe_result =
767 Heap::non_monomorphic_cache()->AtNumberPut(flags,
768 Heap::undefined_value());
769 if (!maybe_result->ToObject(&result)) return maybe_result;
770 }
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000771 Heap::public_set_non_monomorphic_cache(NumberDictionary::cast(result));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000772 return probe;
773}
774
775
lrn@chromium.org303ada72010-10-27 09:33:13 +0000776static MaybeObject* FillCache(MaybeObject* maybe_code) {
777 Object* code;
778 if (maybe_code->ToObject(&code)) {
779 if (code->IsCode()) {
780 int entry =
781 Heap::non_monomorphic_cache()->FindEntry(
782 Code::cast(code)->flags());
783 // The entry must be present see comment in ProbeCache.
784 ASSERT(entry != -1);
785 ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) ==
786 Heap::undefined_value());
787 Heap::non_monomorphic_cache()->ValueAtPut(entry, code);
788 CHECK(GetProbeValue(Code::cast(code)->flags()) == code);
789 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000790 }
lrn@chromium.org303ada72010-10-27 09:33:13 +0000791 return maybe_code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000792}
793
794
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000795Code* StubCache::FindCallInitialize(int argc,
796 InLoopFlag in_loop,
797 Code::Kind kind) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000798 Code::Flags flags =
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000799 Code::ComputeFlags(kind, in_loop, UNINITIALIZED, NORMAL, argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000800 Object* result = ProbeCache(flags)->ToObjectUnchecked();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000801 ASSERT(!result->IsUndefined());
802 // This might be called during the marking phase of the collector
803 // hence the unchecked cast.
804 return reinterpret_cast<Code*>(result);
805}
806
807
lrn@chromium.org303ada72010-10-27 09:33:13 +0000808MaybeObject* StubCache::ComputeCallInitialize(int argc,
809 InLoopFlag in_loop,
810 Code::Kind kind) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000811 Code::Flags flags =
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000812 Code::ComputeFlags(kind, in_loop, UNINITIALIZED, NORMAL, argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000813 Object* probe;
814 { MaybeObject* maybe_probe = ProbeCache(flags);
815 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
816 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000817 if (!probe->IsUndefined()) return probe;
818 StubCompiler compiler;
819 return FillCache(compiler.CompileCallInitialize(flags));
820}
821
822
lrn@chromium.org303ada72010-10-27 09:33:13 +0000823MaybeObject* StubCache::ComputeCallPreMonomorphic(int argc,
824 InLoopFlag in_loop,
825 Code::Kind kind) {
ager@chromium.org3bf7b912008-11-17 09:09:45 +0000826 Code::Flags flags =
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000827 Code::ComputeFlags(kind, in_loop, PREMONOMORPHIC, NORMAL, argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000828 Object* probe;
829 { MaybeObject* maybe_probe = ProbeCache(flags);
830 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
831 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000832 if (!probe->IsUndefined()) return probe;
833 StubCompiler compiler;
834 return FillCache(compiler.CompileCallPreMonomorphic(flags));
835}
836
837
lrn@chromium.org303ada72010-10-27 09:33:13 +0000838MaybeObject* StubCache::ComputeCallNormal(int argc,
839 InLoopFlag in_loop,
840 Code::Kind kind) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000841 Code::Flags flags =
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000842 Code::ComputeFlags(kind, in_loop, MONOMORPHIC, NORMAL, argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000843 Object* probe;
844 { MaybeObject* maybe_probe = ProbeCache(flags);
845 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
846 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000847 if (!probe->IsUndefined()) return probe;
848 StubCompiler compiler;
849 return FillCache(compiler.CompileCallNormal(flags));
850}
851
852
lrn@chromium.org303ada72010-10-27 09:33:13 +0000853MaybeObject* StubCache::ComputeCallMegamorphic(int argc,
854 InLoopFlag in_loop,
855 Code::Kind kind) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000856 Code::Flags flags =
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000857 Code::ComputeFlags(kind, in_loop, MEGAMORPHIC, NORMAL, argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000858 Object* probe;
859 { MaybeObject* maybe_probe = ProbeCache(flags);
860 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
861 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000862 if (!probe->IsUndefined()) return probe;
863 StubCompiler compiler;
864 return FillCache(compiler.CompileCallMegamorphic(flags));
865}
866
867
lrn@chromium.org303ada72010-10-27 09:33:13 +0000868MaybeObject* StubCache::ComputeCallMiss(int argc, Code::Kind kind) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000869 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs
870 // and monomorphic stubs are not mixed up together in the stub cache.
871 Code::Flags flags = Code::ComputeFlags(
872 kind, NOT_IN_LOOP, MONOMORPHIC_PROTOTYPE_FAILURE, NORMAL, argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000873 Object* probe;
874 { MaybeObject* maybe_probe = ProbeCache(flags);
875 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
876 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000877 if (!probe->IsUndefined()) return probe;
878 StubCompiler compiler;
879 return FillCache(compiler.CompileCallMiss(flags));
880}
881
882
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000883#ifdef ENABLE_DEBUGGER_SUPPORT
lrn@chromium.org303ada72010-10-27 09:33:13 +0000884MaybeObject* StubCache::ComputeCallDebugBreak(int argc, Code::Kind kind) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000885 Code::Flags flags =
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000886 Code::ComputeFlags(kind, NOT_IN_LOOP, DEBUG_BREAK, NORMAL, argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000887 Object* probe;
888 { MaybeObject* maybe_probe = ProbeCache(flags);
889 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
890 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000891 if (!probe->IsUndefined()) return probe;
892 StubCompiler compiler;
893 return FillCache(compiler.CompileCallDebugBreak(flags));
894}
895
896
lrn@chromium.org303ada72010-10-27 09:33:13 +0000897MaybeObject* StubCache::ComputeCallDebugPrepareStepIn(int argc,
898 Code::Kind kind) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000899 Code::Flags flags =
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000900 Code::ComputeFlags(kind,
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000901 NOT_IN_LOOP,
902 DEBUG_PREPARE_STEP_IN,
903 NORMAL,
904 argc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000905 Object* probe;
906 { MaybeObject* maybe_probe = ProbeCache(flags);
907 if (!maybe_probe->ToObject(&probe)) return maybe_probe;
908 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000909 if (!probe->IsUndefined()) return probe;
910 StubCompiler compiler;
911 return FillCache(compiler.CompileCallDebugPrepareStepIn(flags));
912}
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000913#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000914
915
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000916void StubCache::Clear() {
917 for (int i = 0; i < kPrimaryTableSize; i++) {
918 primary_[i].key = Heap::empty_string();
919 primary_[i].value = Builtins::builtin(Builtins::Illegal);
920 }
921 for (int j = 0; j < kSecondaryTableSize; j++) {
922 secondary_[j].key = Heap::empty_string();
923 secondary_[j].value = Builtins::builtin(Builtins::Illegal);
924 }
925}
926
927
928// ------------------------------------------------------------------------
929// StubCompiler implementation.
930
931
lrn@chromium.org303ada72010-10-27 09:33:13 +0000932MaybeObject* LoadCallbackProperty(Arguments args) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000933 ASSERT(args[0]->IsJSObject());
934 ASSERT(args[1]->IsJSObject());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000935 AccessorInfo* callback = AccessorInfo::cast(args[2]);
ager@chromium.org3b45ab52009-03-19 22:21:34 +0000936 Address getter_address = v8::ToCData<Address>(callback->getter());
937 v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000938 ASSERT(fun != NULL);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000939 CustomArguments custom_args(callback->data(),
940 JSObject::cast(args[0]),
941 JSObject::cast(args[1]));
942 v8::AccessorInfo info(custom_args.end());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000943 HandleScope scope;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000944 v8::Handle<v8::Value> result;
945 {
946 // Leaving JavaScript.
ager@chromium.org41826e72009-03-30 13:30:57 +0000947 VMState state(EXTERNAL);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000948#ifdef ENABLE_LOGGING_AND_PROFILING
949 state.set_external_callback(getter_address);
950#endif
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000951 result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000952 }
953 RETURN_IF_SCHEDULED_EXCEPTION();
ager@chromium.org3b45ab52009-03-19 22:21:34 +0000954 if (result.IsEmpty()) return Heap::undefined_value();
955 return *v8::Utils::OpenHandle(*result);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000956}
957
958
lrn@chromium.org303ada72010-10-27 09:33:13 +0000959MaybeObject* StoreCallbackProperty(Arguments args) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000960 JSObject* recv = JSObject::cast(args[0]);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000961 AccessorInfo* callback = AccessorInfo::cast(args[1]);
ager@chromium.org3b45ab52009-03-19 22:21:34 +0000962 Address setter_address = v8::ToCData<Address>(callback->setter());
963 v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000964 ASSERT(fun != NULL);
965 Handle<String> name = args.at<String>(2);
966 Handle<Object> value = args.at<Object>(3);
967 HandleScope scope;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000968 LOG(ApiNamedPropertyAccess("store", recv, *name));
969 CustomArguments custom_args(callback->data(), recv, recv);
970 v8::AccessorInfo info(custom_args.end());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000971 {
972 // Leaving JavaScript.
ager@chromium.org41826e72009-03-30 13:30:57 +0000973 VMState state(EXTERNAL);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000974#ifdef ENABLE_LOGGING_AND_PROFILING
975 state.set_external_callback(setter_address);
976#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000977 fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
978 }
979 RETURN_IF_SCHEDULED_EXCEPTION();
980 return *value;
981}
982
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000983
984static const int kAccessorInfoOffsetInInterceptorArgs = 2;
985
986
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000987/**
988 * Attempts to load a property with an interceptor (which must be present),
989 * but doesn't search the prototype chain.
990 *
991 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
992 * provide any value for the given name.
993 */
lrn@chromium.org303ada72010-10-27 09:33:13 +0000994MaybeObject* LoadPropertyWithInterceptorOnly(Arguments args) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +0000995 Handle<String> name_handle = args.at<String>(0);
996 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1);
997 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
998 ASSERT(args[2]->IsJSObject()); // Receiver.
999 ASSERT(args[3]->IsJSObject()); // Holder.
1000 ASSERT(args.length() == 5); // Last arg is data object.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001001
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001002 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1003 v8::NamedPropertyGetter getter =
1004 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1005 ASSERT(getter != NULL);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001006
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001007 {
1008 // Use the interceptor getter.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001009 v8::AccessorInfo info(args.arguments() -
1010 kAccessorInfoOffsetInInterceptorArgs);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001011 HandleScope scope;
1012 v8::Handle<v8::Value> r;
1013 {
1014 // Leaving JavaScript.
1015 VMState state(EXTERNAL);
1016 r = getter(v8::Utils::ToLocal(name_handle), info);
1017 }
1018 RETURN_IF_SCHEDULED_EXCEPTION();
1019 if (!r.IsEmpty()) {
1020 return *v8::Utils::OpenHandle(*r);
1021 }
1022 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001023
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001024 return Heap::no_interceptor_result_sentinel();
1025}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001026
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001027
lrn@chromium.org303ada72010-10-27 09:33:13 +00001028static MaybeObject* ThrowReferenceError(String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001029 // If the load is non-contextual, just return the undefined result.
1030 // Note that both keyed and non-keyed loads may end up here, so we
1031 // can't use either LoadIC or KeyedLoadIC constructors.
1032 IC ic(IC::NO_EXTRA_FRAME);
1033 ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001034 if (!ic.SlowIsContextual()) return Heap::undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001035
1036 // Throw a reference error.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001037 HandleScope scope;
1038 Handle<String> name_handle(name);
1039 Handle<Object> error =
1040 Factory::NewReferenceError("not_defined",
1041 HandleVector(&name_handle, 1));
1042 return Top::Throw(*error);
1043}
1044
1045
lrn@chromium.org303ada72010-10-27 09:33:13 +00001046static MaybeObject* LoadWithInterceptor(Arguments* args,
1047 PropertyAttributes* attrs) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001048 Handle<String> name_handle = args->at<String>(0);
1049 Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1);
1050 ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2);
1051 Handle<JSObject> receiver_handle = args->at<JSObject>(2);
1052 Handle<JSObject> holder_handle = args->at<JSObject>(3);
1053 ASSERT(args->length() == 5); // Last arg is data object.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001054
1055 Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
1056 v8::NamedPropertyGetter getter =
1057 FUNCTION_CAST<v8::NamedPropertyGetter>(getter_address);
1058 ASSERT(getter != NULL);
1059
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001060 {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001061 // Use the interceptor getter.
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001062 v8::AccessorInfo info(args->arguments() -
1063 kAccessorInfoOffsetInInterceptorArgs);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001064 HandleScope scope;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001065 v8::Handle<v8::Value> r;
1066 {
1067 // Leaving JavaScript.
1068 VMState state(EXTERNAL);
1069 r = getter(v8::Utils::ToLocal(name_handle), info);
1070 }
1071 RETURN_IF_SCHEDULED_EXCEPTION();
1072 if (!r.IsEmpty()) {
1073 *attrs = NONE;
1074 return *v8::Utils::OpenHandle(*r);
1075 }
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001076 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001077
lrn@chromium.org303ada72010-10-27 09:33:13 +00001078 MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001079 *receiver_handle,
1080 *name_handle,
1081 attrs);
1082 RETURN_IF_SCHEDULED_EXCEPTION();
1083 return result;
1084}
1085
1086
1087/**
1088 * Loads a property with an interceptor performing post interceptor
1089 * lookup if interceptor failed.
1090 */
lrn@chromium.org303ada72010-10-27 09:33:13 +00001091MaybeObject* LoadPropertyWithInterceptorForLoad(Arguments args) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001092 PropertyAttributes attr = NONE;
lrn@chromium.org303ada72010-10-27 09:33:13 +00001093 Object* result;
1094 { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr);
1095 if (!maybe_result->ToObject(&result)) return maybe_result;
1096 }
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001097
1098 // If the property is present, return it.
1099 if (attr != ABSENT) return result;
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00001100 return ThrowReferenceError(String::cast(args[0]));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001101}
1102
1103
lrn@chromium.org303ada72010-10-27 09:33:13 +00001104MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001105 PropertyAttributes attr;
lrn@chromium.org303ada72010-10-27 09:33:13 +00001106 MaybeObject* result = LoadWithInterceptor(&args, &attr);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001107 RETURN_IF_SCHEDULED_EXCEPTION();
1108 // This is call IC. In this case, we simply return the undefined result which
1109 // will lead to an exception when trying to invoke the result as a
1110 // function.
1111 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001112}
1113
1114
lrn@chromium.org303ada72010-10-27 09:33:13 +00001115MaybeObject* StoreInterceptorProperty(Arguments args) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001116 JSObject* recv = JSObject::cast(args[0]);
1117 String* name = String::cast(args[1]);
1118 Object* value = args[2];
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001119 ASSERT(recv->HasNamedInterceptor());
1120 PropertyAttributes attr = NONE;
lrn@chromium.org303ada72010-10-27 09:33:13 +00001121 MaybeObject* result = recv->SetPropertyWithInterceptor(name, value, attr);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00001122 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001123}
1124
1125
lrn@chromium.org303ada72010-10-27 09:33:13 +00001126MaybeObject* KeyedLoadPropertyWithInterceptor(Arguments args) {
ager@chromium.org5c838252010-02-19 08:53:10 +00001127 JSObject* receiver = JSObject::cast(args[0]);
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00001128 ASSERT(Smi::cast(args[1])->value() >= 0);
ager@chromium.org5c838252010-02-19 08:53:10 +00001129 uint32_t index = Smi::cast(args[1])->value();
1130 return receiver->GetElementWithInterceptor(receiver, index);
1131}
1132
1133
lrn@chromium.org303ada72010-10-27 09:33:13 +00001134MaybeObject* StubCompiler::CompileCallInitialize(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001135 HandleScope scope;
1136 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001137 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1138 if (kind == Code::CALL_IC) {
1139 CallIC::GenerateInitialize(masm(), argc);
1140 } else {
1141 KeyedCallIC::GenerateInitialize(masm(), argc);
1142 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001143 Object* result;
1144 { MaybeObject* maybe_result =
1145 GetCodeWithFlags(flags, "CompileCallInitialize");
1146 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001147 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001148 Counters::call_initialize_stubs.Increment();
1149 Code* code = Code::cast(result);
1150 USE(code);
1151 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG),
1152 code, code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001153 return result;
1154}
1155
1156
lrn@chromium.org303ada72010-10-27 09:33:13 +00001157MaybeObject* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001158 HandleScope scope;
1159 int argc = Code::ExtractArgumentsCountFromFlags(flags);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001160 // The code of the PreMonomorphic stub is the same as the code
1161 // of the Initialized stub. They just differ on the code object flags.
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001162 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1163 if (kind == Code::CALL_IC) {
1164 CallIC::GenerateInitialize(masm(), argc);
1165 } else {
1166 KeyedCallIC::GenerateInitialize(masm(), argc);
1167 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001168 Object* result;
1169 { MaybeObject* maybe_result =
1170 GetCodeWithFlags(flags, "CompileCallPreMonomorphic");
1171 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001172 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001173 Counters::call_premonomorphic_stubs.Increment();
1174 Code* code = Code::cast(result);
1175 USE(code);
1176 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG),
1177 code, code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001178 return result;
1179}
1180
1181
lrn@chromium.org303ada72010-10-27 09:33:13 +00001182MaybeObject* StubCompiler::CompileCallNormal(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001183 HandleScope scope;
1184 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001185 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1186 if (kind == Code::CALL_IC) {
1187 CallIC::GenerateNormal(masm(), argc);
1188 } else {
1189 KeyedCallIC::GenerateNormal(masm(), argc);
1190 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001191 Object* result;
1192 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallNormal");
1193 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001194 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001195 Counters::call_normal_stubs.Increment();
1196 Code* code = Code::cast(result);
1197 USE(code);
1198 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG),
1199 code, code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001200 return result;
1201}
1202
1203
lrn@chromium.org303ada72010-10-27 09:33:13 +00001204MaybeObject* StubCompiler::CompileCallMegamorphic(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001205 HandleScope scope;
1206 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001207 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1208 if (kind == Code::CALL_IC) {
1209 CallIC::GenerateMegamorphic(masm(), argc);
1210 } else {
1211 KeyedCallIC::GenerateMegamorphic(masm(), argc);
1212 }
1213
lrn@chromium.org303ada72010-10-27 09:33:13 +00001214 Object* result;
1215 { MaybeObject* maybe_result =
1216 GetCodeWithFlags(flags, "CompileCallMegamorphic");
1217 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001218 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001219 Counters::call_megamorphic_stubs.Increment();
1220 Code* code = Code::cast(result);
1221 USE(code);
1222 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG),
1223 code, code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001224 return result;
1225}
1226
1227
lrn@chromium.org303ada72010-10-27 09:33:13 +00001228MaybeObject* StubCompiler::CompileCallMiss(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001229 HandleScope scope;
1230 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001231 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1232 if (kind == Code::CALL_IC) {
1233 CallIC::GenerateMiss(masm(), argc);
1234 } else {
1235 KeyedCallIC::GenerateMiss(masm(), argc);
1236 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001237 Object* result;
1238 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallMiss");
1239 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001240 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001241 Counters::call_megamorphic_stubs.Increment();
1242 Code* code = Code::cast(result);
1243 USE(code);
1244 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG),
1245 code, code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001246 return result;
1247}
1248
1249
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001250#ifdef ENABLE_DEBUGGER_SUPPORT
lrn@chromium.org303ada72010-10-27 09:33:13 +00001251MaybeObject* StubCompiler::CompileCallDebugBreak(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001252 HandleScope scope;
ager@chromium.org8bb60582008-12-11 12:02:20 +00001253 Debug::GenerateCallICDebugBreak(masm());
lrn@chromium.org303ada72010-10-27 09:33:13 +00001254 Object* result;
1255 { MaybeObject* maybe_result =
1256 GetCodeWithFlags(flags, "CompileCallDebugBreak");
1257 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001258 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001259 Code* code = Code::cast(result);
1260 USE(code);
1261 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1262 USE(kind);
1263 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG),
1264 code, code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001265 return result;
1266}
1267
1268
lrn@chromium.org303ada72010-10-27 09:33:13 +00001269MaybeObject* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001270 HandleScope scope;
1271 // Use the same code for the the step in preparations as we do for
1272 // the miss case.
1273 int argc = Code::ExtractArgumentsCountFromFlags(flags);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001274 Code::Kind kind = Code::ExtractKindFromFlags(flags);
1275 if (kind == Code::CALL_IC) {
1276 CallIC::GenerateMiss(masm(), argc);
1277 } else {
1278 KeyedCallIC::GenerateMiss(masm(), argc);
1279 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001280 Object* result;
1281 { MaybeObject* maybe_result =
1282 GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn");
1283 if (!maybe_result->ToObject(&result)) return maybe_result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001284 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001285 Code* code = Code::cast(result);
1286 USE(code);
1287 PROFILE(CodeCreateEvent(
1288 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG),
1289 code,
1290 code->arguments_count()));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001291 return result;
1292}
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001293#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001294
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001295#undef CALL_LOGGER_TAG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001296
lrn@chromium.org303ada72010-10-27 09:33:13 +00001297MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags,
1298 const char* name) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001299 // Check for allocation failures during stub compilation.
1300 if (failure_->IsFailure()) return failure_;
1301
1302 // Create code object in the heap.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001303 CodeDesc desc;
1304 masm_.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001305 MaybeObject* result = Heap::CreateCode(desc, flags, masm_.CodeObject());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001306#ifdef ENABLE_DISASSEMBLER
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001307 if (FLAG_print_code_stubs && !result->IsFailure()) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001308 Code::cast(result->ToObjectUnchecked())->Disassemble(name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001309 }
1310#endif
1311 return result;
1312}
1313
1314
lrn@chromium.org303ada72010-10-27 09:33:13 +00001315MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001316 if (FLAG_print_code_stubs && (name != NULL)) {
1317 return GetCodeWithFlags(flags, *name->ToCString());
1318 }
1319 return GetCodeWithFlags(flags, reinterpret_cast<char*>(NULL));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001320}
1321
ager@chromium.org5c838252010-02-19 08:53:10 +00001322
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001323void StubCompiler::LookupPostInterceptor(JSObject* holder,
1324 String* name,
1325 LookupResult* lookup) {
1326 holder->LocalLookupRealNamedProperty(name, lookup);
ager@chromium.org5c838252010-02-19 08:53:10 +00001327 if (!lookup->IsProperty()) {
1328 lookup->NotFound();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001329 Object* proto = holder->GetPrototype();
1330 if (proto != Heap::null_value()) {
1331 proto->Lookup(name, lookup);
1332 }
1333 }
1334}
1335
1336
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001337
lrn@chromium.org303ada72010-10-27 09:33:13 +00001338MaybeObject* LoadStubCompiler::GetCode(PropertyType type, String* name) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001339 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001340 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001341 if (!result->IsFailure()) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001342 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG,
1343 Code::cast(result->ToObjectUnchecked()),
1344 name));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001345 }
1346 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001347}
1348
1349
lrn@chromium.org303ada72010-10-27 09:33:13 +00001350MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type, String* name) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001351 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001352 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001353 if (!result->IsFailure()) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001354 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
1355 Code::cast(result->ToObjectUnchecked()),
1356 name));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001357 }
1358 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001359}
1360
1361
lrn@chromium.org303ada72010-10-27 09:33:13 +00001362MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001363 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001364 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001365 if (!result->IsFailure()) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001366 PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG,
1367 Code::cast(result->ToObjectUnchecked()),
1368 name));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001369 }
1370 return result;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001371}
1372
1373
lrn@chromium.org303ada72010-10-27 09:33:13 +00001374MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001375 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001376 MaybeObject* result = GetCodeWithFlags(flags, name);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001377 if (!result->IsFailure()) {
lrn@chromium.org303ada72010-10-27 09:33:13 +00001378 PROFILE(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
1379 Code::cast(result->ToObjectUnchecked()),
1380 name));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00001381 }
1382 return result;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001383}
1384
1385
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001386CallStubCompiler::CallStubCompiler(int argc,
1387 InLoopFlag in_loop,
1388 Code::Kind kind,
1389 InlineCacheHolderFlag cache_holder)
1390 : arguments_(argc)
1391 , in_loop_(in_loop)
1392 , kind_(kind)
1393 , cache_holder_(cache_holder) {
1394}
1395
1396
lrn@chromium.org303ada72010-10-27 09:33:13 +00001397MaybeObject* CallStubCompiler::CompileCustomCall(int generator_id,
1398 Object* object,
1399 JSObject* holder,
1400 JSGlobalPropertyCell* cell,
1401 JSFunction* function,
1402 String* fname) {
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +00001403 ASSERT(generator_id >= 0 && generator_id < kNumCallGenerators);
1404 switch (generator_id) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001405#define CALL_GENERATOR_CASE(ignored1, ignored2, name) \
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +00001406 case k##name##CallGenerator: \
1407 return CallStubCompiler::Compile##name##Call(object, \
1408 holder, \
1409 cell, \
1410 function, \
1411 fname);
1412 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001413#undef CALL_GENERATOR_CASE
sgjesse@chromium.org2ec107f2010-09-13 09:19:46 +00001414 }
1415 UNREACHABLE();
1416 return Heap::undefined_value();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001417}
1418
1419
lrn@chromium.org303ada72010-10-27 09:33:13 +00001420MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001421 int argc = arguments_.immediate();
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001422 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001423 type,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001424 cache_holder_,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +00001425 in_loop_,
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001426 argc);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001427 return GetCodeWithFlags(flags, name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001428}
1429
1430
lrn@chromium.org303ada72010-10-27 09:33:13 +00001431MaybeObject* CallStubCompiler::GetCode(JSFunction* function) {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001432 String* function_name = NULL;
1433 if (function->shared()->name()->IsString()) {
1434 function_name = String::cast(function->shared()->name());
1435 }
1436 return GetCode(CONSTANT_FUNCTION, function_name);
1437}
1438
1439
lrn@chromium.org303ada72010-10-27 09:33:13 +00001440MaybeObject* ConstructStubCompiler::GetCode() {
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001441 Code::Flags flags = Code::ComputeFlags(Code::STUB);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001442 Object* result;
1443 { MaybeObject* maybe_result = GetCodeWithFlags(flags, "ConstructStub");
1444 if (!maybe_result->ToObject(&result)) return maybe_result;
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001445 }
lrn@chromium.org303ada72010-10-27 09:33:13 +00001446 Code* code = Code::cast(result);
1447 USE(code);
1448 PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub"));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001449 return result;
1450}
1451
1452
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001453CallOptimization::CallOptimization(LookupResult* lookup) {
1454 if (!lookup->IsProperty() || !lookup->IsCacheable() ||
1455 lookup->type() != CONSTANT_FUNCTION) {
1456 Initialize(NULL);
1457 } else {
1458 // We only optimize constant function calls.
1459 Initialize(lookup->GetConstantFunction());
1460 }
1461}
1462
1463CallOptimization::CallOptimization(JSFunction* function) {
1464 Initialize(function);
1465}
1466
1467
1468int CallOptimization::GetPrototypeDepthOfExpectedType(JSObject* object,
1469 JSObject* holder) const {
1470 ASSERT(is_simple_api_call_);
1471 if (expected_receiver_type_ == NULL) return 0;
1472 int depth = 0;
1473 while (object != holder) {
1474 if (object->IsInstanceOf(expected_receiver_type_)) return depth;
1475 object = JSObject::cast(object->GetPrototype());
1476 ++depth;
1477 }
1478 if (holder->IsInstanceOf(expected_receiver_type_)) return depth;
1479 return kInvalidProtoDepth;
1480}
1481
1482
1483void CallOptimization::Initialize(JSFunction* function) {
1484 constant_function_ = NULL;
1485 is_simple_api_call_ = false;
1486 expected_receiver_type_ = NULL;
1487 api_call_info_ = NULL;
1488
1489 if (function == NULL || !function->is_compiled()) return;
1490
1491 constant_function_ = function;
1492 AnalyzePossibleApiFunction(function);
1493}
1494
1495
1496void CallOptimization::AnalyzePossibleApiFunction(JSFunction* function) {
1497 SharedFunctionInfo* sfi = function->shared();
1498 if (!sfi->IsApiFunction()) return;
1499 FunctionTemplateInfo* info = sfi->get_api_func_data();
1500
1501 // Require a C++ callback.
1502 if (info->call_code()->IsUndefined()) return;
1503 api_call_info_ = CallHandlerInfo::cast(info->call_code());
1504
1505 // Accept signatures that either have no restrictions at all or
1506 // only have restrictions on the receiver.
1507 if (!info->signature()->IsUndefined()) {
1508 SignatureInfo* signature = SignatureInfo::cast(info->signature());
1509 if (!signature->args()->IsUndefined()) return;
1510 if (!signature->receiver()->IsUndefined()) {
1511 expected_receiver_type_ =
1512 FunctionTemplateInfo::cast(signature->receiver());
1513 }
1514 }
1515
1516 is_simple_api_call_ = true;
1517}
1518
1519
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001520} } // namespace v8::internal