OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 2716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2727 __ cmpl(left, temp); | 2727 __ cmpl(left, temp); |
2728 __ j(NOT_EQUAL, deopt); // Overflow. | 2728 __ j(NOT_EQUAL, deopt); // Overflow. |
2729 } | 2729 } |
2730 // Shift for result now we know there is no overflow. | 2730 // Shift for result now we know there is no overflow. |
2731 __ shll(left, Immediate(value)); | 2731 __ shll(left, Immediate(value)); |
2732 return; | 2732 return; |
2733 } | 2733 } |
2734 | 2734 |
2735 // Right (locs.in(1)) is not constant. | 2735 // Right (locs.in(1)) is not constant. |
2736 Register right = locs.in(1).reg(); | 2736 Register right = locs.in(1).reg(); |
2737 Range* right_range = shift_left->right()->definition()->range(); | 2737 Range* right_range = shift_left->right_range(); |
2738 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { | 2738 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { |
2739 // TODO(srdjan): Implement code below for can_overflow(). | 2739 // TODO(srdjan): Implement code below for can_overflow(). |
2740 // If left is constant, we know the maximal allowed size for right. | 2740 // If left is constant, we know the maximal allowed size for right. |
2741 const Object& obj = shift_left->left()->BoundConstant(); | 2741 const Object& obj = shift_left->left()->BoundConstant(); |
2742 if (obj.IsSmi()) { | 2742 if (obj.IsSmi()) { |
2743 const intptr_t left_int = Smi::Cast(obj).Value(); | 2743 const intptr_t left_int = Smi::Cast(obj).Value(); |
2744 if (left_int == 0) { | 2744 if (left_int == 0) { |
2745 __ cmpl(right, Immediate(0)); | 2745 __ cmpl(right, Immediate(0)); |
2746 __ j(NEGATIVE, deopt); | 2746 __ j(NEGATIVE, deopt); |
2747 return; | 2747 return; |
(...skipping 10 matching lines...) Expand all Loading... |
2758 __ shll(left, right); | 2758 __ shll(left, right); |
2759 } | 2759 } |
2760 return; | 2760 return; |
2761 } | 2761 } |
2762 | 2762 |
2763 const bool right_needs_check = | 2763 const bool right_needs_check = |
2764 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); | 2764 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); |
2765 ASSERT(right == ECX); // Count must be in ECX | 2765 ASSERT(right == ECX); // Count must be in ECX |
2766 if (!shift_left->can_overflow()) { | 2766 if (!shift_left->can_overflow()) { |
2767 if (right_needs_check) { | 2767 if (right_needs_check) { |
2768 const bool right_may_be_negative = | 2768 if (!RangeUtils::IsPositive(right_range)) { |
2769 (right_range == NULL) || !right_range->IsPositive(); | |
2770 if (right_may_be_negative) { | |
2771 ASSERT(shift_left->CanDeoptimize()); | 2769 ASSERT(shift_left->CanDeoptimize()); |
2772 __ cmpl(right, Immediate(0)); | 2770 __ cmpl(right, Immediate(0)); |
2773 __ j(NEGATIVE, deopt); | 2771 __ j(NEGATIVE, deopt); |
2774 } | 2772 } |
2775 Label done, is_not_zero; | 2773 Label done, is_not_zero; |
2776 __ cmpl(right, | 2774 __ cmpl(right, |
2777 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); | 2775 Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); |
2778 __ j(BELOW, &is_not_zero, Assembler::kNearJump); | 2776 __ j(BELOW, &is_not_zero, Assembler::kNearJump); |
2779 __ xorl(left, left); | 2777 __ xorl(left, left); |
2780 __ jmp(&done, Assembler::kNearJump); | 2778 __ jmp(&done, Assembler::kNearJump); |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3036 const Address& right = locs()->in(1).ToStackSlotAddress(); | 3034 const Address& right = locs()->in(1).ToStackSlotAddress(); |
3037 if (op_kind() == Token::kMUL) { | 3035 if (op_kind() == Token::kMUL) { |
3038 __ SmiUntag(left); | 3036 __ SmiUntag(left); |
3039 } | 3037 } |
3040 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); | 3038 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); |
3041 return; | 3039 return; |
3042 } | 3040 } |
3043 | 3041 |
3044 // if locs()->in(1).IsRegister. | 3042 // if locs()->in(1).IsRegister. |
3045 Register right = locs()->in(1).reg(); | 3043 Register right = locs()->in(1).reg(); |
3046 Range* right_range = this->right()->definition()->range(); | |
3047 switch (op_kind()) { | 3044 switch (op_kind()) { |
3048 case Token::kADD: | 3045 case Token::kADD: |
3049 case Token::kSUB: | 3046 case Token::kSUB: |
3050 case Token::kBIT_AND: | 3047 case Token::kBIT_AND: |
3051 case Token::kBIT_OR: | 3048 case Token::kBIT_OR: |
3052 case Token::kBIT_XOR: | 3049 case Token::kBIT_XOR: |
3053 case Token::kMUL: | 3050 case Token::kMUL: |
3054 if (op_kind() == Token::kMUL) { | 3051 if (op_kind() == Token::kMUL) { |
3055 __ SmiUntag(left); | 3052 __ SmiUntag(left); |
3056 } | 3053 } |
3057 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); | 3054 EmitIntegerArithmetic(compiler, op_kind(), left, right, deopt); |
3058 break; | 3055 break; |
3059 | 3056 |
3060 | 3057 |
3061 case Token::kTRUNCDIV: { | 3058 case Token::kTRUNCDIV: { |
3062 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3059 if (RangeUtils::CanBeZero(right_range())) { |
3063 // Handle divide by zero in runtime. | 3060 // Handle divide by zero in runtime. |
3064 __ testl(right, right); | 3061 __ testl(right, right); |
3065 __ j(ZERO, deopt); | 3062 __ j(ZERO, deopt); |
3066 } | 3063 } |
3067 ASSERT(left == EAX); | 3064 ASSERT(left == EAX); |
3068 ASSERT((right != EDX) && (right != EAX)); | 3065 ASSERT((right != EDX) && (right != EAX)); |
3069 ASSERT(locs()->temp(0).reg() == EDX); | 3066 ASSERT(locs()->temp(0).reg() == EDX); |
3070 ASSERT(result == EAX); | 3067 ASSERT(result == EAX); |
3071 __ SmiUntag(left); | 3068 __ SmiUntag(left); |
3072 __ SmiUntag(right); | 3069 __ SmiUntag(right); |
3073 __ cdq(); // Sign extend EAX -> EDX:EAX. | 3070 __ cdq(); // Sign extend EAX -> EDX:EAX. |
3074 __ idivl(right); // EAX: quotient, EDX: remainder. | 3071 __ idivl(right); // EAX: quotient, EDX: remainder. |
3075 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 3072 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
3076 // case we cannot tag the result. | 3073 // case we cannot tag the result. |
3077 __ cmpl(result, Immediate(0x40000000)); | 3074 __ cmpl(result, Immediate(0x40000000)); |
3078 __ j(EQUAL, deopt); | 3075 __ j(EQUAL, deopt); |
3079 __ SmiTag(result); | 3076 __ SmiTag(result); |
3080 break; | 3077 break; |
3081 } | 3078 } |
3082 case Token::kMOD: { | 3079 case Token::kMOD: { |
3083 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3080 if (RangeUtils::CanBeZero(right_range())) { |
3084 // Handle divide by zero in runtime. | 3081 // Handle divide by zero in runtime. |
3085 __ testl(right, right); | 3082 __ testl(right, right); |
3086 __ j(ZERO, deopt); | 3083 __ j(ZERO, deopt); |
3087 } | 3084 } |
3088 ASSERT(left == EDX); | 3085 ASSERT(left == EDX); |
3089 ASSERT((right != EDX) && (right != EAX)); | 3086 ASSERT((right != EDX) && (right != EAX)); |
3090 ASSERT(locs()->temp(0).reg() == EAX); | 3087 ASSERT(locs()->temp(0).reg() == EAX); |
3091 ASSERT(result == EDX); | 3088 ASSERT(result == EDX); |
3092 __ SmiUntag(left); | 3089 __ SmiUntag(left); |
3093 __ SmiUntag(right); | 3090 __ SmiUntag(right); |
3094 __ movl(EAX, EDX); | 3091 __ movl(EAX, EDX); |
3095 __ cdq(); // Sign extend EAX -> EDX:EAX. | 3092 __ cdq(); // Sign extend EAX -> EDX:EAX. |
3096 __ idivl(right); // EAX: quotient, EDX: remainder. | 3093 __ idivl(right); // EAX: quotient, EDX: remainder. |
3097 // res = left % right; | 3094 // res = left % right; |
3098 // if (res < 0) { | 3095 // if (res < 0) { |
3099 // if (right < 0) { | 3096 // if (right < 0) { |
3100 // res = res - right; | 3097 // res = res - right; |
3101 // } else { | 3098 // } else { |
3102 // res = res + right; | 3099 // res = res + right; |
3103 // } | 3100 // } |
3104 // } | 3101 // } |
3105 Label done; | 3102 Label done; |
3106 __ cmpl(result, Immediate(0)); | 3103 __ cmpl(result, Immediate(0)); |
3107 __ j(GREATER_EQUAL, &done, Assembler::kNearJump); | 3104 __ j(GREATER_EQUAL, &done, Assembler::kNearJump); |
3108 // Result is negative, adjust it. | 3105 // Result is negative, adjust it. |
3109 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) { | 3106 if (RangeUtils::Overlaps(right_range(), -1, 1)) { |
3110 // Right can be positive and negative. | 3107 // Right can be positive and negative. |
3111 Label subtract; | 3108 Label subtract; |
3112 __ cmpl(right, Immediate(0)); | 3109 __ cmpl(right, Immediate(0)); |
3113 __ j(LESS, &subtract, Assembler::kNearJump); | 3110 __ j(LESS, &subtract, Assembler::kNearJump); |
3114 __ addl(result, right); | 3111 __ addl(result, right); |
3115 __ jmp(&done, Assembler::kNearJump); | 3112 __ jmp(&done, Assembler::kNearJump); |
3116 __ Bind(&subtract); | 3113 __ Bind(&subtract); |
3117 __ subl(result, right); | 3114 __ subl(result, right); |
3118 } else if (right_range->IsPositive()) { | 3115 } else if (right_range()->IsPositive()) { |
3119 // Right is positive. | 3116 // Right is positive. |
3120 __ addl(result, right); | 3117 __ addl(result, right); |
3121 } else { | 3118 } else { |
3122 // Right is negative. | 3119 // Right is negative. |
3123 __ subl(result, right); | 3120 __ subl(result, right); |
3124 } | 3121 } |
3125 __ Bind(&done); | 3122 __ Bind(&done); |
3126 __ SmiTag(result); | 3123 __ SmiTag(result); |
3127 break; | 3124 break; |
3128 } | 3125 } |
3129 case Token::kSHR: { | 3126 case Token::kSHR: { |
3130 if (CanDeoptimize()) { | 3127 if (CanDeoptimize()) { |
3131 __ cmpl(right, Immediate(0)); | 3128 __ cmpl(right, Immediate(0)); |
3132 __ j(LESS, deopt); | 3129 __ j(LESS, deopt); |
3133 } | 3130 } |
3134 __ SmiUntag(right); | 3131 __ SmiUntag(right); |
3135 // sarl operation masks the count to 5 bits. | 3132 // sarl operation masks the count to 5 bits. |
3136 const intptr_t kCountLimit = 0x1F; | 3133 const intptr_t kCountLimit = 0x1F; |
3137 if ((right_range == NULL) || | 3134 if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) { |
3138 !right_range->OnlyLessThanOrEqualTo(kCountLimit)) { | |
3139 __ cmpl(right, Immediate(kCountLimit)); | 3135 __ cmpl(right, Immediate(kCountLimit)); |
3140 Label count_ok; | 3136 Label count_ok; |
3141 __ j(LESS, &count_ok, Assembler::kNearJump); | 3137 __ j(LESS, &count_ok, Assembler::kNearJump); |
3142 __ movl(right, Immediate(kCountLimit)); | 3138 __ movl(right, Immediate(kCountLimit)); |
3143 __ Bind(&count_ok); | 3139 __ Bind(&count_ok); |
3144 } | 3140 } |
3145 ASSERT(right == ECX); // Count must be in ECX | 3141 ASSERT(right == ECX); // Count must be in ECX |
3146 __ SmiUntag(left); | 3142 __ SmiUntag(left); |
3147 __ sarl(left, right); | 3143 __ sarl(left, right); |
3148 __ SmiTag(left); | 3144 __ SmiTag(left); |
(...skipping 2552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5701 __ movaps(out, in); | 5697 __ movaps(out, in); |
5702 } else { | 5698 } else { |
5703 ASSERT(representation() == kTagged); | 5699 ASSERT(representation() == kTagged); |
5704 Register out = locs()->out(0).reg(); | 5700 Register out = locs()->out(0).reg(); |
5705 Register in = in_loc.reg(); | 5701 Register in = in_loc.reg(); |
5706 __ movl(out, in); | 5702 __ movl(out, in); |
5707 } | 5703 } |
5708 } | 5704 } |
5709 | 5705 |
5710 | 5706 |
5711 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 5707 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, |
5712 bool opt) const { | 5708 bool opt) const { |
5713 if (kind() == MergedMathInstr::kTruncDivMod) { | 5709 const intptr_t kNumInputs = 2; |
5714 const intptr_t kNumInputs = 2; | 5710 const intptr_t kNumTemps = 0; |
5715 const intptr_t kNumTemps = 0; | 5711 LocationSummary* summary = new (zone) |
5716 LocationSummary* summary = new (zone) | 5712 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5717 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5713 // Both inputs must be writable because they will be untagged. |
5718 // Both inputs must be writable because they will be untagged. | 5714 summary->set_in(0, Location::RegisterLocation(EAX)); |
5719 summary->set_in(0, Location::RegisterLocation(EAX)); | 5715 summary->set_in(1, Location::WritableRegister()); |
5720 summary->set_in(1, Location::WritableRegister()); | 5716 // Output is a pair of registers. |
5721 // Output is a pair of registers. | 5717 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), |
5722 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX), | 5718 Location::RegisterLocation(EDX))); |
5723 Location::RegisterLocation(EDX))); | 5719 return summary; |
5724 return summary; | |
5725 } | |
5726 UNIMPLEMENTED(); | |
5727 return NULL; | |
5728 } | 5720 } |
5729 | 5721 |
5730 | 5722 |
5731 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5723 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5732 Label* deopt = NULL; | 5724 ASSERT(CanDeoptimize()); |
5733 if (CanDeoptimize()) { | 5725 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
5734 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 5726 Register left = locs()->in(0).reg(); |
| 5727 Register right = locs()->in(1).reg(); |
| 5728 ASSERT(locs()->out(0).IsPairLocation()); |
| 5729 PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 5730 Register result1 = pair->At(0).reg(); |
| 5731 Register result2 = pair->At(1).reg(); |
| 5732 if (RangeUtils::CanBeZero(divisor_range())) { |
| 5733 // Handle divide by zero in runtime. |
| 5734 __ testl(right, right); |
| 5735 __ j(ZERO, deopt); |
5735 } | 5736 } |
| 5737 ASSERT(left == EAX); |
| 5738 ASSERT((right != EDX) && (right != EAX)); |
| 5739 ASSERT(result1 == EAX); |
| 5740 ASSERT(result2 == EDX); |
| 5741 __ SmiUntag(left); |
| 5742 __ SmiUntag(right); |
| 5743 __ cdq(); // Sign extend EAX -> EDX:EAX. |
| 5744 __ idivl(right); // EAX: quotient, EDX: remainder. |
| 5745 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 5746 // case we cannot tag the result. |
| 5747 // TODO(srdjan): We could store instead untagged intermediate results in a |
| 5748 // typed array, but then the load indexed instructions would need to be |
| 5749 // able to deoptimize. |
| 5750 __ cmpl(EAX, Immediate(0x40000000)); |
| 5751 __ j(EQUAL, deopt); |
| 5752 // Modulo result (EDX) correction: |
| 5753 // res = left % right; |
| 5754 // if (res < 0) { |
| 5755 // if (right < 0) { |
| 5756 // res = res - right; |
| 5757 // } else { |
| 5758 // res = res + right; |
| 5759 // } |
| 5760 // } |
| 5761 Label done; |
| 5762 __ cmpl(EDX, Immediate(0)); |
| 5763 __ j(GREATER_EQUAL, &done, Assembler::kNearJump); |
| 5764 // Result is negative, adjust it. |
| 5765 if (RangeUtils::Overlaps(divisor_range(), -1, 1)) { |
| 5766 Label subtract; |
| 5767 __ cmpl(right, Immediate(0)); |
| 5768 __ j(LESS, &subtract, Assembler::kNearJump); |
| 5769 __ addl(EDX, right); |
| 5770 __ jmp(&done, Assembler::kNearJump); |
| 5771 __ Bind(&subtract); |
| 5772 __ subl(EDX, right); |
| 5773 } else if (divisor_range()->IsPositive()) { |
| 5774 // Right is positive. |
| 5775 __ addl(EDX, right); |
| 5776 } else { |
| 5777 // Right is negative. |
| 5778 __ subl(EDX, right); |
| 5779 } |
| 5780 __ Bind(&done); |
5736 | 5781 |
5737 if (kind() == MergedMathInstr::kTruncDivMod) { | 5782 __ SmiTag(EAX); |
5738 Register left = locs()->in(0).reg(); | 5783 __ SmiTag(EDX); |
5739 Register right = locs()->in(1).reg(); | |
5740 ASSERT(locs()->out(0).IsPairLocation()); | |
5741 PairLocation* pair = locs()->out(0).AsPairLocation(); | |
5742 Register result1 = pair->At(0).reg(); | |
5743 Register result2 = pair->At(1).reg(); | |
5744 Range* right_range = InputAt(1)->definition()->range(); | |
5745 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | |
5746 // Handle divide by zero in runtime. | |
5747 __ testl(right, right); | |
5748 __ j(ZERO, deopt); | |
5749 } | |
5750 ASSERT(left == EAX); | |
5751 ASSERT((right != EDX) && (right != EAX)); | |
5752 ASSERT(result1 == EAX); | |
5753 ASSERT(result2 == EDX); | |
5754 __ SmiUntag(left); | |
5755 __ SmiUntag(right); | |
5756 __ cdq(); // Sign extend EAX -> EDX:EAX. | |
5757 __ idivl(right); // EAX: quotient, EDX: remainder. | |
5758 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | |
5759 // case we cannot tag the result. | |
5760 // TODO(srdjan): We could store instead untagged intermediate results in a | |
5761 // typed array, but then the load indexed instructions would need to be | |
5762 // able to deoptimize. | |
5763 __ cmpl(EAX, Immediate(0x40000000)); | |
5764 __ j(EQUAL, deopt); | |
5765 // Modulo result (EDX) correction: | |
5766 // res = left % right; | |
5767 // if (res < 0) { | |
5768 // if (right < 0) { | |
5769 // res = res - right; | |
5770 // } else { | |
5771 // res = res + right; | |
5772 // } | |
5773 // } | |
5774 Label done; | |
5775 __ cmpl(EDX, Immediate(0)); | |
5776 __ j(GREATER_EQUAL, &done, Assembler::kNearJump); | |
5777 // Result is negative, adjust it. | |
5778 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) { | |
5779 Label subtract; | |
5780 __ cmpl(right, Immediate(0)); | |
5781 __ j(LESS, &subtract, Assembler::kNearJump); | |
5782 __ addl(EDX, right); | |
5783 __ jmp(&done, Assembler::kNearJump); | |
5784 __ Bind(&subtract); | |
5785 __ subl(EDX, right); | |
5786 } else if (right_range->IsPositive()) { | |
5787 // Right is positive. | |
5788 __ addl(EDX, right); | |
5789 } else { | |
5790 // Right is negative. | |
5791 __ subl(EDX, right); | |
5792 } | |
5793 __ Bind(&done); | |
5794 | |
5795 __ SmiTag(EAX); | |
5796 __ SmiTag(EDX); | |
5797 return; | |
5798 } | |
5799 UNIMPLEMENTED(); | |
5800 } | 5784 } |
5801 | 5785 |
5802 | 5786 |
5803 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5787 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
5804 Zone* zone, | 5788 Zone* zone, |
5805 bool opt) const { | 5789 bool opt) const { |
5806 return MakeCallSummary(zone); | 5790 return MakeCallSummary(zone); |
5807 } | 5791 } |
5808 | 5792 |
5809 | 5793 |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6150 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 6134 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
6151 if ((op_kind() == Token::kSHL) && CanDeoptimize()) { | 6135 if ((op_kind() == Token::kSHL) && CanDeoptimize()) { |
6152 summary->set_temp(0, Location::RequiresRegister()); | 6136 summary->set_temp(0, Location::RequiresRegister()); |
6153 summary->set_temp(1, Location::RequiresRegister()); | 6137 summary->set_temp(1, Location::RequiresRegister()); |
6154 } | 6138 } |
6155 summary->set_out(0, Location::SameAsFirstInput()); | 6139 summary->set_out(0, Location::SameAsFirstInput()); |
6156 return summary; | 6140 return summary; |
6157 } | 6141 } |
6158 | 6142 |
6159 | 6143 |
6160 static const intptr_t kMintShiftCountLimit = 63; | |
6161 | |
6162 bool ShiftMintOpInstr::has_shift_count_check() const { | |
6163 return !RangeUtils::IsWithin(right()->definition()->range(), 0, | |
6164 kMintShiftCountLimit); | |
6165 } | |
6166 | |
6167 | |
6168 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6144 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6169 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 6145 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
6170 Register left_lo = left_pair->At(0).reg(); | 6146 Register left_lo = left_pair->At(0).reg(); |
6171 Register left_hi = left_pair->At(1).reg(); | 6147 Register left_hi = left_pair->At(1).reg(); |
6172 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6148 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
6173 Register out_lo = out_pair->At(0).reg(); | 6149 Register out_lo = out_pair->At(0).reg(); |
6174 Register out_hi = out_pair->At(1).reg(); | 6150 Register out_hi = out_pair->At(1).reg(); |
6175 ASSERT(out_lo == left_lo); | 6151 ASSERT(out_lo == left_lo); |
6176 ASSERT(out_hi == left_hi); | 6152 ASSERT(out_hi == left_hi); |
6177 | 6153 |
(...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6932 __ Drop(1); | 6908 __ Drop(1); |
6933 __ popl(result); | 6909 __ popl(result); |
6934 } | 6910 } |
6935 | 6911 |
6936 | 6912 |
6937 } // namespace dart | 6913 } // namespace dart |
6938 | 6914 |
6939 #undef __ | 6915 #undef __ |
6940 | 6916 |
6941 #endif // defined TARGET_ARCH_IA32 | 6917 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |