Index: runtime/vm/intermediate_language_dbc.cc |
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc |
index 8c954b66fda2af8aabb5ac868ede98968f4e31d1..5996336b7a2cf51d77f330a88f3bff23bcce280c 100644 |
--- a/runtime/vm/intermediate_language_dbc.cc |
+++ b/runtime/vm/intermediate_language_dbc.cc |
@@ -30,7 +30,6 @@ DECLARE_FLAG(int, optimization_counter_threshold); |
// List of instructions that are still unimplemented by DBC backend. |
#define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M) \ |
- M(IndirectGoto) \ |
M(LoadCodeUnits) \ |
M(LoadUntagged) \ |
M(AllocateUninitializedContext) \ |
@@ -51,7 +50,6 @@ DECLARE_FLAG(int, optimization_counter_threshold); |
M(Box) \ |
M(Unbox) \ |
M(BoxInt64) \ |
- M(CaseInsensitiveCompareUC16) \ |
M(BinaryMintOp) \ |
M(ShiftMintOp) \ |
M(UnaryMintOp) \ |
@@ -82,7 +80,6 @@ DECLARE_FLAG(int, optimization_counter_threshold); |
M(Int32x4SetFlag) \ |
M(Int32x4ToFloat32x4) \ |
M(BinaryInt32x4Op) \ |
- M(TestCids) \ |
M(BinaryFloat64x2Op) \ |
M(Float64x2Zero) \ |
M(Float64x2Constructor) \ |
@@ -97,7 +94,6 @@ DECLARE_FLAG(int, optimization_counter_threshold); |
M(ShiftUint32Op) \ |
M(UnaryUint32Op) \ |
M(UnboxedIntConverter) \ |
- M(GrowRegExpStack) \ |
M(BoxInteger32) \ |
M(UnboxInteger32) \ |
M(CheckedSmiOp) \ |
@@ -106,6 +102,12 @@ DECLARE_FLAG(int, optimization_counter_threshold); |
M(EqualityCompare) \ |
M(LoadIndexed) |
+// List of instructions that are not used by DBC. |
+#define FOR_EACH_UNREACHABLE_INSTRUCTION(M) \ |
+ M(CaseInsensitiveCompareUC16) \ |
+ M(GrowRegExpStack) \ |
+ M(IndirectGoto) |
+ |
// Location summaries actually are not used by the unoptimizing DBC compiler |
// because we don't allocate any registers. |
static LocationSummary* CreateLocationSummary( |
@@ -145,11 +147,23 @@ static LocationSummary* CreateLocationSummary( |
return NULL; \ |
} \ |
+#define DEFINE_UNREACHABLE_MAKE_LOCATION_SUMMARY(Name) \ |
+ LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt) \ |
+ const { \ |
+ UNREACHABLE(); \ |
+ return NULL; \ |
+ } \ |
+ |
#define DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name) \ |
void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) { \ |
UNIMPLEMENTED(); \ |
} |
+#define DEFINE_UNREACHABLE_EMIT_NATIVE_CODE(Name) \ |
+ void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) { \ |
+ UNREACHABLE(); \ |
+ } |
+ |
#define DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(Name) \ |
void Name##Instr::EmitBranchCode(FlowGraphCompiler*, BranchInstr*) { \ |
UNIMPLEMENTED(); \ |
@@ -168,7 +182,14 @@ FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED) |
#undef DEFINE_UNIMPLEMENTED |
-DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(TestCids) |
+#define DEFINE_UNREACHABLE(Name) \ |
+ DEFINE_UNREACHABLE_MAKE_LOCATION_SUMMARY(Name) \ |
+ DEFINE_UNREACHABLE_EMIT_NATIVE_CODE(Name) \ |
+ |
+FOR_EACH_UNREACHABLE_INSTRUCTION(DEFINE_UNREACHABLE) |
+ |
+#undef DEFINE_UNREACHABLE |
+ |
DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(RelationalOp) |
DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(EqualityCompare) |
@@ -544,6 +565,62 @@ EMIT_NATIVE_CODE(TestSmi, |
} |
+Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
+ BranchLabels labels) { |
+ ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
+ const Register value = locs()->in(0).reg(); |
+ const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
+ |
+ const ZoneGrowableArray<intptr_t>& data = cid_results(); |
+ const intptr_t num_cases = data.length() / 2; |
+ ASSERT(num_cases <= 255); |
+ __ TestCids(value, num_cases); |
+ |
+ bool result = false; |
+ for (intptr_t i = 0; i < data.length(); i += 2) { |
+ const intptr_t test_cid = data[i]; |
+ result = data[i + 1] == true_result; |
+ __ Nop(result ? 1 : 0, compiler->ToEmbeddableCid(test_cid, this)); |
+ } |
+ |
+ // No match found, deoptimize or false. |
+ if (CanDeoptimize()) { |
+ compiler->EmitDeopt(deopt_id(), |
+ ICData::kDeoptTestCids, |
+ licm_hoisted_ ? ICData::kHoisted : 0); |
+ } else { |
+ Label* target = result ? labels.false_label : labels.true_label; |
+ __ Jump(target); |
+ } |
+ |
+ return NEXT_IS_TRUE; |
+} |
+ |
+ |
+void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
+ BranchInstr* branch) { |
+ BranchLabels labels = compiler->CreateBranchLabels(branch); |
+ Condition true_condition = EmitComparisonCode(compiler, labels); |
+ EmitBranchOnCondition(compiler, true_condition, labels); |
+} |
+ |
+ |
+EMIT_NATIVE_CODE(TestCids, 1, Location::RequiresRegister(), |
+ LocationSummary::kNoCall) { |
+ Register result_reg = locs()->out(0).reg(); |
+ Label is_true, is_false, done; |
+ BranchLabels labels = { &is_true, &is_false, &is_false }; |
+ EmitComparisonCode(compiler, labels); |
+ __ Jump(&is_true); |
+ __ Bind(&is_false); |
+ __ LoadConstant(result_reg, Bool::False()); |
+ __ Jump(&done); |
+ __ Bind(&is_true); |
+ __ LoadConstant(result_reg, Bool::True()); |
+ __ Bind(&done); |
+} |
+ |
+ |
EMIT_NATIVE_CODE(CreateArray, |
2, Location::RequiresRegister(), |
LocationSummary::kCall) { |