OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
93 } else { | 93 } else { |
94 PrintF("<unknown>"); | 94 PrintF("<unknown>"); |
95 } | 95 } |
96 PrintF(" (%c->%c)", | 96 PrintF(" (%c->%c)", |
97 TransitionMarkFromState(old_state), | 97 TransitionMarkFromState(old_state), |
98 TransitionMarkFromState(new_state)); | 98 TransitionMarkFromState(new_state)); |
99 name->Print(); | 99 name->Print(); |
100 PrintF("]\n"); | 100 PrintF("]\n"); |
101 } | 101 } |
102 } | 102 } |
103 #endif | 103 #endif // DEBUG |
104 | |
105 | |
106 #define TRACE_IC(type, name, old_state, new_target) \ | |
107 ASSERT((TraceIC(type, name, old_state, new_target), true)) | |
104 | 108 |
105 | 109 |
106 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { | 110 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { |
107 ASSERT(isolate == Isolate::Current()); | 111 ASSERT(isolate == Isolate::Current()); |
108 // To improve the performance of the (much used) IC code, we unfold | 112 // To improve the performance of the (much used) IC code, we unfold |
109 // a few levels of the stack frame iteration code. This yields a | 113 // a few levels of the stack frame iteration code. This yields a |
110 // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. | 114 // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. |
111 const Address entry = | 115 const Address entry = |
112 Isolate::c_entry_fp(isolate->thread_local_top()); | 116 Isolate::c_entry_fp(isolate->thread_local_top()); |
113 Address* pc_address = | 117 Address* pc_address = |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
610 } | 614 } |
611 } | 615 } |
612 break; | 616 break; |
613 default: | 617 default: |
614 return false; | 618 return false; |
615 } | 619 } |
616 return false; | 620 return false; |
617 } | 621 } |
618 | 622 |
619 | 623 |
620 MaybeObject* CallICBase::ComputeMonomorphicStub( | 624 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, |
621 LookupResult* lookup, | 625 State state, |
622 State state, | 626 Code::ExtraICState extra_state, |
623 Code::ExtraICState extra_ic_state, | 627 Handle<Object> object, |
624 Handle<Object> object, | 628 Handle<String> name) { |
625 Handle<String> name) { | |
626 int argc = target()->arguments_count(); | 629 int argc = target()->arguments_count(); |
627 MaybeObject* maybe_code = NULL; | 630 Handle<JSObject> holder(lookup->holder()); |
628 switch (lookup->type()) { | 631 switch (lookup->type()) { |
629 case FIELD: { | 632 case FIELD: { |
630 int index = lookup->GetFieldIndex(); | 633 int index = lookup->GetFieldIndex(); |
631 maybe_code = isolate()->stub_cache()->ComputeCallField(argc, | 634 return isolate()->stub_cache()->ComputeCallField( |
632 kind_, | 635 argc, kind_, extra_state, name, object, holder, index); |
633 extra_ic_state, | |
634 *name, | |
635 *object, | |
636 lookup->holder(), | |
637 index); | |
638 break; | |
639 } | 636 } |
640 case CONSTANT_FUNCTION: { | 637 case CONSTANT_FUNCTION: { |
641 // Get the constant function and compute the code stub for this | 638 // Get the constant function and compute the code stub for this |
642 // call; used for rewriting to monomorphic state and making sure | 639 // call; used for rewriting to monomorphic state and making sure |
643 // that the code stub is in the stub cache. | 640 // that the code stub is in the stub cache. |
644 JSFunction* function = lookup->GetConstantFunction(); | 641 Handle<JSFunction> function(lookup->GetConstantFunction()); |
645 maybe_code = | 642 return isolate()->stub_cache()->ComputeCallConstant( |
646 isolate()->stub_cache()->ComputeCallConstant(argc, | 643 argc, kind_, extra_state, name, object, holder, function); |
647 kind_, | |
648 extra_ic_state, | |
649 *name, | |
650 *object, | |
651 lookup->holder(), | |
652 function); | |
653 break; | |
654 } | 644 } |
655 case NORMAL: { | 645 case NORMAL: { |
656 if (!object->IsJSObject()) return NULL; | 646 // If we return a null handle, the IC will not be patched. |
647 if (!object->IsJSObject()) return Handle<Code>::null(); | |
657 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 648 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
658 | 649 |
659 if (lookup->holder()->IsGlobalObject()) { | 650 if (holder->IsGlobalObject()) { |
660 GlobalObject* global = GlobalObject::cast(lookup->holder()); | 651 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
661 JSGlobalPropertyCell* cell = | 652 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); |
662 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | 653 if (!cell->value()->IsJSFunction()) return Handle<Code>::null(); |
663 if (!cell->value()->IsJSFunction()) return NULL; | 654 Handle<JSFunction> function(JSFunction::cast(cell->value())); |
664 JSFunction* function = JSFunction::cast(cell->value()); | 655 return isolate()->stub_cache()->ComputeCallGlobal( |
665 maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc, | 656 argc, kind_, extra_state, name, receiver, global, cell, function); |
666 kind_, | |
667 extra_ic_state, | |
668 *name, | |
669 *receiver, | |
670 global, | |
671 cell, | |
672 function); | |
673 } else { | 657 } else { |
674 // There is only one shared stub for calling normalized | 658 // There is only one shared stub for calling normalized |
675 // properties. It does not traverse the prototype chain, so the | 659 // properties. It does not traverse the prototype chain, so the |
676 // property must be found in the receiver for the stub to be | 660 // property must be found in the receiver for the stub to be |
677 // applicable. | 661 // applicable. |
678 if (lookup->holder() != *receiver) return NULL; | 662 if (!holder.is_identical_to(receiver)) return Handle<Code>::null(); |
679 maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc, | 663 return isolate()->stub_cache()->ComputeCallNormal( |
680 kind_, | 664 argc, kind_, extra_state); |
681 extra_ic_state, | |
682 *name, | |
683 *receiver); | |
684 } | 665 } |
685 break; | 666 break; |
686 } | 667 } |
687 case INTERCEPTOR: { | 668 case INTERCEPTOR: |
688 ASSERT(HasInterceptorGetter(lookup->holder())); | 669 ASSERT(HasInterceptorGetter(*holder)); |
689 maybe_code = isolate()->stub_cache()->ComputeCallInterceptor( | 670 return isolate()->stub_cache()->ComputeCallInterceptor( |
690 argc, | 671 argc, kind_, extra_state, name, object, holder); |
691 kind_, | |
692 extra_ic_state, | |
693 *name, | |
694 *object, | |
695 lookup->holder()); | |
696 break; | |
697 } | |
698 default: | 672 default: |
699 maybe_code = NULL; | 673 return Handle<Code>::null(); |
700 break; | |
701 } | 674 } |
702 return maybe_code; | |
703 } | 675 } |
704 | 676 |
705 | 677 |
706 void CallICBase::UpdateCaches(LookupResult* lookup, | 678 void CallICBase::UpdateCaches(LookupResult* lookup, |
707 State state, | 679 State state, |
708 Code::ExtraICState extra_ic_state, | 680 Code::ExtraICState extra_ic_state, |
709 Handle<Object> object, | 681 Handle<Object> object, |
710 Handle<String> name) { | 682 Handle<String> name) { |
711 // Bail out if we didn't find a result. | 683 // Bail out if we didn't find a result. |
712 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 684 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
713 | 685 |
714 if (lookup->holder() != *object && | 686 if (lookup->holder() != *object && |
715 HasNormalObjectsInPrototypeChain( | 687 HasNormalObjectsInPrototypeChain( |
716 isolate(), lookup, object->GetPrototype())) { | 688 isolate(), lookup, object->GetPrototype())) { |
717 // Suppress optimization for prototype chains with slow properties objects | 689 // Suppress optimization for prototype chains with slow properties objects |
718 // in the middle. | 690 // in the middle. |
719 return; | 691 return; |
720 } | 692 } |
721 | 693 |
722 // Compute the number of arguments. | 694 // Compute the number of arguments. |
723 int argc = target()->arguments_count(); | 695 int argc = target()->arguments_count(); |
724 MaybeObject* maybe_code = NULL; | |
725 bool had_proto_failure = false; | 696 bool had_proto_failure = false; |
697 Handle<Code> code; | |
726 if (state == UNINITIALIZED) { | 698 if (state == UNINITIALIZED) { |
727 // This is the first time we execute this inline cache. | 699 // This is the first time we execute this inline cache. |
728 // Set the target to the pre monomorphic stub to delay | 700 // Set the target to the pre monomorphic stub to delay |
729 // setting the monomorphic state. | 701 // setting the monomorphic state. |
730 maybe_code = | 702 code = isolate()->stub_cache()->ComputeCallPreMonomorphic( |
731 isolate()->stub_cache()->ComputeCallPreMonomorphic(argc, | 703 argc, kind_, extra_ic_state); |
732 kind_, | |
733 extra_ic_state); | |
734 } else if (state == MONOMORPHIC) { | 704 } else if (state == MONOMORPHIC) { |
735 if (kind_ == Code::CALL_IC && | 705 if (kind_ == Code::CALL_IC && |
736 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { | 706 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { |
737 maybe_code = ComputeMonomorphicStub(lookup, | 707 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
738 state, | 708 object, name); |
739 extra_ic_state, | |
740 object, | |
741 name); | |
742 } else if (kind_ == Code::CALL_IC && | 709 } else if (kind_ == Code::CALL_IC && |
743 TryRemoveInvalidPrototypeDependentStub(target(), | 710 TryRemoveInvalidPrototypeDependentStub(target(), |
744 *object, | 711 *object, |
745 *name)) { | 712 *name)) { |
746 had_proto_failure = true; | 713 had_proto_failure = true; |
747 maybe_code = ComputeMonomorphicStub(lookup, | 714 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
748 state, | 715 object, name); |
749 extra_ic_state, | |
750 object, | |
751 name); | |
752 } else { | 716 } else { |
753 maybe_code = | 717 code = isolate()->stub_cache()->ComputeCallMegamorphic( |
754 isolate()->stub_cache()->ComputeCallMegamorphic(argc, | 718 argc, kind_, extra_ic_state); |
755 kind_, | |
756 extra_ic_state); | |
757 } | 719 } |
758 } else { | 720 } else { |
759 maybe_code = ComputeMonomorphicStub(lookup, | 721 code = ComputeMonomorphicStub(lookup, state, extra_ic_state, |
760 state, | 722 object, name); |
761 extra_ic_state, | |
762 object, | |
763 name); | |
764 } | 723 } |
765 | 724 |
766 // If we're unable to compute the stub (not enough memory left), we | 725 // If there's no appropriate stub we simply avoid updating the caches. |
767 // simply avoid updating the caches. | 726 if (code.is_null()) return; |
768 Object* code; | |
769 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | |
770 | 727 |
771 // Patch the call site depending on the state of the cache. | 728 // Patch the call site depending on the state of the cache. |
772 if (state == UNINITIALIZED || | 729 if (state == UNINITIALIZED || |
773 state == PREMONOMORPHIC || | 730 state == PREMONOMORPHIC || |
774 state == MONOMORPHIC || | 731 state == MONOMORPHIC || |
775 state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 732 state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
776 set_target(Code::cast(code)); | 733 set_target(*code); |
777 } else if (state == MEGAMORPHIC) { | 734 } else if (state == MEGAMORPHIC) { |
778 // Cache code holding map should be consistent with | 735 // Cache code holding map should be consistent with |
779 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. | 736 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. |
780 Map* map = JSObject::cast(object->IsJSObject() ? *object : | 737 Handle<JSObject> cache_object = object->IsJSObject() |
781 object->GetPrototype())->map(); | 738 ? Handle<JSObject>::cast(object) |
782 | 739 : Handle<JSObject>(JSObject::cast(object->GetPrototype())); |
783 // Update the stub cache. | 740 // Update the stub cache. |
784 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); | 741 isolate()->stub_cache()->Set(*name, cache_object->map(), *code); |
785 } | 742 } |
786 | 743 |
787 USE(had_proto_failure); | |
788 #ifdef DEBUG | |
789 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; | 744 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; |
790 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", | 745 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", |
791 name, state, target()); | 746 name, state, target()); |
792 #endif | |
793 } | 747 } |
794 | 748 |
795 | 749 |
796 MaybeObject* KeyedCallIC::LoadFunction(State state, | 750 MaybeObject* KeyedCallIC::LoadFunction(State state, |
797 Handle<Object> object, | 751 Handle<Object> object, |
798 Handle<Object> key) { | 752 Handle<Object> key) { |
799 if (key->IsSymbol()) { | 753 if (key->IsSymbol()) { |
800 return CallICBase::LoadFunction(state, | 754 return CallICBase::LoadFunction(state, |
801 Code::kNoExtraICState, | 755 Code::kNoExtraICState, |
802 object, | 756 object, |
803 Handle<String>::cast(key)); | 757 Handle<String>::cast(key)); |
804 } | 758 } |
805 | 759 |
806 if (object->IsUndefined() || object->IsNull()) { | 760 if (object->IsUndefined() || object->IsNull()) { |
807 return TypeError("non_object_property_call", object, key); | 761 return TypeError("non_object_property_call", object, key); |
808 } | 762 } |
809 | 763 |
810 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { | 764 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { |
811 int argc = target()->arguments_count(); | 765 int argc = target()->arguments_count(); |
812 Handle<Map> map = | 766 Handle<Map> map = |
813 isolate()->factory()->non_strict_arguments_elements_map(); | 767 isolate()->factory()->non_strict_arguments_elements_map(); |
814 if (object->IsJSObject() && | 768 if (object->IsJSObject() && |
815 Handle<JSObject>::cast(object)->elements()->map() == *map) { | 769 Handle<JSObject>::cast(object)->elements()->map() == *map) { |
816 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments( | 770 Handle<Code> code = isolate()->stub_cache()->ComputeCallArguments( |
817 argc, Code::KEYED_CALL_IC); | 771 argc, Code::KEYED_CALL_IC); |
818 Code* code = NULL; | 772 set_target(*code); |
819 if (maybe_code->To(&code)) { | 773 TRACE_IC("KeyedCallIC", key, state, target()); |
820 set_target(code); | |
821 #ifdef DEBUG | |
822 TraceIC("KeyedCallIC", key, state, target()); | |
823 #endif | |
824 } | |
825 } else if (!object->IsAccessCheckNeeded()) { | 774 } else if (!object->IsAccessCheckNeeded()) { |
826 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( | 775 Handle<Code> code = isolate()->stub_cache()->ComputeCallMegamorphic( |
827 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); | 776 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
828 Code* code; | 777 set_target(*code); |
829 if (maybe_code->To(&code)) { | 778 TRACE_IC("KeyedCallIC", key, state, target()); |
830 set_target(code); | |
831 #ifdef DEBUG | |
832 TraceIC("KeyedCallIC", key, state, target()); | |
833 #endif | |
834 } | |
835 } | 779 } |
836 } | 780 } |
837 | 781 |
838 Handle<Object> result = GetProperty(object, key); | 782 Handle<Object> result = GetProperty(object, key); |
839 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 783 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
840 | 784 |
841 // Make receiver an object if the callee requires it. Strict mode or builtin | 785 // Make receiver an object if the callee requires it. Strict mode or builtin |
842 // functions do not wrap the receiver, non-strict functions and objects | 786 // functions do not wrap the receiver, non-strict functions and objects |
843 // called as functions do. | 787 // called as functions do. |
844 ReceiverToObjectIfRequired(result, object); | 788 ReceiverToObjectIfRequired(result, object); |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1055 state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 999 state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
1056 set_target(*code); | 1000 set_target(*code); |
1057 } else if (state == MONOMORPHIC) { | 1001 } else if (state == MONOMORPHIC) { |
1058 set_target(*megamorphic_stub()); | 1002 set_target(*megamorphic_stub()); |
1059 } else if (state == MEGAMORPHIC) { | 1003 } else if (state == MEGAMORPHIC) { |
1060 // Cache code holding map should be consistent with | 1004 // Cache code holding map should be consistent with |
1061 // GenerateMonomorphicCacheProbe. | 1005 // GenerateMonomorphicCacheProbe. |
1062 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | 1006 isolate()->stub_cache()->Set(*name, receiver->map(), *code); |
1063 } | 1007 } |
1064 | 1008 |
1065 #ifdef DEBUG | 1009 TRACE_IC("LoadIC", name, state, target()); |
1066 TraceIC("LoadIC", name, state, target()); | |
1067 #endif | |
1068 } | 1010 } |
1069 | 1011 |
1070 | 1012 |
1071 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck( | 1013 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck( |
1072 bool is_js_array, | 1014 bool is_js_array, |
1073 ElementsKind elements_kind) { | 1015 ElementsKind elements_kind) { |
1074 return KeyedLoadElementStub(elements_kind).TryGetCode(); | 1016 return KeyedLoadElementStub(elements_kind).TryGetCode(); |
1075 } | 1017 } |
1076 | 1018 |
1077 | 1019 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1131 if (object->IsString() && | 1073 if (object->IsString() && |
1132 name->Equals(isolate()->heap()->length_symbol())) { | 1074 name->Equals(isolate()->heap()->length_symbol())) { |
1133 Handle<String> string = Handle<String>::cast(object); | 1075 Handle<String> string = Handle<String>::cast(object); |
1134 Object* code = NULL; | 1076 Object* code = NULL; |
1135 { MaybeObject* maybe_code = | 1077 { MaybeObject* maybe_code = |
1136 isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name, | 1078 isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name, |
1137 *string); | 1079 *string); |
1138 if (!maybe_code->ToObject(&code)) return maybe_code; | 1080 if (!maybe_code->ToObject(&code)) return maybe_code; |
1139 } | 1081 } |
1140 set_target(Code::cast(code)); | 1082 set_target(Code::cast(code)); |
1141 #ifdef DEBUG | 1083 TRACE_IC("KeyedLoadIC", name, state, target()); |
1142 TraceIC("KeyedLoadIC", name, state, target()); | |
1143 #endif // DEBUG | |
1144 return Smi::FromInt(string->length()); | 1084 return Smi::FromInt(string->length()); |
1145 } | 1085 } |
1146 | 1086 |
1147 // Use specialized code for getting the length of arrays. | 1087 // Use specialized code for getting the length of arrays. |
1148 if (object->IsJSArray() && | 1088 if (object->IsJSArray() && |
1149 name->Equals(isolate()->heap()->length_symbol())) { | 1089 name->Equals(isolate()->heap()->length_symbol())) { |
1150 Handle<JSArray> array = Handle<JSArray>::cast(object); | 1090 Handle<JSArray> array = Handle<JSArray>::cast(object); |
1151 Object* code; | 1091 Object* code; |
1152 { MaybeObject* maybe_code = | 1092 { MaybeObject* maybe_code = |
1153 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name, | 1093 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name, |
1154 *array); | 1094 *array); |
1155 if (!maybe_code->ToObject(&code)) return maybe_code; | 1095 if (!maybe_code->ToObject(&code)) return maybe_code; |
1156 } | 1096 } |
1157 set_target(Code::cast(code)); | 1097 set_target(Code::cast(code)); |
1158 #ifdef DEBUG | 1098 TRACE_IC("KeyedLoadIC", name, state, target()); |
1159 TraceIC("KeyedLoadIC", name, state, target()); | |
1160 #endif // DEBUG | |
1161 return JSArray::cast(*object)->length(); | 1099 return JSArray::cast(*object)->length(); |
1162 } | 1100 } |
1163 | 1101 |
1164 // Use specialized code for getting prototype of functions. | 1102 // Use specialized code for getting prototype of functions. |
1165 if (object->IsJSFunction() && | 1103 if (object->IsJSFunction() && |
1166 name->Equals(isolate()->heap()->prototype_symbol()) && | 1104 name->Equals(isolate()->heap()->prototype_symbol()) && |
1167 JSFunction::cast(*object)->should_have_prototype()) { | 1105 JSFunction::cast(*object)->should_have_prototype()) { |
1168 Handle<JSFunction> function = Handle<JSFunction>::cast(object); | 1106 Handle<JSFunction> function = Handle<JSFunction>::cast(object); |
1169 Object* code; | 1107 Object* code; |
1170 { MaybeObject* maybe_code = | 1108 { MaybeObject* maybe_code = |
1171 isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( | 1109 isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( |
1172 *name, *function); | 1110 *name, *function); |
1173 if (!maybe_code->ToObject(&code)) return maybe_code; | 1111 if (!maybe_code->ToObject(&code)) return maybe_code; |
1174 } | 1112 } |
1175 set_target(Code::cast(code)); | 1113 set_target(Code::cast(code)); |
1176 #ifdef DEBUG | 1114 TRACE_IC("KeyedLoadIC", name, state, target()); |
1177 TraceIC("KeyedLoadIC", name, state, target()); | |
1178 #endif // DEBUG | |
1179 return Accessors::FunctionGetPrototype(*object, 0); | 1115 return Accessors::FunctionGetPrototype(*object, 0); |
1180 } | 1116 } |
1181 } | 1117 } |
1182 | 1118 |
1183 // Check if the name is trivially convertible to an index and get | 1119 // Check if the name is trivially convertible to an index and get |
1184 // the element or char if so. | 1120 // the element or char if so. |
1185 uint32_t index = 0; | 1121 uint32_t index = 0; |
1186 if (name->AsArrayIndex(&index)) { | 1122 if (name->AsArrayIndex(&index)) { |
1187 HandleScope scope(isolate()); | 1123 HandleScope scope(isolate()); |
1188 // Rewrite to the generic keyed load stub. | 1124 // Rewrite to the generic keyed load stub. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1247 kNonStrictMode, | 1183 kNonStrictMode, |
1248 stub); | 1184 stub); |
1249 stub = maybe_stub->IsFailure() ? | 1185 stub = maybe_stub->IsFailure() ? |
1250 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); | 1186 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); |
1251 } | 1187 } |
1252 } | 1188 } |
1253 } | 1189 } |
1254 if (stub != NULL) set_target(stub); | 1190 if (stub != NULL) set_target(stub); |
1255 } | 1191 } |
1256 | 1192 |
1257 #ifdef DEBUG | 1193 TRACE_IC("KeyedLoadIC", key, state, target()); |
1258 TraceIC("KeyedLoadIC", key, state, target()); | |
1259 #endif // DEBUG | |
1260 | 1194 |
1261 // Get the property. | 1195 // Get the property. |
1262 return Runtime::GetObjectProperty(isolate(), object, key); | 1196 return Runtime::GetObjectProperty(isolate(), object, key); |
1263 } | 1197 } |
1264 | 1198 |
1265 | 1199 |
1266 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, | 1200 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, |
1267 Handle<Object> object, Handle<String> name) { | 1201 Handle<Object> object, Handle<String> name) { |
1268 // Bail out if we didn't find a result. | 1202 // Bail out if we didn't find a result. |
1269 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 1203 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1326 | 1260 |
1327 // Patch the call site depending on the state of the cache. Make | 1261 // Patch the call site depending on the state of the cache. Make |
1328 // sure to always rewrite from monomorphic to megamorphic. | 1262 // sure to always rewrite from monomorphic to megamorphic. |
1329 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); | 1263 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); |
1330 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { | 1264 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { |
1331 set_target(Code::cast(code)); | 1265 set_target(Code::cast(code)); |
1332 } else if (state == MONOMORPHIC) { | 1266 } else if (state == MONOMORPHIC) { |
1333 set_target(megamorphic_stub()); | 1267 set_target(megamorphic_stub()); |
1334 } | 1268 } |
1335 | 1269 |
1336 #ifdef DEBUG | 1270 TRACE_IC("KeyedLoadIC", name, state, target()); |
1337 TraceIC("KeyedLoadIC", name, state, target()); | |
1338 #endif | |
1339 } | 1271 } |
1340 | 1272 |
1341 | 1273 |
1342 static bool StoreICableLookup(LookupResult* lookup) { | 1274 static bool StoreICableLookup(LookupResult* lookup) { |
1343 // Bail out if we didn't find a result. | 1275 // Bail out if we didn't find a result. |
1344 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; | 1276 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; |
1345 | 1277 |
1346 // If the property is read-only, we leave the IC in its current | 1278 // If the property is read-only, we leave the IC in its current |
1347 // state. | 1279 // state. |
1348 if (lookup->IsReadOnly()) return false; | 1280 if (lookup->IsReadOnly()) return false; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1443 | 1375 |
1444 if (receiver->IsJSGlobalProxy()) { | 1376 if (receiver->IsJSGlobalProxy()) { |
1445 // TODO(ulan): find out why we patch this site even with --no-use-ic | 1377 // TODO(ulan): find out why we patch this site even with --no-use-ic |
1446 // Generate a generic stub that goes to the runtime when we see a global | 1378 // Generate a generic stub that goes to the runtime when we see a global |
1447 // proxy as receiver. | 1379 // proxy as receiver. |
1448 Handle<Code> stub = (strict_mode == kStrictMode) | 1380 Handle<Code> stub = (strict_mode == kStrictMode) |
1449 ? global_proxy_stub_strict() | 1381 ? global_proxy_stub_strict() |
1450 : global_proxy_stub(); | 1382 : global_proxy_stub(); |
1451 if (target() != *stub) { | 1383 if (target() != *stub) { |
1452 set_target(*stub); | 1384 set_target(*stub); |
1453 #ifdef DEBUG | 1385 TRACE_IC("StoreIC", name, state, target()); |
1454 TraceIC("StoreIC", name, state, target()); | |
1455 #endif | |
1456 } | 1386 } |
1457 } | 1387 } |
1458 | 1388 |
1459 // Set the property. | 1389 // Set the property. |
1460 return receiver->SetProperty(*name, *value, NONE, strict_mode); | 1390 return receiver->SetProperty(*name, *value, NONE, strict_mode); |
1461 } | 1391 } |
1462 | 1392 |
1463 | 1393 |
1464 void StoreIC::UpdateCaches(LookupResult* lookup, | 1394 void StoreIC::UpdateCaches(LookupResult* lookup, |
1465 State state, | 1395 State state, |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1539 if (target() != *code) { | 1469 if (target() != *code) { |
1540 set_target((strict_mode == kStrictMode) | 1470 set_target((strict_mode == kStrictMode) |
1541 ? megamorphic_stub_strict() | 1471 ? megamorphic_stub_strict() |
1542 : megamorphic_stub()); | 1472 : megamorphic_stub()); |
1543 } | 1473 } |
1544 } else if (state == MEGAMORPHIC) { | 1474 } else if (state == MEGAMORPHIC) { |
1545 // Update the stub cache. | 1475 // Update the stub cache. |
1546 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | 1476 isolate()->stub_cache()->Set(*name, receiver->map(), *code); |
1547 } | 1477 } |
1548 | 1478 |
1549 #ifdef DEBUG | 1479 TRACE_IC("StoreIC", name, state, target()); |
1550 TraceIC("StoreIC", name, state, target()); | |
1551 #endif | |
1552 } | 1480 } |
1553 | 1481 |
1554 | 1482 |
1555 static bool AddOneReceiverMapIfMissing(MapList* receiver_maps, | 1483 static bool AddOneReceiverMapIfMissing(MapList* receiver_maps, |
1556 Map* new_receiver_map) { | 1484 Map* new_receiver_map) { |
1557 for (int current = 0; current < receiver_maps->length(); ++current) { | 1485 for (int current = 0; current < receiver_maps->length(); ++current) { |
1558 if (receiver_maps->at(current) == new_receiver_map) { | 1486 if (receiver_maps->at(current) == new_receiver_map) { |
1559 return false; | 1487 return false; |
1560 } | 1488 } |
1561 } | 1489 } |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1879 strict_mode, | 1807 strict_mode, |
1880 stub); | 1808 stub); |
1881 stub = maybe_stub->IsFailure() ? | 1809 stub = maybe_stub->IsFailure() ? |
1882 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); | 1810 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); |
1883 } | 1811 } |
1884 } | 1812 } |
1885 } | 1813 } |
1886 if (stub != NULL) set_target(stub); | 1814 if (stub != NULL) set_target(stub); |
1887 } | 1815 } |
1888 | 1816 |
1889 #ifdef DEBUG | 1817 TRACE_IC("KeyedStoreIC", key, state, target()); |
1890 TraceIC("KeyedStoreIC", key, state, target()); | |
1891 #endif | |
1892 | 1818 |
1893 // Set the property. | 1819 // Set the property. |
1894 return Runtime::SetObjectProperty( | 1820 return Runtime::SetObjectProperty( |
1895 isolate(), object , key, value, NONE, strict_mode); | 1821 isolate(), object , key, value, NONE, strict_mode); |
1896 } | 1822 } |
1897 | 1823 |
1898 | 1824 |
1899 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, | 1825 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, |
1900 State state, | 1826 State state, |
1901 StrictModeFlag strict_mode, | 1827 StrictModeFlag strict_mode, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1959 // sure to always rewrite from monomorphic to megamorphic. | 1885 // sure to always rewrite from monomorphic to megamorphic. |
1960 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); | 1886 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); |
1961 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { | 1887 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { |
1962 set_target(Code::cast(code)); | 1888 set_target(Code::cast(code)); |
1963 } else if (state == MONOMORPHIC) { | 1889 } else if (state == MONOMORPHIC) { |
1964 set_target((strict_mode == kStrictMode) | 1890 set_target((strict_mode == kStrictMode) |
1965 ? megamorphic_stub_strict() | 1891 ? megamorphic_stub_strict() |
1966 : megamorphic_stub()); | 1892 : megamorphic_stub()); |
1967 } | 1893 } |
1968 | 1894 |
1969 #ifdef DEBUG | 1895 TRACE_IC("KeyedStoreIC", name, state, target()); |
1970 TraceIC("KeyedStoreIC", name, state, target()); | |
1971 #endif | |
1972 } | 1896 } |
1973 | 1897 |
Vyacheslav Egorov (Chromium)
2011/10/20 10:12:23
add empty line
Kevin Millikin (Chromium)
2011/10/20 10:57:08
Done.
| |
1898 #undef TRACE_IC | |
1899 | |
1974 | 1900 |
1975 // ---------------------------------------------------------------------------- | 1901 // ---------------------------------------------------------------------------- |
1976 // Static IC stub generators. | 1902 // Static IC stub generators. |
1977 // | 1903 // |
1978 | 1904 |
1979 // Used from ic-<arch>.cc. | 1905 // Used from ic-<arch>.cc. |
1980 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | 1906 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { |
1981 HandleScope scope(isolate); | 1907 HandleScope scope(isolate); |
1982 ASSERT(args.length() == 2); | 1908 ASSERT(args.length() == 2); |
1983 CallIC ic(isolate); | 1909 CallIC ic(isolate); |
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2586 #undef ADDR | 2512 #undef ADDR |
2587 }; | 2513 }; |
2588 | 2514 |
2589 | 2515 |
2590 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2516 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2591 return IC_utilities[id]; | 2517 return IC_utilities[id]; |
2592 } | 2518 } |
2593 | 2519 |
2594 | 2520 |
2595 } } // namespace v8::internal | 2521 } } // namespace v8::internal |
OLD | NEW |