Chromium Code Reviews| Index: runtime/vm/intermediate_language_ia32.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_ia32.cc (revision 17939) |
| +++ runtime/vm/intermediate_language_ia32.cc (working copy) |
| @@ -1951,12 +1951,19 @@ |
| LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { |
| const intptr_t kNumInputs = 2; |
| 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(EAX)); |
| - 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(EBX)); |
| + } |
| summary->set_out(Location::SameAsFirstInput()); |
| // Will be used for sign extension and division. |
| summary->set_temp(0, Location::RegisterLocation(EDX)); |
| @@ -1996,8 +2003,7 @@ |
| ASSERT(left == result); |
| Label* deopt = NULL; |
| if (CanDeoptimize()) { |
| - deopt = compiler->AddDeoptStub(deopt_id(), |
| - kDeoptBinarySmiOp); |
| + deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
| } |
| if (locs()->in(1).IsConstant()) { |
| @@ -2022,6 +2028,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)); |
| + __ cmpl(left, Immediate(0)); |
|
Florian Schneider
2013/02/01 11:48:33
For checking x < 0, this sequence is 1 byte shorte
|
| + __ j(LESS, &use_div, Assembler::kNearJump); |
| + // Positive division by power of two is an arithmetic left shift. |
|
Florian Schneider
2013/02/01 11:48:33
In the comment s/left/right/.
srdjan
2013/02/01 22:57:54
Done.
|
| + intptr_t shift_count = Utils::ShiftForPowerOfTwo(value) + kSmiTagSize; |
| + __ sarl(left, Immediate(shift_count)); |
| + __ jmp(&done, Assembler::kNearJump); |
| + __ Bind(&use_div); |
|
Florian Schneider
2013/02/01 11:48:33
I think this could be improved for negative number
Florian Schneider
2013/02/04 13:04:02
Yes, my mistake: of course the absolute value of r
|
| + Register right = locs()->temp(1).reg(); |
| + ASSERT(left == EAX); |
| + ASSERT((right != EDX) && (right != EAX)); |
| + ASSERT(locs()->temp(0).reg() == EDX); |
| + ASSERT(result == EAX); |
| + __ movl(right, Immediate(value)); |
| + __ SmiUntag(left); |
| + __ cdq(); // Sign extend EAX -> EDX:EAX. |
| + __ idivl(right); // EAX: quotient, EDX: remainder. |
| + // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
|
Florian Schneider
2013/02/01 11:48:33
Since the right side is a known constant, you can
|
| + // case we cannot tag the result. |
| + __ cmpl(result, Immediate(0x40000000)); |
| + __ j(EQUAL, deopt); |
| + __ Bind(&done); |
| + __ SmiTag(result); |
| + break; |
| + } |
| case Token::kBIT_AND: { |
| // No overflow check. |
| __ andl(left, Immediate(imm)); |