| 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 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 __ push(receiver); | 398 __ push(receiver); |
| 399 __ push(holder); | 399 __ push(holder); |
| 400 } | 400 } |
| 401 | 401 |
| 402 | 402 |
| 403 static void CompileCallLoadPropertyWithInterceptor( | 403 static void CompileCallLoadPropertyWithInterceptor( |
| 404 MacroAssembler* masm, | 404 MacroAssembler* masm, |
| 405 Register receiver, | 405 Register receiver, |
| 406 Register holder, | 406 Register holder, |
| 407 Register name, | 407 Register name, |
| 408 Handle<JSObject> holder_obj) { | 408 Handle<JSObject> holder_obj, |
| 409 IC::UtilityId id) { |
| 409 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 410 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 410 __ CallExternalReference( | 411 __ CallExternalReference( |
| 411 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 412 ExternalReference(IC_Utility(id), masm->isolate()), |
| 412 masm->isolate()), | |
| 413 StubCache::kInterceptorArgsLength); | 413 StubCache::kInterceptorArgsLength); |
| 414 } | 414 } |
| 415 | 415 |
| 416 | 416 |
| 417 // Number of pointers to be reserved on stack for fast API call. | 417 // Number of pointers to be reserved on stack for fast API call. |
| 418 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; | 418 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; |
| 419 | 419 |
| 420 | 420 |
| 421 // Reserves space for the extra arguments to API function in the | 421 // Reserves space for the extra arguments to API function in the |
| 422 // caller's frame. | 422 // caller's frame. |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 if (can_do_fast_api_call) { | 716 if (can_do_fast_api_call) { |
| 717 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); | 717 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); |
| 718 ReserveSpaceForFastApiCall(masm, scratch1); | 718 ReserveSpaceForFastApiCall(masm, scratch1); |
| 719 } | 719 } |
| 720 | 720 |
| 721 // Check that the maps from receiver to interceptor's holder | 721 // Check that the maps from receiver to interceptor's holder |
| 722 // haven't changed and thus we can invoke interceptor. | 722 // haven't changed and thus we can invoke interceptor. |
| 723 Label miss_cleanup; | 723 Label miss_cleanup; |
| 724 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 724 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 725 Register holder = | 725 Register holder = |
| 726 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 726 stub_compiler_->CheckPrototypes( |
| 727 scratch1, scratch2, scratch3, | 727 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 728 name, depth1, miss); | 728 interceptor_holder, scratch1, scratch2, scratch3, |
| 729 name, depth1, miss); |
| 729 | 730 |
| 730 // Invoke an interceptor and if it provides a value, | 731 // Invoke an interceptor and if it provides a value, |
| 731 // branch to |regular_invoke|. | 732 // branch to |regular_invoke|. |
| 732 Label regular_invoke; | 733 Label regular_invoke; |
| 733 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, | 734 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, |
| 734 ®ular_invoke); | 735 ®ular_invoke); |
| 735 | 736 |
| 736 // Interceptor returned nothing for this property. Try to use cached | 737 // Interceptor returned nothing for this property. Try to use cached |
| 737 // constant function. | 738 // constant function. |
| 738 | 739 |
| 739 // Check that the maps from interceptor's holder to constant function's | 740 // Check that the maps from interceptor's holder to constant function's |
| 740 // holder haven't changed and thus we can use cached constant function. | 741 // holder haven't changed and thus we can use cached constant function. |
| 741 if (*interceptor_holder != lookup->holder()) { | 742 if (*interceptor_holder != lookup->holder()) { |
| 742 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 743 stub_compiler_->CheckPrototypes( |
| 743 Handle<JSObject>(lookup->holder()), | 744 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), receiver, |
| 744 scratch1, scratch2, scratch3, | 745 handle(lookup->holder()), scratch1, scratch2, scratch3, |
| 745 name, depth2, miss); | 746 name, depth2, miss); |
| 746 } else { | 747 } else { |
| 747 // CheckPrototypes has a side effect of fetching a 'holder' | 748 // CheckPrototypes has a side effect of fetching a 'holder' |
| 748 // for API (object which is instanceof for the signature). It's | 749 // for API (object which is instanceof for the signature). It's |
| 749 // safe to omit it here, as if present, it should be fetched | 750 // safe to omit it here, as if present, it should be fetched |
| 750 // by the previous CheckPrototypes. | 751 // by the previous CheckPrototypes. |
| 751 ASSERT(depth2 == kInvalidProtoDepth); | 752 ASSERT(depth2 == kInvalidProtoDepth); |
| 752 } | 753 } |
| 753 | 754 |
| 754 // Invoke function. | 755 // Invoke function. |
| 755 if (can_do_fast_api_call) { | 756 if (can_do_fast_api_call) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 781 void CompileRegular(MacroAssembler* masm, | 782 void CompileRegular(MacroAssembler* masm, |
| 782 Handle<JSObject> object, | 783 Handle<JSObject> object, |
| 783 Register receiver, | 784 Register receiver, |
| 784 Register scratch1, | 785 Register scratch1, |
| 785 Register scratch2, | 786 Register scratch2, |
| 786 Register scratch3, | 787 Register scratch3, |
| 787 Handle<Name> name, | 788 Handle<Name> name, |
| 788 Handle<JSObject> interceptor_holder, | 789 Handle<JSObject> interceptor_holder, |
| 789 Label* miss_label) { | 790 Label* miss_label) { |
| 790 Register holder = | 791 Register holder = |
| 791 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 792 stub_compiler_->CheckPrototypes( |
| 792 scratch1, scratch2, scratch3, | 793 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 793 name, miss_label); | 794 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label); |
| 794 | 795 |
| 795 FrameScope scope(masm, StackFrame::INTERNAL); | 796 FrameScope scope(masm, StackFrame::INTERNAL); |
| 796 // Save the name_ register across the call. | 797 // Save the name_ register across the call. |
| 797 __ push(name_); | 798 __ push(name_); |
| 798 | 799 |
| 799 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); | 800 CompileCallLoadPropertyWithInterceptor( |
| 800 | 801 masm, receiver, holder, name_, interceptor_holder, |
| 801 __ CallExternalReference( | 802 IC::kLoadPropertyWithInterceptorForCall); |
| 802 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | |
| 803 masm->isolate()), | |
| 804 StubCache::kInterceptorArgsLength); | |
| 805 | 803 |
| 806 // Restore the name_ register. | 804 // Restore the name_ register. |
| 807 __ pop(name_); | 805 __ pop(name_); |
| 808 | 806 |
| 809 // Leave the internal frame. | 807 // Leave the internal frame. |
| 810 } | 808 } |
| 811 | 809 |
| 812 void LoadWithInterceptor(MacroAssembler* masm, | 810 void LoadWithInterceptor(MacroAssembler* masm, |
| 813 Register receiver, | 811 Register receiver, |
| 814 Register holder, | 812 Register holder, |
| 815 Handle<JSObject> holder_obj, | 813 Handle<JSObject> holder_obj, |
| 816 Label* interceptor_succeeded) { | 814 Label* interceptor_succeeded) { |
| 817 { | 815 { |
| 818 FrameScope scope(masm, StackFrame::INTERNAL); | 816 FrameScope scope(masm, StackFrame::INTERNAL); |
| 819 __ push(holder); // Save the holder. | 817 __ push(holder); // Save the holder. |
| 820 __ push(name_); // Save the name. | 818 __ push(name_); // Save the name. |
| 821 | 819 |
| 822 CompileCallLoadPropertyWithInterceptor(masm, | 820 CompileCallLoadPropertyWithInterceptor( |
| 823 receiver, | 821 masm, receiver, holder, name_, holder_obj, |
| 824 holder, | 822 IC::kLoadPropertyWithInterceptorOnly); |
| 825 name_, | |
| 826 holder_obj); | |
| 827 | 823 |
| 828 __ pop(name_); // Restore the name. | 824 __ pop(name_); // Restore the name. |
| 829 __ pop(receiver); // Restore the holder. | 825 __ pop(receiver); // Restore the holder. |
| 830 // Leave the internal frame. | 826 // Leave the internal frame. |
| 831 } | 827 } |
| 832 | 828 |
| 833 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); | 829 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); |
| 834 __ j(not_equal, interceptor_succeeded); | 830 __ j(not_equal, interceptor_succeeded); |
| 835 } | 831 } |
| 836 | 832 |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1177 smi_check); | 1173 smi_check); |
| 1178 } | 1174 } |
| 1179 } | 1175 } |
| 1180 | 1176 |
| 1181 // Return the value (register eax). | 1177 // Return the value (register eax). |
| 1182 ASSERT(value_reg.is(eax)); | 1178 ASSERT(value_reg.is(eax)); |
| 1183 __ ret(0); | 1179 __ ret(0); |
| 1184 } | 1180 } |
| 1185 | 1181 |
| 1186 | 1182 |
| 1187 void StubCompiler::GenerateCheckPropertyCells(MacroAssembler* masm, | |
| 1188 Handle<JSObject> object, | |
| 1189 Handle<JSObject> holder, | |
| 1190 Handle<Name> name, | |
| 1191 Register scratch, | |
| 1192 Label* miss) { | |
| 1193 Handle<JSObject> current = object; | |
| 1194 while (!current.is_identical_to(holder)) { | |
| 1195 if (current->IsJSGlobalObject()) { | |
| 1196 GenerateCheckPropertyCell(masm, | |
| 1197 Handle<JSGlobalObject>::cast(current), | |
| 1198 name, | |
| 1199 scratch, | |
| 1200 miss); | |
| 1201 } | |
| 1202 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | |
| 1203 } | |
| 1204 } | |
| 1205 | |
| 1206 | |
| 1207 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1183 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1208 __ jmp(code, RelocInfo::CODE_TARGET); | 1184 __ jmp(code, RelocInfo::CODE_TARGET); |
| 1209 } | 1185 } |
| 1210 | 1186 |
| 1211 | 1187 |
| 1212 #undef __ | 1188 #undef __ |
| 1213 #define __ ACCESS_MASM(masm()) | 1189 #define __ ACCESS_MASM(masm()) |
| 1214 | 1190 |
| 1215 | 1191 |
| 1216 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1192 Register StubCompiler::CheckPrototypes(Handle<Type> type, |
| 1217 Register object_reg, | 1193 Register object_reg, |
| 1218 Handle<JSObject> holder, | 1194 Handle<JSObject> holder, |
| 1219 Register holder_reg, | 1195 Register holder_reg, |
| 1220 Register scratch1, | 1196 Register scratch1, |
| 1221 Register scratch2, | 1197 Register scratch2, |
| 1222 Handle<Name> name, | 1198 Handle<Name> name, |
| 1223 int save_at_depth, | 1199 int save_at_depth, |
| 1224 Label* miss, | 1200 Label* miss, |
| 1225 PrototypeCheckType check) { | 1201 PrototypeCheckType check) { |
| 1226 const int kHolderIndex = FunctionCallbackArguments::kHolderIndex + 1; | 1202 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
| 1227 // Make sure that the type feedback oracle harvests the receiver map. | 1203 // Make sure that the type feedback oracle harvests the receiver map. |
| 1228 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1204 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
| 1229 __ mov(scratch1, Handle<Map>(object->map())); | 1205 __ mov(scratch1, receiver_map); |
| 1230 | 1206 |
| 1231 Handle<JSObject> first = object; | |
| 1232 // Make sure there's no overlap between holder and object registers. | 1207 // Make sure there's no overlap between holder and object registers. |
| 1233 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1208 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 1234 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1209 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 1235 && !scratch2.is(scratch1)); | 1210 && !scratch2.is(scratch1)); |
| 1236 | 1211 |
| 1237 // Keep track of the current object in register reg. | 1212 // Keep track of the current object in register reg. |
| 1238 Register reg = object_reg; | 1213 Register reg = object_reg; |
| 1239 Handle<JSObject> current = object; | |
| 1240 int depth = 0; | 1214 int depth = 0; |
| 1241 | 1215 |
| 1216 const int kHolderIndex = FunctionCallbackArguments::kHolderIndex + 1; |
| 1242 if (save_at_depth == depth) { | 1217 if (save_at_depth == depth) { |
| 1243 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); | 1218 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); |
| 1244 } | 1219 } |
| 1245 | 1220 |
| 1221 Handle<JSObject> current = Handle<JSObject>::null(); |
| 1222 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); |
| 1223 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 1224 Handle<Map> current_map = receiver_map; |
| 1225 Handle<Map> holder_map(holder->map()); |
| 1246 // Traverse the prototype chain and check the maps in the prototype chain for | 1226 // Traverse the prototype chain and check the maps in the prototype chain for |
| 1247 // fast and global objects or do negative lookup for normal objects. | 1227 // fast and global objects or do negative lookup for normal objects. |
| 1248 while (!current.is_identical_to(holder)) { | 1228 while (!current_map.is_identical_to(holder_map)) { |
| 1249 ++depth; | 1229 ++depth; |
| 1250 | 1230 |
| 1251 // Only global objects and objects that do not require access | 1231 // Only global objects and objects that do not require access |
| 1252 // checks are allowed in stubs. | 1232 // checks are allowed in stubs. |
| 1253 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1233 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1234 !current_map->is_access_check_needed()); |
| 1254 | 1235 |
| 1255 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); | 1236 prototype = handle(JSObject::cast(current_map->prototype())); |
| 1256 if (!current->HasFastProperties() && | 1237 if (current_map->is_dictionary_map() && |
| 1257 !current->IsJSGlobalObject() && | 1238 !current_map->IsJSGlobalObjectMap() && |
| 1258 !current->IsJSGlobalProxy()) { | 1239 !current_map->IsJSGlobalProxyMap()) { |
| 1259 if (!name->IsUniqueName()) { | 1240 if (!name->IsUniqueName()) { |
| 1260 ASSERT(name->IsString()); | 1241 ASSERT(name->IsString()); |
| 1261 name = factory()->InternalizeString(Handle<String>::cast(name)); | 1242 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 1262 } | 1243 } |
| 1263 ASSERT(current->property_dictionary()->FindEntry(*name) == | 1244 ASSERT(current.is_null() || |
| 1245 current->property_dictionary()->FindEntry(*name) == |
| 1264 NameDictionary::kNotFound); | 1246 NameDictionary::kNotFound); |
| 1265 | 1247 |
| 1266 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 1248 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 1267 scratch1, scratch2); | 1249 scratch1, scratch2); |
| 1268 | 1250 |
| 1269 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1251 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1270 reg = holder_reg; // From now on the object will be in holder_reg. | 1252 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1271 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1253 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1272 } else { | 1254 } else { |
| 1273 bool in_new_space = heap()->InNewSpace(*prototype); | 1255 bool in_new_space = heap()->InNewSpace(*prototype); |
| 1274 Handle<Map> current_map(current->map()); | 1256 if (depth != 1 || check == CHECK_ALL_MAPS) { |
| 1275 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { | |
| 1276 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); | 1257 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); |
| 1277 } | 1258 } |
| 1278 | 1259 |
| 1279 // Check access rights to the global object. This has to happen after | 1260 // Check access rights to the global object. This has to happen after |
| 1280 // the map check so that we know that the object is actually a global | 1261 // the map check so that we know that the object is actually a global |
| 1281 // object. | 1262 // object. |
| 1282 if (current->IsJSGlobalProxy()) { | 1263 if (current_map->IsJSGlobalProxyMap()) { |
| 1283 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); | 1264 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); |
| 1265 } else if (current_map->IsJSGlobalObjectMap()) { |
| 1266 GenerateCheckPropertyCell( |
| 1267 masm(), Handle<JSGlobalObject>::cast(current), name, |
| 1268 scratch2, miss); |
| 1284 } | 1269 } |
| 1285 | 1270 |
| 1286 if (in_new_space) { | 1271 if (in_new_space) { |
| 1287 // Save the map in scratch1 for later. | 1272 // Save the map in scratch1 for later. |
| 1288 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1273 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1289 } | 1274 } |
| 1290 | 1275 |
| 1291 reg = holder_reg; // From now on the object will be in holder_reg. | 1276 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1292 | 1277 |
| 1293 if (in_new_space) { | 1278 if (in_new_space) { |
| 1294 // The prototype is in new space; we cannot store a reference to it | 1279 // The prototype is in new space; we cannot store a reference to it |
| 1295 // in the code. Load it from the map. | 1280 // in the code. Load it from the map. |
| 1296 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1281 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1297 } else { | 1282 } else { |
| 1298 // The prototype is in old space; load it directly. | 1283 // The prototype is in old space; load it directly. |
| 1299 __ mov(reg, prototype); | 1284 __ mov(reg, prototype); |
| 1300 } | 1285 } |
| 1301 } | 1286 } |
| 1302 | 1287 |
| 1303 if (save_at_depth == depth) { | 1288 if (save_at_depth == depth) { |
| 1304 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); | 1289 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); |
| 1305 } | 1290 } |
| 1306 | 1291 |
| 1307 // Go to the next object in the prototype chain. | 1292 // Go to the next object in the prototype chain. |
| 1308 current = prototype; | 1293 current = prototype; |
| 1294 current_map = handle(current->map()); |
| 1309 } | 1295 } |
| 1310 ASSERT(current.is_identical_to(holder)); | |
| 1311 | 1296 |
| 1312 // Log the check depth. | 1297 // Log the check depth. |
| 1313 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1298 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1314 | 1299 |
| 1315 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { | 1300 if (depth != 0 || check == CHECK_ALL_MAPS) { |
| 1316 // Check the holder map. | 1301 // Check the holder map. |
| 1317 __ CheckMap(reg, Handle<Map>(holder->map()), miss, DONT_DO_SMI_CHECK); | 1302 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); |
| 1318 } | 1303 } |
| 1319 | 1304 |
| 1320 // Perform security check for access to the global object. | 1305 // Perform security check for access to the global object. |
| 1321 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1306 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1322 if (holder->IsJSGlobalProxy()) { | 1307 !current_map->is_access_check_needed()); |
| 1308 if (current_map->IsJSGlobalProxyMap()) { |
| 1323 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); | 1309 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); |
| 1324 } | 1310 } |
| 1325 | 1311 |
| 1326 // If we've skipped any global objects, it's not enough to verify that | |
| 1327 // their maps haven't changed. We also need to check that the property | |
| 1328 // cell for the property is still empty. | |
| 1329 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | |
| 1330 | |
| 1331 // Return the register containing the holder. | 1312 // Return the register containing the holder. |
| 1332 return reg; | 1313 return reg; |
| 1333 } | 1314 } |
| 1334 | 1315 |
| 1335 | 1316 |
| 1336 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 1317 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1337 if (!miss->is_unused()) { | 1318 if (!miss->is_unused()) { |
| 1338 Label success; | 1319 Label success; |
| 1339 __ jmp(&success); | 1320 __ jmp(&success); |
| 1340 __ bind(miss); | 1321 __ bind(miss); |
| 1341 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1322 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1342 __ bind(&success); | 1323 __ bind(&success); |
| 1343 } | 1324 } |
| 1344 } | 1325 } |
| 1345 | 1326 |
| 1346 | 1327 |
| 1347 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 1328 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1348 if (!miss->is_unused()) { | 1329 if (!miss->is_unused()) { |
| 1349 Label success; | 1330 Label success; |
| 1350 __ jmp(&success); | 1331 __ jmp(&success); |
| 1351 GenerateRestoreName(masm(), miss, name); | 1332 GenerateRestoreName(masm(), miss, name); |
| 1352 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1333 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1353 __ bind(&success); | 1334 __ bind(&success); |
| 1354 } | 1335 } |
| 1355 } | 1336 } |
| 1356 | 1337 |
| 1357 | 1338 |
| 1358 Register LoadStubCompiler::CallbackHandlerFrontend( | 1339 Register LoadStubCompiler::CallbackHandlerFrontend( |
| 1359 Handle<Object> object, | 1340 Handle<Type> type, |
| 1360 Register object_reg, | 1341 Register object_reg, |
| 1361 Handle<JSObject> holder, | 1342 Handle<JSObject> holder, |
| 1362 Handle<Name> name, | 1343 Handle<Name> name, |
| 1363 Handle<Object> callback) { | 1344 Handle<Object> callback) { |
| 1364 Label miss; | 1345 Label miss; |
| 1365 | 1346 |
| 1366 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); | 1347 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); |
| 1367 | 1348 |
| 1368 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1349 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| 1369 ASSERT(!reg.is(scratch2())); | 1350 ASSERT(!reg.is(scratch2())); |
| 1370 ASSERT(!reg.is(scratch3())); | 1351 ASSERT(!reg.is(scratch3())); |
| 1371 Register dictionary = scratch1(); | 1352 Register dictionary = scratch1(); |
| 1372 bool must_preserve_dictionary_reg = reg.is(dictionary); | 1353 bool must_preserve_dictionary_reg = reg.is(dictionary); |
| 1373 | 1354 |
| 1374 // Load the properties dictionary. | 1355 // Load the properties dictionary. |
| 1375 if (must_preserve_dictionary_reg) { | 1356 if (must_preserve_dictionary_reg) { |
| 1376 __ push(dictionary); | 1357 __ push(dictionary); |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1560 | 1541 |
| 1561 if (must_preserve_receiver_reg) { | 1542 if (must_preserve_receiver_reg) { |
| 1562 __ push(receiver()); | 1543 __ push(receiver()); |
| 1563 } | 1544 } |
| 1564 __ push(holder_reg); | 1545 __ push(holder_reg); |
| 1565 __ push(this->name()); | 1546 __ push(this->name()); |
| 1566 | 1547 |
| 1567 // Invoke an interceptor. Note: map checks from receiver to | 1548 // Invoke an interceptor. Note: map checks from receiver to |
| 1568 // interceptor's holder has been compiled before (see a caller | 1549 // interceptor's holder has been compiled before (see a caller |
| 1569 // of this method.) | 1550 // of this method.) |
| 1570 CompileCallLoadPropertyWithInterceptor(masm(), | 1551 CompileCallLoadPropertyWithInterceptor( |
| 1571 receiver(), | 1552 masm(), receiver(), holder_reg, this->name(), interceptor_holder, |
| 1572 holder_reg, | 1553 IC::kLoadPropertyWithInterceptorOnly); |
| 1573 this->name(), | |
| 1574 interceptor_holder); | |
| 1575 | 1554 |
| 1576 // Check if interceptor provided a value for property. If it's | 1555 // Check if interceptor provided a value for property. If it's |
| 1577 // the case, return immediately. | 1556 // the case, return immediately. |
| 1578 Label interceptor_failed; | 1557 Label interceptor_failed; |
| 1579 __ cmp(eax, factory()->no_interceptor_result_sentinel()); | 1558 __ cmp(eax, factory()->no_interceptor_result_sentinel()); |
| 1580 __ j(equal, &interceptor_failed); | 1559 __ j(equal, &interceptor_failed); |
| 1581 frame_scope.GenerateLeaveFrame(); | 1560 frame_scope.GenerateLeaveFrame(); |
| 1582 __ ret(0); | 1561 __ ret(0); |
| 1583 | 1562 |
| 1584 // Clobber registers when generating debug-code to provoke errors. | 1563 // Clobber registers when generating debug-code to provoke errors. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1631 | 1610 |
| 1632 // Get the number of arguments. | 1611 // Get the number of arguments. |
| 1633 const int argc = arguments().immediate(); | 1612 const int argc = arguments().immediate(); |
| 1634 | 1613 |
| 1635 // Get the receiver from the stack. | 1614 // Get the receiver from the stack. |
| 1636 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1615 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1637 | 1616 |
| 1638 | 1617 |
| 1639 // Check that the maps haven't changed. | 1618 // Check that the maps haven't changed. |
| 1640 __ JumpIfSmi(edx, miss); | 1619 __ JumpIfSmi(edx, miss); |
| 1641 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); | 1620 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 1621 ebx, eax, edi, name, miss); |
| 1642 } | 1622 } |
| 1643 | 1623 |
| 1644 | 1624 |
| 1645 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1625 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1646 Handle<Cell> cell, | 1626 Handle<Cell> cell, |
| 1647 Handle<JSFunction> function, | 1627 Handle<JSFunction> function, |
| 1648 Label* miss) { | 1628 Label* miss) { |
| 1649 // Get the value from the cell. | 1629 // Get the value from the cell. |
| 1650 if (Serializer::enabled()) { | 1630 if (Serializer::enabled()) { |
| 1651 __ mov(edi, Immediate(cell)); | 1631 __ mov(edi, Immediate(cell)); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1700 GenerateNameCheck(name, &miss); | 1680 GenerateNameCheck(name, &miss); |
| 1701 | 1681 |
| 1702 // Get the receiver from the stack. | 1682 // Get the receiver from the stack. |
| 1703 const int argc = arguments().immediate(); | 1683 const int argc = arguments().immediate(); |
| 1704 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1684 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1705 | 1685 |
| 1706 // Check that the receiver isn't a smi. | 1686 // Check that the receiver isn't a smi. |
| 1707 __ JumpIfSmi(edx, &miss); | 1687 __ JumpIfSmi(edx, &miss); |
| 1708 | 1688 |
| 1709 // Do the right check and compute the holder register. | 1689 // Do the right check and compute the holder register. |
| 1710 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, | 1690 Register reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, |
| 1711 name, &miss); | 1691 holder, ebx, eax, edi, name, &miss); |
| 1712 | 1692 |
| 1713 GenerateFastPropertyLoad( | 1693 GenerateFastPropertyLoad( |
| 1714 masm(), edi, reg, index.is_inobject(holder), | 1694 masm(), edi, reg, index.is_inobject(holder), |
| 1715 index.translate(holder), Representation::Tagged()); | 1695 index.translate(holder), Representation::Tagged()); |
| 1716 | 1696 |
| 1717 // Check that the function really is a function. | 1697 // Check that the function really is a function. |
| 1718 __ JumpIfSmi(edi, &miss); | 1698 __ JumpIfSmi(edi, &miss); |
| 1719 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1699 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
| 1720 __ j(not_equal, &miss); | 1700 __ j(not_equal, &miss); |
| 1721 | 1701 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1754 // Check that function is still array | 1734 // Check that function is still array |
| 1755 const int argc = arguments().immediate(); | 1735 const int argc = arguments().immediate(); |
| 1756 GenerateNameCheck(name, &miss); | 1736 GenerateNameCheck(name, &miss); |
| 1757 | 1737 |
| 1758 if (cell.is_null()) { | 1738 if (cell.is_null()) { |
| 1759 // Get the receiver from the stack. | 1739 // Get the receiver from the stack. |
| 1760 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1740 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1761 | 1741 |
| 1762 // Check that the receiver isn't a smi. | 1742 // Check that the receiver isn't a smi. |
| 1763 __ JumpIfSmi(edx, &miss); | 1743 __ JumpIfSmi(edx, &miss); |
| 1764 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 1744 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 1765 name, &miss); | 1745 ebx, eax, edi, name, &miss); |
| 1766 } else { | 1746 } else { |
| 1767 ASSERT(cell->value() == *function); | 1747 ASSERT(cell->value() == *function); |
| 1768 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 1748 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1769 &miss); | 1749 &miss); |
| 1770 GenerateLoadFunctionFromCell(cell, function, &miss); | 1750 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1771 } | 1751 } |
| 1772 | 1752 |
| 1773 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1753 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1774 site->SetElementsKind(GetInitialFastElementsKind()); | 1754 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1775 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1755 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1814 | 1794 |
| 1815 GenerateNameCheck(name, &miss); | 1795 GenerateNameCheck(name, &miss); |
| 1816 | 1796 |
| 1817 // Get the receiver from the stack. | 1797 // Get the receiver from the stack. |
| 1818 const int argc = arguments().immediate(); | 1798 const int argc = arguments().immediate(); |
| 1819 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1799 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1820 | 1800 |
| 1821 // Check that the receiver isn't a smi. | 1801 // Check that the receiver isn't a smi. |
| 1822 __ JumpIfSmi(edx, &miss); | 1802 __ JumpIfSmi(edx, &miss); |
| 1823 | 1803 |
| 1824 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 1804 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 1825 name, &miss); | 1805 ebx, eax, edi, name, &miss); |
| 1826 | 1806 |
| 1827 if (argc == 0) { | 1807 if (argc == 0) { |
| 1828 // Noop, return the length. | 1808 // Noop, return the length. |
| 1829 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1809 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
| 1830 __ ret((argc + 1) * kPointerSize); | 1810 __ ret((argc + 1) * kPointerSize); |
| 1831 } else { | 1811 } else { |
| 1832 Label call_builtin; | 1812 Label call_builtin; |
| 1833 | 1813 |
| 1834 if (argc == 1) { // Otherwise fall through to call builtin. | 1814 if (argc == 1) { // Otherwise fall through to call builtin. |
| 1835 Label attempt_to_grow_elements, with_write_barrier, check_double; | 1815 Label attempt_to_grow_elements, with_write_barrier, check_double; |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2074 Label miss, return_undefined, call_builtin; | 2054 Label miss, return_undefined, call_builtin; |
| 2075 | 2055 |
| 2076 GenerateNameCheck(name, &miss); | 2056 GenerateNameCheck(name, &miss); |
| 2077 | 2057 |
| 2078 // Get the receiver from the stack. | 2058 // Get the receiver from the stack. |
| 2079 const int argc = arguments().immediate(); | 2059 const int argc = arguments().immediate(); |
| 2080 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2060 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2081 | 2061 |
| 2082 // Check that the receiver isn't a smi. | 2062 // Check that the receiver isn't a smi. |
| 2083 __ JumpIfSmi(edx, &miss); | 2063 __ JumpIfSmi(edx, &miss); |
| 2084 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2064 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 2085 name, &miss); | 2065 ebx, eax, edi, name, &miss); |
| 2086 | 2066 |
| 2087 // Get the elements array of the object. | 2067 // Get the elements array of the object. |
| 2088 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 2068 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
| 2089 | 2069 |
| 2090 // Check that the elements are in fast mode and writable. | 2070 // Check that the elements are in fast mode and writable. |
| 2091 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 2071 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
| 2092 Immediate(factory()->fixed_array_map())); | 2072 Immediate(factory()->fixed_array_map())); |
| 2093 __ j(not_equal, &call_builtin); | 2073 __ j(not_equal, &call_builtin); |
| 2094 | 2074 |
| 2095 // Get the array's length into ecx and calculate new length. | 2075 // Get the array's length into ecx and calculate new length. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2168 } | 2148 } |
| 2169 | 2149 |
| 2170 GenerateNameCheck(name, &name_miss); | 2150 GenerateNameCheck(name, &name_miss); |
| 2171 | 2151 |
| 2172 // Check that the maps starting from the prototype haven't changed. | 2152 // Check that the maps starting from the prototype haven't changed. |
| 2173 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2153 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2174 Context::STRING_FUNCTION_INDEX, | 2154 Context::STRING_FUNCTION_INDEX, |
| 2175 eax, | 2155 eax, |
| 2176 &miss); | 2156 &miss); |
| 2177 ASSERT(!object.is_identical_to(holder)); | 2157 ASSERT(!object.is_identical_to(holder)); |
| 2158 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2178 CheckPrototypes( | 2159 CheckPrototypes( |
| 2179 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2160 IC::CurrentTypeOf(prototype, isolate()), |
| 2180 eax, holder, ebx, edx, edi, name, &miss); | 2161 eax, holder, ebx, edx, edi, name, &miss); |
| 2181 | 2162 |
| 2182 Register receiver = ebx; | 2163 Register receiver = ebx; |
| 2183 Register index = edi; | 2164 Register index = edi; |
| 2184 Register result = eax; | 2165 Register result = eax; |
| 2185 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 2166 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
| 2186 if (argc > 0) { | 2167 if (argc > 0) { |
| 2187 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 2168 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
| 2188 } else { | 2169 } else { |
| 2189 __ Set(index, Immediate(factory()->undefined_value())); | 2170 __ Set(index, Immediate(factory()->undefined_value())); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2253 } | 2234 } |
| 2254 | 2235 |
| 2255 GenerateNameCheck(name, &name_miss); | 2236 GenerateNameCheck(name, &name_miss); |
| 2256 | 2237 |
| 2257 // Check that the maps starting from the prototype haven't changed. | 2238 // Check that the maps starting from the prototype haven't changed. |
| 2258 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2239 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2259 Context::STRING_FUNCTION_INDEX, | 2240 Context::STRING_FUNCTION_INDEX, |
| 2260 eax, | 2241 eax, |
| 2261 &miss); | 2242 &miss); |
| 2262 ASSERT(!object.is_identical_to(holder)); | 2243 ASSERT(!object.is_identical_to(holder)); |
| 2244 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2263 CheckPrototypes( | 2245 CheckPrototypes( |
| 2264 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2246 IC::CurrentTypeOf(prototype, isolate()), |
| 2265 eax, holder, ebx, edx, edi, name, &miss); | 2247 eax, holder, ebx, edx, edi, name, &miss); |
| 2266 | 2248 |
| 2267 Register receiver = eax; | 2249 Register receiver = eax; |
| 2268 Register index = edi; | 2250 Register index = edi; |
| 2269 Register scratch = edx; | 2251 Register scratch = edx; |
| 2270 Register result = eax; | 2252 Register result = eax; |
| 2271 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 2253 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
| 2272 if (argc > 0) { | 2254 if (argc > 0) { |
| 2273 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 2255 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
| 2274 } else { | 2256 } else { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2329 return Handle<Code>::null(); | 2311 return Handle<Code>::null(); |
| 2330 } | 2312 } |
| 2331 | 2313 |
| 2332 Label miss; | 2314 Label miss; |
| 2333 GenerateNameCheck(name, &miss); | 2315 GenerateNameCheck(name, &miss); |
| 2334 | 2316 |
| 2335 if (cell.is_null()) { | 2317 if (cell.is_null()) { |
| 2336 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2318 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 2337 STATIC_ASSERT(kSmiTag == 0); | 2319 STATIC_ASSERT(kSmiTag == 0); |
| 2338 __ JumpIfSmi(edx, &miss); | 2320 __ JumpIfSmi(edx, &miss); |
| 2339 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2321 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 2340 name, &miss); | 2322 ebx, eax, edi, name, &miss); |
| 2341 } else { | 2323 } else { |
| 2342 ASSERT(cell->value() == *function); | 2324 ASSERT(cell->value() == *function); |
| 2343 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2325 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2344 &miss); | 2326 &miss); |
| 2345 GenerateLoadFunctionFromCell(cell, function, &miss); | 2327 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2346 } | 2328 } |
| 2347 | 2329 |
| 2348 // Load the char code argument. | 2330 // Load the char code argument. |
| 2349 Register code = ebx; | 2331 Register code = ebx; |
| 2350 __ mov(code, Operand(esp, 1 * kPointerSize)); | 2332 __ mov(code, Operand(esp, 1 * kPointerSize)); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2414 | 2396 |
| 2415 Label miss; | 2397 Label miss; |
| 2416 GenerateNameCheck(name, &miss); | 2398 GenerateNameCheck(name, &miss); |
| 2417 | 2399 |
| 2418 if (cell.is_null()) { | 2400 if (cell.is_null()) { |
| 2419 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2401 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 2420 | 2402 |
| 2421 STATIC_ASSERT(kSmiTag == 0); | 2403 STATIC_ASSERT(kSmiTag == 0); |
| 2422 __ JumpIfSmi(edx, &miss); | 2404 __ JumpIfSmi(edx, &miss); |
| 2423 | 2405 |
| 2424 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2406 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 2425 name, &miss); | 2407 ebx, eax, edi, name, &miss); |
| 2426 } else { | 2408 } else { |
| 2427 ASSERT(cell->value() == *function); | 2409 ASSERT(cell->value() == *function); |
| 2428 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2410 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2429 &miss); | 2411 &miss); |
| 2430 GenerateLoadFunctionFromCell(cell, function, &miss); | 2412 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2431 } | 2413 } |
| 2432 | 2414 |
| 2433 // Load the (only) argument into eax. | 2415 // Load the (only) argument into eax. |
| 2434 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2416 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
| 2435 | 2417 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2540 | 2522 |
| 2541 Label miss; | 2523 Label miss; |
| 2542 GenerateNameCheck(name, &miss); | 2524 GenerateNameCheck(name, &miss); |
| 2543 | 2525 |
| 2544 if (cell.is_null()) { | 2526 if (cell.is_null()) { |
| 2545 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2527 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 2546 | 2528 |
| 2547 STATIC_ASSERT(kSmiTag == 0); | 2529 STATIC_ASSERT(kSmiTag == 0); |
| 2548 __ JumpIfSmi(edx, &miss); | 2530 __ JumpIfSmi(edx, &miss); |
| 2549 | 2531 |
| 2550 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2532 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 2551 name, &miss); | 2533 ebx, eax, edi, name, &miss); |
| 2552 } else { | 2534 } else { |
| 2553 ASSERT(cell->value() == *function); | 2535 ASSERT(cell->value() == *function); |
| 2554 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2536 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2555 &miss); | 2537 &miss); |
| 2556 GenerateLoadFunctionFromCell(cell, function, &miss); | 2538 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2557 } | 2539 } |
| 2558 | 2540 |
| 2559 // Load the (only) argument into eax. | 2541 // Load the (only) argument into eax. |
| 2560 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2542 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
| 2561 | 2543 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2654 | 2636 |
| 2655 Counters* counters = isolate()->counters(); | 2637 Counters* counters = isolate()->counters(); |
| 2656 __ IncrementCounter(counters->call_const(), 1); | 2638 __ IncrementCounter(counters->call_const(), 1); |
| 2657 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2639 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| 2658 | 2640 |
| 2659 // Allocate space for v8::Arguments implicit values. Must be initialized | 2641 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2660 // before calling any runtime function. | 2642 // before calling any runtime function. |
| 2661 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2643 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2662 | 2644 |
| 2663 // Check that the maps haven't changed and find a Holder as a side effect. | 2645 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2664 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2646 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 2665 name, depth, &miss); | 2647 ebx, eax, edi, name, depth, &miss); |
| 2666 | 2648 |
| 2667 // Move the return address on top of the stack. | 2649 // Move the return address on top of the stack. |
| 2668 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); | 2650 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); |
| 2669 __ mov(Operand(esp, 0 * kPointerSize), eax); | 2651 __ mov(Operand(esp, 0 * kPointerSize), eax); |
| 2670 | 2652 |
| 2671 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2653 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
| 2672 // duplicate of return address and will be overwritten. | 2654 // duplicate of return address and will be overwritten. |
| 2673 GenerateFastApiCall(masm(), optimization, argc); | 2655 GenerateFastApiCall(masm(), optimization, argc); |
| 2674 | 2656 |
| 2675 __ bind(&miss); | 2657 __ bind(&miss); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2718 } | 2700 } |
| 2719 | 2701 |
| 2720 // Make sure that it's okay not to patch the on stack receiver | 2702 // Make sure that it's okay not to patch the on stack receiver |
| 2721 // unless we're doing a receiver map check. | 2703 // unless we're doing a receiver map check. |
| 2722 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2704 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2723 switch (check) { | 2705 switch (check) { |
| 2724 case RECEIVER_MAP_CHECK: | 2706 case RECEIVER_MAP_CHECK: |
| 2725 __ IncrementCounter(isolate()->counters()->call_const(), 1); | 2707 __ IncrementCounter(isolate()->counters()->call_const(), 1); |
| 2726 | 2708 |
| 2727 // Check that the maps haven't changed. | 2709 // Check that the maps haven't changed. |
| 2728 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, | 2710 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 2729 edi, name, &miss); | 2711 ebx, eax, edi, name, &miss); |
| 2730 | 2712 |
| 2731 // Patch the receiver on the stack with the global proxy if | 2713 // Patch the receiver on the stack with the global proxy if |
| 2732 // necessary. | 2714 // necessary. |
| 2733 if (object->IsGlobalObject()) { | 2715 if (object->IsGlobalObject()) { |
| 2734 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2716 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2735 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2717 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 2736 } | 2718 } |
| 2737 break; | 2719 break; |
| 2738 | 2720 |
| 2739 case STRING_CHECK: | 2721 case STRING_CHECK: { |
| 2740 // Check that the object is a string. | 2722 // Check that the object is a string. |
| 2741 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); | 2723 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); |
| 2742 __ j(above_equal, &miss); | 2724 __ j(above_equal, &miss); |
| 2743 // Check that the maps starting from the prototype haven't changed. | 2725 // Check that the maps starting from the prototype haven't changed. |
| 2744 GenerateDirectLoadGlobalFunctionPrototype( | 2726 GenerateDirectLoadGlobalFunctionPrototype( |
| 2745 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); | 2727 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); |
| 2728 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2746 CheckPrototypes( | 2729 CheckPrototypes( |
| 2747 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2730 IC::CurrentTypeOf(prototype, isolate()), |
| 2748 eax, holder, ebx, edx, edi, name, &miss); | 2731 eax, holder, ebx, edx, edi, name, &miss); |
| 2749 break; | 2732 break; |
| 2750 | 2733 } |
| 2751 case SYMBOL_CHECK: | 2734 case SYMBOL_CHECK: { |
| 2752 // Check that the object is a symbol. | 2735 // Check that the object is a symbol. |
| 2753 __ CmpObjectType(edx, SYMBOL_TYPE, eax); | 2736 __ CmpObjectType(edx, SYMBOL_TYPE, eax); |
| 2754 __ j(not_equal, &miss); | 2737 __ j(not_equal, &miss); |
| 2755 // Check that the maps starting from the prototype haven't changed. | 2738 // Check that the maps starting from the prototype haven't changed. |
| 2756 GenerateDirectLoadGlobalFunctionPrototype( | 2739 GenerateDirectLoadGlobalFunctionPrototype( |
| 2757 masm(), Context::SYMBOL_FUNCTION_INDEX, eax, &miss); | 2740 masm(), Context::SYMBOL_FUNCTION_INDEX, eax, &miss); |
| 2741 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2758 CheckPrototypes( | 2742 CheckPrototypes( |
| 2759 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2743 IC::CurrentTypeOf(prototype, isolate()), |
| 2760 eax, holder, ebx, edx, edi, name, &miss); | 2744 eax, holder, ebx, edx, edi, name, &miss); |
| 2761 break; | 2745 break; |
| 2762 | 2746 } |
| 2763 case NUMBER_CHECK: { | 2747 case NUMBER_CHECK: { |
| 2764 Label fast; | 2748 Label fast; |
| 2765 // Check that the object is a smi or a heap number. | 2749 // Check that the object is a smi or a heap number. |
| 2766 __ JumpIfSmi(edx, &fast); | 2750 __ JumpIfSmi(edx, &fast); |
| 2767 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); | 2751 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); |
| 2768 __ j(not_equal, &miss); | 2752 __ j(not_equal, &miss); |
| 2769 __ bind(&fast); | 2753 __ bind(&fast); |
| 2770 // Check that the maps starting from the prototype haven't changed. | 2754 // Check that the maps starting from the prototype haven't changed. |
| 2771 GenerateDirectLoadGlobalFunctionPrototype( | 2755 GenerateDirectLoadGlobalFunctionPrototype( |
| 2772 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); | 2756 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); |
| 2757 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2773 CheckPrototypes( | 2758 CheckPrototypes( |
| 2774 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2759 IC::CurrentTypeOf(prototype, isolate()), |
| 2775 eax, holder, ebx, edx, edi, name, &miss); | 2760 eax, holder, ebx, edx, edi, name, &miss); |
| 2776 break; | 2761 break; |
| 2777 } | 2762 } |
| 2778 case BOOLEAN_CHECK: { | 2763 case BOOLEAN_CHECK: { |
| 2779 GenerateBooleanCheck(edx, &miss); | 2764 GenerateBooleanCheck(edx, &miss); |
| 2780 // Check that the maps starting from the prototype haven't changed. | 2765 // Check that the maps starting from the prototype haven't changed. |
| 2781 GenerateDirectLoadGlobalFunctionPrototype( | 2766 GenerateDirectLoadGlobalFunctionPrototype( |
| 2782 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); | 2767 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); |
| 2768 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2783 CheckPrototypes( | 2769 CheckPrototypes( |
| 2784 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2770 IC::CurrentTypeOf(prototype, isolate()), |
| 2785 eax, holder, ebx, edx, edi, name, &miss); | 2771 eax, holder, ebx, edx, edi, name, &miss); |
| 2786 break; | 2772 break; |
| 2787 } | 2773 } |
| 2788 } | 2774 } |
| 2789 | 2775 |
| 2790 Label success; | 2776 Label success; |
| 2791 __ jmp(&success); | 2777 __ jmp(&success); |
| 2792 | 2778 |
| 2793 // Handle call cache miss. | 2779 // Handle call cache miss. |
| 2794 __ bind(&miss); | 2780 __ bind(&miss); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2952 // Return the generated code. | 2938 // Return the generated code. |
| 2953 return GetCode(Code::NORMAL, name); | 2939 return GetCode(Code::NORMAL, name); |
| 2954 } | 2940 } |
| 2955 | 2941 |
| 2956 | 2942 |
| 2957 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2943 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2958 Handle<JSObject> object, | 2944 Handle<JSObject> object, |
| 2959 Handle<JSObject> holder, | 2945 Handle<JSObject> holder, |
| 2960 Handle<Name> name, | 2946 Handle<Name> name, |
| 2961 Handle<ExecutableAccessorInfo> callback) { | 2947 Handle<ExecutableAccessorInfo> callback) { |
| 2962 HandlerFrontend(object, receiver(), holder, name); | 2948 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 2949 receiver(), holder, name); |
| 2963 | 2950 |
| 2964 __ pop(scratch1()); // remove the return address | 2951 __ pop(scratch1()); // remove the return address |
| 2965 __ push(receiver()); | 2952 __ push(receiver()); |
| 2966 __ Push(callback); | 2953 __ Push(callback); |
| 2967 __ Push(name); | 2954 __ Push(name); |
| 2968 __ push(value()); | 2955 __ push(value()); |
| 2969 __ push(scratch1()); // restore return address | 2956 __ push(scratch1()); // restore return address |
| 2970 | 2957 |
| 2971 // Do tail-call to the runtime system. | 2958 // Do tail-call to the runtime system. |
| 2972 ExternalReference store_callback_property = | 2959 ExternalReference store_callback_property = |
| 2973 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 2960 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
| 2974 __ TailCallExternalReference(store_callback_property, 4, 1); | 2961 __ TailCallExternalReference(store_callback_property, 4, 1); |
| 2975 | 2962 |
| 2976 // Return the generated code. | 2963 // Return the generated code. |
| 2977 return GetCode(kind(), Code::FAST, name); | 2964 return GetCode(kind(), Code::FAST, name); |
| 2978 } | 2965 } |
| 2979 | 2966 |
| 2980 | 2967 |
| 2981 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2968 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2982 Handle<JSObject> object, | 2969 Handle<JSObject> object, |
| 2983 Handle<JSObject> holder, | 2970 Handle<JSObject> holder, |
| 2984 Handle<Name> name, | 2971 Handle<Name> name, |
| 2985 const CallOptimization& call_optimization) { | 2972 const CallOptimization& call_optimization) { |
| 2986 HandlerFrontend(object, receiver(), holder, name); | 2973 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), |
| 2974 receiver(), holder, name); |
| 2987 | 2975 |
| 2988 Register values[] = { value() }; | 2976 Register values[] = { value() }; |
| 2989 GenerateFastApiCall( | 2977 GenerateFastApiCall( |
| 2990 masm(), call_optimization, receiver(), scratch1(), | 2978 masm(), call_optimization, receiver(), scratch1(), |
| 2991 scratch2(), this->name(), 1, values); | 2979 scratch2(), this->name(), 1, values); |
| 2992 | 2980 |
| 2993 // Return the generated code. | 2981 // Return the generated code. |
| 2994 return GetCode(kind(), Code::FAST, name); | 2982 return GetCode(kind(), Code::FAST, name); |
| 2995 } | 2983 } |
| 2996 | 2984 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3083 } | 3071 } |
| 3084 __ bind(&miss); | 3072 __ bind(&miss); |
| 3085 TailCallBuiltin(masm(), MissBuiltin(kind())); | 3073 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 3086 | 3074 |
| 3087 // Return the generated code. | 3075 // Return the generated code. |
| 3088 return GetICCode( | 3076 return GetICCode( |
| 3089 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 3077 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
| 3090 } | 3078 } |
| 3091 | 3079 |
| 3092 | 3080 |
| 3093 Handle<Code> LoadStubCompiler::CompileLoadNonexistent( | 3081 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type, |
| 3094 Handle<Object> object, | 3082 Handle<JSObject> last, |
| 3095 Handle<JSObject> last, | 3083 Handle<Name> name) { |
| 3096 Handle<Name> name, | 3084 NonexistentHandlerFrontend(type, last, name); |
| 3097 Handle<JSGlobalObject> global) { | |
| 3098 NonexistentHandlerFrontend(object, last, name, global); | |
| 3099 | 3085 |
| 3100 // Return undefined if maps of the full prototype chain are still the | 3086 // Return undefined if maps of the full prototype chain are still the |
| 3101 // same and no global property with this name contains a value. | 3087 // same and no global property with this name contains a value. |
| 3102 __ mov(eax, isolate()->factory()->undefined_value()); | 3088 __ mov(eax, isolate()->factory()->undefined_value()); |
| 3103 __ ret(0); | 3089 __ ret(0); |
| 3104 | 3090 |
| 3105 // Return the generated code. | 3091 // Return the generated code. |
| 3106 return GetCode(kind(), Code::FAST, name); | 3092 return GetCode(kind(), Code::FAST, name); |
| 3107 } | 3093 } |
| 3108 | 3094 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3179 } | 3165 } |
| 3180 __ ret(0); | 3166 __ ret(0); |
| 3181 } | 3167 } |
| 3182 | 3168 |
| 3183 | 3169 |
| 3184 #undef __ | 3170 #undef __ |
| 3185 #define __ ACCESS_MASM(masm()) | 3171 #define __ ACCESS_MASM(masm()) |
| 3186 | 3172 |
| 3187 | 3173 |
| 3188 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 3174 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 3189 Handle<Object> object, | 3175 Handle<Type> type, |
| 3190 Handle<GlobalObject> global, | 3176 Handle<GlobalObject> global, |
| 3191 Handle<PropertyCell> cell, | 3177 Handle<PropertyCell> cell, |
| 3192 Handle<Name> name, | 3178 Handle<Name> name, |
| 3193 bool is_dont_delete) { | 3179 bool is_dont_delete) { |
| 3194 Label miss; | 3180 Label miss; |
| 3195 | 3181 |
| 3196 HandlerFrontendHeader(object, receiver(), global, name, &miss); | 3182 HandlerFrontendHeader(type, receiver(), global, name, &miss); |
| 3197 // Get the value from the cell. | 3183 // Get the value from the cell. |
| 3198 if (Serializer::enabled()) { | 3184 if (Serializer::enabled()) { |
| 3199 __ mov(eax, Immediate(cell)); | 3185 __ mov(eax, Immediate(cell)); |
| 3200 __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset)); | 3186 __ mov(eax, FieldOperand(eax, PropertyCell::kValueOffset)); |
| 3201 } else { | 3187 } else { |
| 3202 __ mov(eax, Operand::ForCell(cell)); | 3188 __ mov(eax, Operand::ForCell(cell)); |
| 3203 } | 3189 } |
| 3204 | 3190 |
| 3205 // Check for deleted property if property can actually be deleted. | 3191 // Check for deleted property if property can actually be deleted. |
| 3206 if (!is_dont_delete) { | 3192 if (!is_dont_delete) { |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3314 // ----------------------------------- | 3300 // ----------------------------------- |
| 3315 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 3301 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3316 } | 3302 } |
| 3317 | 3303 |
| 3318 | 3304 |
| 3319 #undef __ | 3305 #undef __ |
| 3320 | 3306 |
| 3321 } } // namespace v8::internal | 3307 } } // namespace v8::internal |
| 3322 | 3308 |
| 3323 #endif // V8_TARGET_ARCH_IA32 | 3309 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |