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

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
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 6009 matching lines...) Expand 10 before | Expand all | Expand 10 after
6020 } 6020 }
6021 6021
6022 6022
6023 void ConstantPropagator::VisitPolymorphicInstanceCall( 6023 void ConstantPropagator::VisitPolymorphicInstanceCall(
6024 PolymorphicInstanceCallInstr* instr) { 6024 PolymorphicInstanceCallInstr* instr) {
6025 SetValue(instr, non_constant_); 6025 SetValue(instr, non_constant_);
6026 } 6026 }
6027 6027
6028 6028
6029 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) { 6029 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) {
6030 SetValue(instr, non_constant_); 6030 MethodRecognizer::Kind recognized_kind =
6031 MethodRecognizer::RecognizeKind(instr->function());
6032 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.
6033 // static String _interpolate(List values)
6034 //
6035 // Code for calling interpolate is generated by the compiler:
6036 // v2 <- CreateArray(v0)
6037 // StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value.
6038 // ..
6039 // PushArgument(v2)
6040 // v8 <- StaticCall(_interpolate, v2)
6041 // Detect that all values are constant, interpolate at compile
6042 // time.
6043 ASSERT(instr->ArgumentCount() == 1);
6044 CreateArrayInstr* create_array = instr->ArgumentAt(0)->AsCreateArray();
6045 ASSERT(create_array != NULL);
6046 // Check if the string interpolation has only constant inputs.
6047 for (Value::Iterator it(create_array->input_use_list());
6048 !it.Done();
6049 it.Advance()) {
6050 Instruction* curr = it.Current()->instruction();
6051 StoreIndexedInstr* store = curr->AsStoreIndexed();
6052 if ((store != NULL) &&
6053 (!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.
6054 SetValue(instr, non_constant_);
6055 return;
6056 }
6057 }
6058 // Interpolate string at compile time.
6059 const Array& value_arr =
6060 Array::Handle(Array::New(create_array->num_elements()));
6061 // GrowableArray<StoreIndexedInstr*> store_instructions;
6062 // Build the array of literal values to interpolate, abort if a value is
6063 // not literal.
6064 for (Value::Iterator it(create_array->input_use_list());
6065 !it.Done();
6066 it.Advance()) {
6067 Instruction* curr = it.Current()->instruction();
6068 StoreIndexedInstr* store = curr->AsStoreIndexed();
6069 if (store == NULL) {
6070 ASSERT(curr == instr->PushArgumentAt(0));
6071 } else {
6072 // store_instructions.Add(store);
6073 Value* index_value = store->index();
6074 ASSERT(index_value->BindsToConstant() && index_value->IsSmiValue());
6075 const intptr_t ix = Smi::Cast(index_value->BoundConstant()).Value();
6076 ASSERT(IsConstant(store->value()->definition()->constant_value()));
6077 value_arr.SetAt(ix, store->value()->definition()->constant_value());
6078 }
6079 }
6080 // Build argument array to pass to the interpolation function.
6081 const Array& interpolate_arg = Array::Handle(Array::New(1));
6082 interpolate_arg.SetAt(0, value_arr);
6083 // Call interpolation function.
6084 String& concatenated = String::ZoneHandle();
6085 concatenated ^=
6086 DartEntry::InvokeFunction(instr->function(), interpolate_arg);
6087 if (concatenated.IsUnhandledException()) {
6088 SetValue(instr, non_constant_);
6089 return;
6090 }
6091
6092 concatenated = Symbols::New(concatenated);
6093 SetValue(instr, concatenated);
6094 } else {
6095 SetValue(instr, non_constant_);
6096 }
6031 } 6097 }
6032 6098
6033 6099
6034 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) { 6100 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) {
6035 // Instruction is eliminated when translating to SSA. 6101 // Instruction is eliminated when translating to SSA.
6036 UNREACHABLE(); 6102 UNREACHABLE();
6037 } 6103 }
6038 6104
6039 6105
6040 void ConstantPropagator::VisitPushTemp(PushTempInstr* instr) { 6106 void ConstantPropagator::VisitPushTemp(PushTempInstr* instr) {
(...skipping 802 matching lines...) Expand 10 before | Expand all | Expand 10 after
6843 } else { 6909 } else {
6844 // No new information: Assume both targets are reachable. 6910 // No new information: Assume both targets are reachable.
6845 SetReachable(branch->true_successor()); 6911 SetReachable(branch->true_successor());
6846 SetReachable(branch->false_successor()); 6912 SetReachable(branch->false_successor());
6847 } 6913 }
6848 } 6914 }
6849 } 6915 }
6850 } 6916 }
6851 6917
6852 6918
6919 // Code for calling interpolate is generated by the compiler:
6920 // v2 <- CreateArray(v0)
6921 // StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value.
6922 // ..
6923 // PushArgument(v2)
6924 // v8 <- StaticCall(_interpolate, v2)
6925 // Remove the inputs.
6926 void ConstantPropagator::RemoveInterpolationInputs(
6927 const StaticCallInstr& call) {
6928 ASSERT(call.ArgumentCount() == 1);
6929 CreateArrayInstr* create_array = call.ArgumentAt(0)->AsCreateArray();
6930 ASSERT(create_array != NULL);
6931 for (Value* use = create_array->input_use_list();
6932 use != NULL;
6933 use = create_array->input_use_list()) {
6934 use->instruction()->RemoveFromGraph();
6935 }
6936 create_array->RemoveFromGraph();
6937 }
6938
6939
6853 void ConstantPropagator::Transform() { 6940 void ConstantPropagator::Transform() {
6854 if (FLAG_trace_constant_propagation) { 6941 if (FLAG_trace_constant_propagation) {
6855 OS::Print("\n==== Before constant propagation ====\n"); 6942 OS::Print("\n==== Before constant propagation ====\n");
6856 FlowGraphPrinter printer(*graph_); 6943 FlowGraphPrinter printer(*graph_);
6857 printer.PrintBlocks(); 6944 printer.PrintBlocks();
6858 } 6945 }
6859 6946
6860 GrowableArray<PhiInstr*> redundant_phis(10); 6947 GrowableArray<PhiInstr*> redundant_phis(10);
6861 6948
6862 // We will recompute dominators, block ordering, block ids, block last 6949 // We will recompute dominators, block ordering, block ids, block last
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
6950 !defn->IsStoreStaticField() && 7037 !defn->IsStoreStaticField() &&
6951 !defn->IsStoreVMField()) { 7038 !defn->IsStoreVMField()) {
6952 if (FLAG_trace_constant_propagation) { 7039 if (FLAG_trace_constant_propagation) {
6953 OS::Print("Constant v%" Pd " = %s\n", 7040 OS::Print("Constant v%" Pd " = %s\n",
6954 defn->ssa_temp_index(), 7041 defn->ssa_temp_index(),
6955 defn->constant_value().ToCString()); 7042 defn->constant_value().ToCString());
6956 } 7043 }
6957 ConstantInstr* constant = graph_->GetConstant(defn->constant_value()); 7044 ConstantInstr* constant = graph_->GetConstant(defn->constant_value());
6958 defn->ReplaceUsesWith(constant); 7045 defn->ReplaceUsesWith(constant);
6959 i.RemoveCurrentFromGraph(); 7046 i.RemoveCurrentFromGraph();
7047 if (defn->IsStaticCall()) {
7048 MethodRecognizer::Kind recognized_kind =
7049 MethodRecognizer::RecognizeKind(defn->AsStaticCall()->function());
7050 if (recognized_kind == MethodRecognizer::kStringBaseInterpolate) {
7051 RemoveInterpolationInputs(*defn->AsStaticCall());
7052 }
7053 }
6960 } 7054 }
6961 } 7055 }
6962 7056
6963 // Replace branches where one target is unreachable with jumps. 7057 // Replace branches where one target is unreachable with jumps.
6964 BranchInstr* branch = block->last_instruction()->AsBranch(); 7058 BranchInstr* branch = block->last_instruction()->AsBranch();
6965 if (branch != NULL) { 7059 if (branch != NULL) {
6966 TargetEntryInstr* if_true = branch->true_successor(); 7060 TargetEntryInstr* if_true = branch->true_successor();
6967 TargetEntryInstr* if_false = branch->false_successor(); 7061 TargetEntryInstr* if_false = branch->false_successor();
6968 JoinEntryInstr* join = NULL; 7062 JoinEntryInstr* join = NULL;
6969 Instruction* next = NULL; 7063 Instruction* next = NULL;
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
7635 } 7729 }
7636 7730
7637 // Insert materializations at environment uses. 7731 // Insert materializations at environment uses.
7638 for (intptr_t i = 0; i < exits.length(); i++) { 7732 for (intptr_t i = 0; i < exits.length(); i++) {
7639 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); 7733 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
7640 } 7734 }
7641 } 7735 }
7642 7736
7643 7737
7644 } // namespace dart 7738 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698