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 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 __ bind(label); | 709 __ bind(label); |
710 __ Move(this->name(), name); | 710 __ Move(this->name(), name); |
711 } | 711 } |
712 } | 712 } |
713 | 713 |
714 | 714 |
715 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 715 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
716 // but may be destroyed if store is successful. | 716 // but may be destroyed if store is successful. |
717 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 717 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
718 Handle<JSObject> object, | 718 Handle<JSObject> object, |
719 int index, | 719 LookupResult* lookup, |
720 Handle<Map> transition, | 720 Handle<Map> transition, |
721 Handle<Name> name, | 721 Handle<Name> name, |
722 Register receiver_reg, | 722 Register receiver_reg, |
723 Register name_reg, | 723 Register name_reg, |
724 Register value_reg, | 724 Register value_reg, |
725 Register scratch1, | 725 Register scratch1, |
726 Register scratch2, | 726 Register scratch2, |
727 Label* miss_label, | 727 Label* miss_label, |
728 Label* miss_restore_name) { | 728 Label* miss_restore_name) { |
729 LookupResult lookup(masm->isolate()); | |
730 object->Lookup(*name, &lookup); | |
731 if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) { | |
732 // In sloppy mode, we could just return the value and be done. However, we | |
733 // might be in strict mode, where we have to throw. Since we cannot tell, | |
734 // go into slow case unconditionally. | |
735 __ jmp(miss_label); | |
736 return; | |
737 } | |
738 | |
739 // Check that the map of the object hasn't changed. | 729 // Check that the map of the object hasn't changed. |
740 CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS | 730 CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS |
741 : REQUIRE_EXACT_MAP; | 731 : REQUIRE_EXACT_MAP; |
742 __ CheckMap(receiver_reg, Handle<Map>(object->map()), | 732 __ CheckMap(receiver_reg, Handle<Map>(object->map()), |
743 miss_label, DO_SMI_CHECK, mode); | 733 miss_label, DO_SMI_CHECK, mode); |
744 | 734 |
745 // Perform global security token check if needed. | 735 // Perform global security token check if needed. |
746 if (object->IsJSGlobalProxy()) { | 736 if (object->IsJSGlobalProxy()) { |
747 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); | 737 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); |
748 } | 738 } |
749 | 739 |
750 // Check that we are allowed to write this. | 740 // Check that we are allowed to write this. |
751 if (!transition.is_null() && object->GetPrototype()->IsJSObject()) { | 741 if (!transition.is_null() && object->GetPrototype()->IsJSObject()) { |
752 JSObject* holder; | 742 JSObject* holder; |
753 if (lookup.IsFound()) { | 743 if (lookup->IsFound()) { |
754 holder = lookup.holder(); | 744 holder = lookup->holder(); |
755 } else { | 745 } else { |
756 // Find the top object. | 746 // Find the top object. |
757 holder = *object; | 747 holder = *object; |
758 do { | 748 do { |
759 holder = JSObject::cast(holder->GetPrototype()); | 749 holder = JSObject::cast(holder->GetPrototype()); |
760 } while (holder->GetPrototype()->IsJSObject()); | 750 } while (holder->GetPrototype()->IsJSObject()); |
761 } | 751 } |
762 CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, | 752 CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, |
763 scratch1, scratch2, name, miss_restore_name); | 753 scratch1, scratch2, name, miss_restore_name); |
764 } | 754 } |
(...skipping 12 matching lines...) Expand all Loading... |
777 __ push(value_reg); | 767 __ push(value_reg); |
778 __ push(scratch1); | 768 __ push(scratch1); |
779 __ TailCallExternalReference( | 769 __ TailCallExternalReference( |
780 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 770 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
781 masm->isolate()), | 771 masm->isolate()), |
782 3, | 772 3, |
783 1); | 773 1); |
784 return; | 774 return; |
785 } | 775 } |
786 | 776 |
| 777 int index; |
787 if (!transition.is_null()) { | 778 if (!transition.is_null()) { |
788 // Update the map of the object. | 779 // Update the map of the object. |
789 __ Move(scratch1, transition); | 780 __ Move(scratch1, transition); |
790 __ movq(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); | 781 __ movq(FieldOperand(receiver_reg, HeapObject::kMapOffset), scratch1); |
791 | 782 |
792 // Update the write barrier for the map field and pass the now unused | 783 // Update the write barrier for the map field and pass the now unused |
793 // name_reg as scratch register. | 784 // name_reg as scratch register. |
794 __ RecordWriteField(receiver_reg, | 785 __ RecordWriteField(receiver_reg, |
795 HeapObject::kMapOffset, | 786 HeapObject::kMapOffset, |
796 scratch1, | 787 scratch1, |
797 name_reg, | 788 name_reg, |
798 kDontSaveFPRegs, | 789 kDontSaveFPRegs, |
799 OMIT_REMEMBERED_SET, | 790 OMIT_REMEMBERED_SET, |
800 OMIT_SMI_CHECK); | 791 OMIT_SMI_CHECK); |
| 792 index = transition->instance_descriptors()->GetFieldIndex( |
| 793 transition->LastAdded()); |
| 794 } else { |
| 795 index = lookup->GetFieldIndex().field_index(); |
801 } | 796 } |
802 | 797 |
803 // Adjust for the number of properties stored in the object. Even in the | 798 // Adjust for the number of properties stored in the object. Even in the |
804 // face of a transition we can use the old map here because the size of the | 799 // face of a transition we can use the old map here because the size of the |
805 // object and the number of in-object properties is not going to change. | 800 // object and the number of in-object properties is not going to change. |
806 index -= object->map()->inobject_properties(); | 801 index -= object->map()->inobject_properties(); |
807 | 802 |
808 if (index < 0) { | 803 if (index < 0) { |
809 // Set the property straight into the object. | 804 // Set the property straight into the object. |
810 int offset = object->map()->instance_size() + (index * kPointerSize); | 805 int offset = object->map()->instance_size() + (index * kPointerSize); |
(...skipping 2590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3401 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); | 3396 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3402 } | 3397 } |
3403 } | 3398 } |
3404 | 3399 |
3405 | 3400 |
3406 #undef __ | 3401 #undef __ |
3407 | 3402 |
3408 } } // namespace v8::internal | 3403 } } // namespace v8::internal |
3409 | 3404 |
3410 #endif // V8_TARGET_ARCH_X64 | 3405 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |