| 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/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 } | 63 } |
| 64 } | 64 } |
| 65 } else if (instr->IsPolymorphicInstanceCall()) { | 65 } else if (instr->IsPolymorphicInstanceCall()) { |
| 66 SpecializePolymorphicInstanceCall(instr->AsPolymorphicInstanceCall()); | 66 SpecializePolymorphicInstanceCall(instr->AsPolymorphicInstanceCall()); |
| 67 } else if (instr->IsStrictCompare()) { | 67 } else if (instr->IsStrictCompare()) { |
| 68 VisitStrictCompare(instr->AsStrictCompare()); | 68 VisitStrictCompare(instr->AsStrictCompare()); |
| 69 } else if (instr->IsBranch()) { | 69 } else if (instr->IsBranch()) { |
| 70 ComparisonInstr* compare = instr->AsBranch()->comparison(); | 70 ComparisonInstr* compare = instr->AsBranch()->comparison(); |
| 71 if (compare->IsStrictCompare()) { | 71 if (compare->IsStrictCompare()) { |
| 72 VisitStrictCompare(compare->AsStrictCompare()); | 72 VisitStrictCompare(compare->AsStrictCompare()); |
| 73 } else if (compare->IsEqualityCompare()) { |
| 74 StrictifyEqualityCompare(compare->AsEqualityCompare(), |
| 75 instr->AsBranch()); |
| 73 } | 76 } |
| 74 } | 77 } |
| 75 } | 78 } |
| 76 current_iterator_ = NULL; | 79 current_iterator_ = NULL; |
| 77 } | 80 } |
| 78 } | 81 } |
| 79 | 82 |
| 80 | 83 |
| 81 // Attempt to build ICData for call using propagated class-ids. | 84 // Attempt to build ICData for call using propagated class-ids. |
| 82 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { | 85 bool FlowGraphOptimizer::TryCreateICData(InstanceCallInstr* call) { |
| (...skipping 2094 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2177 comp->set_operands_class_id(kMintCid); | 2180 comp->set_operands_class_id(kMintCid); |
| 2178 } | 2181 } |
| 2179 } | 2182 } |
| 2180 | 2183 |
| 2181 | 2184 |
| 2182 void FlowGraphOptimizer::VisitRelationalOp(RelationalOpInstr* instr) { | 2185 void FlowGraphOptimizer::VisitRelationalOp(RelationalOpInstr* instr) { |
| 2183 HandleRelationalOp(instr); | 2186 HandleRelationalOp(instr); |
| 2184 } | 2187 } |
| 2185 | 2188 |
| 2186 | 2189 |
| 2190 bool FlowGraphOptimizer::CanStrictifyEqualityCompare( |
| 2191 EqualityCompareInstr* compare) { |
| 2192 // If one of the inputs is null this is a strict comparison. |
| 2193 if (compare->left()->BindsToConstantNull() || |
| 2194 compare->right()->BindsToConstantNull()) { |
| 2195 return true; |
| 2196 } |
| 2197 |
| 2198 if (compare->left()->Type()->IsNone()) { |
| 2199 return false; // We might be running prior to any type propagation passes. |
| 2200 } |
| 2201 |
| 2202 // Try resolving target function using propagated cid for the receiver. |
| 2203 // If receiver is either null or has default equality operator then |
| 2204 // we can convert such comparison to a strict one. |
| 2205 const intptr_t receiver_cid = |
| 2206 compare->left()->Type()->ToNullableCid(); |
| 2207 |
| 2208 if (receiver_cid == kDynamicCid) { |
| 2209 return false; |
| 2210 } |
| 2211 |
| 2212 const Class& receiver_class = Class::Handle( |
| 2213 Isolate::Current()->class_table()->At(receiver_cid)); |
| 2214 |
| 2215 // Resolve equality operator. |
| 2216 const Function& function = Function::Handle( |
| 2217 Resolver::ResolveDynamicForReceiverClass( |
| 2218 receiver_class, |
| 2219 Symbols::EqualOperator(), |
| 2220 2, |
| 2221 0)); |
| 2222 |
| 2223 if (function.IsNull()) { |
| 2224 return false; |
| 2225 } |
| 2226 |
| 2227 // Default equality operator declared on the Object class just calls |
| 2228 // identical. |
| 2229 return (Class::Handle(function.Owner()).id() == kInstanceCid); |
| 2230 } |
| 2231 |
| 2232 |
| 2233 template <typename T> |
| 2234 bool FlowGraphOptimizer::StrictifyEqualityCompare( |
| 2235 EqualityCompareInstr* compare, |
| 2236 T current_instruction) const { |
| 2237 if (CanStrictifyEqualityCompare(compare)) { |
| 2238 Token::Kind strict_kind = (compare->kind() == Token::kEQ) ? |
| 2239 Token::kEQ_STRICT : Token::kNE_STRICT; |
| 2240 StrictCompareInstr* strict_comp = |
| 2241 new StrictCompareInstr(strict_kind, |
| 2242 compare->left()->CopyWithType(), |
| 2243 compare->right()->CopyWithType()); |
| 2244 current_instruction->ReplaceWith(strict_comp, current_iterator()); |
| 2245 return true; |
| 2246 } |
| 2247 return false; |
| 2248 } |
| 2249 |
| 2250 |
| 2187 template <typename T> | 2251 template <typename T> |
| 2188 void FlowGraphOptimizer::HandleEqualityCompare(EqualityCompareInstr* comp, | 2252 void FlowGraphOptimizer::HandleEqualityCompare(EqualityCompareInstr* comp, |
| 2189 T current_instruction) { | 2253 T current_instruction) { |
| 2190 // If one of the inputs is null, no ICdata will be collected. | 2254 if (StrictifyEqualityCompare(comp, current_instruction)) { |
| 2191 if (comp->left()->BindsToConstantNull() || | |
| 2192 comp->right()->BindsToConstantNull()) { | |
| 2193 Token::Kind strict_kind = (comp->kind() == Token::kEQ) ? | |
| 2194 Token::kEQ_STRICT : Token::kNE_STRICT; | |
| 2195 StrictCompareInstr* strict_comp = | |
| 2196 new StrictCompareInstr(strict_kind, | |
| 2197 comp->left()->Copy(), | |
| 2198 comp->right()->Copy()); | |
| 2199 current_instruction->ReplaceWith(strict_comp, current_iterator()); | |
| 2200 return; | 2255 return; |
| 2201 } | 2256 } |
| 2257 |
| 2202 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) { | 2258 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) { |
| 2203 return; | 2259 return; |
| 2204 } | 2260 } |
| 2261 |
| 2205 ASSERT(comp->ic_data()->num_args_tested() == 2); | 2262 ASSERT(comp->ic_data()->num_args_tested() == 2); |
| 2206 if (comp->ic_data()->NumberOfChecks() == 1) { | 2263 if (comp->ic_data()->NumberOfChecks() == 1) { |
| 2207 GrowableArray<intptr_t> class_ids; | 2264 GrowableArray<intptr_t> class_ids; |
| 2208 Function& target = Function::Handle(); | 2265 Function& target = Function::Handle(); |
| 2209 comp->ic_data()->GetCheckAt(0, &class_ids, &target); | 2266 comp->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 2210 // TODO(srdjan): allow for mixed mode int/double comparison. | 2267 // TODO(srdjan): allow for mixed mode int/double comparison. |
| 2211 | 2268 |
| 2212 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { | 2269 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { |
| 2213 InsertBefore(current_instruction, | 2270 InsertBefore(current_instruction, |
| 2214 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), | 2271 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2260 AddCheckClass(comp->right()->definition(), | 2317 AddCheckClass(comp->right()->definition(), |
| 2261 unary_checks_1, | 2318 unary_checks_1, |
| 2262 comp->deopt_id(), | 2319 comp->deopt_id(), |
| 2263 current_instruction->env(), | 2320 current_instruction->env(), |
| 2264 current_instruction); | 2321 current_instruction); |
| 2265 comp->set_receiver_class_id(kSmiCid); | 2322 comp->set_receiver_class_id(kSmiCid); |
| 2266 } | 2323 } |
| 2267 } | 2324 } |
| 2268 | 2325 |
| 2269 | 2326 |
| 2327 |
| 2328 |
| 2270 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { | 2329 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { |
| 2271 HandleEqualityCompare(instr, instr); | 2330 HandleEqualityCompare(instr, instr); |
| 2272 } | 2331 } |
| 2273 | 2332 |
| 2274 | 2333 |
| 2275 void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) { | 2334 void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) { |
| 2276 ComparisonInstr* comparison = instr->comparison(); | 2335 ComparisonInstr* comparison = instr->comparison(); |
| 2277 if (comparison->IsRelationalOp()) { | 2336 if (comparison->IsRelationalOp()) { |
| 2278 HandleRelationalOp(comparison->AsRelationalOp()); | 2337 HandleRelationalOp(comparison->AsRelationalOp()); |
| 2279 } else if (comparison->IsEqualityCompare()) { | 2338 } else if (comparison->IsEqualityCompare()) { |
| (...skipping 2780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5060 if (changed) { | 5119 if (changed) { |
| 5061 // We may have changed the block order and the dominator tree. | 5120 // We may have changed the block order and the dominator tree. |
| 5062 flow_graph->DiscoverBlocks(); | 5121 flow_graph->DiscoverBlocks(); |
| 5063 GrowableArray<BitVector*> dominance_frontier; | 5122 GrowableArray<BitVector*> dominance_frontier; |
| 5064 flow_graph->ComputeDominators(&dominance_frontier); | 5123 flow_graph->ComputeDominators(&dominance_frontier); |
| 5065 } | 5124 } |
| 5066 } | 5125 } |
| 5067 | 5126 |
| 5068 | 5127 |
| 5069 } // namespace dart | 5128 } // namespace dart |
| OLD | NEW |