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_X64 | 7 #if V8_TARGET_ARCH_X64 |
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 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
560 static void KeyedStoreGenerateGenericHelper( | 560 static void KeyedStoreGenerateGenericHelper( |
561 MacroAssembler* masm, | 561 MacroAssembler* masm, |
562 Label* fast_object, | 562 Label* fast_object, |
563 Label* fast_double, | 563 Label* fast_double, |
564 Label* slow, | 564 Label* slow, |
565 KeyedStoreCheckMap check_map, | 565 KeyedStoreCheckMap check_map, |
566 KeyedStoreIncrementLength increment_length) { | 566 KeyedStoreIncrementLength increment_length) { |
567 Label transition_smi_elements; | 567 Label transition_smi_elements; |
568 Label finish_object_store, non_double_value, transition_double_elements; | 568 Label finish_object_store, non_double_value, transition_double_elements; |
569 Label fast_double_without_map_check; | 569 Label fast_double_without_map_check; |
570 Register receiver = KeyedStoreIC::ReceiverRegister(); | |
571 Register key = KeyedStoreIC::NameRegister(); | |
572 Register value = KeyedStoreIC::ValueRegister(); | |
573 ASSERT(receiver.is(rdx)); | |
574 ASSERT(key.is(rcx)); | |
575 ASSERT(value.is(rax)); | |
570 // Fast case: Do the store, could be either Object or double. | 576 // Fast case: Do the store, could be either Object or double. |
571 __ bind(fast_object); | 577 __ bind(fast_object); |
572 // rax: value | |
573 // rbx: receiver's elements array (a FixedArray) | 578 // rbx: receiver's elements array (a FixedArray) |
574 // rcx: index | 579 // receiver is a JSArray. |
575 // rdx: receiver (a JSArray) | |
576 // r9: map of receiver | 580 // r9: map of receiver |
577 if (check_map == kCheckMap) { | 581 if (check_map == kCheckMap) { |
578 __ movp(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); | 582 __ movp(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); |
579 __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex); | 583 __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex); |
580 __ j(not_equal, fast_double); | 584 __ j(not_equal, fast_double); |
581 } | 585 } |
582 | 586 |
583 // HOLECHECK: guards "A[i] = V" | 587 // HOLECHECK: guards "A[i] = V" |
584 // We have to go to the runtime if the current value is the hole because | 588 // We have to go to the runtime if the current value is the hole because |
585 // there may be a callback on the element | 589 // there may be a callback on the element |
586 Label holecheck_passed1; | 590 Label holecheck_passed1; |
587 __ movp(kScratchRegister, FieldOperand(rbx, | 591 __ movp(kScratchRegister, FieldOperand(rbx, |
588 rcx, | 592 key, |
589 times_pointer_size, | 593 times_pointer_size, |
590 FixedArray::kHeaderSize)); | 594 FixedArray::kHeaderSize)); |
591 __ CompareRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | 595 __ CompareRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); |
592 __ j(not_equal, &holecheck_passed1); | 596 __ j(not_equal, &holecheck_passed1); |
593 __ JumpIfDictionaryInPrototypeChain(rdx, rdi, kScratchRegister, slow); | 597 __ JumpIfDictionaryInPrototypeChain(receiver, rdi, kScratchRegister, slow); |
594 | 598 |
595 __ bind(&holecheck_passed1); | 599 __ bind(&holecheck_passed1); |
596 | 600 |
597 // Smi stores don't require further checks. | 601 // Smi stores don't require further checks. |
598 Label non_smi_value; | 602 Label non_smi_value; |
599 __ JumpIfNotSmi(rax, &non_smi_value); | 603 __ JumpIfNotSmi(value, &non_smi_value); |
600 if (increment_length == kIncrementLength) { | 604 if (increment_length == kIncrementLength) { |
601 // Add 1 to receiver->length. | 605 // Add 1 to receiver->length. |
602 __ leal(rdi, Operand(rcx, 1)); | 606 __ leal(rdi, Operand(key, 1)); |
603 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi); | 607 __ Integer32ToSmiField(FieldOperand(receiver, JSArray::kLengthOffset), rdi); |
604 } | 608 } |
605 // It's irrelevant whether array is smi-only or not when writing a smi. | 609 // It's irrelevant whether array is smi-only or not when writing a smi. |
606 __ movp(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize), | 610 __ movp(FieldOperand(rbx, key, times_pointer_size, FixedArray::kHeaderSize), |
607 rax); | 611 value); |
608 __ ret(0); | 612 __ ret(0); |
609 | 613 |
610 __ bind(&non_smi_value); | 614 __ bind(&non_smi_value); |
611 // Writing a non-smi, check whether array allows non-smi elements. | 615 // Writing a non-smi, check whether array allows non-smi elements. |
612 // r9: receiver's map | 616 // r9: receiver's map |
613 __ CheckFastObjectElements(r9, &transition_smi_elements); | 617 __ CheckFastObjectElements(r9, &transition_smi_elements); |
614 | 618 |
615 __ bind(&finish_object_store); | 619 __ bind(&finish_object_store); |
616 if (increment_length == kIncrementLength) { | 620 if (increment_length == kIncrementLength) { |
617 // Add 1 to receiver->length. | 621 // Add 1 to receiver->length. |
618 __ leal(rdi, Operand(rcx, 1)); | 622 __ leal(rdi, Operand(key, 1)); |
619 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi); | 623 __ Integer32ToSmiField(FieldOperand(receiver, JSArray::kLengthOffset), rdi); |
620 } | 624 } |
621 __ movp(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize), | 625 __ movp(FieldOperand(rbx, key, times_pointer_size, FixedArray::kHeaderSize), |
622 rax); | 626 value); |
623 __ movp(rdx, rax); // Preserve the value which is returned. | 627 __ movp(rdx, value); // Preserve the value which is returned. |
624 __ RecordWriteArray( | 628 __ RecordWriteArray( |
625 rbx, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 629 rbx, rdx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
626 __ ret(0); | 630 __ ret(0); |
627 | 631 |
628 __ bind(fast_double); | 632 __ bind(fast_double); |
629 if (check_map == kCheckMap) { | 633 if (check_map == kCheckMap) { |
630 // Check for fast double array case. If this fails, call through to the | 634 // Check for fast double array case. If this fails, call through to the |
631 // runtime. | 635 // runtime. |
632 // rdi: elements array's map | 636 // rdi: elements array's map |
633 __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); | 637 __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); |
634 __ j(not_equal, slow); | 638 __ j(not_equal, slow); |
635 } | 639 } |
636 | 640 |
637 // HOLECHECK: guards "A[i] double hole?" | 641 // HOLECHECK: guards "A[i] double hole?" |
638 // We have to see if the double version of the hole is present. If so | 642 // We have to see if the double version of the hole is present. If so |
639 // go to the runtime. | 643 // go to the runtime. |
640 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); | 644 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); |
641 __ cmpl(FieldOperand(rbx, rcx, times_8, offset), Immediate(kHoleNanUpper32)); | 645 __ cmpl(FieldOperand(rbx, key, times_8, offset), Immediate(kHoleNanUpper32)); |
642 __ j(not_equal, &fast_double_without_map_check); | 646 __ j(not_equal, &fast_double_without_map_check); |
643 __ JumpIfDictionaryInPrototypeChain(rdx, rdi, kScratchRegister, slow); | 647 __ JumpIfDictionaryInPrototypeChain(receiver, rdi, kScratchRegister, slow); |
644 | 648 |
645 __ bind(&fast_double_without_map_check); | 649 __ bind(&fast_double_without_map_check); |
646 __ StoreNumberToDoubleElements(rax, rbx, rcx, xmm0, | 650 __ StoreNumberToDoubleElements(value, rbx, key, xmm0, |
647 &transition_double_elements); | 651 &transition_double_elements); |
648 if (increment_length == kIncrementLength) { | 652 if (increment_length == kIncrementLength) { |
649 // Add 1 to receiver->length. | 653 // Add 1 to receiver->length. |
650 __ leal(rdi, Operand(rcx, 1)); | 654 __ leal(rdi, Operand(key, 1)); |
651 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi); | 655 __ Integer32ToSmiField(FieldOperand(receiver, JSArray::kLengthOffset), rdi); |
652 } | 656 } |
653 __ ret(0); | 657 __ ret(0); |
654 | 658 |
655 __ bind(&transition_smi_elements); | 659 __ bind(&transition_smi_elements); |
656 __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); | 660 __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset)); |
657 | 661 |
658 // Transition the array appropriately depending on the value type. | 662 // Transition the array appropriately depending on the value type. |
659 __ movp(r9, FieldOperand(rax, HeapObject::kMapOffset)); | 663 __ movp(r9, FieldOperand(value, HeapObject::kMapOffset)); |
660 __ CompareRoot(r9, Heap::kHeapNumberMapRootIndex); | 664 __ CompareRoot(r9, Heap::kHeapNumberMapRootIndex); |
661 __ j(not_equal, &non_double_value); | 665 __ j(not_equal, &non_double_value); |
662 | 666 |
663 // Value is a double. Transition FAST_SMI_ELEMENTS -> | 667 // Value is a double. Transition FAST_SMI_ELEMENTS -> |
664 // FAST_DOUBLE_ELEMENTS and complete the store. | 668 // FAST_DOUBLE_ELEMENTS and complete the store. |
665 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | 669 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, |
666 FAST_DOUBLE_ELEMENTS, | 670 FAST_DOUBLE_ELEMENTS, |
667 rbx, | 671 rbx, |
668 rdi, | 672 rdi, |
669 slow); | 673 slow); |
670 AllocationSiteMode mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, | 674 AllocationSiteMode mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, |
671 FAST_DOUBLE_ELEMENTS); | 675 FAST_DOUBLE_ELEMENTS); |
672 ElementsTransitionGenerator::GenerateSmiToDouble(masm, mode, slow); | 676 ElementsTransitionGenerator::GenerateSmiToDouble(masm, mode, slow); |
673 __ movp(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 677 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); |
674 __ jmp(&fast_double_without_map_check); | 678 __ jmp(&fast_double_without_map_check); |
675 | 679 |
676 __ bind(&non_double_value); | 680 __ bind(&non_double_value); |
677 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS | 681 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS |
678 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | 682 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, |
679 FAST_ELEMENTS, | 683 FAST_ELEMENTS, |
680 rbx, | 684 rbx, |
681 rdi, | 685 rdi, |
682 slow); | 686 slow); |
683 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); | 687 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); |
684 ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm, mode, | 688 ElementsTransitionGenerator::GenerateMapChangeElementsTransition(masm, mode, |
685 slow); | 689 slow); |
686 __ movp(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 690 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); |
687 __ jmp(&finish_object_store); | 691 __ jmp(&finish_object_store); |
688 | 692 |
689 __ bind(&transition_double_elements); | 693 __ bind(&transition_double_elements); |
690 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a | 694 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a |
691 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and | 695 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and |
692 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS | 696 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS |
693 __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); | 697 __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset)); |
694 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, | 698 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, |
695 FAST_ELEMENTS, | 699 FAST_ELEMENTS, |
696 rbx, | 700 rbx, |
697 rdi, | 701 rdi, |
698 slow); | 702 slow); |
699 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); | 703 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); |
700 ElementsTransitionGenerator::GenerateDoubleToObject(masm, mode, slow); | 704 ElementsTransitionGenerator::GenerateDoubleToObject(masm, mode, slow); |
701 __ movp(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 705 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); |
702 __ jmp(&finish_object_store); | 706 __ jmp(&finish_object_store); |
703 } | 707 } |
704 | 708 |
705 | 709 |
706 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, | 710 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
707 StrictMode strict_mode) { | 711 StrictMode strict_mode) { |
708 // ----------- S t a t e ------------- | 712 // Return address is on the stack. |
709 // -- rax : value | |
710 // -- rcx : key | |
711 // -- rdx : receiver | |
712 // -- rsp[0] : return address | |
713 // ----------------------------------- | |
714 Label slow, slow_with_tagged_index, fast_object, fast_object_grow; | 713 Label slow, slow_with_tagged_index, fast_object, fast_object_grow; |
715 Label fast_double, fast_double_grow; | 714 Label fast_double, fast_double_grow; |
716 Label array, extra, check_if_double_array; | 715 Label array, extra, check_if_double_array; |
716 Register receiver = ReceiverRegister(); | |
717 Register key = NameRegister(); | |
718 ASSERT(receiver.is(rdx)); | |
719 ASSERT(key.is(rcx)); | |
717 | 720 |
718 // Check that the object isn't a smi. | 721 // Check that the object isn't a smi. |
719 __ JumpIfSmi(rdx, &slow_with_tagged_index); | 722 __ JumpIfSmi(receiver, &slow_with_tagged_index); |
720 // Get the map from the receiver. | 723 // Get the map from the receiver. |
721 __ movp(r9, FieldOperand(rdx, HeapObject::kMapOffset)); | 724 __ movp(r9, FieldOperand(receiver, HeapObject::kMapOffset)); |
722 // Check that the receiver does not require access checks and is not observed. | 725 // Check that the receiver does not require access checks and is not observed. |
723 // The generic stub does not perform map checks or handle observed objects. | 726 // The generic stub does not perform map checks or handle observed objects. |
724 __ testb(FieldOperand(r9, Map::kBitFieldOffset), | 727 __ testb(FieldOperand(r9, Map::kBitFieldOffset), |
725 Immediate(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved)); | 728 Immediate(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved)); |
726 __ j(not_zero, &slow_with_tagged_index); | 729 __ j(not_zero, &slow_with_tagged_index); |
727 // Check that the key is a smi. | 730 // Check that the key is a smi. |
728 __ JumpIfNotSmi(rcx, &slow_with_tagged_index); | 731 __ JumpIfNotSmi(key, &slow_with_tagged_index); |
729 __ SmiToInteger32(rcx, rcx); | 732 __ SmiToInteger32(key, key); |
730 | 733 |
731 __ CmpInstanceType(r9, JS_ARRAY_TYPE); | 734 __ CmpInstanceType(r9, JS_ARRAY_TYPE); |
732 __ j(equal, &array); | 735 __ j(equal, &array); |
733 // Check that the object is some kind of JSObject. | 736 // Check that the object is some kind of JSObject. |
734 __ CmpInstanceType(r9, FIRST_JS_OBJECT_TYPE); | 737 __ CmpInstanceType(r9, FIRST_JS_OBJECT_TYPE); |
735 __ j(below, &slow); | 738 __ j(below, &slow); |
736 | 739 |
737 // Object case: Check key against length in the elements array. | 740 // Object case: Check key against length in the elements array. |
738 // rax: value | 741 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); |
739 // rdx: JSObject | |
740 // rcx: index | |
741 __ movp(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | |
742 // Check array bounds. | 742 // Check array bounds. |
743 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); | 743 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), key); |
744 // rax: value | |
745 // rbx: FixedArray | 744 // rbx: FixedArray |
746 // rcx: index | |
747 __ j(above, &fast_object); | 745 __ j(above, &fast_object); |
748 | 746 |
749 // Slow case: call runtime. | 747 // Slow case: call runtime. |
750 __ bind(&slow); | 748 __ bind(&slow); |
751 __ Integer32ToSmi(rcx, rcx); | 749 __ Integer32ToSmi(key, key); |
752 __ bind(&slow_with_tagged_index); | 750 __ bind(&slow_with_tagged_index); |
753 GenerateRuntimeSetProperty(masm, strict_mode); | 751 GenerateRuntimeSetProperty(masm, strict_mode); |
754 // Never returns to here. | 752 // Never returns to here. |
755 | 753 |
756 // Extra capacity case: Check if there is extra capacity to | 754 // Extra capacity case: Check if there is extra capacity to |
757 // perform the store and update the length. Used for adding one | 755 // perform the store and update the length. Used for adding one |
758 // element to the array by writing to array[array.length]. | 756 // element to the array by writing to array[array.length]. |
759 __ bind(&extra); | 757 __ bind(&extra); |
760 // rax: value | 758 // receiver is a JSArray. |
761 // rdx: receiver (a JSArray) | |
762 // rbx: receiver's elements array (a FixedArray) | 759 // rbx: receiver's elements array (a FixedArray) |
763 // rcx: index | 760 // flags: smicompare (receiver.length(), rbx) |
764 // flags: smicompare (rdx.length(), rbx) | |
765 __ j(not_equal, &slow); // do not leave holes in the array | 761 __ j(not_equal, &slow); // do not leave holes in the array |
766 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx); | 762 __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), key); |
767 __ j(below_equal, &slow); | 763 __ j(below_equal, &slow); |
768 // Increment index to get new length. | 764 // Increment index to get new length. |
769 __ movp(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); | 765 __ movp(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); |
770 __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex); | 766 __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex); |
771 __ j(not_equal, &check_if_double_array); | 767 __ j(not_equal, &check_if_double_array); |
772 __ jmp(&fast_object_grow); | 768 __ jmp(&fast_object_grow); |
773 | 769 |
774 __ bind(&check_if_double_array); | 770 __ bind(&check_if_double_array); |
775 // rdi: elements array's map | 771 // rdi: elements array's map |
776 __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); | 772 __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); |
777 __ j(not_equal, &slow); | 773 __ j(not_equal, &slow); |
778 __ jmp(&fast_double_grow); | 774 __ jmp(&fast_double_grow); |
779 | 775 |
780 // Array case: Get the length and the elements array from the JS | 776 // Array case: Get the length and the elements array from the JS |
781 // array. Check that the array is in fast mode (and writable); if it | 777 // array. Check that the array is in fast mode (and writable); if it |
782 // is the length is always a smi. | 778 // is the length is always a smi. |
783 __ bind(&array); | 779 __ bind(&array); |
784 // rax: value | 780 // receiver is a JSArray. |
785 // rdx: receiver (a JSArray) | 781 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); |
786 // rcx: index | |
787 __ movp(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | |
788 | 782 |
789 // Check the key against the length in the array, compute the | 783 // Check the key against the length in the array, compute the |
790 // address to store into and fall through to fast case. | 784 // address to store into and fall through to fast case. |
791 __ SmiCompareInteger32(FieldOperand(rdx, JSArray::kLengthOffset), rcx); | 785 __ SmiCompareInteger32(FieldOperand(receiver, JSArray::kLengthOffset), key); |
792 __ j(below_equal, &extra); | 786 __ j(below_equal, &extra); |
793 | 787 |
794 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, | 788 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, |
795 &slow, kCheckMap, kDontIncrementLength); | 789 &slow, kCheckMap, kDontIncrementLength); |
796 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, | 790 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, |
797 &slow, kDontCheckMap, kIncrementLength); | 791 &slow, kDontCheckMap, kIncrementLength); |
798 } | 792 } |
799 | 793 |
800 | 794 |
801 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, | 795 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
899 __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex); | 893 __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex); |
900 __ j(equal, &slow); | 894 __ j(equal, &slow); |
901 __ movp(rax, unmapped_location); | 895 __ movp(rax, unmapped_location); |
902 __ Ret(); | 896 __ Ret(); |
903 __ bind(&slow); | 897 __ bind(&slow); |
904 GenerateMiss(masm); | 898 GenerateMiss(masm); |
905 } | 899 } |
906 | 900 |
907 | 901 |
908 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { | 902 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { |
909 // ----------- S t a t e ------------- | 903 // ----------- S t a t e ------------- |
Jakob Kummerow
2014/07/10 13:42:05
just "// The return address is on the stack."
| |
910 // -- rax : value | 904 // -- rax : value |
911 // -- rcx : key | 905 // -- rcx : key |
912 // -- rdx : receiver | 906 // -- rdx : receiver |
913 // -- rsp[0] : return address | 907 // -- rsp[0] : return address |
914 // ----------------------------------- | 908 // ----------------------------------- |
915 Label slow, notin; | 909 Label slow, notin; |
910 Register receiver = ReceiverRegister(); | |
911 Register name = NameRegister(); | |
912 Register value = ValueRegister(); | |
913 ASSERT(receiver.is(rdx)); | |
914 ASSERT(name.is(rcx)); | |
915 ASSERT(value.is(rax)); | |
916 | |
916 Operand mapped_location = GenerateMappedArgumentsLookup( | 917 Operand mapped_location = GenerateMappedArgumentsLookup( |
917 masm, rdx, rcx, rbx, rdi, r8, ¬in, &slow); | 918 masm, receiver, name, rbx, rdi, r8, ¬in, &slow); |
918 __ movp(mapped_location, rax); | 919 __ movp(mapped_location, value); |
919 __ leap(r9, mapped_location); | 920 __ leap(r9, mapped_location); |
920 __ movp(r8, rax); | 921 __ movp(r8, value); |
921 __ RecordWrite(rbx, | 922 __ RecordWrite(rbx, |
922 r9, | 923 r9, |
923 r8, | 924 r8, |
924 kDontSaveFPRegs, | 925 kDontSaveFPRegs, |
925 EMIT_REMEMBERED_SET, | 926 EMIT_REMEMBERED_SET, |
926 INLINE_SMI_CHECK); | 927 INLINE_SMI_CHECK); |
927 __ Ret(); | 928 __ Ret(); |
928 __ bind(¬in); | 929 __ bind(¬in); |
929 // The unmapped lookup expects that the parameter map is in rbx. | 930 // The unmapped lookup expects that the parameter map is in rbx. |
930 Operand unmapped_location = | 931 Operand unmapped_location = |
931 GenerateUnmappedArgumentsLookup(masm, rcx, rbx, rdi, &slow); | 932 GenerateUnmappedArgumentsLookup(masm, name, rbx, rdi, &slow); |
932 __ movp(unmapped_location, rax); | 933 __ movp(unmapped_location, value); |
933 __ leap(r9, unmapped_location); | 934 __ leap(r9, unmapped_location); |
934 __ movp(r8, rax); | 935 __ movp(r8, value); |
935 __ RecordWrite(rbx, | 936 __ RecordWrite(rbx, |
936 r9, | 937 r9, |
937 r8, | 938 r8, |
938 kDontSaveFPRegs, | 939 kDontSaveFPRegs, |
939 EMIT_REMEMBERED_SET, | 940 EMIT_REMEMBERED_SET, |
940 INLINE_SMI_CHECK); | 941 INLINE_SMI_CHECK); |
941 __ Ret(); | 942 __ Ret(); |
942 __ bind(&slow); | 943 __ bind(&slow); |
943 GenerateMiss(masm); | 944 GenerateMiss(masm); |
944 } | 945 } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1042 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); | 1043 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); |
1043 __ TailCallExternalReference(ref, 2, 1); | 1044 __ TailCallExternalReference(ref, 2, 1); |
1044 } | 1045 } |
1045 | 1046 |
1046 | 1047 |
1047 // IC register specifications | 1048 // IC register specifications |
1048 const Register LoadIC::ReceiverRegister() { return rdx; } | 1049 const Register LoadIC::ReceiverRegister() { return rdx; } |
1049 const Register LoadIC::NameRegister() { return rcx; } | 1050 const Register LoadIC::NameRegister() { return rcx; } |
1050 | 1051 |
1051 | 1052 |
1053 const Register StoreIC::ReceiverRegister() { return rdx; } | |
1054 const Register StoreIC::NameRegister() { return rcx; } | |
1055 const Register StoreIC::ValueRegister() { return rax; } | |
1056 | |
1057 | |
1058 const Register KeyedStoreIC::ReceiverRegister() { | |
1059 return StoreIC::ReceiverRegister(); | |
1060 } | |
1061 | |
1062 | |
1063 const Register KeyedStoreIC::NameRegister() { | |
1064 return StoreIC::NameRegister(); | |
1065 } | |
1066 | |
1067 | |
1068 const Register KeyedStoreIC::ValueRegister() { | |
1069 return StoreIC::ValueRegister(); | |
1070 } | |
1071 | |
1072 | |
1052 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 1073 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
1053 // The return address is on the stack. | 1074 // The return address is on the stack. |
1054 | 1075 |
1055 __ PopReturnAddressTo(KeyedLoadIC_TempRegister()); | 1076 __ PopReturnAddressTo(KeyedLoadIC_TempRegister()); |
1056 __ Push(ReceiverRegister()); // receiver | 1077 __ Push(ReceiverRegister()); // receiver |
1057 __ Push(NameRegister()); // name | 1078 __ Push(NameRegister()); // name |
1058 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); | 1079 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); |
1059 | 1080 |
1060 // Perform tail call to the entry. | 1081 // Perform tail call to the entry. |
1061 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 1082 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
1062 } | 1083 } |
1063 | 1084 |
1064 | 1085 |
1065 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1086 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
1066 // ----------- S t a t e ------------- | 1087 // The return address is on the stack. |
1067 // -- rax : value | |
1068 // -- rcx : name | |
1069 // -- rdx : receiver | |
1070 // -- rsp[0] : return address | |
1071 // ----------------------------------- | |
1072 | 1088 |
1073 // Get the receiver from the stack and probe the stub cache. | 1089 // Get the receiver from the stack and probe the stub cache. |
1074 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC); | 1090 Code::Flags flags = Code::ComputeHandlerFlags(Code::STORE_IC); |
1075 masm->isolate()->stub_cache()->GenerateProbe( | 1091 masm->isolate()->stub_cache()->GenerateProbe( |
1076 masm, flags, rdx, rcx, rbx, no_reg); | 1092 masm, flags, ReceiverRegister(), NameRegister(), rbx, no_reg); |
1077 | 1093 |
1078 // Cache miss: Jump to runtime. | 1094 // Cache miss: Jump to runtime. |
1079 GenerateMiss(masm); | 1095 GenerateMiss(masm); |
1080 } | 1096 } |
1081 | 1097 |
1082 | 1098 |
1083 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1099 static void StoreIC_PushArgs(MacroAssembler* masm) { |
1084 // ----------- S t a t e ------------- | 1100 Register receiver = StoreIC::ReceiverRegister(); |
1085 // -- rax : value | 1101 Register name = StoreIC::NameRegister(); |
1086 // -- rcx : name | 1102 Register value = StoreIC::ValueRegister(); |
1087 // -- rdx : receiver | 1103 |
1088 // -- rsp[0] : return address | 1104 ASSERT(!rbx.is(receiver) && !rbx.is(name) && !rbx.is(value)); |
1089 // ----------------------------------- | |
1090 | 1105 |
1091 __ PopReturnAddressTo(rbx); | 1106 __ PopReturnAddressTo(rbx); |
1092 __ Push(rdx); // receiver | 1107 __ Push(receiver); |
1093 __ Push(rcx); // name | 1108 __ Push(name); |
1094 __ Push(rax); // value | 1109 __ Push(value); |
1095 __ PushReturnAddressFrom(rbx); | 1110 __ PushReturnAddressFrom(rbx); |
1111 } | |
1112 | |
1113 | |
1114 void StoreIC::GenerateMiss(MacroAssembler* masm) { | |
1115 // Return address is on the stack. | |
1116 StoreIC_PushArgs(masm); | |
1096 | 1117 |
1097 // Perform tail call to the entry. | 1118 // Perform tail call to the entry. |
1098 ExternalReference ref = | 1119 ExternalReference ref = |
1099 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); | 1120 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); |
1100 __ TailCallExternalReference(ref, 3, 1); | 1121 __ TailCallExternalReference(ref, 3, 1); |
1101 } | 1122 } |
1102 | 1123 |
1103 | 1124 |
1104 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 1125 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
1105 // ----------- S t a t e ------------- | 1126 // Return address is on the stack. |
1106 // -- rax : value | 1127 Register receiver = ReceiverRegister(); |
1107 // -- rcx : name | 1128 Register name = NameRegister(); |
1108 // -- rdx : receiver | 1129 Register value = ValueRegister(); |
1109 // -- rsp[0] : return address | |
1110 // ----------------------------------- | |
1111 | 1130 |
1112 Label miss; | 1131 Label miss; |
1113 | 1132 |
1114 GenerateNameDictionaryReceiverCheck(masm, rdx, rbx, rdi, &miss); | 1133 GenerateNameDictionaryReceiverCheck(masm, receiver, rbx, rdi, &miss); |
1115 | 1134 |
1116 GenerateDictionaryStore(masm, &miss, rbx, rcx, rax, r8, r9); | 1135 GenerateDictionaryStore(masm, &miss, rbx, name, value, r8, r9); |
1117 Counters* counters = masm->isolate()->counters(); | 1136 Counters* counters = masm->isolate()->counters(); |
1118 __ IncrementCounter(counters->store_normal_hit(), 1); | 1137 __ IncrementCounter(counters->store_normal_hit(), 1); |
1119 __ ret(0); | 1138 __ ret(0); |
1120 | 1139 |
1121 __ bind(&miss); | 1140 __ bind(&miss); |
1122 __ IncrementCounter(counters->store_normal_miss(), 1); | 1141 __ IncrementCounter(counters->store_normal_miss(), 1); |
1123 GenerateMiss(masm); | 1142 GenerateMiss(masm); |
1124 } | 1143 } |
1125 | 1144 |
1126 | 1145 |
1127 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, | 1146 void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, |
1128 StrictMode strict_mode) { | 1147 StrictMode strict_mode) { |
1129 // ----------- S t a t e ------------- | 1148 // Return address is on the stack. |
1130 // -- rax : value | 1149 ASSERT(!rbx.is(ReceiverRegister()) && !rbx.is(NameRegister()) && |
1131 // -- rcx : name | 1150 !rbx.is(ValueRegister())); |
1132 // -- rdx : receiver | 1151 |
1133 // -- rsp[0] : return address | |
1134 // ----------------------------------- | |
1135 __ PopReturnAddressTo(rbx); | 1152 __ PopReturnAddressTo(rbx); |
1136 __ Push(rdx); | 1153 __ Push(ReceiverRegister()); |
1137 __ Push(rcx); | 1154 __ Push(NameRegister()); |
1138 __ Push(rax); | 1155 __ Push(ValueRegister()); |
1139 __ Push(Smi::FromInt(strict_mode)); | 1156 __ Push(Smi::FromInt(strict_mode)); |
1140 __ PushReturnAddressFrom(rbx); | 1157 __ PushReturnAddressFrom(rbx); |
1141 | 1158 |
1142 // Do tail-call to runtime routine. | 1159 // Do tail-call to runtime routine. |
1143 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); | 1160 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); |
1144 } | 1161 } |
1145 | 1162 |
1146 | 1163 |
1147 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, | 1164 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, |
1148 StrictMode strict_mode) { | 1165 StrictMode strict_mode) { |
1149 // ----------- S t a t e ------------- | 1166 // Return address is on the stack. |
1150 // -- rax : value | 1167 ASSERT(!rbx.is(ReceiverRegister()) && !rbx.is(NameRegister()) && |
1151 // -- rcx : key | 1168 !rbx.is(ValueRegister())); |
1152 // -- rdx : receiver | |
1153 // -- rsp[0] : return address | |
1154 // ----------------------------------- | |
1155 | 1169 |
1156 __ PopReturnAddressTo(rbx); | 1170 __ PopReturnAddressTo(rbx); |
1157 __ Push(rdx); // receiver | 1171 __ Push(ReceiverRegister()); |
1158 __ Push(rcx); // key | 1172 __ Push(NameRegister()); |
1159 __ Push(rax); // value | 1173 __ Push(ValueRegister()); |
1160 __ Push(Smi::FromInt(strict_mode)); // Strict mode. | 1174 __ Push(Smi::FromInt(strict_mode)); // Strict mode. |
1161 __ PushReturnAddressFrom(rbx); | 1175 __ PushReturnAddressFrom(rbx); |
1162 | 1176 |
1163 // Do tail-call to runtime routine. | 1177 // Do tail-call to runtime routine. |
1164 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); | 1178 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); |
1165 } | 1179 } |
1166 | 1180 |
1167 | 1181 |
1168 void StoreIC::GenerateSlow(MacroAssembler* masm) { | 1182 void StoreIC::GenerateSlow(MacroAssembler* masm) { |
1169 // ----------- S t a t e ------------- | 1183 // Return address is on the stack. |
1170 // -- rax : value | 1184 StoreIC_PushArgs(masm); |
1171 // -- rcx : key | |
1172 // -- rdx : receiver | |
1173 // -- rsp[0] : return address | |
1174 // ----------------------------------- | |
1175 | |
1176 __ PopReturnAddressTo(rbx); | |
1177 __ Push(rdx); // receiver | |
1178 __ Push(rcx); // key | |
1179 __ Push(rax); // value | |
1180 __ PushReturnAddressFrom(rbx); | |
1181 | 1185 |
1182 // Do tail-call to runtime routine. | 1186 // Do tail-call to runtime routine. |
1183 ExternalReference ref(IC_Utility(kStoreIC_Slow), masm->isolate()); | 1187 ExternalReference ref(IC_Utility(kStoreIC_Slow), masm->isolate()); |
1184 __ TailCallExternalReference(ref, 3, 1); | 1188 __ TailCallExternalReference(ref, 3, 1); |
1185 } | 1189 } |
1186 | 1190 |
1187 | 1191 |
1188 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { | 1192 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { |
1189 // ----------- S t a t e ------------- | 1193 // Return address is on the stack. |
1190 // -- rax : value | 1194 StoreIC_PushArgs(masm); |
1191 // -- rcx : key | |
1192 // -- rdx : receiver | |
1193 // -- rsp[0] : return address | |
1194 // ----------------------------------- | |
1195 | |
1196 __ PopReturnAddressTo(rbx); | |
1197 __ Push(rdx); // receiver | |
1198 __ Push(rcx); // key | |
1199 __ Push(rax); // value | |
1200 __ PushReturnAddressFrom(rbx); | |
1201 | 1195 |
1202 // Do tail-call to runtime routine. | 1196 // Do tail-call to runtime routine. |
1203 ExternalReference ref(IC_Utility(kKeyedStoreIC_Slow), masm->isolate()); | 1197 ExternalReference ref(IC_Utility(kKeyedStoreIC_Slow), masm->isolate()); |
1204 __ TailCallExternalReference(ref, 3, 1); | 1198 __ TailCallExternalReference(ref, 3, 1); |
1205 } | 1199 } |
1206 | 1200 |
1207 | 1201 |
1208 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 1202 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
1209 // ----------- S t a t e ------------- | 1203 // Return address is on the stack. |
1210 // -- rax : value | 1204 StoreIC_PushArgs(masm); |
1211 // -- rcx : key | |
1212 // -- rdx : receiver | |
1213 // -- rsp[0] : return address | |
1214 // ----------------------------------- | |
1215 | |
1216 __ PopReturnAddressTo(rbx); | |
1217 __ Push(rdx); // receiver | |
1218 __ Push(rcx); // key | |
1219 __ Push(rax); // value | |
1220 __ PushReturnAddressFrom(rbx); | |
1221 | 1205 |
1222 // Do tail-call to runtime routine. | 1206 // Do tail-call to runtime routine. |
1223 ExternalReference ref = | 1207 ExternalReference ref = |
1224 ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate()); | 1208 ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate()); |
1225 __ TailCallExternalReference(ref, 3, 1); | 1209 __ TailCallExternalReference(ref, 3, 1); |
1226 } | 1210 } |
1227 | 1211 |
1228 | 1212 |
1229 #undef __ | 1213 #undef __ |
1230 | 1214 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1293 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) | 1277 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) |
1294 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 1278 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
1295 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 1279 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
1296 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1280 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
1297 } | 1281 } |
1298 | 1282 |
1299 | 1283 |
1300 } } // namespace v8::internal | 1284 } } // namespace v8::internal |
1301 | 1285 |
1302 #endif // V8_TARGET_ARCH_X64 | 1286 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |