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

Side by Side Diff: pkg/compiler/lib/src/ssa/codegen_helpers.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) 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 import '../compiler.dart' show Compiler;
6 import '../constants/values.dart'; 5 import '../constants/values.dart';
7 import '../elements/elements.dart'; 6 import '../elements/elements.dart';
8 import '../js_backend/js_backend.dart'; 7 import '../js_backend/js_backend.dart';
8 import '../js_backend/interceptor_data.dart';
9 import '../options.dart';
9 import '../types/types.dart'; 10 import '../types/types.dart';
10 import '../universe/selector.dart' show Selector; 11 import '../universe/selector.dart' show Selector;
11 import '../world.dart' show ClosedWorld; 12 import '../world.dart' show ClosedWorld;
12 import 'nodes.dart'; 13 import 'nodes.dart';
13 14
14 /** 15 /**
15 * Replaces some instructions with specialized versions to make codegen easier. 16 * Replaces some instructions with specialized versions to make codegen easier.
16 * Caches codegen information on nodes. 17 * Caches codegen information on nodes.
17 */ 18 */
18 class SsaInstructionSelection extends HBaseVisitor { 19 class SsaInstructionSelection extends HBaseVisitor {
19 final Compiler compiler; 20 final ClosedWorld _closedWorld;
20 final ClosedWorld closedWorld; 21 final InterceptorData _interceptorData;
21 HGraph graph; 22 HGraph graph;
22 23
23 SsaInstructionSelection(this.compiler, this.closedWorld); 24 SsaInstructionSelection(this._closedWorld, this._interceptorData);
24
25 JavaScriptBackend get backend => compiler.backend;
26 25
27 void visitGraph(HGraph graph) { 26 void visitGraph(HGraph graph) {
28 this.graph = graph; 27 this.graph = graph;
29 visitDominatorTree(graph); 28 visitDominatorTree(graph);
30 } 29 }
31 30
32 visitBasicBlock(HBasicBlock block) { 31 visitBasicBlock(HBasicBlock block) {
33 HInstruction instruction = block.first; 32 HInstruction instruction = block.first;
34 while (instruction != null) { 33 while (instruction != null) {
35 HInstruction next = instruction.next; 34 HInstruction next = instruction.next;
(...skipping 25 matching lines...) Expand all
61 } 60 }
62 61
63 HInstruction visitInstruction(HInstruction node) { 62 HInstruction visitInstruction(HInstruction node) {
64 return node; 63 return node;
65 } 64 }
66 65
67 HInstruction visitIs(HIs node) { 66 HInstruction visitIs(HIs node) {
68 if (node.kind == HIs.RAW_CHECK) { 67 if (node.kind == HIs.RAW_CHECK) {
69 HInstruction interceptor = node.interceptor; 68 HInstruction interceptor = node.interceptor;
70 if (interceptor != null) { 69 if (interceptor != null) {
71 return new HIsViaInterceptor( 70 return new HIsViaInterceptor(node.typeExpression, interceptor,
72 node.typeExpression, interceptor, closedWorld.commonMasks.boolType); 71 _closedWorld.commonMasks.boolType);
73 } 72 }
74 } 73 }
75 return node; 74 return node;
76 } 75 }
77 76
78 HInstruction visitIdentity(HIdentity node) { 77 HInstruction visitIdentity(HIdentity node) {
79 node.singleComparisonOp = simpleOp(node.left, node.right); 78 node.singleComparisonOp = simpleOp(node.left, node.right);
80 return node; 79 return node;
81 } 80 }
82 81
83 String simpleOp(HInstruction left, HInstruction right) { 82 String simpleOp(HInstruction left, HInstruction right) {
84 // Returns the single identity comparison (== or ===) or null if a more 83 // Returns the single identity comparison (== or ===) or null if a more
85 // complex expression is required. 84 // complex expression is required.
86 TypeMask leftType = left.instructionType; 85 TypeMask leftType = left.instructionType;
87 TypeMask rightType = right.instructionType; 86 TypeMask rightType = right.instructionType;
88 if (leftType.isNullable && rightType.isNullable) { 87 if (leftType.isNullable && rightType.isNullable) {
89 if (left.isConstantNull() || 88 if (left.isConstantNull() ||
90 right.isConstantNull() || 89 right.isConstantNull() ||
91 (left.isPrimitive(closedWorld) && leftType == rightType)) { 90 (left.isPrimitive(_closedWorld) && leftType == rightType)) {
92 return '=='; 91 return '==';
93 } 92 }
94 return null; 93 return null;
95 } 94 }
96 return '==='; 95 return '===';
97 } 96 }
98 97
99 HInstruction visitInvokeDynamic(HInvokeDynamic node) { 98 HInstruction visitInvokeDynamic(HInvokeDynamic node) {
100 if (node.isInterceptedCall) { 99 if (node.isInterceptedCall) {
101 tryReplaceInterceptorWithDummy(node, node.selector, node.mask); 100 tryReplaceInterceptorWithDummy(node, node.selector, node.mask);
102 } 101 }
103 return node; 102 return node;
104 } 103 }
105 104
106 HInstruction visitInvokeSuper(HInvokeSuper node) { 105 HInstruction visitInvokeSuper(HInvokeSuper node) {
107 if (node.isInterceptedCall) { 106 if (node.isInterceptedCall) {
108 TypeMask mask = node.getDartReceiver(closedWorld).instructionType; 107 TypeMask mask = node.getDartReceiver(_closedWorld).instructionType;
109 tryReplaceInterceptorWithDummy(node, node.selector, mask); 108 tryReplaceInterceptorWithDummy(node, node.selector, mask);
110 } 109 }
111 return node; 110 return node;
112 } 111 }
113 112
114 void tryReplaceInterceptorWithDummy( 113 void tryReplaceInterceptorWithDummy(
115 HInvoke node, Selector selector, TypeMask mask) { 114 HInvoke node, Selector selector, TypeMask mask) {
116 // Calls of the form 115 // Calls of the form
117 // 116 //
118 // a.foo$1(a, x) 117 // a.foo$1(a, x)
(...skipping 16 matching lines...) Expand all
135 134
136 // TODO(15933): Make automatically generated property extraction closures 135 // TODO(15933): Make automatically generated property extraction closures
137 // work with the dummy receiver optimization. 136 // work with the dummy receiver optimization.
138 if (selector.isGetter) return; 137 if (selector.isGetter) return;
139 138
140 // This assignment of inputs is uniform for HInvokeDynamic and HInvokeSuper. 139 // This assignment of inputs is uniform for HInvokeDynamic and HInvokeSuper.
141 HInstruction interceptor = node.inputs[0]; 140 HInstruction interceptor = node.inputs[0];
142 HInstruction receiverArgument = node.inputs[1]; 141 HInstruction receiverArgument = node.inputs[1];
143 142
144 if (interceptor.nonCheck() == receiverArgument.nonCheck()) { 143 if (interceptor.nonCheck() == receiverArgument.nonCheck()) {
145 if (backend.interceptorData.isInterceptedSelector(selector) && 144 if (_interceptorData.isInterceptedSelector(selector) &&
146 !backend.interceptorData.isInterceptedMixinSelector(selector, mask)) { 145 !_interceptorData.isInterceptedMixinSelector(selector, mask)) {
147 ConstantValue constant = new SyntheticConstantValue( 146 ConstantValue constant = new SyntheticConstantValue(
148 SyntheticConstantKind.DUMMY_INTERCEPTOR, 147 SyntheticConstantKind.DUMMY_INTERCEPTOR,
149 receiverArgument.instructionType); 148 receiverArgument.instructionType);
150 HConstant dummy = graph.addConstant(constant, closedWorld); 149 HConstant dummy = graph.addConstant(constant, _closedWorld);
151 receiverArgument.usedBy.remove(node); 150 receiverArgument.usedBy.remove(node);
152 node.inputs[1] = dummy; 151 node.inputs[1] = dummy;
153 dummy.usedBy.add(node); 152 dummy.usedBy.add(node);
154 } 153 }
155 } 154 }
156 } 155 }
157 156
158 HInstruction visitFieldSet(HFieldSet setter) { 157 HInstruction visitFieldSet(HFieldSet setter) {
159 // Pattern match 158 // Pattern match
160 // t1 = x.f; t2 = t1 + 1; x.f = t2; use(t2) --> ++x.f 159 // t1 = x.f; t2 = t1 + 1; x.f = t2; use(t2) --> ++x.f
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 } 236 }
238 237
239 HInstruction simpleBinary(String assignOp) { 238 HInstruction simpleBinary(String assignOp) {
240 HInvokeBinary binary = op; 239 HInvokeBinary binary = op;
241 return simple(assignOp, binary.left, binary.right); 240 return simple(assignOp, binary.left, binary.right);
242 } 241 }
243 242
244 HInstruction bitop(String assignOp) { 243 HInstruction bitop(String assignOp) {
245 // HBitAnd, HBitOr etc. are more difficult because HBitAnd(a.x, y) 244 // HBitAnd, HBitOr etc. are more difficult because HBitAnd(a.x, y)
246 // sometimes needs to be forced to unsigned: a.x = (a.x & y) >>> 0. 245 // sometimes needs to be forced to unsigned: a.x = (a.x & y) >>> 0.
247 if (op.isUInt31(closedWorld)) return simpleBinary(assignOp); 246 if (op.isUInt31(_closedWorld)) return simpleBinary(assignOp);
248 return noMatchingRead(); 247 return noMatchingRead();
249 } 248 }
250 249
251 if (op is HAdd) return plusOrMinus('+', '++'); 250 if (op is HAdd) return plusOrMinus('+', '++');
252 if (op is HSubtract) return plusOrMinus('-', '--'); 251 if (op is HSubtract) return plusOrMinus('-', '--');
253 252
254 if (op is HStringConcat) return simple('+', op.left, op.right); 253 if (op is HStringConcat) return simple('+', op.left, op.right);
255 254
256 if (op is HMultiply) return simpleBinary('*'); 255 if (op is HMultiply) return simpleBinary('*');
257 if (op is HDivide) return simpleBinary('/'); 256 if (op is HDivide) return simpleBinary('/');
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 instruction.block.rewrite(instruction, instruction.checkedInput); 290 instruction.block.rewrite(instruction, instruction.checkedInput);
292 instruction.block.remove(instruction); 291 instruction.block.remove(instruction);
293 } 292 }
294 } 293 }
295 294
296 /** 295 /**
297 * Remove [HTypeConversion] instructions from the graph in '--trust-primitives' 296 * Remove [HTypeConversion] instructions from the graph in '--trust-primitives'
298 * mode. 297 * mode.
299 */ 298 */
300 class SsaTrustedCheckRemover extends HBaseVisitor { 299 class SsaTrustedCheckRemover extends HBaseVisitor {
301 Compiler compiler; 300 final CompilerOptions _options;
302 SsaTrustedCheckRemover(this.compiler); 301
302 SsaTrustedCheckRemover(this._options);
303 303
304 void visitGraph(HGraph graph) { 304 void visitGraph(HGraph graph) {
305 if (!compiler.options.trustPrimitives) return; 305 if (!_options.trustPrimitives) return;
306 visitDominatorTree(graph); 306 visitDominatorTree(graph);
307 } 307 }
308 308
309 void visitBasicBlock(HBasicBlock block) { 309 void visitBasicBlock(HBasicBlock block) {
310 HInstruction instruction = block.first; 310 HInstruction instruction = block.first;
311 while (instruction != null) { 311 while (instruction != null) {
312 HInstruction next = instruction.next; 312 HInstruction next = instruction.next;
313 instruction.accept(this); 313 instruction.accept(this);
314 instruction = next; 314 instruction = next;
315 } 315 }
(...skipping 11 matching lines...) Expand all
327 * Instead of emitting each SSA instruction with a temporary variable 327 * Instead of emitting each SSA instruction with a temporary variable
328 * mark instructions that can be emitted at their use-site. 328 * mark instructions that can be emitted at their use-site.
329 * For example, in: 329 * For example, in:
330 * t0 = 4; 330 * t0 = 4;
331 * t1 = 3; 331 * t1 = 3;
332 * t2 = add(t0, t1); 332 * t2 = add(t0, t1);
333 * t0 and t1 would be marked and the resulting code would then be: 333 * t0 and t1 would be marked and the resulting code would then be:
334 * t2 = add(4, 3); 334 * t2 = add(4, 3);
335 */ 335 */
336 class SsaInstructionMerger extends HBaseVisitor { 336 class SsaInstructionMerger extends HBaseVisitor {
337 final Compiler compiler; 337 final JavaScriptBackend _backend;
338 /** 338 /**
339 * List of [HInstruction] that the instruction merger expects in 339 * List of [HInstruction] that the instruction merger expects in
340 * order when visiting the inputs of an instruction. 340 * order when visiting the inputs of an instruction.
341 */ 341 */
342 List<HInstruction> expectedInputs; 342 List<HInstruction> expectedInputs;
343 /** 343 /**
344 * Set of pure [HInstruction] that the instruction merger expects to 344 * Set of pure [HInstruction] that the instruction merger expects to
345 * find. The order of pure instructions do not matter, as they will 345 * find. The order of pure instructions do not matter, as they will
346 * not be affected by side effects. 346 * not be affected by side effects.
347 */ 347 */
348 Set<HInstruction> pureInputs; 348 Set<HInstruction> pureInputs;
349 Set<HInstruction> generateAtUseSite; 349 Set<HInstruction> generateAtUseSite;
350 350
351 void markAsGenerateAtUseSite(HInstruction instruction) { 351 void markAsGenerateAtUseSite(HInstruction instruction) {
352 assert(!instruction.isJsStatement()); 352 assert(!instruction.isJsStatement());
353 generateAtUseSite.add(instruction); 353 generateAtUseSite.add(instruction);
354 } 354 }
355 355
356 SsaInstructionMerger(this.generateAtUseSite, this.compiler); 356 SsaInstructionMerger(this.generateAtUseSite, this._backend);
357
358 JavaScriptBackend get backend => compiler.backend;
359 357
360 void visitGraph(HGraph graph) { 358 void visitGraph(HGraph graph) {
361 visitDominatorTree(graph); 359 visitDominatorTree(graph);
362 } 360 }
363 361
364 void analyzeInputs(HInstruction user, int start) { 362 void analyzeInputs(HInstruction user, int start) {
365 List<HInstruction> inputs = user.inputs; 363 List<HInstruction> inputs = user.inputs;
366 for (int i = start; i < inputs.length; i++) { 364 for (int i = start; i < inputs.length; i++) {
367 HInstruction input = inputs[i]; 365 HInstruction input = inputs[i];
368 if (!generateAtUseSite.contains(input) && 366 if (!generateAtUseSite.contains(input) &&
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 // If aliased super members cannot be used, we will generate code like 429 // If aliased super members cannot be used, we will generate code like
432 // 430 //
433 // C.prototype.method.call(instance) 431 // C.prototype.method.call(instance)
434 // 432 //
435 // where instance is the [this] object for the method. In such a case, the 433 // where instance is the [this] object for the method. In such a case, the
436 // get of prototype might be evaluated before instance is created if we 434 // get of prototype might be evaluated before instance is created if we
437 // generate instance at use site, which in turn might update the prototype 435 // generate instance at use site, which in turn might update the prototype
438 // after first access if we use lazy initialization. 436 // after first access if we use lazy initialization.
439 // In this case, we therefore don't allow the receiver (the first argument) 437 // In this case, we therefore don't allow the receiver (the first argument)
440 // to be generated at use site, and only analyze all other arguments. 438 // to be generated at use site, and only analyze all other arguments.
441 if (!backend.canUseAliasedSuperMember(superMethod, selector)) { 439 if (!_backend.canUseAliasedSuperMember(superMethod, selector)) {
442 analyzeInputs(instruction, 1); 440 analyzeInputs(instruction, 1);
443 } else { 441 } else {
444 super.visitInvokeSuper(instruction); 442 super.visitInvokeSuper(instruction);
445 } 443 }
446 } 444 }
447 445
448 void visitIs(HIs instruction) { 446 void visitIs(HIs instruction) {
449 // In the general case the input might be used multple multiple times, so it 447 // In the general case the input might be used multple multiple times, so it
450 // must not be set generate at use site. 448 // must not be set generate at use site.
451 449
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 } 800 }
803 801
804 // If [thenInput] is defined in the first predecessor, then it is only used 802 // If [thenInput] is defined in the first predecessor, then it is only used
805 // by [phi] and can be generated at use site. 803 // by [phi] and can be generated at use site.
806 if (identical(thenInput.block, end.predecessors[0])) { 804 if (identical(thenInput.block, end.predecessors[0])) {
807 assert(thenInput.usedBy.length == 1); 805 assert(thenInput.usedBy.length == 1);
808 markAsGenerateAtUseSite(thenInput); 806 markAsGenerateAtUseSite(thenInput);
809 } 807 }
810 } 808 }
811 } 809 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/codegen.dart ('k') | pkg/compiler/lib/src/ssa/interceptor_simplifier.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698