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