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