Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(464)

Side by Side Diff: src/ia32/stub-cache-ia32.cc

Issue 14142005: Implement Polymorphic Store ICs (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« src/arm/stub-cache-arm.cc ('K') | « src/ia32/ic-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698