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

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

Issue 338963003: KeyedLoadIC should have same register spec as LoadIC. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: A bit more refactoring. Created 6 years, 5 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
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_IA32 7 #if V8_TARGET_ARCH_IA32
8 8
9 #include "src/codegen.h" 9 #include "src/codegen.h"
10 #include "src/ic-inl.h" 10 #include "src/ic-inl.h"
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 __ cmp(key, scratch); 376 __ cmp(key, scratch);
377 __ j(greater_equal, slow_case); 377 __ j(greater_equal, slow_case);
378 return FieldOperand(backing_store, 378 return FieldOperand(backing_store,
379 key, 379 key,
380 times_half_pointer_size, 380 times_half_pointer_size,
381 FixedArray::kHeaderSize); 381 FixedArray::kHeaderSize);
382 } 382 }
383 383
384 384
385 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 385 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
386 // ----------- S t a t e ------------- 386 // The return address is on the stack.
387 // -- ecx : key
388 // -- edx : receiver
389 // -- esp[0] : return address
390 // -----------------------------------
391 ASSERT(edx.is(ReceiverRegister()));
392 ASSERT(ecx.is(NameRegister()));
393 Label slow, check_name, index_smi, index_name, property_array_property; 387 Label slow, check_name, index_smi, index_name, property_array_property;
394 Label probe_dictionary, check_number_dictionary; 388 Label probe_dictionary, check_number_dictionary;
395 389
390 Register receiver = ReceiverRegister();
391 Register key = NameRegister();
392 ASSERT(receiver.is(edx));
393 ASSERT(key.is(ecx));
394
396 // Check that the key is a smi. 395 // Check that the key is a smi.
397 __ JumpIfNotSmi(ecx, &check_name); 396 __ JumpIfNotSmi(key, &check_name);
398 __ bind(&index_smi); 397 __ bind(&index_smi);
399 // Now the key is known to be a smi. This place is also jumped to from 398 // Now the key is known to be a smi. This place is also jumped to from
400 // where a numeric string is converted to a smi. 399 // where a numeric string is converted to a smi.
401 400
402 GenerateKeyedLoadReceiverCheck( 401 GenerateKeyedLoadReceiverCheck(
403 masm, edx, eax, Map::kHasIndexedInterceptor, &slow); 402 masm, receiver, eax, Map::kHasIndexedInterceptor, &slow);
404 403
405 // Check the receiver's map to see if it has fast elements. 404 // Check the receiver's map to see if it has fast elements.
406 __ CheckFastElements(eax, &check_number_dictionary); 405 __ CheckFastElements(eax, &check_number_dictionary);
407 406
408 GenerateFastArrayLoad(masm, edx, ecx, eax, eax, NULL, &slow); 407 GenerateFastArrayLoad(masm, receiver, key, eax, eax, NULL, &slow);
409 Isolate* isolate = masm->isolate(); 408 Isolate* isolate = masm->isolate();
410 Counters* counters = isolate->counters(); 409 Counters* counters = isolate->counters();
411 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); 410 __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
412 __ ret(0); 411 __ ret(0);
413 412
414 __ bind(&check_number_dictionary); 413 __ bind(&check_number_dictionary);
415 __ mov(ebx, ecx); 414 __ mov(ebx, key);
416 __ SmiUntag(ebx); 415 __ SmiUntag(ebx);
417 __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset)); 416 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset));
418 417
419 // Check whether the elements is a number dictionary. 418 // Check whether the elements is a number dictionary.
420 // edx: receiver 419 // receiver: receiver
421 // ebx: untagged index 420 // ebx: untagged index
422 // ecx: key 421 // key: key
423 // eax: elements 422 // eax: elements
424 __ CheckMap(eax, 423 __ CheckMap(eax,
425 isolate->factory()->hash_table_map(), 424 isolate->factory()->hash_table_map(),
426 &slow, 425 &slow,
427 DONT_DO_SMI_CHECK); 426 DONT_DO_SMI_CHECK);
428 Label slow_pop_receiver; 427 Label slow_pop_receiver;
429 // Push receiver on the stack to free up a register for the dictionary 428 // Push receiver on the stack to free up a register for the dictionary
430 // probing. 429 // probing.
431 __ push(edx); 430 __ push(receiver);
432 __ LoadFromNumberDictionary(&slow_pop_receiver, eax, ecx, ebx, edx, edi, eax); 431 __ LoadFromNumberDictionary(&slow_pop_receiver, eax, key, ebx, edx, edi, eax);
433 // Pop receiver before returning. 432 // Pop receiver before returning.
434 __ pop(edx); 433 __ pop(receiver);
435 __ ret(0); 434 __ ret(0);
436 435
437 __ bind(&slow_pop_receiver); 436 __ bind(&slow_pop_receiver);
438 // Pop the receiver from the stack and jump to runtime. 437 // Pop the receiver from the stack and jump to runtime.
439 __ pop(edx); 438 __ pop(receiver);
440 439
441 __ bind(&slow); 440 __ bind(&slow);
442 // Slow case: jump to runtime. 441 // Slow case: jump to runtime.
443 // edx: receiver 442 // receiver: receiver
444 // ecx: key 443 // key: key
445 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); 444 __ IncrementCounter(counters->keyed_load_generic_slow(), 1);
446 GenerateRuntimeGetProperty(masm); 445 GenerateRuntimeGetProperty(masm);
447 446
448 __ bind(&check_name); 447 __ bind(&check_name);
449 GenerateKeyNameCheck(masm, ecx, eax, ebx, &index_name, &slow); 448 GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow);
450 449
451 GenerateKeyedLoadReceiverCheck( 450 GenerateKeyedLoadReceiverCheck(
452 masm, edx, eax, Map::kHasNamedInterceptor, &slow); 451 masm, receiver, eax, Map::kHasNamedInterceptor, &slow);
453 452
454 // If the receiver is a fast-case object, check the keyed lookup 453 // If the receiver is a fast-case object, check the keyed lookup
455 // cache. Otherwise probe the dictionary. 454 // cache. Otherwise probe the dictionary.
456 __ mov(ebx, FieldOperand(edx, JSObject::kPropertiesOffset)); 455 __ mov(ebx, FieldOperand(receiver, JSObject::kPropertiesOffset));
457 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 456 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
458 Immediate(isolate->factory()->hash_table_map())); 457 Immediate(isolate->factory()->hash_table_map()));
459 __ j(equal, &probe_dictionary); 458 __ j(equal, &probe_dictionary);
460 459
461 // The receiver's map is still in eax, compute the keyed lookup cache hash 460 // The receiver's map is still in eax, compute the keyed lookup cache hash
462 // based on 32 bits of the map pointer and the string hash. 461 // based on 32 bits of the map pointer and the string hash.
463 if (FLAG_debug_code) { 462 if (FLAG_debug_code) {
464 __ cmp(eax, FieldOperand(edx, HeapObject::kMapOffset)); 463 __ cmp(eax, FieldOperand(receiver, HeapObject::kMapOffset));
465 __ Check(equal, kMapIsNoLongerInEax); 464 __ Check(equal, kMapIsNoLongerInEax);
466 } 465 }
467 __ mov(ebx, eax); // Keep the map around for later. 466 __ mov(ebx, eax); // Keep the map around for later.
468 __ shr(eax, KeyedLookupCache::kMapHashShift); 467 __ shr(eax, KeyedLookupCache::kMapHashShift);
469 __ mov(edi, FieldOperand(ecx, String::kHashFieldOffset)); 468 __ mov(edi, FieldOperand(key, String::kHashFieldOffset));
470 __ shr(edi, String::kHashShift); 469 __ shr(edi, String::kHashShift);
471 __ xor_(eax, edi); 470 __ xor_(eax, edi);
472 __ and_(eax, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); 471 __ and_(eax, KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
473 472
474 // Load the key (consisting of map and internalized string) from the cache and 473 // Load the key (consisting of map and internalized string) from the cache and
475 // check for match. 474 // check for match.
476 Label load_in_object_property; 475 Label load_in_object_property;
477 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; 476 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
478 Label hit_on_nth_entry[kEntriesPerBucket]; 477 Label hit_on_nth_entry[kEntriesPerBucket];
479 ExternalReference cache_keys = 478 ExternalReference cache_keys =
480 ExternalReference::keyed_lookup_cache_keys(masm->isolate()); 479 ExternalReference::keyed_lookup_cache_keys(masm->isolate());
481 480
482 for (int i = 0; i < kEntriesPerBucket - 1; i++) { 481 for (int i = 0; i < kEntriesPerBucket - 1; i++) {
483 Label try_next_entry; 482 Label try_next_entry;
484 __ mov(edi, eax); 483 __ mov(edi, eax);
485 __ shl(edi, kPointerSizeLog2 + 1); 484 __ shl(edi, kPointerSizeLog2 + 1);
486 if (i != 0) { 485 if (i != 0) {
487 __ add(edi, Immediate(kPointerSize * i * 2)); 486 __ add(edi, Immediate(kPointerSize * i * 2));
488 } 487 }
489 __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); 488 __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
490 __ j(not_equal, &try_next_entry); 489 __ j(not_equal, &try_next_entry);
491 __ add(edi, Immediate(kPointerSize)); 490 __ add(edi, Immediate(kPointerSize));
492 __ cmp(ecx, Operand::StaticArray(edi, times_1, cache_keys)); 491 __ cmp(key, Operand::StaticArray(edi, times_1, cache_keys));
493 __ j(equal, &hit_on_nth_entry[i]); 492 __ j(equal, &hit_on_nth_entry[i]);
494 __ bind(&try_next_entry); 493 __ bind(&try_next_entry);
495 } 494 }
496 495
497 __ lea(edi, Operand(eax, 1)); 496 __ lea(edi, Operand(eax, 1));
498 __ shl(edi, kPointerSizeLog2 + 1); 497 __ shl(edi, kPointerSizeLog2 + 1);
499 __ add(edi, Immediate(kPointerSize * (kEntriesPerBucket - 1) * 2)); 498 __ add(edi, Immediate(kPointerSize * (kEntriesPerBucket - 1) * 2));
500 __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); 499 __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
501 __ j(not_equal, &slow); 500 __ j(not_equal, &slow);
502 __ add(edi, Immediate(kPointerSize)); 501 __ add(edi, Immediate(kPointerSize));
503 __ cmp(ecx, Operand::StaticArray(edi, times_1, cache_keys)); 502 __ cmp(key, Operand::StaticArray(edi, times_1, cache_keys));
504 __ j(not_equal, &slow); 503 __ j(not_equal, &slow);
505 504
506 // Get field offset. 505 // Get field offset.
507 // edx : receiver 506 // receiver : receiver
508 // ebx : receiver's map 507 // ebx : receiver's map
509 // ecx : key 508 // key : key
510 // eax : lookup cache index 509 // eax : lookup cache index
511 ExternalReference cache_field_offsets = 510 ExternalReference cache_field_offsets =
512 ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate()); 511 ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
513 512
514 // Hit on nth entry. 513 // Hit on nth entry.
515 for (int i = kEntriesPerBucket - 1; i >= 0; i--) { 514 for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
516 __ bind(&hit_on_nth_entry[i]); 515 __ bind(&hit_on_nth_entry[i]);
517 if (i != 0) { 516 if (i != 0) {
518 __ add(eax, Immediate(i)); 517 __ add(eax, Immediate(i));
519 } 518 }
520 __ mov(edi, 519 __ mov(edi,
521 Operand::StaticArray(eax, times_pointer_size, cache_field_offsets)); 520 Operand::StaticArray(eax, times_pointer_size, cache_field_offsets));
522 __ movzx_b(eax, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); 521 __ movzx_b(eax, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
523 __ sub(edi, eax); 522 __ sub(edi, eax);
524 __ j(above_equal, &property_array_property); 523 __ j(above_equal, &property_array_property);
525 if (i != 0) { 524 if (i != 0) {
526 __ jmp(&load_in_object_property); 525 __ jmp(&load_in_object_property);
527 } 526 }
528 } 527 }
529 528
530 // Load in-object property. 529 // Load in-object property.
531 __ bind(&load_in_object_property); 530 __ bind(&load_in_object_property);
532 __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceSizeOffset)); 531 __ movzx_b(eax, FieldOperand(ebx, Map::kInstanceSizeOffset));
533 __ add(eax, edi); 532 __ add(eax, edi);
534 __ mov(eax, FieldOperand(edx, eax, times_pointer_size, 0)); 533 __ mov(eax, FieldOperand(receiver, eax, times_pointer_size, 0));
535 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); 534 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
536 __ ret(0); 535 __ ret(0);
537 536
538 // Load property array property. 537 // Load property array property.
539 __ bind(&property_array_property); 538 __ bind(&property_array_property);
540 __ mov(eax, FieldOperand(edx, JSObject::kPropertiesOffset)); 539 __ mov(eax, FieldOperand(receiver, JSObject::kPropertiesOffset));
541 __ mov(eax, FieldOperand(eax, edi, times_pointer_size, 540 __ mov(eax, FieldOperand(eax, edi, times_pointer_size,
542 FixedArray::kHeaderSize)); 541 FixedArray::kHeaderSize));
543 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); 542 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
544 __ ret(0); 543 __ ret(0);
545 544
546 // Do a quick inline probe of the receiver's dictionary, if it 545 // Do a quick inline probe of the receiver's dictionary, if it
547 // exists. 546 // exists.
548 __ bind(&probe_dictionary); 547 __ bind(&probe_dictionary);
549 548
550 __ mov(eax, FieldOperand(edx, JSObject::kMapOffset)); 549 __ mov(eax, FieldOperand(receiver, JSObject::kMapOffset));
551 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); 550 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
552 GenerateGlobalInstanceTypeCheck(masm, eax, &slow); 551 GenerateGlobalInstanceTypeCheck(masm, eax, &slow);
553 552
554 GenerateDictionaryLoad(masm, &slow, ebx, ecx, eax, edi, eax); 553 GenerateDictionaryLoad(masm, &slow, ebx, key, eax, edi, eax);
555 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1); 554 __ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
556 __ ret(0); 555 __ ret(0);
557 556
558 __ bind(&index_name); 557 __ bind(&index_name);
559 __ IndexFromHash(ebx, ecx); 558 __ IndexFromHash(ebx, key);
560 // Now jump to the place where smi keys are handled. 559 // Now jump to the place where smi keys are handled.
561 __ jmp(&index_smi); 560 __ jmp(&index_smi);
562 } 561 }
563 562
564 563
565 // A register that isn't one of the parameters to the load ic. 564 // A register that isn't one of the parameters to the load ic.
566 static const Register LoadIC_TempRegister() { return ebx; } 565 static const Register LoadIC_TempRegister() { return ebx; }
567 566
568 567
569 // A register that isn't one of the parameters to the load ic. 568 // A register that isn't one of the parameters to the load ic.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), 637 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor),
639 masm->isolate()); 638 masm->isolate());
640 __ TailCallExternalReference(ref, 2, 1); 639 __ TailCallExternalReference(ref, 2, 1);
641 640
642 __ bind(&slow); 641 __ bind(&slow);
643 GenerateMiss(masm); 642 GenerateMiss(masm);
644 } 643 }
645 644
646 645
647 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { 646 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
648 // ----------- S t a t e ------------- 647 // The return address is on the stack.
649 // -- ecx : key 648 Register receiver = ReceiverRegister();
650 // -- edx : receiver 649 Register key = NameRegister();
651 // -- esp[0] : return address 650 ASSERT(receiver.is(edx));
652 // ----------------------------------- 651 ASSERT(key.is(ecx));
653 ASSERT(edx.is(ReceiverRegister())); 652
654 ASSERT(ecx.is(NameRegister()));
655 Label slow, notin; 653 Label slow, notin;
656 Factory* factory = masm->isolate()->factory(); 654 Factory* factory = masm->isolate()->factory();
657 Operand mapped_location = 655 Operand mapped_location =
658 GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, eax, &notin, &slow); 656 GenerateMappedArgumentsLookup(
657 masm, receiver, key, ebx, eax, &notin, &slow);
659 __ mov(eax, mapped_location); 658 __ mov(eax, mapped_location);
660 __ Ret(); 659 __ Ret();
661 __ bind(&notin); 660 __ bind(&notin);
662 // The unmapped lookup expects that the parameter map is in ebx. 661 // The unmapped lookup expects that the parameter map is in ebx.
663 Operand unmapped_location = 662 Operand unmapped_location =
664 GenerateUnmappedArgumentsLookup(masm, ecx, ebx, eax, &slow); 663 GenerateUnmappedArgumentsLookup(masm, key, ebx, eax, &slow);
665 __ cmp(unmapped_location, factory->the_hole_value()); 664 __ cmp(unmapped_location, factory->the_hole_value());
666 __ j(equal, &slow); 665 __ j(equal, &slow);
667 __ mov(eax, unmapped_location); 666 __ mov(eax, unmapped_location);
668 __ Ret(); 667 __ Ret();
669 __ bind(&slow); 668 __ bind(&slow);
670 GenerateMiss(masm); 669 GenerateMiss(masm);
671 } 670 }
672 671
673 672
674 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { 673 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); 1024 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
1026 __ TailCallExternalReference(ref, 2, 1); 1025 __ TailCallExternalReference(ref, 2, 1);
1027 } 1026 }
1028 1027
1029 1028
1030 // IC register specifications 1029 // IC register specifications
1031 const Register LoadIC::ReceiverRegister() { return edx; } 1030 const Register LoadIC::ReceiverRegister() { return edx; }
1032 const Register LoadIC::NameRegister() { return ecx; } 1031 const Register LoadIC::NameRegister() { return ecx; }
1033 1032
1034 1033
1035 const Register KeyedLoadIC::ReceiverRegister() {
1036 return LoadIC::ReceiverRegister();
1037 }
1038
1039
1040 const Register KeyedLoadIC::NameRegister() { return LoadIC::NameRegister(); }
1041
1042
1043 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 1034 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
1044 // Return address is on the stack. 1035 // Return address is on the stack.
1045 __ pop(KeyedLoadIC_TempRegister()); 1036 __ pop(KeyedLoadIC_TempRegister());
1046 __ push(ReceiverRegister()); // receiver 1037 __ push(ReceiverRegister()); // receiver
1047 __ push(NameRegister()); // name 1038 __ push(NameRegister()); // name
1048 __ push(KeyedLoadIC_TempRegister()); // return address 1039 __ push(KeyedLoadIC_TempRegister()); // return address
1049 1040
1050 // Perform tail call to the entry. 1041 // Perform tail call to the entry.
1051 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 1042 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
1052 } 1043 }
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1291 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) 1282 Condition cc = (check == ENABLE_INLINED_SMI_CHECK)
1292 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) 1283 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
1293 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); 1284 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
1294 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1285 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1295 } 1286 }
1296 1287
1297 1288
1298 } } // namespace v8::internal 1289 } } // namespace v8::internal
1299 1290
1300 #endif // V8_TARGET_ARCH_IA32 1291 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698