Chromium Code Reviews| 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(); |
| } |