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

Unified Diff: pkg/dev_compiler/lib/src/compiler/js_metalet.dart

Issue 2980113002: fix #27320, better DDC temp generation (Closed)
Patch Set: rebase Created 3 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/dev_compiler/lib/src/compiler/code_generator.dart ('k') | pkg/dev_compiler/lib/src/js_ast/nodes.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/dev_compiler/lib/src/compiler/js_metalet.dart
diff --git a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
index 7ae35a70be63671a786da028b8245c7774fee808..7ec0f6ec3c7834211473f85266d3f41d72df7a58 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
@@ -65,22 +65,43 @@ class MetaLet extends Expression {
return _toInvokedFunction(block);
}
- Expression toAssignExpression(Expression left) {
+ Expression toAssignExpression(Expression left, [String op]) {
if (left is Identifier) {
- var simple = _simplifyAssignment(left);
- if (simple != null) return simple;
-
- var exprs = body.toList();
- exprs.add(exprs.removeLast().toAssignExpression(left));
- return new MetaLet(variables, exprs);
+ return _simplifyAssignment(left, op: op) ?? _toAssign(left, op);
+ } else if (left is PropertyAccess &&
+ left.receiver is This &&
+ (left.selector is Identifier || left.selector is LiteralString)) {
+ return _toAssign(left, op);
}
- return super.toAssignExpression(left);
+ return super.toAssignExpression(left, op);
+ }
+
+ Expression _toAssign(Expression left, [String op]) {
+ var exprs = body.toList();
+ exprs.add(exprs.removeLast().toAssignExpression(left, op));
+ return new MetaLet(variables, exprs);
}
Statement toVariableDeclaration(Identifier name) {
var simple = _simplifyAssignment(name, isDeclaration: true);
if (simple != null) return simple.toStatement();
- return super.toVariableDeclaration(name);
+
+ // We can still optimize something like:
+ //
+ // let x = ((l) => l == null ? null : l.xyz)(some.expr);
+ //
+ // can be transformed to:
+ //
+ // let l = some.expr;
+ // let x = l == null ? null : l.xyz;
+ //
+ // Because `x` is a declaration, we know it is safe to move.
+ // (see also _toAssign)
+ var statements = body
+ .map((e) =>
+ e == body.last ? e.toVariableDeclaration(name) : e.toStatement())
+ .toList();
+ return _finishStatement(statements);
}
Expression toExpression() {
@@ -198,8 +219,11 @@ class MetaLet extends Expression {
// Interpolate the body.
node = _substitute(node, substitutions);
if (initializers.isNotEmpty) {
+ var first = initializers[0];
node = new Block([
- new VariableDeclarationList('let', initializers).toStatement(),
+ initializers.length == 1
+ ? first.value.toVariableDeclaration(first.declaration)
+ : new VariableDeclarationList('let', initializers).toStatement(),
node
]);
}
@@ -209,7 +233,7 @@ class MetaLet extends Expression {
/// If we finish with an assignment to an identifier, try to simplify the
/// block. For example:
///
- /// ((_) => _.add(1), _.add(2), result = _)([])
+ /// result = ((_) => _.add(1), _.add(2), _)([])
///
/// Can be transformed to:
///
@@ -217,48 +241,37 @@ class MetaLet extends Expression {
///
/// However we should not simplify in this case because `result` is read:
///
- /// ((_) => _.addAll(result), _.add(2), result = _)([])
+ /// result = ((_) => _.addAll(result), _.add(2), _)([])
///
- MetaLet _simplifyAssignment(Identifier left, {bool isDeclaration: false}) {
+ MetaLet _simplifyAssignment(Identifier left,
+ {String op, bool isDeclaration: false}) {
// See if the result value is a let* temporary variable.
- if (body.last is! MetaLetVariable) return null;
-
- MetaLetVariable result = body.last;
- if (!variables.containsKey(result)) return null;
-
- // Variables declared can't be used inside their initializer, so make
- // sure we don't transform an assignment into an initializer.
- // If this already was a declaration, then we know it's legal, so we can
- // skip the check.
- if (!isDeclaration) {
- var finder = new _IdentFinder(left.name);
- for (var expr in body) {
- if (finder.found) break;
- expr.accept(finder);
+ var result = body.last;
+ if (result is MetaLetVariable && variables.containsKey(result)) {
+ // For assignments, make sure the identifier isn't used in body, as that
+ // would change the assignment order and be an invalid optimization.
+ if (!isDeclaration && _IdentFinder.foundIn(left.name, body)) return null;
+
+ var vars = new Map<MetaLetVariable, Expression>.from(variables);
+ var value = vars.remove(result);
+ Expression assign;
+ if (isDeclaration) {
+ // Technically, putting one of these in a comma expression is not
+ // legal. However when isDeclaration is true, toStatement will be
+ // called immediately on the MetaLet, which results in legal JS.
+ assign = new VariableDeclarationList(
+ 'let', [new VariableInitialization(left, value)]);
+ } else {
+ assign = value.toAssignExpression(left, op);
}
- // If the identifier was used elsewhere, bail, because we're going to
- // change the order of when the assignment happens.
- if (finder.found) return null;
- }
- var vars = new Map<MetaLetVariable, Expression>.from(variables);
- var value = vars.remove(result);
- Expression assign;
- if (isDeclaration) {
- // Technically, putting one of these in a comma expression is not
- // legal. However when isDeclaration is true, toStatement will be
- // called immediately on the MetaLet, which results in legal JS.
- assign = new VariableDeclarationList(
- 'let', [new VariableInitialization(left, value)]);
- } else {
- assign = value.toAssignExpression(left);
+ assert(body.isNotEmpty);
+ Binary newBody = new Expression.binary([assign]..addAll(body), ',');
+ newBody = _substitute(newBody, {result: left});
+ return new MetaLet(vars, newBody.commaToExpressionList(),
+ statelessResult: statelessResult);
}
-
- assert(body.isNotEmpty);
- Binary newBody = new Expression.binary([assign]..addAll(body), ',');
- newBody = _substitute(newBody, {result: left});
- return new MetaLet(vars, newBody.commaToExpressionList(),
- statelessResult: statelessResult);
+ return null;
}
}
@@ -317,6 +330,15 @@ class _IdentFinder extends BaseVisitor {
bool found = false;
_IdentFinder(this.name);
+ static bool foundIn(String name, List<Node> body) {
+ var finder = new _IdentFinder(name);
+ for (var expr in body) {
+ expr.accept(finder);
+ if (finder.found) return true;
+ }
+ return false;
+ }
+
@override
visitIdentifier(Identifier node) {
if (node.name == name) found = true;
« no previous file with comments | « pkg/dev_compiler/lib/src/compiler/code_generator.dart ('k') | pkg/dev_compiler/lib/src/js_ast/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698