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 ce258c038f69909b353077aa651e8c74ace88038..88d81518338a57ad9ffadd3f59ccf74e11d99477 100644 |
| --- a/runtime/vm/flow_graph_optimizer.cc |
| +++ b/runtime/vm/flow_graph_optimizer.cc |
| @@ -1361,6 +1361,10 @@ bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid, |
| return InlineByteArrayViewLoad(call, receiver, receiver_cid, |
| kTypedDataInt32x4ArrayCid, |
| ic_data, entry, last); |
| + case MethodRecognizer::kStringBaseCodeUnitAt: |
| + return InlineStringCodeUnitAt(call, receiver_cid, entry, last); |
| + case MethodRecognizer::kStringBaseCharAt: |
| + return InlineStringBaseCharAt(call, receiver_cid, entry, last); |
| default: |
| return false; |
| } |
| @@ -2369,6 +2373,103 @@ bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { |
| } |
| +// Returns the LoadIndexedInstr. |
| +Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp( |
| + Instruction* call, |
| + intptr_t cid, |
| + Definition* str, |
| + Definition* index, |
| + Instruction* cursor) { |
| + |
| + cursor = flow_graph()->AppendTo(cursor, |
| + new CheckSmiInstr(new Value(index), |
| + call->deopt_id()), |
| + call->env(), |
| + Definition::kEffect); |
| + |
| + // If both index and string are constants, then do a compile-time check. |
| + // TODO(srdjan): Remove once constant propagation handles bounds checks. |
| + bool skip_check = false; |
|
Florian Schneider
2014/02/13 11:57:46
I'm pretty sure that constant propagation handles
|
| + if (str->IsConstant() && index->IsConstant()) { |
| + const String& constant_string = |
| + String::Cast(str->AsConstant()->value()); |
| + const Object& constant_index = index->AsConstant()->value(); |
| + skip_check = constant_index.IsSmi() && |
| + (Smi::Cast(constant_index).Value() < constant_string.Length()); |
| + } |
| + |
| + if (!skip_check) { |
| + // Load the length of the string. |
| + LoadFieldInstr* length = BuildLoadStringLength(str); |
| + cursor = flow_graph()->AppendTo(cursor, length, NULL, Definition::kValue); |
| + // Bounds check. |
| + cursor = flow_graph()->AppendTo(cursor, |
| + new CheckArrayBoundInstr(new Value(length), |
| + new Value(index), |
| + call->deopt_id()), |
| + call->env(), |
| + Definition::kEffect); |
| + } |
| + LoadIndexedInstr* load_indexed = new LoadIndexedInstr( |
| + new Value(str), |
| + new Value(index), |
| + FlowGraphCompiler::ElementSizeFor(cid), |
| + cid, |
| + Isolate::kNoDeoptId); |
| + |
| + cursor = flow_graph()->AppendTo(cursor, |
| + load_indexed, |
| + NULL, |
| + Definition::kValue); |
| + ASSERT(cursor == load_indexed); |
| + return load_indexed; |
| +} |
| + |
| + |
| +bool FlowGraphOptimizer::InlineStringCodeUnitAt( |
| + Instruction* call, |
| + intptr_t cid, |
| + TargetEntryInstr** entry, |
| + Definition** last) { |
| + |
| + Definition* str = call->ArgumentAt(0); |
| + Definition* index = call->ArgumentAt(1); |
| + |
| + *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(), |
| + call->GetBlock()->try_index()); |
| + (*entry)->InheritDeoptTarget(call); |
| + |
| + *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
| + |
| + return true; |
| +} |
| + |
| + |
| +bool FlowGraphOptimizer::InlineStringBaseCharAt( |
| + Instruction* call, |
| + intptr_t cid, |
| + TargetEntryInstr** entry, |
| + Definition** last) { |
| + |
| + Definition* str = call->ArgumentAt(0); |
| + Definition* index = call->ArgumentAt(1); |
| + |
| + *entry = new TargetEntryInstr(flow_graph()->allocate_block_id(), |
| + call->GetBlock()->try_index()); |
| + (*entry)->InheritDeoptTarget(call); |
| + |
| + *last = PrepareInlineStringIndexOp(call, cid, str, index, *entry); |
| + |
| + StringFromCharCodeInstr* char_at = |
| + new StringFromCharCodeInstr(new Value(*last), cid); |
| + |
| + flow_graph()->AppendTo(*last, char_at, NULL, Definition::kValue); |
| + *last = char_at; |
| + |
| + return true; |
| +} |
| + |
| + |
| LoadIndexedInstr* FlowGraphOptimizer::BuildStringCodeUnitAt( |
|
Florian Schneider
2014/02/13 11:57:46
I think you should be able to use your newly intro
|
| InstanceCallInstr* call, |
| intptr_t cid) { |