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 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |