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

Side by Side Diff: src/x64/stub-cache-x64.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/x64/ic-x64.cc ('k') | no next file » | 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 739 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 Handle<PropertyCell> cell = 750 Handle<PropertyCell> cell =
751 GlobalObject::EnsurePropertyCell(global, name); 751 GlobalObject::EnsurePropertyCell(global, name);
752 ASSERT(cell->value()->IsTheHole()); 752 ASSERT(cell->value()->IsTheHole());
753 __ Move(scratch, cell); 753 __ Move(scratch, cell);
754 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), 754 __ Cmp(FieldOperand(scratch, Cell::kValueOffset),
755 masm->isolate()->factory()->the_hole_value()); 755 masm->isolate()->factory()->the_hole_value());
756 __ j(not_equal, miss); 756 __ j(not_equal, miss);
757 } 757 }
758 758
759 759
760 // Both name_reg and receiver_reg are preserved on jumps to miss_label, 760 void BaseStoreStubCompiler::GenerateNegativeHolderLookup(
761 // but may be destroyed if store is successful. 761 MacroAssembler* masm,
762 void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, 762 Handle<JSObject> holder,
763 Handle<JSObject> object, 763 Register holder_reg,
764 LookupResult* lookup, 764 Handle<Name> name,
765 Handle<Map> transition, 765 Label* miss) {
766 Handle<Name> name, 766 if (holder->IsJSGlobalObject()) {
767 Register receiver_reg, 767 GenerateCheckPropertyCell(
768 Register name_reg, 768 masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss);
769 Register value_reg, 769 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) {
770 Register scratch1, 770 GenerateDictionaryNegativeLookup(
771 Register scratch2, 771 masm, miss, holder_reg, name, scratch1(), scratch2());
772 Register unused, 772 }
773 Label* miss_label, 773 }
774 Label* miss_restore_name,
775 Label* slow) {
776 // Check that the map of the object hasn't changed.
777 __ CheckMap(receiver_reg, Handle<Map>(object->map()),
778 miss_label, DO_SMI_CHECK);
779 774
780 // Perform global security token check if needed.
781 if (object->IsJSGlobalProxy()) {
782 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label);
783 }
784 775
776 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if
777 // store is successful.
778 void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
779 Handle<JSObject> object,
780 LookupResult* lookup,
781 Handle<Map> transition,
782 Handle<Name> name,
783 Register receiver_reg,
784 Register storage_reg,
785 Register value_reg,
786 Register scratch1,
787 Register scratch2,
788 Register unused,
789 Label* miss_label,
790 Label* slow) {
785 int descriptor = transition->LastAdded(); 791 int descriptor = transition->LastAdded();
786 DescriptorArray* descriptors = transition->instance_descriptors(); 792 DescriptorArray* descriptors = transition->instance_descriptors();
787 PropertyDetails details = descriptors->GetDetails(descriptor); 793 PropertyDetails details = descriptors->GetDetails(descriptor);
788 Representation representation = details.representation(); 794 Representation representation = details.representation();
789 ASSERT(!representation.IsNone()); 795 ASSERT(!representation.IsNone());
790 796
791 // Ensure no transitions to deprecated maps are followed.
792 __ CheckMapDeprecated(transition, scratch1, miss_label);
793
794 // Check that we are allowed to write this.
795 if (object->GetPrototype()->IsJSObject()) {
796 JSObject* holder;
797 // holder == object indicates that no property was found.
798 if (lookup->holder() != *object) {
799 holder = lookup->holder();
800 } else {
801 // Find the top object.
802 holder = *object;
803 do {
804 holder = JSObject::cast(holder->GetPrototype());
805 } while (holder->GetPrototype()->IsJSObject());
806 }
807 Register holder_reg = CheckPrototypes(
808 object, receiver_reg, Handle<JSObject>(holder), name_reg,
809 scratch1, scratch2, name, miss_restore_name, SKIP_RECEIVER);
810 // If no property was found, and the holder (the last object in the
811 // prototype chain) is in slow mode, we need to do a negative lookup on the
812 // holder.
813 if (lookup->holder() == *object) {
814 if (holder->IsJSGlobalObject()) {
815 GenerateCheckPropertyCell(
816 masm,
817 Handle<GlobalObject>(GlobalObject::cast(holder)),
818 name,
819 scratch1,
820 miss_restore_name);
821 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) {
822 GenerateDictionaryNegativeLookup(
823 masm, miss_restore_name, holder_reg, name, scratch1, scratch2);
824 }
825 }
826 }
827
828 Register storage_reg = name_reg;
829
830 if (details.type() == CONSTANT_FUNCTION) { 797 if (details.type() == CONSTANT_FUNCTION) {
831 Handle<HeapObject> constant( 798 Handle<HeapObject> constant(
832 HeapObject::cast(descriptors->GetValue(descriptor))); 799 HeapObject::cast(descriptors->GetValue(descriptor)));
833 __ LoadHeapObject(scratch1, constant); 800 __ LoadHeapObject(scratch1, constant);
834 __ cmpq(value_reg, scratch1); 801 __ cmpq(value_reg, scratch1);
835 __ j(not_equal, miss_restore_name); 802 __ j(not_equal, miss_label);
836 } else if (FLAG_track_fields && representation.IsSmi()) { 803 } else if (FLAG_track_fields && representation.IsSmi()) {
837 __ JumpIfNotSmi(value_reg, miss_restore_name); 804 __ JumpIfNotSmi(value_reg, miss_label);
838 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { 805 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
839 __ JumpIfSmi(value_reg, miss_restore_name); 806 __ JumpIfSmi(value_reg, miss_label);
840 } else if (FLAG_track_double_fields && representation.IsDouble()) { 807 } else if (FLAG_track_double_fields && representation.IsDouble()) {
841 Label do_store, heap_number; 808 Label do_store, heap_number;
842 __ AllocateHeapNumber(storage_reg, scratch1, slow); 809 __ AllocateHeapNumber(storage_reg, scratch1, slow);
843 810
844 __ JumpIfNotSmi(value_reg, &heap_number); 811 __ JumpIfNotSmi(value_reg, &heap_number);
845 __ SmiToInteger32(scratch1, value_reg); 812 __ SmiToInteger32(scratch1, value_reg);
846 __ cvtlsi2sd(xmm0, scratch1); 813 __ cvtlsi2sd(xmm0, scratch1);
847 __ jmp(&do_store); 814 __ jmp(&do_store);
848 815
849 __ bind(&heap_number); 816 __ bind(&heap_number);
850 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(), 817 __ CheckMap(value_reg, masm->isolate()->factory()->heap_number_map(),
851 miss_restore_name, DONT_DO_SMI_CHECK); 818 miss_label, DONT_DO_SMI_CHECK);
852 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); 819 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset));
853 820
854 __ bind(&do_store); 821 __ bind(&do_store);
855 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); 822 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0);
856 } 823 }
857 824
858 // Stub never generated for non-global objects that require access 825 // Stub never generated for non-global objects that require access
859 // checks. 826 // checks.
860 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 827 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
861 828
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
911 // Set the property straight into the object. 878 // Set the property straight into the object.
912 int offset = object->map()->instance_size() + (index * kPointerSize); 879 int offset = object->map()->instance_size() + (index * kPointerSize);
913 if (FLAG_track_double_fields && representation.IsDouble()) { 880 if (FLAG_track_double_fields && representation.IsDouble()) {
914 __ movq(FieldOperand(receiver_reg, offset), storage_reg); 881 __ movq(FieldOperand(receiver_reg, offset), storage_reg);
915 } else { 882 } else {
916 __ movq(FieldOperand(receiver_reg, offset), value_reg); 883 __ movq(FieldOperand(receiver_reg, offset), value_reg);
917 } 884 }
918 885
919 if (!FLAG_track_fields || !representation.IsSmi()) { 886 if (!FLAG_track_fields || !representation.IsSmi()) {
920 // Update the write barrier for the array address. 887 // Update the write barrier for the array address.
921 // Pass the value being stored in the now unused name_reg.
922 if (!FLAG_track_double_fields || !representation.IsDouble()) { 888 if (!FLAG_track_double_fields || !representation.IsDouble()) {
923 __ movq(name_reg, value_reg); 889 __ movq(storage_reg, value_reg);
924 } else {
925 ASSERT(storage_reg.is(name_reg));
926 } 890 }
927 __ RecordWriteField( 891 __ RecordWriteField(
928 receiver_reg, offset, name_reg, scratch1, kDontSaveFPRegs, 892 receiver_reg, offset, storage_reg, scratch1, kDontSaveFPRegs,
929 EMIT_REMEMBERED_SET, smi_check); 893 EMIT_REMEMBERED_SET, smi_check);
930 } 894 }
931 } else { 895 } else {
932 // Write to the properties array. 896 // Write to the properties array.
933 int offset = index * kPointerSize + FixedArray::kHeaderSize; 897 int offset = index * kPointerSize + FixedArray::kHeaderSize;
934 // Get the properties array (optimistically). 898 // Get the properties array (optimistically).
935 __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); 899 __ movq(scratch1, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
936 if (FLAG_track_double_fields && representation.IsDouble()) { 900 if (FLAG_track_double_fields && representation.IsDouble()) {
937 __ movq(FieldOperand(scratch1, offset), storage_reg); 901 __ movq(FieldOperand(scratch1, offset), storage_reg);
938 } else { 902 } else {
939 __ movq(FieldOperand(scratch1, offset), value_reg); 903 __ movq(FieldOperand(scratch1, offset), value_reg);
940 } 904 }
941 905
942 if (!FLAG_track_fields || !representation.IsSmi()) { 906 if (!FLAG_track_fields || !representation.IsSmi()) {
943 // Update the write barrier for the array address. 907 // Update the write barrier for the array address.
944 // Pass the value being stored in the now unused name_reg.
945 if (!FLAG_track_double_fields || !representation.IsDouble()) { 908 if (!FLAG_track_double_fields || !representation.IsDouble()) {
946 __ movq(name_reg, value_reg); 909 __ movq(storage_reg, value_reg);
947 } else {
948 ASSERT(storage_reg.is(name_reg));
949 } 910 }
950 __ RecordWriteField( 911 __ RecordWriteField(
951 scratch1, offset, name_reg, receiver_reg, kDontSaveFPRegs, 912 scratch1, offset, storage_reg, receiver_reg, kDontSaveFPRegs,
952 EMIT_REMEMBERED_SET, smi_check); 913 EMIT_REMEMBERED_SET, smi_check);
953 } 914 }
954 } 915 }
955 916
956 // Return the value (register rax). 917 // Return the value (register rax).
957 ASSERT(value_reg.is(rax)); 918 ASSERT(value_reg.is(rax));
958 __ ret(0); 919 __ ret(0);
959 } 920 }
960 921
961 922
962 // Both name_reg and receiver_reg are preserved on jumps to miss_label, 923 // Both name_reg and receiver_reg are preserved on jumps to miss_label,
963 // but may be destroyed if store is successful. 924 // but may be destroyed if store is successful.
964 void StubCompiler::GenerateStoreField(MacroAssembler* masm, 925 void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
965 Handle<JSObject> object, 926 Handle<JSObject> object,
966 LookupResult* lookup, 927 LookupResult* lookup,
967 Register receiver_reg, 928 Register receiver_reg,
968 Register name_reg, 929 Register name_reg,
969 Register value_reg, 930 Register value_reg,
970 Register scratch1, 931 Register scratch1,
971 Register scratch2, 932 Register scratch2,
972 Label* miss_label) { 933 Label* miss_label) {
973 // Check that the map of the object hasn't changed.
974 __ CheckMap(receiver_reg, Handle<Map>(object->map()),
975 miss_label, DO_SMI_CHECK);
976
977 // Perform global security token check if needed.
978 if (object->IsJSGlobalProxy()) {
979 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label);
980 }
981
982 // Stub never generated for non-global objects that require access 934 // Stub never generated for non-global objects that require access
983 // checks. 935 // checks.
984 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 936 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
985 937
986 int index = lookup->GetFieldIndex().field_index(); 938 int index = lookup->GetFieldIndex().field_index();
987 939
988 // Adjust for the number of properties stored in the object. Even in the 940 // Adjust for the number of properties stored in the object. Even in the
989 // face of a transition we can use the old map here because the size of the 941 // face of a transition we can use the old map here because the size of the
990 // object and the number of in-object properties is not going to change. 942 // object and the number of in-object properties is not going to change.
991 index -= object->map()->inobject_properties(); 943 index -= object->map()->inobject_properties();
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
1205 // If we've skipped any global objects, it's not enough to verify that 1157 // If we've skipped any global objects, it's not enough to verify that
1206 // their maps haven't changed. We also need to check that the property 1158 // their maps haven't changed. We also need to check that the property
1207 // cell for the property is still empty. 1159 // cell for the property is still empty.
1208 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 1160 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1209 1161
1210 // Return the register containing the holder. 1162 // Return the register containing the holder.
1211 return reg; 1163 return reg;
1212 } 1164 }
1213 1165
1214 1166
1215 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, 1167 void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
1168 Label* success,
1216 Label* miss) { 1169 Label* miss) {
1217 if (!miss->is_unused()) { 1170 if (!miss->is_unused()) {
1218 __ jmp(success); 1171 __ jmp(success);
1219 __ bind(miss); 1172 __ bind(miss);
1220 TailCallBuiltin(masm(), MissBuiltin(kind())); 1173 TailCallBuiltin(masm(), MissBuiltin(kind()));
1221 } 1174 }
1222 } 1175 }
1223 1176
1224 1177
1178 void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
1179 Label* success,
1180 Label* miss) {
1181 if (!miss->is_unused()) {
1182 __ jmp(success);
1183 GenerateRestoreName(masm(), miss, name);
1184 TailCallBuiltin(masm(), MissBuiltin(kind()));
1185 }
1186 }
1187
1188
1225 Register BaseLoadStubCompiler::CallbackHandlerFrontend( 1189 Register BaseLoadStubCompiler::CallbackHandlerFrontend(
1226 Handle<JSObject> object, 1190 Handle<JSObject> object,
1227 Register object_reg, 1191 Register object_reg,
1228 Handle<JSObject> holder, 1192 Handle<JSObject> holder,
1229 Handle<Name> name, 1193 Handle<Name> name,
1230 Label* success, 1194 Label* success,
1231 Handle<ExecutableAccessorInfo> callback) { 1195 Handle<ExecutableAccessorInfo> callback) {
1232 Label miss; 1196 Label miss;
1233 1197
1234 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); 1198 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
(...skipping 26 matching lines...) Expand all
1261 NameDictionary::kElementsStartIndex * kPointerSize; 1225 NameDictionary::kElementsStartIndex * kPointerSize;
1262 const int kValueOffset = kElementsStartOffset + kPointerSize; 1226 const int kValueOffset = kElementsStartOffset + kPointerSize;
1263 __ movq(scratch2(), 1227 __ movq(scratch2(),
1264 Operand(dictionary, index, times_pointer_size, 1228 Operand(dictionary, index, times_pointer_size,
1265 kValueOffset - kHeapObjectTag)); 1229 kValueOffset - kHeapObjectTag));
1266 __ movq(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT); 1230 __ movq(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT);
1267 __ cmpq(scratch2(), scratch3()); 1231 __ cmpq(scratch2(), scratch3());
1268 __ j(not_equal, &miss); 1232 __ j(not_equal, &miss);
1269 } 1233 }
1270 1234
1271 HandlerFrontendFooter(success, &miss); 1235 HandlerFrontendFooter(name, success, &miss);
1272 return reg; 1236 return reg;
1273 } 1237 }
1274 1238
1275 1239
1276 void BaseLoadStubCompiler::NonexistentHandlerFrontend( 1240 void BaseLoadStubCompiler::NonexistentHandlerFrontend(
1277 Handle<JSObject> object, 1241 Handle<JSObject> object,
1278 Handle<JSObject> last, 1242 Handle<JSObject> last,
1279 Handle<Name> name, 1243 Handle<Name> name,
1280 Label* success, 1244 Label* success,
1281 Handle<GlobalObject> global) { 1245 Handle<GlobalObject> global) {
1282 Label miss; 1246 Label miss;
1283 1247
1284 HandlerFrontendHeader(object, receiver(), last, name, &miss); 1248 HandlerFrontendHeader(object, receiver(), last, name, &miss);
1285 1249
1286 // If the last object in the prototype chain is a global object, 1250 // If the last object in the prototype chain is a global object,
1287 // check that the global property cell is empty. 1251 // check that the global property cell is empty.
1288 if (!global.is_null()) { 1252 if (!global.is_null()) {
1289 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); 1253 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
1290 } 1254 }
1291 1255
1292 HandlerFrontendFooter(success, &miss); 1256 HandlerFrontendFooter(name, success, &miss);
1293 } 1257 }
1294 1258
1295 1259
1296 void BaseLoadStubCompiler::GenerateLoadField(Register reg, 1260 void BaseLoadStubCompiler::GenerateLoadField(Register reg,
1297 Handle<JSObject> holder, 1261 Handle<JSObject> holder,
1298 PropertyIndex field, 1262 PropertyIndex field,
1299 Representation representation) { 1263 Representation representation) {
1300 if (!reg.is(receiver())) __ movq(receiver(), reg); 1264 if (!reg.is(receiver())) __ movq(receiver(), reg);
1301 if (kind() == Code::LOAD_IC) { 1265 if (kind() == Code::LOAD_IC) {
1302 LoadFieldStub stub(field.is_inobject(holder), 1266 LoadFieldStub stub(field.is_inobject(holder),
(...skipping 1364 matching lines...) Expand 10 before | Expand all | Expand 10 after
2667 __ bind(&miss); 2631 __ bind(&miss);
2668 __ IncrementCounter(counters->call_global_inline_miss(), 1); 2632 __ IncrementCounter(counters->call_global_inline_miss(), 1);
2669 GenerateMissBranch(); 2633 GenerateMissBranch();
2670 2634
2671 // Return the generated code. 2635 // Return the generated code.
2672 return GetCode(Code::NORMAL, name); 2636 return GetCode(Code::NORMAL, name);
2673 } 2637 }
2674 2638
2675 2639
2676 Handle<Code> StoreStubCompiler::CompileStoreCallback( 2640 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2677 Handle<Name> name,
2678 Handle<JSObject> object, 2641 Handle<JSObject> object,
2679 Handle<JSObject> holder, 2642 Handle<JSObject> holder,
2643 Handle<Name> name,
2680 Handle<ExecutableAccessorInfo> callback) { 2644 Handle<ExecutableAccessorInfo> callback) {
2681 Label miss; 2645 Label success;
2682 // Check that the maps haven't changed. 2646 HandlerFrontend(object, receiver(), holder, name, &success);
2683 __ JumpIfSmi(receiver(), &miss); 2647 __ bind(&success);
2684 CheckPrototypes(object, receiver(), holder,
2685 scratch1(), scratch2(), scratch3(), name, &miss);
2686
2687 // Stub never generated for non-global objects that require access checks.
2688 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
2689 2648
2690 __ pop(scratch1()); // remove the return address 2649 __ pop(scratch1()); // remove the return address
2691 __ push(receiver()); 2650 __ push(receiver());
2692 __ Push(callback); // callback info 2651 __ Push(callback); // callback info
2693 __ push(this->name()); 2652 __ Push(name);
2694 __ push(value()); 2653 __ push(value());
2695 __ push(scratch1()); // restore return address 2654 __ push(scratch1()); // restore return address
2696 2655
2697 // Do tail-call to the runtime system. 2656 // Do tail-call to the runtime system.
2698 ExternalReference store_callback_property = 2657 ExternalReference store_callback_property =
2699 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 2658 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
2700 __ TailCallExternalReference(store_callback_property, 4, 1); 2659 __ TailCallExternalReference(store_callback_property, 4, 1);
2701 2660
2702 // Handle store cache miss.
2703 __ bind(&miss);
2704 TailCallBuiltin(masm(), MissBuiltin(kind()));
2705
2706 // Return the generated code. 2661 // Return the generated code.
2707 return GetICCode(kind(), Code::CALLBACKS, name); 2662 return GetCode(kind(), Code::CALLBACKS, name);
2708 } 2663 }
2709 2664
2710 2665
2711 #undef __ 2666 #undef __
2712 #define __ ACCESS_MASM(masm) 2667 #define __ ACCESS_MASM(masm)
2713 2668
2714 2669
2715 void StoreStubCompiler::GenerateStoreViaSetter( 2670 void StoreStubCompiler::GenerateStoreViaSetter(
2716 MacroAssembler* masm, 2671 MacroAssembler* masm,
2717 Handle<JSFunction> setter) { 2672 Handle<JSFunction> setter) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2751 } 2706 }
2752 2707
2753 2708
2754 #undef __ 2709 #undef __
2755 #define __ ACCESS_MASM(masm()) 2710 #define __ ACCESS_MASM(masm())
2756 2711
2757 2712
2758 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( 2713 Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
2759 Handle<JSObject> object, 2714 Handle<JSObject> object,
2760 Handle<Name> name) { 2715 Handle<Name> name) {
2761 Label miss;
2762
2763 // Check that the map of the object hasn't changed.
2764 __ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK);
2765
2766 // Perform global security token check if needed.
2767 if (object->IsJSGlobalProxy()) {
2768 __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss);
2769 }
2770
2771 // Stub never generated for non-global objects that require access
2772 // checks.
2773 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
2774
2775 __ pop(scratch1()); // remove the return address 2716 __ pop(scratch1()); // remove the return address
2776 __ push(receiver()); 2717 __ push(receiver());
2777 __ push(this->name()); 2718 __ push(this->name());
2778 __ push(value()); 2719 __ push(value());
2779 __ Push(Smi::FromInt(strict_mode())); 2720 __ Push(Smi::FromInt(strict_mode()));
2780 __ push(scratch1()); // restore return address 2721 __ push(scratch1()); // restore return address
2781 2722
2782 // Do tail-call to the runtime system. 2723 // Do tail-call to the runtime system.
2783 ExternalReference store_ic_property = 2724 ExternalReference store_ic_property =
2784 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); 2725 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate());
2785 __ TailCallExternalReference(store_ic_property, 4, 1); 2726 __ TailCallExternalReference(store_ic_property, 4, 1);
2786 2727
2787 // Handle store cache miss.
2788 __ bind(&miss);
2789 TailCallBuiltin(masm(), MissBuiltin(kind()));
2790
2791 // Return the generated code. 2728 // Return the generated code.
2792 return GetICCode(kind(), Code::INTERCEPTOR, name); 2729 return GetCode(kind(), Code::INTERCEPTOR, name);
2793 } 2730 }
2794 2731
2795 2732
2796 Handle<Code> StoreStubCompiler::CompileStoreGlobal( 2733 Handle<Code> StoreStubCompiler::CompileStoreGlobal(
2797 Handle<GlobalObject> object, 2734 Handle<GlobalObject> object,
2798 Handle<PropertyCell> cell, 2735 Handle<PropertyCell> cell,
2799 Handle<Name> name) { 2736 Handle<Name> name) {
2800 Label miss; 2737 Label miss;
2801 2738
2802 // Check that the map of the global has not changed. 2739 // Check that the map of the global has not changed.
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
2993 2930
2994 // Check for deleted property if property can actually be deleted. 2931 // Check for deleted property if property can actually be deleted.
2995 if (!is_dont_delete) { 2932 if (!is_dont_delete) {
2996 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 2933 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
2997 __ j(equal, &miss); 2934 __ j(equal, &miss);
2998 } else if (FLAG_debug_code) { 2935 } else if (FLAG_debug_code) {
2999 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 2936 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
3000 __ Check(not_equal, "DontDelete cells can't contain the hole"); 2937 __ Check(not_equal, "DontDelete cells can't contain the hole");
3001 } 2938 }
3002 2939
3003 HandlerFrontendFooter(&success, &miss); 2940 HandlerFrontendFooter(name, &success, &miss);
3004 __ bind(&success); 2941 __ bind(&success);
3005 2942
3006 Counters* counters = isolate()->counters(); 2943 Counters* counters = isolate()->counters();
3007 __ IncrementCounter(counters->named_load_global_stub(), 1); 2944 __ IncrementCounter(counters->named_load_global_stub(), 1);
3008 __ movq(rax, rbx); 2945 __ movq(rax, rbx);
3009 __ ret(0); 2946 __ ret(0);
3010 2947
3011 // Return the generated code. 2948 // Return the generated code.
3012 return GetICCode(kind(), Code::NORMAL, name); 2949 return GetICCode(kind(), Code::NORMAL, name);
3013 } 2950 }
3014 2951
3015 2952
3016 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( 2953 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
3017 MapHandleList* receiver_maps, 2954 MapHandleList* receiver_maps,
3018 CodeHandleList* handlers, 2955 CodeHandleList* handlers,
3019 Handle<Name> name, 2956 Handle<Name> name,
3020 Code::StubType type, 2957 Code::StubType type,
3021 IcCheckType check) { 2958 IcCheckType check) {
3022 Label miss; 2959 Label miss;
3023 2960
3024 if (check == PROPERTY) { 2961 if (check == PROPERTY) {
3025 GenerateNameCheck(name, this->name(), &miss); 2962 GenerateNameCheck(name, this->name(), &miss);
3026 } 2963 }
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after
3573 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); 3510 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
3574 } 3511 }
3575 } 3512 }
3576 3513
3577 3514
3578 #undef __ 3515 #undef __
3579 3516
3580 } } // namespace v8::internal 3517 } } // namespace v8::internal
3581 3518
3582 #endif // V8_TARGET_ARCH_X64 3519 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/ic-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698