Chromium Code Reviews| Index: runtime/vm/intermediate_language_ia32.cc |
| =================================================================== |
| --- runtime/vm/intermediate_language_ia32.cc (revision 30005) |
| +++ runtime/vm/intermediate_language_ia32.cc (working copy) |
| @@ -2206,6 +2206,17 @@ |
| summary->set_temp(0, Location::RegisterLocation(EDX)); |
| } |
| 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(EDX)); |
| + 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(EAX)); |
| + return summary; |
| } else if (op_kind() == Token::kSHR) { |
| const intptr_t kNumTemps = 0; |
| LocationSummary* summary = |
| @@ -2451,6 +2462,41 @@ |
| __ SmiTag(result); |
| break; |
| } |
| + case Token::kMOD: { |
| + // Handle divide by zero in runtime. |
| + __ testl(right, right); |
| + __ j(ZERO, deopt); |
|
sra1
2013/11/07 00:50:23
This should be unnecessary in cases where right ==
srdjan
2013/11/07 05:26:52
Yes. I had the code in and have removed it in orde
sra1
2013/11/08 01:40:16
I see. The latency of idiv covers everything else
srdjan
2013/11/08 16:02:53
Yes, preliminary measurement show a big benefit of
|
| + ASSERT(left == EDX); |
| + ASSERT((right != EDX) && (right != EAX)); |
| + ASSERT(locs()->temp(0).reg() == EAX); |
| + ASSERT(result == EDX); |
| + __ SmiUntag(left); |
| + __ SmiUntag(right); |
| + __ movl(EAX, EDX); |
| + __ cdq(); // Sign extend EAX -> EDX:EAX. |
| + __ idivl(right); // EAX: quotient, EDX: remainder. |
| + // res = left % right; |
| + // if (res < 0) { |
| + // if (right < 0) { |
| + // res = res - right; |
| + // } else { |
| + // res = res + right; |
| + // } |
| + // } |
| + Label subtract, done; |
| + __ cmpl(result, Immediate(0)); |
| + __ j(GREATER_EQUAL, &done, Assembler::kNearJump); |
|
sra1
2013/11/07 00:50:23
You might be able to test whether this is necessar
srdjan
2013/11/07 05:26:52
Ditto. I have not used the val range, but the rang
|
| + // Result is negative, adjust it. |
| + __ cmpl(right, Immediate(0)); |
| + __ j(LESS, &subtract, Assembler::kNearJump); |
| + __ addl(result, right); |
| + __ jmp(&done, Assembler::kNearJump); |
| + __ Bind(&subtract); |
| + __ subl(result, right); |
| + __ Bind(&done); |
| + __ SmiTag(result); |
| + break; |
| + } |
| case Token::kSHR: { |
| if (CanDeoptimize()) { |
| __ cmpl(right, Immediate(0)); |
| @@ -2480,11 +2526,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 |