Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: src/ia32/ic-ia32.cc

Issue 2853003: Port KeyedCallIC implementation to x64 and ARM.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/virtual-frame-arm.cc ('k') | src/x64/codegen-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss); 299 StubCompiler::GenerateLoadFunctionPrototype(masm, eax, edx, ebx, &miss);
300 __ bind(&miss); 300 __ bind(&miss);
301 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); 301 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
302 } 302 }
303 303
304 304
305 // Checks the receiver for special cases (value type, slow case bits). 305 // Checks the receiver for special cases (value type, slow case bits).
306 // Falls through for regular JS object. 306 // Falls through for regular JS object.
307 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, 307 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
308 Register receiver, 308 Register receiver,
309 Register r0, 309 Register map,
310 Label* slow) { 310 Label* slow) {
311 // Register use: 311 // Register use:
312 // receiver - holds the receiver and is unchanged. 312 // receiver - holds the receiver and is unchanged.
313 // Scratch registers: 313 // Scratch registers:
314 // r0 - used to hold the map of the receiver. 314 // map - used to hold the map of the receiver.
315 315
316 // Check that the object isn't a smi. 316 // Check that the object isn't a smi.
317 __ test(receiver, Immediate(kSmiTagMask)); 317 __ test(receiver, Immediate(kSmiTagMask));
318 __ j(zero, slow, not_taken); 318 __ j(zero, slow, not_taken);
319 319
320 // Get the map of the receiver. 320 // Get the map of the receiver.
321 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); 321 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset));
322 322
323 // Check bit field. 323 // Check bit field.
324 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), 324 __ test_b(FieldOperand(map, Map::kBitFieldOffset),
325 KeyedLoadIC::kSlowCaseBitFieldMask); 325 KeyedLoadIC::kSlowCaseBitFieldMask);
326 __ j(not_zero, slow, not_taken); 326 __ j(not_zero, slow, not_taken);
327 // Check that the object is some kind of JS object EXCEPT JS Value type. 327 // Check that the object is some kind of JS object EXCEPT JS Value type.
328 // In the case that the object is a value-wrapper object, 328 // In the case that the object is a value-wrapper object,
329 // we enter the runtime system to make sure that indexing 329 // we enter the runtime system to make sure that indexing
330 // into string objects works as intended. 330 // into string objects works as intended.
331 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 331 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
332 332
333 __ CmpInstanceType(r0, JS_OBJECT_TYPE); 333 __ CmpInstanceType(map, JS_OBJECT_TYPE);
334 __ j(below, slow, not_taken); 334 __ j(below, slow, not_taken);
335 } 335 }
336 336
337 337
338 // Loads an indexed element from a fast case array. 338 // Loads an indexed element from a fast case array.
339 static void GenerateFastArrayLoad(MacroAssembler* masm, 339 static void GenerateFastArrayLoad(MacroAssembler* masm,
340 Register receiver, 340 Register receiver,
341 Register key, 341 Register key,
342 Register scratch, 342 Register scratch,
343 Register result, 343 Register result,
(...skipping 20 matching lines...) Expand all
364 // In case the loaded value is the_hole we have to consult GetProperty 364 // In case the loaded value is the_hole we have to consult GetProperty
365 // to ensure the prototype chain is searched. 365 // to ensure the prototype chain is searched.
366 __ j(equal, out_of_range); 366 __ j(equal, out_of_range);
367 if (!result.is(scratch)) { 367 if (!result.is(scratch)) {
368 __ mov(result, scratch); 368 __ mov(result, scratch);
369 } 369 }
370 } 370 }
371 371
372 372
373 // Checks whether a key is an array index string or a symbol string. 373 // Checks whether a key is an array index string or a symbol string.
374 // Falls through if a key is a symbol. 374 // Falls through if the key is a symbol.
375 static void GenerateKeyStringCheck(MacroAssembler* masm, 375 static void GenerateKeyStringCheck(MacroAssembler* masm,
376 Register key, 376 Register key,
377 Register map, 377 Register map,
378 Register hash, 378 Register hash,
379 Label* index_string, 379 Label* index_string,
380 Label* not_symbol) { 380 Label* not_symbol) {
381 // Register use: 381 // Register use:
382 // key - holds the key and is unchanged. Assumed to be non-smi. 382 // key - holds the key and is unchanged. Assumed to be non-smi.
383 // Scratch registers: 383 // Scratch registers:
384 // map - used to hold the map of the key. 384 // map - used to hold the map of the key.
385 // hash - used to hold the hash of the key. 385 // hash - used to hold the hash of the key.
386 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map); 386 __ CmpObjectType(key, FIRST_NONSTRING_TYPE, map);
387 __ j(above_equal, not_symbol); 387 __ j(above_equal, not_symbol);
388 388
389 // Is the string an array index, with cached numeric value? 389 // Is the string an array index, with cached numeric value?
390 __ mov(hash, FieldOperand(key, String::kHashFieldOffset)); 390 __ mov(hash, FieldOperand(key, String::kHashFieldOffset));
391 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); 391 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask));
392 __ j(zero, index_string, not_taken); 392 __ j(zero, index_string, not_taken);
393 393
394 // Is the string a symbol? 394 // Is the string a symbol?
395 ASSERT(kSymbolTag != 0); 395 ASSERT(kSymbolTag != 0);
396 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); 396 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask);
397 __ j(zero, not_symbol, not_taken); 397 __ j(zero, not_symbol, not_taken);
398 } 398 }
399 399
400 400
401 // Picks out an array index from the hash field. 401 // Picks out an array index from the hash field.
402 // The generated code never falls through.
403 static void GenerateIndexFromHash(MacroAssembler* masm, 402 static void GenerateIndexFromHash(MacroAssembler* masm,
404 Register key, 403 Register key,
405 Register hash, 404 Register hash) {
406 Label* index_smi) {
407 // Register use: 405 // Register use:
408 // key - holds the overwritten key on exit. 406 // key - holds the overwritten key on exit.
409 // hash - holds the key's hash. Clobbered. 407 // hash - holds the key's hash. Clobbered.
410 408
411 // The assert checks that the constants for the maximum number of digits 409 // The assert checks that the constants for the maximum number of digits
412 // for an array index cached in the hash field and the number of bits 410 // for an array index cached in the hash field and the number of bits
413 // reserved for it does not conflict. 411 // reserved for it does not conflict.
414 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 412 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
415 (1 << String::kArrayIndexValueBits)); 413 (1 << String::kArrayIndexValueBits));
416 // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in 414 // We want the smi-tagged index in key. kArrayIndexValueMask has zeros in
417 // the low kHashShift bits. 415 // the low kHashShift bits.
418 // key: string key
419 // ebx: hash field.
420 ASSERT(String::kHashShift >= kSmiTagSize); 416 ASSERT(String::kHashShift >= kSmiTagSize);
421 __ and_(hash, String::kArrayIndexValueMask); 417 __ and_(hash, String::kArrayIndexValueMask);
422 __ shr(hash, String::kHashShift - kSmiTagSize); 418 __ shr(hash, String::kHashShift - kSmiTagSize);
423 // Here we actually clobber the key which will be used if calling into 419 // Here we actually clobber the key which will be used if calling into
424 // runtime later. However as the new key is the numeric value of a string key 420 // runtime later. However as the new key is the numeric value of a string key
425 // there is no difference in using either key. 421 // there is no difference in using either key.
426 __ mov(key, hash); 422 __ mov(key, hash);
427 // Now jump to the place where smi keys are handled.
428 __ jmp(index_smi);
429 } 423 }
430 424
431 425
432 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 426 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
433 // ----------- S t a t e ------------- 427 // ----------- S t a t e -------------
434 // -- eax : key 428 // -- eax : key
435 // -- edx : receiver 429 // -- edx : receiver
436 // -- esp[0] : return address 430 // -- esp[0] : return address
437 // ----------------------------------- 431 // -----------------------------------
438 Label slow, check_string, index_smi, index_string; 432 Label slow, check_string, index_smi, index_string;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 eax, 561 eax,
568 ebx, 562 ebx,
569 ecx, 563 ecx,
570 edi, 564 edi,
571 eax, 565 eax,
572 DICTIONARY_CHECK_DONE); 566 DICTIONARY_CHECK_DONE);
573 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 567 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
574 __ ret(0); 568 __ ret(0);
575 569
576 __ bind(&index_string); 570 __ bind(&index_string);
577 GenerateIndexFromHash(masm, eax, ebx, &index_smi); 571 GenerateIndexFromHash(masm, eax, ebx);
572 // Now jump to the place where smi keys are handled.
573 __ jmp(&index_smi);
578 } 574 }
579 575
580 576
581 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 577 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
582 // ----------- S t a t e ------------- 578 // ----------- S t a t e -------------
583 // -- eax : key (index) 579 // -- eax : key (index)
584 // -- edx : receiver 580 // -- edx : receiver
585 // -- esp[0] : return address 581 // -- esp[0] : return address
586 // ----------------------------------- 582 // -----------------------------------
587 Label miss; 583 Label miss;
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after
1118 } 1114 }
1119 1115
1120 1116
1121 // Defined in ic.cc. 1117 // Defined in ic.cc.
1122 Object* CallIC_Miss(Arguments args); 1118 Object* CallIC_Miss(Arguments args);
1123 1119
1124 // The generated code does not accept smi keys. 1120 // The generated code does not accept smi keys.
1125 // The generated code falls through if both probes miss. 1121 // The generated code falls through if both probes miss.
1126 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, 1122 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
1127 int argc, 1123 int argc,
1128 Code::Kind kind, 1124 Code::Kind kind) {
1129 Label* miss) {
1130 // ----------- S t a t e ------------- 1125 // ----------- S t a t e -------------
1131 // -- ecx : name 1126 // -- ecx : name
1132 // -- edx : receiver 1127 // -- edx : receiver
1133 // ----------------------------------- 1128 // -----------------------------------
1134 Label number, non_number, non_string, boolean, probe; 1129 Label number, non_number, non_string, boolean, probe, miss;
1135 1130
1136 // Probe the stub cache. 1131 // Probe the stub cache.
1137 Code::Flags flags = 1132 Code::Flags flags =
1138 Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); 1133 Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
1139 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax); 1134 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax);
1140 1135
1141 // If the stub cache probing failed, the receiver might be a value. 1136 // If the stub cache probing failed, the receiver might be a value.
1142 // For value objects, we use the map of the prototype objects for 1137 // For value objects, we use the map of the prototype objects for
1143 // the corresponding JSValue for the cache and that is what we need 1138 // the corresponding JSValue for the cache and that is what we need
1144 // to probe. 1139 // to probe.
(...skipping 14 matching lines...) Expand all
1159 __ j(above_equal, &non_string, taken); 1154 __ j(above_equal, &non_string, taken);
1160 StubCompiler::GenerateLoadGlobalFunctionPrototype( 1155 StubCompiler::GenerateLoadGlobalFunctionPrototype(
1161 masm, Context::STRING_FUNCTION_INDEX, edx); 1156 masm, Context::STRING_FUNCTION_INDEX, edx);
1162 __ jmp(&probe); 1157 __ jmp(&probe);
1163 1158
1164 // Check for boolean. 1159 // Check for boolean.
1165 __ bind(&non_string); 1160 __ bind(&non_string);
1166 __ cmp(edx, Factory::true_value()); 1161 __ cmp(edx, Factory::true_value());
1167 __ j(equal, &boolean, not_taken); 1162 __ j(equal, &boolean, not_taken);
1168 __ cmp(edx, Factory::false_value()); 1163 __ cmp(edx, Factory::false_value());
1169 __ j(not_equal, miss, taken); 1164 __ j(not_equal, &miss, taken);
1170 __ bind(&boolean); 1165 __ bind(&boolean);
1171 StubCompiler::GenerateLoadGlobalFunctionPrototype( 1166 StubCompiler::GenerateLoadGlobalFunctionPrototype(
1172 masm, Context::BOOLEAN_FUNCTION_INDEX, edx); 1167 masm, Context::BOOLEAN_FUNCTION_INDEX, edx);
1173 1168
1174 // Probe the stub cache for the value object. 1169 // Probe the stub cache for the value object.
1175 __ bind(&probe); 1170 __ bind(&probe);
1176 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg); 1171 StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
1172 __ bind(&miss);
1177 } 1173 }
1178 1174
1179 1175
1180 static void GenerateNormalHelper(MacroAssembler* masm, 1176 static void GenerateNormalHelper(MacroAssembler* masm,
1181 int argc, 1177 int argc,
1182 bool is_global_object, 1178 bool is_global_object,
1183 Label* miss) { 1179 Label* miss) {
1184 // ----------- S t a t e ------------- 1180 // ----------- S t a t e -------------
1185 // -- ecx : name 1181 // -- ecx : name
1186 // -- edx : receiver 1182 // -- edx : receiver
(...skipping 20 matching lines...) Expand all
1207 if (is_global_object) { 1203 if (is_global_object) {
1208 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1204 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1209 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1205 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1210 } 1206 }
1211 1207
1212 // Invoke the function. 1208 // Invoke the function.
1213 ParameterCount actual(argc); 1209 ParameterCount actual(argc);
1214 __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1210 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
1215 } 1211 }
1216 1212
1217 // The generated code never falls through. 1213 // The generated code falls through if the call should be handled by runtime.
1218 static void GenerateCallNormal(MacroAssembler* masm, int argc, Label* miss) { 1214 static void GenerateCallNormal(MacroAssembler* masm, int argc) {
1219 // ----------- S t a t e ------------- 1215 // ----------- S t a t e -------------
1220 // -- ecx : name 1216 // -- ecx : name
1221 // -- esp[0] : return address 1217 // -- esp[0] : return address
1222 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1218 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1223 // -- ... 1219 // -- ...
1224 // -- esp[(argc + 1) * 4] : receiver 1220 // -- esp[(argc + 1) * 4] : receiver
1225 // ----------------------------------- 1221 // -----------------------------------
1226 Label global_object, non_global_object; 1222 Label miss, global_object, non_global_object;
1227 1223
1228 // Get the receiver of the function from the stack; 1 ~ return address. 1224 // Get the receiver of the function from the stack; 1 ~ return address.
1229 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1225 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1230 1226
1231 // Check that the receiver isn't a smi. 1227 // Check that the receiver isn't a smi.
1232 __ test(edx, Immediate(kSmiTagMask)); 1228 __ test(edx, Immediate(kSmiTagMask));
1233 __ j(zero, miss, not_taken); 1229 __ j(zero, &miss, not_taken);
1234 1230
1235 // Check that the receiver is a valid JS object. 1231 // Check that the receiver is a valid JS object.
1236 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); 1232 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
1237 __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset)); 1233 __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceTypeOffset));
1238 __ cmp(eax, FIRST_JS_OBJECT_TYPE); 1234 __ cmp(eax, FIRST_JS_OBJECT_TYPE);
1239 __ j(below, miss, not_taken); 1235 __ j(below, &miss, not_taken);
1240 1236
1241 // If this assert fails, we have to check upper bound too. 1237 // If this assert fails, we have to check upper bound too.
1242 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); 1238 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
1243 1239
1244 // Check for access to global object. 1240 // Check for access to global object.
1245 __ cmp(eax, JS_GLOBAL_OBJECT_TYPE); 1241 __ cmp(eax, JS_GLOBAL_OBJECT_TYPE);
1246 __ j(equal, &global_object); 1242 __ j(equal, &global_object);
1247 __ cmp(eax, JS_BUILTINS_OBJECT_TYPE); 1243 __ cmp(eax, JS_BUILTINS_OBJECT_TYPE);
1248 __ j(not_equal, &non_global_object); 1244 __ j(not_equal, &non_global_object);
1249 1245
1250 // Accessing global object: Load and invoke. 1246 // Accessing global object: Load and invoke.
1251 __ bind(&global_object); 1247 __ bind(&global_object);
1252 // Check that the global object does not require access checks. 1248 // Check that the global object does not require access checks.
1253 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), 1249 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset),
1254 1 << Map::kIsAccessCheckNeeded); 1250 1 << Map::kIsAccessCheckNeeded);
1255 __ j(not_equal, miss, not_taken); 1251 __ j(not_equal, &miss, not_taken);
1256 GenerateNormalHelper(masm, argc, true, miss); 1252 GenerateNormalHelper(masm, argc, true, &miss);
1257 1253
1258 // Accessing non-global object: Check for access to global proxy. 1254 // Accessing non-global object: Check for access to global proxy.
1259 Label global_proxy, invoke; 1255 Label global_proxy, invoke;
1260 __ bind(&non_global_object); 1256 __ bind(&non_global_object);
1261 __ cmp(eax, JS_GLOBAL_PROXY_TYPE); 1257 __ cmp(eax, JS_GLOBAL_PROXY_TYPE);
1262 __ j(equal, &global_proxy, not_taken); 1258 __ j(equal, &global_proxy, not_taken);
1263 // Check that the non-global, non-global-proxy object does not 1259 // Check that the non-global, non-global-proxy object does not
1264 // require access checks. 1260 // require access checks.
1265 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset), 1261 __ test_b(FieldOperand(ebx, Map::kBitFieldOffset),
1266 1 << Map::kIsAccessCheckNeeded); 1262 1 << Map::kIsAccessCheckNeeded);
1267 __ j(not_equal, miss, not_taken); 1263 __ j(not_equal, &miss, not_taken);
1268 __ bind(&invoke); 1264 __ bind(&invoke);
1269 GenerateNormalHelper(masm, argc, false, miss); 1265 GenerateNormalHelper(masm, argc, false, &miss);
1270 1266
1271 // Global object proxy access: Check access rights. 1267 // Global object proxy access: Check access rights.
1272 __ bind(&global_proxy); 1268 __ bind(&global_proxy);
1273 __ CheckAccessGlobalProxy(edx, eax, miss); 1269 __ CheckAccessGlobalProxy(edx, eax, &miss);
1274 __ jmp(&invoke); 1270 __ jmp(&invoke);
1271
1272 __ bind(&miss);
1275 } 1273 }
1276 1274
1277 1275
1278 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { 1276 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
1279 // ----------- S t a t e ------------- 1277 // ----------- S t a t e -------------
1280 // -- ecx : name 1278 // -- ecx : name
1281 // -- esp[0] : return address 1279 // -- esp[0] : return address
1282 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1280 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1283 // -- ... 1281 // -- ...
1284 // -- esp[(argc + 1) * 4] : receiver 1282 // -- esp[(argc + 1) * 4] : receiver
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1330 1328
1331 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 1329 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
1332 // ----------- S t a t e ------------- 1330 // ----------- S t a t e -------------
1333 // -- ecx : name 1331 // -- ecx : name
1334 // -- esp[0] : return address 1332 // -- esp[0] : return address
1335 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1333 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1336 // -- ... 1334 // -- ...
1337 // -- esp[(argc + 1) * 4] : receiver 1335 // -- esp[(argc + 1) * 4] : receiver
1338 // ----------------------------------- 1336 // -----------------------------------
1339 1337
1340 Label miss;
1341 // Get the receiver of the function from the stack; 1 ~ return address. 1338 // Get the receiver of the function from the stack; 1 ~ return address.
1342 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1339 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1343 GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, &miss); 1340 GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC);
1344 __ bind(&miss);
1345 GenerateMiss(masm, argc); 1341 GenerateMiss(masm, argc);
1346 } 1342 }
1347 1343
1348 1344
1349 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { 1345 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
1350 Label miss; 1346 // ----------- S t a t e -------------
1351 GenerateCallNormal(masm, argc, &miss); 1347 // -- ecx : name
1352 __ bind(&miss); 1348 // -- esp[0] : return address
1349 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1350 // -- ...
1351 // -- esp[(argc + 1) * 4] : receiver
1352 // -----------------------------------
1353
1354 GenerateCallNormal(masm, argc);
1353 GenerateMiss(masm, argc); 1355 GenerateMiss(masm, argc);
1354 } 1356 }
1355 1357
1356 1358
1357 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { 1359 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
1360 // ----------- S t a t e -------------
1361 // -- ecx : name
1362 // -- esp[0] : return address
1363 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1364 // -- ...
1365 // -- esp[(argc + 1) * 4] : receiver
1366 // -----------------------------------
1367
1358 GenerateCallMiss(masm, argc, IC::kCallIC_Miss); 1368 GenerateCallMiss(masm, argc, IC::kCallIC_Miss);
1359 } 1369 }
1360 1370
1361 1371
1362 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { 1372 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
1363 // ----------- S t a t e ------------- 1373 // ----------- S t a t e -------------
1364 // -- ecx : name 1374 // -- ecx : name
1365 // -- esp[0] : return address 1375 // -- esp[0] : return address
1366 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 1376 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1367 // -- ... 1377 // -- ...
(...skipping 10 matching lines...) Expand all
1378 // Check that the key is a smi. 1388 // Check that the key is a smi.
1379 __ test(ecx, Immediate(kSmiTagMask)); 1389 __ test(ecx, Immediate(kSmiTagMask));
1380 __ j(not_zero, &check_string, not_taken); 1390 __ j(not_zero, &check_string, not_taken);
1381 1391
1382 __ bind(&index_smi); 1392 __ bind(&index_smi);
1383 // Now the key is known to be a smi. This place is also jumped to from 1393 // Now the key is known to be a smi. This place is also jumped to from
1384 // where a numeric string is converted to a smi. 1394 // where a numeric string is converted to a smi.
1385 1395
1386 GenerateKeyedLoadReceiverCheck(masm, edx, eax, &slow_call); 1396 GenerateKeyedLoadReceiverCheck(masm, edx, eax, &slow_call);
1387 1397
1388 GenerateFastArrayLoad(masm, 1398 GenerateFastArrayLoad(
1389 edx, 1399 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load);
1390 ecx,
1391 eax,
1392 edi,
1393 &check_number_dictionary,
1394 &slow_load);
1395 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1); 1400 __ IncrementCounter(&Counters::keyed_call_generic_smi_fast, 1);
1396 1401
1397 __ bind(&do_call); 1402 __ bind(&do_call);
1398 // receiver in edx is not used after this point. 1403 // receiver in edx is not used after this point.
1399 // ecx: key 1404 // ecx: key
1400 // edi: function 1405 // edi: function
1401 1406
1402 // Check that the value in edi is a JavaScript function. 1407 // Check that the value in edi is a JavaScript function.
1403 __ test(edi, Immediate(kSmiTagMask)); 1408 __ test(edi, Immediate(kSmiTagMask));
1404 __ j(zero, &slow_call, not_taken); 1409 __ j(zero, &slow_call, not_taken);
1405 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); 1410 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax);
1406 __ j(not_equal, &slow_call, not_taken); 1411 __ j(not_equal, &slow_call, not_taken);
1407 // Invoke the function. 1412 // Invoke the function.
1408 ParameterCount actual(argc); 1413 ParameterCount actual(argc);
1409 __ InvokeFunction(edi, actual, JUMP_FUNCTION); 1414 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
1410 1415
1411 __ bind(&check_number_dictionary); 1416 __ bind(&check_number_dictionary);
1412 // eax: elements 1417 // eax: elements
1413 // ecx: smi key 1418 // ecx: smi key
1414 // Check whether the elements is a number dictionary. 1419 // Check whether the elements is a number dictionary.
1415 __ CheckMap(eax, Factory::hash_table_map(), &slow_load, true); 1420 __ CheckMap(eax, Factory::hash_table_map(), &slow_load, true);
1416 __ mov(ebx, ecx); 1421 __ mov(ebx, ecx);
1417 __ SmiUntag(ebx); 1422 __ SmiUntag(ebx);
1418 // ebx: untagged index 1423 // ebx: untagged index
1419 // Receiver in edx will be clobbered, need to reload it on miss. 1424 // Receiver in edx will be clobbered, need to reload it on miss.
1420 GenerateNumberDictionaryLoad(masm, 1425 GenerateNumberDictionaryLoad(
1421 &slow_reload_receiver, 1426 masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi);
1422 eax,
1423 ecx,
1424 ebx,
1425 edx,
1426 edi,
1427 edi);
1428 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1); 1427 __ IncrementCounter(&Counters::keyed_call_generic_smi_dict, 1);
1429 __ jmp(&do_call); 1428 __ jmp(&do_call);
1430 1429
1431 __ bind(&slow_reload_receiver); 1430 __ bind(&slow_reload_receiver);
1432 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1431 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1433 1432
1434 __ bind(&slow_load); 1433 __ bind(&slow_load);
1435 // This branch is taken when calling KeyedCallIC_Miss is neither required 1434 // This branch is taken when calling KeyedCallIC_Miss is neither required
1436 // nor beneficial. 1435 // nor beneficial.
1437 __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1); 1436 __ IncrementCounter(&Counters::keyed_call_generic_slow_load, 1);
(...skipping 14 matching lines...) Expand all
1452 // If the receiver is a regular JS object with slow properties then do 1451 // If the receiver is a regular JS object with slow properties then do
1453 // a quick inline probe of the receiver's dictionary. 1452 // a quick inline probe of the receiver's dictionary.
1454 // Otherwise do the monomorphic cache probe. 1453 // Otherwise do the monomorphic cache probe.
1455 GenerateKeyedLoadReceiverCheck(masm, edx, eax, &lookup_monomorphic_cache); 1454 GenerateKeyedLoadReceiverCheck(masm, edx, eax, &lookup_monomorphic_cache);
1456 1455
1457 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 1456 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset));
1458 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 1457 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
1459 Immediate(Factory::hash_table_map())); 1458 Immediate(Factory::hash_table_map()));
1460 __ j(not_equal, &lookup_monomorphic_cache, not_taken); 1459 __ j(not_equal, &lookup_monomorphic_cache, not_taken);
1461 1460
1462 GenerateDictionaryLoad(masm, 1461 GenerateDictionaryLoad(
1463 &slow_load, 1462 masm, &slow_load, edx, ecx, ebx, eax, edi, edi, DICTIONARY_CHECK_DONE);
1464 edx,
1465 ecx,
1466 ebx,
1467 eax,
1468 edi,
1469 edi,
1470 DICTIONARY_CHECK_DONE);
1471 __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1); 1463 __ IncrementCounter(&Counters::keyed_call_generic_lookup_dict, 1);
1472 __ jmp(&do_call); 1464 __ jmp(&do_call);
1473 1465
1474 __ bind(&lookup_monomorphic_cache); 1466 __ bind(&lookup_monomorphic_cache);
1475 __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1); 1467 __ IncrementCounter(&Counters::keyed_call_generic_lookup_cache, 1);
1476 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC, &slow_call); 1468 GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC);
1477 // Fall through on miss. 1469 // Fall through on miss.
1478 1470
1479 __ bind(&slow_call); 1471 __ bind(&slow_call);
1480 // This branch is taken if: 1472 // This branch is taken if:
1481 // - the receiver requires boxing or access check, 1473 // - the receiver requires boxing or access check,
1482 // - the key is neither smi nor symbol, 1474 // - the key is neither smi nor symbol,
1483 // - the value loaded is not a function, 1475 // - the value loaded is not a function,
1484 // - there is hope that the runtime will create a monomorphic call stub 1476 // - there is hope that the runtime will create a monomorphic call stub
1485 // that will get fetched next time. 1477 // that will get fetched next time.
1486 __ IncrementCounter(&Counters::keyed_call_generic_slow, 1); 1478 __ IncrementCounter(&Counters::keyed_call_generic_slow, 1);
1487 GenerateMiss(masm, argc); 1479 GenerateMiss(masm, argc);
1488 1480
1489 __ bind(&index_string); 1481 __ bind(&index_string);
1490 GenerateIndexFromHash(masm, ecx, ebx, &index_smi); 1482 GenerateIndexFromHash(masm, ecx, ebx);
1483 // Now jump to the place where smi keys are handled.
1484 __ jmp(&index_smi);
1491 } 1485 }
1492 1486
1493 1487
1494 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { 1488 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) {
1495 Label miss; 1489 // ----------- S t a t e -------------
1496 GenerateCallNormal(masm, argc, &miss); 1490 // -- ecx : name
1497 __ bind(&miss); 1491 // -- esp[0] : return address
1492 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1493 // -- ...
1494 // -- esp[(argc + 1) * 4] : receiver
1495 // -----------------------------------
1496
1497 GenerateCallNormal(masm, argc);
1498 GenerateMiss(masm, argc); 1498 GenerateMiss(masm, argc);
1499 } 1499 }
1500 1500
1501 1501
1502 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { 1502 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
1503 // ----------- S t a t e -------------
1504 // -- ecx : name
1505 // -- esp[0] : return address
1506 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
1507 // -- ...
1508 // -- esp[(argc + 1) * 4] : receiver
1509 // -----------------------------------
1510
1503 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); 1511 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss);
1504 } 1512 }
1505 1513
1506 1514
1507 // Defined in ic.cc. 1515 // Defined in ic.cc.
1508 Object* LoadIC_Miss(Arguments args); 1516 Object* LoadIC_Miss(Arguments args);
1509 1517
1510 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 1518 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
1511 // ----------- S t a t e ------------- 1519 // ----------- S t a t e -------------
1512 // -- eax : receiver 1520 // -- eax : receiver
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
1861 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); 1869 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss));
1862 __ TailCallExternalReference(ref, 3, 1); 1870 __ TailCallExternalReference(ref, 3, 1);
1863 } 1871 }
1864 1872
1865 #undef __ 1873 #undef __
1866 1874
1867 1875
1868 } } // namespace v8::internal 1876 } } // namespace v8::internal
1869 1877
1870 #endif // V8_TARGET_ARCH_IA32 1878 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/arm/virtual-frame-arm.cc ('k') | src/x64/codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698