Index: runtime/vm/flow_graph_optimizer.cc |
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc |
index f5333546f2ed98d51cc45fded39181aab427b875..ceab334b4677ad13a93e99803773695b59409553 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: |
@@ -2840,6 +2848,56 @@ 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), |
+ Instance::ElementSizeFor(cid), |
+ count, |
+ cid, |
+ Isolate::kNoDeoptId, |
+ 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(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. |
+ 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, |
@@ -3032,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))) { |
@@ -7687,6 +7750,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) { |
@@ -7734,6 +7804,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); |
@@ -8145,6 +8222,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()); |
} |
@@ -8787,6 +8870,13 @@ void ConstantPropagator::VisitMathMinMax(MathMinMaxInstr* instr) { |
} |
+void ConstantPropagator::VisitCaseInsensitiveCompareUC16( |
+ CaseInsensitiveCompareUC16Instr *instr) { |
+ // TODO(jgruber): Handle constant propagation. |
+ SetValue(instr, non_constant_); |
+} |
+ |
+ |
void ConstantPropagator::VisitUnboxDouble(UnboxDoubleInstr* instr) { |
const Object& value = instr->value()->definition()->constant_value(); |
if (IsNonConstant(value)) { |
@@ -8936,7 +9026,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(); |
} |