| 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_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
| 8 | 8 |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 masm->set_has_frame(false); | 544 masm->set_has_frame(false); |
| 545 } | 545 } |
| 546 | 546 |
| 547 | 547 |
| 548 // ------------------------------------------------------------------------- | 548 // ------------------------------------------------------------------------- |
| 549 // Code generators | 549 // Code generators |
| 550 | 550 |
| 551 #define __ ACCESS_MASM(masm) | 551 #define __ ACCESS_MASM(masm) |
| 552 | 552 |
| 553 void ElementsTransitionGenerator::GenerateMapChangeElementsTransition( | 553 void ElementsTransitionGenerator::GenerateMapChangeElementsTransition( |
| 554 MacroAssembler* masm, AllocationSiteMode mode, | 554 MacroAssembler* masm, |
| 555 Register receiver, |
| 556 Register key, |
| 557 Register value, |
| 558 Register target_map, |
| 559 AllocationSiteMode mode, |
| 555 Label* allocation_memento_found) { | 560 Label* allocation_memento_found) { |
| 556 // ----------- S t a t e ------------- | 561 Register scratch_elements = a4; |
| 557 // -- a0 : value | 562 ASSERT(!AreAliased(receiver, key, value, target_map, |
| 558 // -- a1 : key | 563 scratch_elements)); |
| 559 // -- a2 : receiver | 564 |
| 560 // -- ra : return address | |
| 561 // -- a3 : target map, scratch for subsequent call | |
| 562 // -- a4 : scratch (elements) | |
| 563 // ----------------------------------- | |
| 564 if (mode == TRACK_ALLOCATION_SITE) { | 565 if (mode == TRACK_ALLOCATION_SITE) { |
| 565 ASSERT(allocation_memento_found != NULL); | 566 __ JumpIfJSArrayHasAllocationMemento( |
| 566 __ JumpIfJSArrayHasAllocationMemento(a2, a4, allocation_memento_found); | 567 receiver, scratch_elements, allocation_memento_found); |
| 567 } | 568 } |
| 568 | 569 |
| 569 // Set transitioned map. | 570 // Set transitioned map. |
| 570 __ sd(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); | 571 __ sd(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 571 __ RecordWriteField(a2, | 572 __ RecordWriteField(a2, |
| 572 HeapObject::kMapOffset, | 573 HeapObject::kMapOffset, |
| 573 a3, | 574 target_map, |
| 574 t1, | 575 t1, |
| 575 kRAHasNotBeenSaved, | 576 kRAHasNotBeenSaved, |
| 576 kDontSaveFPRegs, | 577 kDontSaveFPRegs, |
| 577 EMIT_REMEMBERED_SET, | 578 EMIT_REMEMBERED_SET, |
| 578 OMIT_SMI_CHECK); | 579 OMIT_SMI_CHECK); |
| 579 } | 580 } |
| 580 | 581 |
| 581 | 582 |
| 582 void ElementsTransitionGenerator::GenerateSmiToDouble( | 583 void ElementsTransitionGenerator::GenerateSmiToDouble( |
| 583 MacroAssembler* masm, AllocationSiteMode mode, Label* fail) { | 584 MacroAssembler* masm, |
| 584 // ----------- S t a t e ------------- | 585 Register receiver, |
| 585 // -- a0 : value | 586 Register key, |
| 586 // -- a1 : key | 587 Register value, |
| 587 // -- a2 : receiver | 588 Register target_map, |
| 588 // -- ra : return address | 589 AllocationSiteMode mode, |
| 589 // -- a3 : target map, scratch for subsequent call | 590 Label* fail) { |
| 590 // -- a4 : scratch (elements) | 591 // Register ra contains the return address. |
| 591 // ----------------------------------- | |
| 592 Label loop, entry, convert_hole, gc_required, only_change_map, done; | 592 Label loop, entry, convert_hole, gc_required, only_change_map, done; |
| 593 Register elements = a4; |
| 594 Register length = a5; |
| 595 Register array = a6; |
| 596 Register array_end = array; |
| 597 |
| 598 // target_map parameter can be clobbered. |
| 599 Register scratch1 = target_map; |
| 600 Register scratch2 = t1; |
| 601 Register scratch3 = a7; |
| 602 |
| 603 // Verify input registers don't conflict with locals. |
| 604 ASSERT(!AreAliased(receiver, key, value, target_map, |
| 605 elements, length, array, scratch2)); |
| 593 | 606 |
| 594 Register scratch = t2; | 607 Register scratch = t2; |
| 595 if (mode == TRACK_ALLOCATION_SITE) { | 608 if (mode == TRACK_ALLOCATION_SITE) { |
| 596 __ JumpIfJSArrayHasAllocationMemento(a2, a4, fail); | 609 __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail); |
| 597 } | 610 } |
| 598 | 611 |
| 599 // Check for empty arrays, which only require a map transition and no changes | 612 // Check for empty arrays, which only require a map transition and no changes |
| 600 // to the backing store. | 613 // to the backing store. |
| 601 __ ld(a4, FieldMemOperand(a2, JSObject::kElementsOffset)); | 614 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 602 __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex); | 615 __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex); |
| 603 __ Branch(&only_change_map, eq, at, Operand(a4)); | 616 __ Branch(&only_change_map, eq, at, Operand(elements)); |
| 604 | 617 |
| 605 __ push(ra); | 618 __ push(ra); |
| 606 __ ld(a5, FieldMemOperand(a4, FixedArray::kLengthOffset)); | 619 __ ld(length, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 607 // a4: source FixedArray | 620 // elements: source FixedArray |
| 608 // a5: number of elements (smi-tagged) | 621 // length: number of elements (smi-tagged) |
| 609 | 622 |
| 610 // Allocate new FixedDoubleArray. | 623 // Allocate new FixedDoubleArray. |
| 611 __ SmiScale(scratch, a5, kDoubleSizeLog2); | 624 __ SmiScale(scratch, length, kDoubleSizeLog2); |
| 612 __ Daddu(scratch, scratch, FixedDoubleArray::kHeaderSize); | 625 __ Daddu(scratch, scratch, FixedDoubleArray::kHeaderSize); |
| 613 __ Allocate(scratch, a6, a7, t1, &gc_required, DOUBLE_ALIGNMENT); | 626 __ Allocate(scratch, array, t3, scratch2, &gc_required, DOUBLE_ALIGNMENT); |
| 614 // a6: destination FixedDoubleArray, not tagged as heap object | 627 // array: destination FixedDoubleArray, not tagged as heap object |
| 615 | 628 |
| 616 // Set destination FixedDoubleArray's length and map. | 629 // Set destination FixedDoubleArray's length and map. |
| 617 __ LoadRoot(t1, Heap::kFixedDoubleArrayMapRootIndex); | 630 __ LoadRoot(scratch2, Heap::kFixedDoubleArrayMapRootIndex); |
| 618 __ sd(a5, MemOperand(a6, FixedDoubleArray::kLengthOffset)); | 631 __ sd(length, MemOperand(array, FixedDoubleArray::kLengthOffset)); |
| 619 __ sd(t1, MemOperand(a6, HeapObject::kMapOffset)); | |
| 620 // Update receiver's map. | 632 // Update receiver's map. |
| 633 __ sd(scratch2, MemOperand(array, HeapObject::kMapOffset)); |
| 621 | 634 |
| 622 __ sd(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); | 635 __ sd(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 623 __ RecordWriteField(a2, | 636 __ RecordWriteField(receiver, |
| 624 HeapObject::kMapOffset, | 637 HeapObject::kMapOffset, |
| 625 a3, | 638 target_map, |
| 626 t1, | 639 scratch2, |
| 627 kRAHasBeenSaved, | 640 kRAHasBeenSaved, |
| 628 kDontSaveFPRegs, | 641 kDontSaveFPRegs, |
| 629 OMIT_REMEMBERED_SET, | 642 OMIT_REMEMBERED_SET, |
| 630 OMIT_SMI_CHECK); | 643 OMIT_SMI_CHECK); |
| 631 // Replace receiver's backing store with newly created FixedDoubleArray. | 644 // Replace receiver's backing store with newly created FixedDoubleArray. |
| 632 __ Daddu(a3, a6, Operand(kHeapObjectTag)); | 645 __ Daddu(scratch1, array, Operand(kHeapObjectTag)); |
| 633 __ sd(a3, FieldMemOperand(a2, JSObject::kElementsOffset)); | 646 __ sd(scratch1, FieldMemOperand(a2, JSObject::kElementsOffset)); |
| 634 __ RecordWriteField(a2, | 647 __ RecordWriteField(receiver, |
| 635 JSObject::kElementsOffset, | 648 JSObject::kElementsOffset, |
| 636 a3, | 649 scratch1, |
| 637 t1, | 650 scratch2, |
| 638 kRAHasBeenSaved, | 651 kRAHasBeenSaved, |
| 639 kDontSaveFPRegs, | 652 kDontSaveFPRegs, |
| 640 EMIT_REMEMBERED_SET, | 653 EMIT_REMEMBERED_SET, |
| 641 OMIT_SMI_CHECK); | 654 OMIT_SMI_CHECK); |
| 642 | 655 |
| 643 | 656 |
| 644 // Prepare for conversion loop. | 657 // Prepare for conversion loop. |
| 645 __ Daddu(a3, a4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 658 __ Daddu(scratch1, elements, |
| 646 __ Daddu(a7, a6, Operand(FixedDoubleArray::kHeaderSize)); | 659 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 647 __ SmiScale(a6, a5, kDoubleSizeLog2); | 660 __ Daddu(scratch3, array, Operand(FixedDoubleArray::kHeaderSize)); |
| 648 __ Daddu(a6, a6, a7); | 661 __ SmiScale(array_end, length, kDoubleSizeLog2); |
| 649 __ li(a4, Operand(kHoleNanLower32)); | 662 __ Daddu(array_end, array_end, scratch3); |
| 650 __ li(a5, Operand(kHoleNanUpper32)); | |
| 651 // a4: kHoleNanLower32 | |
| 652 // a5: kHoleNanUpper32 | |
| 653 // a6: end of destination FixedDoubleArray, not tagged | |
| 654 // a7: begin of FixedDoubleArray element fields, not tagged | |
| 655 | 663 |
| 664 // Repurpose registers no longer in use. |
| 665 Register hole_lower = elements; |
| 666 Register hole_upper = length; |
| 667 __ li(hole_lower, Operand(kHoleNanLower32)); |
| 668 __ li(hole_upper, Operand(kHoleNanUpper32)); |
| 669 // scratch1: begin of source FixedArray element fields, not tagged |
| 670 // hole_lower: kHoleNanLower32 |
| 671 // hole_upper: kHoleNanUpper32 |
| 672 // array_end: end of destination FixedDoubleArray, not tagged |
| 673 // scratch3: begin of FixedDoubleArray element fields, not tagged |
| 656 __ Branch(&entry); | 674 __ Branch(&entry); |
| 657 | 675 |
| 658 __ bind(&only_change_map); | 676 __ bind(&only_change_map); |
| 659 __ sd(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); | 677 __ sd(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 660 __ RecordWriteField(a2, | 678 __ RecordWriteField(receiver, |
| 661 HeapObject::kMapOffset, | 679 HeapObject::kMapOffset, |
| 662 a3, | 680 target_map, |
| 663 t1, | 681 scratch2, |
| 664 kRAHasNotBeenSaved, | 682 kRAHasNotBeenSaved, |
| 665 kDontSaveFPRegs, | 683 kDontSaveFPRegs, |
| 666 OMIT_REMEMBERED_SET, | 684 OMIT_REMEMBERED_SET, |
| 667 OMIT_SMI_CHECK); | 685 OMIT_SMI_CHECK); |
| 668 __ Branch(&done); | 686 __ Branch(&done); |
| 669 | 687 |
| 670 // Call into runtime if GC is required. | 688 // Call into runtime if GC is required. |
| 671 __ bind(&gc_required); | 689 __ bind(&gc_required); |
| 672 __ pop(ra); | 690 __ pop(ra); |
| 673 __ Branch(fail); | 691 __ Branch(fail); |
| 674 | 692 |
| 675 // Convert and copy elements. | 693 // Convert and copy elements. |
| 676 __ bind(&loop); | 694 __ bind(&loop); |
| 677 __ ld(t1, MemOperand(a3)); | 695 __ ld(scratch2, MemOperand(scratch1)); |
| 678 __ Daddu(a3, a3, kIntSize); | 696 __ Daddu(scratch1, scratch1, kIntSize); |
| 679 // t1: current element | 697 // scratch2: current element |
| 680 __ JumpIfNotSmi(t1, &convert_hole); | 698 __ JumpIfNotSmi(scratch2, &convert_hole); |
| 681 __ SmiUntag(t1); | 699 __ SmiUntag(scratch2); |
| 682 | 700 |
| 683 // Normal smi, convert to double and store. | 701 // Normal smi, convert to double and store. |
| 684 __ mtc1(t1, f0); | 702 __ mtc1(scratch2, f0); |
| 685 __ cvt_d_w(f0, f0); | 703 __ cvt_d_w(f0, f0); |
| 686 __ sdc1(f0, MemOperand(a7)); | 704 __ sdc1(f0, MemOperand(scratch3)); |
| 687 __ Daddu(a7, a7, kDoubleSize); | 705 __ Daddu(scratch3, scratch3, kDoubleSize); |
| 688 | 706 |
| 689 __ Branch(&entry); | 707 __ Branch(&entry); |
| 690 | 708 |
| 691 // Hole found, store the-hole NaN. | 709 // Hole found, store the-hole NaN. |
| 692 __ bind(&convert_hole); | 710 __ bind(&convert_hole); |
| 693 if (FLAG_debug_code) { | 711 if (FLAG_debug_code) { |
| 694 // Restore a "smi-untagged" heap object. | 712 // Restore a "smi-untagged" heap object. |
| 695 __ Or(t1, t1, Operand(1)); | 713 __ Or(scratch2, scratch2, Operand(1)); |
| 696 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 714 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 697 __ Assert(eq, kObjectFoundInSmiOnlyArray, at, Operand(t1)); | 715 __ Assert(eq, kObjectFoundInSmiOnlyArray, at, Operand(scratch2)); |
| 698 } | 716 } |
| 699 __ sw(a4, MemOperand(a7)); // mantissa | 717 // mantissa |
| 700 __ sw(a5, MemOperand(a7, kIntSize)); // exponent | 718 __ sw(hole_lower, MemOperand(scratch3)); |
| 701 __ Daddu(a7, a7, kDoubleSize); | 719 // exponent |
| 720 __ sw(hole_upper, MemOperand(scratch3, kIntSize)); |
| 721 __ Daddu(scratch3, scratch3, kDoubleSize); |
| 702 | 722 |
| 703 __ bind(&entry); | 723 __ bind(&entry); |
| 704 __ Branch(&loop, lt, a7, Operand(a6)); | 724 __ Branch(&loop, lt, scratch3, Operand(array_end)); |
| 705 | 725 |
| 706 __ pop(ra); | 726 __ pop(ra); |
| 707 __ bind(&done); | 727 __ bind(&done); |
| 708 } | 728 } |
| 709 | 729 |
| 710 | 730 |
| 711 void ElementsTransitionGenerator::GenerateDoubleToObject( | 731 void ElementsTransitionGenerator::GenerateDoubleToObject( |
| 712 MacroAssembler* masm, AllocationSiteMode mode, Label* fail) { | 732 MacroAssembler* masm, |
| 713 // ----------- S t a t e ------------- | 733 Register receiver, |
| 714 // -- a0 : value | 734 Register key, |
| 715 // -- a1 : key | 735 Register value, |
| 716 // -- a2 : receiver | 736 Register target_map, |
| 717 // -- ra : return address | 737 AllocationSiteMode mode, |
| 718 // -- a3 : target map, scratch for subsequent call | 738 Label* fail) { |
| 719 // -- a4 : scratch (elements) | 739 // Register ra contains the return address. |
| 720 // ----------------------------------- | |
| 721 Label entry, loop, convert_hole, gc_required, only_change_map; | 740 Label entry, loop, convert_hole, gc_required, only_change_map; |
| 741 Register elements = a4; |
| 742 Register array = a6; |
| 743 Register length = a5; |
| 744 Register scratch = t1; |
| 745 |
| 746 // Verify input registers don't conflict with locals. |
| 747 ASSERT(!AreAliased(receiver, key, value, target_map, |
| 748 elements, array, length, scratch)); |
| 722 if (mode == TRACK_ALLOCATION_SITE) { | 749 if (mode == TRACK_ALLOCATION_SITE) { |
| 723 __ JumpIfJSArrayHasAllocationMemento(a2, a4, fail); | 750 __ JumpIfJSArrayHasAllocationMemento(receiver, elements, fail); |
| 724 } | 751 } |
| 725 | 752 |
| 726 // Check for empty arrays, which only require a map transition and no changes | 753 // Check for empty arrays, which only require a map transition and no changes |
| 727 // to the backing store. | 754 // to the backing store. |
| 728 __ ld(a4, FieldMemOperand(a2, JSObject::kElementsOffset)); | 755 __ ld(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 729 __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex); | 756 __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex); |
| 730 __ Branch(&only_change_map, eq, at, Operand(a4)); | 757 __ Branch(&only_change_map, eq, at, Operand(elements)); |
| 731 | 758 |
| 732 __ MultiPush(a0.bit() | a1.bit() | a2.bit() | a3.bit() | ra.bit()); | 759 __ MultiPush( |
| 760 value.bit() | key.bit() | receiver.bit() | target_map.bit() | ra.bit()); |
| 733 | 761 |
| 734 __ ld(a5, FieldMemOperand(a4, FixedArray::kLengthOffset)); | 762 __ ld(length, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 735 // a4: source FixedArray | 763 // elements: source FixedArray |
| 736 // a5: number of elements (smi-tagged) | 764 // length: number of elements (smi-tagged) |
| 737 | 765 |
| 738 // Allocate new FixedArray. | 766 // Allocate new FixedArray. |
| 739 __ SmiScale(a0, a5, kPointerSizeLog2); | 767 // Re-use value and target_map registers, as they have been saved on the |
| 740 __ Daddu(a0, a0, FixedDoubleArray::kHeaderSize); | 768 // stack. |
| 741 __ Allocate(a0, a6, a7, t1, &gc_required, NO_ALLOCATION_FLAGS); | 769 Register array_size = value; |
| 742 // a6: destination FixedArray, not tagged as heap object | 770 Register allocate_scratch = target_map; |
| 771 __ SmiScale(array_size, length, kPointerSizeLog2); |
| 772 __ Daddu(array_size, array_size, FixedDoubleArray::kHeaderSize); |
| 773 __ Allocate(array_size, array, allocate_scratch, scratch, &gc_required, |
| 774 NO_ALLOCATION_FLAGS); |
| 775 // array: destination FixedArray, not tagged as heap object |
| 743 // Set destination FixedDoubleArray's length and map. | 776 // Set destination FixedDoubleArray's length and map. |
| 744 __ LoadRoot(t1, Heap::kFixedArrayMapRootIndex); | 777 __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex); |
| 745 __ sd(a5, MemOperand(a6, FixedDoubleArray::kLengthOffset)); | 778 __ sd(length, MemOperand(array, FixedDoubleArray::kLengthOffset)); |
| 746 __ sd(t1, MemOperand(a6, HeapObject::kMapOffset)); | 779 __ sd(scratch, MemOperand(array, HeapObject::kMapOffset)); |
| 747 | 780 |
| 748 // Prepare for conversion loop. | 781 // Prepare for conversion loop. |
| 749 __ Daddu(a4, a4, Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4)); | 782 Register src_elements = elements; |
| 750 __ Daddu(a3, a6, Operand(FixedArray::kHeaderSize)); | 783 Register dst_elements = target_map; |
| 751 __ Daddu(a6, a6, Operand(kHeapObjectTag)); | 784 Register dst_end = length; |
| 752 __ SmiScale(a5, a5, kPointerSizeLog2); | 785 Register heap_number_map = scratch; |
| 753 __ Daddu(a5, a3, a5); | 786 __ Daddu(src_elements, src_elements, |
| 754 __ LoadRoot(a7, Heap::kTheHoleValueRootIndex); | 787 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4)); |
| 755 __ LoadRoot(t1, Heap::kHeapNumberMapRootIndex); | 788 __ Daddu(dst_elements, array, Operand(FixedArray::kHeaderSize)); |
| 789 __ Daddu(array, array, Operand(kHeapObjectTag)); |
| 790 __ SmiScale(dst_end, dst_end, kPointerSizeLog2); |
| 791 __ Daddu(dst_end, dst_elements, dst_end); |
| 792 __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); |
| 756 // Using offsetted addresses. | 793 // Using offsetted addresses. |
| 757 // a3: begin of destination FixedArray element fields, not tagged | 794 // dst_elements: begin of destination FixedArray element fields, not tagged |
| 758 // a4: begin of source FixedDoubleArray element fields, not tagged, +4 | 795 // src_elements: begin of source FixedDoubleArray element fields, not tagged, |
| 759 // a5: end of destination FixedArray, not tagged | 796 // points to the exponent |
| 760 // a6: destination FixedArray | 797 // dst_end: end of destination FixedArray, not tagged |
| 761 // a7: the-hole pointer | 798 // array: destination FixedArray |
| 762 // t1: heap number map | 799 // heap_number_map: heap number map |
| 763 __ Branch(&entry); | 800 __ Branch(&entry); |
| 764 | 801 |
| 765 // Call into runtime if GC is required. | 802 // Call into runtime if GC is required. |
| 766 __ bind(&gc_required); | 803 __ bind(&gc_required); |
| 767 __ MultiPop(a0.bit() | a1.bit() | a2.bit() | a3.bit() | ra.bit()); | 804 __ MultiPop( |
| 805 value.bit() | key.bit() | receiver.bit() | target_map.bit() | ra.bit()); |
| 768 | 806 |
| 769 __ Branch(fail); | 807 __ Branch(fail); |
| 770 | 808 |
| 771 __ bind(&loop); | 809 __ bind(&loop); |
| 772 __ lw(a1, MemOperand(a4)); | 810 Register upper_bits = key; |
| 773 __ Daddu(a4, a4, kDoubleSize); | 811 __ lw(upper_bits, MemOperand(src_elements)); |
| 774 // a1: current element's upper 32 bit | 812 __ Daddu(src_elements, src_elements, kDoubleSize); |
| 775 // a4: address of next element's upper 32 bit | 813 // upper_bits: current element's upper 32 bit |
| 814 // src_elements: address of next element's upper 32 bit |
| 776 __ Branch(&convert_hole, eq, a1, Operand(kHoleNanUpper32)); | 815 __ Branch(&convert_hole, eq, a1, Operand(kHoleNanUpper32)); |
| 777 | 816 |
| 778 // Non-hole double, copy value into a heap number. | 817 // Non-hole double, copy value into a heap number. |
| 779 __ AllocateHeapNumber(a2, a0, t2, t1, &gc_required); | 818 Register heap_number = receiver; |
| 780 // a2: new heap number | 819 Register scratch2 = value; |
| 781 __ lw(a0, MemOperand(a4, -12)); | 820 Register scratch3 = t2; |
| 782 __ sw(a0, FieldMemOperand(a2, HeapNumber::kMantissaOffset)); | 821 __ AllocateHeapNumber(heap_number, scratch2, scratch3, heap_number_map, |
| 783 __ sw(a1, FieldMemOperand(a2, HeapNumber::kExponentOffset)); | 822 &gc_required); |
| 784 __ mov(a0, a3); | 823 // heap_number: new heap number |
| 785 __ sd(a2, MemOperand(a3)); | 824 // Load mantissa of current element, src_elements |
| 786 __ Daddu(a3, a3, kPointerSize); | 825 // point to exponent of next element. |
| 787 __ RecordWrite(a6, | 826 __ lw(scratch2, MemOperand(heap_number, -12)); |
| 788 a0, | 827 __ sw(scratch2, FieldMemOperand(heap_number, HeapNumber::kMantissaOffset)); |
| 789 a2, | 828 __ sw(upper_bits, FieldMemOperand(heap_number, HeapNumber::kExponentOffset)); |
| 829 __ mov(scratch2, dst_elements); |
| 830 __ sd(heap_number, MemOperand(dst_elements)); |
| 831 __ Daddu(dst_elements, dst_elements, kPointerSize); |
| 832 __ RecordWrite(array, |
| 833 scratch2, |
| 834 heap_number, |
| 790 kRAHasBeenSaved, | 835 kRAHasBeenSaved, |
| 791 kDontSaveFPRegs, | 836 kDontSaveFPRegs, |
| 792 EMIT_REMEMBERED_SET, | 837 EMIT_REMEMBERED_SET, |
| 793 OMIT_SMI_CHECK); | 838 OMIT_SMI_CHECK); |
| 794 __ Branch(&entry); | 839 __ Branch(&entry); |
| 795 | 840 |
| 796 // Replace the-hole NaN with the-hole pointer. | 841 // Replace the-hole NaN with the-hole pointer. |
| 797 __ bind(&convert_hole); | 842 __ bind(&convert_hole); |
| 798 __ sd(a7, MemOperand(a3)); | 843 __ LoadRoot(scratch2, Heap::kTheHoleValueRootIndex); |
| 799 __ Daddu(a3, a3, kPointerSize); | 844 __ sd(scratch2, MemOperand(dst_elements)); |
| 845 __ Daddu(dst_elements, dst_elements, kPointerSize); |
| 800 | 846 |
| 801 __ bind(&entry); | 847 __ bind(&entry); |
| 802 __ Branch(&loop, lt, a3, Operand(a5)); | 848 __ Branch(&loop, lt, dst_elements, Operand(dst_end)); |
| 803 | 849 |
| 804 __ MultiPop(a2.bit() | a3.bit() | a0.bit() | a1.bit()); | 850 __ MultiPop(receiver.bit() | target_map.bit() | value.bit() | key.bit()); |
| 805 // Replace receiver's backing store with newly created and filled FixedArray. | 851 // Replace receiver's backing store with newly created and filled FixedArray. |
| 806 __ sd(a6, FieldMemOperand(a2, JSObject::kElementsOffset)); | 852 __ sd(array, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 807 __ RecordWriteField(a2, | 853 __ RecordWriteField(receiver, |
| 808 JSObject::kElementsOffset, | 854 JSObject::kElementsOffset, |
| 809 a6, | 855 array, |
| 810 t1, | 856 scratch, |
| 811 kRAHasBeenSaved, | 857 kRAHasBeenSaved, |
| 812 kDontSaveFPRegs, | 858 kDontSaveFPRegs, |
| 813 EMIT_REMEMBERED_SET, | 859 EMIT_REMEMBERED_SET, |
| 814 OMIT_SMI_CHECK); | 860 OMIT_SMI_CHECK); |
| 815 __ pop(ra); | 861 __ pop(ra); |
| 816 | 862 |
| 817 __ bind(&only_change_map); | 863 __ bind(&only_change_map); |
| 818 // Update receiver's map. | 864 // Update receiver's map. |
| 819 __ sd(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); | 865 __ sd(target_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 820 __ RecordWriteField(a2, | 866 __ RecordWriteField(receiver, |
| 821 HeapObject::kMapOffset, | 867 HeapObject::kMapOffset, |
| 822 a3, | 868 target_map, |
| 823 t1, | 869 scratch, |
| 824 kRAHasNotBeenSaved, | 870 kRAHasNotBeenSaved, |
| 825 kDontSaveFPRegs, | 871 kDontSaveFPRegs, |
| 826 OMIT_REMEMBERED_SET, | 872 OMIT_REMEMBERED_SET, |
| 827 OMIT_SMI_CHECK); | 873 OMIT_SMI_CHECK); |
| 828 } | 874 } |
| 829 | 875 |
| 830 | 876 |
| 831 void StringCharLoadGenerator::Generate(MacroAssembler* masm, | 877 void StringCharLoadGenerator::Generate(MacroAssembler* masm, |
| 832 Register string, | 878 Register string, |
| 833 Register index, | 879 Register index, |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1086 patcher.masm()->nop(); // Pad the empty space. | 1132 patcher.masm()->nop(); // Pad the empty space. |
| 1087 } | 1133 } |
| 1088 } | 1134 } |
| 1089 | 1135 |
| 1090 | 1136 |
| 1091 #undef __ | 1137 #undef __ |
| 1092 | 1138 |
| 1093 } } // namespace v8::internal | 1139 } } // namespace v8::internal |
| 1094 | 1140 |
| 1095 #endif // V8_TARGET_ARCH_MIPS64 | 1141 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |