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