Chromium Code Reviews| Index: runtime/vm/intermediate_language_x64.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_x64.cc (revision 30005) |
| +++ runtime/vm/intermediate_language_x64.cc (working copy) |
| @@ -2164,6 +2164,7 @@ |
| (op_kind() != Token::kTRUNCDIV) && |
| (op_kind() != Token::kSHL) && |
| (op_kind() != Token::kMUL) && |
| + (op_kind() != Token::kMOD) && |
| CanBeImmediate(right_constant->value())) { |
| const intptr_t kNumTemps = 0; |
| LocationSummary* summary = |
| @@ -2193,6 +2194,17 @@ |
| summary->set_temp(0, Location::RegisterLocation(RDX)); |
| } |
| return summary; |
| + } else if (op_kind() == Token::kMOD) { |
| + const intptr_t kNumTemps = 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(RDX)); |
| + summary->set_in(1, Location::WritableRegister()); |
| + summary->set_out(Location::SameAsFirstInput()); |
| + // Will be used for sign extension and division. |
| + summary->set_temp(0, Location::RegisterLocation(RAX)); |
| + return summary; |
| } else if (op_kind() == Token::kSHR) { |
| const intptr_t kNumTemps = 0; |
| LocationSummary* summary = |
| @@ -2477,6 +2489,71 @@ |
| __ SmiTag(result); |
| break; |
| } |
| + case Token::kMOD: { |
| + Label not_32bit, div_done; |
| + |
| + Register temp = locs()->temp(0).reg(); |
| + ASSERT(left == RDX); |
| + ASSERT((right != RDX) && (right != RAX)); |
| + ASSERT(temp == RAX); |
| + ASSERT(result == RDX); |
| + // Handle divide by zero in runtime. |
| + __ testq(right, right); |
| + __ j(ZERO, deopt); |
| + // Check if both operands fit into 32bits as idiv with 64bit operands |
| + // requires twice as many cycles and has much higher latency. |
| + // We are checking this before untagging them to avoid corner case |
| + // dividing INT_MAX by -1 that raises exception because quotient is |
| + // too large for 32bit register. |
| + __ movsxd(temp, left); |
| + __ cmpq(temp, left); |
| + __ j(NOT_EQUAL, ¬_32bit); |
| + __ movsxd(temp, right); |
| + __ cmpq(temp, right); |
| + __ j(NOT_EQUAL, ¬_32bit); |
| + // Both operands are 31bit smis. Divide using 32bit idiv. |
| + __ SmiUntag(left); |
| + __ SmiUntag(right); |
| + __ movq(RAX, RDX); |
| + __ cdq(); |
| + __ idivl(right); |
| + __ movsxd(result, result); |
| + __ jmp(&div_done); |
| + |
| + // Divide using 64bit idiv. |
| + __ Bind(¬_32bit); |
| + __ SmiUntag(left); |
| + __ SmiUntag(right); |
| + __ movq(RAX, RDX); |
| + __ 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. |
| + __ CompareImmediate(result, Immediate(0x4000000000000000), PP); |
|
zra
2013/11/07 16:40:06
I couldn't find an existing test for this case. Is
srdjan
2013/11/07 21:26:10
Copy and paste error, removing. The other architec
|
| + __ j(EQUAL, deopt); |
| + __ Bind(&div_done); |
| + // res = left % right; |
| + // if (res < 0) { |
| + // if (right < 0) { |
| + // res = res - right; |
| + // } else { |
| + // res = res + right; |
| + // } |
| + // } |
| + Label subtract, all_done; |
| + __ cmpq(result, Immediate(0)); |
| + __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump); |
| + // Result is negative, adjust it. |
| + __ cmpq(right, Immediate(0)); |
| + __ j(LESS, &subtract, Assembler::kNearJump); |
| + __ addq(result, right); |
| + __ jmp(&all_done, Assembler::kNearJump); |
| + __ Bind(&subtract); |
| + __ subq(result, right); |
| + __ Bind(&all_done); |
| + __ SmiTag(result); |
| + break; |
| + } |
| case Token::kSHR: { |
| if (CanDeoptimize()) { |
| __ CompareImmediate(right, Immediate(0), PP); |
| @@ -2506,11 +2583,6 @@ |
| UNREACHABLE(); |
| break; |
| } |
| - case Token::kMOD: { |
| - // TODO(srdjan): Implement. |
| - UNREACHABLE(); |
| - break; |
| - } |
| case Token::kOR: |
| case Token::kAND: { |
| // Flow graph builder has dissected this operation to guarantee correct |