Index: runtime/vm/intermediate_language_ia32.cc |
=================================================================== |
--- runtime/vm/intermediate_language_ia32.cc (revision 38398) |
+++ runtime/vm/intermediate_language_ia32.cc (working copy) |
@@ -651,7 +651,7 @@ |
Register cid_reg = locs()->temp(0).reg(); |
Label* deopt = CanDeoptimize() ? |
- compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL; |
+ compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids) : NULL; |
const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
const ZoneGrowableArray<intptr_t>& data = cid_results(); |
@@ -5846,27 +5846,24 @@ |
switch (op_kind()) { |
case Token::kBIT_AND: |
case Token::kBIT_OR: |
- case Token::kBIT_XOR: { |
- const intptr_t kNumTemps = 0; |
- LocationSummary* summary = new(isolate) LocationSummary( |
- isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
- summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
- Location::RequiresRegister())); |
- summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
- Location::RequiresRegister())); |
- summary->set_out(0, Location::SameAsFirstInput()); |
- return summary; |
- } |
+ case Token::kBIT_XOR: |
case Token::kADD: |
- case Token::kSUB: { |
- const intptr_t kNumTemps = 0; |
+ case Token::kSUB: |
+ case Token::kMUL: { |
+ const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; |
LocationSummary* summary = new(isolate) LocationSummary( |
isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
- summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
- Location::RequiresRegister())); |
+ summary->set_in(0, (op_kind() == Token::kMUL) |
+ ? Location::Pair(Location::RegisterLocation(EAX), |
+ Location::RegisterLocation(EDX)) |
+ : Location::Pair(Location::RequiresRegister(), |
+ Location::RequiresRegister())); |
summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
Location::RequiresRegister())); |
summary->set_out(0, Location::SameAsFirstInput()); |
+ if (kNumTemps > 0) { |
+ summary->set_temp(0, Location::RequiresRegister()); |
+ } |
return summary; |
} |
default: |
@@ -5920,7 +5917,28 @@ |
} |
break; |
} |
- default: UNREACHABLE(); |
+ case Token::kMUL: { |
+ // The product of two signed 32-bit integers fits in a signed 64-bit |
+ // result without causing overflow. |
+ // We deopt on larger inputs. |
+ // TODO(regis): Range analysis may eliminate the deopt check. |
+ Register temp = locs()->temp(0).reg(); |
+ __ movl(temp, left_lo); |
+ __ sarl(temp, Immediate(31)); |
+ __ cmpl(temp, left_hi); |
+ __ j(NOT_EQUAL, deopt); |
+ __ movl(temp, right_lo); |
+ __ sarl(temp, Immediate(31)); |
+ __ cmpl(temp, right_hi); |
+ __ j(NOT_EQUAL, deopt); |
+ ASSERT(left_lo == EAX); |
+ __ imull(right_lo); // Result in EDX:EAX. |
+ ASSERT(out_lo == EAX); |
+ ASSERT(out_hi == EDX); |
+ break; |
+ } |
+ default: |
+ UNREACHABLE(); |
} |
if (FLAG_throw_on_javascript_int_overflow) { |
EmitJavascriptIntOverflowCheck(compiler, deopt, left_lo, left_hi); |
@@ -6113,7 +6131,6 @@ |
} |
default: |
UNREACHABLE(); |
- break; |
} |
__ Bind(&done); |
} |
@@ -6192,10 +6209,15 @@ |
LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
bool opt) const { |
const intptr_t kNumInputs = 2; |
- const intptr_t kNumTemps = 0; |
+ const intptr_t kNumTemps = (op_kind() == Token::kMUL) ? 1 : 0; |
LocationSummary* summary = new(isolate) LocationSummary( |
isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
- summary->set_in(0, Location::RequiresRegister()); |
+ if (op_kind() == Token::kMUL) { |
+ summary->set_in(0, Location::RegisterLocation(EAX)); |
+ summary->set_temp(0, Location::RegisterLocation(EDX)); |
+ } else { |
+ summary->set_in(0, Location::RequiresRegister()); |
+ } |
summary->set_in(1, Location::RequiresRegister()); |
summary->set_out(0, Location::SameAsFirstInput()); |
return summary; |
@@ -6210,19 +6232,24 @@ |
switch (op_kind()) { |
case Token::kBIT_AND: |
__ andl(out, right); |
- break; |
+ break; |
case Token::kBIT_OR: |
__ orl(out, right); |
- break; |
+ break; |
case Token::kBIT_XOR: |
__ xorl(out, right); |
- break; |
+ break; |
case Token::kADD: |
__ addl(out, right); |
- break; |
+ break; |
case Token::kSUB: |
__ subl(out, right); |
- break; |
+ break; |
+ case Token::kMUL: |
+ __ mull(right); // Result in EDX:EAX. |
+ ASSERT(out == EAX); |
+ ASSERT(locs()->temp(0).reg() == EDX); |
+ break; |
default: |
UNREACHABLE(); |
} |