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