Chromium Code Reviews| 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( | |
|
srdjan
2013/04/18 16:54:49
Can this be a const function?
Vyacheslav Egorov (Google)
2013/04/18 19:48:36
Made it static.
| |
| 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 const Function& function = Function::Handle( | |
| 2215 Resolver::ResolveDynamicForReceiverClass( | |
| 2216 receiver_class, | |
| 2217 Symbols::EqualOperator(), | |
| 2218 2, | |
| 2219 0)); | |
|
srdjan
2013/04/18 16:54:49
Don't you need to look up the super chain if any (
srdjan
2013/04/18 17:28:59
Correction: ResolveDynamicForReceiverClass goes up
Vyacheslav Egorov (Google)
2013/04/18 19:48:36
Object has kInstanceCid cid that is how it works.
| |
| 2220 | |
| 2221 if (function.IsNull()) { | |
| 2222 return false; | |
| 2223 } | |
| 2224 | |
| 2225 return (Class::Handle(function.Owner()).id() == kInstanceCid); | |
| 2226 } | |
| 2227 | |
| 2228 | |
| 2229 template <typename T> | |
| 2230 bool FlowGraphOptimizer::StrictifyEqualityCompare(EqualityCompareInstr* compare, | |
| 2231 T current_instruction) { | |
|
srdjan
2013/04/18 16:54:49
Can this be a const function?
srdjan
2013/04/18 16:54:49
I assume that it is templated bcause current_instr
Vyacheslav Egorov (Google)
2013/04/18 19:48:36
Made it const.
Vyacheslav Egorov (Google)
2013/04/18 19:48:36
Yes, for the same reason the HandleEqualityCompare
| |
| 2232 if (CanStrictifyEqualityCompare(compare)) { | |
| 2233 Token::Kind strict_kind = (compare->kind() == Token::kEQ) ? | |
| 2234 Token::kEQ_STRICT : Token::kNE_STRICT; | |
| 2235 StrictCompareInstr* strict_comp = | |
| 2236 new StrictCompareInstr(strict_kind, | |
| 2237 compare->left()->CopyWithType(), | |
| 2238 compare->right()->CopyWithType()); | |
| 2239 current_instruction->ReplaceWith(strict_comp, current_iterator()); | |
| 2240 return true; | |
| 2241 } | |
| 2242 return false; | |
| 2243 } | |
| 2244 | |
| 2245 | |
| 2187 template <typename T> | 2246 template <typename T> |
| 2188 void FlowGraphOptimizer::HandleEqualityCompare(EqualityCompareInstr* comp, | 2247 void FlowGraphOptimizer::HandleEqualityCompare(EqualityCompareInstr* comp, |
| 2189 T current_instruction) { | 2248 T current_instruction) { |
| 2190 // If one of the inputs is null, no ICdata will be collected. | 2249 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; | 2250 return; |
| 2201 } | 2251 } |
| 2252 | |
| 2202 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) { | 2253 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) { |
| 2203 return; | 2254 return; |
| 2204 } | 2255 } |
| 2256 | |
| 2205 ASSERT(comp->ic_data()->num_args_tested() == 2); | 2257 ASSERT(comp->ic_data()->num_args_tested() == 2); |
| 2206 if (comp->ic_data()->NumberOfChecks() == 1) { | 2258 if (comp->ic_data()->NumberOfChecks() == 1) { |
| 2207 GrowableArray<intptr_t> class_ids; | 2259 GrowableArray<intptr_t> class_ids; |
| 2208 Function& target = Function::Handle(); | 2260 Function& target = Function::Handle(); |
| 2209 comp->ic_data()->GetCheckAt(0, &class_ids, &target); | 2261 comp->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 2210 // TODO(srdjan): allow for mixed mode int/double comparison. | 2262 // TODO(srdjan): allow for mixed mode int/double comparison. |
| 2211 | 2263 |
| 2212 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { | 2264 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { |
| 2213 InsertBefore(current_instruction, | 2265 InsertBefore(current_instruction, |
| 2214 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), | 2266 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(), | 2312 AddCheckClass(comp->right()->definition(), |
| 2261 unary_checks_1, | 2313 unary_checks_1, |
| 2262 comp->deopt_id(), | 2314 comp->deopt_id(), |
| 2263 current_instruction->env(), | 2315 current_instruction->env(), |
| 2264 current_instruction); | 2316 current_instruction); |
| 2265 comp->set_receiver_class_id(kSmiCid); | 2317 comp->set_receiver_class_id(kSmiCid); |
| 2266 } | 2318 } |
| 2267 } | 2319 } |
| 2268 | 2320 |
| 2269 | 2321 |
| 2322 | |
| 2323 | |
| 2270 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { | 2324 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { |
| 2271 HandleEqualityCompare(instr, instr); | 2325 HandleEqualityCompare(instr, instr); |
| 2272 } | 2326 } |
| 2273 | 2327 |
| 2274 | 2328 |
| 2275 void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) { | 2329 void FlowGraphOptimizer::VisitBranch(BranchInstr* instr) { |
| 2276 ComparisonInstr* comparison = instr->comparison(); | 2330 ComparisonInstr* comparison = instr->comparison(); |
| 2277 if (comparison->IsRelationalOp()) { | 2331 if (comparison->IsRelationalOp()) { |
| 2278 HandleRelationalOp(comparison->AsRelationalOp()); | 2332 HandleRelationalOp(comparison->AsRelationalOp()); |
| 2279 } else if (comparison->IsEqualityCompare()) { | 2333 } else if (comparison->IsEqualityCompare()) { |
| (...skipping 2780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5060 if (changed) { | 5114 if (changed) { |
| 5061 // We may have changed the block order and the dominator tree. | 5115 // We may have changed the block order and the dominator tree. |
| 5062 flow_graph->DiscoverBlocks(); | 5116 flow_graph->DiscoverBlocks(); |
| 5063 GrowableArray<BitVector*> dominance_frontier; | 5117 GrowableArray<BitVector*> dominance_frontier; |
| 5064 flow_graph->ComputeDominators(&dominance_frontier); | 5118 flow_graph->ComputeDominators(&dominance_frontier); |
| 5065 } | 5119 } |
| 5066 } | 5120 } |
| 5067 | 5121 |
| 5068 | 5122 |
| 5069 } // namespace dart | 5123 } // namespace dart |
| OLD | NEW |