 Chromium Code Reviews
 Chromium Code Reviews Issue 2113563002:
  DBC: Various instructions.  (Closed) 
  Base URL: git@github.com:dart-lang/sdk.git@master
    
  
    Issue 2113563002:
  DBC: Various instructions.  (Closed) 
  Base URL: git@github.com:dart-lang/sdk.git@master| Index: runtime/vm/intermediate_language_dbc.cc | 
| diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc | 
| index cfbfaa8ca07efc16546b90d81baea243f638e62e..29f5e0ff2764f6b620fb1f4ca7cd139965d1364b 100644 | 
| --- a/runtime/vm/intermediate_language_dbc.cc | 
| +++ b/runtime/vm/intermediate_language_dbc.cc | 
| @@ -101,10 +101,6 @@ DECLARE_FLAG(int, optimization_counter_threshold); | 
| M(BoxInteger32) \ | 
| M(UnboxInteger32) \ | 
| M(CheckedSmiOp) \ | 
| - M(CheckArrayBound) \ | 
| - M(RelationalOp) \ | 
| - M(EqualityCompare) \ | 
| - M(LoadIndexed) | 
| // Location summaries actually are not used by the unoptimizing DBC compiler | 
| // because we don't allocate any registers. | 
| @@ -169,8 +165,6 @@ FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED) | 
| #undef DEFINE_UNIMPLEMENTED | 
| DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(TestCids) | 
| -DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(RelationalOp) | 
| -DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(EqualityCompare) | 
| EMIT_NATIVE_CODE(InstanceOf, 2, Location::SameAsFirstInput(), | 
| @@ -582,6 +576,23 @@ EMIT_NATIVE_CODE(StoreIndexed, 3) { | 
| } | 
| +EMIT_NATIVE_CODE(LoadIndexed, 2, Location::RequiresRegister()) { | 
| + ASSERT(compiler->is_optimizing()); | 
| + if (class_id() != kArrayCid) { | 
| +#if defined(PRODUCT) | 
| 
Vyacheslav Egorov (Google)
2016/06/30 15:55:26
Consider adding a helper method on the Instruction
 
zra
2016/06/30 17:32:31
Doing this here: https://codereview.chromium.org/2
 | 
| + compiler->Bailout("LoadIndexed"); | 
| +#else // defined(PRODUCT) | 
| + compiler->Bailout(ToCString()); | 
| +#endif // defined(PRODUCT) | 
| + } | 
| + const Register array = locs()->in(0).reg(); | 
| + const Register index = locs()->in(1).reg(); | 
| + const Register result = locs()->out(0).reg(); | 
| + | 
| + __ LoadIndexed(result, array, index); | 
| +} | 
| + | 
| + | 
| EMIT_NATIVE_CODE(StringInterpolate, | 
| 1, Location::RegisterLocation(0), | 
| LocationSummary::kCall) { | 
| @@ -649,7 +660,6 @@ EMIT_NATIVE_CODE(StringToCharCode, | 
| } | 
| - | 
| EMIT_NATIVE_CODE(AllocateObject, | 
| 0, Location::RequiresRegister(), | 
| LocationSummary::kCall) { | 
| @@ -1163,6 +1173,139 @@ EMIT_NATIVE_CODE(UnarySmiOp, 1, Location::RequiresRegister()) { | 
| } | 
| } | 
| + | 
| +static Token::Kind FlipCondition(Token::Kind kind) { | 
| + switch (kind) { | 
| + case Token::kEQ: return Token::kNE; | 
| + case Token::kNE: return Token::kEQ; | 
| + case Token::kLT: return Token::kGTE; | 
| + case Token::kGT: return Token::kLTE; | 
| + case Token::kLTE: return Token::kGT; | 
| + case Token::kGTE: return Token::kLT; | 
| + default: | 
| + UNREACHABLE(); | 
| + return Token::kNE; | 
| + } | 
| +} | 
| + | 
| + | 
| +static Bytecode::Opcode OpcodeForCondition(Token::Kind kind) { | 
| + switch (kind) { | 
| + case Token::kEQ: return Bytecode::kIfEqStrict; | 
| + case Token::kNE: return Bytecode::kIfNeStrict; | 
| + case Token::kLT: return Bytecode::kIfLt; | 
| + case Token::kGT: return Bytecode::kIfGt; | 
| + case Token::kLTE: return Bytecode::kIfLe; | 
| + case Token::kGTE: return Bytecode::kIfGe; | 
| + default: | 
| + UNREACHABLE(); | 
| + return Bytecode::kTrap; | 
| + } | 
| +} | 
| + | 
| + | 
| +static Condition EmitSmiComparisonOp(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) { | 
| + // Flip comparision to save a jump. | 
| + condition = NEXT_IS_FALSE; | 
| + comparison = FlipCondition(kind); | 
| + } | 
| + __ Emit(Bytecode::Encode(OpcodeForCondition(comparison), left, right)); | 
| + return condition; | 
| +} | 
| + | 
| + | 
| +Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 
| + BranchLabels labels) { | 
| + if (operation_cid() == kSmiCid) { | 
| + return EmitSmiComparisonOp(compiler, locs(), kind(), labels); | 
| + } else { | 
| + ASSERT(operation_cid() == kDoubleCid); | 
| +#if defined(PRODUCT) | 
| + compiler->Bailout("EqualityCompareInstr::EmitComparisonCode"); | 
| +#else // defined(PRODUCT) | 
| + compiler->Bailout(ToCString()); | 
| +#endif // defined(PRODUCT) | 
| + return NEXT_IS_FALSE; | 
| + } | 
| +} | 
| + | 
| + | 
| +EMIT_NATIVE_CODE(EqualityCompare, 2, Location::RequiresRegister()) { | 
| + ASSERT(compiler->is_optimizing()); | 
| + ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 
| + Label is_true, is_false; | 
| + BranchLabels labels = { &is_true, &is_false, &is_false }; | 
| + const Register result = locs()->out(0).reg(); | 
| + __ LoadConstant(result, Bool::False()); | 
| + Condition true_condition = EmitComparisonCode(compiler, labels); | 
| + ASSERT(true_condition == NEXT_IS_TRUE); | 
| + __ LoadConstant(result, Bool::True()); | 
| +} | 
| + | 
| + | 
| +void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 
| + BranchInstr* branch) { | 
| + ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 
| + BranchLabels labels = compiler->CreateBranchLabels(branch); | 
| + Condition true_condition = EmitComparisonCode(compiler, labels); | 
| + EmitBranchOnCondition(compiler, true_condition, labels); | 
| +} | 
| + | 
| + | 
| +Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 
| + BranchLabels labels) { | 
| + if (operation_cid() == kSmiCid) { | 
| + return EmitSmiComparisonOp(compiler, locs(), kind(), labels); | 
| + } else { | 
| + ASSERT(operation_cid() == kDoubleCid); | 
| +#if defined(PRODUCT) | 
| + compiler->Bailout("EqualityCompareInstr::EmitComparisonCode"); | 
| +#else // defined(PRODUCT) | 
| + compiler->Bailout(ToCString()); | 
| +#endif // defined(PRODUCT) | 
| + return NEXT_IS_FALSE; | 
| + } | 
| +} | 
| + | 
| + | 
| +EMIT_NATIVE_CODE(RelationalOp, 2, Location::RequiresRegister()) { | 
| + ASSERT(compiler->is_optimizing()); | 
| + Label is_true, is_false; | 
| + BranchLabels labels = { &is_true, &is_false, &is_false }; | 
| + const Register result = locs()->out(0).reg(); | 
| + __ LoadConstant(result, Bool::False()); | 
| + Condition true_condition = EmitComparisonCode(compiler, labels); | 
| + ASSERT(true_condition == NEXT_IS_TRUE); | 
| + __ LoadConstant(result, Bool::True()); | 
| +} | 
| + | 
| + | 
| +void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 
| + BranchInstr* branch) { | 
| + BranchLabels labels = compiler->CreateBranchLabels(branch); | 
| + Condition true_condition = EmitComparisonCode(compiler, labels); | 
| + EmitBranchOnCondition(compiler, true_condition, labels); | 
| +} | 
| + | 
| + | 
| +EMIT_NATIVE_CODE(CheckArrayBound, 2) { | 
| + const Register length = locs()->in(kLengthPos).reg(); | 
| + const Register index = locs()->in(kIndexPos).reg(); | 
| + __ IfLe(length, index); | 
| + compiler->EmitDeopt(deopt_id(), | 
| + ICData::kDeoptCheckArrayBound, | 
| + (generalized_ ? ICData::kGeneralized : 0) | | 
| + (licm_hoisted_ ? ICData::kHoisted : 0)); | 
| +} | 
| + | 
| } // namespace dart | 
| #endif // defined TARGET_ARCH_DBC |