| Index: pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| index 07bc61a0962c51b9aecb82e2c2e338ededeb5ba6..1d0d8a0d2901e5d1f6dd0a5c8037c9babd973063 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
|
| @@ -13,6 +13,7 @@ import '../elements/elements.dart';
|
| import '../universe/universe.dart' show Selector, SelectorKind;
|
| import '../dart_types.dart' show DartType, GenericType;
|
| import '../cps_ir/optimizers.dart';
|
| +import '../closure.dart' show ClosureClassElement;
|
|
|
| abstract class Node {
|
| /// A pointer to the parent node. Is null until set by optimization passes.
|
| @@ -59,7 +60,7 @@ abstract class Definition<T extends Definition<T>> extends Node {
|
| abstract class Primitive extends Definition<Primitive> {
|
| /// The [VariableElement] or [ParameterElement] from which the primitive
|
| /// binding originated.
|
| - Element hint;
|
| + Entity hint;
|
|
|
| /// Register in which the variable binding this primitive can be allocated.
|
| /// Separate register spaces are used for primitives with different [element].
|
| @@ -69,7 +70,7 @@ abstract class Primitive extends Definition<Primitive> {
|
| /// Use the given element as a hint for naming this primitive.
|
| ///
|
| /// Has no effect if this primitive already has a non-null [element].
|
| - void useElementAsHint(Element hint) {
|
| + void useElementAsHint(Entity hint) {
|
| if (this.hint == null) {
|
| this.hint = hint;
|
| }
|
| @@ -460,6 +461,55 @@ class Branch extends Expression {
|
| /// to the Tree IR, which is implemented in JsTreeBuilder.
|
| abstract class JsSpecificNode {}
|
|
|
| +/// Directly assigns to a field on a given object.
|
| +class SetField extends Expression implements JsSpecificNode {
|
| + final Reference<Primitive> object;
|
| + Element field;
|
| + final Reference<Primitive> value;
|
| + Expression body;
|
| +
|
| + SetField(Primitive object, this.field, Primitive value)
|
| + : this.object = new Reference<Primitive>(object),
|
| + this.value = new Reference<Primitive>(value);
|
| +
|
| + Expression plug(Expression expr) {
|
| + assert(body == null);
|
| + return body = expr;
|
| + }
|
| +
|
| + accept(Visitor visitor) => visitor.visitSetField(this);
|
| +}
|
| +
|
| +/// Directly reads from a field on a given object.
|
| +class GetField extends Primitive implements JsSpecificNode {
|
| + final Reference<Primitive> object;
|
| + Element field;
|
| +
|
| + GetField(Primitive object, this.field)
|
| + : this.object = new Reference<Primitive>(object);
|
| +
|
| + accept(Visitor visitor) => visitor.visitGetField(this);
|
| +}
|
| +
|
| +/// Creates an object for holding boxed variables captured by a closure.
|
| +class CreateBox extends Primitive implements JsSpecificNode {
|
| + accept(Visitor visitor) => visitor.visitCreateBox(this);
|
| +}
|
| +
|
| +/// Instantiates a synthetic class created by closure conversion.
|
| +class CreateClosureClass extends Primitive implements JsSpecificNode {
|
| + final ClosureClassElement classElement;
|
| +
|
| + /// Values and boxes for locals captured by the closure.
|
| + /// The order corresponds to [ClosureClassElement.closureFields].
|
| + final List<Reference<Primitive>> arguments;
|
| +
|
| + CreateClosureClass(this.classElement, List<Primitive> arguments)
|
| + : this.arguments = _referenceList(arguments);
|
| +
|
| + accept(Visitor visitor) => visitor.visitCreateClosureClass(this);
|
| +}
|
| +
|
| class Identical extends Primitive implements JsSpecificNode {
|
| final Reference<Primitive> left;
|
| final Reference<Primitive> right;
|
| @@ -544,8 +594,8 @@ class CreateFunction extends Primitive {
|
| }
|
|
|
| class Parameter extends Primitive {
|
| - Parameter(Element element) {
|
| - super.hint = element;
|
| + Parameter(Entity hint) {
|
| + super.hint = hint;
|
| }
|
|
|
| accept(Visitor visitor) => visitor.visitParameter(this);
|
| @@ -757,6 +807,7 @@ abstract class Visitor<T> {
|
| T visitTypeOperator(TypeOperator node) => visitExpression(node);
|
| T visitSetClosureVariable(SetClosureVariable node) => visitExpression(node);
|
| T visitDeclareFunction(DeclareFunction node) => visitExpression(node);
|
| + T visitSetField(SetField node) => visitExpression(node);
|
|
|
| // Definitions.
|
| T visitLiteralList(LiteralList node) => visitPrimitive(node);
|
| @@ -769,6 +820,9 @@ abstract class Visitor<T> {
|
| T visitParameter(Parameter node) => visitPrimitive(node);
|
| T visitContinuation(Continuation node) => visitDefinition(node);
|
| T visitClosureVariable(ClosureVariable node) => visitDefinition(node);
|
| + T visitGetField(GetField node) => visitDefinition(node);
|
| + T visitCreateBox(CreateBox node) => visitDefinition(node);
|
| + T visitCreateClosureClass(CreateClosureClass node) => visitDefinition(node);
|
|
|
| // Conditions.
|
| T visitIsTrue(IsTrue node) => visitCondition(node);
|
| @@ -998,6 +1052,31 @@ abstract class RecursiveVisitor extends Visitor {
|
| processInterceptor(node);
|
| processReference(node.input);
|
| }
|
| +
|
| + processCreateClosureClass(CreateClosureClass node) {}
|
| + visitCreateClosureClass(CreateClosureClass node) {
|
| + processCreateClosureClass(node);
|
| + node.arguments.forEach(processReference);
|
| + }
|
| +
|
| + processSetField(SetField node) {}
|
| + visitSetField(SetField node) {
|
| + processSetField(node);
|
| + processReference(node.object);
|
| + processReference(node.value);
|
| + visit(node.body);
|
| + }
|
| +
|
| + processGetField(GetField node) {}
|
| + visitGetField(GetField node) {
|
| + processGetField(node);
|
| + processReference(node.object);
|
| + }
|
| +
|
| + processCreateBox(CreateBox node) {}
|
| + visitCreateBox(CreateBox node) {
|
| + processCreateBox(node);
|
| + }
|
| }
|
|
|
| /// Keeps track of currently unused register indices.
|
| @@ -1027,15 +1106,14 @@ class RegisterArray {
|
| /// for removing all of the redundant variables.
|
| class RegisterAllocator extends Visitor {
|
| /// Separate register spaces for each source-level variable/parameter.
|
| - /// Note that null is used as key for primitives without elements.
|
| - final Map<Element, RegisterArray> elementRegisters =
|
| - <Element, RegisterArray>{};
|
| + /// Note that null is used as key for primitives without hints.
|
| + final Map<Local, RegisterArray> elementRegisters = <Local, RegisterArray>{};
|
|
|
| - RegisterArray getRegisterArray(Element element) {
|
| - RegisterArray registers = elementRegisters[element];
|
| + RegisterArray getRegisterArray(Local local) {
|
| + RegisterArray registers = elementRegisters[local];
|
| if (registers == null) {
|
| registers = new RegisterArray();
|
| - elementRegisters[element] = registers;
|
| + elementRegisters[local] = registers;
|
| }
|
| return registers;
|
| }
|
| @@ -1203,6 +1281,23 @@ class RegisterAllocator extends Visitor {
|
|
|
| // JavaScript specific nodes.
|
|
|
| + void visitSetField(SetField node) {
|
| + visit(node.body);
|
| + visitReference(node.value);
|
| + visitReference(node.object);
|
| + }
|
| +
|
| + void visitGetField(GetField node) {
|
| + visitReference(node.object);
|
| + }
|
| +
|
| + void visitCreateBox(CreateBox node) {
|
| + }
|
| +
|
| + void visitCreateClosureClass(CreateClosureClass node) {
|
| + node.arguments.forEach(visitReference);
|
| + }
|
| +
|
| void visitIdentical(Identical node) {
|
| visitReference(node.left);
|
| visitReference(node.right);
|
|
|