| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 | 250 |
| 251 __ bind(&unique); | 251 __ bind(&unique); |
| 252 } | 252 } |
| 253 | 253 |
| 254 | 254 |
| 255 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 255 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
| 256 // The return address is on the stack. | 256 // The return address is on the stack. |
| 257 Label slow, check_name, index_smi, index_name, property_array_property; | 257 Label slow, check_name, index_smi, index_name, property_array_property; |
| 258 Label probe_dictionary, check_number_dictionary; | 258 Label probe_dictionary, check_number_dictionary; |
| 259 | 259 |
| 260 Register receiver = ReceiverRegister(); | 260 Register receiver = LoadConvention::ReceiverRegister(); |
| 261 Register key = NameRegister(); | 261 Register key = LoadConvention::NameRegister(); |
| 262 DCHECK(receiver.is(rdx)); | 262 DCHECK(receiver.is(rdx)); |
| 263 DCHECK(key.is(rcx)); | 263 DCHECK(key.is(rcx)); |
| 264 | 264 |
| 265 // Check that the key is a smi. | 265 // Check that the key is a smi. |
| 266 __ JumpIfNotSmi(key, &check_name); | 266 __ JumpIfNotSmi(key, &check_name); |
| 267 __ bind(&index_smi); | 267 __ bind(&index_smi); |
| 268 // Now the key is known to be a smi. This place is also jumped to from below | 268 // Now the key is known to be a smi. This place is also jumped to from below |
| 269 // where a numeric string is converted to a smi. | 269 // where a numeric string is converted to a smi. |
| 270 | 270 |
| 271 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, | 271 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 __ bind(&index_name); | 400 __ bind(&index_name); |
| 401 __ IndexFromHash(rbx, key); | 401 __ IndexFromHash(rbx, key); |
| 402 __ jmp(&index_smi); | 402 __ jmp(&index_smi); |
| 403 } | 403 } |
| 404 | 404 |
| 405 | 405 |
| 406 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 406 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
| 407 // Return address is on the stack. | 407 // Return address is on the stack. |
| 408 Label miss; | 408 Label miss; |
| 409 | 409 |
| 410 Register receiver = ReceiverRegister(); | 410 Register receiver = LoadConvention::ReceiverRegister(); |
| 411 Register index = NameRegister(); | 411 Register index = LoadConvention::NameRegister(); |
| 412 Register scratch = rbx; | 412 Register scratch = rbx; |
| 413 Register result = rax; | 413 Register result = rax; |
| 414 DCHECK(!scratch.is(receiver) && !scratch.is(index)); | 414 DCHECK(!scratch.is(receiver) && !scratch.is(index)); |
| 415 | 415 |
| 416 StringCharAtGenerator char_at_generator(receiver, index, scratch, result, | 416 StringCharAtGenerator char_at_generator(receiver, index, scratch, result, |
| 417 &miss, // When not a string. | 417 &miss, // When not a string. |
| 418 &miss, // When not a number. | 418 &miss, // When not a number. |
| 419 &miss, // When index out of range. | 419 &miss, // When index out of range. |
| 420 STRING_INDEX_IS_ARRAY_INDEX); | 420 STRING_INDEX_IS_ARRAY_INDEX); |
| 421 char_at_generator.GenerateFast(masm); | 421 char_at_generator.GenerateFast(masm); |
| 422 __ ret(0); | 422 __ ret(0); |
| 423 | 423 |
| 424 StubRuntimeCallHelper call_helper; | 424 StubRuntimeCallHelper call_helper; |
| 425 char_at_generator.GenerateSlow(masm, call_helper); | 425 char_at_generator.GenerateSlow(masm, call_helper); |
| 426 | 426 |
| 427 __ bind(&miss); | 427 __ bind(&miss); |
| 428 GenerateMiss(masm); | 428 GenerateMiss(masm); |
| 429 } | 429 } |
| 430 | 430 |
| 431 | 431 |
| 432 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 432 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
| 433 // Return address is on the stack. | 433 // Return address is on the stack. |
| 434 Label slow; | 434 Label slow; |
| 435 | 435 |
| 436 Register receiver = ReceiverRegister(); | 436 Register receiver = LoadConvention::ReceiverRegister(); |
| 437 Register key = NameRegister(); | 437 Register key = LoadConvention::NameRegister(); |
| 438 Register scratch = rax; | 438 Register scratch = rax; |
| 439 DCHECK(!scratch.is(receiver) && !scratch.is(key)); | 439 DCHECK(!scratch.is(receiver) && !scratch.is(key)); |
| 440 | 440 |
| 441 // Check that the receiver isn't a smi. | 441 // Check that the receiver isn't a smi. |
| 442 __ JumpIfSmi(receiver, &slow); | 442 __ JumpIfSmi(receiver, &slow); |
| 443 | 443 |
| 444 // Check that the key is an array index, that is Uint32. | 444 // Check that the key is an array index, that is Uint32. |
| 445 STATIC_ASSERT(kSmiValueSize <= 32); | 445 STATIC_ASSERT(kSmiValueSize <= 32); |
| 446 __ JumpUnlessNonNegativeSmi(key, &slow); | 446 __ JumpUnlessNonNegativeSmi(key, &slow); |
| 447 | 447 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 471 GenerateMiss(masm); | 471 GenerateMiss(masm); |
| 472 } | 472 } |
| 473 | 473 |
| 474 | 474 |
| 475 static void KeyedStoreGenerateGenericHelper( | 475 static void KeyedStoreGenerateGenericHelper( |
| 476 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, | 476 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, |
| 477 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length) { | 477 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length) { |
| 478 Label transition_smi_elements; | 478 Label transition_smi_elements; |
| 479 Label finish_object_store, non_double_value, transition_double_elements; | 479 Label finish_object_store, non_double_value, transition_double_elements; |
| 480 Label fast_double_without_map_check; | 480 Label fast_double_without_map_check; |
| 481 Register receiver = KeyedStoreIC::ReceiverRegister(); | 481 Register receiver = StoreConvention::ReceiverRegister(); |
| 482 Register key = KeyedStoreIC::NameRegister(); | 482 Register key = StoreConvention::NameRegister(); |
| 483 Register value = KeyedStoreIC::ValueRegister(); | 483 Register value = StoreConvention::ValueRegister(); |
| 484 DCHECK(receiver.is(rdx)); | 484 DCHECK(receiver.is(rdx)); |
| 485 DCHECK(key.is(rcx)); | 485 DCHECK(key.is(rcx)); |
| 486 DCHECK(value.is(rax)); | 486 DCHECK(value.is(rax)); |
| 487 // Fast case: Do the store, could be either Object or double. | 487 // Fast case: Do the store, could be either Object or double. |
| 488 __ bind(fast_object); | 488 __ bind(fast_object); |
| 489 // rbx: receiver's elements array (a FixedArray) | 489 // rbx: receiver's elements array (a FixedArray) |
| 490 // receiver is a JSArray. | 490 // receiver is a JSArray. |
| 491 // r9: map of receiver | 491 // r9: map of receiver |
| 492 if (check_map == kCheckMap) { | 492 if (check_map == kCheckMap) { |
| 493 __ movp(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); | 493 __ movp(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 __ jmp(&finish_object_store); | 608 __ jmp(&finish_object_store); |
| 609 } | 609 } |
| 610 | 610 |
| 611 | 611 |
| 612 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, | 612 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
| 613 StrictMode strict_mode) { | 613 StrictMode strict_mode) { |
| 614 // Return address is on the stack. | 614 // Return address is on the stack. |
| 615 Label slow, slow_with_tagged_index, fast_object, fast_object_grow; | 615 Label slow, slow_with_tagged_index, fast_object, fast_object_grow; |
| 616 Label fast_double, fast_double_grow; | 616 Label fast_double, fast_double_grow; |
| 617 Label array, extra, check_if_double_array; | 617 Label array, extra, check_if_double_array; |
| 618 Register receiver = ReceiverRegister(); | 618 Register receiver = StoreConvention::ReceiverRegister(); |
| 619 Register key = NameRegister(); | 619 Register key = StoreConvention::NameRegister(); |
| 620 DCHECK(receiver.is(rdx)); | 620 DCHECK(receiver.is(rdx)); |
| 621 DCHECK(key.is(rcx)); | 621 DCHECK(key.is(rcx)); |
| 622 | 622 |
| 623 // Check that the object isn't a smi. | 623 // Check that the object isn't a smi. |
| 624 __ JumpIfSmi(receiver, &slow_with_tagged_index); | 624 __ JumpIfSmi(receiver, &slow_with_tagged_index); |
| 625 // Get the map from the receiver. | 625 // Get the map from the receiver. |
| 626 __ movp(r9, FieldOperand(receiver, HeapObject::kMapOffset)); | 626 __ movp(r9, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 627 // Check that the receiver does not require access checks and is not observed. | 627 // Check that the receiver does not require access checks and is not observed. |
| 628 // The generic stub does not perform map checks or handle observed objects. | 628 // The generic stub does not perform map checks or handle observed objects. |
| 629 __ testb(FieldOperand(r9, Map::kBitFieldOffset), | 629 __ testb(FieldOperand(r9, Map::kBitFieldOffset), |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 __ cmpp(key, scratch); | 760 __ cmpp(key, scratch); |
| 761 __ j(greater_equal, slow_case); | 761 __ j(greater_equal, slow_case); |
| 762 __ SmiToInteger64(scratch, key); | 762 __ SmiToInteger64(scratch, key); |
| 763 return FieldOperand(backing_store, scratch, times_pointer_size, | 763 return FieldOperand(backing_store, scratch, times_pointer_size, |
| 764 FixedArray::kHeaderSize); | 764 FixedArray::kHeaderSize); |
| 765 } | 765 } |
| 766 | 766 |
| 767 | 767 |
| 768 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { | 768 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { |
| 769 // The return address is on the stack. | 769 // The return address is on the stack. |
| 770 Register receiver = ReceiverRegister(); | 770 Register receiver = LoadConvention::ReceiverRegister(); |
| 771 Register key = NameRegister(); | 771 Register key = LoadConvention::NameRegister(); |
| 772 DCHECK(receiver.is(rdx)); | 772 DCHECK(receiver.is(rdx)); |
| 773 DCHECK(key.is(rcx)); | 773 DCHECK(key.is(rcx)); |
| 774 | 774 |
| 775 Label slow, notin; | 775 Label slow, notin; |
| 776 Operand mapped_location = GenerateMappedArgumentsLookup( | 776 Operand mapped_location = GenerateMappedArgumentsLookup( |
| 777 masm, receiver, key, rbx, rax, rdi, ¬in, &slow); | 777 masm, receiver, key, rbx, rax, rdi, ¬in, &slow); |
| 778 __ movp(rax, mapped_location); | 778 __ movp(rax, mapped_location); |
| 779 __ Ret(); | 779 __ Ret(); |
| 780 __ bind(¬in); | 780 __ bind(¬in); |
| 781 // The unmapped lookup expects that the parameter map is in rbx. | 781 // The unmapped lookup expects that the parameter map is in rbx. |
| 782 Operand unmapped_location = | 782 Operand unmapped_location = |
| 783 GenerateUnmappedArgumentsLookup(masm, key, rbx, rax, &slow); | 783 GenerateUnmappedArgumentsLookup(masm, key, rbx, rax, &slow); |
| 784 __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex); | 784 __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex); |
| 785 __ j(equal, &slow); | 785 __ j(equal, &slow); |
| 786 __ movp(rax, unmapped_location); | 786 __ movp(rax, unmapped_location); |
| 787 __ Ret(); | 787 __ Ret(); |
| 788 __ bind(&slow); | 788 __ bind(&slow); |
| 789 GenerateMiss(masm); | 789 GenerateMiss(masm); |
| 790 } | 790 } |
| 791 | 791 |
| 792 | 792 |
| 793 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { | 793 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { |
| 794 // The return address is on the stack. | 794 // The return address is on the stack. |
| 795 Label slow, notin; | 795 Label slow, notin; |
| 796 Register receiver = ReceiverRegister(); | 796 Register receiver = StoreConvention::ReceiverRegister(); |
| 797 Register name = NameRegister(); | 797 Register name = StoreConvention::NameRegister(); |
| 798 Register value = ValueRegister(); | 798 Register value = StoreConvention::ValueRegister(); |
| 799 DCHECK(receiver.is(rdx)); | 799 DCHECK(receiver.is(rdx)); |
| 800 DCHECK(name.is(rcx)); | 800 DCHECK(name.is(rcx)); |
| 801 DCHECK(value.is(rax)); | 801 DCHECK(value.is(rax)); |
| 802 | 802 |
| 803 Operand mapped_location = GenerateMappedArgumentsLookup( | 803 Operand mapped_location = GenerateMappedArgumentsLookup( |
| 804 masm, receiver, name, rbx, rdi, r8, ¬in, &slow); | 804 masm, receiver, name, rbx, rdi, r8, ¬in, &slow); |
| 805 __ movp(mapped_location, value); | 805 __ movp(mapped_location, value); |
| 806 __ leap(r9, mapped_location); | 806 __ leap(r9, mapped_location); |
| 807 __ movp(r8, value); | 807 __ movp(r8, value); |
| 808 __ RecordWrite(rbx, r9, r8, kDontSaveFPRegs, EMIT_REMEMBERED_SET, | 808 __ RecordWrite(rbx, r9, r8, kDontSaveFPRegs, EMIT_REMEMBERED_SET, |
| 809 INLINE_SMI_CHECK); | 809 INLINE_SMI_CHECK); |
| 810 __ Ret(); | 810 __ Ret(); |
| 811 __ bind(¬in); | 811 __ bind(¬in); |
| 812 // The unmapped lookup expects that the parameter map is in rbx. | 812 // The unmapped lookup expects that the parameter map is in rbx. |
| 813 Operand unmapped_location = | 813 Operand unmapped_location = |
| 814 GenerateUnmappedArgumentsLookup(masm, name, rbx, rdi, &slow); | 814 GenerateUnmappedArgumentsLookup(masm, name, rbx, rdi, &slow); |
| 815 __ movp(unmapped_location, value); | 815 __ movp(unmapped_location, value); |
| 816 __ leap(r9, unmapped_location); | 816 __ leap(r9, unmapped_location); |
| 817 __ movp(r8, value); | 817 __ movp(r8, value); |
| 818 __ RecordWrite(rbx, r9, r8, kDontSaveFPRegs, EMIT_REMEMBERED_SET, | 818 __ RecordWrite(rbx, r9, r8, kDontSaveFPRegs, EMIT_REMEMBERED_SET, |
| 819 INLINE_SMI_CHECK); | 819 INLINE_SMI_CHECK); |
| 820 __ Ret(); | 820 __ Ret(); |
| 821 __ bind(&slow); | 821 __ bind(&slow); |
| 822 GenerateMiss(masm); | 822 GenerateMiss(masm); |
| 823 } | 823 } |
| 824 | 824 |
| 825 | 825 |
| 826 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 826 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 827 // The return address is on the stack. | 827 // The return address is on the stack. |
| 828 Register receiver = ReceiverRegister(); | 828 Register receiver = LoadConvention::ReceiverRegister(); |
| 829 Register name = NameRegister(); | 829 Register name = LoadConvention::NameRegister(); |
| 830 DCHECK(receiver.is(rdx)); | 830 DCHECK(receiver.is(rdx)); |
| 831 DCHECK(name.is(rcx)); | 831 DCHECK(name.is(rcx)); |
| 832 | 832 |
| 833 // Probe the stub cache. | 833 // Probe the stub cache. |
| 834 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 834 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
| 835 Code::ComputeHandlerFlags(Code::LOAD_IC)); | 835 Code::ComputeHandlerFlags(Code::LOAD_IC)); |
| 836 masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, rbx, | 836 masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, rbx, |
| 837 rax); | 837 rax); |
| 838 | 838 |
| 839 GenerateMiss(masm); | 839 GenerateMiss(masm); |
| 840 } | 840 } |
| 841 | 841 |
| 842 | 842 |
| 843 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 843 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 844 Register dictionary = rax; | 844 Register dictionary = rax; |
| 845 DCHECK(!dictionary.is(ReceiverRegister())); | 845 DCHECK(!dictionary.is(LoadConvention::ReceiverRegister())); |
| 846 DCHECK(!dictionary.is(NameRegister())); | 846 DCHECK(!dictionary.is(LoadConvention::NameRegister())); |
| 847 | 847 |
| 848 Label slow; | 848 Label slow; |
| 849 | 849 |
| 850 __ movp(dictionary, | 850 __ movp(dictionary, FieldOperand(LoadConvention::ReceiverRegister(), |
| 851 FieldOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); | 851 JSObject::kPropertiesOffset)); |
| 852 GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), rbx, rdi, | 852 GenerateDictionaryLoad(masm, &slow, dictionary, |
| 853 rax); | 853 LoadConvention::NameRegister(), rbx, rdi, rax); |
| 854 __ ret(0); | 854 __ ret(0); |
| 855 | 855 |
| 856 // Dictionary load failed, go slow (but don't miss). | 856 // Dictionary load failed, go slow (but don't miss). |
| 857 __ bind(&slow); | 857 __ bind(&slow); |
| 858 GenerateRuntimeGetProperty(masm); | 858 GenerateRuntimeGetProperty(masm); |
| 859 } | 859 } |
| 860 | 860 |
| 861 | 861 |
| 862 // A register that isn't one of the parameters to the load ic. | 862 // A register that isn't one of the parameters to the load ic. |
| 863 static const Register LoadIC_TempRegister() { return rbx; } | 863 static const Register LoadIC_TempRegister() { return rbx; } |
| 864 | 864 |
| 865 | 865 |
| 866 static const Register KeyedLoadIC_TempRegister() { return rbx; } | 866 static const Register KeyedLoadIC_TempRegister() { return rbx; } |
| 867 | 867 |
| 868 | 868 |
| 869 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 869 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 870 // The return address is on the stack. | 870 // The return address is on the stack. |
| 871 | 871 |
| 872 Counters* counters = masm->isolate()->counters(); | 872 Counters* counters = masm->isolate()->counters(); |
| 873 __ IncrementCounter(counters->load_miss(), 1); | 873 __ IncrementCounter(counters->load_miss(), 1); |
| 874 | 874 |
| 875 __ PopReturnAddressTo(LoadIC_TempRegister()); | 875 __ PopReturnAddressTo(LoadIC_TempRegister()); |
| 876 __ Push(ReceiverRegister()); // receiver | 876 __ Push(LoadConvention::ReceiverRegister()); // receiver |
| 877 __ Push(NameRegister()); // name | 877 __ Push(LoadConvention::NameRegister()); // name |
| 878 __ PushReturnAddressFrom(LoadIC_TempRegister()); | 878 __ PushReturnAddressFrom(LoadIC_TempRegister()); |
| 879 | 879 |
| 880 // Perform tail call to the entry. | 880 // Perform tail call to the entry. |
| 881 ExternalReference ref = | 881 ExternalReference ref = |
| 882 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); | 882 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); |
| 883 __ TailCallExternalReference(ref, 2, 1); | 883 __ TailCallExternalReference(ref, 2, 1); |
| 884 } | 884 } |
| 885 | 885 |
| 886 | 886 |
| 887 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 887 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 888 // The return address is on the stack. | 888 // The return address is on the stack. |
| 889 | 889 |
| 890 __ PopReturnAddressTo(LoadIC_TempRegister()); | 890 __ PopReturnAddressTo(LoadIC_TempRegister()); |
| 891 __ Push(ReceiverRegister()); // receiver | 891 __ Push(LoadConvention::ReceiverRegister()); // receiver |
| 892 __ Push(NameRegister()); // name | 892 __ Push(LoadConvention::NameRegister()); // name |
| 893 __ PushReturnAddressFrom(LoadIC_TempRegister()); | 893 __ PushReturnAddressFrom(LoadIC_TempRegister()); |
| 894 | 894 |
| 895 // Perform tail call to the entry. | 895 // Perform tail call to the entry. |
| 896 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); | 896 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); |
| 897 } | 897 } |
| 898 | 898 |
| 899 | 899 |
| 900 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 900 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 901 // The return address is on the stack. | 901 // The return address is on the stack. |
| 902 Counters* counters = masm->isolate()->counters(); | 902 Counters* counters = masm->isolate()->counters(); |
| 903 __ IncrementCounter(counters->keyed_load_miss(), 1); | 903 __ IncrementCounter(counters->keyed_load_miss(), 1); |
| 904 | 904 |
| 905 __ PopReturnAddressTo(KeyedLoadIC_TempRegister()); | 905 __ PopReturnAddressTo(KeyedLoadIC_TempRegister()); |
| 906 __ Push(ReceiverRegister()); // receiver | 906 __ Push(LoadConvention::ReceiverRegister()); // receiver |
| 907 __ Push(NameRegister()); // name | 907 __ Push(LoadConvention::NameRegister()); // name |
| 908 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); | 908 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); |
| 909 | 909 |
| 910 // Perform tail call to the entry. | 910 // Perform tail call to the entry. |
| 911 ExternalReference ref = | 911 ExternalReference ref = |
| 912 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); | 912 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); |
| 913 __ TailCallExternalReference(ref, 2, 1); | 913 __ TailCallExternalReference(ref, 2, 1); |
| 914 } | 914 } |
| 915 | 915 |
| 916 | 916 |
| 917 // IC register specifications | |
| 918 const Register LoadIC::ReceiverRegister() { return rdx; } | |
| 919 const Register LoadIC::NameRegister() { return rcx; } | |
| 920 | |
| 921 | |
| 922 const Register LoadIC::SlotRegister() { | |
| 923 DCHECK(FLAG_vector_ics); | |
| 924 return rax; | |
| 925 } | |
| 926 | |
| 927 | |
| 928 const Register LoadIC::VectorRegister() { | |
| 929 DCHECK(FLAG_vector_ics); | |
| 930 return rbx; | |
| 931 } | |
| 932 | |
| 933 | |
| 934 const Register StoreIC::ReceiverRegister() { return rdx; } | |
| 935 const Register StoreIC::NameRegister() { return rcx; } | |
| 936 const Register StoreIC::ValueRegister() { return rax; } | |
| 937 | |
| 938 | |
| 939 const Register KeyedStoreIC::MapRegister() { return rbx; } | |
| 940 | |
| 941 | |
| 942 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 917 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 943 // The return address is on the stack. | 918 // The return address is on the stack. |
| 944 | 919 |
| 945 __ PopReturnAddressTo(KeyedLoadIC_TempRegister()); | 920 __ PopReturnAddressTo(KeyedLoadIC_TempRegister()); |
| 946 __ Push(ReceiverRegister()); // receiver | 921 __ Push(LoadConvention::ReceiverRegister()); // receiver |
| 947 __ Push(NameRegister()); // name | 922 __ Push(LoadConvention::NameRegister()); // name |
| 948 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); | 923 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); |
| 949 | 924 |
| 950 // Perform tail call to the entry. | 925 // Perform tail call to the entry. |
| 951 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 926 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 952 } | 927 } |
| 953 | 928 |
| 954 | 929 |
| 955 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 930 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 956 // The return address is on the stack. | 931 // The return address is on the stack. |
| 957 | 932 |
| 958 // Get the receiver from the stack and probe the stub cache. | 933 // Get the receiver from the stack and probe the stub cache. |
| 959 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 934 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
| 960 Code::ComputeHandlerFlags(Code::STORE_IC)); | 935 Code::ComputeHandlerFlags(Code::STORE_IC)); |
| 961 masm->isolate()->stub_cache()->GenerateProbe(masm, flags, ReceiverRegister(), | 936 masm->isolate()->stub_cache()->GenerateProbe( |
| 962 NameRegister(), rbx, no_reg); | 937 masm, flags, StoreConvention::ReceiverRegister(), |
| 938 StoreConvention::NameRegister(), rbx, no_reg); |
| 963 | 939 |
| 964 // Cache miss: Jump to runtime. | 940 // Cache miss: Jump to runtime. |
| 965 GenerateMiss(masm); | 941 GenerateMiss(masm); |
| 966 } | 942 } |
| 967 | 943 |
| 968 | 944 |
| 969 static void StoreIC_PushArgs(MacroAssembler* masm) { | 945 static void StoreIC_PushArgs(MacroAssembler* masm) { |
| 970 Register receiver = StoreIC::ReceiverRegister(); | 946 Register receiver = StoreConvention::ReceiverRegister(); |
| 971 Register name = StoreIC::NameRegister(); | 947 Register name = StoreConvention::NameRegister(); |
| 972 Register value = StoreIC::ValueRegister(); | 948 Register value = StoreConvention::ValueRegister(); |
| 973 | 949 |
| 974 DCHECK(!rbx.is(receiver) && !rbx.is(name) && !rbx.is(value)); | 950 DCHECK(!rbx.is(receiver) && !rbx.is(name) && !rbx.is(value)); |
| 975 | 951 |
| 976 __ PopReturnAddressTo(rbx); | 952 __ PopReturnAddressTo(rbx); |
| 977 __ Push(receiver); | 953 __ Push(receiver); |
| 978 __ Push(name); | 954 __ Push(name); |
| 979 __ Push(value); | 955 __ Push(value); |
| 980 __ PushReturnAddressFrom(rbx); | 956 __ PushReturnAddressFrom(rbx); |
| 981 } | 957 } |
| 982 | 958 |
| 983 | 959 |
| 984 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 960 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 985 // Return address is on the stack. | 961 // Return address is on the stack. |
| 986 StoreIC_PushArgs(masm); | 962 StoreIC_PushArgs(masm); |
| 987 | 963 |
| 988 // Perform tail call to the entry. | 964 // Perform tail call to the entry. |
| 989 ExternalReference ref = | 965 ExternalReference ref = |
| 990 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); | 966 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); |
| 991 __ TailCallExternalReference(ref, 3, 1); | 967 __ TailCallExternalReference(ref, 3, 1); |
| 992 } | 968 } |
| 993 | 969 |
| 994 | 970 |
| 995 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 971 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
| 996 Register receiver = ReceiverRegister(); | 972 Register receiver = StoreConvention::ReceiverRegister(); |
| 997 Register name = NameRegister(); | 973 Register name = StoreConvention::NameRegister(); |
| 998 Register value = ValueRegister(); | 974 Register value = StoreConvention::ValueRegister(); |
| 999 Register dictionary = rbx; | 975 Register dictionary = rbx; |
| 1000 | 976 |
| 1001 Label miss; | 977 Label miss; |
| 1002 | 978 |
| 1003 __ movp(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 979 __ movp(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 1004 GenerateDictionaryStore(masm, &miss, dictionary, name, value, r8, r9); | 980 GenerateDictionaryStore(masm, &miss, dictionary, name, value, r8, r9); |
| 1005 Counters* counters = masm->isolate()->counters(); | 981 Counters* counters = masm->isolate()->counters(); |
| 1006 __ IncrementCounter(counters->store_normal_hit(), 1); | 982 __ IncrementCounter(counters->store_normal_hit(), 1); |
| 1007 __ ret(0); | 983 __ ret(0); |
| 1008 | 984 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1090 Condition cc = | 1066 Condition cc = |
| 1091 (check == ENABLE_INLINED_SMI_CHECK) | 1067 (check == ENABLE_INLINED_SMI_CHECK) |
| 1092 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1068 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| 1093 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1069 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| 1094 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1070 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1095 } | 1071 } |
| 1096 } | 1072 } |
| 1097 } // namespace v8::internal | 1073 } // namespace v8::internal |
| 1098 | 1074 |
| 1099 #endif // V8_TARGET_ARCH_X64 | 1075 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |