| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/flow_graph_builder.h" | 7 #include "vm/flow_graph_builder.h" |
| 8 #include "vm/il_printer.h" | 8 #include "vm/il_printer.h" |
| 9 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
| 10 | 10 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 32 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 33 Instruction* instr = block_order_[i]->Accept(this); | 33 Instruction* instr = block_order_[i]->Accept(this); |
| 34 // Compile all successors until an exit, branch, or a block entry. | 34 // Compile all successors until an exit, branch, or a block entry. |
| 35 while ((instr != NULL) && !instr->IsBlockEntry()) { | 35 while ((instr != NULL) && !instr->IsBlockEntry()) { |
| 36 instr = instr->Accept(this); | 36 instr = instr->Accept(this); |
| 37 } | 37 } |
| 38 } | 38 } |
| 39 } | 39 } |
| 40 | 40 |
| 41 | 41 |
| 42 static bool ICDataHasReceiverClass(const ICData& ic_data, const Class& cls) { |
| 43 ASSERT(!cls.IsNull()); |
| 44 ASSERT(ic_data.num_args_tested() > 0); |
| 45 Class& test_class = Class::Handle(); |
| 46 Function& target = Function::Handle(); |
| 47 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 48 ic_data.GetOneClassCheckAt(i, &test_class, &target); |
| 49 if (cls.raw() == test_class.raw()) { |
| 50 return true; |
| 51 } |
| 52 } |
| 53 return false; |
| 54 } |
| 55 |
| 56 |
| 42 static bool ICDataHasTwoReceiverClasses(const ICData& ic_data, | 57 static bool ICDataHasTwoReceiverClasses(const ICData& ic_data, |
| 43 const Class& cls1, | 58 const Class& cls1, |
| 44 const Class& cls2) { | 59 const Class& cls2) { |
| 45 ASSERT(!cls1.IsNull() && !cls2.IsNull()); | 60 ASSERT(!cls1.IsNull() && !cls2.IsNull()); |
| 46 if (ic_data.num_args_tested() != 2) { | 61 if (ic_data.num_args_tested() != 2) { |
| 47 return false; | 62 return false; |
| 48 } | 63 } |
| 64 Function& target = Function::Handle(); |
| 49 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 65 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 50 GrowableArray<const Class*> classes; | 66 GrowableArray<const Class*> classes; |
| 51 Function& target = Function::Handle(); | |
| 52 ic_data.GetCheckAt(i, &classes, &target); | 67 ic_data.GetCheckAt(i, &classes, &target); |
| 53 ASSERT(classes.length() == 2); | 68 ASSERT(classes.length() == 2); |
| 54 if (classes[0]->raw() == cls1.raw()) { | 69 if (classes[0]->raw() == cls1.raw()) { |
| 55 if (classes[1]->raw() == cls2.raw()) { | 70 if (classes[1]->raw() == cls2.raw()) { |
| 56 return true; | 71 return true; |
| 57 } | 72 } |
| 58 } | 73 } |
| 59 } | 74 } |
| 60 return false; | 75 return false; |
| 61 } | 76 } |
| 62 | 77 |
| 63 | 78 |
| 79 static bool HasOneSmi(const ICData& ic_data) { |
| 80 const Class& smi_class = |
| 81 Class::Handle(Isolate::Current()->object_store()->smi_class()); |
| 82 return ICDataHasReceiverClass(ic_data, smi_class); |
| 83 } |
| 84 |
| 85 |
| 64 static bool HasTwoSmi(const ICData& ic_data) { | 86 static bool HasTwoSmi(const ICData& ic_data) { |
| 65 const Class& smi_class = | 87 const Class& smi_class = |
| 66 Class::Handle(Isolate::Current()->object_store()->smi_class()); | 88 Class::Handle(Isolate::Current()->object_store()->smi_class()); |
| 67 return ICDataHasTwoReceiverClasses(ic_data, smi_class, smi_class); | 89 return ICDataHasTwoReceiverClasses(ic_data, smi_class, smi_class); |
| 68 } | 90 } |
| 69 | 91 |
| 70 | 92 |
| 93 static bool HasOneDouble(const ICData& ic_data) { |
| 94 const Class& double_class = |
| 95 Class::Handle(Isolate::Current()->object_store()->double_class()); |
| 96 return ICDataHasReceiverClass(ic_data, double_class); |
| 97 } |
| 98 |
| 99 |
| 100 |
| 101 void FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallComp* comp, |
| 102 Token::Kind op_kind) { |
| 103 if (comp->ic_data()->NumberOfChecks() != 1) { |
| 104 // TODO(srdjan): Not yet supported. |
| 105 return; |
| 106 } |
| 107 if (!HasTwoSmi(*comp->ic_data())) { |
| 108 // TODO(srdjan): Not yet supported. |
| 109 return; |
| 110 } |
| 111 ASSERT(comp->instr() != NULL); |
| 112 ASSERT(comp->InputCount() == 2); |
| 113 BinaryOpComp* bin_op = |
| 114 new BinaryOpComp(op_kind, comp, comp->InputAt(0), comp->InputAt(1)); |
| 115 ASSERT(bin_op->ic_data() == NULL); |
| 116 bin_op->set_ic_data(comp->ic_data()); |
| 117 bin_op->set_instr(comp->instr()); |
| 118 comp->instr()->replace_computation(bin_op); |
| 119 } |
| 120 |
| 121 |
| 122 void FlowGraphOptimizer::TryReplaceWithUnaryOp(InstanceCallComp* comp, |
| 123 Token::Kind op_kind) { |
| 124 if (comp->ic_data()->NumberOfChecks() != 1) { |
| 125 // TODO(srdjan): Not yet supported. |
| 126 return; |
| 127 } |
| 128 if (HasOneSmi(*comp->ic_data()) || HasOneDouble(*comp->ic_data())) { |
| 129 ASSERT(comp->instr() != NULL); |
| 130 ASSERT(comp->InputCount() == 1); |
| 131 UnaryOpComp* unary_op = new UnaryOpComp(op_kind, comp, comp->InputAt(0)); |
| 132 ASSERT(unary_op->ic_data() == NULL); |
| 133 unary_op->set_ic_data(comp->ic_data()); |
| 134 unary_op->set_instr(comp->instr()); |
| 135 comp->instr()->replace_computation(unary_op); |
| 136 } |
| 137 } |
| 138 |
| 139 |
| 71 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) { | 140 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) { |
| 72 if ((comp->ic_data() != NULL) && (!comp->ic_data()->IsNull())) { | 141 if ((comp->ic_data() != NULL) && (!comp->ic_data()->IsNull())) { |
| 73 Token::Kind op_kind = Token::GetBinaryOp(comp->function_name()); | 142 Token::Kind op_kind = Token::GetBinaryOp(comp->function_name()); |
| 74 if (op_kind == Token::kILLEGAL) { | 143 if (op_kind != Token::kILLEGAL) { |
| 75 // Not a recognized binary operation. | 144 TryReplaceWithBinaryOp(comp, op_kind); |
| 76 return; | 145 return; |
| 77 } | 146 } |
| 78 if (comp->ic_data()->NumberOfChecks() != 1) { | 147 op_kind = Token::GetUnaryOp(comp->function_name()); |
| 79 // TODO(srdjan): Not yet supported. | 148 if (op_kind != Token::kILLEGAL) { |
| 149 TryReplaceWithUnaryOp(comp, op_kind); |
| 80 return; | 150 return; |
| 81 } | 151 } |
| 82 if (!HasTwoSmi(*comp->ic_data())) { | |
| 83 // TODO(srdjan): Not yet supported. | |
| 84 return; | |
| 85 } | |
| 86 ASSERT(comp->instr() != NULL); | |
| 87 ASSERT(comp->InputCount() == 2); | |
| 88 BinaryOpComp* bin_op = | |
| 89 new BinaryOpComp(op_kind, comp, comp->InputAt(0), comp->InputAt(1)); | |
| 90 ASSERT(bin_op->ic_data() == NULL); | |
| 91 bin_op->set_ic_data(comp->ic_data()); | |
| 92 bin_op->set_instr(comp->instr()); | |
| 93 comp->instr()->replace_computation(bin_op); | |
| 94 } | 152 } |
| 95 } | 153 } |
| 96 | 154 |
| 97 | 155 |
| 98 void FlowGraphOptimizer::VisitDo(DoInstr* instr) { | 156 void FlowGraphOptimizer::VisitDo(DoInstr* instr) { |
| 99 instr->computation()->Accept(this); | 157 instr->computation()->Accept(this); |
| 100 } | 158 } |
| 101 | 159 |
| 102 | 160 |
| 103 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { | 161 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { |
| 104 instr->computation()->Accept(this); | 162 instr->computation()->Accept(this); |
| 105 } | 163 } |
| 106 | 164 |
| 107 | 165 |
| 108 } // namespace dart | 166 } // namespace dart |
| OLD | NEW |