| 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 6017 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |