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

Side by Side Diff: src/ic.cc

Issue 6344005: Introduce extra IC state to record additional feedback from IC-s. (Closed)
Patch Set: Last fixes and ports to arm and x64 Created 9 years, 11 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
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 !current->IsJSGlobalProxy() && 147 !current->IsJSGlobalProxy() &&
148 !current->IsJSGlobalObject()) { 148 !current->IsJSGlobalObject()) {
149 return true; 149 return true;
150 } 150 }
151 } 151 }
152 152
153 return false; 153 return false;
154 } 154 }
155 155
156 156
157 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { 157 static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
158 IC::State state = target->ic_state(); 158 Object* receiver,
159 159 Object* name) {
160 if (state != MONOMORPHIC || !name->IsString()) return state;
161 if (receiver->IsUndefined() || receiver->IsNull()) return state;
162
163 InlineCacheHolderFlag cache_holder = 160 InlineCacheHolderFlag cache_holder =
164 Code::ExtractCacheHolderFromFlags(target->flags()); 161 Code::ExtractCacheHolderFromFlags(target->flags());
165 162
166
167 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) { 163 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) {
168 // The stub was generated for JSObject but called for non-JSObject. 164 // The stub was generated for JSObject but called for non-JSObject.
169 // IC::GetCodeCacheHolder is not applicable. 165 // IC::GetCodeCacheHolder is not applicable.
170 return MONOMORPHIC; 166 return false;
171 } else if (cache_holder == PROTOTYPE_MAP && 167 } else if (cache_holder == PROTOTYPE_MAP &&
172 receiver->GetPrototype()->IsNull()) { 168 receiver->GetPrototype()->IsNull()) {
173 // IC::GetCodeCacheHolder is not applicable. 169 // IC::GetCodeCacheHolder is not applicable.
174 return MONOMORPHIC; 170 return false;
175 } 171 }
176 Map* map = IC::GetCodeCacheHolder(receiver, cache_holder)->map(); 172 Map* map = IC::GetCodeCacheHolder(receiver, cache_holder)->map();
177 173
178 // Decide whether the inline cache failed because of changes to the 174 // Decide whether the inline cache failed because of changes to the
179 // receiver itself or changes to one of its prototypes. 175 // receiver itself or changes to one of its prototypes.
180 // 176 //
181 // If there are changes to the receiver itself, the map of the 177 // If there are changes to the receiver itself, the map of the
182 // receiver will have changed and the current target will not be in 178 // receiver will have changed and the current target will not be in
183 // the receiver map's code cache. Therefore, if the current target 179 // the receiver map's code cache. Therefore, if the current target
184 // is in the receiver map's code cache, the inline cache failed due 180 // is in the receiver map's code cache, the inline cache failed due
185 // to prototype check failure. 181 // to prototype check failure.
186 int index = map->IndexInCodeCache(name, target); 182 int index = map->IndexInCodeCache(name, target);
187 if (index >= 0) { 183 if (index >= 0) {
188 // For keyed load/store/call, the most likely cause of cache failure is 184 map->RemoveFromCodeCache(String::cast(name), target, index);
189 // that the key has changed. We do not distinguish between 185 return true;
190 // prototype and non-prototype failures for keyed access. 186 }
191 Code::Kind kind = target->kind();
192 if (kind == Code::KEYED_LOAD_IC ||
193 kind == Code::KEYED_STORE_IC ||
194 kind == Code::KEYED_CALL_IC) {
195 return MONOMORPHIC;
196 }
197 187
198 // Remove the target from the code cache to avoid hitting the same 188 return false;
199 // invalid stub again. 189 }
200 map->RemoveFromCodeCache(String::cast(name), target, index);
201 190
191
192 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
193 IC::State state = target->ic_state();
194
195 if (state != MONOMORPHIC || !name->IsString()) return state;
196 if (receiver->IsUndefined() || receiver->IsNull()) return state;
197
198 // For keyed load/store/call, the most likely cause of cache failure is
199 // that the key has changed. We do not distinguish between
200 // prototype and non-prototype failures for keyed access.
201 Code::Kind kind = target->kind();
202 if (kind == Code::KEYED_LOAD_IC ||
203 kind == Code::KEYED_STORE_IC ||
204 kind == Code::KEYED_CALL_IC) {
205 return MONOMORPHIC;
206 }
207
208 // Remove the target from the code cache if it became invalid
209 // because of changes in the prototype chain to avoid hitting it
210 // again.
211 // Call stubs handle this later to allow extra IC state
212 // transitions.
213 if (kind != Code::CALL_IC &&
214 TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) {
202 return MONOMORPHIC_PROTOTYPE_FAILURE; 215 return MONOMORPHIC_PROTOTYPE_FAILURE;
203 } 216 }
204 217
205 // The builtins object is special. It only changes when JavaScript 218 // The builtins object is special. It only changes when JavaScript
206 // builtins are loaded lazily. It is important to keep inline 219 // builtins are loaded lazily. It is important to keep inline
207 // caches for the builtins object monomorphic. Therefore, if we get 220 // caches for the builtins object monomorphic. Therefore, if we get
208 // an inline cache miss for the builtins object after lazily loading 221 // an inline cache miss for the builtins object after lazily loading
209 // JavaScript builtins, we return uninitialized as the state to 222 // JavaScript builtins, we return uninitialized as the state to
210 // force the inline cache back to monomorphic state. 223 // force the inline cache back to monomorphic state.
211 if (receiver->IsJSBuiltinsObject()) { 224 if (receiver->IsJSBuiltinsObject()) {
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 // Change the receiver to the result of calling ToObject on it. 488 // Change the receiver to the result of calling ToObject on it.
476 const int argc = this->target()->arguments_count(); 489 const int argc = this->target()->arguments_count();
477 StackFrameLocator locator; 490 StackFrameLocator locator;
478 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); 491 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
479 int index = frame->ComputeExpressionsCount() - (argc + 1); 492 int index = frame->ComputeExpressionsCount() - (argc + 1);
480 frame->SetExpression(index, *Factory::ToObject(object)); 493 frame->SetExpression(index, *Factory::ToObject(object));
481 } 494 }
482 495
483 496
484 MaybeObject* CallICBase::LoadFunction(State state, 497 MaybeObject* CallICBase::LoadFunction(State state,
498 Code::ExtraICState extra_ic_state,
485 Handle<Object> object, 499 Handle<Object> object,
486 Handle<String> name) { 500 Handle<String> name) {
487 // If the object is undefined or null it's illegal to try to get any 501 // If the object is undefined or null it's illegal to try to get any
488 // of its properties; throw a TypeError in that case. 502 // of its properties; throw a TypeError in that case.
489 if (object->IsUndefined() || object->IsNull()) { 503 if (object->IsUndefined() || object->IsNull()) {
490 return TypeError("non_object_property_call", object, name); 504 return TypeError("non_object_property_call", object, name);
491 } 505 }
492 506
493 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { 507 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
494 ReceiverToObject(object); 508 ReceiverToObject(object);
(...skipping 25 matching lines...) Expand all
520 // If the object does not have the requested property, check which 534 // If the object does not have the requested property, check which
521 // exception we need to throw. 535 // exception we need to throw.
522 if (IsContextual(object)) { 536 if (IsContextual(object)) {
523 return ReferenceError("not_defined", name); 537 return ReferenceError("not_defined", name);
524 } 538 }
525 return TypeError("undefined_method", object, name); 539 return TypeError("undefined_method", object, name);
526 } 540 }
527 541
528 // Lookup is valid: Update inline cache and stub cache. 542 // Lookup is valid: Update inline cache and stub cache.
529 if (FLAG_use_ic) { 543 if (FLAG_use_ic) {
530 UpdateCaches(&lookup, state, object, name); 544 UpdateCaches(&lookup, state, extra_ic_state, object, name);
531 } 545 }
532 546
533 // Get the property. 547 // Get the property.
534 PropertyAttributes attr; 548 PropertyAttributes attr;
535 Object* result; 549 Object* result;
536 { MaybeObject* maybe_result = 550 { MaybeObject* maybe_result =
537 object->GetProperty(*object, &lookup, *name, &attr); 551 object->GetProperty(*object, &lookup, *name, &attr);
538 if (!maybe_result->ToObject(&result)) return maybe_result; 552 if (!maybe_result->ToObject(&result)) return maybe_result;
539 } 553 }
540 if (lookup.type() == INTERCEPTOR) { 554 if (lookup.type() == INTERCEPTOR) {
(...skipping 28 matching lines...) Expand all
569 // Try to find a suitable function delegate for the object at hand. 583 // Try to find a suitable function delegate for the object at hand.
570 result = TryCallAsFunction(result); 584 result = TryCallAsFunction(result);
571 MaybeObject* answer = result; 585 MaybeObject* answer = result;
572 if (!result->IsJSFunction()) { 586 if (!result->IsJSFunction()) {
573 answer = TypeError("property_not_function", object, name); 587 answer = TypeError("property_not_function", object, name);
574 } 588 }
575 return answer; 589 return answer;
576 } 590 }
577 591
578 592
593 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
594 Handle<Object> object,
595 Code::ExtraICState* extra_ic_state) {
596 ASSERT(kind_ == Code::CALL_IC);
597 if (lookup->type() != CONSTANT_FUNCTION) return false;
598 JSFunction* function = lookup->GetConstantFunction();
599 if (!function->shared()->HasBuiltinFunctionId()) return false;
600
601 // Fetch the arguments passed to the called function.
602 const int argc = target()->arguments_count();
603 Address entry = Top::c_entry_fp(Top::GetCurrentThread());
604 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
605 Arguments args(argc + 1,
606 &Memory::Object_at(fp +
607 StandardFrameConstants::kCallerSPOffset +
608 argc * kPointerSize));
609 switch (function->shared()->builtin_function_id()) {
610 case kStringCharCodeAt:
611 case kStringCharAt:
612 if (object->IsString()) {
613 String* string = String::cast(*object);
614 // Check that there's the right wrapper in the receiver slot.
615 ASSERT(string == JSValue::cast(args[0])->value());
616 // If we're in the default (fastest) state and the index is
617 // out of bounds, update the state to record this fact.
618 if (*extra_ic_state == DEFAULT_STRING_STUB &&
619 argc >= 1 && args[1]->IsNumber()) {
620 double index;
621 if (args[1]->IsSmi()) {
622 index = Smi::cast(args[1])->value();
623 } else {
624 ASSERT(args[1]->IsHeapNumber());
625 index = DoubleToInteger(HeapNumber::cast(args[1])->value());
626 }
627 if (index < 0 || index >= string->length()) {
628 *extra_ic_state = STRING_INDEX_OUT_OF_BOUNDS;
629 return true;
630 }
631 }
632 }
633 break;
634 default:
635 return false;
636 }
637 return false;
638 }
639
640
641 MaybeObject* CallICBase::ComputeMonomorphicStub(
642 LookupResult* lookup,
643 State state,
644 Code::ExtraICState extra_ic_state,
645 Handle<Object> object,
646 Handle<String> name) {
647 int argc = target()->arguments_count();
648 InLoopFlag in_loop = target()->ic_in_loop();
649 MaybeObject* maybe_code = NULL;
650 switch (lookup->type()) {
651 case FIELD: {
652 int index = lookup->GetFieldIndex();
653 maybe_code = StubCache::ComputeCallField(argc,
654 in_loop,
655 kind_,
656 *name,
657 *object,
658 lookup->holder(),
659 index);
660 break;
661 }
662 case CONSTANT_FUNCTION: {
663 // Get the constant function and compute the code stub for this
664 // call; used for rewriting to monomorphic state and making sure
665 // that the code stub is in the stub cache.
666 JSFunction* function = lookup->GetConstantFunction();
667 maybe_code = StubCache::ComputeCallConstant(argc,
668 in_loop,
669 kind_,
670 extra_ic_state,
671 *name,
672 *object,
673 lookup->holder(),
674 function);
675 break;
676 }
677 case NORMAL: {
678 if (!object->IsJSObject()) return NULL;
679 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
680
681 if (lookup->holder()->IsGlobalObject()) {
682 GlobalObject* global = GlobalObject::cast(lookup->holder());
683 JSGlobalPropertyCell* cell =
684 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
685 if (!cell->value()->IsJSFunction()) return NULL;
686 JSFunction* function = JSFunction::cast(cell->value());
687 maybe_code = StubCache::ComputeCallGlobal(argc,
688 in_loop,
689 kind_,
690 *name,
691 *receiver,
692 global,
693 cell,
694 function);
695 } else {
696 // There is only one shared stub for calling normalized
697 // properties. It does not traverse the prototype chain, so the
698 // property must be found in the receiver for the stub to be
699 // applicable.
700 if (lookup->holder() != *receiver) return NULL;
701 maybe_code = StubCache::ComputeCallNormal(argc,
702 in_loop,
703 kind_,
704 *name,
705 *receiver);
706 }
707 break;
708 }
709 case INTERCEPTOR: {
710 ASSERT(HasInterceptorGetter(lookup->holder()));
711 maybe_code = StubCache::ComputeCallInterceptor(argc,
712 kind_,
713 *name,
714 *object,
715 lookup->holder());
716 break;
717 }
718 default:
719 maybe_code = NULL;
720 break;
721 }
722 return maybe_code;
723 }
724
725
579 void CallICBase::UpdateCaches(LookupResult* lookup, 726 void CallICBase::UpdateCaches(LookupResult* lookup,
580 State state, 727 State state,
728 Code::ExtraICState extra_ic_state,
581 Handle<Object> object, 729 Handle<Object> object,
582 Handle<String> name) { 730 Handle<String> name) {
583 // Bail out if we didn't find a result. 731 // Bail out if we didn't find a result.
584 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 732 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
585 733
586 if (lookup->holder() != *object && 734 if (lookup->holder() != *object &&
587 HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) { 735 HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) {
588 // Suppress optimization for prototype chains with slow properties objects 736 // Suppress optimization for prototype chains with slow properties objects
589 // in the middle. 737 // in the middle.
590 return; 738 return;
591 } 739 }
592 740
593 // Compute the number of arguments. 741 // Compute the number of arguments.
594 int argc = target()->arguments_count(); 742 int argc = target()->arguments_count();
595 InLoopFlag in_loop = target()->ic_in_loop(); 743 InLoopFlag in_loop = target()->ic_in_loop();
596 MaybeObject* maybe_code = NULL; 744 MaybeObject* maybe_code = NULL;
597 Object* code; 745 bool had_proto_failure = false;
598 if (state == UNINITIALIZED) { 746 if (state == UNINITIALIZED) {
599 // This is the first time we execute this inline cache. 747 // This is the first time we execute this inline cache.
600 // Set the target to the pre monomorphic stub to delay 748 // Set the target to the pre monomorphic stub to delay
601 // setting the monomorphic state. 749 // setting the monomorphic state.
602 maybe_code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_); 750 maybe_code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_);
603 } else if (state == MONOMORPHIC) { 751 } else if (state == MONOMORPHIC) {
604 maybe_code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_); 752 if (kind_ == Code::CALL_IC &&
753 TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
754 maybe_code = ComputeMonomorphicStub(lookup,
755 state,
756 extra_ic_state,
757 object,
758 name);
759 } else if (kind_ == Code::CALL_IC &&
760 TryRemoveInvalidPrototypeDependentStub(target(),
761 *object,
762 *name)) {
763 had_proto_failure = true;
764 maybe_code = ComputeMonomorphicStub(lookup,
765 state,
766 extra_ic_state,
767 object,
768 name);
769 } else {
770 maybe_code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_);
771 }
605 } else { 772 } else {
606 // Compute monomorphic stub. 773 maybe_code = ComputeMonomorphicStub(lookup,
607 switch (lookup->type()) { 774 state,
608 case FIELD: { 775 extra_ic_state,
609 int index = lookup->GetFieldIndex(); 776 object,
610 maybe_code = StubCache::ComputeCallField(argc, 777 name);
611 in_loop,
612 kind_,
613 *name,
614 *object,
615 lookup->holder(),
616 index);
617 break;
618 }
619 case CONSTANT_FUNCTION: {
620 // Get the constant function and compute the code stub for this
621 // call; used for rewriting to monomorphic state and making sure
622 // that the code stub is in the stub cache.
623 JSFunction* function = lookup->GetConstantFunction();
624 maybe_code = StubCache::ComputeCallConstant(argc,
625 in_loop,
626 kind_,
627 *name,
628 *object,
629 lookup->holder(),
630 function);
631 break;
632 }
633 case NORMAL: {
634 if (!object->IsJSObject()) return;
635 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
636
637 if (lookup->holder()->IsGlobalObject()) {
638 GlobalObject* global = GlobalObject::cast(lookup->holder());
639 JSGlobalPropertyCell* cell =
640 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
641 if (!cell->value()->IsJSFunction()) return;
642 JSFunction* function = JSFunction::cast(cell->value());
643 maybe_code = StubCache::ComputeCallGlobal(argc,
644 in_loop,
645 kind_,
646 *name,
647 *receiver,
648 global,
649 cell,
650 function);
651 } else {
652 // There is only one shared stub for calling normalized
653 // properties. It does not traverse the prototype chain, so the
654 // property must be found in the receiver for the stub to be
655 // applicable.
656 if (lookup->holder() != *receiver) return;
657 maybe_code = StubCache::ComputeCallNormal(argc,
658 in_loop,
659 kind_,
660 *name,
661 *receiver);
662 }
663 break;
664 }
665 case INTERCEPTOR: {
666 ASSERT(HasInterceptorGetter(lookup->holder()));
667 maybe_code = StubCache::ComputeCallInterceptor(argc,
668 kind_,
669 *name,
670 *object,
671 lookup->holder());
672 break;
673 }
674 default:
675 return;
676 }
677 } 778 }
678 779
679 // If we're unable to compute the stub (not enough memory left), we 780 // If we're unable to compute the stub (not enough memory left), we
680 // simply avoid updating the caches. 781 // simply avoid updating the caches.
782 Object* code;
681 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; 783 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
682 784
683 // Patch the call site depending on the state of the cache. 785 // Patch the call site depending on the state of the cache.
684 if (state == UNINITIALIZED || 786 if (state == UNINITIALIZED ||
685 state == PREMONOMORPHIC || 787 state == PREMONOMORPHIC ||
686 state == MONOMORPHIC || 788 state == MONOMORPHIC ||
687 state == MONOMORPHIC_PROTOTYPE_FAILURE) { 789 state == MONOMORPHIC_PROTOTYPE_FAILURE) {
688 set_target(Code::cast(code)); 790 set_target(Code::cast(code));
689 } else if (state == MEGAMORPHIC) { 791 } else if (state == MEGAMORPHIC) {
690 // Cache code holding map should be consistent with 792 // Cache code holding map should be consistent with
691 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. 793 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
692 Map* map = JSObject::cast(object->IsJSObject() ? *object : 794 Map* map = JSObject::cast(object->IsJSObject() ? *object :
693 object->GetPrototype())->map(); 795 object->GetPrototype())->map();
694 796
695 // Update the stub cache. 797 // Update the stub cache.
696 StubCache::Set(*name, map, Code::cast(code)); 798 StubCache::Set(*name, map, Code::cast(code));
697 } 799 }
698 800
801 USE(had_proto_failure);
699 #ifdef DEBUG 802 #ifdef DEBUG
803 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE;
700 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", 804 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
701 name, state, target(), in_loop ? " (in-loop)" : ""); 805 name, state, target(), in_loop ? " (in-loop)" : "");
702 #endif 806 #endif
703 } 807 }
704 808
705 809
706 MaybeObject* KeyedCallIC::LoadFunction(State state, 810 MaybeObject* KeyedCallIC::LoadFunction(State state,
707 Handle<Object> object, 811 Handle<Object> object,
708 Handle<Object> key) { 812 Handle<Object> key) {
709 if (key->IsSymbol()) { 813 if (key->IsSymbol()) {
710 return CallICBase::LoadFunction(state, object, Handle<String>::cast(key)); 814 return CallICBase::LoadFunction(state,
815 Code::kNoExtraICState,
816 object,
817 Handle<String>::cast(key));
711 } 818 }
712 819
713 if (object->IsUndefined() || object->IsNull()) { 820 if (object->IsUndefined() || object->IsNull()) {
714 return TypeError("non_object_property_call", object, key); 821 return TypeError("non_object_property_call", object, key);
715 } 822 }
716 823
717 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { 824 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
718 ReceiverToObject(object); 825 ReceiverToObject(object);
719 } 826 }
720 827
(...skipping 913 matching lines...) Expand 10 before | Expand all | Expand 10 after
1634 return *function_handle; 1741 return *function_handle;
1635 } 1742 }
1636 1743
1637 1744
1638 // Used from ic-<arch>.cc. 1745 // Used from ic-<arch>.cc.
1639 MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) { 1746 MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) {
1640 NoHandleAllocation na; 1747 NoHandleAllocation na;
1641 ASSERT(args.length() == 2); 1748 ASSERT(args.length() == 2);
1642 CallIC ic; 1749 CallIC ic;
1643 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1750 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1751 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1752 MaybeObject* maybe_result = ic.LoadFunction(state,
1753 extra_ic_state,
1754 args.at<Object>(0),
1755 args.at<String>(1));
1644 Object* result; 1756 Object* result;
1645 { MaybeObject* maybe_result = 1757 if (!maybe_result->ToObject(&result)) return maybe_result;
1646 ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
1647 if (!maybe_result->ToObject(&result)) return maybe_result;
1648 }
1649 1758
1650 // The first time the inline cache is updated may be the first time the 1759 // The first time the inline cache is updated may be the first time the
1651 // function it references gets called. If the function was lazily compiled 1760 // function it references gets called. If the function was lazily compiled
1652 // then the first call will trigger a compilation. We check for this case 1761 // then the first call will trigger a compilation. We check for this case
1653 // and we do the compilation immediately, instead of waiting for the stub 1762 // and we do the compilation immediately, instead of waiting for the stub
1654 // currently attached to the JSFunction object to trigger compilation. We 1763 // currently attached to the JSFunction object to trigger compilation. We
1655 // do this in the case where we know that the inline cache is inside a loop, 1764 // do this in the case where we know that the inline cache is inside a loop,
1656 // because then we know that we want to optimize the function. 1765 // because then we know that we want to optimize the function.
1657 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { 1766 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
1658 return result; 1767 return result;
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after
2164 #undef ADDR 2273 #undef ADDR
2165 }; 2274 };
2166 2275
2167 2276
2168 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2277 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2169 return IC_utilities[id]; 2278 return IC_utilities[id];
2170 } 2279 }
2171 2280
2172 2281
2173 } } // namespace v8::internal 2282 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698