| 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 if ((op_kind == Token::kBIT_AND) && HasTwoMintOrSmi(*comp->ic_data())) { |
| 100 if (HasMintSmi(*comp->ic_data())) { | |
| 101 // We check for Mint receiver and Smi argument, but we try to support any | |
| 102 // combination of Mint and Smi. | |
| 103 if (op_kind != Token::kBIT_AND) { | |
| 104 // TODO(regis): Not yet supported. | |
| 105 return false; | |
| 106 } | |
| 107 | |
| 108 operands_type = BinaryOpComp::kMintOperands; | 136 operands_type = BinaryOpComp::kMintOperands; |
| 109 } | 137 } else if (comp->ic_data()->NumberOfChecks() != 1) { |
| 110 | |
| 111 if (comp->ic_data()->NumberOfChecks() != 1) { | |
| 112 // TODO(srdjan): Not yet supported. | 138 // TODO(srdjan): Not yet supported. |
| 113 return false; | 139 return false; |
| 114 } | 140 } else if (HasTwoSmi(*comp->ic_data())) { |
| 115 | |
| 116 if (HasTwoSmi(*comp->ic_data())) { | |
| 117 if (op_kind == Token::kDIV || | 141 if (op_kind == Token::kDIV || |
| 118 op_kind == Token::kMOD) { | 142 op_kind == Token::kMOD) { |
| 119 // TODO(srdjan): Not yet supported. | 143 // TODO(srdjan): Not yet supported. |
| 120 return false; | 144 return false; |
| 121 } | 145 } |
| 122 | |
| 123 operands_type = BinaryOpComp::kSmiOperands; | 146 operands_type = BinaryOpComp::kSmiOperands; |
| 124 } else if (HasTwoDouble(*comp->ic_data())) { | 147 } else if (HasTwoDouble(*comp->ic_data())) { |
| 125 if (op_kind != Token::kADD && | 148 if (op_kind != Token::kADD && |
| 126 op_kind != Token::kSUB && | 149 op_kind != Token::kSUB && |
| 127 op_kind != Token::kMUL && | 150 op_kind != Token::kMUL && |
| 128 op_kind != Token::kDIV) { | 151 op_kind != Token::kDIV) { |
| 129 // TODO(vegorov): Not yet supported. | 152 // TODO(vegorov): Not yet supported. |
| 130 return false; | 153 return false; |
| 131 } | 154 } |
| 132 | |
| 133 operands_type = BinaryOpComp::kDoubleOperands; | 155 operands_type = BinaryOpComp::kDoubleOperands; |
| 134 } else { | 156 } else { |
| 135 // TODO(srdjan): Not yet supported. | 157 // TODO(srdjan): Not yet supported. |
| 136 return false; | 158 return false; |
| 137 } | 159 } |
| 138 | 160 |
| 139 ASSERT(comp->instr() != NULL); | 161 ASSERT(comp->instr() != NULL); |
| 140 ASSERT(comp->InputCount() == 2); | 162 ASSERT(comp->InputCount() == 2); |
| 141 Value* left = comp->InputAt(0); | 163 Value* left = comp->InputAt(0); |
| 142 Value* right = comp->InputAt(1); | 164 Value* right = comp->InputAt(1); |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 instr->computation()->Accept(this); | 587 instr->computation()->Accept(this); |
| 566 } | 588 } |
| 567 | 589 |
| 568 | 590 |
| 569 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { | 591 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { |
| 570 instr->computation()->Accept(this); | 592 instr->computation()->Accept(this); |
| 571 } | 593 } |
| 572 | 594 |
| 573 | 595 |
| 574 } // namespace dart | 596 } // namespace dart |
| OLD | NEW |