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 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
746 Label* miss_restore_name) { | 746 Label* miss_restore_name) { |
747 // Check that the map of the object hasn't changed. | 747 // Check that the map of the object hasn't changed. |
748 __ CheckMap(receiver_reg, Handle<Map>(object->map()), | 748 __ CheckMap(receiver_reg, Handle<Map>(object->map()), |
749 miss_label, DO_SMI_CHECK, REQUIRE_EXACT_MAP); | 749 miss_label, DO_SMI_CHECK, REQUIRE_EXACT_MAP); |
750 | 750 |
751 // Perform global security token check if needed. | 751 // Perform global security token check if needed. |
752 if (object->IsJSGlobalProxy()) { | 752 if (object->IsJSGlobalProxy()) { |
753 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); | 753 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); |
754 } | 754 } |
755 | 755 |
| 756 int descriptor = transition->LastAdded(); |
| 757 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 758 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 759 Representation representation = details.representation(); |
| 760 ASSERT(!representation.IsNone()); |
| 761 |
| 762 // Ensure no transitions to deprecated maps are followed. |
| 763 __ CheckMapDeprecated(transition, scratch1, miss_label); |
| 764 |
| 765 if (FLAG_track_fields && representation.IsSmi()) { |
| 766 __ JumpIfNotSmi(value_reg, miss_label); |
| 767 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
| 768 Label do_store; |
| 769 __ JumpIfSmi(value_reg, &do_store); |
| 770 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
| 771 miss_label, DONT_DO_SMI_CHECK, REQUIRE_EXACT_MAP); |
| 772 __ bind(&do_store); |
| 773 } |
| 774 |
756 // Check that we are allowed to write this. | 775 // Check that we are allowed to write this. |
757 if (object->GetPrototype()->IsJSObject()) { | 776 if (object->GetPrototype()->IsJSObject()) { |
758 JSObject* holder; | 777 JSObject* holder; |
759 // holder == object indicates that no property was found. | 778 // holder == object indicates that no property was found. |
760 if (lookup->holder() != *object) { | 779 if (lookup->holder() != *object) { |
761 holder = lookup->holder(); | 780 holder = lookup->holder(); |
762 } else { | 781 } else { |
763 // Find the top object. | 782 // Find the top object. |
764 holder = *object; | 783 holder = *object; |
765 do { | 784 do { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 // 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 |
830 // 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. |
831 index -= object->map()->inobject_properties(); | 850 index -= object->map()->inobject_properties(); |
832 | 851 |
833 // TODO(verwaest): Share this code as a code stub. | 852 // TODO(verwaest): Share this code as a code stub. |
834 if (index < 0) { | 853 if (index < 0) { |
835 // Set the property straight into the object. | 854 // Set the property straight into the object. |
836 int offset = object->map()->instance_size() + (index * kPointerSize); | 855 int offset = object->map()->instance_size() + (index * kPointerSize); |
837 __ movq(FieldOperand(receiver_reg, offset), value_reg); | 856 __ movq(FieldOperand(receiver_reg, offset), value_reg); |
838 | 857 |
839 // Update the write barrier for the array address. | 858 if (!FLAG_track_fields || !representation.IsSmi()) { |
840 // Pass the value being stored in the now unused name_reg. | 859 // Update the write barrier for the array address. |
841 __ movq(name_reg, value_reg); | 860 // Pass the value being stored in the now unused name_reg. |
842 __ RecordWriteField( | 861 __ movq(name_reg, value_reg); |
843 receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs); | 862 __ RecordWriteField( |
| 863 receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs); |
| 864 } |
844 } else { | 865 } else { |
845 // Write to the properties array. | 866 // Write to the properties array. |
846 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 867 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
847 // Get the properties array (optimistically). | 868 // Get the properties array (optimistically). |
848 __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 869 __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
849 __ movq(FieldOperand(scratch1, offset), value_reg); | 870 __ movq(FieldOperand(scratch1, offset), value_reg); |
850 | 871 |
851 // Update the write barrier for the array address. | 872 if (!FLAG_track_fields || !representation.IsSmi()) { |
852 // Pass the value being stored in the now unused name_reg. | 873 // Update the write barrier for the array address. |
853 __ movq(name_reg, value_reg); | 874 // Pass the value being stored in the now unused name_reg. |
854 __ RecordWriteField( | 875 __ movq(name_reg, value_reg); |
855 scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs); | 876 __ RecordWriteField( |
| 877 scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs); |
| 878 } |
856 } | 879 } |
857 | 880 |
858 // Return the value (register rax). | 881 // Return the value (register rax). |
859 ASSERT(value_reg.is(rax)); | 882 ASSERT(value_reg.is(rax)); |
860 __ ret(0); | 883 __ ret(0); |
861 } | 884 } |
862 | 885 |
863 | 886 |
864 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 887 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
865 // but may be destroyed if store is successful. | 888 // but may be destroyed if store is successful. |
(...skipping 19 matching lines...) Expand all Loading... |
885 // checks. | 908 // checks. |
886 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 909 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
887 | 910 |
888 int index = lookup->GetFieldIndex().field_index(); | 911 int index = lookup->GetFieldIndex().field_index(); |
889 | 912 |
890 // Adjust for the number of properties stored in the object. Even in the | 913 // Adjust for the number of properties stored in the object. Even in the |
891 // face of a transition we can use the old map here because the size of the | 914 // face of a transition we can use the old map here because the size of the |
892 // object and the number of in-object properties is not going to change. | 915 // object and the number of in-object properties is not going to change. |
893 index -= object->map()->inobject_properties(); | 916 index -= object->map()->inobject_properties(); |
894 | 917 |
| 918 Representation representation = lookup->GetPropertyDetails().representation(); |
| 919 ASSERT(!representation.IsNone()); |
| 920 if (FLAG_track_fields && representation.IsSmi()) { |
| 921 __ JumpIfNotSmi(value_reg, miss_label); |
| 922 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
| 923 Label do_store; |
| 924 __ JumpIfSmi(value_reg, &do_store); |
| 925 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
| 926 miss_label, DONT_DO_SMI_CHECK, REQUIRE_EXACT_MAP); |
| 927 __ bind(&do_store); |
| 928 } |
| 929 |
895 // TODO(verwaest): Share this code as a code stub. | 930 // TODO(verwaest): Share this code as a code stub. |
896 if (index < 0) { | 931 if (index < 0) { |
897 // Set the property straight into the object. | 932 // Set the property straight into the object. |
898 int offset = object->map()->instance_size() + (index * kPointerSize); | 933 int offset = object->map()->instance_size() + (index * kPointerSize); |
899 __ movq(FieldOperand(receiver_reg, offset), value_reg); | 934 __ movq(FieldOperand(receiver_reg, offset), value_reg); |
900 | 935 |
901 // Update the write barrier for the array address. | 936 if (!FLAG_track_fields || !representation.IsSmi()) { |
902 // Pass the value being stored in the now unused name_reg. | 937 // Update the write barrier for the array address. |
903 __ movq(name_reg, value_reg); | 938 // Pass the value being stored in the now unused name_reg. |
904 __ RecordWriteField( | 939 __ movq(name_reg, value_reg); |
905 receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs); | 940 __ RecordWriteField( |
| 941 receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs); |
| 942 } |
906 } else { | 943 } else { |
907 // Write to the properties array. | 944 // Write to the properties array. |
908 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 945 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
909 // Get the properties array (optimistically). | 946 // Get the properties array (optimistically). |
910 __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 947 __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
911 __ movq(FieldOperand(scratch1, offset), value_reg); | 948 __ movq(FieldOperand(scratch1, offset), value_reg); |
912 | 949 |
913 // Update the write barrier for the array address. | 950 if (!FLAG_track_fields || !representation.IsSmi()) { |
914 // Pass the value being stored in the now unused name_reg. | 951 // Update the write barrier for the array address. |
915 __ movq(name_reg, value_reg); | 952 // Pass the value being stored in the now unused name_reg. |
916 __ RecordWriteField( | 953 __ movq(name_reg, value_reg); |
917 scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs); | 954 __ RecordWriteField( |
| 955 scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs); |
| 956 } |
918 } | 957 } |
919 | 958 |
920 // Return the value (register rax). | 959 // Return the value (register rax). |
921 ASSERT(value_reg.is(rax)); | 960 ASSERT(value_reg.is(rax)); |
922 __ ret(0); | 961 __ ret(0); |
923 } | 962 } |
924 | 963 |
925 | 964 |
926 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 965 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
927 // from object to (but not including) holder. | 966 // from object to (but not including) holder. |
(...skipping 1864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2792 Label miss; | 2831 Label miss; |
2793 | 2832 |
2794 if (check == PROPERTY) { | 2833 if (check == PROPERTY) { |
2795 GenerateNameCheck(name, this->name(), &miss); | 2834 GenerateNameCheck(name, this->name(), &miss); |
2796 } | 2835 } |
2797 | 2836 |
2798 __ JumpIfSmi(receiver(), &miss); | 2837 __ JumpIfSmi(receiver(), &miss); |
2799 Register map_reg = scratch1(); | 2838 Register map_reg = scratch1(); |
2800 __ movq(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); | 2839 __ movq(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); |
2801 int receiver_count = receiver_maps->length(); | 2840 int receiver_count = receiver_maps->length(); |
| 2841 int number_of_handled_maps = 0; |
2802 for (int current = 0; current < receiver_count; ++current) { | 2842 for (int current = 0; current < receiver_count; ++current) { |
2803 // Check map and tail call if there's a match | 2843 Handle<Map> map = receiver_maps->at(current); |
2804 __ Cmp(map_reg, receiver_maps->at(current)); | 2844 if (!map->is_deprecated()) { |
2805 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET); | 2845 number_of_handled_maps++; |
| 2846 // Check map and tail call if there's a match |
| 2847 __ Cmp(map_reg, receiver_maps->at(current)); |
| 2848 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET); |
| 2849 } |
2806 } | 2850 } |
| 2851 ASSERT(number_of_handled_maps > 0); |
2807 | 2852 |
2808 __ bind(&miss); | 2853 __ bind(&miss); |
2809 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2854 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2810 | 2855 |
2811 // Return the generated code. | 2856 // Return the generated code. |
2812 InlineCacheState state = | 2857 InlineCacheState state = |
2813 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; | 2858 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |
2814 return GetICCode(kind(), type, name, state); | 2859 return GetICCode(kind(), type, name, state); |
2815 } | 2860 } |
2816 | 2861 |
2817 | 2862 |
2818 // Specialized stub for constructing objects from functions which only have only | 2863 // Specialized stub for constructing objects from functions which only have only |
2819 // simple assignments of the form this.x = ...; in their body. | 2864 // simple assignments of the form this.x = ...; in their body. |
2820 Handle<Code> ConstructStubCompiler::CompileConstructStub( | 2865 Handle<Code> ConstructStubCompiler::CompileConstructStub( |
2821 Handle<JSFunction> function) { | 2866 Handle<JSFunction> function) { |
2822 // ----------- S t a t e ------------- | 2867 // ----------- S t a t e ------------- |
2823 // -- rax : argc | 2868 // -- rax : argc |
(...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3470 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); | 3515 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3471 } | 3516 } |
3472 } | 3517 } |
3473 | 3518 |
3474 | 3519 |
3475 #undef __ | 3520 #undef __ |
3476 | 3521 |
3477 } } // namespace v8::internal | 3522 } } // namespace v8::internal |
3478 | 3523 |
3479 #endif // V8_TARGET_ARCH_X64 | 3524 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |