Index: runtime/vm/intermediate_language_dbc.cc |
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc |
index 7ada86f52d5e67ebf605a604f2210bab2ba2de24..eabc1bc8730c7cd8fd95352b32714f1bee2b3889 100644 |
--- a/runtime/vm/intermediate_language_dbc.cc |
+++ b/runtime/vm/intermediate_language_dbc.cc |
@@ -34,30 +34,43 @@ DECLARE_FLAG(int, optimization_counter_threshold); |
M(LoadUntagged) \ |
M(AllocateUninitializedContext) \ |
M(BinaryInt32Op) \ |
- M(UnaryDoubleOp) \ |
- M(SmiToDouble) \ |
M(Int32ToDouble) \ |
- M(MintToDouble) \ |
M(DoubleToInteger) \ |
M(DoubleToSmi) \ |
M(DoubleToDouble) \ |
M(DoubleToFloat) \ |
M(FloatToDouble) \ |
M(UnboxedConstant) \ |
- M(BinaryDoubleOp) \ |
M(MathUnary) \ |
M(MathMinMax) \ |
- M(Box) \ |
- M(Unbox) \ |
M(BoxInt64) \ |
- M(BinaryMintOp) \ |
- M(ShiftMintOp) \ |
- M(UnaryMintOp) \ |
M(InvokeMathCFunction) \ |
M(MergedMath) \ |
M(GuardFieldClass) \ |
M(GuardFieldLength) \ |
M(IfThenElse) \ |
+ M(ExtractNthOutput) \ |
+ M(BinaryUint32Op) \ |
+ M(ShiftUint32Op) \ |
+ M(UnaryUint32Op) \ |
+ M(UnboxedIntConverter) \ |
+ M(BoxInteger32) \ |
+ M(UnboxInteger32) \ |
+ |
+// List of instructions that are not used by DBC. |
+// Things we aren't planning to implement for DBC: |
+// - Unboxed SIMD, |
+// - Unboxed Mint, |
+// - Optimized RegExps, |
+// - Precompilation. |
+#define FOR_EACH_UNREACHABLE_INSTRUCTION(M) \ |
+ M(CaseInsensitiveCompareUC16) \ |
+ M(GrowRegExpStack) \ |
+ M(IndirectGoto) \ |
+ M(MintToDouble) \ |
+ M(BinaryMintOp) \ |
+ M(ShiftMintOp) \ |
+ M(UnaryMintOp) \ |
M(BinaryFloat32x4Op) \ |
M(Simd32x4Shuffle) \ |
M(Simd32x4ShuffleMix) \ |
@@ -89,21 +102,8 @@ DECLARE_FLAG(int, optimization_counter_threshold); |
M(Simd64x2Shuffle) \ |
M(Float64x2ZeroArg) \ |
M(Float64x2OneArg) \ |
- M(ExtractNthOutput) \ |
- M(BinaryUint32Op) \ |
- M(ShiftUint32Op) \ |
- M(UnaryUint32Op) \ |
- M(UnboxedIntConverter) \ |
- M(BoxInteger32) \ |
- M(UnboxInteger32) \ |
M(CheckedSmiOp) \ |
- |
-// List of instructions that are not used by DBC. |
-#define FOR_EACH_UNREACHABLE_INSTRUCTION(M) \ |
- M(CaseInsensitiveCompareUC16) \ |
M(GenericCheckBound) \ |
- M(GrowRegExpStack) \ |
- M(IndirectGoto) |
// Location summaries actually are not used by the unoptimizing DBC compiler |
// because we don't allocate any registers. |
@@ -1081,22 +1081,9 @@ EMIT_NATIVE_CODE(CheckSmi, 1) { |
EMIT_NATIVE_CODE(CheckEitherNonSmi, 2) { |
- intptr_t left_cid = left()->Type()->ToCid(); |
- intptr_t right_cid = right()->Type()->ToCid(); |
const Register left = locs()->in(0).reg(); |
const Register right = locs()->in(1).reg(); |
- if (this->left()->definition() == this->right()->definition()) { |
- __ CheckSmi(left); |
- } else if (left_cid == kSmiCid) { |
- __ CheckSmi(right); |
- } else if (right_cid == kSmiCid) { |
- __ CheckSmi(left); |
- } else { |
- __ CheckSmi(left); |
- compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
- licm_hoisted_ ? ICData::kHoisted : 0); |
- __ CheckSmi(right); |
- } |
+ __ CheckEitherNonSmi(left, right); |
compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
licm_hoisted_ ? ICData::kHoisted : 0); |
} |
@@ -1222,10 +1209,76 @@ EMIT_NATIVE_CODE(UnarySmiOp, 1, Location::RequiresRegister()) { |
break; |
default: |
UNREACHABLE(); |
+ break; |
} |
} |
+EMIT_NATIVE_CODE(Box, 1, Location::RequiresRegister(), LocationSummary::kCall) { |
+ ASSERT(from_representation() == kUnboxedDouble); |
+ const Register value = locs()->in(0).reg(); |
+ const Register out = locs()->out(0).reg(); |
+ const intptr_t kidx = __ AddConstant(compiler->double_class()); |
+ __ Allocate(kidx); |
+ compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, |
+ Thread::kNoDeoptId, |
+ token_pos()); |
+ compiler->RecordSafepoint(locs()); |
+ // __ Allocate puts the box at the top of the stack. |
+ __ WriteIntoDouble(out, value); |
+} |
+ |
+ |
+EMIT_NATIVE_CODE(Unbox, 1, Location::RequiresRegister()) { |
+ ASSERT(representation() == kUnboxedDouble); |
+ const intptr_t value_cid = value()->Type()->ToCid(); |
+ const intptr_t box_cid = BoxCid(); |
+ const Register box = locs()->in(0).reg(); |
+ const Register result = locs()->out(0).reg(); |
+ if (value_cid == box_cid) { |
+ __ UnboxDouble(result, box); |
+ } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
+ __ SmiToDouble(result, box); |
+ } else if ((value()->Type()->ToNullableCid() == box_cid) && |
+ value()->Type()->is_nullable()) { |
+ __ IfEqNull(box); |
+ compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass); |
+ __ UnboxDouble(result, box); |
+ } else { |
+ __ CheckedUnboxDouble(result, box); |
+ compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass); |
+ } |
+} |
+ |
+ |
+EMIT_NATIVE_CODE(SmiToDouble, 1, Location::RequiresRegister()) { |
+ const Register value = locs()->in(0).reg(); |
+ const Register result = locs()->out(0).reg(); |
+ __ SmiToDouble(result, value); |
+} |
+ |
+ |
+EMIT_NATIVE_CODE(BinaryDoubleOp, 2, Location::RequiresRegister()) { |
+ const Register left = locs()->in(0).reg(); |
+ const Register right = locs()->in(1).reg(); |
+ const Register result = locs()->out(0).reg(); |
+ switch (op_kind()) { |
+ case Token::kADD: __ DAdd(result, left, right); break; |
+ case Token::kSUB: __ DSub(result, left, right); break; |
+ case Token::kMUL: __ DMul(result, left, right); break; |
+ case Token::kDIV: __ DDiv(result, left, right); break; |
+ default: UNREACHABLE(); |
+ } |
+} |
+ |
+ |
+EMIT_NATIVE_CODE(UnaryDoubleOp, 1, Location::RequiresRegister()) { |
+ const Register value = locs()->in(0).reg(); |
+ const Register result = locs()->out(0).reg(); |
+ __ DNeg(result, value); |
+} |
+ |
+ |
static Token::Kind FlipCondition(Token::Kind kind) { |
switch (kind) { |
case Token::kEQ: return Token::kNE; |
@@ -1241,7 +1294,7 @@ static Token::Kind FlipCondition(Token::Kind kind) { |
} |
-static Bytecode::Opcode OpcodeForCondition(Token::Kind kind) { |
+static Bytecode::Opcode OpcodeForSmiCondition(Token::Kind kind) { |
switch (kind) { |
case Token::kEQ: return Bytecode::kIfEqStrict; |
case Token::kNE: return Bytecode::kIfNeStrict; |
@@ -1256,6 +1309,21 @@ static Bytecode::Opcode OpcodeForCondition(Token::Kind kind) { |
} |
+static Bytecode::Opcode OpcodeForDoubleCondition(Token::Kind kind) { |
+ switch (kind) { |
+ case Token::kEQ: return Bytecode::kIfDEq; |
+ case Token::kNE: return Bytecode::kIfDNe; |
+ case Token::kLT: return Bytecode::kIfDLt; |
+ case Token::kGT: return Bytecode::kIfDGt; |
+ case Token::kLTE: return Bytecode::kIfDLe; |
+ case Token::kGTE: return Bytecode::kIfDGe; |
+ default: |
+ UNREACHABLE(); |
+ return Bytecode::kTrap; |
+ } |
+} |
+ |
+ |
static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
LocationSummary* locs, |
Token::Kind kind, |
@@ -1272,7 +1340,28 @@ static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
condition = NEXT_IS_FALSE; |
comparison = FlipCondition(kind); |
} |
- __ Emit(Bytecode::Encode(OpcodeForCondition(comparison), left, right)); |
+ __ Emit(Bytecode::Encode(OpcodeForSmiCondition(comparison), left, right)); |
+ return condition; |
+} |
+ |
+ |
+static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
+ LocationSummary* locs, |
+ Token::Kind kind, |
+ BranchLabels labels) { |
+ const Register left = locs->in(0).reg(); |
+ const Register right = locs->in(1).reg(); |
+ Token::Kind comparison = kind; |
+ Condition condition = NEXT_IS_TRUE; |
+ if (labels.fall_through != labels.false_label) { |
+ // If we aren't falling through to the false label, we can save a Jump |
+ // instruction in the case that the true case is the fall through by |
+ // flipping the sense of the test such that the instruction following the |
+ // test is the Jump to the false label. |
+ condition = NEXT_IS_FALSE; |
+ comparison = FlipCondition(kind); |
+ } |
+ __ Emit(Bytecode::Encode(OpcodeForDoubleCondition(comparison), left, right)); |
return condition; |
} |
@@ -1283,9 +1372,7 @@ Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
return EmitSmiComparisonOp(compiler, locs(), kind(), labels); |
} else { |
ASSERT(operation_cid() == kDoubleCid); |
- Unsupported(compiler); |
- UNREACHABLE(); |
- return NEXT_IS_FALSE; |
+ return EmitDoubleComparisonOp(compiler, locs(), kind(), labels); |
} |
} |
@@ -1321,9 +1408,7 @@ Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
return EmitSmiComparisonOp(compiler, locs(), kind(), labels); |
} else { |
ASSERT(operation_cid() == kDoubleCid); |
- Unsupported(compiler); |
- UNREACHABLE(); |
- return NEXT_IS_FALSE; |
+ return EmitDoubleComparisonOp(compiler, locs(), kind(), labels); |
} |
} |