Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1448)

Side by Side Diff: src/ia32/stub-cache-ia32.cc

Issue 14063006: Disentangle field from transition stores. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/stub-cache-arm.cc ('k') | src/ic.cc » ('j') | src/stub-cache.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698