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...) 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::DoLoadKeyedExternal(LLoadKeyed* instr) { |
2626 Register elements = ToRegister(instr->elements()); | |
2627 Register result = ToRegister(instr->result()); | |
2628 Register scratch = scratch0(); | |
2629 Register store_base = scratch; | |
2630 int offset = 0; | |
2631 | |
2632 if (instr->key()->IsConstantOperand()) { | |
2633 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); | |
2634 offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + | |
2635 instr->additional_index()); | |
2636 store_base = elements; | |
2637 } else { | |
2638 Register key = EmitLoadRegister(instr->key(), scratch); | |
2639 // Even though the HLoadKeyedFastElement instruction forces the input | |
2640 // representation for the key to be an integer, the input gets replaced | |
2641 // during bound check elimination with the index argument to the bounds | |
2642 // check, which can be tagged, so that case must be handled here, too. | |
2643 if (instr->hydrogen()->key()->representation().IsTagged()) { | |
2644 __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); | |
2645 __ addu(scratch, elements, scratch); | |
2646 } else { | |
2647 __ sll(scratch, key, kPointerSizeLog2); | |
2648 __ addu(scratch, elements, scratch); | |
2649 } | |
2650 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); | |
2651 } | |
2652 __ lw(result, FieldMemOperand(store_base, offset)); | |
2653 | |
2654 // Check for the hole value. | |
2655 if (instr->hydrogen()->RequiresHoleCheck()) { | |
2656 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { | |
2657 __ And(scratch, result, Operand(kSmiTagMask)); | |
2658 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); | |
2659 } else { | |
2660 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | |
2661 DeoptimizeIf(eq, instr->environment(), result, Operand(scratch)); | |
2662 } | |
2663 } | |
2664 } | |
2665 | |
2666 | |
2667 void LCodeGen::DoLoadKeyedFastDoubleElement( | |
2668 LLoadKeyedFastDoubleElement* instr) { | |
2669 Register elements = ToRegister(instr->elements()); | |
2670 bool key_is_constant = instr->key()->IsConstantOperand(); | |
2671 Register key = no_reg; | |
2672 DoubleRegister result = ToDoubleRegister(instr->result()); | |
2673 Register scratch = scratch0(); | |
2674 | |
2675 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); | |
2676 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) | |
2677 ? (element_size_shift - kSmiTagSize) : element_size_shift; | |
2678 int constant_key = 0; | |
2679 if (key_is_constant) { | |
2680 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | |
2681 if (constant_key & 0xF0000000) { | |
2682 Abort("array index constant value too big."); | |
2683 } | |
2684 } else { | |
2685 key = ToRegister(instr->key()); | |
2686 } | |
2687 | |
2688 if (key_is_constant) { | |
2689 __ Addu(elements, elements, | |
2690 Operand(((constant_key + instr->additional_index()) << | |
2691 element_size_shift) + | |
2692 FixedDoubleArray::kHeaderSize - kHeapObjectTag)); | |
2693 } else { | |
2694 __ sll(scratch, key, shift_size); | |
2695 __ Addu(elements, elements, Operand(scratch)); | |
2696 __ Addu(elements, elements, | |
2697 Operand((FixedDoubleArray::kHeaderSize - kHeapObjectTag) + | |
2698 (instr->additional_index() << element_size_shift))); | |
2699 } | |
2700 | |
2701 if (instr->hydrogen()->RequiresHoleCheck()) { | |
2702 __ lw(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); | |
2703 DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32)); | |
2704 } | |
2705 | |
2706 __ ldc1(result, MemOperand(elements)); | |
2707 } | |
2708 | |
2709 | |
2710 MemOperand LCodeGen::PrepareKeyedOperand(Register key, | |
2711 Register base, | |
2712 bool key_is_constant, | |
2713 int constant_key, | |
2714 int element_size, | |
2715 int shift_size, | |
2716 int additional_index, | |
2717 int additional_offset) { | |
2718 if (additional_index != 0 && !key_is_constant) { | |
2719 additional_index *= 1 << (element_size - shift_size); | |
2720 __ Addu(scratch0(), key, Operand(additional_index)); | |
2721 } | |
2722 | |
2723 if (key_is_constant) { | |
2724 return MemOperand(base, | |
2725 (constant_key << element_size) + additional_offset); | |
2726 } | |
2727 | |
2728 if (additional_index == 0) { | |
2729 if (shift_size >= 0) { | |
2730 __ sll(scratch0(), key, shift_size); | |
2731 __ Addu(scratch0(), base, scratch0()); | |
2732 return MemOperand(scratch0()); | |
2733 } else { | |
2734 ASSERT_EQ(-1, shift_size); | |
2735 __ srl(scratch0(), key, 1); | |
2736 __ Addu(scratch0(), base, scratch0()); | |
2737 return MemOperand(scratch0()); | |
2738 } | |
2739 } | |
2740 | |
2741 if (shift_size >= 0) { | |
2742 __ sll(scratch0(), scratch0(), shift_size); | |
2743 __ Addu(scratch0(), base, scratch0()); | |
2744 return MemOperand(scratch0()); | |
2745 } else { | |
2746 ASSERT_EQ(-1, shift_size); | |
2747 __ srl(scratch0(), scratch0(), 1); | |
2748 __ Addu(scratch0(), base, scratch0()); | |
2749 return MemOperand(scratch0()); | |
2750 } | |
2751 } | |
2752 | |
2753 | |
2754 void LCodeGen::DoLoadKeyedSpecializedArrayElement( | |
2755 LLoadKeyedSpecializedArrayElement* instr) { | |
2756 Register external_pointer = ToRegister(instr->external_pointer()); | 2626 Register external_pointer = ToRegister(instr->external_pointer()); |
2757 Register key = no_reg; | 2627 Register key = no_reg; |
2758 ElementsKind elements_kind = instr->elements_kind(); | 2628 ElementsKind elements_kind = instr->elements_kind(); |
2759 bool key_is_constant = instr->key()->IsConstantOperand(); | 2629 bool key_is_constant = instr->key()->IsConstantOperand(); |
2760 int constant_key = 0; | 2630 int constant_key = 0; |
2761 if (key_is_constant) { | 2631 if (key_is_constant) { |
2762 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 2632 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
2763 if (constant_key & 0xF0000000) { | 2633 if (constant_key & 0xF0000000) { |
2764 Abort("array index constant value too big."); | 2634 Abort("array index constant value too big."); |
2765 } | 2635 } |
2766 } else { | 2636 } else { |
2767 key = ToRegister(instr->key()); | 2637 key = ToRegister(instr->key()); |
2768 } | 2638 } |
2769 int element_size_shift = ElementsKindToShiftSize(elements_kind); | 2639 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
2770 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) | 2640 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
2771 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 2641 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
2772 int additional_offset = instr->additional_index() << element_size_shift; | 2642 int additional_offset = instr->additional_index() << element_size_shift; |
2773 | 2643 |
2774 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 2644 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
2775 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 2645 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
2776 FPURegister result = ToDoubleRegister(instr->result()); | 2646 FPURegister result = ToDoubleRegister(instr->result()); |
2777 if (key_is_constant) { | 2647 if (key_is_constant) { |
2778 __ Addu(scratch0(), external_pointer, constant_key << element_size_shift); | 2648 __ Addu(scratch0(), external_pointer, |
| 2649 constant_key << element_size_shift); |
2779 } else { | 2650 } else { |
2780 __ sll(scratch0(), key, shift_size); | 2651 __ sll(scratch0(), key, shift_size); |
2781 __ Addu(scratch0(), scratch0(), external_pointer); | 2652 __ Addu(scratch0(), scratch0(), external_pointer); |
2782 } | 2653 } |
2783 | 2654 |
2784 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | 2655 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
2785 __ lwc1(result, MemOperand(scratch0(), additional_offset)); | 2656 __ lwc1(result, MemOperand(scratch0(), additional_offset)); |
2786 __ cvt_d_s(result, result); | 2657 __ cvt_d_s(result, result); |
2787 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS | 2658 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
2788 __ ldc1(result, MemOperand(scratch0(), additional_offset)); | 2659 __ ldc1(result, MemOperand(scratch0(), additional_offset)); |
(...skipping 18 matching lines...) Loading... |
2807 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 2678 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
2808 __ lhu(result, mem_operand); | 2679 __ lhu(result, mem_operand); |
2809 break; | 2680 break; |
2810 case EXTERNAL_INT_ELEMENTS: | 2681 case EXTERNAL_INT_ELEMENTS: |
2811 __ lw(result, mem_operand); | 2682 __ lw(result, mem_operand); |
2812 break; | 2683 break; |
2813 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 2684 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
2814 __ lw(result, mem_operand); | 2685 __ lw(result, mem_operand); |
2815 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 2686 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
2816 DeoptimizeIf(Ugreater_equal, instr->environment(), | 2687 DeoptimizeIf(Ugreater_equal, instr->environment(), |
2817 result, Operand(0x80000000)); | 2688 result, Operand(0x80000000)); |
2818 } | 2689 } |
2819 break; | 2690 break; |
2820 case EXTERNAL_FLOAT_ELEMENTS: | 2691 case EXTERNAL_FLOAT_ELEMENTS: |
2821 case EXTERNAL_DOUBLE_ELEMENTS: | 2692 case EXTERNAL_DOUBLE_ELEMENTS: |
2822 case FAST_DOUBLE_ELEMENTS: | 2693 case FAST_DOUBLE_ELEMENTS: |
2823 case FAST_ELEMENTS: | 2694 case FAST_ELEMENTS: |
2824 case FAST_SMI_ELEMENTS: | 2695 case FAST_SMI_ELEMENTS: |
2825 case FAST_HOLEY_DOUBLE_ELEMENTS: | 2696 case FAST_HOLEY_DOUBLE_ELEMENTS: |
2826 case FAST_HOLEY_ELEMENTS: | 2697 case FAST_HOLEY_ELEMENTS: |
2827 case FAST_HOLEY_SMI_ELEMENTS: | 2698 case FAST_HOLEY_SMI_ELEMENTS: |
2828 case DICTIONARY_ELEMENTS: | 2699 case DICTIONARY_ELEMENTS: |
2829 case NON_STRICT_ARGUMENTS_ELEMENTS: | 2700 case NON_STRICT_ARGUMENTS_ELEMENTS: |
2830 UNREACHABLE(); | 2701 UNREACHABLE(); |
2831 break; | 2702 break; |
2832 } | 2703 } |
2833 } | 2704 } |
2834 } | 2705 } |
2835 | 2706 |
| 2707 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
| 2708 if (instr->is_external()) { |
| 2709 DoLoadKeyedExternal(instr); |
| 2710 } else if (instr->hydrogen()->representation().IsDouble()) { |
| 2711 Register elements = ToRegister(instr->elements()); |
| 2712 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 2713 Register key = no_reg; |
| 2714 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 2715 Register scratch = scratch0(); |
| 2716 |
| 2717 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); |
| 2718 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
| 2719 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 2720 int constant_key = 0; |
| 2721 if (key_is_constant) { |
| 2722 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| 2723 if (constant_key & 0xF0000000) { |
| 2724 Abort("array index constant value too big."); |
| 2725 } |
| 2726 } else { |
| 2727 key = ToRegister(instr->key()); |
| 2728 } |
| 2729 |
| 2730 if (key_is_constant) { |
| 2731 __ Addu(elements, elements, |
| 2732 Operand(((constant_key + instr->additional_index()) << |
| 2733 element_size_shift) + |
| 2734 FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| 2735 } else { |
| 2736 __ sll(scratch, key, shift_size); |
| 2737 __ Addu(elements, elements, Operand(scratch)); |
| 2738 __ Addu(elements, elements, |
| 2739 Operand((FixedDoubleArray::kHeaderSize - kHeapObjectTag) + |
| 2740 (instr->additional_index() << element_size_shift))); |
| 2741 } |
| 2742 |
| 2743 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2744 __ lw(scratch, MemOperand(elements, sizeof(kHoleNanLower32))); |
| 2745 DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32)); |
| 2746 } |
| 2747 |
| 2748 __ ldc1(result, MemOperand(elements)); |
| 2749 } else { |
| 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(), scratch); |
| 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 |
| 2792 MemOperand LCodeGen::PrepareKeyedOperand(Register key, |
| 2793 Register base, |
| 2794 bool key_is_constant, |
| 2795 int constant_key, |
| 2796 int element_size, |
| 2797 int shift_size, |
| 2798 int additional_index, |
| 2799 int additional_offset) { |
| 2800 if (additional_index != 0 && !key_is_constant) { |
| 2801 additional_index *= 1 << (element_size - shift_size); |
| 2802 __ Addu(scratch0(), key, Operand(additional_index)); |
| 2803 } |
| 2804 |
| 2805 if (key_is_constant) { |
| 2806 return MemOperand(base, |
| 2807 (constant_key << element_size) + additional_offset); |
| 2808 } |
| 2809 |
| 2810 if (additional_index == 0) { |
| 2811 if (shift_size >= 0) { |
| 2812 __ sll(scratch0(), key, shift_size); |
| 2813 __ Addu(scratch0(), base, scratch0()); |
| 2814 return MemOperand(scratch0()); |
| 2815 } else { |
| 2816 ASSERT_EQ(-1, shift_size); |
| 2817 __ srl(scratch0(), key, 1); |
| 2818 __ Addu(scratch0(), base, scratch0()); |
| 2819 return MemOperand(scratch0()); |
| 2820 } |
| 2821 } |
| 2822 |
| 2823 if (shift_size >= 0) { |
| 2824 __ sll(scratch0(), scratch0(), shift_size); |
| 2825 __ Addu(scratch0(), base, scratch0()); |
| 2826 return MemOperand(scratch0()); |
| 2827 } else { |
| 2828 ASSERT_EQ(-1, shift_size); |
| 2829 __ srl(scratch0(), scratch0(), 1); |
| 2830 __ Addu(scratch0(), base, scratch0()); |
| 2831 return MemOperand(scratch0()); |
| 2832 } |
| 2833 } |
| 2834 |
2836 | 2835 |
2837 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2836 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
2838 ASSERT(ToRegister(instr->object()).is(a1)); | 2837 ASSERT(ToRegister(instr->object()).is(a1)); |
2839 ASSERT(ToRegister(instr->key()).is(a0)); | 2838 ASSERT(ToRegister(instr->key()).is(a0)); |
2840 | 2839 |
2841 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2840 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2842 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2841 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2843 } | 2842 } |
2844 | 2843 |
2845 | 2844 |
(...skipping 884 matching lines...) Loading... |
3730 Operand(ToRegister(instr->length()))); | 3729 Operand(ToRegister(instr->length()))); |
3731 } else { | 3730 } else { |
3732 DeoptimizeIf(hs, | 3731 DeoptimizeIf(hs, |
3733 instr->environment(), | 3732 instr->environment(), |
3734 ToRegister(instr->index()), | 3733 ToRegister(instr->index()), |
3735 Operand(ToRegister(instr->length()))); | 3734 Operand(ToRegister(instr->length()))); |
3736 } | 3735 } |
3737 } | 3736 } |
3738 | 3737 |
3739 | 3738 |
3740 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { | 3739 void LCodeGen::DoStoreKeyedExternal(LStoreKeyed* instr) { |
3741 Register value = ToRegister(instr->value()); | |
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()); | 3740 Register external_pointer = ToRegister(instr->external_pointer()); |
3842 Register key = no_reg; | 3741 Register key = no_reg; |
3843 ElementsKind elements_kind = instr->elements_kind(); | 3742 ElementsKind elements_kind = instr->elements_kind(); |
3844 bool key_is_constant = instr->key()->IsConstantOperand(); | 3743 bool key_is_constant = instr->key()->IsConstantOperand(); |
3845 int constant_key = 0; | 3744 int constant_key = 0; |
3846 if (key_is_constant) { | 3745 if (key_is_constant) { |
3847 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 3746 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
3848 if (constant_key & 0xF0000000) { | 3747 if (constant_key & 0xF0000000) { |
3849 Abort("array index constant value too big."); | 3748 Abort("array index constant value too big."); |
3850 } | 3749 } |
3851 } else { | 3750 } else { |
3852 key = ToRegister(instr->key()); | 3751 key = ToRegister(instr->key()); |
3853 } | 3752 } |
3854 int element_size_shift = ElementsKindToShiftSize(elements_kind); | 3753 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
3855 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) | 3754 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
3856 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 3755 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
3857 int additional_offset = instr->additional_index() << element_size_shift; | 3756 int additional_offset = instr->additional_index() << element_size_shift; |
3858 | 3757 |
3859 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 3758 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || |
3860 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 3759 elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
3861 FPURegister value(ToDoubleRegister(instr->value())); | 3760 FPURegister value(ToDoubleRegister(instr->value())); |
3862 if (key_is_constant) { | 3761 if (key_is_constant) { |
3863 __ Addu(scratch0(), external_pointer, constant_key << | 3762 __ Addu(scratch0(), external_pointer, constant_key << |
3864 element_size_shift); | 3763 element_size_shift); |
3865 } else { | 3764 } else { |
3866 __ sll(scratch0(), key, shift_size); | 3765 __ sll(scratch0(), key, shift_size); |
3867 __ Addu(scratch0(), scratch0(), external_pointer); | 3766 __ Addu(scratch0(), scratch0(), external_pointer); |
3868 } | 3767 } |
3869 | 3768 |
3870 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | 3769 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
3871 __ cvt_s_d(double_scratch0(), value); | 3770 __ cvt_s_d(double_scratch0(), value); |
3872 __ swc1(double_scratch0(), MemOperand(scratch0(), additional_offset)); | 3771 __ swc1(double_scratch0(), MemOperand(scratch0(), additional_offset)); |
3873 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS | 3772 } else { // i.e. elements_kind == EXTERNAL_DOUBLE_ELEMENTS |
3874 __ sdc1(value, MemOperand(scratch0(), additional_offset)); | 3773 __ sdc1(value, MemOperand(scratch0(), additional_offset)); |
(...skipping 27 matching lines...) Loading... |
3902 case FAST_HOLEY_ELEMENTS: | 3801 case FAST_HOLEY_ELEMENTS: |
3903 case FAST_HOLEY_SMI_ELEMENTS: | 3802 case FAST_HOLEY_SMI_ELEMENTS: |
3904 case DICTIONARY_ELEMENTS: | 3803 case DICTIONARY_ELEMENTS: |
3905 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3804 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3906 UNREACHABLE(); | 3805 UNREACHABLE(); |
3907 break; | 3806 break; |
3908 } | 3807 } |
3909 } | 3808 } |
3910 } | 3809 } |
3911 | 3810 |
| 3811 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { |
| 3812 // By cases: external, fast double, fast |
| 3813 if (instr->is_external()) { |
| 3814 DoStoreKeyedEternal(instr); |
| 3815 } else if (instr->hydrogen()->value()->representation().IsDouble()) { |
| 3816 DoubleRegister value = ToDoubleRegister(instr->value()); |
| 3817 Register elements = ToRegister(instr->elements()); |
| 3818 Register key = no_reg; |
| 3819 Register scratch = scratch0(); |
| 3820 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 3821 int constant_key = 0; |
| 3822 Label not_nan; |
| 3823 |
| 3824 // Calculate the effective address of the slot in the array to store the |
| 3825 // double value. |
| 3826 if (key_is_constant) { |
| 3827 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
| 3828 if (constant_key & 0xF0000000) { |
| 3829 Abort("array index constant value too big."); |
| 3830 } |
| 3831 } else { |
| 3832 key = ToRegister(instr->key()); |
| 3833 } |
| 3834 int element_size_shift = ElementsKindToShiftSize(FAST_DOUBLE_ELEMENTS); |
| 3835 int shift_size = (instr->hydrogen()->key()->representation().IsTagged()) |
| 3836 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 3837 if (key_is_constant) { |
| 3838 __ Addu(scratch, elements, |
| 3839 Operand((constant_key << element_size_shift) + |
| 3840 FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| 3841 } else { |
| 3842 __ sll(scratch, key, shift_size); |
| 3843 __ Addu(scratch, elements, Operand(scratch)); |
| 3844 __ Addu(scratch, scratch, |
| 3845 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| 3846 } |
| 3847 |
| 3848 if (instr->NeedsCanonicalization()) { |
| 3849 Label is_nan; |
| 3850 // Check for NaN. All NaNs must be canonicalized. |
| 3851 __ BranchF(NULL, &is_nan, eq, value, value); |
| 3852 __ Branch(¬_nan); |
| 3853 |
| 3854 // Only load canonical NaN if the comparison above set the overflow. |
| 3855 __ bind(&is_nan); |
| 3856 __ Move(value, FixedDoubleArray::canonical_not_the_hole_nan_as_double()); |
| 3857 } |
| 3858 |
| 3859 __ bind(¬_nan); |
| 3860 __ sdc1(value, MemOperand(scratch, instr->additional_index() << |
| 3861 element_size_shift)); |
| 3862 } else { |
| 3863 Register value = ToRegister(instr->value()); |
| 3864 Register elements = ToRegister(instr->object()); |
| 3865 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) |
| 3866 : no_reg; |
| 3867 Register scratch = scratch0(); |
| 3868 Register store_base = scratch; |
| 3869 int offset = 0; |
| 3870 |
| 3871 // Do the store. |
| 3872 if (instr->key()->IsConstantOperand()) { |
| 3873 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 3874 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
| 3875 offset = FixedArray::OffsetOfElementAt(ToInteger32(const_operand) + |
| 3876 instr->additional_index()); |
| 3877 store_base = elements; |
| 3878 } else { |
| 3879 // Even though the HLoadKeyed instruction forces the input |
| 3880 // representation for the key to be an integer, the input gets replaced |
| 3881 // during bound check elimination with the index argument to the bounds |
| 3882 // check, which can be tagged, so that case must be handled here, too. |
| 3883 if (instr->hydrogen()->key()->representation().IsTagged()) { |
| 3884 __ sll(scratch, key, kPointerSizeLog2 - kSmiTagSize); |
| 3885 __ addu(scratch, elements, scratch); |
| 3886 } else { |
| 3887 __ sll(scratch, key, kPointerSizeLog2); |
| 3888 __ addu(scratch, elements, scratch); |
| 3889 } |
| 3890 offset = FixedArray::OffsetOfElementAt(instr->additional_index()); |
| 3891 } |
| 3892 __ sw(value, FieldMemOperand(store_base, offset)); |
| 3893 |
| 3894 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3895 HType type = instr->hydrogen()->value()->type(); |
| 3896 SmiCheck check_needed = |
| 3897 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 3898 // Compute address of modified element and store it into key register. |
| 3899 __ Addu(key, store_base, Operand(offset - kHeapObjectTag)); |
| 3900 __ RecordWrite(elements, |
| 3901 key, |
| 3902 value, |
| 3903 kRAHasBeenSaved, |
| 3904 kSaveFPRegs, |
| 3905 EMIT_REMEMBERED_SET, |
| 3906 check_needed); |
| 3907 } |
| 3908 } |
| 3909 } |
| 3910 |
| 3911 |
3912 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 3912 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
3913 ASSERT(ToRegister(instr->object()).is(a2)); | 3913 ASSERT(ToRegister(instr->object()).is(a2)); |
3914 ASSERT(ToRegister(instr->key()).is(a1)); | 3914 ASSERT(ToRegister(instr->key()).is(a1)); |
3915 ASSERT(ToRegister(instr->value()).is(a0)); | 3915 ASSERT(ToRegister(instr->value()).is(a0)); |
3916 | 3916 |
3917 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3917 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
3918 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3918 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
3919 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3919 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
3920 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3920 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3921 } | 3921 } |
(...skipping 1517 matching lines...) Loading... |
5439 __ Subu(scratch, result, scratch); | 5439 __ Subu(scratch, result, scratch); |
5440 __ lw(result, FieldMemOperand(scratch, | 5440 __ lw(result, FieldMemOperand(scratch, |
5441 FixedArray::kHeaderSize - kPointerSize)); | 5441 FixedArray::kHeaderSize - kPointerSize)); |
5442 __ bind(&done); | 5442 __ bind(&done); |
5443 } | 5443 } |
5444 | 5444 |
5445 | 5445 |
5446 #undef __ | 5446 #undef __ |
5447 | 5447 |
5448 } } // namespace v8::internal | 5448 } } // namespace v8::internal |
OLD | NEW |