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 2594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2605 // Subtracting from length accounts for one of them add one more. | 2605 // Subtracting from length accounts for one of them add one more. |
2606 if (instr->index()->IsRegister()) { | 2606 if (instr->index()->IsRegister()) { |
2607 __ subl(length, ToRegister(instr->index())); | 2607 __ subl(length, ToRegister(instr->index())); |
2608 } else { | 2608 } else { |
2609 __ subl(length, ToOperand(instr->index())); | 2609 __ subl(length, ToOperand(instr->index())); |
2610 } | 2610 } |
2611 __ movq(result, Operand(arguments, length, times_pointer_size, kPointerSize)); | 2611 __ movq(result, Operand(arguments, length, times_pointer_size, kPointerSize)); |
2612 } | 2612 } |
2613 | 2613 |
2614 | 2614 |
2615 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { | 2615 void LCodeGen::DoLoadKeyedExternal(LLoadKeyed* instr) { |
2616 Register result = ToRegister(instr->result()); | |
2617 LOperand* key = instr->key(); | |
2618 if (!key->IsConstantOperand()) { | |
2619 Register key_reg = ToRegister(key); | |
2620 // Even though the HLoad/StoreKeyedFastElement instructions force the input | |
2621 // representation for the key to be an integer, the input gets replaced | |
2622 // during bound check elimination with the index argument to the bounds | |
2623 // check, which can be tagged, so that case must be handled here, too. | |
2624 if (instr->hydrogen()->key()->representation().IsTagged()) { | |
2625 __ SmiToInteger64(key_reg, key_reg); | |
2626 } else if (instr->hydrogen()->IsDehoisted()) { | |
2627 // Sign extend key because it could be a 32 bit negative value | |
2628 // and the dehoisted address computation happens in 64 bits | |
2629 __ movsxlq(key_reg, key_reg); | |
2630 } | |
2631 } | |
2632 | |
2633 // Load the result. | |
2634 __ movq(result, | |
2635 BuildFastArrayOperand(instr->elements(), | |
2636 key, | |
2637 FAST_ELEMENTS, | |
2638 FixedArray::kHeaderSize - kHeapObjectTag, | |
2639 instr->additional_index())); | |
2640 | |
2641 // Check for the hole value. | |
2642 if (instr->hydrogen()->RequiresHoleCheck()) { | |
2643 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { | |
2644 Condition smi = __ CheckSmi(result); | |
2645 DeoptimizeIf(NegateCondition(smi), instr->environment()); | |
2646 } else { | |
2647 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | |
2648 DeoptimizeIf(equal, instr->environment()); | |
2649 } | |
2650 } | |
2651 } | |
2652 | |
2653 | |
2654 void LCodeGen::DoLoadKeyedFastDoubleElement( | |
2655 LLoadKeyedFastDoubleElement* instr) { | |
2656 XMMRegister result(ToDoubleRegister(instr->result())); | |
2657 LOperand* key = instr->key(); | |
2658 if (!key->IsConstantOperand()) { | |
2659 Register key_reg = ToRegister(key); | |
2660 // Even though the HLoad/StoreKeyedFastElement instructions force the input | |
2661 // representation for the key to be an integer, the input gets replaced | |
2662 // during bound check elimination with the index argument to the bounds | |
2663 // check, which can be tagged, so that case must be handled here, too. | |
2664 if (instr->hydrogen()->key()->representation().IsTagged()) { | |
2665 __ SmiToInteger64(key_reg, key_reg); | |
2666 } else if (instr->hydrogen()->IsDehoisted()) { | |
2667 // Sign extend key because it could be a 32 bit negative value | |
2668 // and the dehoisted address computation happens in 64 bits | |
2669 __ movsxlq(key_reg, key_reg); | |
2670 } | |
2671 } | |
2672 | |
2673 if (instr->hydrogen()->RequiresHoleCheck()) { | |
2674 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + | |
2675 sizeof(kHoleNanLower32); | |
2676 Operand hole_check_operand = BuildFastArrayOperand( | |
2677 instr->elements(), | |
2678 key, | |
2679 FAST_DOUBLE_ELEMENTS, | |
2680 offset, | |
2681 instr->additional_index()); | |
2682 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); | |
2683 DeoptimizeIf(equal, instr->environment()); | |
2684 } | |
2685 | |
2686 Operand double_load_operand = BuildFastArrayOperand( | |
2687 instr->elements(), | |
2688 key, | |
2689 FAST_DOUBLE_ELEMENTS, | |
2690 FixedDoubleArray::kHeaderSize - kHeapObjectTag, | |
2691 instr->additional_index()); | |
2692 __ movsd(result, double_load_operand); | |
2693 } | |
2694 | |
2695 | |
2696 Operand LCodeGen::BuildFastArrayOperand( | |
2697 LOperand* elements_pointer, | |
2698 LOperand* key, | |
2699 ElementsKind elements_kind, | |
2700 uint32_t offset, | |
2701 uint32_t additional_index) { | |
2702 Register elements_pointer_reg = ToRegister(elements_pointer); | |
2703 int shift_size = ElementsKindToShiftSize(elements_kind); | |
2704 if (key->IsConstantOperand()) { | |
2705 int constant_value = ToInteger32(LConstantOperand::cast(key)); | |
2706 if (constant_value & 0xF0000000) { | |
2707 Abort("array index constant value too big"); | |
2708 } | |
2709 return Operand(elements_pointer_reg, | |
2710 ((constant_value + additional_index) << shift_size) | |
2711 + offset); | |
2712 } else { | |
2713 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); | |
2714 return Operand(elements_pointer_reg, | |
2715 ToRegister(key), | |
2716 scale_factor, | |
2717 offset + (additional_index << shift_size)); | |
2718 } | |
2719 } | |
2720 | |
2721 | |
2722 void LCodeGen::DoLoadKeyedSpecializedArrayElement( | |
2723 LLoadKeyedSpecializedArrayElement* instr) { | |
2724 ElementsKind elements_kind = instr->elements_kind(); | 2616 ElementsKind elements_kind = instr->elements_kind(); |
2725 LOperand* key = instr->key(); | 2617 LOperand* key = instr->key(); |
2726 if (!key->IsConstantOperand()) { | 2618 if (!key->IsConstantOperand()) { |
2727 Register key_reg = ToRegister(key); | 2619 Register key_reg = ToRegister(key); |
2728 // Even though the HLoad/StoreKeyedFastElement instructions force the input | 2620 // Even though the HLoad/StoreKeyed (in this case) instructions force |
2729 // representation for the key to be an integer, the input gets replaced | 2621 // the input representation for the key to be an integer, the input |
2730 // during bound check elimination with the index argument to the bounds | 2622 // gets replaced during bound check elimination with the index argument |
2731 // check, which can be tagged, so that case must be handled here, too. | 2623 // to the bounds check, which can be tagged, so that case must be |
| 2624 // handled here, too. |
2732 if (instr->hydrogen()->key()->representation().IsTagged()) { | 2625 if (instr->hydrogen()->key()->representation().IsTagged()) { |
2733 __ SmiToInteger64(key_reg, key_reg); | 2626 __ SmiToInteger64(key_reg, key_reg); |
2734 } else if (instr->hydrogen()->IsDehoisted()) { | 2627 } else if (instr->hydrogen()->IsDehoisted()) { |
2735 // Sign extend key because it could be a 32 bit negative value | 2628 // Sign extend key because it could be a 32 bit negative value |
2736 // and the dehoisted address computation happens in 64 bits | 2629 // and the dehoisted address computation happens in 64 bits |
2737 __ movsxlq(key_reg, key_reg); | 2630 __ movsxlq(key_reg, key_reg); |
2738 } | 2631 } |
2739 } | 2632 } |
2740 Operand operand(BuildFastArrayOperand( | 2633 Operand operand(BuildFastArrayOperand( |
2741 instr->external_pointer(), | 2634 instr->external_pointer(), |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2783 case FAST_DOUBLE_ELEMENTS: | 2676 case FAST_DOUBLE_ELEMENTS: |
2784 case FAST_HOLEY_ELEMENTS: | 2677 case FAST_HOLEY_ELEMENTS: |
2785 case FAST_HOLEY_SMI_ELEMENTS: | 2678 case FAST_HOLEY_SMI_ELEMENTS: |
2786 case FAST_HOLEY_DOUBLE_ELEMENTS: | 2679 case FAST_HOLEY_DOUBLE_ELEMENTS: |
2787 case DICTIONARY_ELEMENTS: | 2680 case DICTIONARY_ELEMENTS: |
2788 case NON_STRICT_ARGUMENTS_ELEMENTS: | 2681 case NON_STRICT_ARGUMENTS_ELEMENTS: |
2789 UNREACHABLE(); | 2682 UNREACHABLE(); |
2790 break; | 2683 break; |
2791 } | 2684 } |
2792 } | 2685 } |
| 2686 |
| 2687 } |
| 2688 |
| 2689 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
| 2690 if (instr->is_external()) { |
| 2691 DoLoadKeyedExternal(instr); |
| 2692 } else if (instr->hydrogen()->representation().IsDouble()) { |
| 2693 XMMRegister result(ToDoubleRegister(instr->result())); |
| 2694 LOperand* key = instr->key(); |
| 2695 if (!key->IsConstantOperand()) { |
| 2696 Register key_reg = ToRegister(key); |
| 2697 // Even though the HLoad/StoreKeyed instructions force the input |
| 2698 // representation for the key to be an integer, the input gets replaced |
| 2699 // during bound check elimination with the index argument to the bounds |
| 2700 // check, which can be tagged, so that case must be handled here, too. |
| 2701 if (instr->hydrogen()->key()->representation().IsTagged()) { |
| 2702 __ SmiToInteger64(key_reg, key_reg); |
| 2703 } else if (instr->hydrogen()->IsDehoisted()) { |
| 2704 // Sign extend key because it could be a 32 bit negative value |
| 2705 // and the dehoisted address computation happens in 64 bits |
| 2706 __ movsxlq(key_reg, key_reg); |
| 2707 } |
| 2708 } |
| 2709 |
| 2710 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2711 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + |
| 2712 sizeof(kHoleNanLower32); |
| 2713 Operand hole_check_operand = BuildFastArrayOperand( |
| 2714 instr->elements(), |
| 2715 key, |
| 2716 FAST_DOUBLE_ELEMENTS, |
| 2717 offset, |
| 2718 instr->additional_index()); |
| 2719 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); |
| 2720 DeoptimizeIf(equal, instr->environment()); |
| 2721 } |
| 2722 |
| 2723 Operand double_load_operand = BuildFastArrayOperand( |
| 2724 instr->elements(), |
| 2725 key, |
| 2726 FAST_DOUBLE_ELEMENTS, |
| 2727 FixedDoubleArray::kHeaderSize - kHeapObjectTag, |
| 2728 instr->additional_index()); |
| 2729 __ movsd(result, double_load_operand); |
| 2730 } else { |
| 2731 Register result = ToRegister(instr->result()); |
| 2732 LOperand* key = instr->key(); |
| 2733 if (!key->IsConstantOperand()) { |
| 2734 Register key_reg = ToRegister(key); |
| 2735 // Even though the HLoad/StoreKeyedFastElement instructions force |
| 2736 // the input representation for the key to be an integer, the input |
| 2737 // gets replaced during bound check elimination with the index |
| 2738 // argument to the bounds check, which can be tagged, so that |
| 2739 // case must be handled here, too. |
| 2740 if (instr->hydrogen()->key()->representation().IsTagged()) { |
| 2741 __ SmiToInteger64(key_reg, key_reg); |
| 2742 } else if (instr->hydrogen()->IsDehoisted()) { |
| 2743 // Sign extend key because it could be a 32 bit negative value |
| 2744 // and the dehoisted address computation happens in 64 bits |
| 2745 __ movsxlq(key_reg, key_reg); |
| 2746 } |
| 2747 } |
| 2748 |
| 2749 // Load the result. |
| 2750 __ movq(result, |
| 2751 BuildFastArrayOperand(instr->elements(), |
| 2752 key, |
| 2753 FAST_ELEMENTS, |
| 2754 FixedArray::kHeaderSize - kHeapObjectTag, |
| 2755 instr->additional_index())); |
| 2756 |
| 2757 // Check for the hole value. |
| 2758 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2759 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
| 2760 Condition smi = __ CheckSmi(result); |
| 2761 DeoptimizeIf(NegateCondition(smi), instr->environment()); |
| 2762 } else { |
| 2763 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 2764 DeoptimizeIf(equal, instr->environment()); |
| 2765 } |
| 2766 } |
| 2767 } |
2793 } | 2768 } |
2794 | 2769 |
2795 | 2770 |
| 2771 Operand LCodeGen::BuildFastArrayOperand( |
| 2772 LOperand* elements_pointer, |
| 2773 LOperand* key, |
| 2774 ElementsKind elements_kind, |
| 2775 uint32_t offset, |
| 2776 uint32_t additional_index) { |
| 2777 Register elements_pointer_reg = ToRegister(elements_pointer); |
| 2778 int shift_size = ElementsKindToShiftSize(elements_kind); |
| 2779 if (key->IsConstantOperand()) { |
| 2780 int constant_value = ToInteger32(LConstantOperand::cast(key)); |
| 2781 if (constant_value & 0xF0000000) { |
| 2782 Abort("array index constant value too big"); |
| 2783 } |
| 2784 return Operand(elements_pointer_reg, |
| 2785 ((constant_value + additional_index) << shift_size) |
| 2786 + offset); |
| 2787 } else { |
| 2788 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); |
| 2789 return Operand(elements_pointer_reg, |
| 2790 ToRegister(key), |
| 2791 scale_factor, |
| 2792 offset + (additional_index << shift_size)); |
| 2793 } |
| 2794 } |
| 2795 |
| 2796 |
2796 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2797 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
2797 ASSERT(ToRegister(instr->object()).is(rdx)); | 2798 ASSERT(ToRegister(instr->object()).is(rdx)); |
2798 ASSERT(ToRegister(instr->key()).is(rax)); | 2799 ASSERT(ToRegister(instr->key()).is(rax)); |
2799 | 2800 |
2800 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2801 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2801 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2802 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2802 } | 2803 } |
2803 | 2804 |
2804 | 2805 |
2805 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 2806 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
(...skipping 852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3658 ASSERT(ToRegister(instr->value()).is(rax)); | 3659 ASSERT(ToRegister(instr->value()).is(rax)); |
3659 | 3660 |
3660 __ Move(rcx, instr->hydrogen()->name()); | 3661 __ Move(rcx, instr->hydrogen()->name()); |
3661 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3662 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
3662 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3663 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
3663 : isolate()->builtins()->StoreIC_Initialize(); | 3664 : isolate()->builtins()->StoreIC_Initialize(); |
3664 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3665 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
3665 } | 3666 } |
3666 | 3667 |
3667 | 3668 |
3668 void LCodeGen::DoStoreKeyedSpecializedArrayElement( | |
3669 LStoreKeyedSpecializedArrayElement* instr) { | |
3670 ElementsKind elements_kind = instr->elements_kind(); | |
3671 LOperand* key = instr->key(); | |
3672 if (!key->IsConstantOperand()) { | |
3673 Register key_reg = ToRegister(key); | |
3674 // Even though the HLoad/StoreKeyedFastElement instructions force the input | |
3675 // representation for the key to be an integer, the input gets replaced | |
3676 // during bound check elimination with the index argument to the bounds | |
3677 // check, which can be tagged, so that case must be handled here, too. | |
3678 if (instr->hydrogen()->key()->representation().IsTagged()) { | |
3679 __ SmiToInteger64(key_reg, key_reg); | |
3680 } else if (instr->hydrogen()->IsDehoisted()) { | |
3681 // Sign extend key because it could be a 32 bit negative value | |
3682 // and the dehoisted address computation happens in 64 bits | |
3683 __ movsxlq(key_reg, key_reg); | |
3684 } | |
3685 } | |
3686 Operand operand(BuildFastArrayOperand( | |
3687 instr->external_pointer(), | |
3688 key, | |
3689 elements_kind, | |
3690 0, | |
3691 instr->additional_index())); | |
3692 | |
3693 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | |
3694 XMMRegister value(ToDoubleRegister(instr->value())); | |
3695 __ cvtsd2ss(value, value); | |
3696 __ movss(operand, value); | |
3697 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | |
3698 __ movsd(operand, ToDoubleRegister(instr->value())); | |
3699 } else { | |
3700 Register value(ToRegister(instr->value())); | |
3701 switch (elements_kind) { | |
3702 case EXTERNAL_PIXEL_ELEMENTS: | |
3703 case EXTERNAL_BYTE_ELEMENTS: | |
3704 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
3705 __ movb(operand, value); | |
3706 break; | |
3707 case EXTERNAL_SHORT_ELEMENTS: | |
3708 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
3709 __ movw(operand, value); | |
3710 break; | |
3711 case EXTERNAL_INT_ELEMENTS: | |
3712 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
3713 __ movl(operand, value); | |
3714 break; | |
3715 case EXTERNAL_FLOAT_ELEMENTS: | |
3716 case EXTERNAL_DOUBLE_ELEMENTS: | |
3717 case FAST_ELEMENTS: | |
3718 case FAST_SMI_ELEMENTS: | |
3719 case FAST_DOUBLE_ELEMENTS: | |
3720 case FAST_HOLEY_ELEMENTS: | |
3721 case FAST_HOLEY_SMI_ELEMENTS: | |
3722 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
3723 case DICTIONARY_ELEMENTS: | |
3724 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
3725 UNREACHABLE(); | |
3726 break; | |
3727 } | |
3728 } | |
3729 } | |
3730 | |
3731 | |
3732 void LCodeGen::DeoptIfTaggedButNotSmi(LEnvironment* environment, | 3669 void LCodeGen::DeoptIfTaggedButNotSmi(LEnvironment* environment, |
3733 HValue* value, | 3670 HValue* value, |
3734 LOperand* operand) { | 3671 LOperand* operand) { |
3735 if (value->representation().IsTagged() && !value->type().IsSmi()) { | 3672 if (value->representation().IsTagged() && !value->type().IsSmi()) { |
3736 Condition cc; | 3673 Condition cc; |
3737 if (operand->IsRegister()) { | 3674 if (operand->IsRegister()) { |
3738 cc = masm()->CheckSmi(ToRegister(operand)); | 3675 cc = masm()->CheckSmi(ToRegister(operand)); |
3739 } else { | 3676 } else { |
3740 cc = masm()->CheckSmi(ToOperand(operand)); | 3677 cc = masm()->CheckSmi(ToOperand(operand)); |
3741 } | 3678 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3782 __ cmpq(length, Immediate(constant_index)); | 3719 __ cmpq(length, Immediate(constant_index)); |
3783 } | 3720 } |
3784 } else { | 3721 } else { |
3785 __ cmpq(length, ToRegister(instr->index())); | 3722 __ cmpq(length, ToRegister(instr->index())); |
3786 } | 3723 } |
3787 } | 3724 } |
3788 DeoptimizeIf(below_equal, instr->environment()); | 3725 DeoptimizeIf(below_equal, instr->environment()); |
3789 } | 3726 } |
3790 | 3727 |
3791 | 3728 |
3792 void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { | 3729 void LCodeGen::DoStoreKeyedExternal(LStoreKeyed* instr) { |
3793 Register value = ToRegister(instr->value()); | 3730 ElementsKind elements_kind = instr->elements_kind(); |
3794 Register elements = ToRegister(instr->object()); | |
3795 LOperand* key = instr->key(); | 3731 LOperand* key = instr->key(); |
3796 if (!key->IsConstantOperand()) { | 3732 if (!key->IsConstantOperand()) { |
3797 Register key_reg = ToRegister(key); | 3733 Register key_reg = ToRegister(key); |
3798 // Even though the HLoad/StoreKeyedFastElement instructions force the input | 3734 // Even though the HLoad/StoreKeyedFastElement instructions force |
3799 // representation for the key to be an integer, the input gets replaced | 3735 // the input representation for the key to be an integer, the input |
3800 // during bound check elimination with the index argument to the bounds | 3736 // gets replaced during bound check elimination with the index |
3801 // check, which can be tagged, so that case must be handled here, too. | 3737 // argument to the bounds check, which can be tagged, so that case |
| 3738 // must be handled here, too. |
3802 if (instr->hydrogen()->key()->representation().IsTagged()) { | 3739 if (instr->hydrogen()->key()->representation().IsTagged()) { |
3803 __ SmiToInteger64(key_reg, key_reg); | 3740 __ SmiToInteger64(key_reg, key_reg); |
3804 } else if (instr->hydrogen()->IsDehoisted()) { | 3741 } else if (instr->hydrogen()->IsDehoisted()) { |
3805 // Sign extend key because it could be a 32 bit negative value | 3742 // Sign extend key because it could be a 32 bit negative value |
3806 // and the dehoisted address computation happens in 64 bits | 3743 // and the dehoisted address computation happens in 64 bits |
3807 __ movsxlq(key_reg, key_reg); | 3744 __ movsxlq(key_reg, key_reg); |
3808 } | 3745 } |
3809 } | 3746 } |
| 3747 Operand operand(BuildFastArrayOperand( |
| 3748 instr->external_pointer(), |
| 3749 key, |
| 3750 elements_kind, |
| 3751 0, |
| 3752 instr->additional_index())); |
3810 | 3753 |
3811 Operand operand = | 3754 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
3812 BuildFastArrayOperand(instr->object(), | 3755 XMMRegister value(ToDoubleRegister(instr->value())); |
3813 key, | 3756 __ cvtsd2ss(value, value); |
3814 FAST_ELEMENTS, | 3757 __ movss(operand, value); |
3815 FixedArray::kHeaderSize - kHeapObjectTag, | 3758 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
3816 instr->additional_index()); | 3759 __ movsd(operand, ToDoubleRegister(instr->value())); |
3817 | |
3818 if (instr->hydrogen()->NeedsWriteBarrier()) { | |
3819 ASSERT(!instr->key()->IsConstantOperand()); | |
3820 HType type = instr->hydrogen()->value()->type(); | |
3821 SmiCheck check_needed = | |
3822 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | |
3823 // Compute address of modified element and store it into key register. | |
3824 Register key_reg(ToRegister(key)); | |
3825 __ lea(key_reg, operand); | |
3826 __ movq(Operand(key_reg, 0), value); | |
3827 __ RecordWrite(elements, | |
3828 key_reg, | |
3829 value, | |
3830 kSaveFPRegs, | |
3831 EMIT_REMEMBERED_SET, | |
3832 check_needed); | |
3833 } else { | 3760 } else { |
3834 __ movq(operand, value); | 3761 Register value(ToRegister(instr->value())); |
| 3762 switch (elements_kind) { |
| 3763 case EXTERNAL_PIXEL_ELEMENTS: |
| 3764 case EXTERNAL_BYTE_ELEMENTS: |
| 3765 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3766 __ movb(operand, value); |
| 3767 break; |
| 3768 case EXTERNAL_SHORT_ELEMENTS: |
| 3769 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3770 __ movw(operand, value); |
| 3771 break; |
| 3772 case EXTERNAL_INT_ELEMENTS: |
| 3773 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3774 __ movl(operand, value); |
| 3775 break; |
| 3776 case EXTERNAL_FLOAT_ELEMENTS: |
| 3777 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3778 case FAST_ELEMENTS: |
| 3779 case FAST_SMI_ELEMENTS: |
| 3780 case FAST_DOUBLE_ELEMENTS: |
| 3781 case FAST_HOLEY_ELEMENTS: |
| 3782 case FAST_HOLEY_SMI_ELEMENTS: |
| 3783 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 3784 case DICTIONARY_ELEMENTS: |
| 3785 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3786 UNREACHABLE(); |
| 3787 break; |
| 3788 } |
3835 } | 3789 } |
3836 } | 3790 } |
3837 | 3791 |
3838 | 3792 |
3839 void LCodeGen::DoStoreKeyedFastDoubleElement( | 3793 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { |
3840 LStoreKeyedFastDoubleElement* instr) { | 3794 if (instr->is_external()) { |
3841 XMMRegister value = ToDoubleRegister(instr->value()); | 3795 DoStoreKeyedExternal(instr); |
3842 LOperand* key = instr->key(); | 3796 } else if (instr->hydrogen()->value()->representation().IsDouble()) { |
3843 if (!key->IsConstantOperand()) { | 3797 XMMRegister value = ToDoubleRegister(instr->value()); |
3844 Register key_reg = ToRegister(key); | 3798 LOperand* key = instr->key(); |
3845 // Even though the HLoad/StoreKeyedFastElement instructions force the input | 3799 if (!key->IsConstantOperand()) { |
3846 // representation for the key to be an integer, the input gets replaced | 3800 Register key_reg = ToRegister(key); |
3847 // during bound check elimination with the index argument to the bounds | 3801 // Even though the HLoad/StoreKeyedFastElement instructions force |
3848 // check, which can be tagged, so that case must be handled here, too. | 3802 // the input representation for the key to be an integer, the |
3849 if (instr->hydrogen()->key()->representation().IsTagged()) { | 3803 // input gets replaced during bound check elimination with the index |
3850 __ SmiToInteger64(key_reg, key_reg); | 3804 // argument to the bounds check, which can be tagged, so that case |
3851 } else if (instr->hydrogen()->IsDehoisted()) { | 3805 // must be handled here, too. |
3852 // Sign extend key because it could be a 32 bit negative value | 3806 if (instr->hydrogen()->key()->representation().IsTagged()) { |
3853 // and the dehoisted address computation happens in 64 bits | 3807 __ SmiToInteger64(key_reg, key_reg); |
3854 __ movsxlq(key_reg, key_reg); | 3808 } else if (instr->hydrogen()->IsDehoisted()) { |
| 3809 // Sign extend key because it could be a 32 bit negative value |
| 3810 // and the dehoisted address computation happens in 64 bits |
| 3811 __ movsxlq(key_reg, key_reg); |
| 3812 } |
| 3813 } |
| 3814 |
| 3815 if (instr->NeedsCanonicalization()) { |
| 3816 Label have_value; |
| 3817 |
| 3818 __ ucomisd(value, value); |
| 3819 __ j(parity_odd, &have_value); // NaN. |
| 3820 |
| 3821 __ Set(kScratchRegister, BitCast<uint64_t>( |
| 3822 FixedDoubleArray::canonical_not_the_hole_nan_as_double())); |
| 3823 __ movq(value, kScratchRegister); |
| 3824 |
| 3825 __ bind(&have_value); |
| 3826 } |
| 3827 |
| 3828 Operand double_store_operand = BuildFastArrayOperand( |
| 3829 instr->object(), |
| 3830 key, |
| 3831 FAST_DOUBLE_ELEMENTS, |
| 3832 FixedDoubleArray::kHeaderSize - kHeapObjectTag, |
| 3833 instr->additional_index()); |
| 3834 |
| 3835 __ movsd(double_store_operand, value); |
| 3836 } else { |
| 3837 Register value = ToRegister(instr->value()); |
| 3838 Register elements = ToRegister(instr->object()); |
| 3839 LOperand* key = instr->key(); |
| 3840 if (!key->IsConstantOperand()) { |
| 3841 Register key_reg = ToRegister(key); |
| 3842 // Even though the HLoad/StoreKeyedFastElement instructions force |
| 3843 // the input representation for the key to be an integer, the |
| 3844 // input gets replaced during bound check elimination with the index |
| 3845 // argument to the bounds check, which can be tagged, so that case |
| 3846 // must be handled here, too. |
| 3847 if (instr->hydrogen()->key()->representation().IsTagged()) { |
| 3848 __ SmiToInteger64(key_reg, key_reg); |
| 3849 } else if (instr->hydrogen()->IsDehoisted()) { |
| 3850 // Sign extend key because it could be a 32 bit negative value |
| 3851 // and the dehoisted address computation happens in 64 bits |
| 3852 __ movsxlq(key_reg, key_reg); |
| 3853 } |
| 3854 } |
| 3855 |
| 3856 Operand operand = |
| 3857 BuildFastArrayOperand(instr->object(), |
| 3858 key, |
| 3859 FAST_ELEMENTS, |
| 3860 FixedArray::kHeaderSize - kHeapObjectTag, |
| 3861 instr->additional_index()); |
| 3862 |
| 3863 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3864 ASSERT(!instr->key()->IsConstantOperand()); |
| 3865 HType type = instr->hydrogen()->value()->type(); |
| 3866 SmiCheck check_needed = |
| 3867 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 3868 // Compute address of modified element and store it into key register. |
| 3869 Register key_reg(ToRegister(key)); |
| 3870 __ lea(key_reg, operand); |
| 3871 __ movq(Operand(key_reg, 0), value); |
| 3872 __ RecordWrite(elements, |
| 3873 key_reg, |
| 3874 value, |
| 3875 kSaveFPRegs, |
| 3876 EMIT_REMEMBERED_SET, |
| 3877 check_needed); |
| 3878 } else { |
| 3879 __ movq(operand, value); |
3855 } | 3880 } |
3856 } | 3881 } |
| 3882 } |
3857 | 3883 |
3858 if (instr->NeedsCanonicalization()) { | |
3859 Label have_value; | |
3860 | |
3861 __ ucomisd(value, value); | |
3862 __ j(parity_odd, &have_value); // NaN. | |
3863 | |
3864 __ Set(kScratchRegister, BitCast<uint64_t>( | |
3865 FixedDoubleArray::canonical_not_the_hole_nan_as_double())); | |
3866 __ movq(value, kScratchRegister); | |
3867 | |
3868 __ bind(&have_value); | |
3869 } | |
3870 | |
3871 Operand double_store_operand = BuildFastArrayOperand( | |
3872 instr->elements(), | |
3873 key, | |
3874 FAST_DOUBLE_ELEMENTS, | |
3875 FixedDoubleArray::kHeaderSize - kHeapObjectTag, | |
3876 instr->additional_index()); | |
3877 | |
3878 __ movsd(double_store_operand, value); | |
3879 } | |
3880 | 3884 |
3881 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 3885 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
3882 ASSERT(ToRegister(instr->object()).is(rdx)); | 3886 ASSERT(ToRegister(instr->object()).is(rdx)); |
3883 ASSERT(ToRegister(instr->key()).is(rcx)); | 3887 ASSERT(ToRegister(instr->key()).is(rcx)); |
3884 ASSERT(ToRegister(instr->value()).is(rax)); | 3888 ASSERT(ToRegister(instr->value()).is(rax)); |
3885 | 3889 |
3886 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3890 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
3887 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 3891 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
3888 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 3892 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
3889 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3893 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
(...skipping 1421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5311 FixedArray::kHeaderSize - kPointerSize)); | 5315 FixedArray::kHeaderSize - kPointerSize)); |
5312 __ bind(&done); | 5316 __ bind(&done); |
5313 } | 5317 } |
5314 | 5318 |
5315 | 5319 |
5316 #undef __ | 5320 #undef __ |
5317 | 5321 |
5318 } } // namespace v8::internal | 5322 } } // namespace v8::internal |
5319 | 5323 |
5320 #endif // V8_TARGET_ARCH_X64 | 5324 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |