OLD | NEW |
---|---|
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_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/arm/assembler-arm.h" | 9 #include "src/arm/assembler-arm.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
307 __ b(ne, not_unique); | 307 __ b(ne, not_unique); |
308 | 308 |
309 __ bind(&unique); | 309 __ bind(&unique); |
310 } | 310 } |
311 | 311 |
312 | 312 |
313 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 313 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
314 // ----------- S t a t e ------------- | 314 // ----------- S t a t e ------------- |
315 // -- r2 : name | 315 // -- r2 : name |
316 // -- lr : return address | 316 // -- lr : return address |
317 // -- r0 : receiver | 317 // -- r1 : receiver |
Jakob Kummerow
2014/06/30 14:12:45
Why doesn't this get the same treatment as e.g. Ke
mvstanton
2014/06/30 14:58:59
Yep, I can do that.
| |
318 // ----------------------------------- | 318 // ----------------------------------- |
319 ASSERT(r0.is(ReceiverRegister())); | 319 ASSERT(r1.is(ReceiverRegister())); |
320 ASSERT(r2.is(NameRegister())); | 320 ASSERT(r2.is(NameRegister())); |
321 | 321 |
322 // Probe the stub cache. | 322 // Probe the stub cache. |
323 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 323 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
324 masm->isolate()->stub_cache()->GenerateProbe( | 324 masm->isolate()->stub_cache()->GenerateProbe( |
325 masm, flags, r0, r2, r3, r4, r5, r6); | 325 masm, flags, r1, r2, r3, r4, r5, r6); |
326 | 326 |
327 // Cache miss: Jump to runtime. | 327 // Cache miss: Jump to runtime. |
328 GenerateMiss(masm); | 328 GenerateMiss(masm); |
329 } | 329 } |
330 | 330 |
331 | 331 |
332 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 332 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
333 // ----------- S t a t e ------------- | 333 // ----------- S t a t e ------------- |
334 // -- r2 : name | 334 // -- r2 : name |
335 // -- lr : return address | 335 // -- lr : return address |
336 // -- r0 : receiver | 336 // -- r1 : receiver |
337 // ----------------------------------- | 337 // ----------------------------------- |
338 ASSERT(r0.is(ReceiverRegister())); | 338 ASSERT(r1.is(ReceiverRegister())); |
339 ASSERT(r2.is(NameRegister())); | 339 ASSERT(r2.is(NameRegister())); |
340 | 340 |
341 Label miss, slow; | 341 Label miss, slow; |
342 | 342 |
343 GenerateNameDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss); | 343 GenerateNameDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss); |
344 | 344 |
345 // r1: elements | 345 // r0: elements |
346 GenerateDictionaryLoad(masm, &slow, r1, r2, r0, r3, r4); | 346 GenerateDictionaryLoad(masm, &slow, r0, r2, r0, r3, r4); |
347 __ Ret(); | 347 __ Ret(); |
348 | 348 |
349 // Dictionary load failed, go slow (but don't miss). | 349 // Dictionary load failed, go slow (but don't miss). |
350 __ bind(&slow); | 350 __ bind(&slow); |
351 GenerateRuntimeGetProperty(masm); | 351 GenerateRuntimeGetProperty(masm); |
352 | 352 |
353 // Cache miss: Jump to runtime. | 353 // Cache miss: Jump to runtime. |
354 __ bind(&miss); | 354 __ bind(&miss); |
355 GenerateMiss(masm); | 355 GenerateMiss(masm); |
356 } | 356 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
465 __ mov(scratch, Operand(kPointerSize >> 1)); | 465 __ mov(scratch, Operand(kPointerSize >> 1)); |
466 __ mul(scratch, key, scratch); | 466 __ mul(scratch, key, scratch); |
467 __ add(scratch, | 467 __ add(scratch, |
468 scratch, | 468 scratch, |
469 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 469 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
470 return MemOperand(backing_store, scratch); | 470 return MemOperand(backing_store, scratch); |
471 } | 471 } |
472 | 472 |
473 | 473 |
474 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { | 474 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { |
475 // ---------- S t a t e -------------- | 475 // The return address is on the stack. |
Jakob Kummerow
2014/06/30 14:12:45
actually, it's in |lr|
mvstanton
2014/06/30 14:58:59
Done.
| |
476 // -- lr : return address | 476 Register receiver = ReceiverRegister(); |
477 // -- r0 : key | 477 Register key = NameRegister(); |
478 // -- r1 : receiver | 478 ASSERT(receiver.is(r1)); |
479 // ----------------------------------- | 479 ASSERT(key.is(r2)); |
480 ASSERT(r1.is(ReceiverRegister())); | 480 |
481 ASSERT(r0.is(NameRegister())); | |
482 Label slow, notin; | 481 Label slow, notin; |
483 MemOperand mapped_location = | 482 MemOperand mapped_location = |
484 GenerateMappedArgumentsLookup(masm, r1, r0, r2, r3, r4, ¬in, &slow); | 483 GenerateMappedArgumentsLookup( |
484 masm, receiver, key, r0, r3, r4, ¬in, &slow); | |
485 __ ldr(r0, mapped_location); | 485 __ ldr(r0, mapped_location); |
486 __ Ret(); | 486 __ Ret(); |
487 __ bind(¬in); | 487 __ bind(¬in); |
488 // The unmapped lookup expects that the parameter map is in r2. | 488 // The unmapped lookup expects that the parameter map is in r0. |
489 MemOperand unmapped_location = | 489 MemOperand unmapped_location = |
490 GenerateUnmappedArgumentsLookup(masm, r0, r2, r3, &slow); | 490 GenerateUnmappedArgumentsLookup(masm, key, r0, r3, &slow); |
491 __ ldr(r2, unmapped_location); | 491 __ ldr(r0, unmapped_location); |
492 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); | 492 __ LoadRoot(r3, Heap::kTheHoleValueRootIndex); |
493 __ cmp(r2, r3); | 493 __ cmp(r0, r3); |
494 __ b(eq, &slow); | 494 __ b(eq, &slow); |
495 __ mov(r0, r2); | |
496 __ Ret(); | 495 __ Ret(); |
497 __ bind(&slow); | 496 __ bind(&slow); |
498 GenerateMiss(masm); | 497 GenerateMiss(masm); |
499 } | 498 } |
500 | 499 |
501 | 500 |
502 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { | 501 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { |
503 // ---------- S t a t e -------------- | 502 // ---------- S t a t e -------------- |
504 // -- r0 : value | 503 // -- r0 : value |
505 // -- r1 : key | 504 // -- r1 : key |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
538 | 537 |
539 // Perform tail call to the entry. | 538 // Perform tail call to the entry. |
540 ExternalReference ref = | 539 ExternalReference ref = |
541 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); | 540 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); |
542 | 541 |
543 __ TailCallExternalReference(ref, 2, 1); | 542 __ TailCallExternalReference(ref, 2, 1); |
544 } | 543 } |
545 | 544 |
546 | 545 |
547 // IC register specifications | 546 // IC register specifications |
548 const Register LoadIC::ReceiverRegister() { return r0; } | 547 const Register LoadIC::ReceiverRegister() { return r1; } |
549 const Register LoadIC::NameRegister() { return r2; } | 548 const Register LoadIC::NameRegister() { return r2; } |
550 const Register KeyedLoadIC::ReceiverRegister() { return r1; } | |
551 const Register KeyedLoadIC::NameRegister() { return r0; } | |
552 | 549 |
553 | 550 |
554 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 551 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
555 // The return address is on the stack. | 552 // The return address is on the stack. |
556 | 553 |
557 __ Push(ReceiverRegister(), NameRegister()); | 554 __ Push(ReceiverRegister(), NameRegister()); |
558 | 555 |
559 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 556 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
560 } | 557 } |
561 | 558 |
562 | 559 |
563 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 560 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
564 // ---------- S t a t e -------------- | 561 // The return address is on the stack. |
565 // -- lr : return address | |
566 // -- r0 : key | |
567 // -- r1 : receiver | |
568 // ----------------------------------- | |
569 Label slow, check_name, index_smi, index_name, property_array_property; | 562 Label slow, check_name, index_smi, index_name, property_array_property; |
570 Label probe_dictionary, check_number_dictionary; | 563 Label probe_dictionary, check_number_dictionary; |
571 | 564 |
572 Register key = NameRegister(); | 565 Register key = NameRegister(); |
573 Register receiver = ReceiverRegister(); | 566 Register receiver = ReceiverRegister(); |
574 ASSERT(key.is(r0)); | 567 ASSERT(key.is(r2)); |
575 ASSERT(receiver.is(r1)); | 568 ASSERT(receiver.is(r1)); |
576 | 569 |
577 Isolate* isolate = masm->isolate(); | 570 Isolate* isolate = masm->isolate(); |
578 | 571 |
579 // Check that the key is a smi. | 572 // Check that the key is a smi. |
580 __ JumpIfNotSmi(key, &check_name); | 573 __ JumpIfNotSmi(key, &check_name); |
581 __ bind(&index_smi); | 574 __ bind(&index_smi); |
582 // Now the key is known to be a smi. This place is also jumped to from below | 575 // Now the key is known to be a smi. This place is also jumped to from below |
583 // where a numeric string is converted to a smi. | 576 // where a numeric string is converted to a smi. |
584 | 577 |
585 GenerateKeyedLoadReceiverCheck( | 578 GenerateKeyedLoadReceiverCheck( |
586 masm, receiver, r2, r3, Map::kHasIndexedInterceptor, &slow); | 579 masm, receiver, r0, r3, Map::kHasIndexedInterceptor, &slow); |
587 | 580 |
588 // Check the receiver's map to see if it has fast elements. | 581 // Check the receiver's map to see if it has fast elements. |
589 __ CheckFastElements(r2, r3, &check_number_dictionary); | 582 __ CheckFastElements(r0, r3, &check_number_dictionary); |
590 | 583 |
591 GenerateFastArrayLoad( | 584 GenerateFastArrayLoad( |
592 masm, receiver, key, r4, r3, r2, r0, NULL, &slow); | 585 masm, receiver, key, r0, r3, r4, r0, NULL, &slow); |
593 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r2, r3); | 586 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r4, r3); |
594 __ Ret(); | 587 __ Ret(); |
595 | 588 |
596 __ bind(&check_number_dictionary); | 589 __ bind(&check_number_dictionary); |
597 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 590 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
598 __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset)); | 591 __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset)); |
599 | 592 |
600 // Check whether the elements is a number dictionary. | 593 // Check whether the elements is a number dictionary. |
601 // r0: key | |
602 // r3: elements map | 594 // r3: elements map |
603 // r4: elements | 595 // r4: elements |
604 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | 596 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
605 __ cmp(r3, ip); | 597 __ cmp(r3, ip); |
606 __ b(ne, &slow); | 598 __ b(ne, &slow); |
607 __ SmiUntag(r2, r0); | 599 __ SmiUntag(r0, key); |
608 __ LoadFromNumberDictionary(&slow, r4, r0, r0, r2, r3, r5); | 600 __ LoadFromNumberDictionary(&slow, r4, key, r0, r0, r3, r5); |
609 __ Ret(); | 601 __ Ret(); |
610 | 602 |
611 // Slow case, key and receiver still in r0 and r1. | 603 // Slow case, key and receiver still in r2 and r1. |
612 __ bind(&slow); | 604 __ bind(&slow); |
613 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), | 605 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), |
614 1, r2, r3); | 606 1, r4, r3); |
615 GenerateRuntimeGetProperty(masm); | 607 GenerateRuntimeGetProperty(masm); |
616 | 608 |
617 __ bind(&check_name); | 609 __ bind(&check_name); |
618 GenerateKeyNameCheck(masm, key, r2, r3, &index_name, &slow); | 610 GenerateKeyNameCheck(masm, key, r0, r3, &index_name, &slow); |
619 | 611 |
620 GenerateKeyedLoadReceiverCheck( | 612 GenerateKeyedLoadReceiverCheck( |
621 masm, receiver, r2, r3, Map::kHasNamedInterceptor, &slow); | 613 masm, receiver, r0, r3, Map::kHasNamedInterceptor, &slow); |
622 | 614 |
623 // If the receiver is a fast-case object, check the keyed lookup | 615 // If the receiver is a fast-case object, check the keyed lookup |
624 // cache. Otherwise probe the dictionary. | 616 // cache. Otherwise probe the dictionary. |
625 __ ldr(r3, FieldMemOperand(r1, JSObject::kPropertiesOffset)); | 617 __ ldr(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
626 __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); | 618 __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); |
627 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | 619 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
628 __ cmp(r4, ip); | 620 __ cmp(r4, ip); |
629 __ b(eq, &probe_dictionary); | 621 __ b(eq, &probe_dictionary); |
630 | 622 |
631 // Load the map of the receiver, compute the keyed lookup cache hash | 623 // Load the map of the receiver, compute the keyed lookup cache hash |
632 // based on 32 bits of the map pointer and the name hash. | 624 // based on 32 bits of the map pointer and the name hash. |
633 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 625 __ ldr(r0, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
634 __ mov(r3, Operand(r2, ASR, KeyedLookupCache::kMapHashShift)); | 626 __ mov(r3, Operand(r0, ASR, KeyedLookupCache::kMapHashShift)); |
635 __ ldr(r4, FieldMemOperand(r0, Name::kHashFieldOffset)); | 627 __ ldr(r4, FieldMemOperand(key, Name::kHashFieldOffset)); |
636 __ eor(r3, r3, Operand(r4, ASR, Name::kHashShift)); | 628 __ eor(r3, r3, Operand(r4, ASR, Name::kHashShift)); |
637 int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask; | 629 int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask; |
638 __ And(r3, r3, Operand(mask)); | 630 __ And(r3, r3, Operand(mask)); |
639 | 631 |
640 // Load the key (consisting of map and unique name) from the cache and | 632 // Load the key (consisting of map and unique name) from the cache and |
641 // check for match. | 633 // check for match. |
642 Label load_in_object_property; | 634 Label load_in_object_property; |
643 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; | 635 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; |
644 Label hit_on_nth_entry[kEntriesPerBucket]; | 636 Label hit_on_nth_entry[kEntriesPerBucket]; |
645 ExternalReference cache_keys = | 637 ExternalReference cache_keys = |
646 ExternalReference::keyed_lookup_cache_keys(isolate); | 638 ExternalReference::keyed_lookup_cache_keys(isolate); |
647 | 639 |
648 __ mov(r4, Operand(cache_keys)); | 640 __ mov(r4, Operand(cache_keys)); |
649 __ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1)); | 641 __ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1)); |
650 | 642 |
651 for (int i = 0; i < kEntriesPerBucket - 1; i++) { | 643 for (int i = 0; i < kEntriesPerBucket - 1; i++) { |
652 Label try_next_entry; | 644 Label try_next_entry; |
653 // Load map and move r4 to next entry. | 645 // Load map and move r4 to next entry. |
654 __ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex)); | 646 __ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex)); |
655 __ cmp(r2, r5); | 647 __ cmp(r0, r5); |
656 __ b(ne, &try_next_entry); | 648 __ b(ne, &try_next_entry); |
657 __ ldr(r5, MemOperand(r4, -kPointerSize)); // Load name | 649 __ ldr(r5, MemOperand(r4, -kPointerSize)); // Load name |
658 __ cmp(r0, r5); | 650 __ cmp(key, r5); |
659 __ b(eq, &hit_on_nth_entry[i]); | 651 __ b(eq, &hit_on_nth_entry[i]); |
660 __ bind(&try_next_entry); | 652 __ bind(&try_next_entry); |
661 } | 653 } |
662 | 654 |
663 // Last entry: Load map and move r4 to name. | 655 // Last entry: Load map and move r4 to name. |
664 __ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); | 656 __ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); |
665 __ cmp(r2, r5); | 657 __ cmp(r0, r5); |
666 __ b(ne, &slow); | 658 __ b(ne, &slow); |
667 __ ldr(r5, MemOperand(r4)); | 659 __ ldr(r5, MemOperand(r4)); |
668 __ cmp(r0, r5); | 660 __ cmp(key, r5); |
669 __ b(ne, &slow); | 661 __ b(ne, &slow); |
670 | 662 |
671 // Get field offset. | 663 // Get field offset. |
672 // r0 : key | 664 // r0 : receiver's map |
673 // r1 : receiver | |
674 // r2 : receiver's map | |
675 // r3 : lookup cache index | 665 // r3 : lookup cache index |
676 ExternalReference cache_field_offsets = | 666 ExternalReference cache_field_offsets = |
677 ExternalReference::keyed_lookup_cache_field_offsets(isolate); | 667 ExternalReference::keyed_lookup_cache_field_offsets(isolate); |
678 | 668 |
679 // Hit on nth entry. | 669 // Hit on nth entry. |
680 for (int i = kEntriesPerBucket - 1; i >= 0; i--) { | 670 for (int i = kEntriesPerBucket - 1; i >= 0; i--) { |
681 __ bind(&hit_on_nth_entry[i]); | 671 __ bind(&hit_on_nth_entry[i]); |
682 __ mov(r4, Operand(cache_field_offsets)); | 672 __ mov(r4, Operand(cache_field_offsets)); |
683 if (i != 0) { | 673 if (i != 0) { |
684 __ add(r3, r3, Operand(i)); | 674 __ add(r3, r3, Operand(i)); |
685 } | 675 } |
686 __ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2)); | 676 __ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2)); |
687 __ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset)); | 677 __ ldrb(r6, FieldMemOperand(r0, Map::kInObjectPropertiesOffset)); |
688 __ sub(r5, r5, r6, SetCC); | 678 __ sub(r5, r5, r6, SetCC); |
689 __ b(ge, &property_array_property); | 679 __ b(ge, &property_array_property); |
690 if (i != 0) { | 680 if (i != 0) { |
691 __ jmp(&load_in_object_property); | 681 __ jmp(&load_in_object_property); |
692 } | 682 } |
693 } | 683 } |
694 | 684 |
695 // Load in-object property. | 685 // Load in-object property. |
696 __ bind(&load_in_object_property); | 686 __ bind(&load_in_object_property); |
697 __ ldrb(r6, FieldMemOperand(r2, Map::kInstanceSizeOffset)); | 687 __ ldrb(r6, FieldMemOperand(r0, Map::kInstanceSizeOffset)); |
698 __ add(r6, r6, r5); // Index from start of object. | 688 __ add(r6, r6, r5); // Index from start of object. |
699 __ sub(r1, r1, Operand(kHeapObjectTag)); // Remove the heap tag. | 689 __ sub(receiver, receiver, Operand(kHeapObjectTag)); // Remove the heap tag. |
700 __ ldr(r0, MemOperand(r1, r6, LSL, kPointerSizeLog2)); | 690 __ ldr(r0, MemOperand(receiver, r6, LSL, kPointerSizeLog2)); |
701 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), | 691 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), |
702 1, r2, r3); | 692 1, r4, r3); |
703 __ Ret(); | 693 __ Ret(); |
704 | 694 |
705 // Load property array property. | 695 // Load property array property. |
706 __ bind(&property_array_property); | 696 __ bind(&property_array_property); |
707 __ ldr(r1, FieldMemOperand(r1, JSObject::kPropertiesOffset)); | 697 __ ldr(receiver, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
708 __ add(r1, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 698 __ add(receiver, receiver, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
709 __ ldr(r0, MemOperand(r1, r5, LSL, kPointerSizeLog2)); | 699 __ ldr(r0, MemOperand(receiver, r5, LSL, kPointerSizeLog2)); |
710 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), | 700 __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), |
711 1, r2, r3); | 701 1, r4, r3); |
712 __ Ret(); | 702 __ Ret(); |
713 | 703 |
714 // Do a quick inline probe of the receiver's dictionary, if it | 704 // Do a quick inline probe of the receiver's dictionary, if it |
715 // exists. | 705 // exists. |
716 __ bind(&probe_dictionary); | 706 __ bind(&probe_dictionary); |
717 // r1: receiver | |
718 // r0: key | |
719 // r3: elements | 707 // r3: elements |
720 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); | 708 __ ldr(r0, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
721 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 709 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
722 GenerateGlobalInstanceTypeCheck(masm, r2, &slow); | 710 GenerateGlobalInstanceTypeCheck(masm, r0, &slow); |
723 // Load the property to r0. | 711 // Load the property to r0. |
724 GenerateDictionaryLoad(masm, &slow, r3, r0, r0, r2, r4); | 712 GenerateDictionaryLoad(masm, &slow, r3, key, r0, r5, r4); |
725 __ IncrementCounter( | 713 __ IncrementCounter( |
726 isolate->counters()->keyed_load_generic_symbol(), 1, r2, r3); | 714 isolate->counters()->keyed_load_generic_symbol(), 1, r4, r3); |
727 __ Ret(); | 715 __ Ret(); |
728 | 716 |
729 __ bind(&index_name); | 717 __ bind(&index_name); |
730 __ IndexFromHash(r3, key); | 718 __ IndexFromHash(r3, key); |
731 // Now jump to the place where smi keys are handled. | 719 // Now jump to the place where smi keys are handled. |
732 __ jmp(&index_smi); | 720 __ jmp(&index_smi); |
733 } | 721 } |
734 | 722 |
735 | 723 |
736 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 724 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
(...skipping 24 matching lines...) Expand all Loading... | |
761 GenerateMiss(masm); | 749 GenerateMiss(masm); |
762 } | 750 } |
763 | 751 |
764 | 752 |
765 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 753 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
766 // Return address is on the stack. | 754 // Return address is on the stack. |
767 Label slow; | 755 Label slow; |
768 | 756 |
769 Register receiver = ReceiverRegister(); | 757 Register receiver = ReceiverRegister(); |
770 Register key = NameRegister(); | 758 Register key = NameRegister(); |
771 Register scratch1 = r2; | 759 Register scratch1 = r3; |
772 Register scratch2 = r3; | 760 Register scratch2 = r4; |
773 ASSERT(!scratch1.is(receiver) && !scratch1.is(key)); | 761 ASSERT(!scratch1.is(receiver) && !scratch1.is(key)); |
774 ASSERT(!scratch2.is(receiver) && !scratch2.is(key)); | 762 ASSERT(!scratch2.is(receiver) && !scratch2.is(key)); |
775 | 763 |
776 // Check that the receiver isn't a smi. | 764 // Check that the receiver isn't a smi. |
777 __ JumpIfSmi(receiver, &slow); | 765 __ JumpIfSmi(receiver, &slow); |
778 | 766 |
779 // Check that the key is an array index, that is Uint32. | 767 // Check that the key is an array index, that is Uint32. |
780 __ NonNegativeSmiTst(key); | 768 __ NonNegativeSmiTst(key); |
781 __ b(ne, &slow); | 769 __ b(ne, &slow); |
782 | 770 |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1316 } else { | 1304 } else { |
1317 ASSERT(Assembler::GetCondition(branch_instr) == ne); | 1305 ASSERT(Assembler::GetCondition(branch_instr) == ne); |
1318 patcher.EmitCondition(eq); | 1306 patcher.EmitCondition(eq); |
1319 } | 1307 } |
1320 } | 1308 } |
1321 | 1309 |
1322 | 1310 |
1323 } } // namespace v8::internal | 1311 } } // namespace v8::internal |
1324 | 1312 |
1325 #endif // V8_TARGET_ARCH_ARM | 1313 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |