| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 Immediate(the_hole)); | 744 Immediate(the_hole)); |
| 745 } else { | 745 } else { |
| 746 __ cmp(Operand::Cell(cell), Immediate(the_hole)); | 746 __ cmp(Operand::Cell(cell), Immediate(the_hole)); |
| 747 } | 747 } |
| 748 __ j(not_equal, miss); | 748 __ j(not_equal, miss); |
| 749 } | 749 } |
| 750 | 750 |
| 751 | 751 |
| 752 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 752 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 753 // but may be destroyed if store is successful. | 753 // but may be destroyed if store is successful. |
| 754 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 754 void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
| 755 Handle<JSObject> object, | 755 Handle<JSObject> object, |
| 756 LookupResult* lookup, | 756 LookupResult* lookup, |
| 757 Handle<Map> transition, | 757 Handle<Map> transition, |
| 758 Handle<Name> name, | 758 Handle<Name> name, |
| 759 Register receiver_reg, | 759 Register receiver_reg, |
| 760 Register name_reg, | 760 Register name_reg, |
| 761 Register value_reg, | 761 Register value_reg, |
| 762 Register scratch1, | 762 Register scratch1, |
| 763 Register scratch2, | 763 Register scratch2, |
| 764 Label* miss_label, | 764 Label* miss_label, |
| 765 Label* miss_restore_name) { | 765 Label* miss_restore_name) { |
| 766 // Check that the map of the object hasn't changed. | 766 // Check that the map of the object hasn't changed. |
| 767 CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS | |
| 768 : REQUIRE_EXACT_MAP; | |
| 769 __ CheckMap(receiver_reg, Handle<Map>(object->map()), | 767 __ CheckMap(receiver_reg, Handle<Map>(object->map()), |
| 770 miss_label, DO_SMI_CHECK, mode); | 768 miss_label, DO_SMI_CHECK, REQUIRE_EXACT_MAP); |
| 771 | 769 |
| 772 // Perform global security token check if needed. | 770 // Perform global security token check if needed. |
| 773 if (object->IsJSGlobalProxy()) { | 771 if (object->IsJSGlobalProxy()) { |
| 774 __ CheckAccessGlobalProxy(receiver_reg, scratch1, scratch2, miss_label); | 772 __ CheckAccessGlobalProxy(receiver_reg, scratch1, scratch2, miss_label); |
| 775 } | 773 } |
| 776 | 774 |
| 777 // Check that we are allowed to write this. | 775 // Check that we are allowed to write this. |
| 778 if (!transition.is_null() && object->GetPrototype()->IsJSObject()) { | 776 if (object->GetPrototype()->IsJSObject()) { |
| 779 JSObject* holder; | 777 JSObject* holder; |
| 780 // holder == object indicates that no property was found. | 778 // holder == object indicates that no property was found. |
| 781 if (lookup->holder() != *object) { | 779 if (lookup->holder() != *object) { |
| 782 holder = lookup->holder(); | 780 holder = lookup->holder(); |
| 783 } else { | 781 } else { |
| 784 // Find the top object. | 782 // Find the top object. |
| 785 holder = *object; | 783 holder = *object; |
| 786 do { | 784 do { |
| 787 holder = JSObject::cast(holder->GetPrototype()); | 785 holder = JSObject::cast(holder->GetPrototype()); |
| 788 } while (holder->GetPrototype()->IsJSObject()); | 786 } while (holder->GetPrototype()->IsJSObject()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 807 masm, miss_restore_name, holder_reg, name, scratch1, scratch2); | 805 masm, miss_restore_name, holder_reg, name, scratch1, scratch2); |
| 808 } | 806 } |
| 809 } | 807 } |
| 810 } | 808 } |
| 811 | 809 |
| 812 // Stub never generated for non-global objects that require access | 810 // Stub never generated for non-global objects that require access |
| 813 // checks. | 811 // checks. |
| 814 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 812 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 815 | 813 |
| 816 // Perform map transition for the receiver if necessary. | 814 // Perform map transition for the receiver if necessary. |
| 817 if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { | 815 if (object->map()->unused_property_fields() == 0) { |
| 818 // The properties must be extended before we can store the value. | 816 // The properties must be extended before we can store the value. |
| 819 // We jump to a runtime call that extends the properties array. | 817 // We jump to a runtime call that extends the properties array. |
| 820 __ pop(scratch1); // Return address. | 818 __ pop(scratch1); // Return address. |
| 821 __ push(receiver_reg); | 819 __ push(receiver_reg); |
| 822 __ push(Immediate(transition)); | 820 __ push(Immediate(transition)); |
| 823 __ push(eax); | 821 __ push(eax); |
| 824 __ push(scratch1); | 822 __ push(scratch1); |
| 825 __ TailCallExternalReference( | 823 __ TailCallExternalReference( |
| 826 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 824 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
| 827 masm->isolate()), | 825 masm->isolate()), |
| 828 3, | 826 3, |
| 829 1); | 827 1); |
| 830 return; | 828 return; |
| 831 } | 829 } |
| 832 | 830 |
| 833 int index; | 831 // Update the map of the object. |
| 834 if (!transition.is_null()) { | 832 __ mov(scratch1, Immediate(transition)); |
| 835 // Update the map of the object. | 833 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); |
| 836 __ mov(scratch1, Immediate(transition)); | |
| 837 __ mov(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); | |
| 838 | 834 |
| 839 // Update the write barrier for the map field and pass the now unused | 835 // Update the write barrier for the map field and pass the now unused |
| 840 // name_reg as scratch register. | 836 // name_reg as scratch register. |
| 841 __ RecordWriteField(receiver_reg, | 837 __ RecordWriteField(receiver_reg, |
| 842 HeapObject::kMapOffset, | 838 HeapObject::kMapOffset, |
| 843 scratch1, | 839 scratch1, |
| 844 name_reg, | 840 name_reg, |
| 845 kDontSaveFPRegs, | 841 kDontSaveFPRegs, |
| 846 OMIT_REMEMBERED_SET, | 842 OMIT_REMEMBERED_SET, |
| 847 OMIT_SMI_CHECK); | 843 OMIT_SMI_CHECK); |
| 848 index = transition->instance_descriptors()->GetFieldIndex( | 844 int index = transition->instance_descriptors()->GetFieldIndex( |
| 849 transition->LastAdded()); | 845 transition->LastAdded()); |
| 850 } else { | |
| 851 index = lookup->GetFieldIndex().field_index(); | |
| 852 } | |
| 853 | |
| 854 | 846 |
| 855 // Adjust for the number of properties stored in the object. Even in the | 847 // Adjust for the number of properties stored in the object. Even in the |
| 856 // face of a transition we can use the old map here because the size of the | 848 // face of a transition we can use the old map here because the size of the |
| 857 // object and the number of in-object properties is not going to change. | 849 // object and the number of in-object properties is not going to change. |
| 858 index -= object->map()->inobject_properties(); | 850 index -= object->map()->inobject_properties(); |
| 859 | 851 |
| 852 // TODO(verwaest): Share this code as a code stub. |
| 860 if (index < 0) { | 853 if (index < 0) { |
| 861 // Set the property straight into the object. | 854 // Set the property straight into the object. |
| 862 int offset = object->map()->instance_size() + (index * kPointerSize); | 855 int offset = object->map()->instance_size() + (index * kPointerSize); |
| 856 __ mov(FieldOperand(receiver_reg, offset), value_reg); |
| 857 |
| 858 // Update the write barrier for the array address. |
| 859 // Pass the value being stored in the now unused name_reg. |
| 860 __ mov(name_reg, value_reg); |
| 861 __ RecordWriteField(receiver_reg, |
| 862 offset, |
| 863 name_reg, |
| 864 scratch1, |
| 865 kDontSaveFPRegs); |
| 866 } else { |
| 867 // Write to the properties array. |
| 868 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 869 // Get the properties array (optimistically). |
| 870 __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 871 __ mov(FieldOperand(scratch1, offset), eax); |
| 872 |
| 873 // Update the write barrier for the array address. |
| 874 // Pass the value being stored in the now unused name_reg. |
| 875 __ mov(name_reg, value_reg); |
| 876 __ RecordWriteField(scratch1, |
| 877 offset, |
| 878 name_reg, |
| 879 receiver_reg, |
| 880 kDontSaveFPRegs); |
| 881 } |
| 882 |
| 883 // Return the value (register eax). |
| 884 ASSERT(value_reg.is(eax)); |
| 885 __ ret(0); |
| 886 } |
| 887 |
| 888 |
| 889 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 890 // but may be destroyed if store is successful. |
| 891 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 892 Handle<JSObject> object, |
| 893 LookupResult* lookup, |
| 894 Register receiver_reg, |
| 895 Register name_reg, |
| 896 Register value_reg, |
| 897 Register scratch1, |
| 898 Register scratch2, |
| 899 Label* miss_label) { |
| 900 // Check that the map of the object hasn't changed. |
| 901 __ CheckMap(receiver_reg, Handle<Map>(object->map()), |
| 902 miss_label, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
| 903 |
| 904 // Perform global security token check if needed. |
| 905 if (object->IsJSGlobalProxy()) { |
| 906 __ CheckAccessGlobalProxy(receiver_reg, scratch1, scratch2, miss_label); |
| 907 } |
| 908 |
| 909 // Stub never generated for non-global objects that require access |
| 910 // checks. |
| 911 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 912 |
| 913 int index = lookup->GetFieldIndex().field_index(); |
| 914 |
| 915 // Adjust for the number of properties stored in the object. Even in the |
| 916 // face of a transition we can use the old map here because the size of the |
| 917 // object and the number of in-object properties is not going to change. |
| 918 index -= object->map()->inobject_properties(); |
| 919 |
| 920 // TODO(verwaest): Share this code as a code stub. |
| 921 if (index < 0) { |
| 922 // Set the property straight into the object. |
| 923 int offset = object->map()->instance_size() + (index * kPointerSize); |
| 863 __ mov(FieldOperand(receiver_reg, offset), value_reg); | 924 __ mov(FieldOperand(receiver_reg, offset), value_reg); |
| 864 | 925 |
| 865 // Update the write barrier for the array address. | 926 // Update the write barrier for the array address. |
| 866 // Pass the value being stored in the now unused name_reg. | 927 // Pass the value being stored in the now unused name_reg. |
| 867 __ mov(name_reg, value_reg); | 928 __ mov(name_reg, value_reg); |
| 868 __ RecordWriteField(receiver_reg, | 929 __ RecordWriteField(receiver_reg, |
| 869 offset, | 930 offset, |
| 870 name_reg, | 931 name_reg, |
| 871 scratch1, | 932 scratch1, |
| 872 kDontSaveFPRegs); | 933 kDontSaveFPRegs); |
| (...skipping 2755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3628 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); | 3689 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
| 3629 } | 3690 } |
| 3630 } | 3691 } |
| 3631 | 3692 |
| 3632 | 3693 |
| 3633 #undef __ | 3694 #undef __ |
| 3634 | 3695 |
| 3635 } } // namespace v8::internal | 3696 } } // namespace v8::internal |
| 3636 | 3697 |
| 3637 #endif // V8_TARGET_ARCH_IA32 | 3698 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |