| Index: runtime/vm/flow_graph_optimizer.cc
|
| diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
|
| index cb7eb2b67e0ca37ba79a0537ea09790b66f88099..901b5a1640917c1159bab69364e8d87477c46182 100644
|
| --- a/runtime/vm/flow_graph_optimizer.cc
|
| +++ b/runtime/vm/flow_graph_optimizer.cc
|
| @@ -1631,6 +1631,14 @@ bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid,
|
| return InlineStringCodeUnitAt(call, receiver_cid, entry, last);
|
| case MethodRecognizer::kStringBaseCharAt:
|
| return InlineStringBaseCharAt(call, receiver_cid, entry, last);
|
| + case MethodRecognizer::kOneByteString_oneCodeUnitAt:
|
| + case MethodRecognizer::kTwoByteString_oneCodeUnitAt:
|
| + return InlineStringCodeUnitsAt(call, receiver_cid, 1, entry, last);
|
| + case MethodRecognizer::kOneByteString_twoCodeUnitsAt:
|
| + case MethodRecognizer::kTwoByteString_twoCodeUnitsAt:
|
| + return InlineStringCodeUnitsAt(call, receiver_cid, 2, entry, last);
|
| + case MethodRecognizer::kOneByteString_fourCodeUnitsAt:
|
| + return InlineStringCodeUnitsAt(call, receiver_cid, 4, entry, last);
|
| case MethodRecognizer::kDoubleAdd:
|
| return InlineDoubleOp(Token::kADD, call, entry, last);
|
| case MethodRecognizer::kDoubleSub:
|
| @@ -2841,6 +2849,55 @@ bool FlowGraphOptimizer::InlineStringCodeUnitAt(
|
| }
|
|
|
|
|
| +Definition* FlowGraphOptimizer::PrepareInlineStringIndexOpUnchecked(
|
| + Instruction* call,
|
| + intptr_t cid,
|
| + intptr_t count,
|
| + Definition* str,
|
| + Definition* index,
|
| + Instruction* cursor) {
|
| + LoadCodeUnitsInstr* load = new(I) LoadCodeUnitsInstr(
|
| + new(I) Value(str),
|
| + new(I) Value(index),
|
| + count,
|
| + cid,
|
| + call->token_pos());
|
| +
|
| + cursor = flow_graph()->AppendTo(cursor,
|
| + load,
|
| + NULL,
|
| + FlowGraph::kValue);
|
| + ASSERT(cursor == load);
|
| + return load;
|
| +}
|
| +
|
| +
|
| +bool FlowGraphOptimizer::InlineStringCodeUnitsAt(
|
| + Instruction* call,
|
| + intptr_t cid,
|
| + intptr_t count,
|
| + TargetEntryInstr** entry,
|
| + Definition** last) {
|
| + // TODO(jgruber): Handle external strings in
|
| + // PrepareInlineStringIndexOpUnchecked.
|
| + if (RawObject::IsExternalStringClassId(cid)) {
|
| + return false;
|
| + }
|
| +
|
| + Definition* str = call->ArgumentAt(0);
|
| + Definition* index = call->ArgumentAt(1);
|
| +
|
| + *entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(),
|
| + call->GetBlock()->try_index());
|
| + (*entry)->InheritDeoptTarget(I, call);
|
| +
|
| + *last = PrepareInlineStringIndexOpUnchecked(
|
| + call, cid, count, str, index, *entry);
|
| +
|
| + return true;
|
| +}
|
| +
|
| +
|
| bool FlowGraphOptimizer::InlineStringBaseCharAt(
|
| Instruction* call,
|
| intptr_t cid,
|
| @@ -3033,7 +3090,12 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
|
| }
|
|
|
| if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) ||
|
| - (recognized_kind == MethodRecognizer::kStringBaseCharAt)) &&
|
| + (recognized_kind == MethodRecognizer::kStringBaseCharAt) ||
|
| + (recognized_kind == MethodRecognizer::kOneByteString_oneCodeUnitAt) ||
|
| + (recognized_kind == MethodRecognizer::kOneByteString_twoCodeUnitsAt) ||
|
| + (recognized_kind == MethodRecognizer::kOneByteString_fourCodeUnitsAt) ||
|
| + (recognized_kind == MethodRecognizer::kTwoByteString_oneCodeUnitAt) ||
|
| + (recognized_kind == MethodRecognizer::kTwoByteString_twoCodeUnitsAt)) &&
|
| (ic_data.NumberOfChecks() == 1) &&
|
| ((class_ids[0] == kOneByteStringCid) ||
|
| (class_ids[0] == kTwoByteStringCid))) {
|
| @@ -7662,6 +7724,13 @@ void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) {
|
| }
|
|
|
|
|
| +void ConstantPropagator::VisitIndirectEntry(IndirectEntryInstr* block) {
|
| + for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
|
| + it.Current()->Accept(this);
|
| + }
|
| +}
|
| +
|
| +
|
| void ConstantPropagator::VisitCatchBlockEntry(CatchBlockEntryInstr* block) {
|
| const GrowableArray<Definition*>& defs = *block->initial_definitions();
|
| for (intptr_t i = 0; i < defs.length(); ++i) {
|
| @@ -7709,6 +7778,13 @@ void ConstantPropagator::VisitGoto(GotoInstr* instr) {
|
| }
|
|
|
|
|
| +void ConstantPropagator::VisitIndirectGoto(IndirectGotoInstr* instr) {
|
| + for (intptr_t i = 0; i < instr->SuccessorCount(); i++) {
|
| + SetReachable(instr->SuccessorAt(i));
|
| + }
|
| +}
|
| +
|
| +
|
| void ConstantPropagator::VisitBranch(BranchInstr* instr) {
|
| instr->comparison()->Accept(this);
|
|
|
| @@ -8120,6 +8196,12 @@ void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) {
|
| }
|
|
|
|
|
| +void ConstantPropagator::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) {
|
| + // TODO(jgruber): Implement constant propagation.
|
| + SetValue(instr, non_constant_);
|
| +}
|
| +
|
| +
|
| void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) {
|
| SetValue(instr, instr->value()->definition()->constant_value());
|
| }
|
| @@ -8762,6 +8844,12 @@ void ConstantPropagator::VisitMathMinMax(MathMinMaxInstr* instr) {
|
| }
|
|
|
|
|
| +void ConstantPropagator::VisitCaseInsensitiveCompareUC16(
|
| + CaseInsensitiveCompareUC16Instr *instr) {
|
| + SetValue(instr, non_constant_);
|
| +}
|
| +
|
| +
|
| void ConstantPropagator::VisitUnboxDouble(UnboxDoubleInstr* instr) {
|
| const Object& value = instr->value()->definition()->constant_value();
|
| if (IsNonConstant(value)) {
|
| @@ -8911,7 +8999,8 @@ void ConstantPropagator::Analyze() {
|
|
|
| static bool IsEmptyBlock(BlockEntryInstr* block) {
|
| return block->next()->IsGoto() &&
|
| - (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL));
|
| + (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) &&
|
| + !block->IsIndirectEntry();
|
| }
|
|
|
|
|
|
|