Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 13878017: Convert EqualityCompare to StrictCompare if reciever is either null or guaranteed to have default e… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address Srdjan's comments Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698