| OLD | NEW |
| 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 6031 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6042 | 6042 |
| 6043 | 6043 |
| 6044 void ConstantPropagator::VisitPolymorphicInstanceCall( | 6044 void ConstantPropagator::VisitPolymorphicInstanceCall( |
| 6045 PolymorphicInstanceCallInstr* instr) { | 6045 PolymorphicInstanceCallInstr* instr) { |
| 6046 SetValue(instr, non_constant_); | 6046 SetValue(instr, non_constant_); |
| 6047 } | 6047 } |
| 6048 | 6048 |
| 6049 | 6049 |
| 6050 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) { | 6050 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) { |
| 6051 SetValue(instr, non_constant_); | 6051 SetValue(instr, non_constant_); |
| 6052 return; | |
| 6053 // TODO(srdjan): Enable code below once issues resolved. | |
| 6054 if (IsNonConstant(instr->constant_value())) { | |
| 6055 // Do not bother with costly analysis if we already know that the | |
| 6056 // instruction is not a constant. | |
| 6057 SetValue(instr, non_constant_); | |
| 6058 return; | |
| 6059 } | |
| 6060 MethodRecognizer::Kind recognized_kind = | |
| 6061 MethodRecognizer::RecognizeKind(instr->function()); | |
| 6062 if (recognized_kind == MethodRecognizer::kStringBaseInterpolate) { | |
| 6063 // static String _interpolate(List values) | |
| 6064 // | |
| 6065 // Code for calling interpolate is generated by the compiler: | |
| 6066 // v2 <- CreateArray(v0) | |
| 6067 // StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value. | |
| 6068 // .. | |
| 6069 // PushArgument(v2) | |
| 6070 // v8 <- StaticCall(_interpolate, v2) | |
| 6071 // Detect that all values are constant, interpolate at compile | |
| 6072 // time. | |
| 6073 ASSERT(instr->ArgumentCount() == 1); | |
| 6074 CreateArrayInstr* create_array = instr->ArgumentAt(0)->AsCreateArray(); | |
| 6075 ASSERT(create_array != NULL); | |
| 6076 // Check if the string interpolation has only constant inputs. | |
| 6077 for (Value::Iterator it(create_array->input_use_list()); | |
| 6078 !it.Done(); | |
| 6079 it.Advance()) { | |
| 6080 Instruction* curr = it.Current()->instruction(); | |
| 6081 StoreIndexedInstr* store = curr->AsStoreIndexed(); | |
| 6082 // 'store' is NULL fir PushArgument instruction: skip it. | |
| 6083 if ((store != NULL) && | |
| 6084 (IsNonConstant(store->value()->definition()->constant_value()))) { | |
| 6085 SetValue(instr, non_constant_); | |
| 6086 return; | |
| 6087 } | |
| 6088 } | |
| 6089 // Interpolate string at compile time. | |
| 6090 const Array& value_arr = | |
| 6091 Array::Handle(Array::New(create_array->num_elements())); | |
| 6092 // Build the array of literal values to interpolate, abort if a value is | |
| 6093 // not literal. | |
| 6094 for (Value::Iterator it(create_array->input_use_list()); | |
| 6095 !it.Done(); | |
| 6096 it.Advance()) { | |
| 6097 Instruction* curr = it.Current()->instruction(); | |
| 6098 StoreIndexedInstr* store = curr->AsStoreIndexed(); | |
| 6099 if (store == NULL) { | |
| 6100 ASSERT(curr == instr->PushArgumentAt(0)); | |
| 6101 } else { | |
| 6102 Value* index_value = store->index(); | |
| 6103 ASSERT(index_value->BindsToConstant() && index_value->IsSmiValue()); | |
| 6104 const intptr_t ix = Smi::Cast(index_value->BoundConstant()).Value(); | |
| 6105 ASSERT(IsConstant(store->value()->definition()->constant_value())); | |
| 6106 value_arr.SetAt(ix, store->value()->definition()->constant_value()); | |
| 6107 } | |
| 6108 } | |
| 6109 // Build argument array to pass to the interpolation function. | |
| 6110 const Array& interpolate_arg = Array::Handle(Array::New(1)); | |
| 6111 interpolate_arg.SetAt(0, value_arr); | |
| 6112 // Call interpolation function. | |
| 6113 String& concatenated = String::ZoneHandle(); | |
| 6114 concatenated ^= | |
| 6115 DartEntry::InvokeFunction(instr->function(), interpolate_arg); | |
| 6116 if (concatenated.IsUnhandledException()) { | |
| 6117 SetValue(instr, non_constant_); | |
| 6118 return; | |
| 6119 } | |
| 6120 | |
| 6121 concatenated = Symbols::New(concatenated); | |
| 6122 SetValue(instr, concatenated); | |
| 6123 } else { | |
| 6124 SetValue(instr, non_constant_); | |
| 6125 } | |
| 6126 } | 6052 } |
| 6127 | 6053 |
| 6128 | 6054 |
| 6129 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) { | 6055 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) { |
| 6130 // Instruction is eliminated when translating to SSA. | 6056 // Instruction is eliminated when translating to SSA. |
| 6131 UNREACHABLE(); | 6057 UNREACHABLE(); |
| 6132 } | 6058 } |
| 6133 | 6059 |
| 6134 | 6060 |
| 6135 void ConstantPropagator::VisitPushTemp(PushTempInstr* instr) { | 6061 void ConstantPropagator::VisitPushTemp(PushTempInstr* instr) { |
| (...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6948 } else { | 6874 } else { |
| 6949 // No new information: Assume both targets are reachable. | 6875 // No new information: Assume both targets are reachable. |
| 6950 SetReachable(branch->true_successor()); | 6876 SetReachable(branch->true_successor()); |
| 6951 SetReachable(branch->false_successor()); | 6877 SetReachable(branch->false_successor()); |
| 6952 } | 6878 } |
| 6953 } | 6879 } |
| 6954 } | 6880 } |
| 6955 } | 6881 } |
| 6956 | 6882 |
| 6957 | 6883 |
| 6958 // Code for calling interpolate is generated by the compiler: | |
| 6959 // v2 <- CreateArray(v0) | |
| 6960 // StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value. | |
| 6961 // .. | |
| 6962 // PushArgument(v2) | |
| 6963 // v8 <- StaticCall(_interpolate, v2) | |
| 6964 // Remove the inputs. | |
| 6965 void ConstantPropagator::RemoveInterpolationInputs( | |
| 6966 const StaticCallInstr& call) { | |
| 6967 ASSERT(call.ArgumentCount() == 1); | |
| 6968 CreateArrayInstr* create_array = call.ArgumentAt(0)->AsCreateArray(); | |
| 6969 ASSERT(create_array != NULL); | |
| 6970 for (Value* use = create_array->input_use_list(); | |
| 6971 use != NULL; | |
| 6972 use = create_array->input_use_list()) { | |
| 6973 use->instruction()->RemoveFromGraph(); | |
| 6974 } | |
| 6975 create_array->RemoveFromGraph(); | |
| 6976 } | |
| 6977 | |
| 6978 | |
| 6979 void ConstantPropagator::Transform() { | 6884 void ConstantPropagator::Transform() { |
| 6980 if (FLAG_trace_constant_propagation) { | 6885 if (FLAG_trace_constant_propagation) { |
| 6981 OS::Print("\n==== Before constant propagation ====\n"); | 6886 OS::Print("\n==== Before constant propagation ====\n"); |
| 6982 FlowGraphPrinter printer(*graph_); | 6887 FlowGraphPrinter printer(*graph_); |
| 6983 printer.PrintBlocks(); | 6888 printer.PrintBlocks(); |
| 6984 } | 6889 } |
| 6985 | 6890 |
| 6986 GrowableArray<PhiInstr*> redundant_phis(10); | 6891 GrowableArray<PhiInstr*> redundant_phis(10); |
| 6987 | 6892 |
| 6988 // We will recompute dominators, block ordering, block ids, block last | 6893 // We will recompute dominators, block ordering, block ids, block last |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7076 !defn->IsStoreStaticField() && | 6981 !defn->IsStoreStaticField() && |
| 7077 !defn->IsStoreVMField()) { | 6982 !defn->IsStoreVMField()) { |
| 7078 if (FLAG_trace_constant_propagation) { | 6983 if (FLAG_trace_constant_propagation) { |
| 7079 OS::Print("Constant v%" Pd " = %s\n", | 6984 OS::Print("Constant v%" Pd " = %s\n", |
| 7080 defn->ssa_temp_index(), | 6985 defn->ssa_temp_index(), |
| 7081 defn->constant_value().ToCString()); | 6986 defn->constant_value().ToCString()); |
| 7082 } | 6987 } |
| 7083 ConstantInstr* constant = graph_->GetConstant(defn->constant_value()); | 6988 ConstantInstr* constant = graph_->GetConstant(defn->constant_value()); |
| 7084 defn->ReplaceUsesWith(constant); | 6989 defn->ReplaceUsesWith(constant); |
| 7085 i.RemoveCurrentFromGraph(); | 6990 i.RemoveCurrentFromGraph(); |
| 7086 if (defn->IsStaticCall()) { | |
| 7087 MethodRecognizer::Kind recognized_kind = | |
| 7088 MethodRecognizer::RecognizeKind(defn->AsStaticCall()->function()); | |
| 7089 if (recognized_kind == MethodRecognizer::kStringBaseInterpolate) { | |
| 7090 RemoveInterpolationInputs(*defn->AsStaticCall()); | |
| 7091 } | |
| 7092 } | |
| 7093 } | 6991 } |
| 7094 } | 6992 } |
| 7095 | 6993 |
| 7096 // Replace branches where one target is unreachable with jumps. | 6994 // Replace branches where one target is unreachable with jumps. |
| 7097 BranchInstr* branch = block->last_instruction()->AsBranch(); | 6995 BranchInstr* branch = block->last_instruction()->AsBranch(); |
| 7098 if (branch != NULL) { | 6996 if (branch != NULL) { |
| 7099 TargetEntryInstr* if_true = branch->true_successor(); | 6997 TargetEntryInstr* if_true = branch->true_successor(); |
| 7100 TargetEntryInstr* if_false = branch->false_successor(); | 6998 TargetEntryInstr* if_false = branch->false_successor(); |
| 7101 JoinEntryInstr* join = NULL; | 6999 JoinEntryInstr* join = NULL; |
| 7102 Instruction* next = NULL; | 7000 Instruction* next = NULL; |
| (...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7768 } | 7666 } |
| 7769 | 7667 |
| 7770 // Insert materializations at environment uses. | 7668 // Insert materializations at environment uses. |
| 7771 for (intptr_t i = 0; i < exits.length(); i++) { | 7669 for (intptr_t i = 0; i < exits.length(); i++) { |
| 7772 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 7670 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 7773 } | 7671 } |
| 7774 } | 7672 } |
| 7775 | 7673 |
| 7776 | 7674 |
| 7777 } // namespace dart | 7675 } // namespace dart |
| OLD | NEW |