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 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 __ CheckMap(receiver_reg, Handle<Map>(object->map()), | 767 __ CheckMap(receiver_reg, Handle<Map>(object->map()), |
768 miss_label, DO_SMI_CHECK, REQUIRE_EXACT_MAP); | 768 miss_label, DO_SMI_CHECK, REQUIRE_EXACT_MAP); |
769 | 769 |
770 // Perform global security token check if needed. | 770 // Perform global security token check if needed. |
771 if (object->IsJSGlobalProxy()) { | 771 if (object->IsJSGlobalProxy()) { |
772 __ CheckAccessGlobalProxy(receiver_reg, scratch1, scratch2, miss_label); | 772 __ CheckAccessGlobalProxy(receiver_reg, scratch1, scratch2, miss_label); |
773 } | 773 } |
774 | 774 |
775 int descriptor = transition->LastAdded(); | |
776 DescriptorArray* descriptors = transition->instance_descriptors(); | |
777 PropertyDetails details = descriptors->GetDetails(descriptor); | |
778 Representation representation = details.representation(); | |
779 ASSERT(!representation.IsNone()); | |
780 | |
781 // Unless we are in the most general state, check whether the map is still a | |
782 // valid transition. | |
783 if (transition->CanTransitionBeInvalidated()) { | |
784 __ mov(scratch1, transition); | |
danno
2013/04/24 15:23:00
Perhaps create a macro-assembler function for this
Toon Verwaest
2013/04/25 14:49:10
Done.
| |
785 __ mov(scratch1, FieldOperand(scratch1, Map::kBitField3Offset)); | |
786 __ and_(scratch1, Immediate(Smi::FromInt(Map::InvalidTransition::kMask))); | |
787 __ j(not_zero, miss_label); | |
788 } | |
789 | |
790 if (FLAG_track_fields && representation.IsSmi()) { | |
791 __ JumpIfNotSmi(value_reg, miss_label); | |
792 } else if (FLAG_track_double_fields && representation.IsDouble()) { | |
793 Label do_store; | |
794 __ JumpIfSmi(value_reg, &do_store); | |
795 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | |
796 miss_label, DONT_DO_SMI_CHECK, REQUIRE_EXACT_MAP); | |
797 __ bind(&do_store); | |
798 } | |
799 | |
775 // Check that we are allowed to write this. | 800 // Check that we are allowed to write this. |
776 if (object->GetPrototype()->IsJSObject()) { | 801 if (object->GetPrototype()->IsJSObject()) { |
777 JSObject* holder; | 802 JSObject* holder; |
778 // holder == object indicates that no property was found. | 803 // holder == object indicates that no property was found. |
779 if (lookup->holder() != *object) { | 804 if (lookup->holder() != *object) { |
780 holder = lookup->holder(); | 805 holder = lookup->holder(); |
781 } else { | 806 } else { |
782 // Find the top object. | 807 // Find the top object. |
783 holder = *object; | 808 holder = *object; |
784 do { | 809 do { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
849 // face of a transition we can use the old map here because the size of the | 874 // face of a transition we can use the old map here because the size of the |
850 // object and the number of in-object properties is not going to change. | 875 // object and the number of in-object properties is not going to change. |
851 index -= object->map()->inobject_properties(); | 876 index -= object->map()->inobject_properties(); |
852 | 877 |
853 // TODO(verwaest): Share this code as a code stub. | 878 // TODO(verwaest): Share this code as a code stub. |
854 if (index < 0) { | 879 if (index < 0) { |
855 // Set the property straight into the object. | 880 // Set the property straight into the object. |
856 int offset = object->map()->instance_size() + (index * kPointerSize); | 881 int offset = object->map()->instance_size() + (index * kPointerSize); |
857 __ mov(FieldOperand(receiver_reg, offset), value_reg); | 882 __ mov(FieldOperand(receiver_reg, offset), value_reg); |
858 | 883 |
859 // Update the write barrier for the array address. | 884 if (!FLAG_track_fields || !representation.IsSmi()) { |
860 // Pass the value being stored in the now unused name_reg. | 885 // Update the write barrier for the array address. |
861 __ mov(name_reg, value_reg); | 886 // Pass the value being stored in the now unused name_reg. |
862 __ RecordWriteField(receiver_reg, | 887 __ mov(name_reg, value_reg); |
863 offset, | 888 __ RecordWriteField(receiver_reg, |
864 name_reg, | 889 offset, |
865 scratch1, | 890 name_reg, |
866 kDontSaveFPRegs); | 891 scratch1, |
892 kDontSaveFPRegs); | |
893 } | |
867 } else { | 894 } else { |
868 // Write to the properties array. | 895 // Write to the properties array. |
869 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 896 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
870 // Get the properties array (optimistically). | 897 // Get the properties array (optimistically). |
871 __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 898 __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
872 __ mov(FieldOperand(scratch1, offset), eax); | 899 __ mov(FieldOperand(scratch1, offset), eax); |
873 | 900 |
874 // Update the write barrier for the array address. | 901 if (!FLAG_track_fields || !representation.IsSmi()) { |
875 // Pass the value being stored in the now unused name_reg. | 902 // Update the write barrier for the array address. |
876 __ mov(name_reg, value_reg); | 903 // Pass the value being stored in the now unused name_reg. |
877 __ RecordWriteField(scratch1, | 904 __ mov(name_reg, value_reg); |
878 offset, | 905 __ RecordWriteField(scratch1, |
879 name_reg, | 906 offset, |
880 receiver_reg, | 907 name_reg, |
881 kDontSaveFPRegs); | 908 receiver_reg, |
909 kDontSaveFPRegs); | |
910 } | |
882 } | 911 } |
883 | 912 |
884 // Return the value (register eax). | 913 // Return the value (register eax). |
885 ASSERT(value_reg.is(eax)); | 914 ASSERT(value_reg.is(eax)); |
886 __ ret(0); | 915 __ ret(0); |
887 } | 916 } |
888 | 917 |
889 | 918 |
890 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 919 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
891 // but may be destroyed if store is successful. | 920 // but may be destroyed if store is successful. |
(...skipping 19 matching lines...) Expand all Loading... | |
911 // checks. | 940 // checks. |
912 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 941 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
913 | 942 |
914 int index = lookup->GetFieldIndex().field_index(); | 943 int index = lookup->GetFieldIndex().field_index(); |
915 | 944 |
916 // Adjust for the number of properties stored in the object. Even in the | 945 // Adjust for the number of properties stored in the object. Even in the |
917 // face of a transition we can use the old map here because the size of the | 946 // face of a transition we can use the old map here because the size of the |
918 // object and the number of in-object properties is not going to change. | 947 // object and the number of in-object properties is not going to change. |
919 index -= object->map()->inobject_properties(); | 948 index -= object->map()->inobject_properties(); |
920 | 949 |
950 Representation representation = lookup->GetPropertyDetails().representation(); | |
951 ASSERT(!representation.IsNone()); | |
952 if (FLAG_track_fields && representation.IsSmi()) { | |
953 __ JumpIfNotSmi(value_reg, miss_label); | |
954 } else if (FLAG_track_double_fields && representation.IsDouble()) { | |
955 Label do_store; | |
956 __ JumpIfSmi(value_reg, &do_store); | |
957 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | |
958 miss_label, DONT_DO_SMI_CHECK, REQUIRE_EXACT_MAP); | |
959 __ bind(&do_store); | |
960 } | |
961 | |
921 // TODO(verwaest): Share this code as a code stub. | 962 // TODO(verwaest): Share this code as a code stub. |
922 if (index < 0) { | 963 if (index < 0) { |
923 // Set the property straight into the object. | 964 // Set the property straight into the object. |
924 int offset = object->map()->instance_size() + (index * kPointerSize); | 965 int offset = object->map()->instance_size() + (index * kPointerSize); |
925 __ mov(FieldOperand(receiver_reg, offset), value_reg); | 966 __ mov(FieldOperand(receiver_reg, offset), value_reg); |
926 | 967 |
927 // Update the write barrier for the array address. | 968 if (!FLAG_track_fields || !representation.IsSmi()) { |
928 // Pass the value being stored in the now unused name_reg. | 969 // Update the write barrier for the array address. |
929 __ mov(name_reg, value_reg); | 970 // Pass the value being stored in the now unused name_reg. |
930 __ RecordWriteField(receiver_reg, | 971 __ mov(name_reg, value_reg); |
931 offset, | 972 __ RecordWriteField(receiver_reg, |
932 name_reg, | 973 offset, |
933 scratch1, | 974 name_reg, |
934 kDontSaveFPRegs); | 975 scratch1, |
976 kDontSaveFPRegs); | |
977 } | |
935 } else { | 978 } else { |
936 // Write to the properties array. | 979 // Write to the properties array. |
937 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 980 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
938 // Get the properties array (optimistically). | 981 // Get the properties array (optimistically). |
939 __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 982 __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
940 __ mov(FieldOperand(scratch1, offset), eax); | 983 __ mov(FieldOperand(scratch1, offset), eax); |
941 | 984 |
942 // Update the write barrier for the array address. | 985 if (!FLAG_track_fields || !representation.IsSmi()) { |
943 // Pass the value being stored in the now unused name_reg. | 986 // Update the write barrier for the array address. |
944 __ mov(name_reg, value_reg); | 987 // Pass the value being stored in the now unused name_reg. |
945 __ RecordWriteField(scratch1, | 988 __ mov(name_reg, value_reg); |
946 offset, | 989 __ RecordWriteField(scratch1, |
947 name_reg, | 990 offset, |
948 receiver_reg, | 991 name_reg, |
949 kDontSaveFPRegs); | 992 receiver_reg, |
993 kDontSaveFPRegs); | |
994 } | |
950 } | 995 } |
951 | 996 |
952 // Return the value (register eax). | 997 // Return the value (register eax). |
953 ASSERT(value_reg.is(eax)); | 998 ASSERT(value_reg.is(eax)); |
954 __ ret(0); | 999 __ ret(0); |
955 } | 1000 } |
956 | 1001 |
957 | 1002 |
958 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 1003 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
959 // from object to (but not including) holder. | 1004 // from object to (but not including) holder. |
(...skipping 2009 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2969 Label miss; | 3014 Label miss; |
2970 | 3015 |
2971 if (check == PROPERTY) { | 3016 if (check == PROPERTY) { |
2972 GenerateNameCheck(name, this->name(), &miss); | 3017 GenerateNameCheck(name, this->name(), &miss); |
2973 } | 3018 } |
2974 | 3019 |
2975 __ JumpIfSmi(receiver(), &miss); | 3020 __ JumpIfSmi(receiver(), &miss); |
2976 Register map_reg = scratch1(); | 3021 Register map_reg = scratch1(); |
2977 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); | 3022 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); |
2978 int receiver_count = receiver_maps->length(); | 3023 int receiver_count = receiver_maps->length(); |
3024 int number_of_handled_maps = 0; | |
2979 for (int current = 0; current < receiver_count; ++current) { | 3025 for (int current = 0; current < receiver_count; ++current) { |
2980 __ cmp(map_reg, receiver_maps->at(current)); | 3026 Handle<Map> map = receiver_maps->at(current); |
2981 __ j(equal, handlers->at(current)); | 3027 if (!map->is_invalid_transition()) { |
3028 number_of_handled_maps++; | |
3029 __ cmp(map_reg, map); | |
3030 __ j(equal, handlers->at(current)); | |
3031 } | |
2982 } | 3032 } |
3033 ASSERT(number_of_handled_maps != 0); | |
2983 | 3034 |
2984 __ bind(&miss); | 3035 __ bind(&miss); |
2985 TailCallBuiltin(masm(), MissBuiltin(kind())); | 3036 TailCallBuiltin(masm(), MissBuiltin(kind())); |
2986 | 3037 |
2987 // Return the generated code. | 3038 // Return the generated code. |
2988 InlineCacheState state = | 3039 InlineCacheState state = |
2989 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; | 3040 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |
2990 return GetICCode(kind(), type, name, state); | 3041 return GetICCode(kind(), type, name, state); |
2991 } | 3042 } |
2992 | 3043 |
2993 | 3044 |
2994 // Specialized stub for constructing objects from functions which only have only | 3045 // Specialized stub for constructing objects from functions which only have only |
2995 // simple assignments of the form this.x = ...; in their body. | 3046 // simple assignments of the form this.x = ...; in their body. |
2996 Handle<Code> ConstructStubCompiler::CompileConstructStub( | 3047 Handle<Code> ConstructStubCompiler::CompileConstructStub( |
2997 Handle<JSFunction> function) { | 3048 Handle<JSFunction> function) { |
2998 // ----------- S t a t e ------------- | 3049 // ----------- S t a t e ------------- |
2999 // -- eax : argc | 3050 // -- eax : argc |
(...skipping 690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3690 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); | 3741 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3691 } | 3742 } |
3692 } | 3743 } |
3693 | 3744 |
3694 | 3745 |
3695 #undef __ | 3746 #undef __ |
3696 | 3747 |
3697 } } // namespace v8::internal | 3748 } } // namespace v8::internal |
3698 | 3749 |
3699 #endif // V8_TARGET_ARCH_IA32 | 3750 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |