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

Unified Diff: sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart

Issue 366853007: dart2dart: Support for inner functions in new IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: SVN rebase Created 6 years, 6 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
Index: sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
diff --git a/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart b/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
index b5d25d38dc0b29a301e28584601206582005625c..039bd847e24dc644afbe06e25382ac80428c4e7f 100644
--- a/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ir/ir_nodes.dart
@@ -49,12 +49,16 @@ abstract class Definition extends Node {
}
}
-/// A pure expression that cannot throw or diverge.
+/// An expression that cannot throw or diverge and has no side-effects.
/// All primitives are named using the identity of the [Primitive] object.
+///
+/// Primitives may allocate objects, this is not considered side-effect here.
+///
+/// Although primitives may not mutate state, they may depend on state.
abstract class Primitive extends Definition {
/// The [VariableElement] or [ParameterElement] from which the primitive
/// binding originated.
- Element element;
+ Element hint;
/// Register in which the variable binding this primitive can be allocated.
/// Separate register spaces are used for primitives with different [element].
@@ -65,8 +69,8 @@ abstract class Primitive extends Definition {
///
/// Has no effect if this primitive already has a non-null [element].
void useElementAsHint(Element hint) {
- if (element == null) {
- element = hint;
+ if (this.hint == null) {
+ this.hint = hint;
}
}
}
@@ -256,6 +260,88 @@ class ConcatenateStrings extends Expression {
accept(Visitor visitor) => visitor.visitConcatenateStrings(this);
}
+/// Gets the value from a closure variable. The identity of the variable is
+/// determined by an [Element].
+///
+/// Closure variables can be seen as ref cells that are not first-class values.
+/// A [LetPrim] with a [GetClosureVariable] can then be seen as:
+///
+/// let prim p = ![variable] in [body]
+///
+class GetClosureVariable extends Primitive {
+ final Element variable;
+
+ GetClosureVariable(this.variable) {
+ assert(variable != null);
+ }
+
+ accept(Visitor visitor) => visitor.visitGetClosureVariable(this);
+}
+
+/// Assign or declare a closure variable. The identity of the variable is
+/// determined by an [Element].
+///
+/// Closure variables can be seen as ref cells that are not first-class values.
+/// If [isDeclaration], this can seen as a let binding:
+///
+/// let [variable] = ref [value] in [body]
+///
+/// And otherwise, it can be seen as a dereferencing assignment:
+///
+/// { ![variable] := [value]; [body] }
+///
+/// Closure variables without a declaring [SetClosureVariable] are implicitly
+/// declared at the entry to the [variable]'s enclosing function.
+class SetClosureVariable extends Expression {
+ final Element variable;
+ final Reference value;
+ Expression body;
+
+ /// If true, this declares a new copy of the closure variable. If so, all
+ /// uses of the closure variable must occur in the [body].
+ ///
+ /// There can be at most one declaration per closure variable. If there is no
+ /// declaration, only one copy exists (per function execution). It is best to
+ /// avoid declaring closure variables if it is not necessary.
+ final bool isDeclaration;
+
+ SetClosureVariable(this.variable, Primitive value,
+ {this.isDeclaration : false })
+ : this.value = new Reference(value) {
+ assert(variable != null);
+ }
+
+ accept(Visitor visitor) => visitor.visitSetClosureVariable(this);
+
+ Expression plug(Expression expr) {
+ assert(body == null);
+ return body = expr;
+ }
+}
+
+/// Create a potentially recursive function and store it in a closure variable.
+/// The function can access itself using [GetClosureVariable] on [variable].
+/// There must not exist a [SetClosureVariable] to [variable].
+///
+/// This can be seen as a let rec binding:
+///
+/// let rec [variable] = [definition] in [body]
+///
+class DeclareFunction extends Expression {
+ final Element variable;
+ final FunctionDefinition definition;
+ Expression body;
+
+ DeclareFunction(this.variable, this.definition);
+
+ Expression plug(Expression expr) {
+ assert(body == null);
+ return body = expr;
+ }
+
+ accept(Visitor visitor) => visitor.visitDeclareFunction(this);
+}
+
/// Invoke a continuation in tail position.
class InvokeContinuation extends Expression {
final Reference continuation;
@@ -319,9 +405,9 @@ class This extends Primitive {
/// Reify the given type variable as a [Type].
/// This depends on the current binding of 'this'.
class ReifyTypeVar extends Primitive {
- final TypeVariableElement element;
+ final TypeVariableElement typeVariable;
- ReifyTypeVar(this.element);
+ ReifyTypeVar(this.typeVariable);
dart2js.Constant get constant => null;
@@ -351,6 +437,15 @@ class LiteralMap extends Primitive {
accept(Visitor visitor) => visitor.visitLiteralMap(this);
}
+/// Create a non-recursive function.
+class CreateFunction extends Primitive {
+ final FunctionDefinition definition;
+
+ CreateFunction(this.definition);
+
+ accept(Visitor visitor) => visitor.visitCreateFunction(this);
+}
+
class IsCheck extends Primitive {
final Reference receiver;
final DartType type;
@@ -365,7 +460,7 @@ class IsCheck extends Primitive {
class Parameter extends Primitive {
Parameter(Element element) {
- super.element = element;
+ super.hint = element;
}
accept(Visitor visitor) => visitor.visitParameter(this);
@@ -391,13 +486,14 @@ class Continuation extends Definition {
/// A function definition, consisting of parameters and a body. The parameters
/// include a distinguished continuation parameter.
class FunctionDefinition extends Node {
+ final FunctionElement element;
final Continuation returnContinuation;
final List<Parameter> parameters;
final Expression body;
final List<ConstDeclaration> localConstants;
- FunctionDefinition(this.returnContinuation, this.parameters, this.body,
- this.localConstants);
+ FunctionDefinition(this.element, this.returnContinuation,
+ this.parameters, this.body, this.localConstants);
accept(Visitor visitor) => visitor.visitFunctionDefinition(this);
}
@@ -429,6 +525,8 @@ abstract class Visitor<T> {
T visitConcatenateStrings(ConcatenateStrings node) => visitExpression(node);
T visitBranch(Branch node) => visitExpression(node);
T visitAsCast(AsCast node) => visitExpression(node);
+ T visitSetClosureVariable(SetClosureVariable node) => visitExpression(node);
+ T visitDeclareFunction(DeclareFunction node) => visitExpression(node);
// Definitions.
T visitLiteralList(LiteralList node) => visitPrimitive(node);
@@ -437,6 +535,8 @@ abstract class Visitor<T> {
T visitConstant(Constant node) => visitPrimitive(node);
T visitThis(This node) => visitPrimitive(node);
T visitReifyTypeVar(ReifyTypeVar node) => visitPrimitive(node);
+ T visitCreateFunction(CreateFunction node) => visitPrimitive(node);
+ T visitGetClosureVariable(GetClosureVariable node) => visitPrimitive(node);
T visitParameter(Parameter node) => visitPrimitive(node);
T visitContinuation(Continuation node) => visitDefinition(node);
@@ -563,7 +663,12 @@ class SExpressionStringifier extends Visitor<String> {
}
String visitReifyTypeVar(ReifyTypeVar node) {
- return '(ReifyTypeVar ${node.element.name})';
+ return '(ReifyTypeVar ${node.typeVariable.name})';
+ }
+
+ String visitCreateFunction(CreateFunction node) {
+ String function = visit(node.definition);
+ return '(CreateFunction ${node.definition.element} $function)';
}
String visitParameter(Parameter node) {
@@ -576,6 +681,22 @@ class SExpressionStringifier extends Visitor<String> {
return '(Unexpected Continuation)';
}
+ String visitGetClosureVariable(GetClosureVariable node) {
+ return '(GetClosureVariable ${node.variable.name})';
+ }
+
+ String visitSetClosureVariable(SetClosureVariable node) {
+ String value = names[node.value.definition];
+ String body = visit(node.body);
+ return '(SetClosureVariable ${node.variable.name} $value $body)';
+ }
+
+ String visitDeclareFunction(DeclareFunction node) {
+ String function = visit(node.definition);
+ String body = visit(node.body);
+ return '(DeclareFunction ${node.variable} = $function in $body)';
+ }
+
String visitIsTrue(IsTrue node) {
String value = names[node.value.definition];
return '(IsTrue $value)';
@@ -624,15 +745,15 @@ class RegisterAllocator extends Visitor {
void allocate(Primitive primitive) {
if (primitive.registerIndex == null) {
- primitive.registerIndex = getRegisterArray(primitive.element).makeIndex();
+ primitive.registerIndex = getRegisterArray(primitive.hint).makeIndex();
}
}
void release(Primitive primitive) {
// Do not share indices for temporaries as this may obstruct inlining.
- if (primitive.element == null) return;
+ if (primitive.hint == null) return;
if (primitive.registerIndex != null) {
- getRegisterArray(primitive.element).releaseIndex(primitive.registerIndex);
+ getRegisterArray(primitive.hint).releaseIndex(primitive.registerIndex);
}
}
@@ -714,6 +835,23 @@ class RegisterAllocator extends Visitor {
void visitReifyTypeVar(ReifyTypeVar node) {
}
+ void visitCreateFunction(CreateFunction node) {
+ new RegisterAllocator().visit(node.definition);
+ }
+
+ void visitGetClosureVariable(GetClosureVariable node) {
+ }
+
+ void visitSetClosureVariable(SetClosureVariable node) {
+ visit(node.body);
+ visitReference(node.value);
+ }
+
+ void visitDeclareFunction(DeclareFunction node) {
+ new RegisterAllocator().visit(node.definition);
+ visit(node.body);
+ }
+
void visitParameter(Parameter node) {
throw "Parameters should not be visited by RegisterAllocator";
}

Powered by Google App Engine
This is Rietveld 408576698