Chromium Code Reviews| 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 29 matching lines...) Expand all Loading... | |
| 40 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 40 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 41 const intptr_t test_class_id = ic_data.GetReceiverClassIdAt(i); | 41 const intptr_t test_class_id = ic_data.GetReceiverClassIdAt(i); |
| 42 if (test_class_id == class_id) { | 42 if (test_class_id == class_id) { |
| 43 return true; | 43 return true; |
| 44 } | 44 } |
| 45 } | 45 } |
| 46 return false; | 46 return false; |
| 47 } | 47 } |
| 48 | 48 |
| 49 | 49 |
| 50 static bool ICDataHasReceiverArgumentClasses(const ICData& ic_data, | 50 static bool ICDataHasReceiverArgumentClassIds(const ICData& ic_data, |
| 51 intptr_t receiver_class_id, | 51 intptr_t receiver_class_id, |
| 52 intptr_t argument_class_id) { | 52 intptr_t argument_class_id) { |
| 53 ASSERT(receiver_class_id != kIllegalObjectKind); | 53 ASSERT(receiver_class_id != kIllegalObjectKind); |
| 54 ASSERT(argument_class_id != kIllegalObjectKind); | 54 ASSERT(argument_class_id != kIllegalObjectKind); |
| 55 if (ic_data.num_args_tested() != 2) return false; | 55 if (ic_data.num_args_tested() != 2) return false; |
| 56 | 56 |
| 57 Function& target = Function::Handle(); | 57 Function& target = Function::Handle(); |
| 58 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 58 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 59 GrowableArray<intptr_t> class_ids; | 59 GrowableArray<intptr_t> class_ids; |
| 60 ic_data.GetCheckAt(i, &class_ids, &target); | 60 ic_data.GetCheckAt(i, &class_ids, &target); |
| 61 ASSERT(class_ids.length() == 2); | 61 ASSERT(class_ids.length() == 2); |
| 62 if ((class_ids[0] == receiver_class_id) && | 62 if ((class_ids[0] == receiver_class_id) && |
| 63 (class_ids[1] == argument_class_id)) { | 63 (class_ids[1] == argument_class_id)) { |
| 64 return true; | 64 return true; |
| 65 } | 65 } |
| 66 } | 66 } |
| 67 return false; | 67 return false; |
| 68 } | 68 } |
| 69 | 69 |
| 70 | 70 |
| 71 static bool ClassIdIsOneOf(intptr_t class_id, | |
| 72 GrowableArray<intptr_t>* class_ids) { | |
| 73 for (intptr_t i = 0; i < class_ids->length(); i++) { | |
| 74 if ((*class_ids)[i] == class_id) { | |
| 75 return true; | |
| 76 } | |
| 77 } | |
| 78 return false; | |
| 79 } | |
| 80 | |
| 81 | |
| 82 static bool ICDataHasOnlyReceiverArgumentClassIds( | |
| 83 const ICData& ic_data, | |
| 84 GrowableArray<intptr_t>* receiver_class_ids, | |
| 85 GrowableArray<intptr_t>* argument_class_ids) { | |
| 86 if (ic_data.num_args_tested() != 2) return false; | |
| 87 | |
| 88 Function& target = Function::Handle(); | |
| 89 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | |
| 90 GrowableArray<intptr_t> class_ids; | |
| 91 ic_data.GetCheckAt(i, &class_ids, &target); | |
| 92 ASSERT(class_ids.length() == 2); | |
| 93 if (!ClassIdIsOneOf(class_ids[0], receiver_class_ids) || | |
| 94 !ClassIdIsOneOf(class_ids[1], argument_class_ids)) { | |
| 95 return false; | |
| 96 } | |
| 97 } | |
| 98 return true; | |
| 99 } | |
| 100 | |
| 101 | |
| 71 static bool HasOneSmi(const ICData& ic_data) { | 102 static bool HasOneSmi(const ICData& ic_data) { |
| 72 return ICDataHasReceiverClassId(ic_data, kSmi); | 103 return ICDataHasReceiverClassId(ic_data, kSmi); |
| 73 } | 104 } |
| 74 | 105 |
| 75 | 106 |
| 76 static bool HasTwoSmi(const ICData& ic_data) { | 107 static bool HasTwoSmi(const ICData& ic_data) { |
| 77 return ICDataHasReceiverArgumentClasses(ic_data, kSmi, kSmi); | 108 return ICDataHasReceiverArgumentClassIds(ic_data, kSmi, kSmi); |
| 78 } | 109 } |
| 79 | 110 |
| 80 | 111 |
| 81 static bool HasMintSmi(const ICData& ic_data) { | 112 // Returns false if the ICData contains anything other than the 4 combinations |
| 82 return ICDataHasReceiverArgumentClasses(ic_data, kMint, kSmi); | 113 // of Mint and Smi for the receiver and argument classes. |
| 114 static bool HasTwoMintOrSmi(const ICData& ic_data) { | |
| 115 GrowableArray<intptr_t> class_ids; | |
| 116 class_ids.Add(kSmi); | |
| 117 class_ids.Add(kMint); | |
| 118 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, &class_ids, &class_ids); | |
| 83 } | 119 } |
| 84 | 120 |
| 85 | 121 |
| 86 static bool HasOneDouble(const ICData& ic_data) { | 122 static bool HasOneDouble(const ICData& ic_data) { |
| 87 return ICDataHasReceiverClassId(ic_data, kDouble); | 123 return ICDataHasReceiverClassId(ic_data, kDouble); |
| 88 } | 124 } |
| 89 | 125 |
| 90 | 126 |
| 91 static bool HasTwoDouble(const ICData& ic_data) { | 127 static bool HasTwoDouble(const ICData& ic_data) { |
| 92 return ICDataHasReceiverArgumentClasses(ic_data, kDouble, kDouble); | 128 return ICDataHasReceiverArgumentClassIds(ic_data, kDouble, kDouble); |
| 93 } | 129 } |
| 94 | 130 |
| 95 | 131 |
| 96 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallComp* comp, | 132 bool FlowGraphOptimizer::TryReplaceWithBinaryOp(InstanceCallComp* comp, |
| 97 Token::Kind op_kind) { | 133 Token::Kind op_kind) { |
| 98 BinaryOpComp::OperandsType operands_type; | 134 BinaryOpComp::OperandsType operands_type; |
| 99 | 135 |
| 100 if (HasMintSmi(*comp->ic_data())) { | 136 const intptr_t num_checks = comp->ic_data()->NumberOfChecks(); |
| 101 // We check for Mint receiver and Smi argument, but we try to support any | 137 if (num_checks == 1) { |
|
srdjan
2012/06/21 16:02:37
What if it has only Mint and Smi (1 check). Wouldn
regis
2012/06/21 18:26:42
True. I did not want to skip other Smi optimizatio
| |
| 102 // combination of Mint and Smi. | 138 if (HasTwoSmi(*comp->ic_data())) { |
| 103 if (op_kind != Token::kBIT_AND) { | 139 if (op_kind == Token::kDIV || |
| 104 // TODO(regis): Not yet supported. | 140 op_kind == Token::kMOD) { |
| 105 return false; | 141 // TODO(srdjan): Not yet supported. |
| 106 } | 142 return false; |
| 107 | 143 } |
| 108 operands_type = BinaryOpComp::kMintOperands; | 144 operands_type = BinaryOpComp::kSmiOperands; |
| 109 } | 145 } else if (HasTwoDouble(*comp->ic_data())) { |
| 110 | 146 if (op_kind != Token::kADD && |
| 111 if (comp->ic_data()->NumberOfChecks() != 1) { | 147 op_kind != Token::kSUB && |
| 112 // TODO(srdjan): Not yet supported. | 148 op_kind != Token::kMUL && |
| 113 return false; | 149 op_kind != Token::kDIV) { |
| 114 } | 150 // TODO(vegorov): Not yet supported. |
| 115 | 151 return false; |
| 116 if (HasTwoSmi(*comp->ic_data())) { | 152 } |
| 117 if (op_kind == Token::kDIV || | 153 operands_type = BinaryOpComp::kDoubleOperands; |
| 118 op_kind == Token::kMOD) { | 154 } else { |
| 119 // TODO(srdjan): Not yet supported. | 155 // TODO(srdjan): Not yet supported. |
| 120 return false; | 156 return false; |
| 121 } | 157 } |
| 122 | 158 } else if (num_checks < 4) { |
|
srdjan
2012/06/21 16:02:37
I would remove the num_checks test. If it has Mint
regis
2012/06/21 18:26:42
Done.
| |
| 123 operands_type = BinaryOpComp::kSmiOperands; | 159 if (HasTwoMintOrSmi(*comp->ic_data())) { |
| 124 } else if (HasTwoDouble(*comp->ic_data())) { | 160 // We check for Mint or Smi receiver and Mint or Smi argument. |
| 125 if (op_kind != Token::kADD && | 161 if (op_kind != Token::kBIT_AND) { |
| 126 op_kind != Token::kSUB && | 162 // TODO(regis): Not yet supported. |
| 127 op_kind != Token::kMUL && | 163 return false; |
| 128 op_kind != Token::kDIV) { | 164 } |
| 129 // TODO(vegorov): Not yet supported. | 165 operands_type = BinaryOpComp::kMintOperands; |
| 166 } else { | |
| 167 // TODO(srdjan): Not yet supported. | |
| 130 return false; | 168 return false; |
| 131 } | 169 } |
| 132 | |
| 133 operands_type = BinaryOpComp::kDoubleOperands; | |
| 134 } else { | 170 } else { |
| 135 // TODO(srdjan): Not yet supported. | 171 // TODO(srdjan): Not yet supported. |
| 136 return false; | 172 return false; |
| 137 } | 173 } |
| 138 | 174 |
| 139 ASSERT(comp->instr() != NULL); | 175 ASSERT(comp->instr() != NULL); |
| 140 ASSERT(comp->InputCount() == 2); | 176 ASSERT(comp->InputCount() == 2); |
| 141 Value* left = comp->InputAt(0); | 177 Value* left = comp->InputAt(0); |
| 142 Value* right = comp->InputAt(1); | 178 Value* right = comp->InputAt(1); |
| 143 BinaryOpComp* bin_op = | 179 BinaryOpComp* bin_op = |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 558 instr->computation()->Accept(this); | 594 instr->computation()->Accept(this); |
| 559 } | 595 } |
| 560 | 596 |
| 561 | 597 |
| 562 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { | 598 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { |
| 563 instr->computation()->Accept(this); | 599 instr->computation()->Accept(this); |
| 564 } | 600 } |
| 565 | 601 |
| 566 | 602 |
| 567 } // namespace dart | 603 } // namespace dart |
| OLD | NEW |