Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(224)

Side by Side Diff: src/ic.cc

Issue 25464004: Use PatchCache for call ICs. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW"; 64 if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
65 if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { 65 if (mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
66 return ".IGNORE_OOB"; 66 return ".IGNORE_OOB";
67 } 67 }
68 if (IsGrowStoreMode(mode)) return ".GROW"; 68 if (IsGrowStoreMode(mode)) return ".GROW";
69 return ""; 69 return "";
70 } 70 }
71 71
72 72
73 void IC::TraceIC(const char* type, 73 void IC::TraceIC(const char* type,
74 Handle<Object> name, 74 Handle<Object> name) {
75 Code* new_target) {
76 if (FLAG_trace_ic) { 75 if (FLAG_trace_ic) {
76 Code* new_target = raw_target();
77 State new_state = new_target->ic_state(); 77 State new_state = new_target->ic_state();
78 PrintF("[%s in ", type); 78 PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
79 StackFrameIterator it(isolate()); 79 StackFrameIterator it(isolate());
80 while (it.frame()->fp() != this->fp()) it.Advance(); 80 while (it.frame()->fp() != this->fp()) it.Advance();
81 StackFrame* raw_frame = it.frame(); 81 StackFrame* raw_frame = it.frame();
82 if (raw_frame->is_internal()) { 82 if (raw_frame->is_internal()) {
83 Code* apply_builtin = isolate()->builtins()->builtin( 83 Code* apply_builtin = isolate()->builtins()->builtin(
84 Builtins::kFunctionApply); 84 Builtins::kFunctionApply);
85 if (raw_frame->unchecked_code() == apply_builtin) { 85 if (raw_frame->unchecked_code() == apply_builtin) {
86 PrintF("apply from "); 86 PrintF("apply from ");
87 it.Advance(); 87 it.Advance();
88 raw_frame = it.frame(); 88 raw_frame = it.frame();
(...skipping 18 matching lines...) Expand all
107 PrintF("[%s patching generic stub in ", type); \ 107 PrintF("[%s patching generic stub in ", type); \
108 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \ 108 JavaScriptFrame::PrintTop(isolate, stdout, false, true); \
109 PrintF(" (%s)]\n", reason); \ 109 PrintF(" (%s)]\n", reason); \
110 } \ 110 } \
111 } while (false) 111 } while (false)
112 112
113 #else 113 #else
114 #define TRACE_GENERIC_IC(isolate, type, reason) 114 #define TRACE_GENERIC_IC(isolate, type, reason)
115 #endif // DEBUG 115 #endif // DEBUG
116 116
117 #define TRACE_IC(type, name, new_target) \ 117 #define TRACE_IC(type, name) \
118 ASSERT((TraceIC(type, name, *new_target), true)) 118 ASSERT((TraceIC(type, name), true))
119 119
120 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { 120 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
121 // To improve the performance of the (much used) IC code, we unfold a few 121 // To improve the performance of the (much used) IC code, we unfold a few
122 // levels of the stack frame iteration code. This yields a ~35% speedup when 122 // levels of the stack frame iteration code. This yields a ~35% speedup when
123 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag. 123 // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
124 const Address entry = 124 const Address entry =
125 Isolate::c_entry_fp(isolate->thread_local_top()); 125 Isolate::c_entry_fp(isolate->thread_local_top());
126 Address* pc_address = 126 Address* pc_address =
127 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); 127 reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
128 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); 128 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 // Return the address in the original code. This is the place where 171 // Return the address in the original code. This is the place where
172 // the call which has been overwritten by the DebugBreakXXX resides 172 // the call which has been overwritten by the DebugBreakXXX resides
173 // and the place where the inline cache system should look. 173 // and the place where the inline cache system should look.
174 intptr_t delta = 174 intptr_t delta =
175 original_code->instruction_start() - code->instruction_start(); 175 original_code->instruction_start() - code->instruction_start();
176 return addr + delta; 176 return addr + delta;
177 } 177 }
178 #endif 178 #endif
179 179
180 180
181 bool IC::TryRemoveInvalidPrototypeDependentStub(Object* receiver, 181 static bool HasInterceptorGetter(JSObject* object) {
182 Object* name) { 182 return !object->GetNamedInterceptor()->getter()->IsUndefined();
183 }
184
185
186 static bool HasInterceptorSetter(JSObject* object) {
187 return !object->GetNamedInterceptor()->setter()->IsUndefined();
188 }
189
190
191 static void LookupForRead(Handle<Object> object,
192 Handle<String> name,
193 LookupResult* lookup) {
194 // Skip all the objects with named interceptors, but
195 // without actual getter.
196 while (true) {
197 object->Lookup(*name, lookup);
198 // Besides normal conditions (property not found or it's not
199 // an interceptor), bail out if lookup is not cacheable: we won't
200 // be able to IC it anyway and regular lookup should work fine.
201 if (!lookup->IsInterceptor() || !lookup->IsCacheable()) {
202 return;
203 }
204
205 Handle<JSObject> holder(lookup->holder(), lookup->isolate());
206 if (HasInterceptorGetter(*holder)) {
207 return;
208 }
209
210 holder->LocalLookupRealNamedProperty(*name, lookup);
211 if (lookup->IsFound()) {
212 ASSERT(!lookup->IsInterceptor());
213 return;
214 }
215
216 Handle<Object> proto(holder->GetPrototype(), lookup->isolate());
217 if (proto->IsNull()) {
218 ASSERT(!lookup->IsFound());
219 return;
220 }
221
222 object = proto;
223 }
224 }
225
226
227 bool CallIC::TryUpdateExtraICState(LookupResult* lookup,
228 Handle<Object> object) {
229 if (!lookup->IsConstantFunction()) return false;
230 JSFunction* function = lookup->GetConstantFunction();
231 if (!function->shared()->HasBuiltinFunctionId()) return false;
232
233 // Fetch the arguments passed to the called function.
234 const int argc = target()->arguments_count();
235 Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
236 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
237 Arguments args(argc + 1,
238 &Memory::Object_at(fp +
239 StandardFrameConstants::kCallerSPOffset +
240 argc * kPointerSize));
241 switch (function->shared()->builtin_function_id()) {
242 case kStringCharCodeAt:
243 case kStringCharAt:
244 if (object->IsString()) {
245 String* string = String::cast(*object);
246 // Check there's the right string value or wrapper in the receiver slot.
247 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
248 // If we're in the default (fastest) state and the index is
249 // out of bounds, update the state to record this fact.
250 if (StringStubState::decode(extra_ic_state()) == DEFAULT_STRING_STUB &&
251 argc >= 1 && args[1]->IsNumber()) {
252 double index = DoubleToInteger(args.number_at(1));
253 if (index < 0 || index >= string->length()) {
254 extra_ic_state_ =
255 StringStubState::update(extra_ic_state(),
256 STRING_INDEX_OUT_OF_BOUNDS);
257 return true;
258 }
259 }
260 }
261 break;
262 default:
263 return false;
264 }
265 return false;
266 }
267
268
269 bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
270 Handle<String> name) {
183 DisallowHeapAllocation no_gc; 271 DisallowHeapAllocation no_gc;
184 272
273 if (target()->is_call_stub()) {
274 LookupResult lookup(isolate());
275 LookupForRead(receiver, name, &lookup);
276 if (static_cast<CallIC*>(this)->TryUpdateExtraICState(&lookup, receiver)) {
277 return true;
278 }
279 }
280
185 if (target()->is_keyed_stub()) { 281 if (target()->is_keyed_stub()) {
186 // Determine whether the failure is due to a name failure. 282 // Determine whether the failure is due to a name failure.
187 if (!name->IsName()) return false; 283 if (!name->IsName()) return false;
188 Name* stub_name = target()->FindFirstName(); 284 Name* stub_name = target()->FindFirstName();
189 if (Name::cast(name) != stub_name) return false; 285 if (*name != stub_name) return false;
190 } 286 }
191 287
192 InlineCacheHolderFlag cache_holder = 288 InlineCacheHolderFlag cache_holder =
193 Code::ExtractCacheHolderFromFlags(target()->flags()); 289 Code::ExtractCacheHolderFromFlags(target()->flags());
194 290
195 switch (cache_holder) { 291 switch (cache_holder) {
196 case OWN_MAP: 292 case OWN_MAP:
197 // The stub was generated for JSObject but called for non-JSObject. 293 // The stub was generated for JSObject but called for non-JSObject.
198 // IC::GetCodeCacheHolder is not applicable. 294 // IC::GetCodeCacheHolder is not applicable.
199 if (!receiver->IsJSObject()) return false; 295 if (!receiver->IsJSObject()) return false;
200 break; 296 break;
201 case PROTOTYPE_MAP: 297 case PROTOTYPE_MAP:
202 // IC::GetCodeCacheHolder is not applicable. 298 // IC::GetCodeCacheHolder is not applicable.
203 if (receiver->GetPrototype(isolate())->IsNull()) return false; 299 if (receiver->GetPrototype(isolate())->IsNull()) return false;
204 break; 300 break;
205 } 301 }
206 302
207 Map* map = IC::GetCodeCacheHolder(isolate(), receiver, cache_holder)->map(); 303 Map* map = IC::GetCodeCacheHolder(isolate(), *receiver, cache_holder)->map();
208 304
209 // Decide whether the inline cache failed because of changes to the 305 // Decide whether the inline cache failed because of changes to the
210 // receiver itself or changes to one of its prototypes. 306 // receiver itself or changes to one of its prototypes.
211 // 307 //
212 // If there are changes to the receiver itself, the map of the 308 // If there are changes to the receiver itself, the map of the
213 // receiver will have changed and the current target will not be in 309 // receiver will have changed and the current target will not be in
214 // the receiver map's code cache. Therefore, if the current target 310 // the receiver map's code cache. Therefore, if the current target
215 // is in the receiver map's code cache, the inline cache failed due 311 // is in the receiver map's code cache, the inline cache failed due
216 // to prototype check failure. 312 // to prototype check failure.
217 int index = map->IndexInCodeCache(name, *target()); 313 int index = map->IndexInCodeCache(*name, *target());
218 if (index >= 0) { 314 if (index >= 0) {
219 map->RemoveFromCodeCache(String::cast(name), *target(), index); 315 map->RemoveFromCodeCache(*name, *target(), index);
220 // Handlers are stored in addition to the ICs on the map. Remove those, too. 316 // Handlers are stored in addition to the ICs on the map. Remove those, too.
221 Code* handler = target()->FindFirstHandler(); 317 Code* handler = target()->FindFirstHandler();
222 if (handler != NULL) { 318 if (handler != NULL) {
223 index = map->IndexInCodeCache(name, handler); 319 index = map->IndexInCodeCache(*name, handler);
224 if (index >= 0) { 320 if (index >= 0) {
225 map->RemoveFromCodeCache(String::cast(name), handler, index); 321 map->RemoveFromCodeCache(*name, handler, index);
226 } 322 }
227 } 323 }
228 return true; 324 return true;
229 } 325 }
230 326
231 // The stub is not in the cache. We've ruled out all other kinds of failure 327 // The stub is not in the cache. We've ruled out all other kinds of failure
232 // except for proptotype chain changes, a deprecated map, a map that's 328 // except for proptotype chain changes, a deprecated map, a map that's
233 // different from the one that the stub expects, elements kind changes, or a 329 // different from the one that the stub expects, elements kind changes, or a
234 // constant global property that will become mutable. Threat all those 330 // constant global property that will become mutable. Threat all those
235 // situations as prototype failures (stay monomorphic if possible). 331 // situations as prototype failures (stay monomorphic if possible).
236 332
237 // If the IC is shared between multiple receivers (slow dictionary mode), then 333 // If the IC is shared between multiple receivers (slow dictionary mode), then
238 // the map cannot be deprecated and the stub invalidated. 334 // the map cannot be deprecated and the stub invalidated.
239 if (cache_holder == OWN_MAP) { 335 if (cache_holder == OWN_MAP) {
240 Map* old_map = target()->FindFirstMap(); 336 Map* old_map = target()->FindFirstMap();
241 if (old_map == map) return true; 337 if (old_map == map) return true;
242 if (old_map != NULL) { 338 if (old_map != NULL) {
243 if (old_map->is_deprecated()) return true; 339 if (old_map->is_deprecated()) return true;
244 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(), 340 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
245 map->elements_kind())) { 341 map->elements_kind())) {
246 return true; 342 return true;
247 } 343 }
248 } 344 }
249 } 345 }
250 346
251 if (receiver->IsGlobalObject()) { 347 if (receiver->IsGlobalObject()) {
252 if (!name->IsName()) return false;
253 LookupResult lookup(isolate()); 348 LookupResult lookup(isolate());
254 GlobalObject* global = GlobalObject::cast(receiver); 349 GlobalObject* global = GlobalObject::cast(*receiver);
255 global->LocalLookupRealNamedProperty(Name::cast(name), &lookup); 350 global->LocalLookupRealNamedProperty(*name, &lookup);
256 if (!lookup.IsFound()) return false; 351 if (!lookup.IsFound()) return false;
257 PropertyCell* cell = global->GetPropertyCell(&lookup); 352 PropertyCell* cell = global->GetPropertyCell(&lookup);
258 return cell->type()->IsConstant(); 353 return cell->type()->IsConstant();
259 } 354 }
260 355
261 return false; 356 return false;
262 } 357 }
263 358
264 359
265 void IC::UpdateState(Object* receiver, Object* name) { 360 void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
266 if (state() != MONOMORPHIC || !name->IsString()) return; 361 if (state() != MONOMORPHIC || !name->IsString()) return;
267 if (receiver->IsUndefined() || receiver->IsNull()) return; 362 if (receiver->IsUndefined() || receiver->IsNull()) return;
268 363
269 Code::Kind kind = target()->kind();
270 // Remove the target from the code cache if it became invalid 364 // Remove the target from the code cache if it became invalid
271 // because of changes in the prototype chain to avoid hitting it 365 // because of changes in the prototype chain to avoid hitting it
272 // again. 366 // again.
273 // Call stubs handle this later to allow extra IC state 367 if (TryRemoveInvalidPrototypeDependentStub(
274 // transitions. 368 receiver, Handle<String>::cast(name))) {
275 if (kind != Code::CALL_IC && kind != Code::KEYED_CALL_IC && 369 return MarkMonomorphicPrototypeFailure();
276 TryRemoveInvalidPrototypeDependentStub(receiver, name)) {
277 MarkMonomorphicPrototypeFailure();
278 return;
279 } 370 }
280 371
281 // The builtins object is special. It only changes when JavaScript 372 // The builtins object is special. It only changes when JavaScript
282 // builtins are loaded lazily. It is important to keep inline 373 // builtins are loaded lazily. It is important to keep inline
283 // caches for the builtins object monomorphic. Therefore, if we get 374 // caches for the builtins object monomorphic. Therefore, if we get
284 // an inline cache miss for the builtins object after lazily loading 375 // an inline cache miss for the builtins object after lazily loading
285 // JavaScript builtins, we return uninitialized as the state to 376 // JavaScript builtins, we return uninitialized as the state to
286 // force the inline cache back to monomorphic state. 377 // force the inline cache back to monomorphic state.
287 if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED; 378 if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED;
288 } 379 }
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 Token::Value op; 533 Token::Value op;
443 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, 534 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL,
444 &handler_state, &op); 535 &handler_state, &op);
445 // Only clear CompareICs that can retain objects. 536 // Only clear CompareICs that can retain objects.
446 if (handler_state != KNOWN_OBJECT) return; 537 if (handler_state != KNOWN_OBJECT) return;
447 SetTargetAtAddress(address, GetRawUninitialized(isolate, op)); 538 SetTargetAtAddress(address, GetRawUninitialized(isolate, op));
448 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); 539 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK);
449 } 540 }
450 541
451 542
452 static bool HasInterceptorGetter(JSObject* object) {
453 return !object->GetNamedInterceptor()->getter()->IsUndefined();
454 }
455
456
457 static bool HasInterceptorSetter(JSObject* object) {
458 return !object->GetNamedInterceptor()->setter()->IsUndefined();
459 }
460
461
462 static void LookupForRead(Handle<Object> object,
463 Handle<String> name,
464 LookupResult* lookup) {
465 // Skip all the objects with named interceptors, but
466 // without actual getter.
467 while (true) {
468 object->Lookup(*name, lookup);
469 // Besides normal conditions (property not found or it's not
470 // an interceptor), bail out if lookup is not cacheable: we won't
471 // be able to IC it anyway and regular lookup should work fine.
472 if (!lookup->IsInterceptor() || !lookup->IsCacheable()) {
473 return;
474 }
475
476 Handle<JSObject> holder(lookup->holder(), lookup->isolate());
477 if (HasInterceptorGetter(*holder)) {
478 return;
479 }
480
481 holder->LocalLookupRealNamedProperty(*name, lookup);
482 if (lookup->IsFound()) {
483 ASSERT(!lookup->IsInterceptor());
484 return;
485 }
486
487 Handle<Object> proto(holder->GetPrototype(), lookup->isolate());
488 if (proto->IsNull()) {
489 ASSERT(!lookup->IsFound());
490 return;
491 }
492
493 object = proto;
494 }
495 }
496
497
498 Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) { 543 Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) {
499 Handle<Object> delegate = Execution::GetFunctionDelegate(isolate(), object); 544 Handle<Object> delegate = Execution::GetFunctionDelegate(isolate(), object);
500 545
501 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) { 546 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) {
502 // Patch the receiver and use the delegate as the function to 547 // Patch the receiver and use the delegate as the function to
503 // invoke. This is used for invoking objects as if they were functions. 548 // invoke. This is used for invoking objects as if they were functions.
504 const int argc = target()->arguments_count(); 549 const int argc = target()->arguments_count();
505 StackFrameLocator locator(isolate()); 550 StackFrameLocator locator(isolate());
506 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); 551 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
507 int index = frame->ComputeExpressionsCount() - (argc + 1); 552 int index = frame->ComputeExpressionsCount() - (argc + 1);
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 } 669 }
625 670
626 // Try to find a suitable function delegate for the object at hand. 671 // Try to find a suitable function delegate for the object at hand.
627 result = TryCallAsFunction(result); 672 result = TryCallAsFunction(result);
628 if (result->IsJSFunction()) return *result; 673 if (result->IsJSFunction()) return *result;
629 674
630 return TypeError("property_not_function", object, name); 675 return TypeError("property_not_function", object, name);
631 } 676 }
632 677
633 678
634 bool CallIC::TryUpdateExtraICState(LookupResult* lookup,
635 Handle<Object> object) {
636 if (!lookup->IsConstantFunction()) return false;
637 JSFunction* function = lookup->GetConstantFunction();
638 if (!function->shared()->HasBuiltinFunctionId()) return false;
639
640 // Fetch the arguments passed to the called function.
641 const int argc = target()->arguments_count();
642 Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
643 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
644 Arguments args(argc + 1,
645 &Memory::Object_at(fp +
646 StandardFrameConstants::kCallerSPOffset +
647 argc * kPointerSize));
648 switch (function->shared()->builtin_function_id()) {
649 case kStringCharCodeAt:
650 case kStringCharAt:
651 if (object->IsString()) {
652 String* string = String::cast(*object);
653 // Check there's the right string value or wrapper in the receiver slot.
654 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
655 // If we're in the default (fastest) state and the index is
656 // out of bounds, update the state to record this fact.
657 if (StringStubState::decode(extra_ic_state()) == DEFAULT_STRING_STUB &&
658 argc >= 1 && args[1]->IsNumber()) {
659 double index = DoubleToInteger(args.number_at(1));
660 if (index < 0 || index >= string->length()) {
661 extra_ic_state_ =
662 StringStubState::update(extra_ic_state(),
663 STRING_INDEX_OUT_OF_BOUNDS);
664 return true;
665 }
666 }
667 }
668 break;
669 default:
670 return false;
671 }
672 return false;
673 }
674
675
676 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, 679 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
677 Code::ExtraICState extra_state,
678 Handle<Object> object, 680 Handle<Object> object,
679 Handle<String> name) { 681 Handle<String> name) {
680 int argc = target()->arguments_count(); 682 int argc = target()->arguments_count();
681 Handle<JSObject> holder(lookup->holder(), isolate()); 683 Handle<JSObject> holder(lookup->holder(), isolate());
682 switch (lookup->type()) { 684 switch (lookup->type()) {
683 case FIELD: { 685 case FIELD: {
684 PropertyIndex index = lookup->GetFieldIndex(); 686 PropertyIndex index = lookup->GetFieldIndex();
685 return isolate()->stub_cache()->ComputeCallField( 687 return isolate()->stub_cache()->ComputeCallField(
686 argc, kind_, extra_state, name, object, holder, index); 688 argc, kind_, extra_ic_state(), name, object, holder, index);
687 } 689 }
688 case CONSTANT: { 690 case CONSTANT: {
689 if (!lookup->IsConstantFunction()) return Handle<Code>::null(); 691 if (!lookup->IsConstantFunction()) return Handle<Code>::null();
690 // Get the constant function and compute the code stub for this 692 // Get the constant function and compute the code stub for this
691 // call; used for rewriting to monomorphic state and making sure 693 // call; used for rewriting to monomorphic state and making sure
692 // that the code stub is in the stub cache. 694 // that the code stub is in the stub cache.
693 Handle<JSFunction> function(lookup->GetConstantFunction(), isolate()); 695 Handle<JSFunction> function(lookup->GetConstantFunction(), isolate());
694 return isolate()->stub_cache()->ComputeCallConstant( 696 return isolate()->stub_cache()->ComputeCallConstant(
695 argc, kind_, extra_state, name, object, holder, function); 697 argc, kind_, extra_ic_state(), name, object, holder, function);
696 } 698 }
697 case NORMAL: { 699 case NORMAL: {
698 // If we return a null handle, the IC will not be patched. 700 // If we return a null handle, the IC will not be patched.
699 if (!object->IsJSObject()) return Handle<Code>::null(); 701 if (!object->IsJSObject()) return Handle<Code>::null();
700 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 702 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
701 703
702 if (holder->IsGlobalObject()) { 704 if (holder->IsGlobalObject()) {
703 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); 705 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
704 Handle<PropertyCell> cell( 706 Handle<PropertyCell> cell(
705 global->GetPropertyCell(lookup), isolate()); 707 global->GetPropertyCell(lookup), isolate());
706 if (!cell->value()->IsJSFunction()) return Handle<Code>::null(); 708 if (!cell->value()->IsJSFunction()) return Handle<Code>::null();
707 Handle<JSFunction> function(JSFunction::cast(cell->value())); 709 Handle<JSFunction> function(JSFunction::cast(cell->value()));
708 return isolate()->stub_cache()->ComputeCallGlobal( 710 return isolate()->stub_cache()->ComputeCallGlobal(
709 argc, kind_, extra_state, name, receiver, global, cell, function); 711 argc, kind_, extra_ic_state(), name,
712 receiver, global, cell, function);
710 } else { 713 } else {
711 // There is only one shared stub for calling normalized 714 // There is only one shared stub for calling normalized
712 // properties. It does not traverse the prototype chain, so the 715 // properties. It does not traverse the prototype chain, so the
713 // property must be found in the receiver for the stub to be 716 // property must be found in the receiver for the stub to be
714 // applicable. 717 // applicable.
715 if (!holder.is_identical_to(receiver)) return Handle<Code>::null(); 718 if (!holder.is_identical_to(receiver)) return Handle<Code>::null();
716 return isolate()->stub_cache()->ComputeCallNormal( 719 return isolate()->stub_cache()->ComputeCallNormal(
717 argc, kind_, extra_state); 720 argc, kind_, extra_ic_state());
718 } 721 }
719 break; 722 break;
720 } 723 }
721 case INTERCEPTOR: 724 case INTERCEPTOR:
722 ASSERT(HasInterceptorGetter(*holder)); 725 ASSERT(HasInterceptorGetter(*holder));
723 return isolate()->stub_cache()->ComputeCallInterceptor( 726 return isolate()->stub_cache()->ComputeCallInterceptor(
724 argc, kind_, extra_state, name, object, holder); 727 argc, kind_, extra_ic_state(), name, object, holder);
725 default: 728 default:
726 return Handle<Code>::null(); 729 return Handle<Code>::null();
727 } 730 }
728 } 731 }
729 732
730 733
734 Handle<Code> CallICBase::megamorphic_stub() {
735 return isolate()->stub_cache()->ComputeCallMegamorphic(
736 target()->arguments_count(), kind_, extra_ic_state());
737 }
738
739
740 Handle<Code> CallICBase::pre_monomorphic_stub() {
741 return isolate()->stub_cache()->ComputeCallPreMonomorphic(
742 target()->arguments_count(), kind_, extra_ic_state());
743 }
744
745
731 void CallICBase::UpdateCaches(LookupResult* lookup, 746 void CallICBase::UpdateCaches(LookupResult* lookup,
732 Handle<Object> object, 747 Handle<Object> object,
733 Handle<String> name) { 748 Handle<String> name) {
734 // Bail out if we didn't find a result. 749 // Bail out if we didn't find a result.
735 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 750 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
736 751
737 // Compute the number of arguments. 752 // Compute the number of arguments.
738 int argc = target()->arguments_count();
739 Handle<Code> code; 753 Handle<Code> code;
740 if (state() == UNINITIALIZED) { 754 code = state() == UNINITIALIZED
741 // This is the first time we execute this inline cache. 755 ? pre_monomorphic_stub()
742 // Set the target to the pre monomorphic stub to delay 756 : ComputeMonomorphicStub(lookup, object, name);
743 // setting the monomorphic state.
744 code = isolate()->stub_cache()->ComputeCallPreMonomorphic(
745 argc, kind_, extra_ic_state());
746 } else if (state() == MONOMORPHIC) {
747 if (kind_ == Code::CALL_IC &&
748 static_cast<CallIC*>(this)->TryUpdateExtraICState(lookup, object)) {
749 code = ComputeMonomorphicStub(lookup, extra_ic_state(), object, name);
750 } else if (TryRemoveInvalidPrototypeDependentStub(*object, *name)) {
751 MarkMonomorphicPrototypeFailure();
752 code = ComputeMonomorphicStub(lookup, extra_ic_state(), object, name);
753 } else {
754 code = isolate()->stub_cache()->ComputeCallMegamorphic(
755 argc, kind_, extra_ic_state());
ulan 2013/10/02 08:45:24 Why are we removing these cases?
Toon Verwaest 2013/10/02 08:56:05 They aren't removed, they are just folded in the e
756 }
757 } else {
758 code = ComputeMonomorphicStub(lookup, extra_ic_state(), object, name);
759 }
760 757
761 // If there's no appropriate stub we simply avoid updating the caches. 758 // If there's no appropriate stub we simply avoid updating the caches.
759 // TODO(verwaest): Install a slow fallback in this case to avoid not learning,
760 // and deopting Crankshaft code.
762 if (code.is_null()) return; 761 if (code.is_null()) return;
763 762
764 // Patch the call site depending on the state of the cache. 763 Handle<JSObject> cache_object = object->IsJSObject()
765 switch (state()) { 764 ? Handle<JSObject>::cast(object)
766 case UNINITIALIZED: 765 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
767 case MONOMORPHIC_PROTOTYPE_FAILURE: 766 isolate());
768 case PREMONOMORPHIC:
769 case MONOMORPHIC:
770 set_target(*code);
771 break;
772 case MEGAMORPHIC: {
773 // Cache code holding map should be consistent with
774 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
775 Handle<JSObject> cache_object = object->IsJSObject()
776 ? Handle<JSObject>::cast(object)
777 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
778 isolate());
779 // Update the stub cache.
780 UpdateMegamorphicCache(cache_object->map(), *name, *code);
781 break;
782 }
783 case DEBUG_STUB:
784 break;
785 case POLYMORPHIC:
786 case GENERIC:
787 UNREACHABLE();
788 break;
789 }
790 767
791 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", name, target()); 768 PatchCache(cache_object, name, code);
769 TRACE_IC("CallIC", name);
792 } 770 }
793 771
794 772
795 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object, 773 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object,
796 Handle<Object> key) { 774 Handle<Object> key) {
797 if (key->IsInternalizedString()) { 775 if (key->IsInternalizedString()) {
798 return CallICBase::LoadFunction(object, Handle<String>::cast(key)); 776 return CallICBase::LoadFunction(object, Handle<String>::cast(key));
799 } 777 }
800 778
801 if (object->IsUndefined() || object->IsNull()) { 779 if (object->IsUndefined() || object->IsNull()) {
(...skipping 10 matching lines...) Expand all
812 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); 790 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState);
813 if (object->IsJSObject()) { 791 if (object->IsJSObject()) {
814 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 792 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
815 if (receiver->elements()->map() == 793 if (receiver->elements()->map() ==
816 isolate()->heap()->non_strict_arguments_elements_map()) { 794 isolate()->heap()->non_strict_arguments_elements_map()) {
817 stub = isolate()->stub_cache()->ComputeCallArguments(argc); 795 stub = isolate()->stub_cache()->ComputeCallArguments(argc);
818 } 796 }
819 } 797 }
820 ASSERT(!stub.is_null()); 798 ASSERT(!stub.is_null());
821 set_target(*stub); 799 set_target(*stub);
822 TRACE_IC("KeyedCallIC", key, target()); 800 TRACE_IC("CallIC", key);
823 } 801 }
824 802
825 Handle<Object> result = GetProperty(isolate(), object, key); 803 Handle<Object> result = GetProperty(isolate(), object, key);
826 RETURN_IF_EMPTY_HANDLE(isolate(), result); 804 RETURN_IF_EMPTY_HANDLE(isolate(), result);
827 805
828 // Make receiver an object if the callee requires it. Strict mode or builtin 806 // Make receiver an object if the callee requires it. Strict mode or builtin
829 // functions do not wrap the receiver, non-strict functions and objects 807 // functions do not wrap the receiver, non-strict functions and objects
830 // called as functions do. 808 // called as functions do.
831 ReceiverToObjectIfRequired(result, object); 809 ReceiverToObjectIfRequired(result, object);
832 if (result->IsJSFunction()) return *result; 810 if (result->IsJSFunction()) return *result;
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 void IC::PatchCache(Handle<HeapObject> receiver, 1028 void IC::PatchCache(Handle<HeapObject> receiver,
1051 Handle<String> name, 1029 Handle<String> name,
1052 Handle<Code> code) { 1030 Handle<Code> code) {
1053 switch (state()) { 1031 switch (state()) {
1054 case UNINITIALIZED: 1032 case UNINITIALIZED:
1055 case PREMONOMORPHIC: 1033 case PREMONOMORPHIC:
1056 case MONOMORPHIC_PROTOTYPE_FAILURE: 1034 case MONOMORPHIC_PROTOTYPE_FAILURE:
1057 UpdateMonomorphicIC(receiver, code, name); 1035 UpdateMonomorphicIC(receiver, code, name);
1058 break; 1036 break;
1059 case MONOMORPHIC: 1037 case MONOMORPHIC:
1060 ASSERT(!target().is_identical_to(code)); 1038 // For now, call stubs are allowed to rewrite to the same stub. This
1039 // happens e.g., when the field does not contain a function.
1040 ASSERT(target()->is_call_stub() ||
1041 target()->is_keyed_call_stub() ||
1042 !target().is_identical_to(code));
1061 if (!target()->is_keyed_stub()) { 1043 if (!target()->is_keyed_stub()) {
1062 bool is_same_handler = false; 1044 bool is_same_handler = false;
1063 { 1045 {
1064 DisallowHeapAllocation no_allocation; 1046 DisallowHeapAllocation no_allocation;
1065 Code* old_handler = target()->FindFirstHandler(); 1047 Code* old_handler = target()->FindFirstHandler();
1066 is_same_handler = old_handler == *code; 1048 is_same_handler = old_handler == *code;
1067 } 1049 }
1068 if (is_same_handler 1050 if (is_same_handler
1069 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { 1051 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) {
1070 UpdateMonomorphicIC(receiver, code, name); 1052 UpdateMonomorphicIC(receiver, code, name);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1137 } else if (!object->IsJSObject()) { 1119 } else if (!object->IsJSObject()) {
1138 // TODO(jkummerow): It would be nice to support non-JSObjects in 1120 // TODO(jkummerow): It would be nice to support non-JSObjects in
1139 // ComputeLoadHandler, then we wouldn't need to go generic here. 1121 // ComputeLoadHandler, then we wouldn't need to go generic here.
1140 code = slow_stub(); 1122 code = slow_stub();
1141 } else { 1123 } else {
1142 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name); 1124 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name);
1143 if (code.is_null()) code = slow_stub(); 1125 if (code.is_null()) code = slow_stub();
1144 } 1126 }
1145 1127
1146 PatchCache(receiver, name, code); 1128 PatchCache(receiver, name, code);
1147 TRACE_IC("LoadIC", name, target()); 1129 TRACE_IC("LoadIC", name);
1148 } 1130 }
1149 1131
1150 1132
1151 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { 1133 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
1152 // Cache code holding map should be consistent with 1134 // Cache code holding map should be consistent with
1153 // GenerateMonomorphicCacheProbe. 1135 // GenerateMonomorphicCacheProbe.
1154 isolate()->stub_cache()->Set(name, map, code); 1136 isolate()->stub_cache()->Set(name, map, code);
1155 } 1137 }
1156 1138
1157 1139
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
1359 } else if (receiver->HasIndexedInterceptor()) { 1341 } else if (receiver->HasIndexedInterceptor()) {
1360 stub = indexed_interceptor_stub(); 1342 stub = indexed_interceptor_stub();
1361 } else if (!key->ToSmi()->IsFailure() && 1343 } else if (!key->ToSmi()->IsFailure() &&
1362 (!target().is_identical_to(non_strict_arguments_stub()))) { 1344 (!target().is_identical_to(non_strict_arguments_stub()))) {
1363 stub = LoadElementStub(receiver); 1345 stub = LoadElementStub(receiver);
1364 } 1346 }
1365 } 1347 }
1366 1348
1367 ASSERT(!stub.is_null()); 1349 ASSERT(!stub.is_null());
1368 set_target(*stub); 1350 set_target(*stub);
1369 TRACE_IC("KeyedLoadIC", key, target()); 1351 TRACE_IC("LoadIC", key);
1370 } 1352 }
1371 1353
1372 1354
1373 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); 1355 return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1374 } 1356 }
1375 1357
1376 1358
1377 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, 1359 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
1378 Handle<JSObject> receiver, 1360 Handle<JSObject> receiver,
1379 Handle<String> name) { 1361 Handle<String> name) {
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1551 // to have fast properties but a read-only length. 1533 // to have fast properties but a read-only length.
1552 if (FLAG_use_ic && 1534 if (FLAG_use_ic &&
1553 receiver->IsJSArray() && 1535 receiver->IsJSArray() &&
1554 name->Equals(isolate()->heap()->length_string()) && 1536 name->Equals(isolate()->heap()->length_string()) &&
1555 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && 1537 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
1556 receiver->HasFastProperties() && 1538 receiver->HasFastProperties() &&
1557 !receiver->map()->is_frozen()) { 1539 !receiver->map()->is_frozen()) {
1558 Handle<Code> stub = 1540 Handle<Code> stub =
1559 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); 1541 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate());
1560 set_target(*stub); 1542 set_target(*stub);
1561 TRACE_IC("StoreIC", name, stub); 1543 TRACE_IC("StoreIC", name);
1562 Handle<Object> result = JSReceiver::SetProperty( 1544 Handle<Object> result = JSReceiver::SetProperty(
1563 receiver, name, value, NONE, strict_mode(), store_mode); 1545 receiver, name, value, NONE, strict_mode(), store_mode);
1564 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1546 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1565 return *result; 1547 return *result;
1566 } 1548 }
1567 1549
1568 if (receiver->IsJSGlobalProxy()) { 1550 if (receiver->IsJSGlobalProxy()) {
1569 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { 1551 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) {
1570 // Generate a generic stub that goes to the runtime when we see a global 1552 // Generate a generic stub that goes to the runtime when we see a global
1571 // proxy as receiver. 1553 // proxy as receiver.
1572 Handle<Code> stub = global_proxy_stub(); 1554 Handle<Code> stub = global_proxy_stub();
1573 set_target(*stub); 1555 set_target(*stub);
1574 TRACE_IC("StoreIC", name, stub); 1556 TRACE_IC("StoreIC", name);
1575 } 1557 }
1576 Handle<Object> result = JSReceiver::SetProperty( 1558 Handle<Object> result = JSReceiver::SetProperty(
1577 receiver, name, value, NONE, strict_mode(), store_mode); 1559 receiver, name, value, NONE, strict_mode(), store_mode);
1578 RETURN_IF_EMPTY_HANDLE(isolate(), result); 1560 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1579 return *result; 1561 return *result;
1580 } 1562 }
1581 1563
1582 LookupResult lookup(isolate()); 1564 LookupResult lookup(isolate());
1583 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); 1565 bool can_store = LookupForWrite(receiver, name, value, &lookup, this);
1584 if (!can_store && 1566 if (!can_store &&
1585 strict_mode() == kStrictMode && 1567 strict_mode() == kStrictMode &&
1586 !(lookup.IsProperty() && lookup.IsReadOnly()) && 1568 !(lookup.IsProperty() && lookup.IsReadOnly()) &&
1587 IsUndeclaredGlobal(object)) { 1569 IsUndeclaredGlobal(object)) {
1588 // Strict mode doesn't allow setting non-existent global property. 1570 // Strict mode doesn't allow setting non-existent global property.
1589 return ReferenceError("not_defined", name); 1571 return ReferenceError("not_defined", name);
1590 } 1572 }
1591 if (FLAG_use_ic) { 1573 if (FLAG_use_ic) {
1592 if (state() == UNINITIALIZED) { 1574 if (state() == UNINITIALIZED) {
1593 Handle<Code> stub = pre_monomorphic_stub(); 1575 Handle<Code> stub = pre_monomorphic_stub();
1594 set_target(*stub); 1576 set_target(*stub);
1595 TRACE_IC("StoreIC", name, stub); 1577 TRACE_IC("StoreIC", name);
1596 } else if (can_store) { 1578 } else if (can_store) {
1597 UpdateCaches(&lookup, receiver, name, value); 1579 UpdateCaches(&lookup, receiver, name, value);
1598 } else if (!name->IsCacheable(isolate()) || 1580 } else if (!name->IsCacheable(isolate()) ||
1599 lookup.IsNormal() || 1581 lookup.IsNormal() ||
1600 (lookup.IsField() && lookup.CanHoldValue(value))) { 1582 (lookup.IsField() && lookup.CanHoldValue(value))) {
1601 Handle<Code> stub = generic_stub(); 1583 Handle<Code> stub = generic_stub();
1602 set_target(*stub); 1584 set_target(*stub);
1603 } 1585 }
1604 } 1586 }
1605 1587
(...skipping 15 matching lines...) Expand all
1621 // These are not cacheable, so we never see such LookupResults here. 1603 // These are not cacheable, so we never see such LookupResults here.
1622 ASSERT(!lookup->IsHandler()); 1604 ASSERT(!lookup->IsHandler());
1623 1605
1624 Handle<Code> code = ComputeStoreHandler(lookup, receiver, name, value); 1606 Handle<Code> code = ComputeStoreHandler(lookup, receiver, name, value);
1625 if (code.is_null()) { 1607 if (code.is_null()) {
1626 set_target(*generic_stub()); 1608 set_target(*generic_stub());
1627 return; 1609 return;
1628 } 1610 }
1629 1611
1630 PatchCache(receiver, name, code); 1612 PatchCache(receiver, name, code);
1631 TRACE_IC("StoreIC", name, target()); 1613 TRACE_IC("StoreIC", name);
1632 } 1614 }
1633 1615
1634 1616
1635 Handle<Code> StoreIC::ComputeStoreHandler(LookupResult* lookup, 1617 Handle<Code> StoreIC::ComputeStoreHandler(LookupResult* lookup,
1636 Handle<JSObject> receiver, 1618 Handle<JSObject> receiver,
1637 Handle<String> name, 1619 Handle<String> name,
1638 Handle<Object> value) { 1620 Handle<Object> value) {
1639 Handle<JSObject> holder(lookup->holder()); 1621 Handle<JSObject> holder(lookup->holder());
1640 switch (lookup->type()) { 1622 switch (lookup->type()) {
1641 case FIELD: 1623 case FIELD:
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
2009 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number"); 1991 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number");
2010 } 1992 }
2011 } else { 1993 } else {
2012 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object"); 1994 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object");
2013 } 1995 }
2014 } else { 1996 } else {
2015 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic"); 1997 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic");
2016 } 1998 }
2017 ASSERT(!stub.is_null()); 1999 ASSERT(!stub.is_null());
2018 set_target(*stub); 2000 set_target(*stub);
2019 TRACE_IC("KeyedStoreIC", key, target()); 2001 TRACE_IC("StoreIC", key);
2020 } 2002 }
2021 2003
2022 return Runtime::SetObjectPropertyOrFail( 2004 return Runtime::SetObjectPropertyOrFail(
2023 isolate(), object , key, value, NONE, strict_mode()); 2005 isolate(), object , key, value, NONE, strict_mode());
2024 } 2006 }
2025 2007
2026 2008
2027 Handle<Code> KeyedStoreIC::ComputeStoreHandler(LookupResult* lookup, 2009 Handle<Code> KeyedStoreIC::ComputeStoreHandler(LookupResult* lookup,
2028 Handle<JSObject> receiver, 2010 Handle<JSObject> receiver,
2029 Handle<String> name, 2011 Handle<String> name,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2072 2054
2073 // ---------------------------------------------------------------------------- 2055 // ----------------------------------------------------------------------------
2074 // Static IC stub generators. 2056 // Static IC stub generators.
2075 // 2057 //
2076 2058
2077 // Used from ic-<arch>.cc. 2059 // Used from ic-<arch>.cc.
2078 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { 2060 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
2079 HandleScope scope(isolate); 2061 HandleScope scope(isolate);
2080 ASSERT(args.length() == 2); 2062 ASSERT(args.length() == 2);
2081 CallIC ic(isolate); 2063 CallIC ic(isolate);
2082 ic.UpdateState(args[0], args[1]); 2064 Handle<Object> receiver = args.at<Object>(0);
2083 MaybeObject* maybe_result = ic.LoadFunction(args.at<Object>(0), 2065 Handle<String> key = args.at<String>(1);
2084 args.at<String>(1)); 2066 ic.UpdateState(receiver, key);
2067 MaybeObject* maybe_result = ic.LoadFunction(receiver, key);
2085 JSFunction* raw_function; 2068 JSFunction* raw_function;
2086 if (!maybe_result->To(&raw_function)) return maybe_result; 2069 if (!maybe_result->To(&raw_function)) return maybe_result;
2087 2070
2088 // The first time the inline cache is updated may be the first time the 2071 // The first time the inline cache is updated may be the first time the
2089 // function it references gets called. If the function is lazily compiled 2072 // function it references gets called. If the function is lazily compiled
2090 // then the first call will trigger a compilation. We check for this case 2073 // then the first call will trigger a compilation. We check for this case
2091 // and we do the compilation immediately, instead of waiting for the stub 2074 // and we do the compilation immediately, instead of waiting for the stub
2092 // currently attached to the JSFunction object to trigger compilation. 2075 // currently attached to the JSFunction object to trigger compilation.
2093 if (raw_function->is_compiled()) return raw_function; 2076 if (raw_function->is_compiled()) return raw_function;
2094 2077
2095 Handle<JSFunction> function(raw_function); 2078 Handle<JSFunction> function(raw_function);
2096 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); 2079 JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
2097 return *function; 2080 return *function;
2098 } 2081 }
2099 2082
2100 2083
2101 // Used from ic-<arch>.cc. 2084 // Used from ic-<arch>.cc.
2102 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { 2085 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
2103 HandleScope scope(isolate); 2086 HandleScope scope(isolate);
2104 ASSERT(args.length() == 2); 2087 ASSERT(args.length() == 2);
2105 KeyedCallIC ic(isolate); 2088 KeyedCallIC ic(isolate);
2106 ic.UpdateState(args[0], args[1]); 2089 Handle<Object> receiver = args.at<Object>(0);
2107 MaybeObject* maybe_result = 2090 Handle<Object> key = args.at<Object>(1);
2108 ic.LoadFunction(args.at<Object>(0), args.at<Object>(1)); 2091 ic.UpdateState(receiver, key);
2092 MaybeObject* maybe_result = ic.LoadFunction(receiver, key);
2109 // Result could be a function or a failure. 2093 // Result could be a function or a failure.
2110 JSFunction* raw_function = NULL; 2094 JSFunction* raw_function = NULL;
2111 if (!maybe_result->To(&raw_function)) return maybe_result; 2095 if (!maybe_result->To(&raw_function)) return maybe_result;
2112 2096
2113 if (raw_function->is_compiled()) return raw_function; 2097 if (raw_function->is_compiled()) return raw_function;
2114 2098
2115 Handle<JSFunction> function(raw_function, isolate); 2099 Handle<JSFunction> function(raw_function, isolate);
2116 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); 2100 JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
2117 return *function; 2101 return *function;
2118 } 2102 }
2119 2103
2120 2104
2121 // Used from ic-<arch>.cc. 2105 // Used from ic-<arch>.cc.
2122 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { 2106 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
2123 HandleScope scope(isolate); 2107 HandleScope scope(isolate);
2124 ASSERT(args.length() == 2); 2108 ASSERT(args.length() == 2);
2125 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); 2109 LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2126 ic.UpdateState(args[0], args[1]); 2110 Handle<Object> receiver = args.at<Object>(0);
2127 return ic.Load(args.at<Object>(0), args.at<String>(1)); 2111 Handle<String> key = args.at<String>(1);
2112 ic.UpdateState(receiver, key);
2113 return ic.Load(receiver, key);
2128 } 2114 }
2129 2115
2130 2116
2131 // Used from ic-<arch>.cc 2117 // Used from ic-<arch>.cc
2132 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { 2118 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
2133 HandleScope scope(isolate); 2119 HandleScope scope(isolate);
2134 ASSERT(args.length() == 2); 2120 ASSERT(args.length() == 2);
2135 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); 2121 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2136 ic.UpdateState(args[0], args[1]); 2122 Handle<Object> receiver = args.at<Object>(0);
2137 return ic.Load(args.at<Object>(0), args.at<Object>(1), MISS); 2123 Handle<Object> key = args.at<Object>(1);
2124 ic.UpdateState(receiver, key);
2125 return ic.Load(receiver, key, MISS);
2138 } 2126 }
2139 2127
2140 2128
2141 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) { 2129 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) {
2142 HandleScope scope(isolate); 2130 HandleScope scope(isolate);
2143 ASSERT(args.length() == 2); 2131 ASSERT(args.length() == 2);
2144 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate); 2132 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate);
2145 ic.UpdateState(args[0], args[1]); 2133 Handle<Object> receiver = args.at<Object>(0);
2146 return ic.Load(args.at<Object>(0), args.at<Object>(1), MISS); 2134 Handle<Object> key = args.at<Object>(1);
2135 ic.UpdateState(receiver, key);
2136 return ic.Load(receiver, key, MISS);
2147 } 2137 }
2148 2138
2149 2139
2150 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { 2140 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
2151 HandleScope scope(isolate); 2141 HandleScope scope(isolate);
2152 ASSERT(args.length() == 2); 2142 ASSERT(args.length() == 2);
2153 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate); 2143 KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2154 ic.UpdateState(args[0], args[1]); 2144 Handle<Object> receiver = args.at<Object>(0);
2155 return ic.Load(args.at<Object>(0), 2145 Handle<Object> key = args.at<Object>(1);
2156 args.at<Object>(1), 2146 ic.UpdateState(receiver, key);
2157 MISS_FORCE_GENERIC); 2147 return ic.Load(receiver, key, MISS_FORCE_GENERIC);
2158 } 2148 }
2159 2149
2160 2150
2161 // Used from ic-<arch>.cc. 2151 // Used from ic-<arch>.cc.
2162 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { 2152 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
2163 HandleScope scope(isolate); 2153 HandleScope scope(isolate);
2164 ASSERT(args.length() == 3); 2154 ASSERT(args.length() == 3);
2165 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2155 StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2166 ic.UpdateState(args[0], args[1]); 2156 Handle<Object> receiver = args.at<Object>(0);
2167 return ic.Store(args.at<Object>(0), 2157 Handle<String> key = args.at<String>(1);
2168 args.at<String>(1), 2158 ic.UpdateState(receiver, key);
2169 args.at<Object>(2)); 2159 return ic.Store(receiver, key, args.at<Object>(2));
2170 } 2160 }
2171 2161
2172 2162
2173 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { 2163 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) {
2174 HandleScope scope(isolate); 2164 HandleScope scope(isolate);
2175 ASSERT(args.length() == 3); 2165 ASSERT(args.length() == 3);
2176 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2166 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2177 ic.UpdateState(args[0], args[1]); 2167 Handle<Object> receiver = args.at<Object>(0);
2178 return ic.Store(args.at<Object>(0), 2168 Handle<String> key = args.at<String>(1);
2179 args.at<String>(1), 2169 ic.UpdateState(receiver, key);
2180 args.at<Object>(2)); 2170 return ic.Store(receiver, key, args.at<Object>(2));
2181 } 2171 }
2182 2172
2183 2173
2184 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { 2174 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
2185 SealHandleScope shs(isolate); 2175 SealHandleScope shs(isolate);
2186 2176
2187 ASSERT(args.length() == 2); 2177 ASSERT(args.length() == 2);
2188 JSArray* receiver = JSArray::cast(args[0]); 2178 JSArray* receiver = JSArray::cast(args[0]);
2189 Object* len = args[1]; 2179 Object* len = args[1];
2190 2180
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2253 // Return the stored value. 2243 // Return the stored value.
2254 return value; 2244 return value;
2255 } 2245 }
2256 2246
2257 2247
2258 // Used from ic-<arch>.cc. 2248 // Used from ic-<arch>.cc.
2259 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { 2249 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
2260 HandleScope scope(isolate); 2250 HandleScope scope(isolate);
2261 ASSERT(args.length() == 3); 2251 ASSERT(args.length() == 3);
2262 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2252 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2263 ic.UpdateState(args[0], args[1]); 2253 Handle<Object> receiver = args.at<Object>(0);
2264 return ic.Store(args.at<Object>(0), 2254 Handle<Object> key = args.at<Object>(1);
2265 args.at<Object>(1), 2255 ic.UpdateState(receiver, key);
2266 args.at<Object>(2), 2256 return ic.Store(receiver, key, args.at<Object>(2), MISS);
2267 MISS);
2268 } 2257 }
2269 2258
2270 2259
2271 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { 2260 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) {
2272 HandleScope scope(isolate); 2261 HandleScope scope(isolate);
2273 ASSERT(args.length() == 3); 2262 ASSERT(args.length() == 3);
2274 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2263 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2275 ic.UpdateState(args[0], args[1]); 2264 Handle<Object> receiver = args.at<Object>(0);
2276 return ic.Store(args.at<Object>(0), 2265 Handle<Object> key = args.at<Object>(1);
2277 args.at<Object>(1), 2266 ic.UpdateState(receiver, key);
2278 args.at<Object>(2), 2267 return ic.Store(receiver, key, args.at<Object>(2), MISS);
2279 MISS);
2280 } 2268 }
2281 2269
2282 2270
2283 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { 2271 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) {
2284 HandleScope scope(isolate); 2272 HandleScope scope(isolate);
2285 ASSERT(args.length() == 3); 2273 ASSERT(args.length() == 3);
2286 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2274 StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2287 Handle<Object> object = args.at<Object>(0); 2275 Handle<Object> object = args.at<Object>(0);
2288 Handle<Object> key = args.at<Object>(1); 2276 Handle<Object> key = args.at<Object>(1);
2289 Handle<Object> value = args.at<Object>(2); 2277 Handle<Object> value = args.at<Object>(2);
(...skipping 21 matching lines...) Expand all
2311 value, 2299 value,
2312 NONE, 2300 NONE,
2313 strict_mode); 2301 strict_mode);
2314 } 2302 }
2315 2303
2316 2304
2317 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { 2305 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2318 HandleScope scope(isolate); 2306 HandleScope scope(isolate);
2319 ASSERT(args.length() == 3); 2307 ASSERT(args.length() == 3);
2320 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); 2308 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2321 ic.UpdateState(args[0], args[1]); 2309 Handle<Object> receiver = args.at<Object>(0);
2322 return ic.Store(args.at<Object>(0), 2310 Handle<Object> key = args.at<Object>(1);
2323 args.at<Object>(1), 2311 ic.UpdateState(receiver, key);
2324 args.at<Object>(2), 2312 return ic.Store(receiver, key, args.at<Object>(2), MISS_FORCE_GENERIC);
2325 MISS_FORCE_GENERIC);
2326 } 2313 }
2327 2314
2328 2315
2329 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { 2316 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) {
2330 HandleScope scope(isolate); 2317 HandleScope scope(isolate);
2331 ASSERT(args.length() == 4); 2318 ASSERT(args.length() == 4);
2332 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); 2319 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2333 Handle<Object> value = args.at<Object>(0); 2320 Handle<Object> value = args.at<Object>(0);
2334 Handle<Object> key = args.at<Object>(2); 2321 Handle<Object> key = args.at<Object>(2);
2335 Handle<Object> object = args.at<Object>(3); 2322 Handle<Object> object = args.at<Object>(3);
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
2939 #undef ADDR 2926 #undef ADDR
2940 }; 2927 };
2941 2928
2942 2929
2943 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2930 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2944 return IC_utilities[id]; 2931 return IC_utilities[id];
2945 } 2932 }
2946 2933
2947 2934
2948 } } // namespace v8::internal 2935 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698