| 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 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 __ push(receiver); | 372 __ push(receiver); |
| 373 __ push(holder); | 373 __ push(holder); |
| 374 } | 374 } |
| 375 | 375 |
| 376 | 376 |
| 377 static void CompileCallLoadPropertyWithInterceptor( | 377 static void CompileCallLoadPropertyWithInterceptor( |
| 378 MacroAssembler* masm, | 378 MacroAssembler* masm, |
| 379 Register receiver, | 379 Register receiver, |
| 380 Register holder, | 380 Register holder, |
| 381 Register name, | 381 Register name, |
| 382 Handle<JSObject> holder_obj) { | 382 Handle<JSObject> holder_obj, |
| 383 IC::UtilityId id) { |
| 383 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 384 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 384 | 385 __ CallExternalReference( |
| 385 ExternalReference ref = | 386 ExternalReference(IC_Utility(id), masm->isolate()), |
| 386 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 387 StubCache::kInterceptorArgsLength); |
| 387 masm->isolate()); | |
| 388 __ Set(rax, StubCache::kInterceptorArgsLength); | |
| 389 __ LoadAddress(rbx, ref); | |
| 390 | |
| 391 CEntryStub stub(1); | |
| 392 __ CallStub(&stub); | |
| 393 } | 388 } |
| 394 | 389 |
| 395 | 390 |
| 396 // Number of pointers to be reserved on stack for fast API call. | 391 // Number of pointers to be reserved on stack for fast API call. |
| 397 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; | 392 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; |
| 398 | 393 |
| 399 | 394 |
| 400 // Reserves space for the extra arguments to API function in the | 395 // Reserves space for the extra arguments to API function in the |
| 401 // caller's frame. | 396 // caller's frame. |
| 402 // | 397 // |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 if (can_do_fast_api_call) { | 708 if (can_do_fast_api_call) { |
| 714 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); | 709 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); |
| 715 ReserveSpaceForFastApiCall(masm, scratch1); | 710 ReserveSpaceForFastApiCall(masm, scratch1); |
| 716 } | 711 } |
| 717 | 712 |
| 718 // Check that the maps from receiver to interceptor's holder | 713 // Check that the maps from receiver to interceptor's holder |
| 719 // haven't changed and thus we can invoke interceptor. | 714 // haven't changed and thus we can invoke interceptor. |
| 720 Label miss_cleanup; | 715 Label miss_cleanup; |
| 721 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 716 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 722 Register holder = | 717 Register holder = |
| 723 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 718 stub_compiler_->CheckPrototypes( |
| 724 scratch1, scratch2, scratch3, | 719 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 725 name, depth1, miss); | 720 interceptor_holder, scratch1, scratch2, scratch3, |
| 721 name, depth1, miss); |
| 726 | 722 |
| 727 // Invoke an interceptor and if it provides a value, | 723 // Invoke an interceptor and if it provides a value, |
| 728 // branch to |regular_invoke|. | 724 // branch to |regular_invoke|. |
| 729 Label regular_invoke; | 725 Label regular_invoke; |
| 730 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, | 726 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, |
| 731 ®ular_invoke); | 727 ®ular_invoke); |
| 732 | 728 |
| 733 // Interceptor returned nothing for this property. Try to use cached | 729 // Interceptor returned nothing for this property. Try to use cached |
| 734 // constant function. | 730 // constant function. |
| 735 | 731 |
| 736 // Check that the maps from interceptor's holder to constant function's | 732 // Check that the maps from interceptor's holder to constant function's |
| 737 // holder haven't changed and thus we can use cached constant function. | 733 // holder haven't changed and thus we can use cached constant function. |
| 738 if (*interceptor_holder != lookup->holder()) { | 734 if (*interceptor_holder != lookup->holder()) { |
| 739 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 735 stub_compiler_->CheckPrototypes( |
| 740 Handle<JSObject>(lookup->holder()), | 736 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), receiver, |
| 741 scratch1, scratch2, scratch3, | 737 handle(lookup->holder()), scratch1, scratch2, scratch3, |
| 742 name, depth2, miss); | 738 name, depth2, miss); |
| 743 } else { | 739 } else { |
| 744 // CheckPrototypes has a side effect of fetching a 'holder' | 740 // CheckPrototypes has a side effect of fetching a 'holder' |
| 745 // for API (object which is instanceof for the signature). It's | 741 // for API (object which is instanceof for the signature). It's |
| 746 // safe to omit it here, as if present, it should be fetched | 742 // safe to omit it here, as if present, it should be fetched |
| 747 // by the previous CheckPrototypes. | 743 // by the previous CheckPrototypes. |
| 748 ASSERT(depth2 == kInvalidProtoDepth); | 744 ASSERT(depth2 == kInvalidProtoDepth); |
| 749 } | 745 } |
| 750 | 746 |
| 751 // Invoke function. | 747 // Invoke function. |
| 752 if (can_do_fast_api_call) { | 748 if (can_do_fast_api_call) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 778 void CompileRegular(MacroAssembler* masm, | 774 void CompileRegular(MacroAssembler* masm, |
| 779 Handle<JSObject> object, | 775 Handle<JSObject> object, |
| 780 Register receiver, | 776 Register receiver, |
| 781 Register scratch1, | 777 Register scratch1, |
| 782 Register scratch2, | 778 Register scratch2, |
| 783 Register scratch3, | 779 Register scratch3, |
| 784 Handle<Name> name, | 780 Handle<Name> name, |
| 785 Handle<JSObject> interceptor_holder, | 781 Handle<JSObject> interceptor_holder, |
| 786 Label* miss_label) { | 782 Label* miss_label) { |
| 787 Register holder = | 783 Register holder = |
| 788 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 784 stub_compiler_->CheckPrototypes( |
| 789 scratch1, scratch2, scratch3, | 785 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 790 name, miss_label); | 786 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label); |
| 791 | 787 |
| 792 FrameScope scope(masm, StackFrame::INTERNAL); | 788 FrameScope scope(masm, StackFrame::INTERNAL); |
| 793 // Save the name_ register across the call. | 789 // Save the name_ register across the call. |
| 794 __ push(name_); | 790 __ push(name_); |
| 795 | 791 |
| 796 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); | 792 CompileCallLoadPropertyWithInterceptor( |
| 797 | 793 masm, receiver, holder, name_, interceptor_holder, |
| 798 __ CallExternalReference( | 794 IC::kLoadPropertyWithInterceptorForCall); |
| 799 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | |
| 800 masm->isolate()), | |
| 801 StubCache::kInterceptorArgsLength); | |
| 802 | 795 |
| 803 // Restore the name_ register. | 796 // Restore the name_ register. |
| 804 __ pop(name_); | 797 __ pop(name_); |
| 805 | 798 |
| 806 // Leave the internal frame. | 799 // Leave the internal frame. |
| 807 } | 800 } |
| 808 | 801 |
| 809 void LoadWithInterceptor(MacroAssembler* masm, | 802 void LoadWithInterceptor(MacroAssembler* masm, |
| 810 Register receiver, | 803 Register receiver, |
| 811 Register holder, | 804 Register holder, |
| 812 Handle<JSObject> holder_obj, | 805 Handle<JSObject> holder_obj, |
| 813 Label* interceptor_succeeded) { | 806 Label* interceptor_succeeded) { |
| 814 { | 807 { |
| 815 FrameScope scope(masm, StackFrame::INTERNAL); | 808 FrameScope scope(masm, StackFrame::INTERNAL); |
| 816 __ push(holder); // Save the holder. | 809 __ push(holder); // Save the holder. |
| 817 __ push(name_); // Save the name. | 810 __ push(name_); // Save the name. |
| 818 | 811 |
| 819 CompileCallLoadPropertyWithInterceptor(masm, | 812 CompileCallLoadPropertyWithInterceptor( |
| 820 receiver, | 813 masm, receiver, holder, name_, holder_obj, |
| 821 holder, | 814 IC::kLoadPropertyWithInterceptorOnly); |
| 822 name_, | |
| 823 holder_obj); | |
| 824 | 815 |
| 825 __ pop(name_); // Restore the name. | 816 __ pop(name_); // Restore the name. |
| 826 __ pop(receiver); // Restore the holder. | 817 __ pop(receiver); // Restore the holder. |
| 827 // Leave the internal frame. | 818 // Leave the internal frame. |
| 828 } | 819 } |
| 829 | 820 |
| 830 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 821 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
| 831 __ j(not_equal, interceptor_succeeded); | 822 __ j(not_equal, interceptor_succeeded); |
| 832 } | 823 } |
| 833 | 824 |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1115 EMIT_REMEMBERED_SET, smi_check); | 1106 EMIT_REMEMBERED_SET, smi_check); |
| 1116 } | 1107 } |
| 1117 } | 1108 } |
| 1118 | 1109 |
| 1119 // Return the value (register rax). | 1110 // Return the value (register rax). |
| 1120 ASSERT(value_reg.is(rax)); | 1111 ASSERT(value_reg.is(rax)); |
| 1121 __ ret(0); | 1112 __ ret(0); |
| 1122 } | 1113 } |
| 1123 | 1114 |
| 1124 | 1115 |
| 1125 void StubCompiler::GenerateCheckPropertyCells(MacroAssembler* masm, | |
| 1126 Handle<JSObject> object, | |
| 1127 Handle<JSObject> holder, | |
| 1128 Handle<Name> name, | |
| 1129 Register scratch, | |
| 1130 Label* miss) { | |
| 1131 Handle<JSObject> current = object; | |
| 1132 while (!current.is_identical_to(holder)) { | |
| 1133 if (current->IsJSGlobalObject()) { | |
| 1134 GenerateCheckPropertyCell(masm, | |
| 1135 Handle<JSGlobalObject>::cast(current), | |
| 1136 name, | |
| 1137 scratch, | |
| 1138 miss); | |
| 1139 } | |
| 1140 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | |
| 1141 } | |
| 1142 } | |
| 1143 | |
| 1144 | |
| 1145 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1116 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1146 __ jmp(code, RelocInfo::CODE_TARGET); | 1117 __ jmp(code, RelocInfo::CODE_TARGET); |
| 1147 } | 1118 } |
| 1148 | 1119 |
| 1149 | 1120 |
| 1150 #undef __ | 1121 #undef __ |
| 1151 #define __ ACCESS_MASM((masm())) | 1122 #define __ ACCESS_MASM((masm())) |
| 1152 | 1123 |
| 1153 | 1124 |
| 1154 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1125 Register StubCompiler::CheckPrototypes(Handle<Type> type, |
| 1155 Register object_reg, | 1126 Register object_reg, |
| 1156 Handle<JSObject> holder, | 1127 Handle<JSObject> holder, |
| 1157 Register holder_reg, | 1128 Register holder_reg, |
| 1158 Register scratch1, | 1129 Register scratch1, |
| 1159 Register scratch2, | 1130 Register scratch2, |
| 1160 Handle<Name> name, | 1131 Handle<Name> name, |
| 1161 int save_at_depth, | 1132 int save_at_depth, |
| 1162 Label* miss, | 1133 Label* miss, |
| 1163 PrototypeCheckType check) { | 1134 PrototypeCheckType check) { |
| 1135 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
| 1164 // Make sure that the type feedback oracle harvests the receiver map. | 1136 // Make sure that the type feedback oracle harvests the receiver map. |
| 1165 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1137 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
| 1166 __ Move(scratch1, Handle<Map>(object->map())); | 1138 __ Move(scratch1, receiver_map); |
| 1167 | 1139 |
| 1168 Handle<JSObject> first = object; | |
| 1169 // Make sure there's no overlap between holder and object registers. | 1140 // Make sure there's no overlap between holder and object registers. |
| 1170 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1141 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 1171 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1142 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 1172 && !scratch2.is(scratch1)); | 1143 && !scratch2.is(scratch1)); |
| 1173 | 1144 |
| 1174 // Keep track of the current object in register reg. On the first | 1145 // Keep track of the current object in register reg. On the first |
| 1175 // iteration, reg is an alias for object_reg, on later iterations, | 1146 // iteration, reg is an alias for object_reg, on later iterations, |
| 1176 // it is an alias for holder_reg. | 1147 // it is an alias for holder_reg. |
| 1177 Register reg = object_reg; | 1148 Register reg = object_reg; |
| 1178 int depth = 0; | 1149 int depth = 0; |
| 1179 | 1150 |
| 1180 StackArgumentsAccessor args(rsp, kFastApiCallArguments, | 1151 StackArgumentsAccessor args(rsp, kFastApiCallArguments, |
| 1181 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 1152 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 1182 const int kHolderIndex = kFastApiCallArguments - 1 - | 1153 const int kHolderIndex = kFastApiCallArguments - 1 - |
| 1183 FunctionCallbackArguments::kHolderIndex; | 1154 FunctionCallbackArguments::kHolderIndex; |
| 1184 | 1155 |
| 1185 if (save_at_depth == depth) { | 1156 if (save_at_depth == depth) { |
| 1186 __ movq(args.GetArgumentOperand(kHolderIndex), object_reg); | 1157 __ movq(args.GetArgumentOperand(kHolderIndex), object_reg); |
| 1187 } | 1158 } |
| 1188 | 1159 |
| 1189 // Check the maps in the prototype chain. | 1160 Handle<JSObject> current = Handle<JSObject>::null(); |
| 1190 // Traverse the prototype chain from the object and do map checks. | 1161 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); |
| 1191 Handle<JSObject> current = object; | 1162 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 1192 while (!current.is_identical_to(holder)) { | 1163 Handle<Map> current_map = receiver_map; |
| 1164 Handle<Map> holder_map(holder->map()); |
| 1165 // Traverse the prototype chain and check the maps in the prototype chain for |
| 1166 // fast and global objects or do negative lookup for normal objects. |
| 1167 while (!current_map.is_identical_to(holder_map)) { |
| 1193 ++depth; | 1168 ++depth; |
| 1194 | 1169 |
| 1195 // Only global objects and objects that do not require access | 1170 // Only global objects and objects that do not require access |
| 1196 // checks are allowed in stubs. | 1171 // checks are allowed in stubs. |
| 1197 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1172 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1173 !current_map->is_access_check_needed()); |
| 1198 | 1174 |
| 1199 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); | 1175 prototype = handle(JSObject::cast(current_map->prototype())); |
| 1200 if (!current->HasFastProperties() && | 1176 if (current_map->is_dictionary_map() && |
| 1201 !current->IsJSGlobalObject() && | 1177 !current_map->IsJSGlobalObjectMap() && |
| 1202 !current->IsJSGlobalProxy()) { | 1178 !current_map->IsJSGlobalProxyMap()) { |
| 1203 if (!name->IsUniqueName()) { | 1179 if (!name->IsUniqueName()) { |
| 1204 ASSERT(name->IsString()); | 1180 ASSERT(name->IsString()); |
| 1205 name = factory()->InternalizeString(Handle<String>::cast(name)); | 1181 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 1206 } | 1182 } |
| 1207 ASSERT(current->property_dictionary()->FindEntry(*name) == | 1183 ASSERT(current.is_null() || |
| 1184 current->property_dictionary()->FindEntry(*name) == |
| 1208 NameDictionary::kNotFound); | 1185 NameDictionary::kNotFound); |
| 1209 | 1186 |
| 1210 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 1187 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 1211 scratch1, scratch2); | 1188 scratch1, scratch2); |
| 1212 | 1189 |
| 1213 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1190 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1214 reg = holder_reg; // From now on the object will be in holder_reg. | 1191 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1215 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1192 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1216 } else { | 1193 } else { |
| 1217 bool in_new_space = heap()->InNewSpace(*prototype); | 1194 bool in_new_space = heap()->InNewSpace(*prototype); |
| 1218 Handle<Map> current_map(current->map()); | |
| 1219 if (in_new_space) { | 1195 if (in_new_space) { |
| 1220 // Save the map in scratch1 for later. | 1196 // Save the map in scratch1 for later. |
| 1221 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1197 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1222 } | 1198 } |
| 1223 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { | 1199 if (depth != 1 || check == CHECK_ALL_MAPS) { |
| 1224 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); | 1200 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); |
| 1225 } | 1201 } |
| 1226 | 1202 |
| 1227 // Check access rights to the global object. This has to happen after | 1203 // Check access rights to the global object. This has to happen after |
| 1228 // the map check so that we know that the object is actually a global | 1204 // the map check so that we know that the object is actually a global |
| 1229 // object. | 1205 // object. |
| 1230 if (current->IsJSGlobalProxy()) { | 1206 if (current_map->IsJSGlobalProxyMap()) { |
| 1231 __ CheckAccessGlobalProxy(reg, scratch2, miss); | 1207 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 1208 } else if (current_map->IsJSGlobalObjectMap()) { |
| 1209 GenerateCheckPropertyCell( |
| 1210 masm(), Handle<JSGlobalObject>::cast(current), name, |
| 1211 scratch2, miss); |
| 1232 } | 1212 } |
| 1233 reg = holder_reg; // From now on the object will be in holder_reg. | 1213 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1234 | 1214 |
| 1235 if (in_new_space) { | 1215 if (in_new_space) { |
| 1236 // The prototype is in new space; we cannot store a reference to it | 1216 // The prototype is in new space; we cannot store a reference to it |
| 1237 // in the code. Load it from the map. | 1217 // in the code. Load it from the map. |
| 1238 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1218 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1239 } else { | 1219 } else { |
| 1240 // The prototype is in old space; load it directly. | 1220 // The prototype is in old space; load it directly. |
| 1241 __ Move(reg, prototype); | 1221 __ Move(reg, prototype); |
| 1242 } | 1222 } |
| 1243 } | 1223 } |
| 1244 | 1224 |
| 1245 if (save_at_depth == depth) { | 1225 if (save_at_depth == depth) { |
| 1246 __ movq(args.GetArgumentOperand(kHolderIndex), reg); | 1226 __ movq(args.GetArgumentOperand(kHolderIndex), reg); |
| 1247 } | 1227 } |
| 1248 | 1228 |
| 1249 // Go to the next object in the prototype chain. | 1229 // Go to the next object in the prototype chain. |
| 1250 current = prototype; | 1230 current = prototype; |
| 1231 current_map = handle(current->map()); |
| 1251 } | 1232 } |
| 1252 ASSERT(current.is_identical_to(holder)); | |
| 1253 | 1233 |
| 1254 // Log the check depth. | 1234 // Log the check depth. |
| 1255 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1235 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1256 | 1236 |
| 1257 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { | 1237 if (depth != 0 || check == CHECK_ALL_MAPS) { |
| 1258 // Check the holder map. | 1238 // Check the holder map. |
| 1259 __ CheckMap(reg, Handle<Map>(holder->map()), miss, DONT_DO_SMI_CHECK); | 1239 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); |
| 1260 } | 1240 } |
| 1261 | 1241 |
| 1262 // Perform security check for access to the global object. | 1242 // Perform security check for access to the global object. |
| 1263 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1243 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1264 if (current->IsJSGlobalProxy()) { | 1244 !current_map->is_access_check_needed()); |
| 1245 if (current_map->IsJSGlobalProxyMap()) { |
| 1265 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1246 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1266 } | 1247 } |
| 1267 | 1248 |
| 1268 // If we've skipped any global objects, it's not enough to verify that | |
| 1269 // their maps haven't changed. We also need to check that the property | |
| 1270 // cell for the property is still empty. | |
| 1271 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | |
| 1272 | |
| 1273 // Return the register containing the holder. | 1249 // Return the register containing the holder. |
| 1274 return reg; | 1250 return reg; |
| 1275 } | 1251 } |
| 1276 | 1252 |
| 1277 | 1253 |
| 1278 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 1254 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1279 if (!miss->is_unused()) { | 1255 if (!miss->is_unused()) { |
| 1280 Label success; | 1256 Label success; |
| 1281 __ jmp(&success); | 1257 __ jmp(&success); |
| 1282 __ bind(miss); | 1258 __ bind(miss); |
| 1283 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1259 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1284 __ bind(&success); | 1260 __ bind(&success); |
| 1285 } | 1261 } |
| 1286 } | 1262 } |
| 1287 | 1263 |
| 1288 | 1264 |
| 1289 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 1265 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1290 if (!miss->is_unused()) { | 1266 if (!miss->is_unused()) { |
| 1291 Label success; | 1267 Label success; |
| 1292 __ jmp(&success); | 1268 __ jmp(&success); |
| 1293 GenerateRestoreName(masm(), miss, name); | 1269 GenerateRestoreName(masm(), miss, name); |
| 1294 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1270 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1295 __ bind(&success); | 1271 __ bind(&success); |
| 1296 } | 1272 } |
| 1297 } | 1273 } |
| 1298 | 1274 |
| 1299 | 1275 |
| 1300 Register LoadStubCompiler::CallbackHandlerFrontend( | 1276 Register LoadStubCompiler::CallbackHandlerFrontend( |
| 1301 Handle<Object> object, | 1277 Handle<Type> type, |
| 1302 Register object_reg, | 1278 Register object_reg, |
| 1303 Handle<JSObject> holder, | 1279 Handle<JSObject> holder, |
| 1304 Handle<Name> name, | 1280 Handle<Name> name, |
| 1305 Handle<Object> callback) { | 1281 Handle<Object> callback) { |
| 1306 Label miss; | 1282 Label miss; |
| 1307 | 1283 |
| 1308 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1284 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); |
| 1309 | 1285 |
| 1310 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1286 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| 1311 ASSERT(!reg.is(scratch2())); | 1287 ASSERT(!reg.is(scratch2())); |
| 1312 ASSERT(!reg.is(scratch3())); | 1288 ASSERT(!reg.is(scratch3())); |
| 1313 ASSERT(!reg.is(scratch4())); | 1289 ASSERT(!reg.is(scratch4())); |
| 1314 | 1290 |
| 1315 // Load the properties dictionary. | 1291 // Load the properties dictionary. |
| 1316 Register dictionary = scratch4(); | 1292 Register dictionary = scratch4(); |
| 1317 __ movq(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); | 1293 __ movq(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); |
| 1318 | 1294 |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1508 | 1484 |
| 1509 if (must_preserve_receiver_reg) { | 1485 if (must_preserve_receiver_reg) { |
| 1510 __ push(receiver()); | 1486 __ push(receiver()); |
| 1511 } | 1487 } |
| 1512 __ push(holder_reg); | 1488 __ push(holder_reg); |
| 1513 __ push(this->name()); | 1489 __ push(this->name()); |
| 1514 | 1490 |
| 1515 // Invoke an interceptor. Note: map checks from receiver to | 1491 // Invoke an interceptor. Note: map checks from receiver to |
| 1516 // interceptor's holder has been compiled before (see a caller | 1492 // interceptor's holder has been compiled before (see a caller |
| 1517 // of this method.) | 1493 // of this method.) |
| 1518 CompileCallLoadPropertyWithInterceptor(masm(), | 1494 CompileCallLoadPropertyWithInterceptor( |
| 1519 receiver(), | 1495 masm(), receiver(), holder_reg, this->name(), interceptor_holder, |
| 1520 holder_reg, | 1496 IC::kLoadPropertyWithInterceptorOnly); |
| 1521 this->name(), | |
| 1522 interceptor_holder); | |
| 1523 | 1497 |
| 1524 // Check if interceptor provided a value for property. If it's | 1498 // Check if interceptor provided a value for property. If it's |
| 1525 // the case, return immediately. | 1499 // the case, return immediately. |
| 1526 Label interceptor_failed; | 1500 Label interceptor_failed; |
| 1527 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 1501 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
| 1528 __ j(equal, &interceptor_failed); | 1502 __ j(equal, &interceptor_failed); |
| 1529 frame_scope.GenerateLeaveFrame(); | 1503 frame_scope.GenerateLeaveFrame(); |
| 1530 __ ret(0); | 1504 __ ret(0); |
| 1531 | 1505 |
| 1532 __ bind(&interceptor_failed); | 1506 __ bind(&interceptor_failed); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1568 Handle<Name> name, | 1542 Handle<Name> name, |
| 1569 Label* miss) { | 1543 Label* miss) { |
| 1570 ASSERT(holder->IsGlobalObject()); | 1544 ASSERT(holder->IsGlobalObject()); |
| 1571 | 1545 |
| 1572 StackArgumentsAccessor args(rsp, arguments()); | 1546 StackArgumentsAccessor args(rsp, arguments()); |
| 1573 __ movq(rdx, args.GetReceiverOperand()); | 1547 __ movq(rdx, args.GetReceiverOperand()); |
| 1574 | 1548 |
| 1575 | 1549 |
| 1576 // Check that the maps haven't changed. | 1550 // Check that the maps haven't changed. |
| 1577 __ JumpIfSmi(rdx, miss); | 1551 __ JumpIfSmi(rdx, miss); |
| 1578 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss); | 1552 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 1553 rbx, rax, rdi, name, miss); |
| 1579 } | 1554 } |
| 1580 | 1555 |
| 1581 | 1556 |
| 1582 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1557 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1583 Handle<Cell> cell, | 1558 Handle<Cell> cell, |
| 1584 Handle<JSFunction> function, | 1559 Handle<JSFunction> function, |
| 1585 Label* miss) { | 1560 Label* miss) { |
| 1586 // Get the value from the cell. | 1561 // Get the value from the cell. |
| 1587 __ Move(rdi, cell); | 1562 __ Move(rdi, cell); |
| 1588 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); | 1563 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1634 | 1609 |
| 1635 GenerateNameCheck(name, &miss); | 1610 GenerateNameCheck(name, &miss); |
| 1636 | 1611 |
| 1637 StackArgumentsAccessor args(rsp, arguments()); | 1612 StackArgumentsAccessor args(rsp, arguments()); |
| 1638 __ movq(rdx, args.GetReceiverOperand()); | 1613 __ movq(rdx, args.GetReceiverOperand()); |
| 1639 | 1614 |
| 1640 // Check that the receiver isn't a smi. | 1615 // Check that the receiver isn't a smi. |
| 1641 __ JumpIfSmi(rdx, &miss); | 1616 __ JumpIfSmi(rdx, &miss); |
| 1642 | 1617 |
| 1643 // Do the right check and compute the holder register. | 1618 // Do the right check and compute the holder register. |
| 1644 Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi, | 1619 Register reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, |
| 1645 name, &miss); | 1620 holder, rbx, rax, rdi, name, &miss); |
| 1646 | 1621 |
| 1647 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), | 1622 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), |
| 1648 index.translate(holder), Representation::Tagged()); | 1623 index.translate(holder), Representation::Tagged()); |
| 1649 | 1624 |
| 1650 // Check that the function really is a function. | 1625 // Check that the function really is a function. |
| 1651 __ JumpIfSmi(rdi, &miss); | 1626 __ JumpIfSmi(rdi, &miss); |
| 1652 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); | 1627 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); |
| 1653 __ j(not_equal, &miss); | 1628 __ j(not_equal, &miss); |
| 1654 | 1629 |
| 1655 // Patch the receiver on the stack with the global proxy if | 1630 // Patch the receiver on the stack with the global proxy if |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1687 // Check that function is still array | 1662 // Check that function is still array |
| 1688 const int argc = arguments().immediate(); | 1663 const int argc = arguments().immediate(); |
| 1689 StackArgumentsAccessor args(rsp, argc); | 1664 StackArgumentsAccessor args(rsp, argc); |
| 1690 GenerateNameCheck(name, &miss); | 1665 GenerateNameCheck(name, &miss); |
| 1691 | 1666 |
| 1692 if (cell.is_null()) { | 1667 if (cell.is_null()) { |
| 1693 __ movq(rdx, args.GetReceiverOperand()); | 1668 __ movq(rdx, args.GetReceiverOperand()); |
| 1694 | 1669 |
| 1695 // Check that the receiver isn't a smi. | 1670 // Check that the receiver isn't a smi. |
| 1696 __ JumpIfSmi(rdx, &miss); | 1671 __ JumpIfSmi(rdx, &miss); |
| 1697 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 1672 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 1698 name, &miss); | 1673 rbx, rax, rdi, name, &miss); |
| 1699 } else { | 1674 } else { |
| 1700 ASSERT(cell->value() == *function); | 1675 ASSERT(cell->value() == *function); |
| 1701 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 1676 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1702 &miss); | 1677 &miss); |
| 1703 GenerateLoadFunctionFromCell(cell, function, &miss); | 1678 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1704 } | 1679 } |
| 1705 | 1680 |
| 1706 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1681 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1707 site->SetElementsKind(GetInitialFastElementsKind()); | 1682 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1708 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1683 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1746 Label miss; | 1721 Label miss; |
| 1747 GenerateNameCheck(name, &miss); | 1722 GenerateNameCheck(name, &miss); |
| 1748 | 1723 |
| 1749 const int argc = arguments().immediate(); | 1724 const int argc = arguments().immediate(); |
| 1750 StackArgumentsAccessor args(rsp, argc); | 1725 StackArgumentsAccessor args(rsp, argc); |
| 1751 __ movq(rdx, args.GetReceiverOperand()); | 1726 __ movq(rdx, args.GetReceiverOperand()); |
| 1752 | 1727 |
| 1753 // Check that the receiver isn't a smi. | 1728 // Check that the receiver isn't a smi. |
| 1754 __ JumpIfSmi(rdx, &miss); | 1729 __ JumpIfSmi(rdx, &miss); |
| 1755 | 1730 |
| 1756 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 1731 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 1757 name, &miss); | 1732 rbx, rax, rdi, name, &miss); |
| 1758 | 1733 |
| 1759 if (argc == 0) { | 1734 if (argc == 0) { |
| 1760 // Noop, return the length. | 1735 // Noop, return the length. |
| 1761 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); | 1736 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |
| 1762 __ ret((argc + 1) * kPointerSize); | 1737 __ ret((argc + 1) * kPointerSize); |
| 1763 } else { | 1738 } else { |
| 1764 Label call_builtin; | 1739 Label call_builtin; |
| 1765 | 1740 |
| 1766 if (argc == 1) { // Otherwise fall through to call builtin. | 1741 if (argc == 1) { // Otherwise fall through to call builtin. |
| 1767 Label attempt_to_grow_elements, with_write_barrier, check_double; | 1742 Label attempt_to_grow_elements, with_write_barrier, check_double; |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2001 Label miss, return_undefined, call_builtin; | 1976 Label miss, return_undefined, call_builtin; |
| 2002 GenerateNameCheck(name, &miss); | 1977 GenerateNameCheck(name, &miss); |
| 2003 | 1978 |
| 2004 const int argc = arguments().immediate(); | 1979 const int argc = arguments().immediate(); |
| 2005 StackArgumentsAccessor args(rsp, argc); | 1980 StackArgumentsAccessor args(rsp, argc); |
| 2006 __ movq(rdx, args.GetReceiverOperand()); | 1981 __ movq(rdx, args.GetReceiverOperand()); |
| 2007 | 1982 |
| 2008 // Check that the receiver isn't a smi. | 1983 // Check that the receiver isn't a smi. |
| 2009 __ JumpIfSmi(rdx, &miss); | 1984 __ JumpIfSmi(rdx, &miss); |
| 2010 | 1985 |
| 2011 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 1986 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 2012 name, &miss); | 1987 rbx, rax, rdi, name, &miss); |
| 2013 | 1988 |
| 2014 // Get the elements array of the object. | 1989 // Get the elements array of the object. |
| 2015 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); | 1990 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); |
| 2016 | 1991 |
| 2017 // Check that the elements are in fast mode and writable. | 1992 // Check that the elements are in fast mode and writable. |
| 2018 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 1993 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
| 2019 Heap::kFixedArrayMapRootIndex); | 1994 Heap::kFixedArrayMapRootIndex); |
| 2020 __ j(not_equal, &call_builtin); | 1995 __ j(not_equal, &call_builtin); |
| 2021 | 1996 |
| 2022 // Get the array's length into rcx and calculate new length. | 1997 // Get the array's length into rcx and calculate new length. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2093 index_out_of_range_label = &miss; | 2068 index_out_of_range_label = &miss; |
| 2094 } | 2069 } |
| 2095 GenerateNameCheck(name, &name_miss); | 2070 GenerateNameCheck(name, &name_miss); |
| 2096 | 2071 |
| 2097 // Check that the maps starting from the prototype haven't changed. | 2072 // Check that the maps starting from the prototype haven't changed. |
| 2098 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2073 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2099 Context::STRING_FUNCTION_INDEX, | 2074 Context::STRING_FUNCTION_INDEX, |
| 2100 rax, | 2075 rax, |
| 2101 &miss); | 2076 &miss); |
| 2102 ASSERT(!object.is_identical_to(holder)); | 2077 ASSERT(!object.is_identical_to(holder)); |
| 2078 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2103 CheckPrototypes( | 2079 CheckPrototypes( |
| 2104 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2080 IC::CurrentTypeOf(prototype, isolate()), |
| 2105 rax, holder, rbx, rdx, rdi, name, &miss); | 2081 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2106 | 2082 |
| 2107 Register receiver = rbx; | 2083 Register receiver = rbx; |
| 2108 Register index = rdi; | 2084 Register index = rdi; |
| 2109 Register result = rax; | 2085 Register result = rax; |
| 2110 __ movq(receiver, args.GetReceiverOperand()); | 2086 __ movq(receiver, args.GetReceiverOperand()); |
| 2111 if (argc > 0) { | 2087 if (argc > 0) { |
| 2112 __ movq(index, args.GetArgumentOperand(1)); | 2088 __ movq(index, args.GetArgumentOperand(1)); |
| 2113 } else { | 2089 } else { |
| 2114 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2090 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2175 index_out_of_range_label = &miss; | 2151 index_out_of_range_label = &miss; |
| 2176 } | 2152 } |
| 2177 GenerateNameCheck(name, &name_miss); | 2153 GenerateNameCheck(name, &name_miss); |
| 2178 | 2154 |
| 2179 // Check that the maps starting from the prototype haven't changed. | 2155 // Check that the maps starting from the prototype haven't changed. |
| 2180 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2156 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2181 Context::STRING_FUNCTION_INDEX, | 2157 Context::STRING_FUNCTION_INDEX, |
| 2182 rax, | 2158 rax, |
| 2183 &miss); | 2159 &miss); |
| 2184 ASSERT(!object.is_identical_to(holder)); | 2160 ASSERT(!object.is_identical_to(holder)); |
| 2161 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2185 CheckPrototypes( | 2162 CheckPrototypes( |
| 2186 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2163 IC::CurrentTypeOf(prototype, isolate()), |
| 2187 rax, holder, rbx, rdx, rdi, name, &miss); | 2164 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2188 | 2165 |
| 2189 Register receiver = rax; | 2166 Register receiver = rax; |
| 2190 Register index = rdi; | 2167 Register index = rdi; |
| 2191 Register scratch = rdx; | 2168 Register scratch = rdx; |
| 2192 Register result = rax; | 2169 Register result = rax; |
| 2193 __ movq(receiver, args.GetReceiverOperand()); | 2170 __ movq(receiver, args.GetReceiverOperand()); |
| 2194 if (argc > 0) { | 2171 if (argc > 0) { |
| 2195 __ movq(index, args.GetArgumentOperand(1)); | 2172 __ movq(index, args.GetArgumentOperand(1)); |
| 2196 } else { | 2173 } else { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2247 const int argc = arguments().immediate(); | 2224 const int argc = arguments().immediate(); |
| 2248 StackArgumentsAccessor args(rsp, argc); | 2225 StackArgumentsAccessor args(rsp, argc); |
| 2249 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2226 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2250 | 2227 |
| 2251 Label miss; | 2228 Label miss; |
| 2252 GenerateNameCheck(name, &miss); | 2229 GenerateNameCheck(name, &miss); |
| 2253 | 2230 |
| 2254 if (cell.is_null()) { | 2231 if (cell.is_null()) { |
| 2255 __ movq(rdx, args.GetReceiverOperand()); | 2232 __ movq(rdx, args.GetReceiverOperand()); |
| 2256 __ JumpIfSmi(rdx, &miss); | 2233 __ JumpIfSmi(rdx, &miss); |
| 2257 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2234 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 2258 name, &miss); | 2235 rbx, rax, rdi, name, &miss); |
| 2259 } else { | 2236 } else { |
| 2260 ASSERT(cell->value() == *function); | 2237 ASSERT(cell->value() == *function); |
| 2261 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2238 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2262 &miss); | 2239 &miss); |
| 2263 GenerateLoadFunctionFromCell(cell, function, &miss); | 2240 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2264 } | 2241 } |
| 2265 | 2242 |
| 2266 // Load the char code argument. | 2243 // Load the char code argument. |
| 2267 Register code = rbx; | 2244 Register code = rbx; |
| 2268 __ movq(code, args.GetArgumentOperand(1)); | 2245 __ movq(code, args.GetArgumentOperand(1)); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2325 | 2302 |
| 2326 Label miss; | 2303 Label miss; |
| 2327 GenerateNameCheck(name, &miss); | 2304 GenerateNameCheck(name, &miss); |
| 2328 | 2305 |
| 2329 if (cell.is_null()) { | 2306 if (cell.is_null()) { |
| 2330 __ movq(rdx, args.GetReceiverOperand()); | 2307 __ movq(rdx, args.GetReceiverOperand()); |
| 2331 | 2308 |
| 2332 STATIC_ASSERT(kSmiTag == 0); | 2309 STATIC_ASSERT(kSmiTag == 0); |
| 2333 __ JumpIfSmi(rdx, &miss); | 2310 __ JumpIfSmi(rdx, &miss); |
| 2334 | 2311 |
| 2335 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2312 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 2336 name, &miss); | 2313 rbx, rax, rdi, name, &miss); |
| 2337 } else { | 2314 } else { |
| 2338 ASSERT(cell->value() == *function); | 2315 ASSERT(cell->value() == *function); |
| 2339 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2316 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2340 &miss); | 2317 &miss); |
| 2341 GenerateLoadFunctionFromCell(cell, function, &miss); | 2318 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2342 } | 2319 } |
| 2343 | 2320 |
| 2344 // Load the (only) argument into rax. | 2321 // Load the (only) argument into rax. |
| 2345 __ movq(rax, args.GetArgumentOperand(1)); | 2322 __ movq(rax, args.GetArgumentOperand(1)); |
| 2346 | 2323 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2448 const int argc = arguments().immediate(); | 2425 const int argc = arguments().immediate(); |
| 2449 StackArgumentsAccessor args(rsp, argc); | 2426 StackArgumentsAccessor args(rsp, argc); |
| 2450 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2427 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2451 | 2428 |
| 2452 Label miss; | 2429 Label miss; |
| 2453 GenerateNameCheck(name, &miss); | 2430 GenerateNameCheck(name, &miss); |
| 2454 | 2431 |
| 2455 if (cell.is_null()) { | 2432 if (cell.is_null()) { |
| 2456 __ movq(rdx, args.GetReceiverOperand()); | 2433 __ movq(rdx, args.GetReceiverOperand()); |
| 2457 __ JumpIfSmi(rdx, &miss); | 2434 __ JumpIfSmi(rdx, &miss); |
| 2458 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2435 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 2459 name, &miss); | 2436 rbx, rax, rdi, name, &miss); |
| 2460 } else { | 2437 } else { |
| 2461 ASSERT(cell->value() == *function); | 2438 ASSERT(cell->value() == *function); |
| 2462 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2439 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2463 &miss); | 2440 &miss); |
| 2464 GenerateLoadFunctionFromCell(cell, function, &miss); | 2441 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2465 } | 2442 } |
| 2466 // Load the (only) argument into rax. | 2443 // Load the (only) argument into rax. |
| 2467 __ movq(rax, args.GetArgumentOperand(1)); | 2444 __ movq(rax, args.GetArgumentOperand(1)); |
| 2468 | 2445 |
| 2469 // Check if the argument is a smi. | 2446 // Check if the argument is a smi. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2562 | 2539 |
| 2563 Counters* counters = isolate()->counters(); | 2540 Counters* counters = isolate()->counters(); |
| 2564 __ IncrementCounter(counters->call_const(), 1); | 2541 __ IncrementCounter(counters->call_const(), 1); |
| 2565 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2542 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| 2566 | 2543 |
| 2567 // Allocate space for v8::Arguments implicit values. Must be initialized | 2544 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2568 // before calling any runtime function. | 2545 // before calling any runtime function. |
| 2569 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2546 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2570 | 2547 |
| 2571 // Check that the maps haven't changed and find a Holder as a side effect. | 2548 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2572 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2549 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 2573 name, depth, &miss); | 2550 rbx, rax, rdi, name, depth, &miss); |
| 2574 | 2551 |
| 2575 // Move the return address on top of the stack. | 2552 // Move the return address on top of the stack. |
| 2576 __ movq(rax, | 2553 __ movq(rax, |
| 2577 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); | 2554 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); |
| 2578 __ movq(StackOperandForReturnAddress(0), rax); | 2555 __ movq(StackOperandForReturnAddress(0), rax); |
| 2579 | 2556 |
| 2580 GenerateFastApiCall(masm(), optimization, argc); | 2557 GenerateFastApiCall(masm(), optimization, argc); |
| 2581 | 2558 |
| 2582 __ bind(&miss); | 2559 __ bind(&miss); |
| 2583 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2560 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2628 // Make sure that it's okay not to patch the on stack receiver | 2605 // Make sure that it's okay not to patch the on stack receiver |
| 2629 // unless we're doing a receiver map check. | 2606 // unless we're doing a receiver map check. |
| 2630 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2607 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2631 | 2608 |
| 2632 Counters* counters = isolate()->counters(); | 2609 Counters* counters = isolate()->counters(); |
| 2633 switch (check) { | 2610 switch (check) { |
| 2634 case RECEIVER_MAP_CHECK: | 2611 case RECEIVER_MAP_CHECK: |
| 2635 __ IncrementCounter(counters->call_const(), 1); | 2612 __ IncrementCounter(counters->call_const(), 1); |
| 2636 | 2613 |
| 2637 // Check that the maps haven't changed. | 2614 // Check that the maps haven't changed. |
| 2638 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, | 2615 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 2639 rdi, name, &miss); | 2616 rbx, rax, rdi, name, &miss); |
| 2640 | 2617 |
| 2641 // Patch the receiver on the stack with the global proxy if | 2618 // Patch the receiver on the stack with the global proxy if |
| 2642 // necessary. | 2619 // necessary. |
| 2643 if (object->IsGlobalObject()) { | 2620 if (object->IsGlobalObject()) { |
| 2644 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2621 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2645 __ movq(args.GetReceiverOperand(), rdx); | 2622 __ movq(args.GetReceiverOperand(), rdx); |
| 2646 } | 2623 } |
| 2647 break; | 2624 break; |
| 2648 | 2625 |
| 2649 case STRING_CHECK: | 2626 case STRING_CHECK: { |
| 2650 // Check that the object is a string. | 2627 // Check that the object is a string. |
| 2651 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); | 2628 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); |
| 2652 __ j(above_equal, &miss); | 2629 __ j(above_equal, &miss); |
| 2653 // Check that the maps starting from the prototype haven't changed. | 2630 // Check that the maps starting from the prototype haven't changed. |
| 2654 GenerateDirectLoadGlobalFunctionPrototype( | 2631 GenerateDirectLoadGlobalFunctionPrototype( |
| 2655 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); | 2632 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); |
| 2633 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2656 CheckPrototypes( | 2634 CheckPrototypes( |
| 2657 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2635 IC::CurrentTypeOf(prototype, isolate()), |
| 2658 rax, holder, rbx, rdx, rdi, name, &miss); | 2636 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2659 break; | 2637 break; |
| 2660 | 2638 } |
| 2661 case SYMBOL_CHECK: | 2639 case SYMBOL_CHECK: { |
| 2662 // Check that the object is a symbol. | 2640 // Check that the object is a symbol. |
| 2663 __ CmpObjectType(rdx, SYMBOL_TYPE, rax); | 2641 __ CmpObjectType(rdx, SYMBOL_TYPE, rax); |
| 2664 __ j(not_equal, &miss); | 2642 __ j(not_equal, &miss); |
| 2665 // Check that the maps starting from the prototype haven't changed. | 2643 // Check that the maps starting from the prototype haven't changed. |
| 2666 GenerateDirectLoadGlobalFunctionPrototype( | 2644 GenerateDirectLoadGlobalFunctionPrototype( |
| 2667 masm(), Context::SYMBOL_FUNCTION_INDEX, rax, &miss); | 2645 masm(), Context::SYMBOL_FUNCTION_INDEX, rax, &miss); |
| 2646 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2668 CheckPrototypes( | 2647 CheckPrototypes( |
| 2669 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2648 IC::CurrentTypeOf(prototype, isolate()), |
| 2670 rax, holder, rbx, rdx, rdi, name, &miss); | 2649 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2671 break; | 2650 break; |
| 2672 | 2651 } |
| 2673 case NUMBER_CHECK: { | 2652 case NUMBER_CHECK: { |
| 2674 Label fast; | 2653 Label fast; |
| 2675 // Check that the object is a smi or a heap number. | 2654 // Check that the object is a smi or a heap number. |
| 2676 __ JumpIfSmi(rdx, &fast); | 2655 __ JumpIfSmi(rdx, &fast); |
| 2677 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); | 2656 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); |
| 2678 __ j(not_equal, &miss); | 2657 __ j(not_equal, &miss); |
| 2679 __ bind(&fast); | 2658 __ bind(&fast); |
| 2680 // Check that the maps starting from the prototype haven't changed. | 2659 // Check that the maps starting from the prototype haven't changed. |
| 2681 GenerateDirectLoadGlobalFunctionPrototype( | 2660 GenerateDirectLoadGlobalFunctionPrototype( |
| 2682 masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); | 2661 masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); |
| 2662 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2683 CheckPrototypes( | 2663 CheckPrototypes( |
| 2684 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2664 IC::CurrentTypeOf(prototype, isolate()), |
| 2685 rax, holder, rbx, rdx, rdi, name, &miss); | 2665 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2686 break; | 2666 break; |
| 2687 } | 2667 } |
| 2688 case BOOLEAN_CHECK: { | 2668 case BOOLEAN_CHECK: { |
| 2689 GenerateBooleanCheck(rdx, &miss); | 2669 GenerateBooleanCheck(rdx, &miss); |
| 2690 // Check that the maps starting from the prototype haven't changed. | 2670 // Check that the maps starting from the prototype haven't changed. |
| 2691 GenerateDirectLoadGlobalFunctionPrototype( | 2671 GenerateDirectLoadGlobalFunctionPrototype( |
| 2692 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); | 2672 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); |
| 2673 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2693 CheckPrototypes( | 2674 CheckPrototypes( |
| 2694 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2675 IC::CurrentTypeOf(prototype, isolate()), |
| 2695 rax, holder, rbx, rdx, rdi, name, &miss); | 2676 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2696 break; | 2677 break; |
| 2697 } | 2678 } |
| 2698 } | 2679 } |
| 2699 | 2680 |
| 2700 Label success; | 2681 Label success; |
| 2701 __ jmp(&success); | 2682 __ jmp(&success); |
| 2702 | 2683 |
| 2703 // Handle call cache miss. | 2684 // Handle call cache miss. |
| 2704 __ bind(&miss); | 2685 __ bind(&miss); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2862 // Return the generated code. | 2843 // Return the generated code. |
| 2863 return GetCode(Code::NORMAL, name); | 2844 return GetCode(Code::NORMAL, name); |
| 2864 } | 2845 } |
| 2865 | 2846 |
| 2866 | 2847 |
| 2867 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2848 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2868 Handle<JSObject> object, | 2849 Handle<JSObject> object, |
| 2869 Handle<JSObject> holder, | 2850 Handle<JSObject> holder, |
| 2870 Handle<Name> name, | 2851 Handle<Name> name, |
| 2871 Handle<ExecutableAccessorInfo> callback) { | 2852 Handle<ExecutableAccessorInfo> callback) { |
| 2872 HandlerFrontend(object, receiver(), holder, name); | 2853 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 2854 receiver(), holder, name); |
| 2873 | 2855 |
| 2874 __ PopReturnAddressTo(scratch1()); | 2856 __ PopReturnAddressTo(scratch1()); |
| 2875 __ push(receiver()); | 2857 __ push(receiver()); |
| 2876 __ Push(callback); // callback info | 2858 __ Push(callback); // callback info |
| 2877 __ Push(name); | 2859 __ Push(name); |
| 2878 __ push(value()); | 2860 __ push(value()); |
| 2879 __ PushReturnAddressFrom(scratch1()); | 2861 __ PushReturnAddressFrom(scratch1()); |
| 2880 | 2862 |
| 2881 // Do tail-call to the runtime system. | 2863 // Do tail-call to the runtime system. |
| 2882 ExternalReference store_callback_property = | 2864 ExternalReference store_callback_property = |
| 2883 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2865 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2884 __ TailCallExternalReference(store_callback_property, 4, 1); | 2866 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2885 | 2867 |
| 2886 // Return the generated code. | 2868 // Return the generated code. |
| 2887 return GetCode(kind(), Code::FAST, name); | 2869 return GetCode(kind(), Code::FAST, name); |
| 2888 } | 2870 } |
| 2889 | 2871 |
| 2890 | 2872 |
| 2891 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2873 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2892 Handle<JSObject> object, | 2874 Handle<JSObject> object, |
| 2893 Handle<JSObject> holder, | 2875 Handle<JSObject> holder, |
| 2894 Handle<Name> name, | 2876 Handle<Name> name, |
| 2895 const CallOptimization& call_optimization) { | 2877 const CallOptimization& call_optimization) { |
| 2896 HandlerFrontend(object, receiver(), holder, name); | 2878 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 2879 receiver(), holder, name); |
| 2897 | 2880 |
| 2898 Register values[] = { value() }; | 2881 Register values[] = { value() }; |
| 2899 GenerateFastApiCall( | 2882 GenerateFastApiCall( |
| 2900 masm(), call_optimization, receiver(), scratch1(), | 2883 masm(), call_optimization, receiver(), scratch1(), |
| 2901 scratch2(), this->name(), 1, values); | 2884 scratch2(), this->name(), 1, values); |
| 2902 | 2885 |
| 2903 // Return the generated code. | 2886 // Return the generated code. |
| 2904 return GetCode(kind(), Code::FAST, name); | 2887 return GetCode(kind(), Code::FAST, name); |
| 2905 } | 2888 } |
| 2906 | 2889 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3000 __ bind(&miss); | 2983 __ bind(&miss); |
| 3001 | 2984 |
| 3002 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2985 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 3003 | 2986 |
| 3004 // Return the generated code. | 2987 // Return the generated code. |
| 3005 return GetICCode( | 2988 return GetICCode( |
| 3006 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 2989 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
| 3007 } | 2990 } |
| 3008 | 2991 |
| 3009 | 2992 |
| 3010 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( | 2993 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type, |
| 3011 Handle<Object> object, | 2994 Handle<JSObject> last, |
| 3012 Handle<JSObject> last, | 2995 Handle<Name> name) { |
| 3013 Handle<Name> name, | 2996 NonexistentHandlerFrontend(type, last, name); |
| 3014 Handle<JSGlobalObject> global) { | |
| 3015 NonexistentHandlerFrontend(object, last, name, global); | |
| 3016 | 2997 |
| 3017 // Return undefined if maps of the full prototype chain are still the | 2998 // Return undefined if maps of the full prototype chain are still the |
| 3018 // same and no global property with this name contains a value. | 2999 // same and no global property with this name contains a value. |
| 3019 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 3000 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 3020 __ ret(0); | 3001 __ ret(0); |
| 3021 | 3002 |
| 3022 // Return the generated code. | 3003 // Return the generated code. |
| 3023 return GetCode(kind(), Code::FAST, name); | 3004 return GetCode(kind(), Code::FAST, name); |
| 3024 } | 3005 } |
| 3025 | 3006 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3101 } | 3082 } |
| 3102 __ ret(0); | 3083 __ ret(0); |
| 3103 } | 3084 } |
| 3104 | 3085 |
| 3105 | 3086 |
| 3106 #undef __ | 3087 #undef __ |
| 3107 #define __ ACCESS_MASM(masm()) | 3088 #define __ ACCESS_MASM(masm()) |
| 3108 | 3089 |
| 3109 | 3090 |
| 3110 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 3091 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 3111 Handle<Object> object, | 3092 Handle<Type> type, |
| 3112 Handle<GlobalObject> global, | 3093 Handle<GlobalObject> global, |
| 3113 Handle<PropertyCell> cell, | 3094 Handle<PropertyCell> cell, |
| 3114 Handle<Name> name, | 3095 Handle<Name> name, |
| 3115 bool is_dont_delete) { | 3096 bool is_dont_delete) { |
| 3116 Label miss; | 3097 Label miss; |
| 3117 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since | 3098 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since |
| 3118 // rax is used as receiver(), which we would otherwise clobber before a | 3099 // rax is used as receiver(), which we would otherwise clobber before a |
| 3119 // potential miss. | 3100 // potential miss. |
| 3120 HandlerFrontendHeader(object, receiver(), global, name, &miss); | 3101 HandlerFrontendHeader(type, receiver(), global, name, &miss); |
| 3121 | 3102 |
| 3122 // Get the value from the cell. | 3103 // Get the value from the cell. |
| 3123 __ Move(rbx, cell); | 3104 __ Move(rbx, cell); |
| 3124 __ movq(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); | 3105 __ movq(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); |
| 3125 | 3106 |
| 3126 // Check for deleted property if property can actually be deleted. | 3107 // Check for deleted property if property can actually be deleted. |
| 3127 if (!is_dont_delete) { | 3108 if (!is_dont_delete) { |
| 3128 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 3109 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
| 3129 __ j(equal, &miss); | 3110 __ j(equal, &miss); |
| 3130 } else if (FLAG_debug_code) { | 3111 } else if (FLAG_debug_code) { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3234 // ----------------------------------- | 3215 // ----------------------------------- |
| 3235 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 3216 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3236 } | 3217 } |
| 3237 | 3218 |
| 3238 | 3219 |
| 3239 #undef __ | 3220 #undef __ |
| 3240 | 3221 |
| 3241 } } // namespace v8::internal | 3222 } } // namespace v8::internal |
| 3242 | 3223 |
| 3243 #endif // V8_TARGET_ARCH_X64 | 3224 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |