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