| 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::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...) Expand all 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand all 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...) Expand 10 before | Expand all | Expand 10 after 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 |