Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 24837002: Optimize string interpolation by running it at compile time if all inputs are constant. This is don… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 6017 matching lines...) Expand 10 before | Expand all | Expand 10 after
6028 } 6028 }
6029 6029
6030 6030
6031 void ConstantPropagator::VisitPolymorphicInstanceCall( 6031 void ConstantPropagator::VisitPolymorphicInstanceCall(
6032 PolymorphicInstanceCallInstr* instr) { 6032 PolymorphicInstanceCallInstr* instr) {
6033 SetValue(instr, non_constant_); 6033 SetValue(instr, non_constant_);
6034 } 6034 }
6035 6035
6036 6036
6037 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) { 6037 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) {
6038 SetValue(instr, non_constant_); 6038 if (IsNonConstant(instr->constant_value())) {
6039 // Do not bother with costly analysis if we already know that the
6040 // instruction is not a constant.
6041 SetValue(instr, non_constant_);
6042 return;
6043 }
6044 MethodRecognizer::Kind recognized_kind =
6045 MethodRecognizer::RecognizeKind(instr->function());
6046 if (recognized_kind == MethodRecognizer::kStringBaseInterpolate) {
6047 // static String _interpolate(List values)
6048 //
6049 // Code for calling interpolate is generated by the compiler:
6050 // v2 <- CreateArray(v0)
6051 // StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value.
6052 // ..
6053 // PushArgument(v2)
6054 // v8 <- StaticCall(_interpolate, v2)
6055 // Detect that all values are constant, interpolate at compile
6056 // time.
6057 ASSERT(instr->ArgumentCount() == 1);
6058 CreateArrayInstr* create_array = instr->ArgumentAt(0)->AsCreateArray();
6059 ASSERT(create_array != NULL);
6060 // Check if the string interpolation has only constant inputs.
6061 for (Value::Iterator it(create_array->input_use_list());
6062 !it.Done();
6063 it.Advance()) {
6064 Instruction* curr = it.Current()->instruction();
6065 StoreIndexedInstr* store = curr->AsStoreIndexed();
6066 // 'store' is NULL fir PushArgument instruction: skip it.
6067 if ((store != NULL) &&
6068 (IsNonConstant(store->value()->definition()->constant_value()))) {
6069 SetValue(instr, non_constant_);
6070 return;
6071 }
6072 }
6073 // Interpolate string at compile time.
6074 const Array& value_arr =
6075 Array::Handle(Array::New(create_array->num_elements()));
6076 // Build the array of literal values to interpolate, abort if a value is
6077 // not literal.
6078 for (Value::Iterator it(create_array->input_use_list());
6079 !it.Done();
6080 it.Advance()) {
6081 Instruction* curr = it.Current()->instruction();
6082 StoreIndexedInstr* store = curr->AsStoreIndexed();
6083 if (store == NULL) {
6084 ASSERT(curr == instr->PushArgumentAt(0));
6085 } else {
6086 Value* index_value = store->index();
6087 ASSERT(index_value->BindsToConstant() && index_value->IsSmiValue());
6088 const intptr_t ix = Smi::Cast(index_value->BoundConstant()).Value();
6089 ASSERT(IsConstant(store->value()->definition()->constant_value()));
6090 value_arr.SetAt(ix, store->value()->definition()->constant_value());
6091 }
6092 }
6093 // Build argument array to pass to the interpolation function.
6094 const Array& interpolate_arg = Array::Handle(Array::New(1));
6095 interpolate_arg.SetAt(0, value_arr);
6096 // Call interpolation function.
6097 String& concatenated = String::ZoneHandle();
6098 concatenated ^=
6099 DartEntry::InvokeFunction(instr->function(), interpolate_arg);
6100 if (concatenated.IsUnhandledException()) {
6101 SetValue(instr, non_constant_);
6102 return;
6103 }
6104
6105 concatenated = Symbols::New(concatenated);
6106 SetValue(instr, concatenated);
6107 } else {
6108 SetValue(instr, non_constant_);
6109 }
6039 } 6110 }
6040 6111
6041 6112
6042 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) { 6113 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) {
6043 // Instruction is eliminated when translating to SSA. 6114 // Instruction is eliminated when translating to SSA.
6044 UNREACHABLE(); 6115 UNREACHABLE();
6045 } 6116 }
6046 6117
6047 6118
6048 void ConstantPropagator::VisitPushTemp(PushTempInstr* instr) { 6119 void ConstantPropagator::VisitPushTemp(PushTempInstr* instr) {
(...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after
6861 } else { 6932 } else {
6862 // No new information: Assume both targets are reachable. 6933 // No new information: Assume both targets are reachable.
6863 SetReachable(branch->true_successor()); 6934 SetReachable(branch->true_successor());
6864 SetReachable(branch->false_successor()); 6935 SetReachable(branch->false_successor());
6865 } 6936 }
6866 } 6937 }
6867 } 6938 }
6868 } 6939 }
6869 6940
6870 6941
6942 // Code for calling interpolate is generated by the compiler:
6943 // v2 <- CreateArray(v0)
6944 // StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value.
6945 // ..
6946 // PushArgument(v2)
6947 // v8 <- StaticCall(_interpolate, v2)
6948 // Remove the inputs.
6949 void ConstantPropagator::RemoveInterpolationInputs(
6950 const StaticCallInstr& call) {
6951 ASSERT(call.ArgumentCount() == 1);
6952 CreateArrayInstr* create_array = call.ArgumentAt(0)->AsCreateArray();
6953 ASSERT(create_array != NULL);
6954 for (Value* use = create_array->input_use_list();
6955 use != NULL;
6956 use = create_array->input_use_list()) {
6957 use->instruction()->RemoveFromGraph();
6958 }
6959 create_array->RemoveFromGraph();
6960 }
6961
6962
6871 void ConstantPropagator::Transform() { 6963 void ConstantPropagator::Transform() {
6872 if (FLAG_trace_constant_propagation) { 6964 if (FLAG_trace_constant_propagation) {
6873 OS::Print("\n==== Before constant propagation ====\n"); 6965 OS::Print("\n==== Before constant propagation ====\n");
6874 FlowGraphPrinter printer(*graph_); 6966 FlowGraphPrinter printer(*graph_);
6875 printer.PrintBlocks(); 6967 printer.PrintBlocks();
6876 } 6968 }
6877 6969
6878 GrowableArray<PhiInstr*> redundant_phis(10); 6970 GrowableArray<PhiInstr*> redundant_phis(10);
6879 6971
6880 // We will recompute dominators, block ordering, block ids, block last 6972 // We will recompute dominators, block ordering, block ids, block last
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
6968 !defn->IsStoreStaticField() && 7060 !defn->IsStoreStaticField() &&
6969 !defn->IsStoreVMField()) { 7061 !defn->IsStoreVMField()) {
6970 if (FLAG_trace_constant_propagation) { 7062 if (FLAG_trace_constant_propagation) {
6971 OS::Print("Constant v%" Pd " = %s\n", 7063 OS::Print("Constant v%" Pd " = %s\n",
6972 defn->ssa_temp_index(), 7064 defn->ssa_temp_index(),
6973 defn->constant_value().ToCString()); 7065 defn->constant_value().ToCString());
6974 } 7066 }
6975 ConstantInstr* constant = graph_->GetConstant(defn->constant_value()); 7067 ConstantInstr* constant = graph_->GetConstant(defn->constant_value());
6976 defn->ReplaceUsesWith(constant); 7068 defn->ReplaceUsesWith(constant);
6977 i.RemoveCurrentFromGraph(); 7069 i.RemoveCurrentFromGraph();
7070 if (defn->IsStaticCall()) {
7071 MethodRecognizer::Kind recognized_kind =
7072 MethodRecognizer::RecognizeKind(defn->AsStaticCall()->function());
7073 if (recognized_kind == MethodRecognizer::kStringBaseInterpolate) {
7074 RemoveInterpolationInputs(*defn->AsStaticCall());
7075 }
7076 }
6978 } 7077 }
6979 } 7078 }
6980 7079
6981 // Replace branches where one target is unreachable with jumps. 7080 // Replace branches where one target is unreachable with jumps.
6982 BranchInstr* branch = block->last_instruction()->AsBranch(); 7081 BranchInstr* branch = block->last_instruction()->AsBranch();
6983 if (branch != NULL) { 7082 if (branch != NULL) {
6984 TargetEntryInstr* if_true = branch->true_successor(); 7083 TargetEntryInstr* if_true = branch->true_successor();
6985 TargetEntryInstr* if_false = branch->false_successor(); 7084 TargetEntryInstr* if_false = branch->false_successor();
6986 JoinEntryInstr* join = NULL; 7085 JoinEntryInstr* join = NULL;
6987 Instruction* next = NULL; 7086 Instruction* next = NULL;
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
7653 } 7752 }
7654 7753
7655 // Insert materializations at environment uses. 7754 // Insert materializations at environment uses.
7656 for (intptr_t i = 0; i < exits.length(); i++) { 7755 for (intptr_t i = 0; i < exits.length(); i++) {
7657 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); 7756 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
7658 } 7757 }
7659 } 7758 }
7660 7759
7661 7760
7662 } // namespace dart 7761 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698