| 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 |