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

Side by Side Diff: pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart

Issue 1526333002: dart2js cps: Clone small constants to use site. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Update tests Created 5 years 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
« no previous file with comments | « no previous file | tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart » ('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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 library tree_ir_builder; 5 library tree_ir_builder;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../constants/values.dart'; 8 import '../constants/values.dart';
9 import '../cps_ir/cps_ir_nodes.dart' as cps_ir; 9 import '../cps_ir/cps_ir_nodes.dart' as cps_ir;
10 import '../elements/elements.dart'; 10 import '../elements/elements.dart';
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 * particular, intermediate values and blocks used for local control flow are 46 * particular, intermediate values and blocks used for local control flow are
47 * still all named. 47 * still all named.
48 */ 48 */
49 class Builder implements cps_ir.Visitor/*<NodeCallback|Node>*/ { 49 class Builder implements cps_ir.Visitor/*<NodeCallback|Node>*/ {
50 final InternalErrorFunction internalError; 50 final InternalErrorFunction internalError;
51 51
52 final Map<cps_ir.Primitive, Variable> primitive2variable = 52 final Map<cps_ir.Primitive, Variable> primitive2variable =
53 <cps_ir.Primitive, Variable>{}; 53 <cps_ir.Primitive, Variable>{};
54 final Map<cps_ir.MutableVariable, Variable> mutable2variable = 54 final Map<cps_ir.MutableVariable, Variable> mutable2variable =
55 <cps_ir.MutableVariable, Variable>{}; 55 <cps_ir.MutableVariable, Variable>{};
56 final Set<cps_ir.Constant> inlinedConstants = new Set<cps_ir.Constant>();
56 57
57 // Continuations with more than one use are replaced with Tree labels. This 58 // Continuations with more than one use are replaced with Tree labels. This
58 // is the mapping from continuations to labels. 59 // is the mapping from continuations to labels.
59 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{}; 60 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{};
60 61
61 ExecutableElement currentElement; 62 ExecutableElement currentElement;
62 /// The 'this' Parameter for currentElement or the enclosing method. 63 /// The 'this' Parameter for currentElement or the enclosing method.
63 cps_ir.Parameter thisParameter; 64 cps_ir.Parameter thisParameter;
64 cps_ir.Continuation returnContinuation; 65 cps_ir.Continuation returnContinuation;
65 66
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 return primitive2variable.putIfAbsent(primitive, 103 return primitive2variable.putIfAbsent(primitive,
103 () => new Variable(currentElement, primitive.hint)); 104 () => new Variable(currentElement, primitive.hint));
104 } 105 }
105 106
106 /// Obtains a reference to the tree Variable corresponding to the IR primitive 107 /// Obtains a reference to the tree Variable corresponding to the IR primitive
107 /// referred to by [reference]. 108 /// referred to by [reference].
108 /// This increments the reference count for the given variable, so the 109 /// This increments the reference count for the given variable, so the
109 /// returned expression must be used in the tree. 110 /// returned expression must be used in the tree.
110 Expression getVariableUse(cps_ir.Reference<cps_ir.Primitive> reference) { 111 Expression getVariableUse(cps_ir.Reference<cps_ir.Primitive> reference) {
111 cps_ir.Primitive prim = reference.definition.effectiveDefinition; 112 cps_ir.Primitive prim = reference.definition.effectiveDefinition;
113 if (prim is cps_ir.Constant && inlinedConstants.contains(prim)) {
114 return new Constant(prim.value);
115 }
112 if (thisParameter != null && prim == thisParameter) { 116 if (thisParameter != null && prim == thisParameter) {
113 return new This(); 117 return new This();
114 } 118 }
115 return new VariableUse(getVariable(prim)); 119 return new VariableUse(getVariable(prim));
116 } 120 }
117 121
118 Expression getVariableUseOrNull( 122 Expression getVariableUseOrNull(
119 cps_ir.Reference<cps_ir.Primitive> reference) { 123 cps_ir.Reference<cps_ir.Primitive> reference) {
120 return reference == null ? null : getVariableUse(reference); 124 return reference == null ? null : getVariableUse(reference);
121 } 125 }
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 return result; 276 return result;
273 } 277 }
274 278
275 /// Translates a CPS primitive to a tree expression. 279 /// Translates a CPS primitive to a tree expression.
276 /// 280 ///
277 /// This simply calls the visit method for the primitive. 281 /// This simply calls the visit method for the primitive.
278 translatePrimitive(cps_ir.Primitive prim) { 282 translatePrimitive(cps_ir.Primitive prim) {
279 return prim.accept(this); 283 return prim.accept(this);
280 } 284 }
281 285
286 /************************ CONSTANT COPYING *****************************/
287
288 /// Estimate of the number of characters needed to emit a use of the given
289 /// constant.
290 int constantSize(PrimitiveConstantValue value) {
291 if (value is StringConstantValue) {
292 // Account for the quotes, but ignore the cost of escape sequences to
293 // avoid traversing the string.
sra1 2015/12/16 18:40:12 Note. The size will depend on the output encoding
asgerf 2015/12/17 15:51:52 Updated the comment to reflect this.
294 return value.length + 2;
295 } else {
296 return '${value.primitiveValue}'.length;
sra1 2015/12/16 18:40:12 We generate true and false as !0 and !1 in minifie
asgerf 2015/12/17 15:51:52 Bools -> done. Added a TODO for the rest. We coul
297 }
298 }
299
300 /// The number of uses [prim] has, or `-1` if it is used in a phi assignment
301 /// which is likely to be eliminated after liveness analysis.
302 int countNonPhiUses(cps_ir.Primitive prim) {
303 int count = 0;
304 for (cps_ir.Reference ref = prim.firstRef; ref != null; ref = ref.next) {
305 cps_ir.Node use = ref.parent;
306 if (use is cps_ir.InvokeContinuation) {
307 cps_ir.Continuation cont = use.continuation.definition;
308 int index = use.arguments.indexOf(ref);
309 if (cont.parameters[index].hint == prim.hint) {
sra1 2015/12/16 18:40:12 Is this because they are both null or both somethi
asgerf 2015/12/17 15:51:52 (this is also in response to the comment below) T
310 return -1;
311 }
312 }
313 count++;
314 }
315 return count;
316 }
317
318 /// True if the given [constant] should be copied to every use site.
319 bool shouldCopyToUses(cps_ir.Constant constant) {
320 if (!constant.value.isPrimitive) return false;
321 if (constant.hasAtMostOneUse) return true;
322 int uses = countNonPhiUses(constant);
323 if (uses == -1) return false; // Copying might prevent elimination of a phi.
324 int size = constantSize(constant.value);
325 // Compare the expected code size output of copying vs sharing.
326 const int USE = 2; // Minified locals usually have length 2.
sra1 2015/12/16 18:40:12 Only in 'large' functions. Can we estimate the nu
asgerf 2015/12/17 15:51:52 Changed to 1. I just wanted to use the common cas
327 const int ASSIGN = USE + 2; // Variable and '=' and ';'
328 const int BIAS = 2; // Artificial bias to slightly favor copying.
329 int costOfSharing = USE * uses + size + ASSIGN + BIAS;
330 int costOfCopying = size * uses;
331 return costOfCopying <= costOfSharing;
332 }
333
282 /************************ INTERIOR EXPRESSIONS ************************/ 334 /************************ INTERIOR EXPRESSIONS ************************/
283 // 335 //
284 // Visit methods for interior expressions must return a function: 336 // Visit methods for interior expressions must return a function:
285 // 337 //
286 // (Statement next) => <result statement> 338 // (Statement next) => <result statement>
287 // 339 //
288 340
289 NodeCallback visitLetPrim(cps_ir.LetPrim node) { 341 NodeCallback visitLetPrim(cps_ir.LetPrim node) {
342 if (node.primitive is cps_ir.Constant && shouldCopyToUses(node.primitive)) {
343 inlinedConstants.add(node.primitive);
344 return (Statement next) => next;
345 }
290 Variable variable = getVariable(node.primitive); 346 Variable variable = getVariable(node.primitive);
291 var value = translatePrimitive(node.primitive); 347 var value = translatePrimitive(node.primitive);
292 if (value is Expression) { 348 if (value is Expression) {
293 if (node.primitive.hasAtLeastOneUse) { 349 if (node.primitive.hasAtLeastOneUse) {
294 return (Statement next) => Assign.makeStatement(variable, value, next); 350 return (Statement next) => Assign.makeStatement(variable, value, next);
295 } else { 351 } else {
296 return (Statement next) => new ExpressionStatement(value, next); 352 return (Statement next) => new ExpressionStatement(value, next);
297 } 353 }
298 } else { 354 } else {
299 assert(value is NodeCallback); 355 assert(value is NodeCallback);
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node'); 755 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node');
700 } 756 }
701 757
702 visitFunctionDefinition(cps_ir.FunctionDefinition node) { 758 visitFunctionDefinition(cps_ir.FunctionDefinition node) {
703 unexpectedNode(node); 759 unexpectedNode(node);
704 } 760 }
705 visitParameter(cps_ir.Parameter node) => unexpectedNode(node); 761 visitParameter(cps_ir.Parameter node) => unexpectedNode(node);
706 visitContinuation(cps_ir.Continuation node) => unexpectedNode(node); 762 visitContinuation(cps_ir.Continuation node) => unexpectedNode(node);
707 visitMutableVariable(cps_ir.MutableVariable node) => unexpectedNode(node); 763 visitMutableVariable(cps_ir.MutableVariable node) => unexpectedNode(node);
708 } 764 }
OLDNEW
« no previous file with comments | « no previous file | tests/compiler/dart2js/js_backend_cps_ir_basic_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698