| Index: runtime/vm/intermediate_language_x64.cc
|
| diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
|
| index 894aae549f483a4eb0329b412d880e503877e1b4..82e1566456b333a7f865f6e2c6cfbc1fa7fade67 100644
|
| --- a/runtime/vm/intermediate_language_x64.cc
|
| +++ b/runtime/vm/intermediate_language_x64.cc
|
| @@ -174,8 +174,11 @@ LocationSummary* ConstantComp::MakeLocationSummary() const {
|
|
|
|
|
| void ConstantComp::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| - Register result = locs()->out().reg();
|
| - __ LoadObject(result, value());
|
| + // Register allocator drops constant definitions that have no uses.
|
| + if (!locs()->out().IsInvalid()) {
|
| + Register result = locs()->out().reg();
|
| + __ LoadObject(result, value());
|
| + }
|
| }
|
|
|
|
|
| @@ -1449,8 +1452,29 @@ void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| }
|
|
|
|
|
| +static bool CanBeImmediate(const Object& constant) {
|
| + return constant.IsSmi() &&
|
| + Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32();
|
| +}
|
| +
|
| LocationSummary* BinarySmiOpComp::MakeLocationSummary() const {
|
| const intptr_t kNumInputs = 2;
|
| +
|
| + ConstantComp* right_constant = right()->definition()->AsConstant();
|
| + if ((right_constant != NULL) &&
|
| + (op_kind() != Token::kTRUNCDIV) &&
|
| + (op_kind() != Token::kSHL) &&
|
| + (op_kind() != Token::kMUL) &&
|
| + CanBeImmediate(right_constant->value())) {
|
| + const intptr_t kNumTemps = 0;
|
| + LocationSummary* summary =
|
| + new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| + summary->set_in(0, Location::RequiresRegister());
|
| + summary->set_in(1, Location::Constant(right_constant->value()));
|
| + summary->set_out(Location::SameAsFirstInput());
|
| + return summary;
|
| + }
|
| +
|
| if (op_kind() == Token::kTRUNCDIV) {
|
| const intptr_t kNumTemps = 3;
|
| LocationSummary* summary =
|
| @@ -1496,7 +1520,6 @@ LocationSummary* BinarySmiOpComp::MakeLocationSummary() const {
|
|
|
| void BinarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| Register left = locs()->in(0).reg();
|
| - Register right = locs()->in(1).reg();
|
| Register result = locs()->out().reg();
|
| ASSERT(left == result);
|
| Label* deopt = NULL;
|
| @@ -1510,6 +1533,68 @@ void BinarySmiOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
|
| kDeoptBinarySmiOp);
|
| }
|
| +
|
| + if (locs()->in(1).IsConstant()) {
|
| + const Object& constant = locs()->in(1).constant();
|
| + ASSERT(constant.IsSmi());
|
| + const int64_t imm =
|
| + reinterpret_cast<int64_t>(constant.raw());
|
| + switch (op_kind()) {
|
| + case Token::kADD: {
|
| + __ addq(left, Immediate(imm));
|
| + __ j(OVERFLOW, deopt);
|
| + break;
|
| + }
|
| + case Token::kSUB: {
|
| + __ subq(left, Immediate(imm));
|
| + __ j(OVERFLOW, deopt);
|
| + break;
|
| + }
|
| + case Token::kBIT_AND: {
|
| + // No overflow check.
|
| + __ andq(left, Immediate(imm));
|
| + break;
|
| + }
|
| + case Token::kBIT_OR: {
|
| + // No overflow check.
|
| + __ orq(left, Immediate(imm));
|
| + break;
|
| + }
|
| + case Token::kBIT_XOR: {
|
| + // No overflow check.
|
| + __ xorq(left, Immediate(imm));
|
| + break;
|
| + }
|
| +
|
| + case Token::kSHR: {
|
| + // sarq operation masks the count to 6 bits.
|
| + const intptr_t kCountLimit = 0x3F;
|
| + intptr_t value = Smi::Cast(constant).Value();
|
| +
|
| + if (value == 0) {
|
| + // TODO(vegorov): should be handled outside.
|
| + break;
|
| + } else if (value < 0) {
|
| + // TODO(vegorov): should be handled outside.
|
| + __ jmp(deopt);
|
| + break;
|
| + }
|
| +
|
| + value = value + kSmiTagSize;
|
| + if (value >= kCountLimit) value = kCountLimit;
|
| +
|
| + __ sarq(left, Immediate(value));
|
| + __ SmiTag(left);
|
| + break;
|
| + }
|
| + default:
|
| + UNREACHABLE();
|
| + break;
|
| + }
|
| + return;
|
| + }
|
| +
|
| + Register right = locs()->in(1).reg();
|
| switch (op_kind()) {
|
| case Token::kADD: {
|
| __ addq(left, right);
|
|
|