| 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/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/ic-inl.h" | 10 #include "src/ic-inl.h" |
| (...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 Register receiver_reg, | 611 Register receiver_reg, |
| 612 Register name_reg, | 612 Register name_reg, |
| 613 Register value_reg, | 613 Register value_reg, |
| 614 Register scratch1, | 614 Register scratch1, |
| 615 Register scratch2, | 615 Register scratch2, |
| 616 Label* miss_label) { | 616 Label* miss_label) { |
| 617 // Stub never generated for non-global objects that require access | 617 // Stub never generated for non-global objects that require access |
| 618 // checks. | 618 // checks. |
| 619 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 619 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 620 | 620 |
| 621 int index = lookup->GetFieldIndex().field_index(); | 621 FieldIndex index = lookup->GetFieldIndex(); |
| 622 | |
| 623 // Adjust for the number of properties stored in the object. Even in the | |
| 624 // face of a transition we can use the old map here because the size of the | |
| 625 // object and the number of in-object properties is not going to change. | |
| 626 index -= object->map()->inobject_properties(); | |
| 627 | 622 |
| 628 Representation representation = lookup->representation(); | 623 Representation representation = lookup->representation(); |
| 629 ASSERT(!representation.IsNone()); | 624 ASSERT(!representation.IsNone()); |
| 630 if (representation.IsSmi()) { | 625 if (representation.IsSmi()) { |
| 631 __ JumpIfNotSmi(value_reg, miss_label); | 626 __ JumpIfNotSmi(value_reg, miss_label); |
| 632 } else if (representation.IsHeapObject()) { | 627 } else if (representation.IsHeapObject()) { |
| 633 __ JumpIfSmi(value_reg, miss_label); | 628 __ JumpIfSmi(value_reg, miss_label); |
| 634 HeapType* field_type = lookup->GetFieldType(); | 629 HeapType* field_type = lookup->GetFieldType(); |
| 635 HeapType::Iterator<Map> it = field_type->Classes(); | 630 HeapType::Iterator<Map> it = field_type->Classes(); |
| 636 if (!it.Done()) { | 631 if (!it.Done()) { |
| 637 Label do_store; | 632 Label do_store; |
| 638 while (true) { | 633 while (true) { |
| 639 __ CompareMap(value_reg, it.Current()); | 634 __ CompareMap(value_reg, it.Current()); |
| 640 it.Advance(); | 635 it.Advance(); |
| 641 if (it.Done()) { | 636 if (it.Done()) { |
| 642 __ j(not_equal, miss_label); | 637 __ j(not_equal, miss_label); |
| 643 break; | 638 break; |
| 644 } | 639 } |
| 645 __ j(equal, &do_store, Label::kNear); | 640 __ j(equal, &do_store, Label::kNear); |
| 646 } | 641 } |
| 647 __ bind(&do_store); | 642 __ bind(&do_store); |
| 648 } | 643 } |
| 649 } else if (representation.IsDouble()) { | 644 } else if (representation.IsDouble()) { |
| 650 // Load the double storage. | 645 // Load the double storage. |
| 651 if (index < 0) { | 646 if (index.is_inobject()) { |
| 652 int offset = object->map()->instance_size() + (index * kPointerSize); | 647 __ movp(scratch1, FieldOperand(receiver_reg, index.offset())); |
| 653 __ movp(scratch1, FieldOperand(receiver_reg, offset)); | |
| 654 } else { | 648 } else { |
| 655 __ movp(scratch1, | 649 __ movp(scratch1, |
| 656 FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 650 FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 657 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 651 __ movp(scratch1, FieldOperand(scratch1, index.offset())); |
| 658 __ movp(scratch1, FieldOperand(scratch1, offset)); | |
| 659 } | 652 } |
| 660 | 653 |
| 661 // Store the value into the storage. | 654 // Store the value into the storage. |
| 662 Label do_store, heap_number; | 655 Label do_store, heap_number; |
| 663 __ JumpIfNotSmi(value_reg, &heap_number); | 656 __ JumpIfNotSmi(value_reg, &heap_number); |
| 664 __ SmiToInteger32(scratch2, value_reg); | 657 __ SmiToInteger32(scratch2, value_reg); |
| 665 __ Cvtlsi2sd(xmm0, scratch2); | 658 __ Cvtlsi2sd(xmm0, scratch2); |
| 666 __ jmp(&do_store); | 659 __ jmp(&do_store); |
| 667 | 660 |
| 668 __ bind(&heap_number); | 661 __ bind(&heap_number); |
| 669 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 662 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
| 670 miss_label, DONT_DO_SMI_CHECK); | 663 miss_label, DONT_DO_SMI_CHECK); |
| 671 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 664 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
| 672 __ bind(&do_store); | 665 __ bind(&do_store); |
| 673 __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0); | 666 __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0); |
| 674 // Return the value (register rax). | 667 // Return the value (register rax). |
| 675 ASSERT(value_reg.is(rax)); | 668 ASSERT(value_reg.is(rax)); |
| 676 __ ret(0); | 669 __ ret(0); |
| 677 return; | 670 return; |
| 678 } | 671 } |
| 679 | 672 |
| 680 // TODO(verwaest): Share this code as a code stub. | 673 // TODO(verwaest): Share this code as a code stub. |
| 681 SmiCheck smi_check = representation.IsTagged() | 674 SmiCheck smi_check = representation.IsTagged() |
| 682 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 675 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
| 683 if (index < 0) { | 676 if (index.is_inobject()) { |
| 684 // Set the property straight into the object. | 677 // Set the property straight into the object. |
| 685 int offset = object->map()->instance_size() + (index * kPointerSize); | 678 __ movp(FieldOperand(receiver_reg, index.offset()), value_reg); |
| 686 __ movp(FieldOperand(receiver_reg, offset), value_reg); | |
| 687 | 679 |
| 688 if (!representation.IsSmi()) { | 680 if (!representation.IsSmi()) { |
| 689 // Update the write barrier for the array address. | 681 // Update the write barrier for the array address. |
| 690 // Pass the value being stored in the now unused name_reg. | 682 // Pass the value being stored in the now unused name_reg. |
| 691 __ movp(name_reg, value_reg); | 683 __ movp(name_reg, value_reg); |
| 692 __ RecordWriteField( | 684 __ RecordWriteField( |
| 693 receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs, | 685 receiver_reg, index.offset(), name_reg, scratch1, kDontSaveFPRegs, |
| 694 EMIT_REMEMBERED_SET, smi_check); | 686 EMIT_REMEMBERED_SET, smi_check); |
| 695 } | 687 } |
| 696 } else { | 688 } else { |
| 697 // Write to the properties array. | 689 // Write to the properties array. |
| 698 int offset = index * kPointerSize + FixedArray::kHeaderSize; | |
| 699 // Get the properties array (optimistically). | 690 // Get the properties array (optimistically). |
| 700 __ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 691 __ movp(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 701 __ movp(FieldOperand(scratch1, offset), value_reg); | 692 __ movp(FieldOperand(scratch1, index.offset()), value_reg); |
| 702 | 693 |
| 703 if (!representation.IsSmi()) { | 694 if (!representation.IsSmi()) { |
| 704 // Update the write barrier for the array address. | 695 // Update the write barrier for the array address. |
| 705 // Pass the value being stored in the now unused name_reg. | 696 // Pass the value being stored in the now unused name_reg. |
| 706 __ movp(name_reg, value_reg); | 697 __ movp(name_reg, value_reg); |
| 707 __ RecordWriteField( | 698 __ RecordWriteField( |
| 708 scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs, | 699 scratch1, index.offset(), name_reg, receiver_reg, kDontSaveFPRegs, |
| 709 EMIT_REMEMBERED_SET, smi_check); | 700 EMIT_REMEMBERED_SET, smi_check); |
| 710 } | 701 } |
| 711 } | 702 } |
| 712 | 703 |
| 713 // Return the value (register rax). | 704 // Return the value (register rax). |
| 714 ASSERT(value_reg.is(rax)); | 705 ASSERT(value_reg.is(rax)); |
| 715 __ ret(0); | 706 __ ret(0); |
| 716 } | 707 } |
| 717 | 708 |
| 718 | 709 |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 906 __ j(not_equal, &miss); | 897 __ j(not_equal, &miss); |
| 907 } | 898 } |
| 908 | 899 |
| 909 HandlerFrontendFooter(name, &miss); | 900 HandlerFrontendFooter(name, &miss); |
| 910 return reg; | 901 return reg; |
| 911 } | 902 } |
| 912 | 903 |
| 913 | 904 |
| 914 void LoadStubCompiler::GenerateLoadField(Register reg, | 905 void LoadStubCompiler::GenerateLoadField(Register reg, |
| 915 Handle<JSObject> holder, | 906 Handle<JSObject> holder, |
| 916 PropertyIndex field, | 907 FieldIndex field, |
| 917 Representation representation) { | 908 Representation representation) { |
| 918 if (!reg.is(receiver())) __ movp(receiver(), reg); | 909 if (!reg.is(receiver())) __ movp(receiver(), reg); |
| 919 if (kind() == Code::LOAD_IC) { | 910 if (kind() == Code::LOAD_IC) { |
| 920 LoadFieldStub stub(isolate(), | 911 LoadFieldStub stub(isolate(), field); |
| 921 field.is_inobject(holder), | |
| 922 field.translate(holder), | |
| 923 representation); | |
| 924 GenerateTailCall(masm(), stub.GetCode()); | 912 GenerateTailCall(masm(), stub.GetCode()); |
| 925 } else { | 913 } else { |
| 926 KeyedLoadFieldStub stub(isolate(), | 914 KeyedLoadFieldStub stub(isolate(), field); |
| 927 field.is_inobject(holder), | |
| 928 field.translate(holder), | |
| 929 representation); | |
| 930 GenerateTailCall(masm(), stub.GetCode()); | 915 GenerateTailCall(masm(), stub.GetCode()); |
| 931 } | 916 } |
| 932 } | 917 } |
| 933 | 918 |
| 934 | 919 |
| 935 void LoadStubCompiler::GenerateLoadCallback( | 920 void LoadStubCompiler::GenerateLoadCallback( |
| 936 Register reg, | 921 Register reg, |
| 937 Handle<ExecutableAccessorInfo> callback) { | 922 Handle<ExecutableAccessorInfo> callback) { |
| 938 // Insert additional parameters into the stack frame above return address. | 923 // Insert additional parameters into the stack frame above return address. |
| 939 ASSERT(!scratch4().is(reg)); | 924 ASSERT(!scratch4().is(reg)); |
| (...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1442 // ----------------------------------- | 1427 // ----------------------------------- |
| 1443 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1428 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 1444 } | 1429 } |
| 1445 | 1430 |
| 1446 | 1431 |
| 1447 #undef __ | 1432 #undef __ |
| 1448 | 1433 |
| 1449 } } // namespace v8::internal | 1434 } } // namespace v8::internal |
| 1450 | 1435 |
| 1451 #endif // V8_TARGET_ARCH_X64 | 1436 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |