| Index: runtime/vm/intermediate_language_arm.cc
|
| diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
|
| index dfe2349685d3694e4c85297adfc3b520b8ec21d8..6b59d4384d6460bf1d75f299bd2d7a7deac88ec5 100644
|
| --- a/runtime/vm/intermediate_language_arm.cc
|
| +++ b/runtime/vm/intermediate_language_arm.cc
|
| @@ -5967,7 +5967,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) {
|
| @@ -5996,7 +5996,7 @@ class BoxIntegerSlowPath : public SlowPathCode {
|
| }
|
|
|
| private:
|
| - BoxIntegerInstr* instruction_;
|
| + Definition* instruction_;
|
| };
|
|
|
|
|
| @@ -6273,6 +6273,323 @@ 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::RequiresRegister());
|
| + 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:
|
| + __ and_(out, left, Operand(right));
|
| + break;
|
| + case Token::kBIT_OR:
|
| + __ orr(out, left, Operand(right));
|
| + break;
|
| + case Token::kBIT_XOR:
|
| + __ eor(out, left, Operand(right));
|
| + break;
|
| + case Token::kADD:
|
| + __ add(out, left, Operand(right));
|
| + break;
|
| + case Token::kSUB:
|
| + __ sub(out, left, Operand(right));
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| +}
|
| +
|
| +
|
| +LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate,
|
| + bool opt) const {
|
| + const intptr_t kNumInputs = 2;
|
| + const intptr_t kNumTemps = 1;
|
| + LocationSummary* summary = new(isolate) LocationSummary(
|
| + isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
|
| + summary->set_in(0, Location::RequiresRegister());
|
| + summary->set_in(1, Location::RegisterOrSmiConstant(right()));
|
| + summary->set_temp(0, Location::RequiresRegister());
|
| + summary->set_out(0, Location::RequiresRegister());
|
| + return summary;
|
| +}
|
| +
|
| +
|
| +void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + const intptr_t kShifterLimit = 31;
|
| +
|
| + Register left = locs()->in(0).reg();
|
| + Register out = locs()->out(0).reg();
|
| + Register temp = locs()->temp(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.
|
| + __ mov(out, Operand(left));
|
| + } else if (shift_value < 0) {
|
| + // Invalid shift value.
|
| + __ b(deopt);
|
| + } else if (shift_value > kShifterLimit) {
|
| + // Result is 0.
|
| + __ eor(out, out, Operand(out));
|
| + } else {
|
| + // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit).
|
| + switch (op_kind()) {
|
| + case Token::kSHR:
|
| + __ Lsr(out, left, shift_value);
|
| + break;
|
| + case Token::kSHL:
|
| + __ Lsl(out, left, shift_value);
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| + }
|
| + return;
|
| + }
|
| +
|
| + // Non constant shift value.
|
| +
|
| + Register shifter = locs()->in(1).reg();
|
| +
|
| + __ mov(temp, Operand(shifter));
|
| + __ SmiUntag(temp);
|
| + __ CompareImmediate(temp, 0);
|
| + // If shift value is < 0, deoptimize.
|
| + __ b(deopt, LT);
|
| + __ CompareImmediate(temp, kShifterLimit);
|
| + // > kShifterLimit, result is 0.
|
| + __ eor(out, out, Operand(out), HI);
|
| + // Do the shift.
|
| + switch (op_kind()) {
|
| + case Token::kSHR:
|
| + __ Lsr(out, left, temp, LS);
|
| + break;
|
| + case Token::kSHL:
|
| + __ Lsl(out, left, temp, LS);
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| +}
|
| +
|
| +
|
| +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::RequiresRegister());
|
| + return summary;
|
| +}
|
| +
|
| +
|
| +void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + Register left = locs()->in(0).reg();
|
| + Register out = locs()->out(0).reg();
|
| + ASSERT(left != out);
|
| +
|
| + ASSERT(op_kind() == Token::kBIT_NOT);
|
| +
|
| + __ mvn(out, Operand(left));
|
| +}
|
| +
|
| +
|
| +LocationSummary* BoxUint32Instr::MakeLocationSummary(Isolate* isolate,
|
| + bool opt) const {
|
| + const intptr_t kNumInputs = 1;
|
| + const intptr_t kNumTemps = 1;
|
| + LocationSummary* summary = new(isolate) LocationSummary(
|
| + isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
|
| + summary->set_in(0, Location::RequiresRegister());
|
| + summary->set_temp(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();
|
| + Register temp = locs()->temp(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.
|
| + __ CompareImmediate(value, kSmiMax);
|
| + __ b(¬_smi, HI);
|
| + // Smi.
|
| + __ mov(out, Operand(value));
|
| + __ SmiTag(out);
|
| + __ b(&done);
|
| + __ Bind(¬_smi);
|
| + // Allocate a mint.
|
| + __ TryAllocate(
|
| + Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
|
| + slow_path->entry_label(),
|
| + out,
|
| + temp);
|
| + __ Bind(slow_path->exit_label());
|
| + // Copy low word into mint.
|
| + __ StoreToOffset(kWord,
|
| + value,
|
| + out,
|
| + Mint::value_offset() - kHeapObjectTag);
|
| + // Zero high word.
|
| + __ eor(temp, temp, Operand(temp));
|
| + __ StoreToOffset(kWord,
|
| + temp,
|
| + out,
|
| + Mint::value_offset() - kHeapObjectTag + kWordSize);
|
| + __ 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::RequiresRegister());
|
| + return summary;
|
| +}
|
| +
|
| +
|
| +void UnboxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
| + const intptr_t value_cid = value()->Type()->ToCid();
|
| + const Register value = locs()->in(0).reg();
|
| + const Register out = locs()->out(0).reg();
|
| + ASSERT(value != out);
|
| +
|
| + // TODO(johnmccutchan): Emit better code for constant inputs.
|
| + if (value_cid == kMintCid) {
|
| + __ LoadFromOffset(kWord, out, value, Mint::value_offset() - kHeapObjectTag);
|
| + } else if (value_cid == kSmiCid) {
|
| + __ mov(out, Operand(value));
|
| + __ SmiUntag(out);
|
| + } else {
|
| + Register temp = locs()->temp(0).reg();
|
| + Label* deopt = compiler->AddDeoptStub(deopt_id_,
|
| + ICData::kDeoptUnboxInteger);
|
| + Label done;
|
| + __ tst(value, Operand(kSmiTagMask));
|
| + // Smi case.
|
| + __ mov(out, Operand(value), EQ);
|
| + __ SmiUntag(out, EQ);
|
| + __ b(&done, EQ);
|
| + // Mint case.
|
| + __ CompareClassId(value, kMintCid, temp);
|
| + __ b(deopt, NE);
|
| + __ LoadFromOffset(kWord, out, value, Mint::value_offset() - kHeapObjectTag);
|
| + __ 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.
|
| + __ mov(out, Operand(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.
|
| + __ mov(out_lo, Operand(in));
|
| + // Zero upper word.
|
| + __ eor(out_hi, out_hi, Operand(out_hi));
|
| + }
|
| +}
|
| +
|
| +
|
| LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate,
|
| bool opt) const {
|
| return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall);
|
|
|