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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
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 2742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2753 __ cmpq(left, temp); | 2753 __ cmpq(left, temp); |
2754 __ j(NOT_EQUAL, deopt); // Overflow. | 2754 __ j(NOT_EQUAL, deopt); // Overflow. |
2755 } | 2755 } |
2756 // Shift for result now we know there is no overflow. | 2756 // Shift for result now we know there is no overflow. |
2757 __ shlq(left, Immediate(value)); | 2757 __ shlq(left, Immediate(value)); |
2758 return; | 2758 return; |
2759 } | 2759 } |
2760 | 2760 |
2761 // Right (locs.in(1)) is not constant. | 2761 // Right (locs.in(1)) is not constant. |
2762 Register right = locs.in(1).reg(); | 2762 Register right = locs.in(1).reg(); |
2763 Range* right_range = shift_left->right()->definition()->range(); | 2763 Range* right_range = shift_left->right_range(); |
2764 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { | 2764 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { |
2765 // TODO(srdjan): Implement code below for is_truncating(). | 2765 // TODO(srdjan): Implement code below for is_truncating(). |
2766 // If left is constant, we know the maximal allowed size for right. | 2766 // If left is constant, we know the maximal allowed size for right. |
2767 const Object& obj = shift_left->left()->BoundConstant(); | 2767 const Object& obj = shift_left->left()->BoundConstant(); |
2768 if (obj.IsSmi()) { | 2768 if (obj.IsSmi()) { |
2769 const intptr_t left_int = Smi::Cast(obj).Value(); | 2769 const intptr_t left_int = Smi::Cast(obj).Value(); |
2770 if (left_int == 0) { | 2770 if (left_int == 0) { |
2771 __ CompareImmediate(right, Immediate(0)); | 2771 __ CompareImmediate(right, Immediate(0)); |
2772 __ j(NEGATIVE, deopt); | 2772 __ j(NEGATIVE, deopt); |
2773 return; | 2773 return; |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3353 } | 3353 } |
3354 default: | 3354 default: |
3355 UNREACHABLE(); | 3355 UNREACHABLE(); |
3356 break; | 3356 break; |
3357 } | 3357 } |
3358 return; | 3358 return; |
3359 } // locs()->in(1).IsStackSlot(). | 3359 } // locs()->in(1).IsStackSlot(). |
3360 | 3360 |
3361 // if locs()->in(1).IsRegister. | 3361 // if locs()->in(1).IsRegister. |
3362 Register right = locs()->in(1).reg(); | 3362 Register right = locs()->in(1).reg(); |
3363 Range* right_range = this->right()->definition()->range(); | |
3364 switch (op_kind()) { | 3363 switch (op_kind()) { |
3365 case Token::kADD: { | 3364 case Token::kADD: { |
3366 __ addq(left, right); | 3365 __ addq(left, right); |
3367 if (deopt != NULL) __ j(OVERFLOW, deopt); | 3366 if (deopt != NULL) __ j(OVERFLOW, deopt); |
3368 break; | 3367 break; |
3369 } | 3368 } |
3370 case Token::kSUB: { | 3369 case Token::kSUB: { |
3371 __ subq(left, right); | 3370 __ subq(left, right); |
3372 if (deopt != NULL) __ j(OVERFLOW, deopt); | 3371 if (deopt != NULL) __ j(OVERFLOW, deopt); |
3373 break; | 3372 break; |
(...skipping 20 matching lines...) Expand all Loading... |
3394 break; | 3393 break; |
3395 } | 3394 } |
3396 case Token::kTRUNCDIV: { | 3395 case Token::kTRUNCDIV: { |
3397 Label not_32bit, done; | 3396 Label not_32bit, done; |
3398 | 3397 |
3399 Register temp = locs()->temp(0).reg(); | 3398 Register temp = locs()->temp(0).reg(); |
3400 ASSERT(left == RAX); | 3399 ASSERT(left == RAX); |
3401 ASSERT((right != RDX) && (right != RAX)); | 3400 ASSERT((right != RDX) && (right != RAX)); |
3402 ASSERT(temp == RDX); | 3401 ASSERT(temp == RDX); |
3403 ASSERT(result == RAX); | 3402 ASSERT(result == RAX); |
3404 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3403 if (RangeUtils::CanBeZero(right_range())) { |
3405 // Handle divide by zero in runtime. | 3404 // Handle divide by zero in runtime. |
3406 __ testq(right, right); | 3405 __ testq(right, right); |
3407 __ j(ZERO, deopt); | 3406 __ j(ZERO, deopt); |
3408 } | 3407 } |
3409 // Check if both operands fit into 32bits as idiv with 64bit operands | 3408 // Check if both operands fit into 32bits as idiv with 64bit operands |
3410 // requires twice as many cycles and has much higher latency. | 3409 // requires twice as many cycles and has much higher latency. |
3411 // We are checking this before untagging them to avoid corner case | 3410 // We are checking this before untagging them to avoid corner case |
3412 // dividing INT_MAX by -1 that raises exception because quotient is | 3411 // dividing INT_MAX by -1 that raises exception because quotient is |
3413 // too large for 32bit register. | 3412 // too large for 32bit register. |
3414 __ movsxd(temp, left); | 3413 __ movsxd(temp, left); |
(...skipping 26 matching lines...) Expand all Loading... |
3441 break; | 3440 break; |
3442 } | 3441 } |
3443 case Token::kMOD: { | 3442 case Token::kMOD: { |
3444 Label not_32bit, div_done; | 3443 Label not_32bit, div_done; |
3445 | 3444 |
3446 Register temp = locs()->temp(0).reg(); | 3445 Register temp = locs()->temp(0).reg(); |
3447 ASSERT(left == RDX); | 3446 ASSERT(left == RDX); |
3448 ASSERT((right != RDX) && (right != RAX)); | 3447 ASSERT((right != RDX) && (right != RAX)); |
3449 ASSERT(temp == RAX); | 3448 ASSERT(temp == RAX); |
3450 ASSERT(result == RDX); | 3449 ASSERT(result == RDX); |
3451 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | 3450 if (RangeUtils::CanBeZero(right_range())) { |
3452 // Handle divide by zero in runtime. | 3451 // Handle divide by zero in runtime. |
3453 __ testq(right, right); | 3452 __ testq(right, right); |
3454 __ j(ZERO, deopt); | 3453 __ j(ZERO, deopt); |
3455 } | 3454 } |
3456 // Check if both operands fit into 32bits as idiv with 64bit operands | 3455 // Check if both operands fit into 32bits as idiv with 64bit operands |
3457 // requires twice as many cycles and has much higher latency. | 3456 // requires twice as many cycles and has much higher latency. |
3458 // We are checking this before untagging them to avoid corner case | 3457 // We are checking this before untagging them to avoid corner case |
3459 // dividing INT_MAX by -1 that raises exception because quotient is | 3458 // dividing INT_MAX by -1 that raises exception because quotient is |
3460 // too large for 32bit register. | 3459 // too large for 32bit register. |
3461 __ movsxd(temp, left); | 3460 __ movsxd(temp, left); |
(...skipping 24 matching lines...) Expand all Loading... |
3486 // if (right < 0) { | 3485 // if (right < 0) { |
3487 // res = res - right; | 3486 // res = res - right; |
3488 // } else { | 3487 // } else { |
3489 // res = res + right; | 3488 // res = res + right; |
3490 // } | 3489 // } |
3491 // } | 3490 // } |
3492 Label all_done; | 3491 Label all_done; |
3493 __ cmpq(result, Immediate(0)); | 3492 __ cmpq(result, Immediate(0)); |
3494 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump); | 3493 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump); |
3495 // Result is negative, adjust it. | 3494 // Result is negative, adjust it. |
3496 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) { | 3495 if (RangeUtils::Overlaps(right_range(), -1, 1)) { |
3497 Label subtract; | 3496 Label subtract; |
3498 __ cmpq(right, Immediate(0)); | 3497 __ cmpq(right, Immediate(0)); |
3499 __ j(LESS, &subtract, Assembler::kNearJump); | 3498 __ j(LESS, &subtract, Assembler::kNearJump); |
3500 __ addq(result, right); | 3499 __ addq(result, right); |
3501 __ jmp(&all_done, Assembler::kNearJump); | 3500 __ jmp(&all_done, Assembler::kNearJump); |
3502 __ Bind(&subtract); | 3501 __ Bind(&subtract); |
3503 __ subq(result, right); | 3502 __ subq(result, right); |
3504 } else if (right_range->IsPositive()) { | 3503 } else if (right_range()->IsPositive()) { |
3505 // Right is positive. | 3504 // Right is positive. |
3506 __ addq(result, right); | 3505 __ addq(result, right); |
3507 } else { | 3506 } else { |
3508 // Right is negative. | 3507 // Right is negative. |
3509 __ subq(result, right); | 3508 __ subq(result, right); |
3510 } | 3509 } |
3511 __ Bind(&all_done); | 3510 __ Bind(&all_done); |
3512 __ SmiTag(result); | 3511 __ SmiTag(result); |
3513 break; | 3512 break; |
3514 } | 3513 } |
3515 case Token::kSHR: { | 3514 case Token::kSHR: { |
3516 if (CanDeoptimize()) { | 3515 if (CanDeoptimize()) { |
3517 __ CompareImmediate(right, Immediate(0)); | 3516 __ CompareImmediate(right, Immediate(0)); |
3518 __ j(LESS, deopt); | 3517 __ j(LESS, deopt); |
3519 } | 3518 } |
3520 __ SmiUntag(right); | 3519 __ SmiUntag(right); |
3521 // sarq operation masks the count to 6 bits. | 3520 // sarq operation masks the count to 6 bits. |
3522 const intptr_t kCountLimit = 0x3F; | 3521 const intptr_t kCountLimit = 0x3F; |
3523 if ((right_range == NULL) || | 3522 if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) { |
3524 !right_range->OnlyLessThanOrEqualTo(kCountLimit)) { | |
3525 __ CompareImmediate(right, Immediate(kCountLimit)); | 3523 __ CompareImmediate(right, Immediate(kCountLimit)); |
3526 Label count_ok; | 3524 Label count_ok; |
3527 __ j(LESS, &count_ok, Assembler::kNearJump); | 3525 __ j(LESS, &count_ok, Assembler::kNearJump); |
3528 __ LoadImmediate(right, Immediate(kCountLimit)); | 3526 __ LoadImmediate(right, Immediate(kCountLimit)); |
3529 __ Bind(&count_ok); | 3527 __ Bind(&count_ok); |
3530 } | 3528 } |
3531 ASSERT(right == RCX); // Count must be in RCX | 3529 ASSERT(right == RCX); // Count must be in RCX |
3532 __ SmiUntag(left); | 3530 __ SmiUntag(left); |
3533 __ sarq(left, right); | 3531 __ sarq(left, right); |
3534 __ SmiTag(left); | 3532 __ SmiTag(left); |
(...skipping 2126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5661 __ movaps(out, in); | 5659 __ movaps(out, in); |
5662 } else { | 5660 } else { |
5663 ASSERT(representation() == kTagged); | 5661 ASSERT(representation() == kTagged); |
5664 Register out = locs()->out(0).reg(); | 5662 Register out = locs()->out(0).reg(); |
5665 Register in = in_loc.reg(); | 5663 Register in = in_loc.reg(); |
5666 __ movq(out, in); | 5664 __ movq(out, in); |
5667 } | 5665 } |
5668 } | 5666 } |
5669 | 5667 |
5670 | 5668 |
5671 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 5669 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, |
5672 bool opt) const { | 5670 bool opt) const { |
5673 if (kind() == MergedMathInstr::kTruncDivMod) { | 5671 const intptr_t kNumInputs = 2; |
5674 const intptr_t kNumInputs = 2; | 5672 const intptr_t kNumTemps = 0; |
5675 const intptr_t kNumTemps = 0; | 5673 LocationSummary* summary = new (zone) |
5676 LocationSummary* summary = new (zone) | 5674 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5677 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5675 // Both inputs must be writable because they will be untagged. |
5678 // Both inputs must be writable because they will be untagged. | 5676 summary->set_in(0, Location::RegisterLocation(RAX)); |
5679 summary->set_in(0, Location::RegisterLocation(RAX)); | 5677 summary->set_in(1, Location::WritableRegister()); |
5680 summary->set_in(1, Location::WritableRegister()); | 5678 summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX), |
5681 summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX), | 5679 Location::RegisterLocation(RDX))); |
5682 Location::RegisterLocation(RDX))); | 5680 return summary; |
5683 return summary; | |
5684 } | |
5685 UNIMPLEMENTED(); | |
5686 return NULL; | |
5687 } | 5681 } |
5688 | 5682 |
5689 | 5683 |
5690 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5684 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5691 Label* deopt = NULL; | 5685 ASSERT(CanDeoptimize()); |
5692 if (CanDeoptimize()) { | 5686 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
5693 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 5687 Register left = locs()->in(0).reg(); |
| 5688 Register right = locs()->in(1).reg(); |
| 5689 ASSERT(locs()->out(0).IsPairLocation()); |
| 5690 PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 5691 Register result1 = pair->At(0).reg(); |
| 5692 Register result2 = pair->At(1).reg(); |
| 5693 Label not_32bit, done; |
| 5694 Register temp = RDX; |
| 5695 ASSERT(left == RAX); |
| 5696 ASSERT((right != RDX) && (right != RAX)); |
| 5697 ASSERT(result1 == RAX); |
| 5698 ASSERT(result2 == RDX); |
| 5699 if (RangeUtils::CanBeZero(divisor_range())) { |
| 5700 // Handle divide by zero in runtime. |
| 5701 __ testq(right, right); |
| 5702 __ j(ZERO, deopt); |
5694 } | 5703 } |
5695 if (kind() == MergedMathInstr::kTruncDivMod) { | 5704 // Check if both operands fit into 32bits as idiv with 64bit operands |
5696 Register left = locs()->in(0).reg(); | 5705 // requires twice as many cycles and has much higher latency. |
5697 Register right = locs()->in(1).reg(); | 5706 // We are checking this before untagging them to avoid corner case |
5698 ASSERT(locs()->out(0).IsPairLocation()); | 5707 // dividing INT_MAX by -1 that raises exception because quotient is |
5699 PairLocation* pair = locs()->out(0).AsPairLocation(); | 5708 // too large for 32bit register. |
5700 Register result1 = pair->At(0).reg(); | 5709 __ movsxd(temp, left); |
5701 Register result2 = pair->At(1).reg(); | 5710 __ cmpq(temp, left); |
5702 Label not_32bit, done; | 5711 __ j(NOT_EQUAL, ¬_32bit); |
5703 Register temp = RDX; | 5712 __ movsxd(temp, right); |
5704 ASSERT(left == RAX); | 5713 __ cmpq(temp, right); |
5705 ASSERT((right != RDX) && (right != RAX)); | 5714 __ j(NOT_EQUAL, ¬_32bit); |
5706 ASSERT(result1 == RAX); | |
5707 ASSERT(result2 == RDX); | |
5708 Range* right_range = InputAt(1)->definition()->range(); | |
5709 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { | |
5710 // Handle divide by zero in runtime. | |
5711 __ testq(right, right); | |
5712 __ j(ZERO, deopt); | |
5713 } | |
5714 // Check if both operands fit into 32bits as idiv with 64bit operands | |
5715 // requires twice as many cycles and has much higher latency. | |
5716 // We are checking this before untagging them to avoid corner case | |
5717 // dividing INT_MAX by -1 that raises exception because quotient is | |
5718 // too large for 32bit register. | |
5719 __ movsxd(temp, left); | |
5720 __ cmpq(temp, left); | |
5721 __ j(NOT_EQUAL, ¬_32bit); | |
5722 __ movsxd(temp, right); | |
5723 __ cmpq(temp, right); | |
5724 __ j(NOT_EQUAL, ¬_32bit); | |
5725 | 5715 |
5726 // Both operands are 31bit smis. Divide using 32bit idiv. | 5716 // Both operands are 31bit smis. Divide using 32bit idiv. |
5727 __ SmiUntag(left); | 5717 __ SmiUntag(left); |
5728 __ SmiUntag(right); | 5718 __ SmiUntag(right); |
5729 __ cdq(); | 5719 __ cdq(); |
5730 __ idivl(right); | 5720 __ idivl(right); |
5731 __ movsxd(RAX, RAX); | 5721 __ movsxd(RAX, RAX); |
5732 __ movsxd(RDX, RDX); | 5722 __ movsxd(RDX, RDX); |
5733 __ jmp(&done); | 5723 __ jmp(&done); |
5734 | 5724 |
5735 // Divide using 64bit idiv. | 5725 // Divide using 64bit idiv. |
5736 __ Bind(¬_32bit); | 5726 __ Bind(¬_32bit); |
5737 __ SmiUntag(left); | 5727 __ SmiUntag(left); |
5738 __ SmiUntag(right); | 5728 __ SmiUntag(right); |
5739 __ cqo(); // Sign extend RAX -> RDX:RAX. | 5729 __ cqo(); // Sign extend RAX -> RDX:RAX. |
5740 __ idivq(right); // RAX: quotient, RDX: remainder. | 5730 __ idivq(right); // RAX: quotient, RDX: remainder. |
5741 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 5731 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
5742 // case we cannot tag the result. | 5732 // case we cannot tag the result. |
5743 __ CompareImmediate(RAX, Immediate(0x4000000000000000)); | 5733 __ CompareImmediate(RAX, Immediate(0x4000000000000000)); |
5744 __ j(EQUAL, deopt); | 5734 __ j(EQUAL, deopt); |
5745 __ Bind(&done); | 5735 __ Bind(&done); |
5746 | 5736 |
5747 // Modulo correction (RDX). | 5737 // Modulo correction (RDX). |
5748 // res = left % right; | 5738 // res = left % right; |
5749 // if (res < 0) { | 5739 // if (res < 0) { |
5750 // if (right < 0) { | 5740 // if (right < 0) { |
5751 // res = res - right; | 5741 // res = res - right; |
5752 // } else { | 5742 // } else { |
5753 // res = res + right; | 5743 // res = res + right; |
5754 // } | 5744 // } |
5755 // } | 5745 // } |
5756 Label all_done; | 5746 Label all_done; |
5757 __ cmpq(RDX, Immediate(0)); | 5747 __ cmpq(RDX, Immediate(0)); |
5758 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump); | 5748 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump); |
5759 // Result is negative, adjust it. | 5749 // Result is negative, adjust it. |
5760 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) { | 5750 if ((divisor_range() == NULL) || divisor_range()->Overlaps(-1, 1)) { |
5761 Label subtract; | 5751 Label subtract; |
5762 __ cmpq(right, Immediate(0)); | 5752 __ cmpq(right, Immediate(0)); |
5763 __ j(LESS, &subtract, Assembler::kNearJump); | 5753 __ j(LESS, &subtract, Assembler::kNearJump); |
5764 __ addq(RDX, right); | 5754 __ addq(RDX, right); |
5765 __ jmp(&all_done, Assembler::kNearJump); | 5755 __ jmp(&all_done, Assembler::kNearJump); |
5766 __ Bind(&subtract); | 5756 __ Bind(&subtract); |
5767 __ subq(RDX, right); | 5757 __ subq(RDX, right); |
5768 } else if (right_range->IsPositive()) { | 5758 } else if (divisor_range()->IsPositive()) { |
5769 // Right is positive. | 5759 // Right is positive. |
5770 __ addq(RDX, right); | 5760 __ addq(RDX, right); |
5771 } else { | 5761 } else { |
5772 // Right is negative. | 5762 // Right is negative. |
5773 __ subq(RDX, right); | 5763 __ subq(RDX, right); |
5774 } | 5764 } |
5775 __ Bind(&all_done); | 5765 __ Bind(&all_done); |
5776 | 5766 |
5777 __ SmiTag(RAX); | 5767 __ SmiTag(RAX); |
5778 __ SmiTag(RDX); | 5768 __ SmiTag(RDX); |
5779 // Note that the result of an integer division/modulo of two | 5769 // Note that the result of an integer division/modulo of two |
5780 // in-range arguments, cannot create out-of-range result. | 5770 // in-range arguments, cannot create out-of-range result. |
5781 return; | |
5782 } | |
5783 UNIMPLEMENTED(); | |
5784 } | 5771 } |
5785 | 5772 |
5786 | 5773 |
5787 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5774 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
5788 Zone* zone, | 5775 Zone* zone, |
5789 bool opt) const { | 5776 bool opt) const { |
5790 return MakeCallSummary(zone); | 5777 return MakeCallSummary(zone); |
5791 } | 5778 } |
5792 | 5779 |
5793 | 5780 |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6119 | 6106 |
6120 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6107 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6121 ASSERT(op_kind() == Token::kBIT_NOT); | 6108 ASSERT(op_kind() == Token::kBIT_NOT); |
6122 const Register left = locs()->in(0).reg(); | 6109 const Register left = locs()->in(0).reg(); |
6123 const Register out = locs()->out(0).reg(); | 6110 const Register out = locs()->out(0).reg(); |
6124 ASSERT(out == left); | 6111 ASSERT(out == left); |
6125 __ notq(left); | 6112 __ notq(left); |
6126 } | 6113 } |
6127 | 6114 |
6128 | 6115 |
6129 static const intptr_t kMintShiftCountLimit = 63; | |
6130 | |
6131 bool ShiftMintOpInstr::has_shift_count_check() const { | |
6132 return !RangeUtils::IsWithin(right()->definition()->range(), 0, | |
6133 kMintShiftCountLimit); | |
6134 } | |
6135 | |
6136 | |
6137 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 6116 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
6138 bool opt) const { | 6117 bool opt) const { |
6139 const intptr_t kNumInputs = 2; | 6118 const intptr_t kNumInputs = 2; |
6140 const intptr_t kNumTemps = can_overflow() ? 1 : 0; | 6119 const intptr_t kNumTemps = can_overflow() ? 1 : 0; |
6141 LocationSummary* summary = new (zone) | 6120 LocationSummary* summary = new (zone) |
6142 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6121 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6143 summary->set_in(0, Location::RequiresRegister()); | 6122 summary->set_in(0, Location::RequiresRegister()); |
6144 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 6123 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
6145 if (kNumTemps > 0) { | 6124 if (kNumTemps > 0) { |
6146 summary->set_temp(0, Location::RequiresRegister()); | 6125 summary->set_temp(0, Location::RequiresRegister()); |
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6790 __ Drop(1); | 6769 __ Drop(1); |
6791 __ popq(result); | 6770 __ popq(result); |
6792 } | 6771 } |
6793 | 6772 |
6794 | 6773 |
6795 } // namespace dart | 6774 } // namespace dart |
6796 | 6775 |
6797 #undef __ | 6776 #undef __ |
6798 | 6777 |
6799 #endif // defined TARGET_ARCH_X64 | 6778 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |