Index: runtime/vm/intermediate_language_ia32.cc |
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc |
index 071f4afd82dccf1f2fd6f43193a2a647310811b0..054a8d64ac3ca18c622bc98833d0351ad8b5b4fd 100644 |
--- a/runtime/vm/intermediate_language_ia32.cc |
+++ b/runtime/vm/intermediate_language_ia32.cc |
@@ -5753,7 +5753,7 @@ LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate, |
class BoxIntegerSlowPath : public SlowPathCode { |
public: |
- explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction) |
+ explicit BoxIntegerSlowPath(Definition* instruction) |
: instruction_(instruction) { } |
virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
@@ -5782,7 +5782,7 @@ class BoxIntegerSlowPath : public SlowPathCode { |
} |
private: |
- BoxIntegerInstr* instruction_; |
+ Definition* instruction_; |
}; |
@@ -6165,6 +6165,320 @@ void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
} |
+CompileType BinaryUint32OpInstr::ComputeType() const { |
+ return CompileType::Int(); |
+} |
+ |
+ |
+CompileType ShiftUint32OpInstr::ComputeType() const { |
+ return CompileType::Int(); |
+} |
+ |
+ |
+CompileType UnaryUint32OpInstr::ComputeType() const { |
+ return CompileType::Int(); |
+} |
+ |
+ |
+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; |
+ 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::RequiresRegister()); |
+ summary->set_out(0, Location::SameAsFirstInput()); |
+ return summary; |
+} |
+ |
+ |
+void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ Register left = locs()->in(0).reg(); |
+ Register right = locs()->in(1).reg(); |
+ Register out = locs()->out(0).reg(); |
+ ASSERT(out == left); |
+ switch (op_kind()) { |
+ case Token::kBIT_AND: |
+ __ andl(out, right); |
+ break; |
+ case Token::kBIT_OR: |
+ __ orl(out, right); |
+ break; |
+ case Token::kBIT_XOR: |
+ __ xorl(out, right); |
+ break; |
+ case Token::kADD: |
+ __ addl(out, right); |
+ break; |
+ case Token::kSUB: |
+ __ subl(out, right); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+} |
+ |
+ |
+LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
+ bool opt) const { |
+ const intptr_t kNumInputs = 2; |
+ 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; |
+} |
+ |
+ |
+void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ const intptr_t kShifterLimit = 31; |
+ |
+ Register left = locs()->in(0).reg(); |
+ Register out = locs()->out(0).reg(); |
+ ASSERT(left == out); |
+ |
+ |
+ Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp); |
+ |
+ if (locs()->in(1).IsConstant()) { |
+ // Shifter is constant. |
+ |
+ const Object& constant = locs()->in(1).constant(); |
+ ASSERT(constant.IsSmi()); |
+ const intptr_t shift_value = Smi::Cast(constant).Value(); |
+ |
+ // Check constant shift value. |
+ if (shift_value == 0) { |
+ // Nothing to do. |
+ } else if (shift_value < 0) { |
+ // Invalid shift value. |
+ __ jmp(deopt); |
+ } else if (shift_value > kShifterLimit) { |
+ // Result is 0. |
+ __ xorl(left, left); |
+ } else { |
+ // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
+ switch (op_kind()) { |
+ case Token::kSHR: |
+ __ shrl(left, Immediate(shift_value)); |
+ break; |
+ case Token::kSHL: |
+ __ shll(left, Immediate(shift_value)); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ } |
+ return; |
+ } |
+ |
+ // Non constant shift value. |
+ |
+ Register shifter = locs()->in(1).reg(); |
+ ASSERT(shifter == ECX); |
+ |
+ Label done; |
+ Label zero; |
+ |
+ // TODO(johnmccutchan): Use range information to avoid these checks. |
+ __ SmiUntag(shifter); |
+ __ cmpl(shifter, Immediate(0)); |
+ // If shift value is < 0, deoptimize. |
+ __ j(NEGATIVE, deopt); |
+ __ cmpl(shifter, Immediate(kShifterLimit)); |
+ // If shift value is >= 32, return zero. |
+ __ j(ABOVE, &zero); |
+ |
+ // Do the shift. |
+ switch (op_kind()) { |
+ case Token::kSHR: |
+ __ shrl(left, shifter); |
+ __ jmp(&done); |
+ break; |
+ case Token::kSHL: |
+ __ shll(left, shifter); |
+ __ jmp(&done); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ |
+ __ Bind(&zero); |
+ // Shift was greater than 31 bits, just return zero. |
+ __ xorl(left, left); |
+ |
+ // Exit path. |
+ __ Bind(&done); |
+} |
+ |
+ |
+LocationSummary* UnaryUint32OpInstr::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); |
+ summary->set_in(0, Location::RequiresRegister()); |
+ summary->set_out(0, Location::SameAsFirstInput()); |
+ return summary; |
+} |
+ |
+ |
+void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ Register out = locs()->out(0).reg(); |
+ ASSERT(locs()->in(0).reg() == out); |
+ |
+ ASSERT(op_kind() == Token::kBIT_NOT); |
+ |
+ __ notl(out); |
+} |
+ |
+ |
+LocationSummary* BoxUint32Instr::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::kCallOnSlowPath); |
+ summary->set_in(0, Location::RequiresRegister()); |
+ summary->set_out(0, Location::RequiresRegister()); |
+ return summary; |
+} |
+ |
+ |
+void BoxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this); |
+ compiler->AddSlowPathCode(slow_path); |
+ 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, ¬_smi); |
+ // Smi. |
+ __ movl(out, value); |
+ __ SmiTag(out); |
+ __ jmp(&done); |
+ __ Bind(¬_smi); |
+ // Allocate a mint. |
+ __ TryAllocate( |
+ Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()), |
+ slow_path->entry_label(), |
+ Assembler::kFarJump, |
+ out, |
+ kNoRegister); |
+ __ Bind(slow_path->exit_label()); |
+ // 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* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate, |
+ bool opt) const { |
+ const intptr_t value_cid = value()->Type()->ToCid(); |
+ const intptr_t kNumInputs = 1; |
+ const intptr_t kNumTemps = |
+ ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1; |
+ 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, Location::SameAsFirstInput()); |
+ return summary; |
+} |
+ |
+ |
+void UnboxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ const intptr_t value_cid = value()->Type()->ToCid(); |
+ const Register value = locs()->in(0).reg(); |
+ ASSERT(value == locs()->out(0).reg()); |
+ |
+ // TODO(johnmccutchan): Emit better code for constant inputs. |
+ if (value_cid == kMintCid) { |
+ __ movl(value, FieldAddress(value, Mint::value_offset())); |
+ } else if (value_cid == kSmiCid) { |
+ __ 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); |
+ __ 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())); |
+ summary->set_out(0, Location::RequiresRegister()); |
+ } else { |
+ ASSERT(from() == kUnboxedUint32); |
+ summary->set_in(0, Location::RequiresRegister()); |
+ summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
+ Location::RequiresRegister())); |
+ } |
+ return summary; |
+} |
+ |
+ |
+void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
+ if (from() == kUnboxedMint) { |
+ PairLocation* in_pair = locs()->in(0).AsPairLocation(); |
+ Register in_lo = in_pair->At(0).reg(); |
+ Register out = locs()->out(0).reg(); |
+ // Copy low word. |
+ __ movl(out, in_lo); |
+ } else { |
+ ASSERT(from() == kUnboxedUint32); |
+ Register in = locs()->in(0).reg(); |
+ PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
+ Register out_lo = out_pair->At(0).reg(); |
+ Register out_hi = out_pair->At(1).reg(); |
+ // Copy low word. |
+ __ movl(out_lo, in); |
+ // Zero upper word. |
+ __ xorl(out_hi, out_hi); |
+ } |
+} |
+ |
+ |
LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
bool opt) const { |
return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |