Index: runtime/vm/intermediate_language_x64.cc |
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc |
index 4fc3b68d2845309a709d2ee451fe5ab1c93e408e..f872c21ad312a94cfa2cc6af393b535ddf37bba4 100644 |
--- a/runtime/vm/intermediate_language_x64.cc |
+++ b/runtime/vm/intermediate_language_x64.cc |
@@ -2879,8 +2879,9 @@ class CheckedSmiSlowPath : public SlowPathCode { |
LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
bool opt) const { |
+ bool is_shift = (op_kind() == Token::kSHL) || (op_kind() == Token::kSHR); |
const intptr_t kNumInputs = 2; |
- const intptr_t kNumTemps = 0; |
+ const intptr_t kNumTemps = is_shift ? 1 : 0; |
LocationSummary* summary = new(zone) LocationSummary( |
zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
summary->set_in(0, Location::RequiresRegister()); |
@@ -2889,6 +2890,8 @@ LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
case Token::kADD: |
case Token::kSUB: |
case Token::kMUL: |
+ case Token::kSHL: |
+ case Token::kSHR: |
summary->set_out(0, Location::RequiresRegister()); |
break; |
case Token::kBIT_OR: |
@@ -2899,6 +2902,9 @@ LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
default: |
UNIMPLEMENTED(); |
} |
+ if (is_shift) { |
+ summary->set_temp(0, Location::RegisterLocation(RCX)); |
+ } |
return summary; |
} |
@@ -2955,6 +2961,40 @@ void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
ASSERT(left == result); |
__ xorq(result, right); |
break; |
+ case Token::kSHL: |
+ ASSERT(result != right); |
+ ASSERT(locs()->temp(0).reg() == RCX); |
+ __ cmpq(right, Immediate(Smi::RawValue(Smi::kBits))); |
+ __ j(ABOVE_EQUAL, slow_path->entry_label()); |
+ |
+ __ movq(RCX, right); |
+ __ SmiUntag(RCX); |
+ __ movq(result, left); |
+ __ shlq(result, RCX); |
+ __ movq(TMP, result); |
+ __ sarq(TMP, RCX); |
+ __ cmpq(TMP, result); |
+ __ j(NOT_EQUAL, slow_path->entry_label()); |
+ break; |
+ case Token::kSHR: { |
+ Label shift_count_ok; |
+ ASSERT(result != right); |
+ ASSERT(locs()->temp(0).reg() == RCX); |
+ __ cmpq(right, Immediate(0)); |
+ __ j(LESS, slow_path->entry_label()); |
Florian Schneider
2016/11/11 18:12:20
Can you use unsigned compare "right < (unsigned)Sm
rmacnak
2016/11/11 21:29:02
Yes. As discussed offline this means something lik
|
+ |
+ __ movq(RCX, right); |
+ __ SmiUntag(RCX); |
+ __ cmpq(RCX, Immediate(0x3F)); |
+ __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump); |
+ __ movq(RCX, Immediate(0x3F)); |
+ __ Bind(&shift_count_ok); |
+ __ movq(result, left); |
+ __ SmiUntag(result); |
+ __ sarq(result, RCX); |
+ __ SmiTag(result); |
+ break; |
+ } |
default: |
UNIMPLEMENTED(); |
} |