Index: runtime/vm/intermediate_language.cc |
=================================================================== |
--- runtime/vm/intermediate_language.cc (revision 29114) |
+++ runtime/vm/intermediate_language.cc (working copy) |
@@ -20,6 +20,8 @@ |
#include "vm/stub_code.h" |
#include "vm/symbols.h" |
+#include "vm/il_printer.h" |
+ |
namespace dart { |
DEFINE_FLAG(int, max_equality_polymorphic_checks, 32, |
@@ -2719,6 +2721,65 @@ |
} |
+// Replace StringInterpolateInstr with a constant string if all inputs are |
+// constant of [string, number, boolean, null]. |
+// Leave the CreateArrayInstr and StoreIndexedInstr in the stream in case |
+// deoptimization occurs. |
+Definition* StringInterpolateInstr::Canonicalize(FlowGraph* flow_graph) { |
+ // The following graph structure is generated by the graph builder: |
+ // v2 <- CreateArray(v0) |
+ // StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value. |
+ // .. |
+ // v8 <- StringInterpolate(v2) |
+ CreateArrayInstr* create_array = value()->definition()->AsCreateArray(); |
+ ASSERT(create_array != NULL); |
+ // Check if the string interpolation has only constant inputs. |
+ GrowableArray<ConstantInstr*> constants(create_array->num_elements()); |
+ for (intptr_t i = 0; i < create_array->num_elements(); i++) { |
+ constants.Add(NULL); |
+ } |
+ for (Value::Iterator it(create_array->input_use_list()); |
+ !it.Done(); |
+ it.Advance()) { |
+ Instruction* curr = it.Current()->instruction(); |
+ if (curr != this) { |
+ StoreIndexedInstr* store = curr->AsStoreIndexed(); |
+ ASSERT(store != NULL); |
+ if (store->value()->definition()->IsConstant()) { |
+ ASSERT(store->index()->BindsToConstant()); |
+ const Object& obj = store->value()->definition()->AsConstant()->value(); |
+ if (obj.IsNumber() || obj.IsString() || obj.IsBool() || obj.IsNull()) { |
+ constants[Smi::Cast(store->index()->BoundConstant()).Value()] = |
+ store->value()->definition()->AsConstant(); |
+ } else { |
+ return this; |
+ } |
+ } else { |
+ return this; |
+ } |
+ } |
+ } |
+ // Interpolate string at compile time. |
+ const Array& array_argument = |
+ Array::Handle(Array::New(create_array->num_elements())); |
+ for (intptr_t i = 0; i < constants.length(); i++) { |
+ array_argument.SetAt(i, constants[i]->value()); |
+ } |
+ // Build argument array to pass to the interpolation function. |
+ const Array& interpolate_arg = Array::Handle(Array::New(1)); |
+ interpolate_arg.SetAt(0, array_argument); |
+ // Call interpolation function. |
+ String& concatenated = String::ZoneHandle(); |
+ concatenated ^= |
+ DartEntry::InvokeFunction(CallFunction(), interpolate_arg); |
+ if (concatenated.IsUnhandledException()) { |
+ return this; |
+ } |
+ concatenated = Symbols::New(concatenated); |
+ return flow_graph->GetConstant(concatenated); |
+} |
+ |
+ |
InvokeMathCFunctionInstr::InvokeMathCFunctionInstr( |
ZoneGrowableArray<Value*>* inputs, |
intptr_t original_deopt_id, |