| Index: runtime/vm/intermediate_language_x64.cc
|
| ===================================================================
|
| --- runtime/vm/intermediate_language_x64.cc (revision 17939)
|
| +++ runtime/vm/intermediate_language_x64.cc (working copy)
|
| @@ -1786,6 +1786,7 @@
|
| Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32();
|
| }
|
|
|
| +
|
| LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
|
| const intptr_t kNumInputs = 2;
|
|
|
| @@ -1805,12 +1806,19 @@
|
| }
|
|
|
| if (op_kind() == Token::kTRUNCDIV) {
|
| - const intptr_t kNumTemps = 1;
|
| + const intptr_t kNumTemps = RightIsPowerOfTwoConstant() ? 2 : 1;
|
| LocationSummary* summary =
|
| new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| // Both inputs must be writable because they will be untagged.
|
| summary->set_in(0, Location::RegisterLocation(RAX));
|
| - summary->set_in(1, Location::WritableRegister());
|
| + if (kNumTemps == 1) {
|
| + summary->set_in(1, Location::WritableRegister());
|
| + } else {
|
| + ConstantInstr* right_constant = right()->definition()->AsConstant();
|
| + summary->set_in(1, Location::Constant(right_constant->value()));
|
| + // Temporary to hold divisor constant.
|
| + summary->set_temp(1, Location::RegisterLocation(RBX));
|
| + }
|
| summary->set_out(Location::SameAsFirstInput());
|
| // Will be used for sign extension and division.
|
| summary->set_temp(0, Location::RegisterLocation(RDX));
|
| @@ -1877,6 +1885,34 @@
|
| if (deopt != NULL) __ j(OVERFLOW, deopt);
|
| break;
|
| }
|
| + case Token::kTRUNCDIV: {
|
| + Label use_div, done;
|
| + const intptr_t value = Smi::Cast(constant).Value();
|
| + ASSERT((value > 0) && Utils::IsPowerOfTwo(value));
|
| + __ cmpq(left, Immediate(0));
|
| + __ j(LESS, &use_div, Assembler::kNearJump);
|
| + // Positive division by power of two is an arithmetic left shift.
|
| + intptr_t shift_count = Utils::ShiftForPowerOfTwo(value) + kSmiTagSize;
|
| + __ sarq(left, Immediate(shift_count));
|
| + __ jmp(&done, Assembler::kNearJump);
|
| + __ Bind(&use_div);
|
| + Register right = locs()->temp(1).reg();
|
| + ASSERT(left == RAX);
|
| + ASSERT((right != RDX) && (right != RAX));
|
| + ASSERT(locs()->temp(0).reg() == RDX);
|
| + ASSERT(result == RAX);
|
| + __ movq(right, Immediate(value));
|
| + __ SmiUntag(left);
|
| + __ cqo(); // Sign extend RAX -> RDX:RAX.
|
| + __ idivq(right); // RAX: quotient, RDX: remainder.
|
| + // Check the corner case of dividing the 'MIN_SMI' with -1, in which
|
| + // case we cannot tag the result.
|
| + __ cmpq(result, Immediate(0x4000000000000000));
|
| + __ j(EQUAL, deopt);
|
| + __ Bind(&done);
|
| + __ SmiTag(result);
|
| + break;
|
| + }
|
| case Token::kBIT_AND: {
|
| // No overflow check.
|
| __ andq(left, Immediate(imm));
|
|
|