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 |