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 |