Index: runtime/vm/intermediate_language_x64.cc |
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc |
index 597f67a6f680e151c17ee7651986cca271d61142..a38509d77ac0da933c367627f23ba55948abd154 100644 |
--- a/runtime/vm/intermediate_language_x64.cc |
+++ b/runtime/vm/intermediate_language_x64.cc |
@@ -2845,8 +2845,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()); |
@@ -2855,6 +2856,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: |
@@ -2865,6 +2868,9 @@ LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
default: |
UNIMPLEMENTED(); |
} |
+ if (is_shift) { |
+ summary->set_temp(0, Location::RegisterLocation(RCX)); |
+ } |
return summary; |
} |
@@ -2921,6 +2927,36 @@ 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(Smi::RawValue(Smi::kBits))); |
+ __ j(ABOVE_EQUAL, slow_path->entry_label()); |
+ |
+ __ movq(RCX, right); |
+ __ SmiUntag(RCX); |
+ __ movq(result, left); |
+ __ SmiUntag(result); |
+ __ sarq(result, RCX); |
+ __ SmiTag(result); |
+ break; |
+ } |
default: |
UNIMPLEMENTED(); |
} |