Chromium Code Reviews| 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 |