Chromium Code Reviews| Index: runtime/vm/flow_graph_optimizer.cc |
| =================================================================== |
| --- runtime/vm/flow_graph_optimizer.cc (revision 28108) |
| +++ runtime/vm/flow_graph_optimizer.cc (working copy) |
| @@ -6027,7 +6027,73 @@ |
| void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) { |
| - SetValue(instr, non_constant_); |
| + MethodRecognizer::Kind recognized_kind = |
| + MethodRecognizer::RecognizeKind(instr->function()); |
| + if (recognized_kind == MethodRecognizer::kStringBaseInterpolate) { |
|
Kevin Millikin (Google)
2013/10/02 14:09:38
You might also make sure !IsNonConstant(instr->con
srdjan
2013/10/02 16:35:23
Done.
|
| + // static String _interpolate(List values) |
| + // |
| + // Code for calling interpolate is generated by the compiler: |
| + // v2 <- CreateArray(v0) |
| + // StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value. |
| + // .. |
| + // PushArgument(v2) |
| + // v8 <- StaticCall(_interpolate, v2) |
| + // Detect that all values are constant, interpolate at compile |
| + // time. |
| + ASSERT(instr->ArgumentCount() == 1); |
| + CreateArrayInstr* create_array = instr->ArgumentAt(0)->AsCreateArray(); |
| + ASSERT(create_array != NULL); |
| + // Check if the string interpolation has only constant inputs. |
| + for (Value::Iterator it(create_array->input_use_list()); |
| + !it.Done(); |
| + it.Advance()) { |
| + Instruction* curr = it.Current()->instruction(); |
| + StoreIndexedInstr* store = curr->AsStoreIndexed(); |
| + if ((store != NULL) && |
| + (!IsConstant(store->value()->definition()->constant_value()))) { |
|
Kevin Millikin (Google)
2013/10/02 14:09:38
Change !IsConstant to IsNonConstant.
We don't wan
srdjan
2013/10/02 16:35:23
Done.
|
| + SetValue(instr, non_constant_); |
| + return; |
| + } |
| + } |
| + // Interpolate string at compile time. |
| + const Array& value_arr = |
| + Array::Handle(Array::New(create_array->num_elements())); |
| + // GrowableArray<StoreIndexedInstr*> store_instructions; |
| + // Build the array of literal values to interpolate, abort if a value is |
| + // not literal. |
| + for (Value::Iterator it(create_array->input_use_list()); |
| + !it.Done(); |
| + it.Advance()) { |
| + Instruction* curr = it.Current()->instruction(); |
| + StoreIndexedInstr* store = curr->AsStoreIndexed(); |
| + if (store == NULL) { |
| + ASSERT(curr == instr->PushArgumentAt(0)); |
| + } else { |
| + // store_instructions.Add(store); |
| + Value* index_value = store->index(); |
| + ASSERT(index_value->BindsToConstant() && index_value->IsSmiValue()); |
| + const intptr_t ix = Smi::Cast(index_value->BoundConstant()).Value(); |
| + ASSERT(IsConstant(store->value()->definition()->constant_value())); |
| + value_arr.SetAt(ix, store->value()->definition()->constant_value()); |
| + } |
| + } |
| + // Build argument array to pass to the interpolation function. |
| + const Array& interpolate_arg = Array::Handle(Array::New(1)); |
| + interpolate_arg.SetAt(0, value_arr); |
| + // Call interpolation function. |
| + String& concatenated = String::ZoneHandle(); |
| + concatenated ^= |
| + DartEntry::InvokeFunction(instr->function(), interpolate_arg); |
| + if (concatenated.IsUnhandledException()) { |
| + SetValue(instr, non_constant_); |
| + return; |
| + } |
| + |
| + concatenated = Symbols::New(concatenated); |
| + SetValue(instr, concatenated); |
| + } else { |
| + SetValue(instr, non_constant_); |
| + } |
| } |
| @@ -6850,6 +6916,27 @@ |
| } |
| +// Code for calling interpolate is generated by the compiler: |
| +// v2 <- CreateArray(v0) |
| +// StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value. |
| +// .. |
| +// PushArgument(v2) |
| +// v8 <- StaticCall(_interpolate, v2) |
| +// Remove the inputs. |
| +void ConstantPropagator::RemoveInterpolationInputs( |
| + const StaticCallInstr& call) { |
| + ASSERT(call.ArgumentCount() == 1); |
| + CreateArrayInstr* create_array = call.ArgumentAt(0)->AsCreateArray(); |
| + ASSERT(create_array != NULL); |
| + for (Value* use = create_array->input_use_list(); |
| + use != NULL; |
| + use = create_array->input_use_list()) { |
| + use->instruction()->RemoveFromGraph(); |
| + } |
| + create_array->RemoveFromGraph(); |
| +} |
| + |
| + |
| void ConstantPropagator::Transform() { |
| if (FLAG_trace_constant_propagation) { |
| OS::Print("\n==== Before constant propagation ====\n"); |
| @@ -6957,6 +7044,13 @@ |
| ConstantInstr* constant = graph_->GetConstant(defn->constant_value()); |
| defn->ReplaceUsesWith(constant); |
| i.RemoveCurrentFromGraph(); |
| + if (defn->IsStaticCall()) { |
| + MethodRecognizer::Kind recognized_kind = |
| + MethodRecognizer::RecognizeKind(defn->AsStaticCall()->function()); |
| + if (recognized_kind == MethodRecognizer::kStringBaseInterpolate) { |
| + RemoveInterpolationInputs(*defn->AsStaticCall()); |
| + } |
| + } |
| } |
| } |