| 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);
|
|
|