Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(800)

Unified Diff: runtime/vm/intermediate_language_ia32.cc

Issue 504143003: Support Int32 representation for selected binary operations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/intermediate_language_ia32.cc
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index d3cf96f2d48b2e25499580adf751714da298d901..828bbd2537b523d6c829415fed40aad93fe4e36d 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -175,15 +175,25 @@ LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Isolate* isolate,
void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
// The register allocator drops constant definitions that have no uses.
if (!locs()->out(0).IsInvalid()) {
- XmmRegister result = locs()->out(0).fpu_reg();
- if (constant_address() == 0) {
- Register boxed = locs()->temp(0).reg();
- __ LoadObjectSafely(boxed, value());
- __ movsd(result, FieldAddress(boxed, Double::value_offset()));
- } else if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) {
- __ xorps(result, result);
- } else {
- __ movsd(result, Address::Absolute(constant_address()));
+ switch (representation()) {
+ case kUnboxedDouble: {
+ XmmRegister result = locs()->out(0).fpu_reg();
+ if (constant_address() == 0) {
+ Register boxed = locs()->temp(0).reg();
+ __ LoadObjectSafely(boxed, value());
+ __ movsd(result, FieldAddress(boxed, Double::value_offset()));
+ } else if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) {
+ __ xorps(result, result);
+ } else {
+ __ movsd(result, Address::Absolute(constant_address()));
+ }
+ break;
+ }
+ case kUnboxedInt32:
+ __ movl(locs()->out(0).reg(), Immediate(Smi::Cast(value()).Value()));
+ break;
+ default:
+ UNREACHABLE();
}
}
}
@@ -1042,7 +1052,7 @@ LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate,
locs->set_in(0, Location::RequiresRegister());
if (CanBeImmediateIndex(index(), class_id())) {
// CanBeImmediateIndex must return false for unsafe smis.
- locs->set_in(1, Location::Constant(index()->BoundConstant()));
+ locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
} else {
// The index is either untagged (element size == 1) or a smi (for all
// element sizes > 1).
@@ -1238,7 +1248,7 @@ LocationSummary* StoreIndexedInstr::MakeLocationSummary(Isolate* isolate,
locs->set_in(0, Location::RequiresRegister());
if (CanBeImmediateIndex(index(), class_id())) {
// CanBeImmediateIndex must return false for unsafe smis.
- locs->set_in(1, Location::Constant(index()->BoundConstant()));
+ locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
} else {
// The index is either untagged (element size == 1) or a smi (for all
// element sizes > 1).
@@ -2775,7 +2785,7 @@ LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Isolate* isolate,
summary->set_in(0, Location::RequiresRegister());
ConstantInstr* right_constant = right()->definition()->AsConstant();
// The programmer only controls one bit, so the constant is safe.
- summary->set_in(1, Location::Constant(right_constant->value()));
+ summary->set_in(1, Location::Constant(right_constant));
summary->set_temp(0, Location::RequiresRegister());
summary->set_out(0, Location::SameAsFirstInput());
} else {
@@ -3139,6 +3149,289 @@ void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
+LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Isolate* isolate,
+ bool opt) const {
+ const intptr_t kNumInputs = 2;
+ if (op_kind() == Token::kTRUNCDIV) {
+ UNREACHABLE();
+ return NULL;
+ } else if (op_kind() == Token::kMOD) {
+ UNREACHABLE();
+ return NULL;
+ } else if (op_kind() == Token::kSHR) {
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new(isolate) LocationSummary(
+ isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
+ summary->set_out(0, Location::SameAsFirstInput());
+ return summary;
+ } else if (op_kind() == Token::kSHL) {
+ const intptr_t kNumTemps = !IsTruncating() ? 1 : 0;
+ LocationSummary* summary = new(isolate) LocationSummary(
+ isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
+ if (!IsTruncating()) {
+ summary->set_temp(0, Location::RequiresRegister());
+ }
+ summary->set_out(0, Location::SameAsFirstInput());
+ return summary;
+ } else {
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new(isolate) LocationSummary(
+ isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ ConstantInstr* constant = right()->definition()->AsConstant();
+ if (constant != NULL) {
+ summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+ } else {
+ summary->set_in(1, Location::PrefersRegister());
+ }
+ summary->set_out(0, Location::SameAsFirstInput());
+ return summary;
+ }
+}
+
+
+static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler,
+ BinaryInt32OpInstr* shift_left) {
+ const bool is_truncating = shift_left->IsTruncating();
+ const LocationSummary& locs = *shift_left->locs();
+ Register left = locs.in(0).reg();
+ Register result = locs.out(0).reg();
+ ASSERT(left == result);
+ Label* deopt = shift_left->CanDeoptimize() ?
+ compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp)
+ : NULL;
+ ASSERT(locs.in(1).IsConstant());
+
+ const Object& constant = locs.in(1).constant();
+ ASSERT(constant.IsSmi());
+ // shll operation masks the count to 5 bits.
+ const intptr_t kCountLimit = 0x1F;
+ const intptr_t value = Smi::Cast(constant).Value();
+ if (value == 0) {
+ // No code needed.
+ } else if ((value < 0) || (value >= kCountLimit)) {
+ // This condition may not be known earlier in some cases because
+ // of constant propagation, inlining, etc.
+ if ((value >= kCountLimit) && is_truncating) {
+ __ xorl(result, result);
+ } else {
+ // Result is Mint or exception.
+ __ jmp(deopt);
+ }
+ } else {
+ if (!is_truncating) {
+ // Check for overflow.
+ Register temp = locs.temp(0).reg();
+ __ movl(temp, left);
+ __ shll(left, Immediate(value));
+ __ sarl(left, Immediate(value));
+ __ cmpl(left, temp);
+ __ j(NOT_EQUAL, deopt); // Overflow.
+ }
+ // Shift for result now we know there is no overflow.
+ __ shll(left, Immediate(value));
+ }
+}
+
+
+void BinaryInt32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ if (op_kind() == Token::kSHL) {
+ EmitInt32ShiftLeft(compiler, this);
+ return;
+ }
+
+ Register left = locs()->in(0).reg();
+ Register result = locs()->out(0).reg();
+ ASSERT(left == result);
+ Label* deopt = NULL;
+ if (CanDeoptimize()) {
+ deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp);
+ }
+
+ if (locs()->in(1).IsConstant()) {
+ const Object& constant = locs()->in(1).constant();
+ ASSERT(constant.IsSmi());
+ const intptr_t value = Smi::Cast(constant).Value();
+ switch (op_kind()) {
+ case Token::kADD:
+ if (value != 0) {
+ // Checking overflow without emitting an instruction would be wrong.
+ __ addl(left, Immediate(value));
+ if (deopt != NULL) __ j(OVERFLOW, deopt);
+ }
+ break;
+ case Token::kSUB: {
+ if (value != 0) {
+ // Checking overflow without emitting an instruction would be wrong.
+ __ subl(left, Immediate(value));
+ if (deopt != NULL) __ j(OVERFLOW, deopt);
+ }
+ break;
+ }
+ case Token::kMUL: {
+ if (value == 2) {
+ __ shll(left, Immediate(1));
+ } else {
+ __ imull(left, Immediate(value));
+ }
+ if (deopt != NULL) __ j(OVERFLOW, deopt);
+ break;
+ }
+ case Token::kTRUNCDIV: {
+ UNREACHABLE();
+ break;
+ }
+ case Token::kBIT_AND: {
+ // No overflow check.
+ __ andl(left, Immediate(value));
+ break;
+ }
+ case Token::kBIT_OR: {
+ // No overflow check.
+ __ orl(left, Immediate(value));
+ break;
+ }
+ case Token::kBIT_XOR: {
+ // No overflow check.
+ __ xorl(left, Immediate(value));
+ break;
+ }
+ case Token::kSHR: {
+ // sarl operation masks the count to 5 bits.
+ const intptr_t kCountLimit = 0x1F;
+ if (value == 0) {
+ // TODO(vegorov): should be handled outside.
+ break;
+ } else if (value < 0) {
+ // TODO(vegorov): should be handled outside.
+ __ jmp(deopt);
+ break;
+ }
+
+ if (value >= kCountLimit) {
+ __ sarl(left, Immediate(kCountLimit));
+ } else {
+ __ sarl(left, Immediate(value));
+ }
+
+ break;
+ }
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ } // if locs()->in(1).IsConstant()
+
+ if (locs()->in(1).IsStackSlot()) {
+ const Address& right = locs()->in(1).ToStackSlotAddress();
+ switch (op_kind()) {
+ case Token::kADD: {
+ __ addl(left, right);
+ if (deopt != NULL) __ j(OVERFLOW, deopt);
+ break;
+ }
+ case Token::kSUB: {
+ __ subl(left, right);
+ if (deopt != NULL) __ j(OVERFLOW, deopt);
+ break;
+ }
+ case Token::kMUL: {
+ __ imull(left, right);
+ if (deopt != NULL) __ j(OVERFLOW, deopt);
+ break;
+ }
+ case Token::kBIT_AND: {
+ // No overflow check.
+ __ andl(left, right);
+ break;
+ }
+ case Token::kBIT_OR: {
+ // No overflow check.
+ __ orl(left, right);
+ break;
+ }
+ case Token::kBIT_XOR: {
+ // No overflow check.
+ __ xorl(left, right);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ return;
+ } // if locs()->in(1).IsStackSlot.
+
+ // if locs()->in(1).IsRegister.
+ Register right = locs()->in(1).reg();
+ switch (op_kind()) {
+ case Token::kADD: {
+ __ addl(left, right);
+ if (deopt != NULL) __ j(OVERFLOW, deopt);
+ break;
+ }
+ case Token::kSUB: {
+ __ subl(left, right);
+ if (deopt != NULL) __ j(OVERFLOW, deopt);
+ break;
+ }
+ case Token::kMUL: {
+ __ imull(left, right);
+ if (deopt != NULL) __ j(OVERFLOW, deopt);
+ break;
+ }
+ case Token::kBIT_AND: {
+ // No overflow check.
+ __ andl(left, right);
+ break;
+ }
+ case Token::kBIT_OR: {
+ // No overflow check.
+ __ orl(left, right);
+ break;
+ }
+ case Token::kBIT_XOR: {
+ // No overflow check.
+ __ xorl(left, right);
+ break;
+ }
+ case Token::kTRUNCDIV: {
+ UNREACHABLE();
+ break;
+ }
+ case Token::kMOD: {
+ UNREACHABLE();
+ break;
+ }
+ case Token::kSHR: {
+ UNREACHABLE();
+ break;
+ }
+ case Token::kDIV: {
+ // Dispatches to 'Double./'.
+ // TODO(srdjan): Implement as conversion to double and double division.
+ UNREACHABLE();
+ break;
+ }
+ case Token::kOR:
+ case Token::kAND: {
+ // Flow graph builder has dissected this operation to guarantee correct
+ // behavior (short-circuit evaluation).
+ UNREACHABLE();
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+
LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Isolate* isolate,
bool opt) const {
intptr_t left_cid = left()->Type()->ToCid();
@@ -4673,6 +4966,25 @@ void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
+LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Isolate* isolate,
+ bool opt) const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* result = new(isolate) LocationSummary(
+ isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ result->set_in(0, Location::WritableRegister());
+ result->set_out(0, Location::RequiresFpuRegister());
+ return result;
+}
+
+
+void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register value = locs()->in(0).reg();
+ FpuRegister result = locs()->out(0).fpu_reg();
+ __ cvtsi2sd(result, value);
+}
+
+
LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate,
bool opt) const {
const intptr_t kNumInputs = 1;
@@ -5910,16 +6222,6 @@ CompileType UnaryUint32OpInstr::ComputeType() const {
}
-CompileType BoxUint32Instr::ComputeType() const {
- return CompileType::Int();
-}
-
-
-CompileType UnboxUint32Instr::ComputeType() const {
- return CompileType::Int();
-}
-
-
LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate,
bool opt) const {
const intptr_t kNumInputs = 2;
@@ -6092,9 +6394,14 @@ LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate,
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(isolate) LocationSummary(
- isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
+ isolate,
+ kNumInputs,
+ kNumTemps,
+ ValueFitsSmi() ? LocationSummary::kNoCall
+ : LocationSummary::kCallOnSlowPath);
summary->set_in(0, Location::RequiresRegister());
- summary->set_out(0, Location::RequiresRegister());
+ summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
+ : Location::RequiresRegister());
return summary;
}
@@ -6102,27 +6409,68 @@ LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate,
void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register value = locs()->in(0).reg();
Register out = locs()->out(0).reg();
- ASSERT(value != out);
Label not_smi, done;
- // TODO(johnmccutchan): Use range information to fast path smi / mint boxing.
- // Test if this value is <= kSmiMax.
- __ cmpl(value, Immediate(kSmiMax));
- __ j(ABOVE, &not_smi);
- // Smi.
- __ movl(out, value);
- __ SmiTag(out);
- __ jmp(&done);
- __ Bind(&not_smi);
- // Allocate a mint.
- BoxAllocationSlowPath::Allocate(
- compiler, this, compiler->mint_class(), out, kNoRegister);
- // Copy low word into mint.
- __ movl(FieldAddress(out, Mint::value_offset()), value);
- // Zero high word.
- __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), Immediate(0));
- __ Bind(&done);
+ if (ValueFitsSmi()) {
+ ASSERT(value == out);
+ __ SmiTag(value);
+ } else {
+ ASSERT(value != out);
+ __ cmpl(value, Immediate(kSmiMax));
+ __ j(ABOVE, &not_smi);
+ // Smi.
+ __ movl(out, value);
+ __ SmiTag(out);
+ __ jmp(&done);
+ __ Bind(&not_smi);
+ // Allocate a mint.
+ BoxAllocationSlowPath::Allocate(
+ compiler, this, compiler->mint_class(), out, kNoRegister);
+ // Copy low word into mint.
+ __ movl(FieldAddress(out, Mint::value_offset()), value);
+ // Zero high word.
+ __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), Immediate(0));
+ __ Bind(&done);
+ }
+}
+
+
+LocationSummary* BoxInt32Instr::MakeLocationSummary(Isolate* isolate,
+ bool opt) const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new(isolate) LocationSummary(
+ isolate, kNumInputs, kNumTemps,
+ ValueFitsSmi() ? LocationSummary::kNoCall
+ : LocationSummary::kCallOnSlowPath);
+ summary->set_in(0, ValueFitsSmi() ? Location::RequiresRegister()
+ : Location::WritableRegister());
+ summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
+ : Location::RequiresRegister());
+ return summary;
+}
+
+
+void BoxInt32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register value = locs()->in(0).reg();
+ Register out = locs()->out(0).reg();
+
+ if (out != value) {
+ __ movl(out, value);
+ }
+ __ shll(out, Immediate(1));
+ if (!ValueFitsSmi()) {
+ Label done;
+ __ j(NO_OVERFLOW, &done);
+ // Allocate a mint.
+ BoxAllocationSlowPath::Allocate(
+ compiler, this, compiler->mint_class(), out, kNoRegister);
+ __ movl(FieldAddress(out, Mint::value_offset()), value);
+ __ sarl(value, Immediate(31)); // Sign extend.
+ __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value);
+ __ Bind(&done);
+ }
}
@@ -6171,35 +6519,142 @@ void UnboxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
}
+LocationSummary* UnboxInt32Instr::MakeLocationSummary(Isolate* isolate,
+ bool opt) const {
+ const intptr_t value_cid = value()->Type()->ToCid();
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0;
+ LocationSummary* summary = new(isolate) LocationSummary(
+ isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ if (kNumTemps > 0) {
+ summary->set_temp(0, Location::RequiresRegister());
+ }
+ summary->set_out(0, (value_cid == kSmiCid) ? Location::SameAsFirstInput()
+ : Location::RequiresRegister());
+ return summary;
+}
+
+
+static void LoadInt32FromMint(FlowGraphCompiler* compiler,
+ Register mint,
+ Register result,
+ Register temp,
+ Label* deopt) {
+ __ movl(result, FieldAddress(mint, Mint::value_offset()));
+ if (deopt != NULL) {
+ __ movl(temp, result);
+ __ sarl(temp, Immediate(31));
+ __ cmpl(temp, FieldAddress(mint, Mint::value_offset() + kWordSize));
+ __ j(NOT_EQUAL, deopt);
+ }
+}
+
+
+void UnboxInt32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const intptr_t value_cid = value()->Type()->ToCid();
+ const Register value = locs()->in(0).reg();
+ const Register result = locs()->out(0).reg();
+
+ // TODO(johnmccutchan): Emit better code for constant inputs.
+ if (value_cid == kMintCid) {
+ Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister;
+ Label* deopt = CanDeoptimize() ?
+ compiler->AddDeoptStub(deopt_id_, ICData::kDeoptUnboxInteger) : NULL;
+ LoadInt32FromMint(compiler,
+ value,
+ result,
+ temp,
+ deopt);
+ } else if (value_cid == kSmiCid) {
+ ASSERT(value == result);
+ __ SmiUntag(value);
+ } else {
+ Register temp = locs()->temp(0).reg();
+ Label* deopt = compiler->AddDeoptStub(deopt_id_,
+ ICData::kDeoptUnboxInteger);
+ Label is_smi, done;
+ __ testl(value, Immediate(kSmiTagMask));
+ __ j(ZERO, &is_smi);
+ __ CompareClassId(value, kMintCid, temp);
+ __ j(NOT_EQUAL, deopt);
+ LoadInt32FromMint(compiler,
+ value,
+ result,
+ temp,
+ deopt);
+ __ movl(value, FieldAddress(value, Mint::value_offset()));
+ __ jmp(&done);
+ __ Bind(&is_smi);
+ __ SmiUntag(value);
+ __ Bind(&done);
+ }
+}
+
+
LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate,
bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
LocationSummary* summary = new(isolate) LocationSummary(
isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
- if (from() == kUnboxedMint) {
- summary->set_in(0, Location::Pair(Location::RequiresRegister(),
- Location::RequiresRegister()));
+ if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) &&
+ (to() == kUnboxedInt32 || to() == kUnboxedUint32)) {
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_out(0, Location::SameAsFirstInput());
+ } else if (from() == kUnboxedMint) {
+ summary->set_in(0, Location::Pair(
+ CanDeoptimize() ? Location::WritableRegister()
+ : Location::RequiresRegister(),
+ Location::RequiresRegister()));
summary->set_out(0, Location::RequiresRegister());
- } else {
- ASSERT(from() == kUnboxedUint32);
+ } else if (from() == kUnboxedUint32) {
summary->set_in(0, Location::RequiresRegister());
summary->set_out(0, Location::Pair(Location::RequiresRegister(),
Location::RequiresRegister()));
+ } else if (from() == kUnboxedInt32) {
+ summary->set_in(0, Location::RegisterLocation(EAX));
+ summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
+ Location::RegisterLocation(EDX)));
}
return summary;
}
void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- if (from() == kUnboxedMint) {
+ if (from() == kUnboxedInt32 && to() == kUnboxedUint32) {
+ // Representations are bitwise equivalent.
+ ASSERT(locs()->out(0).reg() == locs()->in(0).reg());
+ } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) {
+ // Representations are bitwise equivalent.
+ ASSERT(locs()->out(0).reg() == locs()->in(0).reg());
+ if (CanDeoptimize()) {
+ Label* deopt =
+ compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
+ __ testl(locs()->out(0).reg(), locs()->out(0).reg());
+ __ j(NEGATIVE, deopt);
+ }
+ } else if (from() == kUnboxedMint) {
+ // TODO(vegorov) kUnboxedMint -> kInt32 conversion is currently usually
+ // dominated by a CheckSmi(BoxInteger(val)) which is an artifact of ordering
+ // of optimization passes and the way we check smi-ness of values.
+ // Optimize it away.
+ ASSERT(to() == kUnboxedInt32 || to() == kUnboxedUint32);
PairLocation* in_pair = locs()->in(0).AsPairLocation();
Register in_lo = in_pair->At(0).reg();
+ Register in_hi = in_pair->At(1).reg();
Register out = locs()->out(0).reg();
// Copy low word.
__ movl(out, in_lo);
- } else {
- ASSERT(from() == kUnboxedUint32);
+ if (CanDeoptimize()) {
+ Label* deopt =
+ compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
+ __ sarl(in_lo, Immediate(31));
+ __ cmpl(in_lo, in_hi);
+ __ j(NOT_EQUAL, deopt);
+ }
+ } else if (from() == kUnboxedUint32) {
+ ASSERT(to() == kUnboxedMint);
Register in = locs()->in(0).reg();
PairLocation* out_pair = locs()->out(0).AsPairLocation();
Register out_lo = out_pair->At(0).reg();
@@ -6208,6 +6663,16 @@ void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ movl(out_lo, in);
// Zero upper word.
__ xorl(out_hi, out_hi);
+ } else if (from() == kUnboxedInt32) {
+ ASSERT(to() == kUnboxedMint);
+ PairLocation* out_pair = locs()->out(0).AsPairLocation();
+ Register out_lo = out_pair->At(0).reg();
+ Register out_hi = out_pair->At(1).reg();
+ ASSERT(locs()->in(0).reg() == EAX);
+ ASSERT(out_lo == EAX && out_hi == EDX);
+ __ cdq();
+ } else {
+ UNREACHABLE();
}
}

Powered by Google App Engine
This is Rietveld 408576698