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

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: 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
« no previous file with comments | « src/ia32/ic-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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, 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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ia32/ic-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698