| Index: pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
|
| diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
|
| index 4312130deaa2b4bbc058c94fd8199a04fd8c6eff..10176e2acf2bef84def8687ade5ef7d5d5d2b155 100644
|
| --- a/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
|
| +++ b/pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart
|
| @@ -84,9 +84,20 @@ class Label {
|
| }
|
|
|
| /**
|
| - * Variables are [Expression]s.
|
| + * A local variable in the tree IR.
|
| + *
|
| + * All tree IR variables are mutable, and may in Dart-mode be referenced inside
|
| + * nested functions.
|
| + *
|
| + * To use a variable as an expression, reference it from a [VariableUse], with
|
| + * one [VariableUse] per expression.
|
| + *
|
| + * [Variable]s are reference counted. The node constructors [VariableUse],
|
| + * [Assign], [FunctionDefinition] automatically update the reference count
|
| + * for their variables, but when transforming the tree, the transformer is
|
| + * responsible for updating reference counts.
|
| */
|
| -class Variable extends Expression {
|
| +class Variable extends Node {
|
| /// Function that declares this variable.
|
| ExecutableElement host;
|
|
|
| @@ -94,6 +105,7 @@ class Variable extends Expression {
|
| /// Different variables may have the same entity. May be null.
|
| Entity element;
|
|
|
| + /// Number of places where this variable occurs in a [VariableUse].
|
| int readCount = 0;
|
|
|
| /// Number of places where this variable occurs as:
|
| @@ -105,9 +117,21 @@ class Variable extends Expression {
|
| Variable(this.host, this.element) {
|
| assert(host != null);
|
| }
|
| +}
|
| +
|
| +/// Read the value of a variable.
|
| +class VariableUse extends Expression {
|
| + Variable variable;
|
| +
|
| + /// Creates a use of [variable] and updates its `readCount`.
|
| + VariableUse(this.variable) {
|
| + variable.readCount++;
|
| + }
|
|
|
| - accept(ExpressionVisitor visitor) => visitor.visitVariable(this);
|
| - accept1(ExpressionVisitor1 visitor, arg) => visitor.visitVariable(this, arg);
|
| + accept(ExpressionVisitor visitor) => visitor.visitVariableUse(this);
|
| + accept1(ExpressionVisitor1 visitor, arg) {
|
| + return visitor.visitVariableUse(this, arg);
|
| + }
|
| }
|
|
|
| /**
|
| @@ -498,6 +522,7 @@ class Assign extends Statement {
|
| /// Variable declarations themselves are hoisted to function level.
|
| bool isDeclaration;
|
|
|
| + /// Creates an assignment to [variable] and updates its `writeCount`.
|
| Assign(this.variable, this.definition, this.next,
|
| { this.isDeclaration: false }) {
|
| variable.writeCount++;
|
| @@ -602,8 +627,13 @@ class FunctionDefinition extends Node implements ExecutableDefinition {
|
| final List<ConstDeclaration> localConstants;
|
| final List<ConstantExpression> defaultParameterValues;
|
|
|
| + /// Creates a function definition and updates `writeCount` for [parameters].
|
| FunctionDefinition(this.element, this.parameters, this.body,
|
| - this.localConstants, this.defaultParameterValues);
|
| + this.localConstants, this.defaultParameterValues) {
|
| + for (Variable param in parameters) {
|
| + param.writeCount++; // Being a parameter counts as a write.
|
| + }
|
| + }
|
|
|
| /// Returns `true` if this function is abstract.
|
| ///
|
| @@ -700,7 +730,7 @@ class SetField extends Statement implements JsSpecificNode {
|
|
|
| abstract class ExpressionVisitor<E> {
|
| E visitExpression(Expression e) => e.accept(this);
|
| - E visitVariable(Variable node);
|
| + E visitVariableUse(VariableUse node);
|
| E visitInvokeStatic(InvokeStatic node);
|
| E visitInvokeMethod(InvokeMethod node);
|
| E visitInvokeMethodDirectly(InvokeMethodDirectly node);
|
| @@ -725,7 +755,7 @@ abstract class ExpressionVisitor<E> {
|
|
|
| abstract class ExpressionVisitor1<E, A> {
|
| E visitExpression(Expression e, A arg) => e.accept1(this, arg);
|
| - E visitVariable(Variable node, A arg);
|
| + E visitVariableUse(VariableUse node, A arg);
|
| E visitInvokeStatic(InvokeStatic node, A arg);
|
| E visitInvokeMethod(InvokeMethod node, A arg);
|
| E visitInvokeMethodDirectly(InvokeMethodDirectly node, A arg);
|
| @@ -792,11 +822,16 @@ abstract class Visitor1<S, E, A> implements ExpressionVisitor1<E, A>,
|
|
|
| class RecursiveVisitor extends Visitor {
|
| visitFunctionDefinition(FunctionDefinition node) {
|
| + node.parameters.forEach(visitVariable);
|
| visitStatement(node.body);
|
| }
|
|
|
| visitVariable(Variable node) {}
|
|
|
| + visitVariableUse(VariableUse node) {
|
| + visitVariable(node.variable);
|
| + }
|
| +
|
| visitInvokeStatic(InvokeStatic node) {
|
| node.arguments.forEach(visitExpression);
|
| }
|
|
|