Chromium Code Reviews| 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..96ca5fe81a20efbe04e83dc002c39eb43c547150 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,54 @@ 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(johnmccutchan): Handle external strings in PrepareInlineStringIndexOp. |
| + if (RawObject::IsExternalStringClassId(cid)) { |
| + return false; |
|
Ivan Posva
2014/10/09 09:54:15
What will be generated when we return false here?
jgruber1
2014/10/09 13:36:16
The inlined version of String::_codeUnitsAt().
|
| + } |
| + |
| + 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 +3088,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 +7748,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 +7802,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 +8220,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 +8868,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)) { |
| @@ -8936,7 +9023,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(); |
| } |