| 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 |