| 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 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 Handle<PropertyCell> cell = | 750 Handle<PropertyCell> cell = |
| 751 GlobalObject::EnsurePropertyCell(global, name); | 751 GlobalObject::EnsurePropertyCell(global, name); |
| 752 ASSERT(cell->value()->IsTheHole()); | 752 ASSERT(cell->value()->IsTheHole()); |
| 753 __ Move(scratch, cell); | 753 __ Move(scratch, cell); |
| 754 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), | 754 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), |
| 755 masm->isolate()->factory()->the_hole_value()); | 755 masm->isolate()->factory()->the_hole_value()); |
| 756 __ j(not_equal, miss); | 756 __ j(not_equal, miss); |
| 757 } | 757 } |
| 758 | 758 |
| 759 | 759 |
| 760 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 760 void BaseStoreStubCompiler::GenerateNegativeHolderLookup( |
| 761 // but may be destroyed if store is successful. | 761 MacroAssembler* masm, |
| 762 void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 762 Handle<JSObject> holder, |
| 763 Handle<JSObject> object, | 763 Register holder_reg, |
| 764 LookupResult* lookup, | 764 Handle<Name> name, |
| 765 Handle<Map> transition, | 765 Label* miss) { |
| 766 Handle<Name> name, | 766 if (holder->IsJSGlobalObject()) { |
| 767 Register receiver_reg, | 767 GenerateCheckPropertyCell( |
| 768 Register name_reg, | 768 masm, |
| 769 Register value_reg, | 769 Handle<GlobalObject>::cast(holder), |
| 770 Register scratch1, | 770 name, |
| 771 Register scratch2, | 771 scratch1(), |
| 772 Register unused, | 772 miss); |
| 773 Label* miss_label, | 773 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
| 774 Label* miss_restore_name, | 774 GenerateDictionaryNegativeLookup( |
| 775 Label* slow) { | 775 masm, miss, holder_reg, name, scratch1(), scratch2()); |
| 776 // Check that the map of the object hasn't changed. | 776 } |
| 777 __ CheckMap(receiver_reg, Handle<Map>(object->map()), | 777 } |
| 778 miss_label, DO_SMI_CHECK); | |
| 779 | 778 |
| 780 // Perform global security token check if needed. | |
| 781 if (object->IsJSGlobalProxy()) { | |
| 782 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); | |
| 783 } | |
| 784 | 779 |
| 780 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
| 781 // store is successful. |
| 782 void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
| 783 Handle<JSObject> object, |
| 784 LookupResult* lookup, |
| 785 Handle<Map> transition, |
| 786 Handle<Name> name, |
| 787 Register receiver_reg, |
| 788 Register storage_reg, |
| 789 Register value_reg, |
| 790 Register scratch1, |
| 791 Register scratch2, |
| 792 Register unused, |
| 793 Label* miss_label, |
| 794 Label* slow) { |
| 785 int descriptor = transition->LastAdded(); | 795 int descriptor = transition->LastAdded(); |
| 786 DescriptorArray* descriptors = transition->instance_descriptors(); | 796 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 787 PropertyDetails details = descriptors->GetDetails(descriptor); | 797 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 788 Representation representation = details.representation(); | 798 Representation representation = details.representation(); |
| 789 ASSERT(!representation.IsNone()); | 799 ASSERT(!representation.IsNone()); |
| 790 | 800 |
| 791 // Ensure no transitions to deprecated maps are followed. | |
| 792 __ CheckMapDeprecated(transition, scratch1, miss_label); | |
| 793 | |
| 794 // Check that we are allowed to write this. | |
| 795 if (object->GetPrototype()->IsJSObject()) { | |
| 796 JSObject* holder; | |
| 797 // holder == object indicates that no property was found. | |
| 798 if (lookup->holder() != *object) { | |
| 799 holder = lookup->holder(); | |
| 800 } else { | |
| 801 // Find the top object. | |
| 802 holder = *object; | |
| 803 do { | |
| 804 holder = JSObject::cast(holder->GetPrototype()); | |
| 805 } while (holder->GetPrototype()->IsJSObject()); | |
| 806 } | |
| 807 Register holder_reg = CheckPrototypes( | |
| 808 object, receiver_reg, Handle<JSObject>(holder), name_reg, | |
| 809 scratch1, scratch2, name, miss_restore_name, SKIP_RECEIVER); | |
| 810 // If no property was found, and the holder (the last object in the | |
| 811 // prototype chain) is in slow mode, we need to do a negative lookup on the | |
| 812 // holder. | |
| 813 if (lookup->holder() == *object) { | |
| 814 if (holder->IsJSGlobalObject()) { | |
| 815 GenerateCheckPropertyCell( | |
| 816 masm, | |
| 817 Handle<GlobalObject>(GlobalObject::cast(holder)), | |
| 818 name, | |
| 819 scratch1, | |
| 820 miss_restore_name); | |
| 821 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | |
| 822 GenerateDictionaryNegativeLookup( | |
| 823 masm, miss_restore_name, holder_reg, name, scratch1, scratch2); | |
| 824 } | |
| 825 } | |
| 826 } | |
| 827 | |
| 828 Register storage_reg = name_reg; | |
| 829 | |
| 830 if (details.type() == CONSTANT_FUNCTION) { | 801 if (details.type() == CONSTANT_FUNCTION) { |
| 831 Handle<HeapObject> constant( | 802 Handle<HeapObject> constant( |
| 832 HeapObject::cast(descriptors->GetValue(descriptor))); | 803 HeapObject::cast(descriptors->GetValue(descriptor))); |
| 833 __ LoadHeapObject(scratch1, constant); | 804 __ LoadHeapObject(scratch1, constant); |
| 834 __ cmpq(value_reg, scratch1); | 805 __ cmpq(value_reg, scratch1); |
| 835 __ j(not_equal, miss_restore_name); | 806 __ j(not_equal, miss_label); |
| 836 } else if (FLAG_track_fields && representation.IsSmi()) { | 807 } else if (FLAG_track_fields && representation.IsSmi()) { |
| 837 __ JumpIfNotSmi(value_reg, miss_restore_name); | 808 __ JumpIfNotSmi(value_reg, miss_label); |
| 838 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 809 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 839 __ JumpIfSmi(value_reg, miss_restore_name); | 810 __ JumpIfSmi(value_reg, miss_label); |
| 840 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 811 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
| 841 Label do_store, heap_number; | 812 Label do_store, heap_number; |
| 842 __ AllocateHeapNumber(storage_reg, scratch1, slow); | 813 __ AllocateHeapNumber(storage_reg, scratch1, slow); |
| 843 | 814 |
| 844 __ JumpIfNotSmi(value_reg, &heap_number); | 815 __ JumpIfNotSmi(value_reg, &heap_number); |
| 845 __ SmiToInteger32(scratch1, value_reg); | 816 __ SmiToInteger32(scratch1, value_reg); |
| 846 __ cvtlsi2sd(xmm0, scratch1); | 817 __ cvtlsi2sd(xmm0, scratch1); |
| 847 __ jmp(&do_store); | 818 __ jmp(&do_store); |
| 848 | 819 |
| 849 __ bind(&heap_number); | 820 __ bind(&heap_number); |
| 850 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 821 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
| 851 miss_restore_name, DONT_DO_SMI_CHECK); | 822 miss_label, DONT_DO_SMI_CHECK); |
| 852 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 823 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
| 853 | 824 |
| 854 __ bind(&do_store); | 825 __ bind(&do_store); |
| 855 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); | 826 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); |
| 856 } | 827 } |
| 857 | 828 |
| 858 // Stub never generated for non-global objects that require access | 829 // Stub never generated for non-global objects that require access |
| 859 // checks. | 830 // checks. |
| 860 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 831 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 861 | 832 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 911 // Set the property straight into the object. | 882 // Set the property straight into the object. |
| 912 int offset = object->map()->instance_size() + (index * kPointerSize); | 883 int offset = object->map()->instance_size() + (index * kPointerSize); |
| 913 if (FLAG_track_double_fields && representation.IsDouble()) { | 884 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 914 __ movq(FieldOperand(receiver_reg, offset), storage_reg); | 885 __ movq(FieldOperand(receiver_reg, offset), storage_reg); |
| 915 } else { | 886 } else { |
| 916 __ movq(FieldOperand(receiver_reg, offset), value_reg); | 887 __ movq(FieldOperand(receiver_reg, offset), value_reg); |
| 917 } | 888 } |
| 918 | 889 |
| 919 if (!FLAG_track_fields || !representation.IsSmi()) { | 890 if (!FLAG_track_fields || !representation.IsSmi()) { |
| 920 // Update the write barrier for the array address. | 891 // Update the write barrier for the array address. |
| 921 // Pass the value being stored in the now unused name_reg. | |
| 922 if (!FLAG_track_double_fields || !representation.IsDouble()) { | 892 if (!FLAG_track_double_fields || !representation.IsDouble()) { |
| 923 __ movq(name_reg, value_reg); | 893 __ movq(storage_reg, value_reg); |
| 924 } else { | |
| 925 ASSERT(storage_reg.is(name_reg)); | |
| 926 } | 894 } |
| 927 __ RecordWriteField( | 895 __ RecordWriteField( |
| 928 receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs, | 896 receiver_reg, offset, storage_reg, scratch1, kDontSaveFPRegs, |
| 929 EMIT_REMEMBERED_SET, smi_check); | 897 EMIT_REMEMBERED_SET, smi_check); |
| 930 } | 898 } |
| 931 } else { | 899 } else { |
| 932 // Write to the properties array. | 900 // Write to the properties array. |
| 933 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 901 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 934 // Get the properties array (optimistically). | 902 // Get the properties array (optimistically). |
| 935 __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 903 __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 936 if (FLAG_track_double_fields && representation.IsDouble()) { | 904 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 937 __ movq(FieldOperand(scratch1, offset), storage_reg); | 905 __ movq(FieldOperand(scratch1, offset), storage_reg); |
| 938 } else { | 906 } else { |
| 939 __ movq(FieldOperand(scratch1, offset), value_reg); | 907 __ movq(FieldOperand(scratch1, offset), value_reg); |
| 940 } | 908 } |
| 941 | 909 |
| 942 if (!FLAG_track_fields || !representation.IsSmi()) { | 910 if (!FLAG_track_fields || !representation.IsSmi()) { |
| 943 // Update the write barrier for the array address. | 911 // Update the write barrier for the array address. |
| 944 // Pass the value being stored in the now unused name_reg. | |
| 945 if (!FLAG_track_double_fields || !representation.IsDouble()) { | 912 if (!FLAG_track_double_fields || !representation.IsDouble()) { |
| 946 __ movq(name_reg, value_reg); | 913 __ movq(storage_reg, value_reg); |
| 947 } else { | |
| 948 ASSERT(storage_reg.is(name_reg)); | |
| 949 } | 914 } |
| 950 __ RecordWriteField( | 915 __ RecordWriteField( |
| 951 scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs, | 916 scratch1, offset, storage_reg, receiver_reg, kDontSaveFPRegs, |
| 952 EMIT_REMEMBERED_SET, smi_check); | 917 EMIT_REMEMBERED_SET, smi_check); |
| 953 } | 918 } |
| 954 } | 919 } |
| 955 | 920 |
| 956 // Return the value (register rax). | 921 // Return the value (register rax). |
| 957 ASSERT(value_reg.is(rax)); | 922 ASSERT(value_reg.is(rax)); |
| 958 __ ret(0); | 923 __ ret(0); |
| 959 } | 924 } |
| 960 | 925 |
| 961 | 926 |
| 962 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 927 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 963 // but may be destroyed if store is successful. | 928 // but may be destroyed if store is successful. |
| 964 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 929 void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 965 Handle<JSObject> object, | 930 Handle<JSObject> object, |
| 966 LookupResult* lookup, | 931 LookupResult* lookup, |
| 967 Register receiver_reg, | 932 Register receiver_reg, |
| 968 Register name_reg, | 933 Register name_reg, |
| 969 Register value_reg, | 934 Register value_reg, |
| 970 Register scratch1, | 935 Register scratch1, |
| 971 Register scratch2, | 936 Register scratch2, |
| 972 Label* miss_label) { | 937 Label* miss_label) { |
| 973 // Check that the map of the object hasn't changed. | |
| 974 __ CheckMap(receiver_reg, Handle<Map>(object->map()), | |
| 975 miss_label, DO_SMI_CHECK); | |
| 976 | |
| 977 // Perform global security token check if needed. | |
| 978 if (object->IsJSGlobalProxy()) { | |
| 979 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); | |
| 980 } | |
| 981 | |
| 982 // Stub never generated for non-global objects that require access | 938 // Stub never generated for non-global objects that require access |
| 983 // checks. | 939 // checks. |
| 984 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 940 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 985 | 941 |
| 986 int index = lookup->GetFieldIndex().field_index(); | 942 int index = lookup->GetFieldIndex().field_index(); |
| 987 | 943 |
| 988 // Adjust for the number of properties stored in the object. Even in the | 944 // Adjust for the number of properties stored in the object. Even in the |
| 989 // face of a transition we can use the old map here because the size of the | 945 // face of a transition we can use the old map here because the size of the |
| 990 // object and the number of in-object properties is not going to change. | 946 // object and the number of in-object properties is not going to change. |
| 991 index -= object->map()->inobject_properties(); | 947 index -= object->map()->inobject_properties(); |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1205 // If we've skipped any global objects, it's not enough to verify that | 1161 // If we've skipped any global objects, it's not enough to verify that |
| 1206 // their maps haven't changed. We also need to check that the property | 1162 // their maps haven't changed. We also need to check that the property |
| 1207 // cell for the property is still empty. | 1163 // cell for the property is still empty. |
| 1208 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1164 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1209 | 1165 |
| 1210 // Return the register containing the holder. | 1166 // Return the register containing the holder. |
| 1211 return reg; | 1167 return reg; |
| 1212 } | 1168 } |
| 1213 | 1169 |
| 1214 | 1170 |
| 1215 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, | 1171 void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
| 1172 Label* success, |
| 1216 Label* miss) { | 1173 Label* miss) { |
| 1217 if (!miss->is_unused()) { | 1174 if (!miss->is_unused()) { |
| 1218 __ jmp(success); | 1175 __ jmp(success); |
| 1219 __ bind(miss); | 1176 __ bind(miss); |
| 1220 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1177 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1221 } | 1178 } |
| 1222 } | 1179 } |
| 1223 | 1180 |
| 1224 | 1181 |
| 1182 void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
| 1183 Label* success, |
| 1184 Label* miss) { |
| 1185 if (!miss->is_unused()) { |
| 1186 __ jmp(success); |
| 1187 __ bind(miss); |
| 1188 __ LoadHeapObject(this->name(), name); |
| 1189 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1190 } |
| 1191 } |
| 1192 |
| 1193 |
| 1225 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1194 Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
| 1226 Handle<JSObject> object, | 1195 Handle<JSObject> object, |
| 1227 Register object_reg, | 1196 Register object_reg, |
| 1228 Handle<JSObject> holder, | 1197 Handle<JSObject> holder, |
| 1229 Handle<Name> name, | 1198 Handle<Name> name, |
| 1230 Label* success, | 1199 Label* success, |
| 1231 Handle<ExecutableAccessorInfo> callback) { | 1200 Handle<ExecutableAccessorInfo> callback) { |
| 1232 Label miss; | 1201 Label miss; |
| 1233 | 1202 |
| 1234 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1203 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1261 NameDictionary::kElementsStartIndex * kPointerSize; | 1230 NameDictionary::kElementsStartIndex * kPointerSize; |
| 1262 const int kValueOffset = kElementsStartOffset + kPointerSize; | 1231 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 1263 __ movq(scratch2(), | 1232 __ movq(scratch2(), |
| 1264 Operand(dictionary, index, times_pointer_size, | 1233 Operand(dictionary, index, times_pointer_size, |
| 1265 kValueOffset - kHeapObjectTag)); | 1234 kValueOffset - kHeapObjectTag)); |
| 1266 __ movq(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT); | 1235 __ movq(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT); |
| 1267 __ cmpq(scratch2(), scratch3()); | 1236 __ cmpq(scratch2(), scratch3()); |
| 1268 __ j(not_equal, &miss); | 1237 __ j(not_equal, &miss); |
| 1269 } | 1238 } |
| 1270 | 1239 |
| 1271 HandlerFrontendFooter(success, &miss); | 1240 HandlerFrontendFooter(name, success, &miss); |
| 1272 return reg; | 1241 return reg; |
| 1273 } | 1242 } |
| 1274 | 1243 |
| 1275 | 1244 |
| 1276 void BaseLoadStubCompiler::NonexistentHandlerFrontend( | 1245 void BaseLoadStubCompiler::NonexistentHandlerFrontend( |
| 1277 Handle<JSObject> object, | 1246 Handle<JSObject> object, |
| 1278 Handle<JSObject> last, | 1247 Handle<JSObject> last, |
| 1279 Handle<Name> name, | 1248 Handle<Name> name, |
| 1280 Label* success, | 1249 Label* success, |
| 1281 Handle<GlobalObject> global) { | 1250 Handle<GlobalObject> global) { |
| 1282 Label miss; | 1251 Label miss; |
| 1283 | 1252 |
| 1284 HandlerFrontendHeader(object, receiver(), last, name, &miss); | 1253 HandlerFrontendHeader(object, receiver(), last, name, &miss); |
| 1285 | 1254 |
| 1286 // If the last object in the prototype chain is a global object, | 1255 // If the last object in the prototype chain is a global object, |
| 1287 // check that the global property cell is empty. | 1256 // check that the global property cell is empty. |
| 1288 if (!global.is_null()) { | 1257 if (!global.is_null()) { |
| 1289 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1258 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
| 1290 } | 1259 } |
| 1291 | 1260 |
| 1292 HandlerFrontendFooter(success, &miss); | 1261 HandlerFrontendFooter(name, success, &miss); |
| 1293 } | 1262 } |
| 1294 | 1263 |
| 1295 | 1264 |
| 1296 void BaseLoadStubCompiler::GenerateLoadField(Register reg, | 1265 void BaseLoadStubCompiler::GenerateLoadField(Register reg, |
| 1297 Handle<JSObject> holder, | 1266 Handle<JSObject> holder, |
| 1298 PropertyIndex field, | 1267 PropertyIndex field, |
| 1299 Representation representation) { | 1268 Representation representation) { |
| 1300 if (!reg.is(receiver())) __ movq(receiver(), reg); | 1269 if (!reg.is(receiver())) __ movq(receiver(), reg); |
| 1301 if (kind() == Code::LOAD_IC) { | 1270 if (kind() == Code::LOAD_IC) { |
| 1302 LoadFieldStub stub(field.is_inobject(holder), | 1271 LoadFieldStub stub(field.is_inobject(holder), |
| (...skipping 1364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2667 __ bind(&miss); | 2636 __ bind(&miss); |
| 2668 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2637 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
| 2669 GenerateMissBranch(); | 2638 GenerateMissBranch(); |
| 2670 | 2639 |
| 2671 // Return the generated code. | 2640 // Return the generated code. |
| 2672 return GetCode(Code::NORMAL, name); | 2641 return GetCode(Code::NORMAL, name); |
| 2673 } | 2642 } |
| 2674 | 2643 |
| 2675 | 2644 |
| 2676 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2645 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2677 Handle<Name> name, | |
| 2678 Handle<JSObject> object, | 2646 Handle<JSObject> object, |
| 2679 Handle<JSObject> holder, | 2647 Handle<JSObject> holder, |
| 2648 Handle<Name> name, |
| 2680 Handle<ExecutableAccessorInfo> callback) { | 2649 Handle<ExecutableAccessorInfo> callback) { |
| 2681 Label miss; | 2650 Label success; |
| 2682 // Check that the maps haven't changed. | 2651 HandlerFrontend(object, receiver(), holder, name, &success); |
| 2683 __ JumpIfSmi(receiver(), &miss); | 2652 __ bind(&success); |
| 2684 CheckPrototypes(object, receiver(), holder, | |
| 2685 scratch1(), scratch2(), scratch3(), name, &miss); | |
| 2686 | |
| 2687 // Stub never generated for non-global objects that require access checks. | |
| 2688 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | |
| 2689 | 2653 |
| 2690 __ pop(scratch1()); // remove the return address | 2654 __ pop(scratch1()); // remove the return address |
| 2691 __ push(receiver()); | 2655 __ push(receiver()); |
| 2692 __ Push(callback); // callback info | 2656 __ Push(callback); // callback info |
| 2693 __ push(this->name()); | 2657 __ Push(name); |
| 2694 __ push(value()); | 2658 __ push(value()); |
| 2695 __ push(scratch1()); // restore return address | 2659 __ push(scratch1()); // restore return address |
| 2696 | 2660 |
| 2697 // Do tail-call to the runtime system. | 2661 // Do tail-call to the runtime system. |
| 2698 ExternalReference store_callback_property = | 2662 ExternalReference store_callback_property = |
| 2699 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2663 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2700 __ TailCallExternalReference(store_callback_property, 4, 1); | 2664 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2701 | 2665 |
| 2702 // Handle store cache miss. | |
| 2703 __ bind(&miss); | |
| 2704 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
| 2705 | |
| 2706 // Return the generated code. | 2666 // Return the generated code. |
| 2707 return GetICCode(kind(), Code::CALLBACKS, name); | 2667 return GetCode(kind(), Code::CALLBACKS, name); |
| 2708 } | 2668 } |
| 2709 | 2669 |
| 2710 | 2670 |
| 2711 #undef __ | 2671 #undef __ |
| 2712 #define __ ACCESS_MASM(masm) | 2672 #define __ ACCESS_MASM(masm) |
| 2713 | 2673 |
| 2714 | 2674 |
| 2715 void StoreStubCompiler::GenerateStoreViaSetter( | 2675 void StoreStubCompiler::GenerateStoreViaSetter( |
| 2716 MacroAssembler* masm, | 2676 MacroAssembler* masm, |
| 2717 Handle<JSFunction> setter) { | 2677 Handle<JSFunction> setter) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2751 } | 2711 } |
| 2752 | 2712 |
| 2753 | 2713 |
| 2754 #undef __ | 2714 #undef __ |
| 2755 #define __ ACCESS_MASM(masm()) | 2715 #define __ ACCESS_MASM(masm()) |
| 2756 | 2716 |
| 2757 | 2717 |
| 2758 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 2718 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
| 2759 Handle<JSObject> object, | 2719 Handle<JSObject> object, |
| 2760 Handle<Name> name) { | 2720 Handle<Name> name) { |
| 2761 Label miss; | |
| 2762 | |
| 2763 // Check that the map of the object hasn't changed. | |
| 2764 __ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK); | |
| 2765 | |
| 2766 // Perform global security token check if needed. | |
| 2767 if (object->IsJSGlobalProxy()) { | |
| 2768 __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss); | |
| 2769 } | |
| 2770 | |
| 2771 // Stub never generated for non-global objects that require access | |
| 2772 // checks. | |
| 2773 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | |
| 2774 | |
| 2775 __ pop(scratch1()); // remove the return address | 2721 __ pop(scratch1()); // remove the return address |
| 2776 __ push(receiver()); | 2722 __ push(receiver()); |
| 2777 __ push(this->name()); | 2723 __ push(this->name()); |
| 2778 __ push(value()); | 2724 __ push(value()); |
| 2779 __ Push(Smi::FromInt(strict_mode())); | 2725 __ Push(Smi::FromInt(strict_mode())); |
| 2780 __ push(scratch1()); // restore return address | 2726 __ push(scratch1()); // restore return address |
| 2781 | 2727 |
| 2782 // Do tail-call to the runtime system. | 2728 // Do tail-call to the runtime system. |
| 2783 ExternalReference store_ic_property = | 2729 ExternalReference store_ic_property = |
| 2784 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 2730 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
| 2785 __ TailCallExternalReference(store_ic_property, 4, 1); | 2731 __ TailCallExternalReference(store_ic_property, 4, 1); |
| 2786 | 2732 |
| 2787 // Handle store cache miss. | |
| 2788 __ bind(&miss); | |
| 2789 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
| 2790 | |
| 2791 // Return the generated code. | 2733 // Return the generated code. |
| 2792 return GetICCode(kind(), Code::INTERCEPTOR, name); | 2734 return GetCode(kind(), Code::INTERCEPTOR, name); |
| 2793 } | 2735 } |
| 2794 | 2736 |
| 2795 | 2737 |
| 2796 Handle<Code> StoreStubCompiler::CompileStoreGlobal( | 2738 Handle<Code> StoreStubCompiler::CompileStoreGlobal( |
| 2797 Handle<GlobalObject> object, | 2739 Handle<GlobalObject> object, |
| 2798 Handle<PropertyCell> cell, | 2740 Handle<PropertyCell> cell, |
| 2799 Handle<Name> name) { | 2741 Handle<Name> name) { |
| 2800 Label miss; | 2742 Label miss; |
| 2801 | 2743 |
| 2802 // Check that the map of the global has not changed. | 2744 // Check that the map of the global has not changed. |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2993 | 2935 |
| 2994 // Check for deleted property if property can actually be deleted. | 2936 // Check for deleted property if property can actually be deleted. |
| 2995 if (!is_dont_delete) { | 2937 if (!is_dont_delete) { |
| 2996 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 2938 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
| 2997 __ j(equal, &miss); | 2939 __ j(equal, &miss); |
| 2998 } else if (FLAG_debug_code) { | 2940 } else if (FLAG_debug_code) { |
| 2999 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 2941 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
| 3000 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 2942 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
| 3001 } | 2943 } |
| 3002 | 2944 |
| 3003 HandlerFrontendFooter(&success, &miss); | 2945 HandlerFrontendFooter(name, &success, &miss); |
| 3004 __ bind(&success); | 2946 __ bind(&success); |
| 3005 | 2947 |
| 3006 Counters* counters = isolate()->counters(); | 2948 Counters* counters = isolate()->counters(); |
| 3007 __ IncrementCounter(counters->named_load_global_stub(), 1); | 2949 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 3008 __ movq(rax, rbx); | 2950 __ movq(rax, rbx); |
| 3009 __ ret(0); | 2951 __ ret(0); |
| 3010 | 2952 |
| 3011 // Return the generated code. | 2953 // Return the generated code. |
| 3012 return GetICCode(kind(), Code::NORMAL, name); | 2954 return GetICCode(kind(), Code::NORMAL, name); |
| 3013 } | 2955 } |
| 3014 | 2956 |
| 3015 | 2957 |
| 3016 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( | 2958 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( |
| 3017 MapHandleList* receiver_maps, | 2959 MapHandleList* receiver_maps, |
| 3018 CodeHandleList* handlers, | 2960 CodeHandleList* handlers, |
| 3019 Handle<Name> name, | 2961 Handle<Name> name, |
| 3020 Code::StubType type, | 2962 Code::StubType type, |
| 3021 IcCheckType check) { | 2963 IcCheckType check) { |
| 3022 Label miss; | 2964 Label miss; |
| 3023 | 2965 |
| 3024 if (check == PROPERTY) { | 2966 if (check == PROPERTY) { |
| 3025 GenerateNameCheck(name, this->name(), &miss); | 2967 GenerateNameCheck(name, this->name(), &miss); |
| 3026 } | 2968 } |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3573 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); | 3515 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
| 3574 } | 3516 } |
| 3575 } | 3517 } |
| 3576 | 3518 |
| 3577 | 3519 |
| 3578 #undef __ | 3520 #undef __ |
| 3579 | 3521 |
| 3580 } } // namespace v8::internal | 3522 } } // namespace v8::internal |
| 3581 | 3523 |
| 3582 #endif // V8_TARGET_ARCH_X64 | 3524 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |