OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
8 | 8 |
9 #include "src/ic/call-optimization.h" | 9 #include "src/ic/call-optimization.h" |
10 #include "src/ic/ic-compiler.h" | 10 #include "src/ic/handler-compiler.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 #define __ ACCESS_MASM(masm) | 15 #define __ ACCESS_MASM(masm) |
16 | 16 |
| 17 |
| 18 void ElementHandlerCompiler::GenerateLoadDictionaryElement( |
| 19 MacroAssembler* masm) { |
| 20 // ----------- S t a t e ------------- |
| 21 // -- ecx : key |
| 22 // -- edx : receiver |
| 23 // -- esp[0] : return address |
| 24 // ----------------------------------- |
| 25 DCHECK(edx.is(LoadIC::ReceiverRegister())); |
| 26 DCHECK(ecx.is(LoadIC::NameRegister())); |
| 27 Label slow, miss; |
| 28 |
| 29 // This stub is meant to be tail-jumped to, the receiver must already |
| 30 // have been verified by the caller to not be a smi. |
| 31 __ JumpIfNotSmi(ecx, &miss); |
| 32 __ mov(ebx, ecx); |
| 33 __ SmiUntag(ebx); |
| 34 __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); |
| 35 |
| 36 // Push receiver on the stack to free up a register for the dictionary |
| 37 // probing. |
| 38 __ push(edx); |
| 39 __ LoadFromNumberDictionary(&slow, eax, ecx, ebx, edx, edi, eax); |
| 40 // Pop receiver before returning. |
| 41 __ pop(edx); |
| 42 __ ret(0); |
| 43 |
| 44 __ bind(&slow); |
| 45 __ pop(edx); |
| 46 |
| 47 // ----------- S t a t e ------------- |
| 48 // -- ecx : key |
| 49 // -- edx : receiver |
| 50 // -- esp[0] : return address |
| 51 // ----------------------------------- |
| 52 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); |
| 53 |
| 54 __ bind(&miss); |
| 55 // ----------- S t a t e ------------- |
| 56 // -- ecx : key |
| 57 // -- edx : receiver |
| 58 // -- esp[0] : return address |
| 59 // ----------------------------------- |
| 60 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 61 } |
| 62 |
| 63 |
| 64 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
| 65 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
| 66 Handle<JSFunction> getter) { |
| 67 { |
| 68 FrameScope scope(masm, StackFrame::INTERNAL); |
| 69 |
| 70 if (!getter.is_null()) { |
| 71 // Call the JavaScript getter with the receiver on the stack. |
| 72 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
| 73 // Swap in the global receiver. |
| 74 __ mov(receiver, |
| 75 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
| 76 } |
| 77 __ push(receiver); |
| 78 ParameterCount actual(0); |
| 79 ParameterCount expected(getter); |
| 80 __ InvokeFunction(getter, expected, actual, CALL_FUNCTION, |
| 81 NullCallWrapper()); |
| 82 } else { |
| 83 // If we generate a global code snippet for deoptimization only, remember |
| 84 // the place to continue after deoptimization. |
| 85 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); |
| 86 } |
| 87 |
| 88 // Restore context register. |
| 89 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 90 } |
| 91 __ ret(0); |
| 92 } |
| 93 |
| 94 |
17 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( | 95 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
18 MacroAssembler* masm, Label* miss_label, Register receiver, | 96 MacroAssembler* masm, Label* miss_label, Register receiver, |
19 Handle<Name> name, Register scratch0, Register scratch1) { | 97 Handle<Name> name, Register scratch0, Register scratch1) { |
20 DCHECK(name->IsUniqueName()); | 98 DCHECK(name->IsUniqueName()); |
21 DCHECK(!receiver.is(scratch0)); | 99 DCHECK(!receiver.is(scratch0)); |
22 Counters* counters = masm->isolate()->counters(); | 100 Counters* counters = masm->isolate()->counters(); |
23 __ IncrementCounter(counters->negative_lookups(), 1); | 101 __ IncrementCounter(counters->negative_lookups(), 1); |
24 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 102 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
25 | 103 |
26 __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); | 104 __ mov(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 | 154 |
77 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( | 155 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( |
78 MacroAssembler* masm, Register receiver, Register scratch1, | 156 MacroAssembler* masm, Register receiver, Register scratch1, |
79 Register scratch2, Label* miss_label) { | 157 Register scratch2, Label* miss_label) { |
80 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 158 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
81 __ mov(eax, scratch1); | 159 __ mov(eax, scratch1); |
82 __ ret(0); | 160 __ ret(0); |
83 } | 161 } |
84 | 162 |
85 | 163 |
86 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, | |
87 Register holder, Register name, | |
88 Handle<JSObject> holder_obj) { | |
89 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); | |
90 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); | |
91 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); | |
92 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); | |
93 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); | |
94 __ push(name); | |
95 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | |
96 DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); | |
97 Register scratch = name; | |
98 __ mov(scratch, Immediate(interceptor)); | |
99 __ push(scratch); | |
100 __ push(receiver); | |
101 __ push(holder); | |
102 } | |
103 | |
104 | |
105 static void CompileCallLoadPropertyWithInterceptor( | |
106 MacroAssembler* masm, Register receiver, Register holder, Register name, | |
107 Handle<JSObject> holder_obj, IC::UtilityId id) { | |
108 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | |
109 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), | |
110 NamedLoadHandlerCompiler::kInterceptorArgsLength); | |
111 } | |
112 | |
113 | |
114 // Generate call to api function. | 164 // Generate call to api function. |
115 // This function uses push() to generate smaller, faster code than | 165 // This function uses push() to generate smaller, faster code than |
116 // the version above. It is an optimization that should will be removed | 166 // the version above. It is an optimization that should will be removed |
117 // when api call ICs are generated in hydrogen. | 167 // when api call ICs are generated in hydrogen. |
118 void PropertyHandlerCompiler::GenerateFastApiCall( | 168 void PropertyHandlerCompiler::GenerateFastApiCall( |
119 MacroAssembler* masm, const CallOptimization& optimization, | 169 MacroAssembler* masm, const CallOptimization& optimization, |
120 Handle<Map> receiver_map, Register receiver, Register scratch_in, | 170 Handle<Map> receiver_map, Register receiver, Register scratch_in, |
121 bool is_store, int argc, Register* values) { | 171 bool is_store, int argc, Register* values) { |
122 // Copy return value. | 172 // Copy return value. |
123 __ pop(scratch_in); | 173 __ pop(scratch_in); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 __ mov(scratch, Immediate(cell)); | 250 __ mov(scratch, Immediate(cell)); |
201 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), | 251 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), |
202 Immediate(the_hole)); | 252 Immediate(the_hole)); |
203 } else { | 253 } else { |
204 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); | 254 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); |
205 } | 255 } |
206 __ j(not_equal, miss); | 256 __ j(not_equal, miss); |
207 } | 257 } |
208 | 258 |
209 | 259 |
| 260 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
| 261 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
| 262 Handle<JSFunction> setter) { |
| 263 // ----------- S t a t e ------------- |
| 264 // -- esp[0] : return address |
| 265 // ----------------------------------- |
| 266 { |
| 267 FrameScope scope(masm, StackFrame::INTERNAL); |
| 268 |
| 269 // Save value register, so we can restore it later. |
| 270 __ push(value()); |
| 271 |
| 272 if (!setter.is_null()) { |
| 273 // Call the JavaScript setter with receiver and value on the stack. |
| 274 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
| 275 // Swap in the global receiver. |
| 276 __ mov(receiver, |
| 277 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
| 278 } |
| 279 __ push(receiver); |
| 280 __ push(value()); |
| 281 ParameterCount actual(1); |
| 282 ParameterCount expected(setter); |
| 283 __ InvokeFunction(setter, expected, actual, CALL_FUNCTION, |
| 284 NullCallWrapper()); |
| 285 } else { |
| 286 // If we generate a global code snippet for deoptimization only, remember |
| 287 // the place to continue after deoptimization. |
| 288 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); |
| 289 } |
| 290 |
| 291 // We have to return the passed value, not the return value of the setter. |
| 292 __ pop(eax); |
| 293 |
| 294 // Restore context register. |
| 295 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 296 } |
| 297 __ ret(0); |
| 298 } |
| 299 |
| 300 |
| 301 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, |
| 302 Register holder, Register name, |
| 303 Handle<JSObject> holder_obj) { |
| 304 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); |
| 305 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); |
| 306 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); |
| 307 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); |
| 308 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); |
| 309 __ push(name); |
| 310 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
| 311 DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
| 312 Register scratch = name; |
| 313 __ mov(scratch, Immediate(interceptor)); |
| 314 __ push(scratch); |
| 315 __ push(receiver); |
| 316 __ push(holder); |
| 317 } |
| 318 |
| 319 |
| 320 static void CompileCallLoadPropertyWithInterceptor( |
| 321 MacroAssembler* masm, Register receiver, Register holder, Register name, |
| 322 Handle<JSObject> holder_obj, IC::UtilityId id) { |
| 323 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 324 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), |
| 325 NamedLoadHandlerCompiler::kInterceptorArgsLength); |
| 326 } |
| 327 |
| 328 |
210 #undef __ | 329 #undef __ |
211 #define __ ACCESS_MASM(masm()) | 330 #define __ ACCESS_MASM(masm()) |
212 | 331 |
213 | 332 |
214 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, | 333 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, |
215 Handle<Name> name) { | 334 Handle<Name> name) { |
216 if (!label->is_unused()) { | 335 if (!label->is_unused()) { |
217 __ bind(label); | 336 __ bind(label); |
218 __ mov(this->name(), Immediate(name)); | 337 __ mov(this->name(), Immediate(name)); |
219 } | 338 } |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 // Do tail-call to the runtime system. | 792 // Do tail-call to the runtime system. |
674 ExternalReference store_callback_property = | 793 ExternalReference store_callback_property = |
675 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 794 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
676 __ TailCallExternalReference(store_callback_property, 5, 1); | 795 __ TailCallExternalReference(store_callback_property, 5, 1); |
677 | 796 |
678 // Return the generated code. | 797 // Return the generated code. |
679 return GetCode(kind(), Code::FAST, name); | 798 return GetCode(kind(), Code::FAST, name); |
680 } | 799 } |
681 | 800 |
682 | 801 |
683 #undef __ | |
684 #define __ ACCESS_MASM(masm) | |
685 | |
686 | |
687 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( | |
688 MacroAssembler* masm, Handle<HeapType> type, Register receiver, | |
689 Handle<JSFunction> setter) { | |
690 // ----------- S t a t e ------------- | |
691 // -- esp[0] : return address | |
692 // ----------------------------------- | |
693 { | |
694 FrameScope scope(masm, StackFrame::INTERNAL); | |
695 | |
696 // Save value register, so we can restore it later. | |
697 __ push(value()); | |
698 | |
699 if (!setter.is_null()) { | |
700 // Call the JavaScript setter with receiver and value on the stack. | |
701 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | |
702 // Swap in the global receiver. | |
703 __ mov(receiver, | |
704 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | |
705 } | |
706 __ push(receiver); | |
707 __ push(value()); | |
708 ParameterCount actual(1); | |
709 ParameterCount expected(setter); | |
710 __ InvokeFunction(setter, expected, actual, CALL_FUNCTION, | |
711 NullCallWrapper()); | |
712 } else { | |
713 // If we generate a global code snippet for deoptimization only, remember | |
714 // the place to continue after deoptimization. | |
715 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); | |
716 } | |
717 | |
718 // We have to return the passed value, not the return value of the setter. | |
719 __ pop(eax); | |
720 | |
721 // Restore context register. | |
722 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
723 } | |
724 __ ret(0); | |
725 } | |
726 | |
727 | |
728 #undef __ | |
729 #define __ ACCESS_MASM(masm()) | |
730 | |
731 | |
732 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 802 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
733 Handle<Name> name) { | 803 Handle<Name> name) { |
734 __ pop(scratch1()); // remove the return address | 804 __ pop(scratch1()); // remove the return address |
735 __ push(receiver()); | 805 __ push(receiver()); |
736 __ push(this->name()); | 806 __ push(this->name()); |
737 __ push(value()); | 807 __ push(value()); |
738 __ push(scratch1()); // restore return address | 808 __ push(scratch1()); // restore return address |
739 | 809 |
740 // Do tail-call to the runtime system. | 810 // Do tail-call to the runtime system. |
741 ExternalReference store_ic_property = ExternalReference( | 811 ExternalReference store_ic_property = ExternalReference( |
742 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 812 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
743 __ TailCallExternalReference(store_ic_property, 3, 1); | 813 __ TailCallExternalReference(store_ic_property, 3, 1); |
744 | 814 |
745 // Return the generated code. | 815 // Return the generated code. |
746 return GetCode(kind(), Code::FAST, name); | 816 return GetCode(kind(), Code::FAST, name); |
747 } | 817 } |
748 | 818 |
749 | 819 |
750 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( | |
751 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, | |
752 MapHandleList* transitioned_maps) { | |
753 Label miss; | |
754 __ JumpIfSmi(receiver(), &miss, Label::kNear); | |
755 __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); | |
756 for (int i = 0; i < receiver_maps->length(); ++i) { | |
757 __ cmp(scratch1(), receiver_maps->at(i)); | |
758 if (transitioned_maps->at(i).is_null()) { | |
759 __ j(equal, handler_stubs->at(i)); | |
760 } else { | |
761 Label next_map; | |
762 __ j(not_equal, &next_map, Label::kNear); | |
763 __ mov(transition_map(), Immediate(transitioned_maps->at(i))); | |
764 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); | |
765 __ bind(&next_map); | |
766 } | |
767 } | |
768 __ bind(&miss); | |
769 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
770 | |
771 // Return the generated code. | |
772 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | |
773 } | |
774 | |
775 | |
776 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } | 820 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
777 | 821 |
778 | 822 |
779 #undef __ | |
780 #define __ ACCESS_MASM(masm) | |
781 | |
782 | |
783 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( | |
784 MacroAssembler* masm, Handle<HeapType> type, Register receiver, | |
785 Handle<JSFunction> getter) { | |
786 { | |
787 FrameScope scope(masm, StackFrame::INTERNAL); | |
788 | |
789 if (!getter.is_null()) { | |
790 // Call the JavaScript getter with the receiver on the stack. | |
791 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | |
792 // Swap in the global receiver. | |
793 __ mov(receiver, | |
794 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | |
795 } | |
796 __ push(receiver); | |
797 ParameterCount actual(0); | |
798 ParameterCount expected(getter); | |
799 __ InvokeFunction(getter, expected, actual, CALL_FUNCTION, | |
800 NullCallWrapper()); | |
801 } else { | |
802 // If we generate a global code snippet for deoptimization only, remember | |
803 // the place to continue after deoptimization. | |
804 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); | |
805 } | |
806 | |
807 // Restore context register. | |
808 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
809 } | |
810 __ ret(0); | |
811 } | |
812 | |
813 | |
814 #undef __ | |
815 #define __ ACCESS_MASM(masm()) | |
816 | |
817 | |
818 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 823 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
819 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { | 824 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { |
820 Label miss; | 825 Label miss; |
821 | 826 |
822 FrontendHeader(receiver(), name, &miss); | 827 FrontendHeader(receiver(), name, &miss); |
823 // Get the value from the cell. | 828 // Get the value from the cell. |
824 Register result = StoreIC::ValueRegister(); | 829 Register result = StoreIC::ValueRegister(); |
825 if (masm()->serializer_enabled()) { | 830 if (masm()->serializer_enabled()) { |
826 __ mov(result, Immediate(cell)); | 831 __ mov(result, Immediate(cell)); |
827 __ mov(result, FieldOperand(result, PropertyCell::kValueOffset)); | 832 __ mov(result, FieldOperand(result, PropertyCell::kValueOffset)); |
(...skipping 15 matching lines...) Expand all Loading... |
843 // The code above already loads the result into the return register. | 848 // The code above already loads the result into the return register. |
844 __ ret(0); | 849 __ ret(0); |
845 | 850 |
846 FrontendFooter(name, &miss); | 851 FrontendFooter(name, &miss); |
847 | 852 |
848 // Return the generated code. | 853 // Return the generated code. |
849 return GetCode(kind(), Code::NORMAL, name); | 854 return GetCode(kind(), Code::NORMAL, name); |
850 } | 855 } |
851 | 856 |
852 | 857 |
853 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, | |
854 CodeHandleList* handlers, | |
855 Handle<Name> name, | |
856 Code::StubType type, | |
857 IcCheckType check) { | |
858 Label miss; | |
859 | |
860 if (check == PROPERTY && | |
861 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { | |
862 // In case we are compiling an IC for dictionary loads and stores, just | |
863 // check whether the name is unique. | |
864 if (name.is_identical_to(isolate()->factory()->normal_ic_symbol())) { | |
865 __ JumpIfNotUniqueName(this->name(), &miss); | |
866 } else { | |
867 __ cmp(this->name(), Immediate(name)); | |
868 __ j(not_equal, &miss); | |
869 } | |
870 } | |
871 | |
872 Label number_case; | |
873 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | |
874 __ JumpIfSmi(receiver(), smi_target); | |
875 | |
876 // Polymorphic keyed stores may use the map register | |
877 Register map_reg = scratch1(); | |
878 DCHECK(kind() != Code::KEYED_STORE_IC || | |
879 map_reg.is(KeyedStoreIC::MapRegister())); | |
880 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); | |
881 int receiver_count = types->length(); | |
882 int number_of_handled_maps = 0; | |
883 for (int current = 0; current < receiver_count; ++current) { | |
884 Handle<HeapType> type = types->at(current); | |
885 Handle<Map> map = IC::TypeToMap(*type, isolate()); | |
886 if (!map->is_deprecated()) { | |
887 number_of_handled_maps++; | |
888 __ cmp(map_reg, map); | |
889 if (type->Is(HeapType::Number())) { | |
890 DCHECK(!number_case.is_unused()); | |
891 __ bind(&number_case); | |
892 } | |
893 __ j(equal, handlers->at(current)); | |
894 } | |
895 } | |
896 DCHECK(number_of_handled_maps != 0); | |
897 | |
898 __ bind(&miss); | |
899 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
900 | |
901 // Return the generated code. | |
902 InlineCacheState state = | |
903 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | |
904 return GetCode(kind(), type, name, state); | |
905 } | |
906 | |
907 | |
908 #undef __ | |
909 #define __ ACCESS_MASM(masm) | |
910 | |
911 | |
912 void ElementHandlerCompiler::GenerateLoadDictionaryElement( | |
913 MacroAssembler* masm) { | |
914 // ----------- S t a t e ------------- | |
915 // -- ecx : key | |
916 // -- edx : receiver | |
917 // -- esp[0] : return address | |
918 // ----------------------------------- | |
919 DCHECK(edx.is(LoadIC::ReceiverRegister())); | |
920 DCHECK(ecx.is(LoadIC::NameRegister())); | |
921 Label slow, miss; | |
922 | |
923 // This stub is meant to be tail-jumped to, the receiver must already | |
924 // have been verified by the caller to not be a smi. | |
925 __ JumpIfNotSmi(ecx, &miss); | |
926 __ mov(ebx, ecx); | |
927 __ SmiUntag(ebx); | |
928 __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); | |
929 | |
930 // Push receiver on the stack to free up a register for the dictionary | |
931 // probing. | |
932 __ push(edx); | |
933 __ LoadFromNumberDictionary(&slow, eax, ecx, ebx, edx, edi, eax); | |
934 // Pop receiver before returning. | |
935 __ pop(edx); | |
936 __ ret(0); | |
937 | |
938 __ bind(&slow); | |
939 __ pop(edx); | |
940 | |
941 // ----------- S t a t e ------------- | |
942 // -- ecx : key | |
943 // -- edx : receiver | |
944 // -- esp[0] : return address | |
945 // ----------------------------------- | |
946 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); | |
947 | |
948 __ bind(&miss); | |
949 // ----------- S t a t e ------------- | |
950 // -- ecx : key | |
951 // -- edx : receiver | |
952 // -- esp[0] : return address | |
953 // ----------------------------------- | |
954 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | |
955 } | |
956 | |
957 | |
958 void PropertyICCompiler::GenerateRuntimeSetProperty(MacroAssembler* masm, | |
959 StrictMode strict_mode) { | |
960 // Return address is on the stack. | |
961 DCHECK(!ebx.is(StoreIC::ReceiverRegister()) && | |
962 !ebx.is(StoreIC::NameRegister()) && !ebx.is(StoreIC::ValueRegister())); | |
963 __ pop(ebx); | |
964 __ push(StoreIC::ReceiverRegister()); | |
965 __ push(StoreIC::NameRegister()); | |
966 __ push(StoreIC::ValueRegister()); | |
967 __ push(Immediate(Smi::FromInt(strict_mode))); | |
968 __ push(ebx); // return address | |
969 | |
970 // Do tail-call to runtime routine. | |
971 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); | |
972 } | |
973 | |
974 | |
975 #undef __ | 858 #undef __ |
976 } | 859 } |
977 } // namespace v8::internal | 860 } // namespace v8::internal |
978 | 861 |
979 #endif // V8_TARGET_ARCH_IA32 | 862 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |