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-inl.h" | 10 #include "src/ic-inl.h" |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 // Scratch registers: | 173 // Scratch registers: |
174 // map - used to hold the map of the receiver. | 174 // map - used to hold the map of the receiver. |
175 | 175 |
176 // Check that the object isn't a smi. | 176 // Check that the object isn't a smi. |
177 __ JumpIfSmi(receiver, slow); | 177 __ JumpIfSmi(receiver, slow); |
178 | 178 |
179 // Check that the object is some kind of JS object EXCEPT JS Value type. | 179 // Check that the object is some kind of JS object EXCEPT JS Value type. |
180 // In the case that the object is a value-wrapper object, | 180 // In the case that the object is a value-wrapper object, |
181 // we enter the runtime system to make sure that indexing | 181 // we enter the runtime system to make sure that indexing |
182 // into string objects work as intended. | 182 // into string objects work as intended. |
183 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 183 DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
184 __ CmpObjectType(receiver, JS_OBJECT_TYPE, map); | 184 __ CmpObjectType(receiver, JS_OBJECT_TYPE, map); |
185 __ j(below, slow); | 185 __ j(below, slow); |
186 | 186 |
187 // Check bit field. | 187 // Check bit field. |
188 __ testb(FieldOperand(map, Map::kBitFieldOffset), | 188 __ testb(FieldOperand(map, Map::kBitFieldOffset), |
189 Immediate((1 << Map::kIsAccessCheckNeeded) | | 189 Immediate((1 << Map::kIsAccessCheckNeeded) | |
190 (1 << interceptor_bit))); | 190 (1 << interceptor_bit))); |
191 __ j(not_zero, slow); | 191 __ j(not_zero, slow); |
192 } | 192 } |
193 | 193 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 | 286 |
287 | 287 |
288 | 288 |
289 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 289 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
290 // The return address is on the stack. | 290 // The return address is on the stack. |
291 Label slow, check_name, index_smi, index_name, property_array_property; | 291 Label slow, check_name, index_smi, index_name, property_array_property; |
292 Label probe_dictionary, check_number_dictionary; | 292 Label probe_dictionary, check_number_dictionary; |
293 | 293 |
294 Register receiver = ReceiverRegister(); | 294 Register receiver = ReceiverRegister(); |
295 Register key = NameRegister(); | 295 Register key = NameRegister(); |
296 ASSERT(receiver.is(rdx)); | 296 DCHECK(receiver.is(rdx)); |
297 ASSERT(key.is(rcx)); | 297 DCHECK(key.is(rcx)); |
298 | 298 |
299 // Check that the key is a smi. | 299 // Check that the key is a smi. |
300 __ JumpIfNotSmi(key, &check_name); | 300 __ JumpIfNotSmi(key, &check_name); |
301 __ bind(&index_smi); | 301 __ bind(&index_smi); |
302 // Now the key is known to be a smi. This place is also jumped to from below | 302 // Now the key is known to be a smi. This place is also jumped to from below |
303 // where a numeric string is converted to a smi. | 303 // where a numeric string is converted to a smi. |
304 | 304 |
305 GenerateKeyedLoadReceiverCheck( | 305 GenerateKeyedLoadReceiverCheck( |
306 masm, receiver, rax, Map::kHasIndexedInterceptor, &slow); | 306 masm, receiver, rax, Map::kHasIndexedInterceptor, &slow); |
307 | 307 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 | 445 |
446 | 446 |
447 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 447 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
448 // Return address is on the stack. | 448 // Return address is on the stack. |
449 Label miss; | 449 Label miss; |
450 | 450 |
451 Register receiver = ReceiverRegister(); | 451 Register receiver = ReceiverRegister(); |
452 Register index = NameRegister(); | 452 Register index = NameRegister(); |
453 Register scratch = rbx; | 453 Register scratch = rbx; |
454 Register result = rax; | 454 Register result = rax; |
455 ASSERT(!scratch.is(receiver) && !scratch.is(index)); | 455 DCHECK(!scratch.is(receiver) && !scratch.is(index)); |
456 | 456 |
457 StringCharAtGenerator char_at_generator(receiver, | 457 StringCharAtGenerator char_at_generator(receiver, |
458 index, | 458 index, |
459 scratch, | 459 scratch, |
460 result, | 460 result, |
461 &miss, // When not a string. | 461 &miss, // When not a string. |
462 &miss, // When not a number. | 462 &miss, // When not a number. |
463 &miss, // When index out of range. | 463 &miss, // When index out of range. |
464 STRING_INDEX_IS_ARRAY_INDEX); | 464 STRING_INDEX_IS_ARRAY_INDEX); |
465 char_at_generator.GenerateFast(masm); | 465 char_at_generator.GenerateFast(masm); |
466 __ ret(0); | 466 __ ret(0); |
467 | 467 |
468 StubRuntimeCallHelper call_helper; | 468 StubRuntimeCallHelper call_helper; |
469 char_at_generator.GenerateSlow(masm, call_helper); | 469 char_at_generator.GenerateSlow(masm, call_helper); |
470 | 470 |
471 __ bind(&miss); | 471 __ bind(&miss); |
472 GenerateMiss(masm); | 472 GenerateMiss(masm); |
473 } | 473 } |
474 | 474 |
475 | 475 |
476 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 476 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
477 // Return address is on the stack. | 477 // Return address is on the stack. |
478 Label slow; | 478 Label slow; |
479 | 479 |
480 Register receiver = ReceiverRegister(); | 480 Register receiver = ReceiverRegister(); |
481 Register key = NameRegister(); | 481 Register key = NameRegister(); |
482 Register scratch = rax; | 482 Register scratch = rax; |
483 ASSERT(!scratch.is(receiver) && !scratch.is(key)); | 483 DCHECK(!scratch.is(receiver) && !scratch.is(key)); |
484 | 484 |
485 // Check that the receiver isn't a smi. | 485 // Check that the receiver isn't a smi. |
486 __ JumpIfSmi(receiver, &slow); | 486 __ JumpIfSmi(receiver, &slow); |
487 | 487 |
488 // Check that the key is an array index, that is Uint32. | 488 // Check that the key is an array index, that is Uint32. |
489 STATIC_ASSERT(kSmiValueSize <= 32); | 489 STATIC_ASSERT(kSmiValueSize <= 32); |
490 __ JumpUnlessNonNegativeSmi(key, &slow); | 490 __ JumpUnlessNonNegativeSmi(key, &slow); |
491 | 491 |
492 // Get the map of the receiver. | 492 // Get the map of the receiver. |
493 __ movp(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 493 __ movp(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
(...skipping 28 matching lines...) Expand all Loading... |
522 Label* fast_double, | 522 Label* fast_double, |
523 Label* slow, | 523 Label* slow, |
524 KeyedStoreCheckMap check_map, | 524 KeyedStoreCheckMap check_map, |
525 KeyedStoreIncrementLength increment_length) { | 525 KeyedStoreIncrementLength increment_length) { |
526 Label transition_smi_elements; | 526 Label transition_smi_elements; |
527 Label finish_object_store, non_double_value, transition_double_elements; | 527 Label finish_object_store, non_double_value, transition_double_elements; |
528 Label fast_double_without_map_check; | 528 Label fast_double_without_map_check; |
529 Register receiver = KeyedStoreIC::ReceiverRegister(); | 529 Register receiver = KeyedStoreIC::ReceiverRegister(); |
530 Register key = KeyedStoreIC::NameRegister(); | 530 Register key = KeyedStoreIC::NameRegister(); |
531 Register value = KeyedStoreIC::ValueRegister(); | 531 Register value = KeyedStoreIC::ValueRegister(); |
532 ASSERT(receiver.is(rdx)); | 532 DCHECK(receiver.is(rdx)); |
533 ASSERT(key.is(rcx)); | 533 DCHECK(key.is(rcx)); |
534 ASSERT(value.is(rax)); | 534 DCHECK(value.is(rax)); |
535 // Fast case: Do the store, could be either Object or double. | 535 // Fast case: Do the store, could be either Object or double. |
536 __ bind(fast_object); | 536 __ bind(fast_object); |
537 // rbx: receiver's elements array (a FixedArray) | 537 // rbx: receiver's elements array (a FixedArray) |
538 // receiver is a JSArray. | 538 // receiver is a JSArray. |
539 // r9: map of receiver | 539 // r9: map of receiver |
540 if (check_map == kCheckMap) { | 540 if (check_map == kCheckMap) { |
541 __ movp(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); | 541 __ movp(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); |
542 __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex); | 542 __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex); |
543 __ j(not_equal, fast_double); | 543 __ j(not_equal, fast_double); |
544 } | 544 } |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 | 669 |
670 | 670 |
671 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, | 671 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
672 StrictMode strict_mode) { | 672 StrictMode strict_mode) { |
673 // Return address is on the stack. | 673 // Return address is on the stack. |
674 Label slow, slow_with_tagged_index, fast_object, fast_object_grow; | 674 Label slow, slow_with_tagged_index, fast_object, fast_object_grow; |
675 Label fast_double, fast_double_grow; | 675 Label fast_double, fast_double_grow; |
676 Label array, extra, check_if_double_array; | 676 Label array, extra, check_if_double_array; |
677 Register receiver = ReceiverRegister(); | 677 Register receiver = ReceiverRegister(); |
678 Register key = NameRegister(); | 678 Register key = NameRegister(); |
679 ASSERT(receiver.is(rdx)); | 679 DCHECK(receiver.is(rdx)); |
680 ASSERT(key.is(rcx)); | 680 DCHECK(key.is(rcx)); |
681 | 681 |
682 // Check that the object isn't a smi. | 682 // Check that the object isn't a smi. |
683 __ JumpIfSmi(receiver, &slow_with_tagged_index); | 683 __ JumpIfSmi(receiver, &slow_with_tagged_index); |
684 // Get the map from the receiver. | 684 // Get the map from the receiver. |
685 __ movp(r9, FieldOperand(receiver, HeapObject::kMapOffset)); | 685 __ movp(r9, FieldOperand(receiver, HeapObject::kMapOffset)); |
686 // Check that the receiver does not require access checks and is not observed. | 686 // Check that the receiver does not require access checks and is not observed. |
687 // The generic stub does not perform map checks or handle observed objects. | 687 // The generic stub does not perform map checks or handle observed objects. |
688 __ testb(FieldOperand(r9, Map::kBitFieldOffset), | 688 __ testb(FieldOperand(r9, Map::kBitFieldOffset), |
689 Immediate(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved)); | 689 Immediate(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved)); |
690 __ j(not_zero, &slow_with_tagged_index); | 690 __ j(not_zero, &slow_with_tagged_index); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 scratch, | 831 scratch, |
832 times_pointer_size, | 832 times_pointer_size, |
833 FixedArray::kHeaderSize); | 833 FixedArray::kHeaderSize); |
834 } | 834 } |
835 | 835 |
836 | 836 |
837 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { | 837 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { |
838 // The return address is on the stack. | 838 // The return address is on the stack. |
839 Register receiver = ReceiverRegister(); | 839 Register receiver = ReceiverRegister(); |
840 Register key = NameRegister(); | 840 Register key = NameRegister(); |
841 ASSERT(receiver.is(rdx)); | 841 DCHECK(receiver.is(rdx)); |
842 ASSERT(key.is(rcx)); | 842 DCHECK(key.is(rcx)); |
843 | 843 |
844 Label slow, notin; | 844 Label slow, notin; |
845 Operand mapped_location = | 845 Operand mapped_location = |
846 GenerateMappedArgumentsLookup( | 846 GenerateMappedArgumentsLookup( |
847 masm, receiver, key, rbx, rax, rdi, ¬in, &slow); | 847 masm, receiver, key, rbx, rax, rdi, ¬in, &slow); |
848 __ movp(rax, mapped_location); | 848 __ movp(rax, mapped_location); |
849 __ Ret(); | 849 __ Ret(); |
850 __ bind(¬in); | 850 __ bind(¬in); |
851 // The unmapped lookup expects that the parameter map is in rbx. | 851 // The unmapped lookup expects that the parameter map is in rbx. |
852 Operand unmapped_location = | 852 Operand unmapped_location = |
853 GenerateUnmappedArgumentsLookup(masm, key, rbx, rax, &slow); | 853 GenerateUnmappedArgumentsLookup(masm, key, rbx, rax, &slow); |
854 __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex); | 854 __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex); |
855 __ j(equal, &slow); | 855 __ j(equal, &slow); |
856 __ movp(rax, unmapped_location); | 856 __ movp(rax, unmapped_location); |
857 __ Ret(); | 857 __ Ret(); |
858 __ bind(&slow); | 858 __ bind(&slow); |
859 GenerateMiss(masm); | 859 GenerateMiss(masm); |
860 } | 860 } |
861 | 861 |
862 | 862 |
863 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { | 863 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { |
864 // The return address is on the stack. | 864 // The return address is on the stack. |
865 Label slow, notin; | 865 Label slow, notin; |
866 Register receiver = ReceiverRegister(); | 866 Register receiver = ReceiverRegister(); |
867 Register name = NameRegister(); | 867 Register name = NameRegister(); |
868 Register value = ValueRegister(); | 868 Register value = ValueRegister(); |
869 ASSERT(receiver.is(rdx)); | 869 DCHECK(receiver.is(rdx)); |
870 ASSERT(name.is(rcx)); | 870 DCHECK(name.is(rcx)); |
871 ASSERT(value.is(rax)); | 871 DCHECK(value.is(rax)); |
872 | 872 |
873 Operand mapped_location = GenerateMappedArgumentsLookup( | 873 Operand mapped_location = GenerateMappedArgumentsLookup( |
874 masm, receiver, name, rbx, rdi, r8, ¬in, &slow); | 874 masm, receiver, name, rbx, rdi, r8, ¬in, &slow); |
875 __ movp(mapped_location, value); | 875 __ movp(mapped_location, value); |
876 __ leap(r9, mapped_location); | 876 __ leap(r9, mapped_location); |
877 __ movp(r8, value); | 877 __ movp(r8, value); |
878 __ RecordWrite(rbx, | 878 __ RecordWrite(rbx, |
879 r9, | 879 r9, |
880 r8, | 880 r8, |
881 kDontSaveFPRegs, | 881 kDontSaveFPRegs, |
(...skipping 16 matching lines...) Expand all Loading... |
898 __ Ret(); | 898 __ Ret(); |
899 __ bind(&slow); | 899 __ bind(&slow); |
900 GenerateMiss(masm); | 900 GenerateMiss(masm); |
901 } | 901 } |
902 | 902 |
903 | 903 |
904 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 904 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
905 // The return address is on the stack. | 905 // The return address is on the stack. |
906 Register receiver = ReceiverRegister(); | 906 Register receiver = ReceiverRegister(); |
907 Register name = NameRegister(); | 907 Register name = NameRegister(); |
908 ASSERT(receiver.is(rdx)); | 908 DCHECK(receiver.is(rdx)); |
909 ASSERT(name.is(rcx)); | 909 DCHECK(name.is(rcx)); |
910 | 910 |
911 // Probe the stub cache. | 911 // Probe the stub cache. |
912 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 912 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
913 Code::ComputeHandlerFlags(Code::LOAD_IC)); | 913 Code::ComputeHandlerFlags(Code::LOAD_IC)); |
914 masm->isolate()->stub_cache()->GenerateProbe( | 914 masm->isolate()->stub_cache()->GenerateProbe( |
915 masm, flags, receiver, name, rbx, rax); | 915 masm, flags, receiver, name, rbx, rax); |
916 | 916 |
917 GenerateMiss(masm); | 917 GenerateMiss(masm); |
918 } | 918 } |
919 | 919 |
920 | 920 |
921 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 921 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
922 Register dictionary = rax; | 922 Register dictionary = rax; |
923 ASSERT(!dictionary.is(ReceiverRegister())); | 923 DCHECK(!dictionary.is(ReceiverRegister())); |
924 ASSERT(!dictionary.is(NameRegister())); | 924 DCHECK(!dictionary.is(NameRegister())); |
925 | 925 |
926 Label slow; | 926 Label slow; |
927 | 927 |
928 __ movp(dictionary, | 928 __ movp(dictionary, |
929 FieldOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); | 929 FieldOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); |
930 GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), rbx, rdi, | 930 GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), rbx, rdi, |
931 rax); | 931 rax); |
932 __ ret(0); | 932 __ ret(0); |
933 | 933 |
934 // Dictionary load failed, go slow (but don't miss). | 934 // Dictionary load failed, go slow (but don't miss). |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
993 __ TailCallExternalReference(ref, 2, 1); | 993 __ TailCallExternalReference(ref, 2, 1); |
994 } | 994 } |
995 | 995 |
996 | 996 |
997 // IC register specifications | 997 // IC register specifications |
998 const Register LoadIC::ReceiverRegister() { return rdx; } | 998 const Register LoadIC::ReceiverRegister() { return rdx; } |
999 const Register LoadIC::NameRegister() { return rcx; } | 999 const Register LoadIC::NameRegister() { return rcx; } |
1000 | 1000 |
1001 | 1001 |
1002 const Register LoadIC::SlotRegister() { | 1002 const Register LoadIC::SlotRegister() { |
1003 ASSERT(FLAG_vector_ics); | 1003 DCHECK(FLAG_vector_ics); |
1004 return rax; | 1004 return rax; |
1005 } | 1005 } |
1006 | 1006 |
1007 | 1007 |
1008 const Register LoadIC::VectorRegister() { | 1008 const Register LoadIC::VectorRegister() { |
1009 ASSERT(FLAG_vector_ics); | 1009 DCHECK(FLAG_vector_ics); |
1010 return rbx; | 1010 return rbx; |
1011 } | 1011 } |
1012 | 1012 |
1013 | 1013 |
1014 const Register StoreIC::ReceiverRegister() { return rdx; } | 1014 const Register StoreIC::ReceiverRegister() { return rdx; } |
1015 const Register StoreIC::NameRegister() { return rcx; } | 1015 const Register StoreIC::NameRegister() { return rcx; } |
1016 const Register StoreIC::ValueRegister() { return rax; } | 1016 const Register StoreIC::ValueRegister() { return rax; } |
1017 | 1017 |
1018 | 1018 |
1019 const Register KeyedStoreIC::MapRegister() { | 1019 const Register KeyedStoreIC::MapRegister() { |
(...skipping 26 matching lines...) Expand all Loading... |
1046 // Cache miss: Jump to runtime. | 1046 // Cache miss: Jump to runtime. |
1047 GenerateMiss(masm); | 1047 GenerateMiss(masm); |
1048 } | 1048 } |
1049 | 1049 |
1050 | 1050 |
1051 static void StoreIC_PushArgs(MacroAssembler* masm) { | 1051 static void StoreIC_PushArgs(MacroAssembler* masm) { |
1052 Register receiver = StoreIC::ReceiverRegister(); | 1052 Register receiver = StoreIC::ReceiverRegister(); |
1053 Register name = StoreIC::NameRegister(); | 1053 Register name = StoreIC::NameRegister(); |
1054 Register value = StoreIC::ValueRegister(); | 1054 Register value = StoreIC::ValueRegister(); |
1055 | 1055 |
1056 ASSERT(!rbx.is(receiver) && !rbx.is(name) && !rbx.is(value)); | 1056 DCHECK(!rbx.is(receiver) && !rbx.is(name) && !rbx.is(value)); |
1057 | 1057 |
1058 __ PopReturnAddressTo(rbx); | 1058 __ PopReturnAddressTo(rbx); |
1059 __ Push(receiver); | 1059 __ Push(receiver); |
1060 __ Push(name); | 1060 __ Push(name); |
1061 __ Push(value); | 1061 __ Push(value); |
1062 __ PushReturnAddressFrom(rbx); | 1062 __ PushReturnAddressFrom(rbx); |
1063 } | 1063 } |
1064 | 1064 |
1065 | 1065 |
1066 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1066 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
(...skipping 23 matching lines...) Expand all Loading... |
1090 | 1090 |
1091 __ bind(&miss); | 1091 __ bind(&miss); |
1092 __ IncrementCounter(counters->store_normal_miss(), 1); | 1092 __ IncrementCounter(counters->store_normal_miss(), 1); |
1093 GenerateMiss(masm); | 1093 GenerateMiss(masm); |
1094 } | 1094 } |
1095 | 1095 |
1096 | 1096 |
1097 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, | 1097 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, |
1098 StrictMode strict_mode) { | 1098 StrictMode strict_mode) { |
1099 // Return address is on the stack. | 1099 // Return address is on the stack. |
1100 ASSERT(!rbx.is(ReceiverRegister()) && !rbx.is(NameRegister()) && | 1100 DCHECK(!rbx.is(ReceiverRegister()) && !rbx.is(NameRegister()) && |
1101 !rbx.is(ValueRegister())); | 1101 !rbx.is(ValueRegister())); |
1102 | 1102 |
1103 __ PopReturnAddressTo(rbx); | 1103 __ PopReturnAddressTo(rbx); |
1104 __ Push(ReceiverRegister()); | 1104 __ Push(ReceiverRegister()); |
1105 __ Push(NameRegister()); | 1105 __ Push(NameRegister()); |
1106 __ Push(ValueRegister()); | 1106 __ Push(ValueRegister()); |
1107 __ Push(Smi::FromInt(strict_mode)); | 1107 __ Push(Smi::FromInt(strict_mode)); |
1108 __ PushReturnAddressFrom(rbx); | 1108 __ PushReturnAddressFrom(rbx); |
1109 | 1109 |
1110 // Do tail-call to runtime routine. | 1110 // Do tail-call to runtime routine. |
1111 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); | 1111 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); |
1112 } | 1112 } |
1113 | 1113 |
1114 | 1114 |
1115 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, | 1115 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, |
1116 StrictMode strict_mode) { | 1116 StrictMode strict_mode) { |
1117 // Return address is on the stack. | 1117 // Return address is on the stack. |
1118 ASSERT(!rbx.is(ReceiverRegister()) && !rbx.is(NameRegister()) && | 1118 DCHECK(!rbx.is(ReceiverRegister()) && !rbx.is(NameRegister()) && |
1119 !rbx.is(ValueRegister())); | 1119 !rbx.is(ValueRegister())); |
1120 | 1120 |
1121 __ PopReturnAddressTo(rbx); | 1121 __ PopReturnAddressTo(rbx); |
1122 __ Push(ReceiverRegister()); | 1122 __ Push(ReceiverRegister()); |
1123 __ Push(NameRegister()); | 1123 __ Push(NameRegister()); |
1124 __ Push(ValueRegister()); | 1124 __ Push(ValueRegister()); |
1125 __ Push(Smi::FromInt(strict_mode)); // Strict mode. | 1125 __ Push(Smi::FromInt(strict_mode)); // Strict mode. |
1126 __ PushReturnAddressFrom(rbx); | 1126 __ PushReturnAddressFrom(rbx); |
1127 | 1127 |
1128 // Do tail-call to runtime routine. | 1128 // Do tail-call to runtime routine. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 | 1196 |
1197 | 1197 |
1198 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { | 1198 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { |
1199 // The address of the instruction following the call. | 1199 // The address of the instruction following the call. |
1200 Address test_instruction_address = | 1200 Address test_instruction_address = |
1201 address + Assembler::kCallTargetAddressOffset; | 1201 address + Assembler::kCallTargetAddressOffset; |
1202 | 1202 |
1203 // If the instruction following the call is not a test al, nothing | 1203 // If the instruction following the call is not a test al, nothing |
1204 // was inlined. | 1204 // was inlined. |
1205 if (*test_instruction_address != Assembler::kTestAlByte) { | 1205 if (*test_instruction_address != Assembler::kTestAlByte) { |
1206 ASSERT(*test_instruction_address == Assembler::kNopByte); | 1206 DCHECK(*test_instruction_address == Assembler::kNopByte); |
1207 return; | 1207 return; |
1208 } | 1208 } |
1209 | 1209 |
1210 Address delta_address = test_instruction_address + 1; | 1210 Address delta_address = test_instruction_address + 1; |
1211 // The delta to the start of the map check instruction and the | 1211 // The delta to the start of the map check instruction and the |
1212 // condition code uses at the patched jump. | 1212 // condition code uses at the patched jump. |
1213 uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address); | 1213 uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address); |
1214 if (FLAG_trace_ic) { | 1214 if (FLAG_trace_ic) { |
1215 PrintF("[ patching ic at %p, test=%p, delta=%d\n", | 1215 PrintF("[ patching ic at %p, test=%p, delta=%d\n", |
1216 address, test_instruction_address, delta); | 1216 address, test_instruction_address, delta); |
1217 } | 1217 } |
1218 | 1218 |
1219 // Patch with a short conditional jump. Enabling means switching from a short | 1219 // Patch with a short conditional jump. Enabling means switching from a short |
1220 // jump-if-carry/not-carry to jump-if-zero/not-zero, whereas disabling is the | 1220 // jump-if-carry/not-carry to jump-if-zero/not-zero, whereas disabling is the |
1221 // reverse operation of that. | 1221 // reverse operation of that. |
1222 Address jmp_address = test_instruction_address - delta; | 1222 Address jmp_address = test_instruction_address - delta; |
1223 ASSERT((check == ENABLE_INLINED_SMI_CHECK) | 1223 DCHECK((check == ENABLE_INLINED_SMI_CHECK) |
1224 ? (*jmp_address == Assembler::kJncShortOpcode || | 1224 ? (*jmp_address == Assembler::kJncShortOpcode || |
1225 *jmp_address == Assembler::kJcShortOpcode) | 1225 *jmp_address == Assembler::kJcShortOpcode) |
1226 : (*jmp_address == Assembler::kJnzShortOpcode || | 1226 : (*jmp_address == Assembler::kJnzShortOpcode || |
1227 *jmp_address == Assembler::kJzShortOpcode)); | 1227 *jmp_address == Assembler::kJzShortOpcode)); |
1228 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) | 1228 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) |
1229 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1229 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
1230 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1230 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
1231 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1231 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
1232 } | 1232 } |
1233 | 1233 |
1234 | 1234 |
1235 } } // namespace v8::internal | 1235 } } // namespace v8::internal |
1236 | 1236 |
1237 #endif // V8_TARGET_ARCH_X64 | 1237 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |