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