| 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 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 __ mov(scratch, Immediate(cell)); | 772 __ mov(scratch, Immediate(cell)); |
| 773 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), | 773 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), |
| 774 Immediate(the_hole)); | 774 Immediate(the_hole)); |
| 775 } else { | 775 } else { |
| 776 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); | 776 __ cmp(Operand::ForCell(cell), Immediate(the_hole)); |
| 777 } | 777 } |
| 778 __ j(not_equal, miss); | 778 __ j(not_equal, miss); |
| 779 } | 779 } |
| 780 | 780 |
| 781 | 781 |
| 782 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 782 void BaseStoreStubCompiler::GenerateNegativeHolderLookup( |
| 783 // but may be destroyed if store is successful. | 783 MacroAssembler* masm, |
| 784 void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 784 Handle<JSObject> holder, |
| 785 Handle<JSObject> object, | 785 Register holder_reg, |
| 786 LookupResult* lookup, | 786 Handle<Name> name, |
| 787 Handle<Map> transition, | 787 Label* miss) { |
| 788 Handle<Name> name, | 788 if (holder->IsJSGlobalObject()) { |
| 789 Register receiver_reg, | 789 GenerateCheckPropertyCell( |
| 790 Register name_reg, | 790 masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss); |
| 791 Register value_reg, | 791 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
| 792 Register scratch1, | 792 GenerateDictionaryNegativeLookup( |
| 793 Register scratch2, | 793 masm, miss, holder_reg, name, scratch1(), scratch2()); |
| 794 Register unused, | 794 } |
| 795 Label* miss_label, | 795 } |
| 796 Label* miss_restore_name, | |
| 797 Label* slow) { | |
| 798 // Check that the map of the object hasn't changed. | |
| 799 __ CheckMap(receiver_reg, Handle<Map>(object->map()), | |
| 800 miss_label, DO_SMI_CHECK); | |
| 801 | 796 |
| 802 // Perform global security token check if needed. | |
| 803 if (object->IsJSGlobalProxy()) { | |
| 804 __ CheckAccessGlobalProxy(receiver_reg, scratch1, scratch2, miss_label); | |
| 805 } | |
| 806 | 797 |
| 798 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
| 799 // store is successful. |
| 800 void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, |
| 801 Handle<JSObject> object, |
| 802 LookupResult* lookup, |
| 803 Handle<Map> transition, |
| 804 Handle<Name> name, |
| 805 Register receiver_reg, |
| 806 Register storage_reg, |
| 807 Register value_reg, |
| 808 Register scratch1, |
| 809 Register scratch2, |
| 810 Register unused, |
| 811 Label* miss_label, |
| 812 Label* slow) { |
| 807 int descriptor = transition->LastAdded(); | 813 int descriptor = transition->LastAdded(); |
| 808 DescriptorArray* descriptors = transition->instance_descriptors(); | 814 DescriptorArray* descriptors = transition->instance_descriptors(); |
| 809 PropertyDetails details = descriptors->GetDetails(descriptor); | 815 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 810 Representation representation = details.representation(); | 816 Representation representation = details.representation(); |
| 811 ASSERT(!representation.IsNone()); | 817 ASSERT(!representation.IsNone()); |
| 812 | 818 |
| 813 // Ensure no transitions to deprecated maps are followed. | |
| 814 __ CheckMapDeprecated(transition, scratch1, miss_label); | |
| 815 | |
| 816 // Check that we are allowed to write this. | |
| 817 if (object->GetPrototype()->IsJSObject()) { | |
| 818 JSObject* holder; | |
| 819 // holder == object indicates that no property was found. | |
| 820 if (lookup->holder() != *object) { | |
| 821 holder = lookup->holder(); | |
| 822 } else { | |
| 823 // Find the top object. | |
| 824 holder = *object; | |
| 825 do { | |
| 826 holder = JSObject::cast(holder->GetPrototype()); | |
| 827 } while (holder->GetPrototype()->IsJSObject()); | |
| 828 } | |
| 829 // We need an extra register, push | |
| 830 Register holder_reg = CheckPrototypes( | |
| 831 object, receiver_reg, Handle<JSObject>(holder), name_reg, | |
| 832 scratch1, scratch2, name, miss_restore_name, SKIP_RECEIVER); | |
| 833 // If no property was found, and the holder (the last object in the | |
| 834 // prototype chain) is in slow mode, we need to do a negative lookup on the | |
| 835 // holder. | |
| 836 if (lookup->holder() == *object) { | |
| 837 if (holder->IsJSGlobalObject()) { | |
| 838 GenerateCheckPropertyCell( | |
| 839 masm, | |
| 840 Handle<GlobalObject>(GlobalObject::cast(holder)), | |
| 841 name, | |
| 842 scratch1, | |
| 843 miss_restore_name); | |
| 844 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | |
| 845 GenerateDictionaryNegativeLookup( | |
| 846 masm, miss_restore_name, holder_reg, name, scratch1, scratch2); | |
| 847 } | |
| 848 } | |
| 849 } | |
| 850 | |
| 851 Register storage_reg = name_reg; | |
| 852 | |
| 853 if (details.type() == CONSTANT_FUNCTION) { | 819 if (details.type() == CONSTANT_FUNCTION) { |
| 854 Handle<HeapObject> constant( | 820 Handle<HeapObject> constant( |
| 855 HeapObject::cast(descriptors->GetValue(descriptor))); | 821 HeapObject::cast(descriptors->GetValue(descriptor))); |
| 856 __ LoadHeapObject(scratch1, constant); | 822 __ LoadHeapObject(scratch1, constant); |
| 857 __ cmp(value_reg, scratch1); | 823 __ cmp(value_reg, scratch1); |
| 858 __ j(not_equal, miss_restore_name); | 824 __ j(not_equal, miss_label); |
| 859 } else if (FLAG_track_fields && representation.IsSmi()) { | 825 } else if (FLAG_track_fields && representation.IsSmi()) { |
| 860 __ JumpIfNotSmi(value_reg, miss_restore_name); | 826 __ JumpIfNotSmi(value_reg, miss_label); |
| 861 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 827 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 862 __ JumpIfSmi(value_reg, miss_restore_name); | 828 __ JumpIfSmi(value_reg, miss_label); |
| 863 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 829 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
| 864 Label do_store, heap_number; | 830 Label do_store, heap_number; |
| 865 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow); | 831 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow); |
| 866 | 832 |
| 867 __ JumpIfNotSmi(value_reg, &heap_number); | 833 __ JumpIfNotSmi(value_reg, &heap_number); |
| 868 __ SmiUntag(value_reg); | 834 __ SmiUntag(value_reg); |
| 869 if (CpuFeatures::IsSupported(SSE2)) { | 835 if (CpuFeatures::IsSupported(SSE2)) { |
| 870 CpuFeatureScope use_sse2(masm, SSE2); | 836 CpuFeatureScope use_sse2(masm, SSE2); |
| 871 __ cvtsi2sd(xmm0, value_reg); | 837 __ cvtsi2sd(xmm0, value_reg); |
| 872 } else { | 838 } else { |
| 873 __ push(value_reg); | 839 __ push(value_reg); |
| 874 __ fild_s(Operand(esp, 0)); | 840 __ fild_s(Operand(esp, 0)); |
| 875 __ pop(value_reg); | 841 __ pop(value_reg); |
| 876 } | 842 } |
| 877 __ SmiTag(value_reg); | 843 __ SmiTag(value_reg); |
| 878 __ jmp(&do_store); | 844 __ jmp(&do_store); |
| 879 | 845 |
| 880 __ bind(&heap_number); | 846 __ bind(&heap_number); |
| 881 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), | 847 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), |
| 882 miss_restore_name, DONT_DO_SMI_CHECK); | 848 miss_label, DONT_DO_SMI_CHECK); |
| 883 if (CpuFeatures::IsSupported(SSE2)) { | 849 if (CpuFeatures::IsSupported(SSE2)) { |
| 884 CpuFeatureScope use_sse2(masm, SSE2); | 850 CpuFeatureScope use_sse2(masm, SSE2); |
| 885 __ movdbl(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 851 __ movdbl(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
| 886 } else { | 852 } else { |
| 887 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); | 853 __ fld_d(FieldOperand(value_reg, HeapNumber::kValueOffset)); |
| 888 } | 854 } |
| 889 | 855 |
| 890 __ bind(&do_store); | 856 __ bind(&do_store); |
| 891 if (CpuFeatures::IsSupported(SSE2)) { | 857 if (CpuFeatures::IsSupported(SSE2)) { |
| 892 CpuFeatureScope use_sse2(masm, SSE2); | 858 CpuFeatureScope use_sse2(masm, SSE2); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 // Set the property straight into the object. | 918 // Set the property straight into the object. |
| 953 int offset = object->map()->instance_size() + (index * kPointerSize); | 919 int offset = object->map()->instance_size() + (index * kPointerSize); |
| 954 if (FLAG_track_double_fields && representation.IsDouble()) { | 920 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 955 __ mov(FieldOperand(receiver_reg, offset), storage_reg); | 921 __ mov(FieldOperand(receiver_reg, offset), storage_reg); |
| 956 } else { | 922 } else { |
| 957 __ mov(FieldOperand(receiver_reg, offset), value_reg); | 923 __ mov(FieldOperand(receiver_reg, offset), value_reg); |
| 958 } | 924 } |
| 959 | 925 |
| 960 if (!FLAG_track_fields || !representation.IsSmi()) { | 926 if (!FLAG_track_fields || !representation.IsSmi()) { |
| 961 // Update the write barrier for the array address. | 927 // Update the write barrier for the array address. |
| 962 // Pass the value being stored in the now unused name_reg. | |
| 963 if (!FLAG_track_double_fields || !representation.IsDouble()) { | 928 if (!FLAG_track_double_fields || !representation.IsDouble()) { |
| 964 __ mov(name_reg, value_reg); | 929 __ mov(storage_reg, value_reg); |
| 965 } else { | |
| 966 ASSERT(storage_reg.is(name_reg)); | |
| 967 } | 930 } |
| 968 __ RecordWriteField(receiver_reg, | 931 __ RecordWriteField(receiver_reg, |
| 969 offset, | 932 offset, |
| 970 name_reg, | 933 storage_reg, |
| 971 scratch1, | 934 scratch1, |
| 972 kDontSaveFPRegs, | 935 kDontSaveFPRegs, |
| 973 EMIT_REMEMBERED_SET, | 936 EMIT_REMEMBERED_SET, |
| 974 smi_check); | 937 smi_check); |
| 975 } | 938 } |
| 976 } else { | 939 } else { |
| 977 // Write to the properties array. | 940 // Write to the properties array. |
| 978 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 941 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 979 // Get the properties array (optimistically). | 942 // Get the properties array (optimistically). |
| 980 __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); | 943 __ mov(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); |
| 981 if (FLAG_track_double_fields && representation.IsDouble()) { | 944 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 982 __ mov(FieldOperand(scratch1, offset), storage_reg); | 945 __ mov(FieldOperand(scratch1, offset), storage_reg); |
| 983 } else { | 946 } else { |
| 984 __ mov(FieldOperand(scratch1, offset), value_reg); | 947 __ mov(FieldOperand(scratch1, offset), value_reg); |
| 985 } | 948 } |
| 986 | 949 |
| 987 if (!FLAG_track_fields || !representation.IsSmi()) { | 950 if (!FLAG_track_fields || !representation.IsSmi()) { |
| 988 // Update the write barrier for the array address. | 951 // Update the write barrier for the array address. |
| 989 // Pass the value being stored in the now unused name_reg. | |
| 990 if (!FLAG_track_double_fields || !representation.IsDouble()) { | 952 if (!FLAG_track_double_fields || !representation.IsDouble()) { |
| 991 __ mov(name_reg, value_reg); | 953 __ mov(storage_reg, value_reg); |
| 992 } else { | |
| 993 ASSERT(storage_reg.is(name_reg)); | |
| 994 } | 954 } |
| 995 __ RecordWriteField(scratch1, | 955 __ RecordWriteField(scratch1, |
| 996 offset, | 956 offset, |
| 997 name_reg, | 957 storage_reg, |
| 998 receiver_reg, | 958 receiver_reg, |
| 999 kDontSaveFPRegs, | 959 kDontSaveFPRegs, |
| 1000 EMIT_REMEMBERED_SET, | 960 EMIT_REMEMBERED_SET, |
| 1001 smi_check); | 961 smi_check); |
| 1002 } | 962 } |
| 1003 } | 963 } |
| 1004 | 964 |
| 1005 // Return the value (register eax). | 965 // Return the value (register eax). |
| 1006 ASSERT(value_reg.is(eax)); | 966 ASSERT(value_reg.is(eax)); |
| 1007 __ ret(0); | 967 __ ret(0); |
| 1008 } | 968 } |
| 1009 | 969 |
| 1010 | 970 |
| 1011 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 971 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 1012 // but may be destroyed if store is successful. | 972 // but may be destroyed if store is successful. |
| 1013 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 973 void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 1014 Handle<JSObject> object, | 974 Handle<JSObject> object, |
| 1015 LookupResult* lookup, | 975 LookupResult* lookup, |
| 1016 Register receiver_reg, | 976 Register receiver_reg, |
| 1017 Register name_reg, | 977 Register name_reg, |
| 1018 Register value_reg, | 978 Register value_reg, |
| 1019 Register scratch1, | 979 Register scratch1, |
| 1020 Register scratch2, | 980 Register scratch2, |
| 1021 Label* miss_label) { | 981 Label* miss_label) { |
| 1022 // Check that the map of the object hasn't changed. | |
| 1023 __ CheckMap(receiver_reg, Handle<Map>(object->map()), | |
| 1024 miss_label, DO_SMI_CHECK); | |
| 1025 | |
| 1026 // Perform global security token check if needed. | |
| 1027 if (object->IsJSGlobalProxy()) { | |
| 1028 __ CheckAccessGlobalProxy(receiver_reg, scratch1, scratch2, miss_label); | |
| 1029 } | |
| 1030 | |
| 1031 // Stub never generated for non-global objects that require access | 982 // Stub never generated for non-global objects that require access |
| 1032 // checks. | 983 // checks. |
| 1033 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 984 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 1034 | 985 |
| 1035 int index = lookup->GetFieldIndex().field_index(); | 986 int index = lookup->GetFieldIndex().field_index(); |
| 1036 | 987 |
| 1037 // Adjust for the number of properties stored in the object. Even in the | 988 // Adjust for the number of properties stored in the object. Even in the |
| 1038 // face of a transition we can use the old map here because the size of the | 989 // face of a transition we can use the old map here because the size of the |
| 1039 // object and the number of in-object properties is not going to change. | 990 // object and the number of in-object properties is not going to change. |
| 1040 index -= object->map()->inobject_properties(); | 991 index -= object->map()->inobject_properties(); |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1279 // If we've skipped any global objects, it's not enough to verify that | 1230 // If we've skipped any global objects, it's not enough to verify that |
| 1280 // their maps haven't changed. We also need to check that the property | 1231 // their maps haven't changed. We also need to check that the property |
| 1281 // cell for the property is still empty. | 1232 // cell for the property is still empty. |
| 1282 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1233 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1283 | 1234 |
| 1284 // Return the register containing the holder. | 1235 // Return the register containing the holder. |
| 1285 return reg; | 1236 return reg; |
| 1286 } | 1237 } |
| 1287 | 1238 |
| 1288 | 1239 |
| 1289 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, | 1240 void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
| 1241 Label* success, |
| 1290 Label* miss) { | 1242 Label* miss) { |
| 1291 if (!miss->is_unused()) { | 1243 if (!miss->is_unused()) { |
| 1292 __ jmp(success); | 1244 __ jmp(success); |
| 1293 __ bind(miss); | 1245 __ bind(miss); |
| 1294 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1246 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1295 } | 1247 } |
| 1296 } | 1248 } |
| 1297 | 1249 |
| 1298 | 1250 |
| 1251 void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, |
| 1252 Label* success, |
| 1253 Label* miss) { |
| 1254 if (!miss->is_unused()) { |
| 1255 __ jmp(success); |
| 1256 GenerateRestoreName(masm(), miss, name); |
| 1257 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1258 } |
| 1259 } |
| 1260 |
| 1261 |
| 1299 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1262 Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
| 1300 Handle<JSObject> object, | 1263 Handle<JSObject> object, |
| 1301 Register object_reg, | 1264 Register object_reg, |
| 1302 Handle<JSObject> holder, | 1265 Handle<JSObject> holder, |
| 1303 Handle<Name> name, | 1266 Handle<Name> name, |
| 1304 Label* success, | 1267 Label* success, |
| 1305 Handle<ExecutableAccessorInfo> callback) { | 1268 Handle<ExecutableAccessorInfo> callback) { |
| 1306 Label miss; | 1269 Label miss; |
| 1307 | 1270 |
| 1308 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1271 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1344 const int kValueOffset = kElementsStartOffset + kPointerSize; | 1307 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 1345 __ mov(scratch3(), | 1308 __ mov(scratch3(), |
| 1346 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag)); | 1309 Operand(dictionary, index, times_4, kValueOffset - kHeapObjectTag)); |
| 1347 if (must_preserve_dictionary_reg) { | 1310 if (must_preserve_dictionary_reg) { |
| 1348 __ pop(dictionary); | 1311 __ pop(dictionary); |
| 1349 } | 1312 } |
| 1350 __ cmp(scratch3(), callback); | 1313 __ cmp(scratch3(), callback); |
| 1351 __ j(not_equal, &miss); | 1314 __ j(not_equal, &miss); |
| 1352 } | 1315 } |
| 1353 | 1316 |
| 1354 HandlerFrontendFooter(success, &miss); | 1317 HandlerFrontendFooter(name, success, &miss); |
| 1355 return reg; | 1318 return reg; |
| 1356 } | 1319 } |
| 1357 | 1320 |
| 1358 | 1321 |
| 1359 void BaseLoadStubCompiler::NonexistentHandlerFrontend( | 1322 void BaseLoadStubCompiler::NonexistentHandlerFrontend( |
| 1360 Handle<JSObject> object, | 1323 Handle<JSObject> object, |
| 1361 Handle<JSObject> last, | 1324 Handle<JSObject> last, |
| 1362 Handle<Name> name, | 1325 Handle<Name> name, |
| 1363 Label* success, | 1326 Label* success, |
| 1364 Handle<GlobalObject> global) { | 1327 Handle<GlobalObject> global) { |
| 1365 Label miss; | 1328 Label miss; |
| 1366 | 1329 |
| 1367 HandlerFrontendHeader(object, receiver(), last, name, &miss); | 1330 HandlerFrontendHeader(object, receiver(), last, name, &miss); |
| 1368 | 1331 |
| 1369 // If the last object in the prototype chain is a global object, | 1332 // If the last object in the prototype chain is a global object, |
| 1370 // check that the global property cell is empty. | 1333 // check that the global property cell is empty. |
| 1371 if (!global.is_null()) { | 1334 if (!global.is_null()) { |
| 1372 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1335 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
| 1373 } | 1336 } |
| 1374 | 1337 |
| 1375 HandlerFrontendFooter(success, &miss); | 1338 HandlerFrontendFooter(name, success, &miss); |
| 1376 } | 1339 } |
| 1377 | 1340 |
| 1378 | 1341 |
| 1379 void BaseLoadStubCompiler::GenerateLoadField(Register reg, | 1342 void BaseLoadStubCompiler::GenerateLoadField(Register reg, |
| 1380 Handle<JSObject> holder, | 1343 Handle<JSObject> holder, |
| 1381 PropertyIndex field, | 1344 PropertyIndex field, |
| 1382 Representation representation) { | 1345 Representation representation) { |
| 1383 if (!reg.is(receiver())) __ mov(receiver(), reg); | 1346 if (!reg.is(receiver())) __ mov(receiver(), reg); |
| 1384 if (kind() == Code::LOAD_IC) { | 1347 if (kind() == Code::LOAD_IC) { |
| 1385 LoadFieldStub stub(field.is_inobject(holder), | 1348 LoadFieldStub stub(field.is_inobject(holder), |
| (...skipping 1506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2892 __ bind(&miss); | 2855 __ bind(&miss); |
| 2893 __ IncrementCounter(counters->call_global_inline_miss(), 1); | 2856 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
| 2894 GenerateMissBranch(); | 2857 GenerateMissBranch(); |
| 2895 | 2858 |
| 2896 // Return the generated code. | 2859 // Return the generated code. |
| 2897 return GetCode(Code::NORMAL, name); | 2860 return GetCode(Code::NORMAL, name); |
| 2898 } | 2861 } |
| 2899 | 2862 |
| 2900 | 2863 |
| 2901 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2864 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2902 Handle<Name> name, | |
| 2903 Handle<JSObject> object, | 2865 Handle<JSObject> object, |
| 2904 Handle<JSObject> holder, | 2866 Handle<JSObject> holder, |
| 2867 Handle<Name> name, |
| 2905 Handle<ExecutableAccessorInfo> callback) { | 2868 Handle<ExecutableAccessorInfo> callback) { |
| 2906 Label miss, miss_restore_name; | 2869 Label success; |
| 2907 // Check that the maps haven't changed, preserving the value register. | 2870 HandlerFrontend(object, receiver(), holder, name, &success); |
| 2908 __ JumpIfSmi(receiver(), &miss); | 2871 __ bind(&success); |
| 2909 CheckPrototypes(object, receiver(), holder, | |
| 2910 scratch1(), this->name(), scratch2(), | |
| 2911 name, &miss_restore_name); | |
| 2912 | |
| 2913 // Stub never generated for non-global objects that require access checks. | |
| 2914 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | |
| 2915 | 2872 |
| 2916 __ pop(scratch1()); // remove the return address | 2873 __ pop(scratch1()); // remove the return address |
| 2917 __ push(receiver()); | 2874 __ push(receiver()); |
| 2918 __ Push(callback); | 2875 __ Push(callback); |
| 2919 __ Push(name); | 2876 __ Push(name); |
| 2920 __ push(value()); | 2877 __ push(value()); |
| 2921 __ push(scratch1()); // restore return address | 2878 __ push(scratch1()); // restore return address |
| 2922 | 2879 |
| 2923 // Do tail-call to the runtime system. | 2880 // Do tail-call to the runtime system. |
| 2924 ExternalReference store_callback_property = | 2881 ExternalReference store_callback_property = |
| 2925 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2882 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2926 __ TailCallExternalReference(store_callback_property, 4, 1); | 2883 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2927 | 2884 |
| 2928 // Handle store cache miss. | |
| 2929 GenerateRestoreName(masm(), &miss_restore_name, name); | |
| 2930 __ bind(&miss); | |
| 2931 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
| 2932 | |
| 2933 // Return the generated code. | 2885 // Return the generated code. |
| 2934 return GetICCode(kind(), Code::CALLBACKS, name); | 2886 return GetCode(kind(), Code::CALLBACKS, name); |
| 2935 } | 2887 } |
| 2936 | 2888 |
| 2937 | 2889 |
| 2938 #undef __ | 2890 #undef __ |
| 2939 #define __ ACCESS_MASM(masm) | 2891 #define __ ACCESS_MASM(masm) |
| 2940 | 2892 |
| 2941 | 2893 |
| 2942 void StoreStubCompiler::GenerateStoreViaSetter( | 2894 void StoreStubCompiler::GenerateStoreViaSetter( |
| 2943 MacroAssembler* masm, | 2895 MacroAssembler* masm, |
| 2944 Handle<JSFunction> setter) { | 2896 Handle<JSFunction> setter) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2978 } | 2930 } |
| 2979 | 2931 |
| 2980 | 2932 |
| 2981 #undef __ | 2933 #undef __ |
| 2982 #define __ ACCESS_MASM(masm()) | 2934 #define __ ACCESS_MASM(masm()) |
| 2983 | 2935 |
| 2984 | 2936 |
| 2985 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 2937 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( |
| 2986 Handle<JSObject> object, | 2938 Handle<JSObject> object, |
| 2987 Handle<Name> name) { | 2939 Handle<Name> name) { |
| 2988 Label miss; | |
| 2989 | |
| 2990 // Check that the map of the object hasn't changed. | |
| 2991 __ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK); | |
| 2992 | |
| 2993 // Perform global security token check if needed. | |
| 2994 if (object->IsJSGlobalProxy()) { | |
| 2995 __ CheckAccessGlobalProxy(receiver(), scratch1(), scratch2(), &miss); | |
| 2996 } | |
| 2997 | |
| 2998 // Stub never generated for non-global objects that require access | |
| 2999 // checks. | |
| 3000 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | |
| 3001 | |
| 3002 __ pop(scratch1()); // remove the return address | 2940 __ pop(scratch1()); // remove the return address |
| 3003 __ push(receiver()); | 2941 __ push(receiver()); |
| 3004 __ push(this->name()); | 2942 __ push(this->name()); |
| 3005 __ push(value()); | 2943 __ push(value()); |
| 3006 __ push(Immediate(Smi::FromInt(strict_mode()))); | 2944 __ push(Immediate(Smi::FromInt(strict_mode()))); |
| 3007 __ push(scratch1()); // restore return address | 2945 __ push(scratch1()); // restore return address |
| 3008 | 2946 |
| 3009 // Do tail-call to the runtime system. | 2947 // Do tail-call to the runtime system. |
| 3010 ExternalReference store_ic_property = | 2948 ExternalReference store_ic_property = |
| 3011 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 2949 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
| 3012 __ TailCallExternalReference(store_ic_property, 4, 1); | 2950 __ TailCallExternalReference(store_ic_property, 4, 1); |
| 3013 | 2951 |
| 3014 // Handle store cache miss. | |
| 3015 __ bind(&miss); | |
| 3016 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
| 3017 | |
| 3018 // Return the generated code. | 2952 // Return the generated code. |
| 3019 return GetICCode(kind(), Code::INTERCEPTOR, name); | 2953 return GetCode(kind(), Code::INTERCEPTOR, name); |
| 3020 } | 2954 } |
| 3021 | 2955 |
| 3022 | 2956 |
| 3023 Handle<Code> StoreStubCompiler::CompileStoreGlobal( | 2957 Handle<Code> StoreStubCompiler::CompileStoreGlobal( |
| 3024 Handle<GlobalObject> object, | 2958 Handle<GlobalObject> object, |
| 3025 Handle<PropertyCell> cell, | 2959 Handle<PropertyCell> cell, |
| 3026 Handle<Name> name) { | 2960 Handle<Name> name) { |
| 3027 Label miss; | 2961 Label miss; |
| 3028 | 2962 |
| 3029 // Check that the map of the global has not changed. | 2963 // Check that the map of the global has not changed. |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3213 | 3147 |
| 3214 // Check for deleted property if property can actually be deleted. | 3148 // Check for deleted property if property can actually be deleted. |
| 3215 if (!is_dont_delete) { | 3149 if (!is_dont_delete) { |
| 3216 __ cmp(eax, factory()->the_hole_value()); | 3150 __ cmp(eax, factory()->the_hole_value()); |
| 3217 __ j(equal, &miss); | 3151 __ j(equal, &miss); |
| 3218 } else if (FLAG_debug_code) { | 3152 } else if (FLAG_debug_code) { |
| 3219 __ cmp(eax, factory()->the_hole_value()); | 3153 __ cmp(eax, factory()->the_hole_value()); |
| 3220 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 3154 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
| 3221 } | 3155 } |
| 3222 | 3156 |
| 3223 HandlerFrontendFooter(&success, &miss); | 3157 HandlerFrontendFooter(name, &success, &miss); |
| 3224 __ bind(&success); | 3158 __ bind(&success); |
| 3225 | 3159 |
| 3226 Counters* counters = isolate()->counters(); | 3160 Counters* counters = isolate()->counters(); |
| 3227 __ IncrementCounter(counters->named_load_global_stub(), 1); | 3161 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 3228 // The code above already loads the result into the return register. | 3162 // The code above already loads the result into the return register. |
| 3229 __ ret(0); | 3163 __ ret(0); |
| 3230 | 3164 |
| 3231 // Return the generated code. | 3165 // Return the generated code. |
| 3232 return GetICCode(kind(), Code::NORMAL, name); | 3166 return GetICCode(kind(), Code::NORMAL, name); |
| 3233 } | 3167 } |
| 3234 | 3168 |
| 3235 | 3169 |
| 3236 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( | 3170 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( |
| 3237 MapHandleList* receiver_maps, | 3171 MapHandleList* receiver_maps, |
| 3238 CodeHandleList* handlers, | 3172 CodeHandleList* handlers, |
| 3239 Handle<Name> name, | 3173 Handle<Name> name, |
| 3240 Code::StubType type, | 3174 Code::StubType type, |
| 3241 IcCheckType check) { | 3175 IcCheckType check) { |
| 3242 Label miss; | 3176 Label miss; |
| 3243 | 3177 |
| 3244 if (check == PROPERTY) { | 3178 if (check == PROPERTY) { |
| 3245 GenerateNameCheck(name, this->name(), &miss); | 3179 GenerateNameCheck(name, this->name(), &miss); |
| 3246 } | 3180 } |
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3830 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); | 3764 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
| 3831 } | 3765 } |
| 3832 } | 3766 } |
| 3833 | 3767 |
| 3834 | 3768 |
| 3835 #undef __ | 3769 #undef __ |
| 3836 | 3770 |
| 3837 } } // namespace v8::internal | 3771 } } // namespace v8::internal |
| 3838 | 3772 |
| 3839 #endif // V8_TARGET_ARCH_IA32 | 3773 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |