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

Side by Side Diff: pkg/compiler/lib/src/ssa/interceptor_simplifier.dart

Issue 2777163002: Make codegen and optimizations depend more directly on data objects. (Closed)
Patch Set: Created 3 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
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 import '../common/backend_api.dart' show BackendClasses; 5 import '../common/backend_api.dart' show BackendClasses;
6 import '../compiler.dart' show Compiler;
7 import '../constants/constant_system.dart'; 6 import '../constants/constant_system.dart';
8 import '../constants/values.dart'; 7 import '../constants/values.dart';
9 import '../elements/entities.dart'; 8 import '../elements/entities.dart';
10 import '../js_backend/backend.dart'; 9 import '../js_backend/backend_helpers.dart';
10 import '../js_backend/interceptor_data.dart';
11 import '../types/types.dart'; 11 import '../types/types.dart';
12 import '../universe/selector.dart' show Selector; 12 import '../universe/selector.dart' show Selector;
13 import '../world.dart' show ClosedWorld; 13 import '../world.dart' show ClosedWorld;
14 import 'nodes.dart'; 14 import 'nodes.dart';
15 import 'optimize.dart'; 15 import 'optimize.dart';
16 16
17 /** 17 /**
18 * This phase simplifies interceptors in multiple ways: 18 * This phase simplifies interceptors in multiple ways:
19 * 19 *
20 * 1) If the interceptor is for an object whose type is known, it 20 * 1) If the interceptor is for an object whose type is known, it
(...skipping 10 matching lines...) Expand all
31 * receiver of an intercepted call a candidate for being generated at use site. 31 * receiver of an intercepted call a candidate for being generated at use site.
32 * 32 *
33 * 5) Some HIs operations on an interceptor are replaced with a HIs version that 33 * 5) Some HIs operations on an interceptor are replaced with a HIs version that
34 * uses 'instanceof' rather than testing a type flag. 34 * uses 'instanceof' rather than testing a type flag.
35 * 35 *
36 */ 36 */
37 class SsaSimplifyInterceptors extends HBaseVisitor 37 class SsaSimplifyInterceptors extends HBaseVisitor
38 implements OptimizationPhase { 38 implements OptimizationPhase {
39 final String name = "SsaSimplifyInterceptors"; 39 final String name = "SsaSimplifyInterceptors";
40 final ClosedWorld closedWorld; 40 final ClosedWorld closedWorld;
41 final Compiler compiler; 41 final BackendHelpers helpers;
42 final InterceptorData interceptorData;
42 final ClassEntity enclosingClass; 43 final ClassEntity enclosingClass;
43 HGraph graph; 44 HGraph graph;
44 45
45 SsaSimplifyInterceptors(this.compiler, this.closedWorld, this.enclosingClass); 46 SsaSimplifyInterceptors(this.closedWorld, this.helpers, this.interceptorData,
46 47 this.enclosingClass);
47 JavaScriptBackend get backend => compiler.backend;
48 48
49 BackendClasses get backendClasses => closedWorld.backendClasses; 49 BackendClasses get backendClasses => closedWorld.backendClasses;
50 50
51 ConstantSystem get constantSystem => closedWorld.constantSystem; 51 ConstantSystem get constantSystem => closedWorld.constantSystem;
52 52
53 void visitGraph(HGraph graph) { 53 void visitGraph(HGraph graph) {
54 this.graph = graph; 54 this.graph = graph;
55 visitDominatorTree(graph); 55 visitDominatorTree(graph);
56 } 56 }
57 57
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 return false; 101 return false;
102 } 102 }
103 if (receiver.canBeNull() && 103 if (receiver.canBeNull() &&
104 interceptedClasses.contains(backendClasses.nullClass)) { 104 interceptedClasses.contains(backendClasses.nullClass)) {
105 // Need the JSNull interceptor. 105 // Need the JSNull interceptor.
106 return false; 106 return false;
107 } 107 }
108 108
109 // All intercepted classes extend `Interceptor`, so if the receiver can't be 109 // All intercepted classes extend `Interceptor`, so if the receiver can't be
110 // a class extending `Interceptor` then it can be called directly. 110 // a class extending `Interceptor` then it can be called directly.
111 return new TypeMask.nonNullSubclass( 111 return new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, closedWorld)
112 backend.helpers.jsInterceptorClass, closedWorld)
113 .isDisjoint(receiver.instructionType, closedWorld); 112 .isDisjoint(receiver.instructionType, closedWorld);
114 } 113 }
115 114
116 HInstruction tryComputeConstantInterceptor( 115 HInstruction tryComputeConstantInterceptor(
117 HInstruction input, Set<ClassEntity> interceptedClasses) { 116 HInstruction input, Set<ClassEntity> interceptedClasses) {
118 if (input == graph.explicitReceiverParameter) { 117 if (input == graph.explicitReceiverParameter) {
119 // If `explicitReceiverParameter` is set it means the current method is an 118 // If `explicitReceiverParameter` is set it means the current method is an
120 // interceptor method, and `this` is the interceptor. The caller just did 119 // interceptor method, and `this` is the interceptor. The caller just did
121 // `getInterceptor(foo).currentMethod(foo)` to enter the current method. 120 // `getInterceptor(foo).currentMethod(foo)` to enter the current method.
122 return graph.thisInstruction; 121 return graph.thisInstruction;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 user.inputs.where((input) => input == used).length; 216 user.inputs.where((input) => input == used).length;
218 217
219 Set<ClassEntity> interceptedClasses; 218 Set<ClassEntity> interceptedClasses;
220 HInstruction dominator = findDominator(node.usedBy); 219 HInstruction dominator = findDominator(node.usedBy);
221 // If there is a call that dominates all other uses, we can use just the 220 // If there is a call that dominates all other uses, we can use just the
222 // selector of that instruction. 221 // selector of that instruction.
223 if (dominator is HInvokeDynamic && 222 if (dominator is HInvokeDynamic &&
224 dominator.isCallOnInterceptor(closedWorld) && 223 dominator.isCallOnInterceptor(closedWorld) &&
225 node == dominator.receiver && 224 node == dominator.receiver &&
226 useCount(dominator, node) == 1) { 225 useCount(dominator, node) == 1) {
227 interceptedClasses = backend.interceptorData 226 interceptedClasses =
228 .getInterceptedClassesOn(dominator.selector.name); 227 interceptorData.getInterceptedClassesOn(dominator.selector.name);
229 228
230 // If we found that we need number, we must still go through all 229 // If we found that we need number, we must still go through all
231 // uses to check if they require int, or double. 230 // uses to check if they require int, or double.
232 if (interceptedClasses.contains(backendClasses.numClass) && 231 if (interceptedClasses.contains(backendClasses.numClass) &&
233 !(interceptedClasses.contains(backendClasses.doubleClass) || 232 !(interceptedClasses.contains(backendClasses.doubleClass) ||
234 interceptedClasses.contains(backendClasses.intClass))) { 233 interceptedClasses.contains(backendClasses.intClass))) {
235 Set<ClassEntity> required; 234 Set<ClassEntity> required;
236 for (HInstruction user in node.usedBy) { 235 for (HInstruction user in node.usedBy) {
237 if (user is! HInvoke) continue; 236 if (user is! HInvoke) continue;
238 Set<ClassEntity> intercepted = backend.interceptorData 237 Set<ClassEntity> intercepted =
239 .getInterceptedClassesOn(user.selector.name); 238 interceptorData.getInterceptedClassesOn(user.selector.name);
240 if (intercepted.contains(backendClasses.intClass)) { 239 if (intercepted.contains(backendClasses.intClass)) {
241 // TODO(johnniwinther): Use type argument when all uses of 240 // TODO(johnniwinther): Use type argument when all uses of
242 // intercepted classes expect entities instead of elements. 241 // intercepted classes expect entities instead of elements.
243 required ??= new Set/*<ClassEntity>*/(); 242 required ??= new Set/*<ClassEntity>*/();
244 required.add(backendClasses.intClass); 243 required.add(backendClasses.intClass);
245 } 244 }
246 if (intercepted.contains(backendClasses.doubleClass)) { 245 if (intercepted.contains(backendClasses.doubleClass)) {
247 // TODO(johnniwinther): Use type argument when all uses of 246 // TODO(johnniwinther): Use type argument when all uses of
248 // intercepted classes expect entities instead of elements. 247 // intercepted classes expect entities instead of elements.
249 required ??= new Set/*<ClassEntity>*/(); 248 required ??= new Set/*<ClassEntity>*/();
250 required.add(backendClasses.doubleClass); 249 required.add(backendClasses.doubleClass);
251 } 250 }
252 } 251 }
253 // Don't modify the result of [backend.getInterceptedClassesOn]. 252 // Don't modify the result of [interceptorData.getInterceptedClassesOn].
254 if (required != null) { 253 if (required != null) {
255 interceptedClasses = interceptedClasses.union(required); 254 interceptedClasses = interceptedClasses.union(required);
256 } 255 }
257 } 256 }
258 } else { 257 } else {
259 // TODO(johnniwinther): Use type argument when all uses of intercepted 258 // TODO(johnniwinther): Use type argument when all uses of intercepted
260 // classes expect entities instead of elements. 259 // classes expect entities instead of elements.
261 interceptedClasses = new Set/*<ClassEntity>*/(); 260 interceptedClasses = new Set/*<ClassEntity>*/();
262 for (HInstruction user in node.usedBy) { 261 for (HInstruction user in node.usedBy) {
263 if (user is HInvokeDynamic && 262 if (user is HInvokeDynamic &&
264 user.isCallOnInterceptor(closedWorld) && 263 user.isCallOnInterceptor(closedWorld) &&
265 node == user.receiver && 264 node == user.receiver &&
266 useCount(user, node) == 1) { 265 useCount(user, node) == 1) {
267 interceptedClasses.addAll(backend.interceptorData 266 interceptedClasses.addAll(
268 .getInterceptedClassesOn(user.selector.name)); 267 interceptorData.getInterceptedClassesOn(user.selector.name));
269 } else if (user is HInvokeSuper && 268 } else if (user is HInvokeSuper &&
270 user.isCallOnInterceptor(closedWorld) && 269 user.isCallOnInterceptor(closedWorld) &&
271 node == user.receiver && 270 node == user.receiver &&
272 useCount(user, node) == 1) { 271 useCount(user, node) == 1) {
273 interceptedClasses.addAll(backend.interceptorData 272 interceptedClasses.addAll(
274 .getInterceptedClassesOn(user.selector.name)); 273 interceptorData.getInterceptedClassesOn(user.selector.name));
275 } else { 274 } else {
276 // Use a most general interceptor for other instructions, example, 275 // Use a most general interceptor for other instructions, example,
277 // is-checks and escaping interceptors. 276 // is-checks and escaping interceptors.
278 interceptedClasses.addAll(backend.interceptorData.interceptedClasses); 277 interceptedClasses.addAll(interceptorData.interceptedClasses);
279 break; 278 break;
280 } 279 }
281 } 280 }
282 } 281 }
283 282
284 node.interceptedClasses = interceptedClasses; 283 node.interceptedClasses = interceptedClasses;
285 284
286 HInstruction receiver = node.receiver; 285 HInstruction receiver = node.receiver;
287 286
288 // TODO(sra): We should consider each use individually and then all uses 287 // TODO(sra): We should consider each use individually and then all uses
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 block.addAfter(user, replacement); 344 block.addAfter(user, replacement);
346 block.rewrite(user, replacement); 345 block.rewrite(user, replacement);
347 block.remove(user); 346 block.remove(user);
348 return false; 347 return false;
349 } 348 }
350 349
351 if (user is HIs) { 350 if (user is HIs) {
352 // See if we can rewrite the is-check to use 'instanceof', i.e. rewrite 351 // See if we can rewrite the is-check to use 'instanceof', i.e. rewrite
353 // "getInterceptor(x).$isT" to "x instanceof T". 352 // "getInterceptor(x).$isT" to "x instanceof T".
354 if (node == user.interceptor) { 353 if (node == user.interceptor) {
355 if (backend.interceptorData 354 if (interceptorData.mayGenerateInstanceofCheck(user.typeExpression)) {
356 .mayGenerateInstanceofCheck(user.typeExpression)) {
357 HInstruction instanceofCheck = new HIs.instanceOf( 355 HInstruction instanceofCheck = new HIs.instanceOf(
358 user.typeExpression, user.expression, user.instructionType); 356 user.typeExpression, user.expression, user.instructionType);
359 instanceofCheck.sourceInformation = user.sourceInformation; 357 instanceofCheck.sourceInformation = user.sourceInformation;
360 instanceofCheck.sourceElement = user.sourceElement; 358 instanceofCheck.sourceElement = user.sourceElement;
361 return replaceUserWith(instanceofCheck); 359 return replaceUserWith(instanceofCheck);
362 } 360 }
363 } 361 }
364 } else if (user is HInvokeDynamic) { 362 } else if (user is HInvokeDynamic) {
365 if (node == user.inputs[0]) { 363 if (node == user.inputs[0]) {
366 // Replace the user with a [HOneShotInterceptor]. 364 // Replace the user with a [HOneShotInterceptor].
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 instruction = new HInvokeDynamicMethod( 421 instruction = new HInvokeDynamicMethod(
424 selector, mask, inputs, node.instructionType, true); 422 selector, mask, inputs, node.instructionType, true);
425 } 423 }
426 424
427 HBasicBlock block = node.block; 425 HBasicBlock block = node.block;
428 block.addAfter(node, instruction); 426 block.addAfter(node, instruction);
429 block.rewrite(node, instruction); 427 block.rewrite(node, instruction);
430 return true; 428 return true;
431 } 429 }
432 } 430 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/codegen_helpers.dart ('k') | pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698