| 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_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 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 PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( | 17 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
| 19 MacroAssembler* masm, Label* miss_label, Register receiver, | 18 MacroAssembler* masm, Label* miss_label, Register receiver, |
| 20 Handle<Name> name, Register scratch0, Register scratch1) { | 19 Handle<Name> name, Register scratch0, Register scratch1) { |
| 21 DCHECK(name->IsUniqueName()); | 20 DCHECK(name->IsUniqueName()); |
| 22 DCHECK(!receiver.is(scratch0)); | 21 DCHECK(!receiver.is(scratch0)); |
| 23 Counters* counters = masm->isolate()->counters(); | 22 Counters* counters = masm->isolate()->counters(); |
| 24 __ IncrementCounter(counters->negative_lookups(), 1); | 23 __ IncrementCounter(counters->negative_lookups(), 1); |
| 25 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 24 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| 26 | 25 |
| 27 __ movp(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); | 26 __ movp(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 Register scratch, Label* miss) { | 191 Register scratch, Label* miss) { |
| 193 Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name); | 192 Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |
| 194 DCHECK(cell->value()->IsTheHole()); | 193 DCHECK(cell->value()->IsTheHole()); |
| 195 __ Move(scratch, cell); | 194 __ Move(scratch, cell); |
| 196 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), | 195 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), |
| 197 masm->isolate()->factory()->the_hole_value()); | 196 masm->isolate()->factory()->the_hole_value()); |
| 198 __ j(not_equal, miss); | 197 __ j(not_equal, miss); |
| 199 } | 198 } |
| 200 | 199 |
| 201 | 200 |
| 201 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
| 202 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
| 203 Handle<JSFunction> setter) { |
| 204 // ----------- S t a t e ------------- |
| 205 // -- rsp[0] : return address |
| 206 // ----------------------------------- |
| 207 { |
| 208 FrameScope scope(masm, StackFrame::INTERNAL); |
| 209 |
| 210 // Save value register, so we can restore it later. |
| 211 __ Push(value()); |
| 212 |
| 213 if (!setter.is_null()) { |
| 214 // Call the JavaScript setter with receiver and value on the stack. |
| 215 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
| 216 // Swap in the global receiver. |
| 217 __ movp(receiver, |
| 218 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
| 219 } |
| 220 __ Push(receiver); |
| 221 __ Push(value()); |
| 222 ParameterCount actual(1); |
| 223 ParameterCount expected(setter); |
| 224 __ InvokeFunction(setter, expected, actual, CALL_FUNCTION, |
| 225 NullCallWrapper()); |
| 226 } else { |
| 227 // If we generate a global code snippet for deoptimization only, remember |
| 228 // the place to continue after deoptimization. |
| 229 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); |
| 230 } |
| 231 |
| 232 // We have to return the passed value, not the return value of the setter. |
| 233 __ Pop(rax); |
| 234 |
| 235 // Restore context register. |
| 236 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 237 } |
| 238 __ ret(0); |
| 239 } |
| 240 |
| 241 |
| 242 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
| 243 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
| 244 Handle<JSFunction> getter) { |
| 245 // ----------- S t a t e ------------- |
| 246 // -- rax : receiver |
| 247 // -- rcx : name |
| 248 // -- rsp[0] : return address |
| 249 // ----------------------------------- |
| 250 { |
| 251 FrameScope scope(masm, StackFrame::INTERNAL); |
| 252 |
| 253 if (!getter.is_null()) { |
| 254 // Call the JavaScript getter with the receiver on the stack. |
| 255 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
| 256 // Swap in the global receiver. |
| 257 __ movp(receiver, |
| 258 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
| 259 } |
| 260 __ Push(receiver); |
| 261 ParameterCount actual(0); |
| 262 ParameterCount expected(getter); |
| 263 __ InvokeFunction(getter, expected, actual, CALL_FUNCTION, |
| 264 NullCallWrapper()); |
| 265 } else { |
| 266 // If we generate a global code snippet for deoptimization only, remember |
| 267 // the place to continue after deoptimization. |
| 268 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); |
| 269 } |
| 270 |
| 271 // Restore context register. |
| 272 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 273 } |
| 274 __ ret(0); |
| 275 } |
| 276 |
| 277 |
| 278 void ElementHandlerCompiler::GenerateLoadDictionaryElement( |
| 279 MacroAssembler* masm) { |
| 280 // ----------- S t a t e ------------- |
| 281 // -- rcx : key |
| 282 // -- rdx : receiver |
| 283 // -- rsp[0] : return address |
| 284 // ----------------------------------- |
| 285 DCHECK(rdx.is(LoadIC::ReceiverRegister())); |
| 286 DCHECK(rcx.is(LoadIC::NameRegister())); |
| 287 Label slow, miss; |
| 288 |
| 289 // This stub is meant to be tail-jumped to, the receiver must already |
| 290 // have been verified by the caller to not be a smi. |
| 291 |
| 292 __ JumpIfNotSmi(rcx, &miss); |
| 293 __ SmiToInteger32(rbx, rcx); |
| 294 __ movp(rax, FieldOperand(rdx, JSObject::kElementsOffset)); |
| 295 |
| 296 // Check whether the elements is a number dictionary. |
| 297 // rdx: receiver |
| 298 // rcx: key |
| 299 // rbx: key as untagged int32 |
| 300 // rax: elements |
| 301 __ LoadFromNumberDictionary(&slow, rax, rcx, rbx, r9, rdi, rax); |
| 302 __ ret(0); |
| 303 |
| 304 __ bind(&slow); |
| 305 // ----------- S t a t e ------------- |
| 306 // -- rcx : key |
| 307 // -- rdx : receiver |
| 308 // -- rsp[0] : return address |
| 309 // ----------------------------------- |
| 310 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); |
| 311 |
| 312 __ bind(&miss); |
| 313 // ----------- S t a t e ------------- |
| 314 // -- rcx : key |
| 315 // -- rdx : receiver |
| 316 // -- rsp[0] : return address |
| 317 // ----------------------------------- |
| 318 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 319 } |
| 320 |
| 321 |
| 202 #undef __ | 322 #undef __ |
| 203 #define __ ACCESS_MASM((masm())) | 323 #define __ ACCESS_MASM((masm())) |
| 204 | 324 |
| 205 | 325 |
| 206 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, | 326 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, |
| 207 Handle<Name> name) { | 327 Handle<Name> name) { |
| 208 if (!label->is_unused()) { | 328 if (!label->is_unused()) { |
| 209 __ bind(label); | 329 __ bind(label); |
| 210 __ Move(this->name(), name); | 330 __ Move(this->name(), name); |
| 211 } | 331 } |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 // Do tail-call to the runtime system. | 777 // Do tail-call to the runtime system. |
| 658 ExternalReference store_callback_property = | 778 ExternalReference store_callback_property = |
| 659 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 779 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 660 __ TailCallExternalReference(store_callback_property, 5, 1); | 780 __ TailCallExternalReference(store_callback_property, 5, 1); |
| 661 | 781 |
| 662 // Return the generated code. | 782 // Return the generated code. |
| 663 return GetCode(kind(), Code::FAST, name); | 783 return GetCode(kind(), Code::FAST, name); |
| 664 } | 784 } |
| 665 | 785 |
| 666 | 786 |
| 667 #undef __ | |
| 668 #define __ ACCESS_MASM(masm) | |
| 669 | |
| 670 | |
| 671 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( | |
| 672 MacroAssembler* masm, Handle<HeapType> type, Register receiver, | |
| 673 Handle<JSFunction> setter) { | |
| 674 // ----------- S t a t e ------------- | |
| 675 // -- rsp[0] : return address | |
| 676 // ----------------------------------- | |
| 677 { | |
| 678 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 679 | |
| 680 // Save value register, so we can restore it later. | |
| 681 __ Push(value()); | |
| 682 | |
| 683 if (!setter.is_null()) { | |
| 684 // Call the JavaScript setter with receiver and value on the stack. | |
| 685 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | |
| 686 // Swap in the global receiver. | |
| 687 __ movp(receiver, | |
| 688 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | |
| 689 } | |
| 690 __ Push(receiver); | |
| 691 __ Push(value()); | |
| 692 ParameterCount actual(1); | |
| 693 ParameterCount expected(setter); | |
| 694 __ InvokeFunction(setter, expected, actual, CALL_FUNCTION, | |
| 695 NullCallWrapper()); | |
| 696 } else { | |
| 697 // If we generate a global code snippet for deoptimization only, remember | |
| 698 // the place to continue after deoptimization. | |
| 699 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); | |
| 700 } | |
| 701 | |
| 702 // We have to return the passed value, not the return value of the setter. | |
| 703 __ Pop(rax); | |
| 704 | |
| 705 // Restore context register. | |
| 706 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 707 } | |
| 708 __ ret(0); | |
| 709 } | |
| 710 | |
| 711 | |
| 712 #undef __ | |
| 713 #define __ ACCESS_MASM(masm()) | |
| 714 | |
| 715 | |
| 716 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 787 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
| 717 Handle<Name> name) { | 788 Handle<Name> name) { |
| 718 __ PopReturnAddressTo(scratch1()); | 789 __ PopReturnAddressTo(scratch1()); |
| 719 __ Push(receiver()); | 790 __ Push(receiver()); |
| 720 __ Push(this->name()); | 791 __ Push(this->name()); |
| 721 __ Push(value()); | 792 __ Push(value()); |
| 722 __ PushReturnAddressFrom(scratch1()); | 793 __ PushReturnAddressFrom(scratch1()); |
| 723 | 794 |
| 724 // Do tail-call to the runtime system. | 795 // Do tail-call to the runtime system. |
| 725 ExternalReference store_ic_property = ExternalReference( | 796 ExternalReference store_ic_property = ExternalReference( |
| 726 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); | 797 IC_Utility(IC::kStorePropertyWithInterceptor), isolate()); |
| 727 __ TailCallExternalReference(store_ic_property, 3, 1); | 798 __ TailCallExternalReference(store_ic_property, 3, 1); |
| 728 | 799 |
| 729 // Return the generated code. | 800 // Return the generated code. |
| 730 return GetCode(kind(), Code::FAST, name); | 801 return GetCode(kind(), Code::FAST, name); |
| 731 } | 802 } |
| 732 | 803 |
| 733 | 804 |
| 734 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( | |
| 735 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, | |
| 736 MapHandleList* transitioned_maps) { | |
| 737 Label miss; | |
| 738 __ JumpIfSmi(receiver(), &miss, Label::kNear); | |
| 739 | |
| 740 __ movp(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); | |
| 741 int receiver_count = receiver_maps->length(); | |
| 742 for (int i = 0; i < receiver_count; ++i) { | |
| 743 // Check map and tail call if there's a match | |
| 744 __ Cmp(scratch1(), receiver_maps->at(i)); | |
| 745 if (transitioned_maps->at(i).is_null()) { | |
| 746 __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET); | |
| 747 } else { | |
| 748 Label next_map; | |
| 749 __ j(not_equal, &next_map, Label::kNear); | |
| 750 __ Move(transition_map(), transitioned_maps->at(i), | |
| 751 RelocInfo::EMBEDDED_OBJECT); | |
| 752 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); | |
| 753 __ bind(&next_map); | |
| 754 } | |
| 755 } | |
| 756 | |
| 757 __ bind(&miss); | |
| 758 | |
| 759 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
| 760 | |
| 761 // Return the generated code. | |
| 762 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | |
| 763 } | |
| 764 | |
| 765 | |
| 766 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } | 805 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
| 767 | 806 |
| 768 | 807 |
| 769 #undef __ | |
| 770 #define __ ACCESS_MASM(masm) | |
| 771 | |
| 772 | |
| 773 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( | |
| 774 MacroAssembler* masm, Handle<HeapType> type, Register receiver, | |
| 775 Handle<JSFunction> getter) { | |
| 776 // ----------- S t a t e ------------- | |
| 777 // -- rax : receiver | |
| 778 // -- rcx : name | |
| 779 // -- rsp[0] : return address | |
| 780 // ----------------------------------- | |
| 781 { | |
| 782 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 783 | |
| 784 if (!getter.is_null()) { | |
| 785 // Call the JavaScript getter with the receiver on the stack. | |
| 786 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | |
| 787 // Swap in the global receiver. | |
| 788 __ movp(receiver, | |
| 789 FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | |
| 790 } | |
| 791 __ Push(receiver); | |
| 792 ParameterCount actual(0); | |
| 793 ParameterCount expected(getter); | |
| 794 __ InvokeFunction(getter, expected, actual, CALL_FUNCTION, | |
| 795 NullCallWrapper()); | |
| 796 } else { | |
| 797 // If we generate a global code snippet for deoptimization only, remember | |
| 798 // the place to continue after deoptimization. | |
| 799 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); | |
| 800 } | |
| 801 | |
| 802 // Restore context register. | |
| 803 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 804 } | |
| 805 __ ret(0); | |
| 806 } | |
| 807 | |
| 808 | |
| 809 #undef __ | |
| 810 #define __ ACCESS_MASM(masm()) | |
| 811 | |
| 812 | |
| 813 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 808 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
| 814 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { | 809 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { |
| 815 Label miss; | 810 Label miss; |
| 816 FrontendHeader(receiver(), name, &miss); | 811 FrontendHeader(receiver(), name, &miss); |
| 817 | 812 |
| 818 // Get the value from the cell. | 813 // Get the value from the cell. |
| 819 Register result = StoreIC::ValueRegister(); | 814 Register result = StoreIC::ValueRegister(); |
| 820 __ Move(result, cell); | 815 __ Move(result, cell); |
| 821 __ movp(result, FieldOperand(result, PropertyCell::kValueOffset)); | 816 __ movp(result, FieldOperand(result, PropertyCell::kValueOffset)); |
| 822 | 817 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 833 __ IncrementCounter(counters->named_load_global_stub(), 1); | 828 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 834 __ ret(0); | 829 __ ret(0); |
| 835 | 830 |
| 836 FrontendFooter(name, &miss); | 831 FrontendFooter(name, &miss); |
| 837 | 832 |
| 838 // Return the generated code. | 833 // Return the generated code. |
| 839 return GetCode(kind(), Code::NORMAL, name); | 834 return GetCode(kind(), Code::NORMAL, name); |
| 840 } | 835 } |
| 841 | 836 |
| 842 | 837 |
| 843 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, | |
| 844 CodeHandleList* handlers, | |
| 845 Handle<Name> name, | |
| 846 Code::StubType type, | |
| 847 IcCheckType check) { | |
| 848 Label miss; | |
| 849 | |
| 850 if (check == PROPERTY && | |
| 851 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { | |
| 852 // In case we are compiling an IC for dictionary loads and stores, just | |
| 853 // check whether the name is unique. | |
| 854 if (name.is_identical_to(isolate()->factory()->normal_ic_symbol())) { | |
| 855 __ JumpIfNotUniqueName(this->name(), &miss); | |
| 856 } else { | |
| 857 __ Cmp(this->name(), name); | |
| 858 __ j(not_equal, &miss); | |
| 859 } | |
| 860 } | |
| 861 | |
| 862 Label number_case; | |
| 863 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | |
| 864 __ JumpIfSmi(receiver(), smi_target); | |
| 865 | |
| 866 // Polymorphic keyed stores may use the map register | |
| 867 Register map_reg = scratch1(); | |
| 868 DCHECK(kind() != Code::KEYED_STORE_IC || | |
| 869 map_reg.is(KeyedStoreIC::MapRegister())); | |
| 870 __ movp(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); | |
| 871 int receiver_count = types->length(); | |
| 872 int number_of_handled_maps = 0; | |
| 873 for (int current = 0; current < receiver_count; ++current) { | |
| 874 Handle<HeapType> type = types->at(current); | |
| 875 Handle<Map> map = IC::TypeToMap(*type, isolate()); | |
| 876 if (!map->is_deprecated()) { | |
| 877 number_of_handled_maps++; | |
| 878 // Check map and tail call if there's a match | |
| 879 __ Cmp(map_reg, map); | |
| 880 if (type->Is(HeapType::Number())) { | |
| 881 DCHECK(!number_case.is_unused()); | |
| 882 __ bind(&number_case); | |
| 883 } | |
| 884 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET); | |
| 885 } | |
| 886 } | |
| 887 DCHECK(number_of_handled_maps > 0); | |
| 888 | |
| 889 __ bind(&miss); | |
| 890 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
| 891 | |
| 892 // Return the generated code. | |
| 893 InlineCacheState state = | |
| 894 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | |
| 895 return GetCode(kind(), type, name, state); | |
| 896 } | |
| 897 | |
| 898 | |
| 899 #undef __ | |
| 900 #define __ ACCESS_MASM(masm) | |
| 901 | |
| 902 | |
| 903 void ElementHandlerCompiler::GenerateLoadDictionaryElement( | |
| 904 MacroAssembler* masm) { | |
| 905 // ----------- S t a t e ------------- | |
| 906 // -- rcx : key | |
| 907 // -- rdx : receiver | |
| 908 // -- rsp[0] : return address | |
| 909 // ----------------------------------- | |
| 910 DCHECK(rdx.is(LoadIC::ReceiverRegister())); | |
| 911 DCHECK(rcx.is(LoadIC::NameRegister())); | |
| 912 Label slow, miss; | |
| 913 | |
| 914 // This stub is meant to be tail-jumped to, the receiver must already | |
| 915 // have been verified by the caller to not be a smi. | |
| 916 | |
| 917 __ JumpIfNotSmi(rcx, &miss); | |
| 918 __ SmiToInteger32(rbx, rcx); | |
| 919 __ movp(rax, FieldOperand(rdx, JSObject::kElementsOffset)); | |
| 920 | |
| 921 // Check whether the elements is a number dictionary. | |
| 922 // rdx: receiver | |
| 923 // rcx: key | |
| 924 // rbx: key as untagged int32 | |
| 925 // rax: elements | |
| 926 __ LoadFromNumberDictionary(&slow, rax, rcx, rbx, r9, rdi, rax); | |
| 927 __ ret(0); | |
| 928 | |
| 929 __ bind(&slow); | |
| 930 // ----------- S t a t e ------------- | |
| 931 // -- rcx : key | |
| 932 // -- rdx : receiver | |
| 933 // -- rsp[0] : return address | |
| 934 // ----------------------------------- | |
| 935 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); | |
| 936 | |
| 937 __ bind(&miss); | |
| 938 // ----------- S t a t e ------------- | |
| 939 // -- rcx : key | |
| 940 // -- rdx : receiver | |
| 941 // -- rsp[0] : return address | |
| 942 // ----------------------------------- | |
| 943 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | |
| 944 } | |
| 945 | |
| 946 | |
| 947 void PropertyICCompiler::GenerateRuntimeSetProperty(MacroAssembler* masm, | |
| 948 StrictMode strict_mode) { | |
| 949 // Return address is on the stack. | |
| 950 DCHECK(!rbx.is(StoreIC::ReceiverRegister()) && | |
| 951 !rbx.is(StoreIC::NameRegister()) && !rbx.is(StoreIC::ValueRegister())); | |
| 952 | |
| 953 __ PopReturnAddressTo(rbx); | |
| 954 __ Push(StoreIC::ReceiverRegister()); | |
| 955 __ Push(StoreIC::NameRegister()); | |
| 956 __ Push(StoreIC::ValueRegister()); | |
| 957 __ Push(Smi::FromInt(strict_mode)); | |
| 958 __ PushReturnAddressFrom(rbx); | |
| 959 | |
| 960 // Do tail-call to runtime routine. | |
| 961 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); | |
| 962 } | |
| 963 | |
| 964 | |
| 965 #undef __ | 838 #undef __ |
| 966 } | 839 } |
| 967 } // namespace v8::internal | 840 } // namespace v8::internal |
| 968 | 841 |
| 969 #endif // V8_TARGET_ARCH_X64 | 842 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |