OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2615 // There are two words between the frame pointer and the last argument. | 2615 // There are two words between the frame pointer and the last argument. |
2616 // Subtracting from length accounts for one of them, add one more. | 2616 // Subtracting from length accounts for one of them, add one more. |
2617 __ subu(length, length, index); | 2617 __ subu(length, length, index); |
2618 __ Addu(length, length, Operand(1)); | 2618 __ Addu(length, length, Operand(1)); |
2619 __ sll(length, length, kPointerSizeLog2); | 2619 __ sll(length, length, kPointerSizeLog2); |
2620 __ Addu(at, arguments, Operand(length)); | 2620 __ Addu(at, arguments, Operand(length)); |
2621 __ lw(result, MemOperand(at, 0)); | 2621 __ lw(result, MemOperand(at, 0)); |
2622 } | 2622 } |
2623 | 2623 |
2624 | 2624 |
2625 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { | 2625 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
2626 Register elements = ToRegister(instr->elements()); | 2626 Register external_pointer = ToRegister(instr->elements()); |
2627 Register result = ToRegister(instr->result()); | 2627 Register key = no_reg; |
2628 Register scratch = scratch0(); | 2628 ElementsKind elements_kind = instr->elements_kind(); |
2629 Register store_base = scratch; | 2629 bool key_is_constant = instr->key()->IsConstantOperand(); |
2630 int offset = 0; | 2630 int constant_key = 0; |
| 2631 if (key_is_constant) { |
| 2632 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| 2633 if (constant_key & 0xF0000000) { |
| 2634 Abort("array index constant value too big."); |
| 2635 } |
| 2636 } else { |
| 2637 key = ToRegister(instr->key()); |
| 2638 } |
| 2639 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
| 2640 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
| 2641 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 2642 int additional_offset = instr->additional_index() << element_size_shift; |
2631 | 2643 |
2632 if (instr->key()->IsConstantOperand()) { | 2644 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
2633 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); | 2645 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
2634 offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + | 2646 FPURegister result = ToDoubleRegister(instr->result()); |
2635 instr->additional_index()); | 2647 if (key_is_constant) { |
2636 store_base = elements; | 2648 __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); |
| 2649 } else { |
| 2650 __ sll(scratch0(), key, shift_size); |
| 2651 __ Addu(scratch0(), scratch0(), external_pointer); |
| 2652 } |
| 2653 |
| 2654 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
| 2655 __ lwc1(result, MemOperand(scratch0(), additional_offset)); |
| 2656 __ cvt_d_s(result, result); |
| 2657 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
| 2658 __ ldc1(result, MemOperand(scratch0(), additional_offset)); |
| 2659 } |
2637 } else { | 2660 } else { |
2638 Register key = EmitLoadRegister(instr->key(), scratch); | 2661 Register result = ToRegister(instr->result()); |
2639 // Even though the HLoadKeyedFastElement instruction forces the input | 2662 MemOperand mem_operand = PrepareKeyedOperand( |
2640 // representation for the key to be an integer, the input gets replaced | 2663 key, external_pointer, key_is_constant, constant_key, |
2641 // during bound check elimination with the index argument to the bounds | 2664 element_size_shift, shift_size, |
2642 // check, which can be tagged, so that case must be handled here, too. | 2665 instr->additional_index(), additional_offset); |
2643 if (instr->hydrogen()->key()->representation().IsTagged()) { | 2666 switch (elements_kind) { |
2644 __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); | 2667 case EXTERNAL_BYTE_ELEMENTS: |
2645 __ addu(scratch, elements, scratch); | 2668 __ lb(result, mem_operand); |
2646 } else { | 2669 break; |
2647 __ sll(scratch, key, kPointerSizeLog2); | 2670 case EXTERNAL_PIXEL_ELEMENTS: |
2648 __ addu(scratch, elements, scratch); | 2671 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
2649 } | 2672 __ lbu(result, mem_operand); |
2650 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); | 2673 break; |
2651 } | 2674 case EXTERNAL_SHORT_ELEMENTS: |
2652 __ lw(result, FieldMemOperand(store_base, offset)); | 2675 __ lh(result, mem_operand); |
2653 | 2676 break; |
2654 // Check for the hole value. | 2677 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
2655 if (instr->hydrogen()->RequiresHoleCheck()) { | 2678 __ lhu(result, mem_operand); |
2656 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { | 2679 break; |
2657 __ And(scratch, result, Operand(kSmiTagMask)); | 2680 case EXTERNAL_INT_ELEMENTS: |
2658 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); | 2681 __ lw(result, mem_operand); |
2659 } else { | 2682 break; |
2660 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 2683 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
2661 DeoptimizeIf(eq, instr->environment(), result, Operand(scratch)); | 2684 __ lw(result, mem_operand); |
| 2685 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| 2686 DeoptimizeIf(Ugreater_equal, instr->environment(), |
| 2687 result, Operand(0x80000000)); |
| 2688 } |
| 2689 break; |
| 2690 case EXTERNAL_FLOAT_ELEMENTS: |
| 2691 case EXTERNAL_DOUBLE_ELEMENTS: |
| 2692 case FAST_DOUBLE_ELEMENTS: |
| 2693 case FAST_ELEMENTS: |
| 2694 case FAST_SMI_ELEMENTS: |
| 2695 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 2696 case FAST_HOLEY_ELEMENTS: |
| 2697 case FAST_HOLEY_SMI_ELEMENTS: |
| 2698 case DICTIONARY_ELEMENTS: |
| 2699 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 2700 UNREACHABLE(); |
| 2701 break; |
2662 } | 2702 } |
2663 } | 2703 } |
2664 } | 2704 } |
2665 | 2705 |
2666 | 2706 |
2667 void LCodeGen::DoLoadKeyedFastDoubleElement( | 2707 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { |
2668 LLoadKeyedFastDoubleElement* instr) { | |
2669 Register elements = ToRegister(instr->elements()); | 2708 Register elements = ToRegister(instr->elements()); |
2670 bool key_is_constant = instr->key()->IsConstantOperand(); | 2709 bool key_is_constant = instr->key()->IsConstantOperand(); |
2671 Register key = no_reg; | 2710 Register key = no_reg; |
2672 DoubleRegister result = ToDoubleRegister(instr->result()); | 2711 DoubleRegister result = ToDoubleRegister(instr->result()); |
2673 Register scratch = scratch0(); | 2712 Register scratch = scratch0(); |
2674 | 2713 |
2675 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); | 2714 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); |
2676 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) | 2715 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
2677 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 2716 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
2678 int constant_key = 0; | 2717 int constant_key = 0; |
(...skipping 21 matching lines...) Expand all Loading... |
2700 | 2739 |
2701 if (instr->hydrogen()->RequiresHoleCheck()) { | 2740 if (instr->hydrogen()->RequiresHoleCheck()) { |
2702 __ lw(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); | 2741 __ lw(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); |
2703 DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32)); | 2742 DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32)); |
2704 } | 2743 } |
2705 | 2744 |
2706 __ ldc1(result, MemOperand(elements)); | 2745 __ ldc1(result, MemOperand(elements)); |
2707 } | 2746 } |
2708 | 2747 |
2709 | 2748 |
| 2749 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 2750 Register elements = ToRegister(instr->elements()); |
| 2751 Register result = ToRegister(instr->result()); |
| 2752 Register scratch = scratch0(); |
| 2753 Register store_base = scratch; |
| 2754 int offset = 0; |
| 2755 |
| 2756 if (instr->key()->IsConstantOperand()) { |
| 2757 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
| 2758 offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
| 2759 instr->additional_index()); |
| 2760 store_base = elements; |
| 2761 } else { |
| 2762 Register key = EmitLoadRegister(instr->key(), scratch0()); |
| 2763 // Even though the HLoadKeyed instruction forces the input |
| 2764 // representation for the key to be an integer, the input gets replaced |
| 2765 // during bound check elimination with the index argument to the bounds |
| 2766 // check, which can be tagged, so that case must be handled here, too. |
| 2767 if (instr->hydrogen()->key()->representation().IsTagged()) { |
| 2768 __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); |
| 2769 __ addu(scratch, elements, scratch); |
| 2770 } else { |
| 2771 __ sll(scratch, key, kPointerSizeLog2); |
| 2772 __ addu(scratch, elements, scratch); |
| 2773 } |
| 2774 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
| 2775 } |
| 2776 __ lw(result, FieldMemOperand(store_base, offset)); |
| 2777 |
| 2778 // Check for the hole value. |
| 2779 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2780 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
| 2781 __ And(scratch, result, Operand(kSmiTagMask)); |
| 2782 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); |
| 2783 } else { |
| 2784 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
| 2785 DeoptimizeIf(eq, instr->environment(), result, Operand(scratch)); |
| 2786 } |
| 2787 } |
| 2788 } |
| 2789 |
| 2790 |
| 2791 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
| 2792 if (instr->is_external()) { |
| 2793 DoLoadKeyedExternalArray(instr); |
| 2794 } else if (instr->hydrogen()->representation().IsDouble()) { |
| 2795 DoLoadKeyedFixedDoubleArray(instr); |
| 2796 } else { |
| 2797 DoLoadKeyedFixedArray(instr); |
| 2798 } |
| 2799 } |
| 2800 |
| 2801 |
2710 MemOperand LCodeGen::PrepareKeyedOperand(Register key, | 2802 MemOperand LCodeGen::PrepareKeyedOperand(Register key, |
2711 Register base, | 2803 Register base, |
2712 bool key_is_constant, | 2804 bool key_is_constant, |
2713 int constant_key, | 2805 int constant_key, |
2714 int element_size, | 2806 int element_size, |
2715 int shift_size, | 2807 int shift_size, |
2716 int additional_index, | 2808 int additional_index, |
2717 int additional_offset) { | 2809 int additional_offset) { |
2718 if (additional_index != 0 && !key_is_constant) { | 2810 if (additional_index != 0 && !key_is_constant) { |
2719 additional_index *= 1 << (element_size - shift_size); | 2811 additional_index *= 1 << (element_size - shift_size); |
(...skipping 24 matching lines...) Expand all Loading... |
2744 return MemOperand(scratch0()); | 2836 return MemOperand(scratch0()); |
2745 } else { | 2837 } else { |
2746 ASSERT_EQ(-1, shift_size); | 2838 ASSERT_EQ(-1, shift_size); |
2747 __ srl(scratch0(), scratch0(), 1); | 2839 __ srl(scratch0(), scratch0(), 1); |
2748 __ Addu(scratch0(), base, scratch0()); | 2840 __ Addu(scratch0(), base, scratch0()); |
2749 return MemOperand(scratch0()); | 2841 return MemOperand(scratch0()); |
2750 } | 2842 } |
2751 } | 2843 } |
2752 | 2844 |
2753 | 2845 |
2754 void LCodeGen::DoLoadKeyedSpecializedArrayElement( | |
2755 LLoadKeyedSpecializedArrayElement* instr) { | |
2756 Register external_pointer = ToRegister(instr->external_pointer()); | |
2757 Register key = no_reg; | |
2758 ElementsKind elements_kind = instr->elements_kind(); | |
2759 bool key_is_constant = instr->key()->IsConstantOperand(); | |
2760 int constant_key = 0; | |
2761 if (key_is_constant) { | |
2762 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | |
2763 if (constant_key & 0xF0000000) { | |
2764 Abort("array index constant value too big."); | |
2765 } | |
2766 } else { | |
2767 key = ToRegister(instr->key()); | |
2768 } | |
2769 int element_size_shift = ElementsKindToShiftSize(elements_kind); | |
2770 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) | |
2771 ? (element_size_shift - kSmiTagSize) : element_size_shift; | |
2772 int additional_offset = instr->additional_index() << element_size_shift; | |
2773 | |
2774 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | |
2775 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | |
2776 FPURegister result = ToDoubleRegister(instr->result()); | |
2777 if (key_is_constant) { | |
2778 __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); | |
2779 } else { | |
2780 __ sll(scratch0(), key, shift_size); | |
2781 __ Addu(scratch0(), scratch0(), external_pointer); | |
2782 } | |
2783 | |
2784 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | |
2785 __ lwc1(result, MemOperand(scratch0(), additional_offset)); | |
2786 __ cvt_d_s(result, result); | |
2787 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS | |
2788 __ ldc1(result, MemOperand(scratch0(), additional_offset)); | |
2789 } | |
2790 } else { | |
2791 Register result = ToRegister(instr->result()); | |
2792 MemOperand mem_operand = PrepareKeyedOperand( | |
2793 key, external_pointer, key_is_constant, constant_key, | |
2794 element_size_shift, shift_size, | |
2795 instr->additional_index(), additional_offset); | |
2796 switch (elements_kind) { | |
2797 case EXTERNAL_BYTE_ELEMENTS: | |
2798 __ lb(result, mem_operand); | |
2799 break; | |
2800 case EXTERNAL_PIXEL_ELEMENTS: | |
2801 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
2802 __ lbu(result, mem_operand); | |
2803 break; | |
2804 case EXTERNAL_SHORT_ELEMENTS: | |
2805 __ lh(result, mem_operand); | |
2806 break; | |
2807 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
2808 __ lhu(result, mem_operand); | |
2809 break; | |
2810 case EXTERNAL_INT_ELEMENTS: | |
2811 __ lw(result, mem_operand); | |
2812 break; | |
2813 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
2814 __ lw(result, mem_operand); | |
2815 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | |
2816 DeoptimizeIf(Ugreater_equal, instr->environment(), | |
2817 result, Operand(0x80000000)); | |
2818 } | |
2819 break; | |
2820 case EXTERNAL_FLOAT_ELEMENTS: | |
2821 case EXTERNAL_DOUBLE_ELEMENTS: | |
2822 case FAST_DOUBLE_ELEMENTS: | |
2823 case FAST_ELEMENTS: | |
2824 case FAST_SMI_ELEMENTS: | |
2825 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
2826 case FAST_HOLEY_ELEMENTS: | |
2827 case FAST_HOLEY_SMI_ELEMENTS: | |
2828 case DICTIONARY_ELEMENTS: | |
2829 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
2830 UNREACHABLE(); | |
2831 break; | |
2832 } | |
2833 } | |
2834 } | |
2835 | |
2836 | |
2837 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2846 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
2838 ASSERT(ToRegister(instr->object()).is(a1)); | 2847 ASSERT(ToRegister(instr->object()).is(a1)); |
2839 ASSERT(ToRegister(instr->key()).is(a0)); | 2848 ASSERT(ToRegister(instr->key()).is(a0)); |
2840 | 2849 |
2841 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2850 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2842 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2851 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2843 } | 2852 } |
2844 | 2853 |
2845 | 2854 |
2846 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 2855 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
(...skipping 883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3730 Operand(ToRegister(instr->length()))); | 3739 Operand(ToRegister(instr->length()))); |
3731 } else { | 3740 } else { |
3732 DeoptimizeIf(hs, | 3741 DeoptimizeIf(hs, |
3733 instr->environment(), | 3742 instr->environment(), |
3734 ToRegister(instr->index()), | 3743 ToRegister(instr->index()), |
3735 Operand(ToRegister(instr->length()))); | 3744 Operand(ToRegister(instr->length()))); |
3736 } | 3745 } |
3737 } | 3746 } |
3738 | 3747 |
3739 | 3748 |
3740 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { | 3749 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
3741 Register value = ToRegister(instr->value()); | 3750 Register external_pointer = ToRegister(instr->elements()); |
3742 Register elements = ToRegister(instr->object()); | |
3743 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; | |
3744 Register scratch = scratch0(); | |
3745 Register store_base = scratch; | |
3746 int offset = 0; | |
3747 | |
3748 // Do the store. | |
3749 if (instr->key()->IsConstantOperand()) { | |
3750 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | |
3751 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); | |
3752 offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + | |
3753 instr->additional_index()); | |
3754 store_base = elements; | |
3755 } else { | |
3756 // Even though the HLoadKeyedFastElement instruction forces the input | |
3757 // representation for the key to be an integer, the input gets replaced | |
3758 // during bound check elimination with the index argument to the bounds | |
3759 // check, which can be tagged, so that case must be handled here, too. | |
3760 if (instr->hydrogen()->key()->representation().IsTagged()) { | |
3761 __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); | |
3762 __ addu(scratch, elements, scratch); | |
3763 } else { | |
3764 __ sll(scratch, key, kPointerSizeLog2); | |
3765 __ addu(scratch, elements, scratch); | |
3766 } | |
3767 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); | |
3768 } | |
3769 __ sw(value, FieldMemOperand(store_base, offset)); | |
3770 | |
3771 if (instr->hydrogen()->NeedsWriteBarrier()) { | |
3772 HType type = instr->hydrogen()->value()->type(); | |
3773 SmiCheck check_needed = | |
3774 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | |
3775 // Compute address of modified element and store it into key register. | |
3776 __ Addu(key, store_base, Operand(offset - kHeapObjectTag)); | |
3777 __ RecordWrite(elements, | |
3778 key, | |
3779 value, | |
3780 kRAHasBeenSaved, | |
3781 kSaveFPRegs, | |
3782 EMIT_REMEMBERED_SET, | |
3783 check_needed); | |
3784 } | |
3785 } | |
3786 | |
3787 | |
3788 void LCodeGen::DoStoreKeyedFastDoubleElement( | |
3789 LStoreKeyedFastDoubleElement* instr) { | |
3790 DoubleRegister value = ToDoubleRegister(instr->value()); | |
3791 Register elements = ToRegister(instr->elements()); | |
3792 Register key = no_reg; | |
3793 Register scratch = scratch0(); | |
3794 bool key_is_constant = instr->key()->IsConstantOperand(); | |
3795 int constant_key = 0; | |
3796 Label not_nan; | |
3797 | |
3798 // Calculate the effective address of the slot in the array to store the | |
3799 // double value. | |
3800 if (key_is_constant) { | |
3801 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | |
3802 if (constant_key & 0xF0000000) { | |
3803 Abort("array index constant value too big."); | |
3804 } | |
3805 } else { | |
3806 key = ToRegister(instr->key()); | |
3807 } | |
3808 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); | |
3809 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) | |
3810 ? (element_size_shift - kSmiTagSize) : element_size_shift; | |
3811 if (key_is_constant) { | |
3812 __ Addu(scratch, elements, Operand((constant_key << element_size_shift) + | |
3813 FixedDoubleArray::kHeaderSize - kHeapObjectTag)); | |
3814 } else { | |
3815 __ sll(scratch, key, shift_size); | |
3816 __ Addu(scratch, elements, Operand(scratch)); | |
3817 __ Addu(scratch, scratch, | |
3818 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); | |
3819 } | |
3820 | |
3821 if (instr->NeedsCanonicalization()) { | |
3822 Label is_nan; | |
3823 // Check for NaN. All NaNs must be canonicalized. | |
3824 __ BranchF(NULL, &is_nan, eq, value, value); | |
3825 __ Branch(¬_nan); | |
3826 | |
3827 // Only load canonical NaN if the comparison above set the overflow. | |
3828 __ bind(&is_nan); | |
3829 __ Move(value, FixedDoubleArray::canonical_not_the_hole_nan_as_double()); | |
3830 } | |
3831 | |
3832 __ bind(¬_nan); | |
3833 __ sdc1(value, MemOperand(scratch, instr->additional_index() << | |
3834 element_size_shift)); | |
3835 } | |
3836 | |
3837 | |
3838 void LCodeGen::DoStoreKeyedSpecializedArrayElement( | |
3839 LStoreKeyedSpecializedArrayElement* instr) { | |
3840 | |
3841 Register external_pointer = ToRegister(instr->external_pointer()); | |
3842 Register key = no_reg; | 3751 Register key = no_reg; |
3843 ElementsKind elements_kind = instr->elements_kind(); | 3752 ElementsKind elements_kind = instr->elements_kind(); |
3844 bool key_is_constant = instr->key()->IsConstantOperand(); | 3753 bool key_is_constant = instr->key()->IsConstantOperand(); |
3845 int constant_key = 0; | 3754 int constant_key = 0; |
3846 if (key_is_constant) { | 3755 if (key_is_constant) { |
3847 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 3756 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
3848 if (constant_key & 0xF0000000) { | 3757 if (constant_key & 0xF0000000) { |
3849 Abort("array index constant value too big."); | 3758 Abort("array index constant value too big."); |
3850 } | 3759 } |
3851 } else { | 3760 } else { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3902 case FAST_HOLEY_ELEMENTS: | 3811 case FAST_HOLEY_ELEMENTS: |
3903 case FAST_HOLEY_SMI_ELEMENTS: | 3812 case FAST_HOLEY_SMI_ELEMENTS: |
3904 case DICTIONARY_ELEMENTS: | 3813 case DICTIONARY_ELEMENTS: |
3905 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3814 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3906 UNREACHABLE(); | 3815 UNREACHABLE(); |
3907 break; | 3816 break; |
3908 } | 3817 } |
3909 } | 3818 } |
3910 } | 3819 } |
3911 | 3820 |
| 3821 |
| 3822 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { |
| 3823 DoubleRegister value = ToDoubleRegister(instr->value()); |
| 3824 Register elements = ToRegister(instr->elements()); |
| 3825 Register key = no_reg; |
| 3826 Register scratch = scratch0(); |
| 3827 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 3828 int constant_key = 0; |
| 3829 Label not_nan; |
| 3830 |
| 3831 // Calculate the effective address of the slot in the array to store the |
| 3832 // double value. |
| 3833 if (key_is_constant) { |
| 3834 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| 3835 if (constant_key & 0xF0000000) { |
| 3836 Abort("array index constant value too big."); |
| 3837 } |
| 3838 } else { |
| 3839 key = ToRegister(instr->key()); |
| 3840 } |
| 3841 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); |
| 3842 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
| 3843 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 3844 if (key_is_constant) { |
| 3845 __ Addu(scratch, elements, Operand((constant_key << element_size_shift) + |
| 3846 FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| 3847 } else { |
| 3848 __ sll(scratch, key, shift_size); |
| 3849 __ Addu(scratch, elements, Operand(scratch)); |
| 3850 __ Addu(scratch, scratch, |
| 3851 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| 3852 } |
| 3853 |
| 3854 if (instr->NeedsCanonicalization()) { |
| 3855 Label is_nan; |
| 3856 // Check for NaN. All NaNs must be canonicalized. |
| 3857 __ BranchF(NULL, &is_nan, eq, value, value); |
| 3858 __ Branch(¬_nan); |
| 3859 |
| 3860 // Only load canonical NaN if the comparison above set the overflow. |
| 3861 __ bind(&is_nan); |
| 3862 __ Move(value, FixedDoubleArray::canonical_not_the_hole_nan_as_double()); |
| 3863 } |
| 3864 |
| 3865 __ bind(¬_nan); |
| 3866 __ sdc1(value, MemOperand(scratch, instr->additional_index() << |
| 3867 element_size_shift)); |
| 3868 } |
| 3869 |
| 3870 |
| 3871 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
| 3872 Register value = ToRegister(instr->value()); |
| 3873 Register elements = ToRegister(instr->elements()); |
| 3874 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) |
| 3875 : no_reg; |
| 3876 Register scratch = scratch0(); |
| 3877 Register store_base = scratch; |
| 3878 int offset = 0; |
| 3879 |
| 3880 // Do the store. |
| 3881 if (instr->key()->IsConstantOperand()) { |
| 3882 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 3883 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
| 3884 offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
| 3885 instr->additional_index()); |
| 3886 store_base = elements; |
| 3887 } else { |
| 3888 // Even though the HLoadKeyed instruction forces the input |
| 3889 // representation for the key to be an integer, the input gets replaced |
| 3890 // during bound check elimination with the index argument to the bounds |
| 3891 // check, which can be tagged, so that case must be handled here, too. |
| 3892 if (instr->hydrogen()->key()->representation().IsTagged()) { |
| 3893 __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); |
| 3894 __ addu(scratch, elements, scratch); |
| 3895 } else { |
| 3896 __ sll(scratch, key, kPointerSizeLog2); |
| 3897 __ addu(scratch, elements, scratch); |
| 3898 } |
| 3899 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
| 3900 } |
| 3901 __ sw(value, FieldMemOperand(store_base, offset)); |
| 3902 |
| 3903 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3904 HType type = instr->hydrogen()->value()->type(); |
| 3905 SmiCheck check_needed = |
| 3906 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 3907 // Compute address of modified element and store it into key register. |
| 3908 __ Addu(key, store_base, Operand(offset - kHeapObjectTag)); |
| 3909 __ RecordWrite(elements, |
| 3910 key, |
| 3911 value, |
| 3912 kRAHasBeenSaved, |
| 3913 kSaveFPRegs, |
| 3914 EMIT_REMEMBERED_SET, |
| 3915 check_needed); |
| 3916 } |
| 3917 } |
| 3918 |
| 3919 |
| 3920 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { |
| 3921 // By cases: external, fast double |
| 3922 if (instr->is_external()) { |
| 3923 DoStoreKeyedExternalArray(instr); |
| 3924 } else if (instr->hydrogen()->value()->representation().IsDouble()) { |
| 3925 DoStoreKeyedFixedDoubleArray(instr); |
| 3926 } else { |
| 3927 DoStoreKeyedFixedArray(instr); |
| 3928 } |
| 3929 } |
| 3930 |
| 3931 |
3912 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 3932 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
3913 ASSERT(ToRegister(instr->object()).is(a2)); | 3933 ASSERT(ToRegister(instr->object()).is(a2)); |
3914 ASSERT(ToRegister(instr->key()).is(a1)); | 3934 ASSERT(ToRegister(instr->key()).is(a1)); |
3915 ASSERT(ToRegister(instr->value()).is(a0)); | 3935 ASSERT(ToRegister(instr->value()).is(a0)); |
3916 | 3936 |
3917 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3937 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
3918 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3938 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
3919 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3939 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
3920 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3940 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3921 } | 3941 } |
(...skipping 1518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5440 __ Subu(scratch, result, scratch); | 5460 __ Subu(scratch, result, scratch); |
5441 __ lw(result, FieldMemOperand(scratch, | 5461 __ lw(result, FieldMemOperand(scratch, |
5442 FixedArray::kHeaderSize - kPointerSize)); | 5462 FixedArray::kHeaderSize - kPointerSize)); |
5443 __ bind(&done); | 5463 __ bind(&done); |
5444 } | 5464 } |
5445 | 5465 |
5446 | 5466 |
5447 #undef __ | 5467 #undef __ |
5448 | 5468 |
5449 } } // namespace v8::internal | 5469 } } // namespace v8::internal |
OLD | NEW |