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

Unified Diff: sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder_visitor.dart

Issue 651163004: Make cps_ir_builder_visitor a part. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 2 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 | « sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder_visitor.dart
diff --git a/sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart b/sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder_visitor.dart
similarity index 77%
copy from sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart
copy to sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder_visitor.dart
index 9c7b87d16dc78eea7c15ed8a529c08013d44ac3b..ae3babf3c0b01bd974e736f5e37ceb768a7e1b14 100644
--- a/sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder_visitor.dart
@@ -2,19 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library dart2js.ir_builder;
-
-import '../constants/expressions.dart';
-import '../constants/values.dart' show PrimitiveConstantValue;
-import '../dart_backend/dart_backend.dart' show DartBackend;
-import '../dart_types.dart';
-import '../dart2jslib.dart';
-import '../elements/elements.dart';
-import '../source_file.dart';
-import '../tree/tree.dart' as ast;
-import '../scanner/scannerlib.dart' show Token, isUserDefinableOperator;
-import '../universe/universe.dart' show SelectorKind;
-import 'cps_ir_nodes.dart' as ir;
+part of dart2js.ir_builder;
/**
* This task iterates through all resolved elements and builds [ir.Node]s. The
@@ -117,485 +105,6 @@ class _GetterElements {
_GetterElements({this.result, this.index, this.receiver}) ;
}
-/// A mapping from variable elements to their compile-time values.
-///
-/// Map elements denoted by parameters and local variables to the
-/// [ir.Primitive] that is their value. Parameters and locals are
-/// assigned indexes which can be used to refer to them.
-class Environment {
- /// A map from elements to their environment index.
- final Map<Element, int> variable2index;
-
- /// A reverse map from environment indexes to the variable.
- final List<Element> index2variable;
-
- /// A map from environment indexes to their value.
- final List<ir.Primitive> index2value;
-
- Environment.empty()
- : variable2index = <Element, int>{},
- index2variable = <Element>[],
- index2value = <ir.Primitive>[];
-
- /// Construct an environment that is a copy of another one.
- ///
- /// The mapping from elements to indexes is shared, not copied.
- Environment.from(Environment other)
- : variable2index = other.variable2index,
- index2variable = new List<Element>.from(other.index2variable),
- index2value = new List<ir.Primitive>.from(other.index2value);
-
- get length => index2variable.length;
-
- ir.Primitive operator [](int index) => index2value[index];
-
- void extend(Element element, ir.Primitive value) {
- // Assert that the name is not already in the environment. `null` is used
- // as the name of anonymous variables. Because the variable2index map is
- // shared, `null` can already occur. This is safe because such variables
- // are not looked up by name.
- //
- // TODO(kmillikin): This is still kind of fishy. Refactor to not share
- // name maps or else garbage collect unneeded names.
- assert(element == null || !variable2index.containsKey(element));
- variable2index[element] = index2variable.length;
- index2variable.add(element);
- index2value.add(value);
- }
-
- ir.Primitive lookup(Element element) {
- assert(!element.isConst);
- assert(invariant(element, variable2index.containsKey(element),
- message: "Unknown variable: $element."));
- return index2value[variable2index[element]];
- }
-
- void update(Element element, ir.Primitive value) {
- index2value[variable2index[element]] = value;
- }
-
- /// Verify that the variable2index and index2variable maps agree up to the
- /// index [length] exclusive.
- bool sameDomain(int length, Environment other) {
- assert(this.length >= length);
- assert(other.length >= length);
- for (int i = 0; i < length; ++i) {
- // An index maps to the same variable in both environments.
- Element variable = index2variable[i];
- if (variable != other.index2variable[i]) return false;
-
- // The variable maps to the same index in both environments.
- int index = variable2index[variable];
- if (index == null || index != other.variable2index[variable]) {
- return false;
- }
- }
- return true;
- }
-}
-
-/// A class to collect breaks or continues.
-///
-/// When visiting a potential target of breaks or continues, any breaks or
-/// continues are collected by a JumpCollector and processed later, on demand.
-/// The site of the break or continue is represented by a continuation
-/// invocation that will have its target and arguments filled in later.
-///
-/// The environment of the builder at that point is captured and should not
-/// be subsequently mutated until the jump is resolved.
-class JumpCollector {
- final JumpTarget target;
- final List<ir.InvokeContinuation> _invocations = <ir.InvokeContinuation>[];
- final List<Environment> _environments = <Environment>[];
-
- JumpCollector(this.target);
-
- bool get isEmpty => _invocations.isEmpty;
- int get length => _invocations.length;
- List<ir.InvokeContinuation> get invocations => _invocations;
- List<Environment> get environments => _environments;
-
- void addJump(IrBuilder builder) {
- ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized();
- builder.add(invoke);
- _invocations.add(invoke);
- _environments.add(builder.environment);
- builder._current = null;
- // TODO(kmillikin): Can we set builder.environment to null to make it
- // less likely to mutate it?
- }
-}
-
-/// Mixin that provided encapsulated access to nested builders.
-class IrBuilderMixin {
- IrBuilder _irBuilder;
-
- /// Execute [f] with [builder] as the current builder.
- withBuilder(IrBuilder builder, f()) {
- assert(builder != null);
- IrBuilder prev = _irBuilder;
- _irBuilder = builder;
- var result = f();
- _irBuilder = prev;
- return result;
- }
-
- /// The current builder.
- IrBuilder get irBuilder {
- assert(_irBuilder != null);
- return _irBuilder;
- }
-}
-
-
-/// Shared state between nested builders.
-class IrBuilderSharedState {
- final ConstantSystem constantSystem;
-
- /// A stack of collectors for breaks.
- final List<JumpCollector> breakCollectors = <JumpCollector>[];
-
- /// A stack of collectors for continues.
- final List<JumpCollector> continueCollectors = <JumpCollector>[];
-
- final List<ConstDeclaration> localConstants = <ConstDeclaration>[];
-
- final Iterable<Entity> closureLocals;
-
- final FunctionElement currentFunction;
-
- final ir.Continuation returnContinuation = new ir.Continuation.retrn();
-
- IrBuilderSharedState(this.constantSystem,
- this.currentFunction,
- this.closureLocals);
-}
-
-/// A factory for building the cps IR.
-class IrBuilder {
- // TODO(johnniwinther): Make these field final and remove the default values
- // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin.
-
- final List<ir.Parameter> _parameters = <ir.Parameter>[];
-
- final IrBuilderSharedState state;
-
- /// A map from variable indexes to their values.
- Environment environment;
-
- // The IR builder maintains a context, which is an expression with a hole in
- // it. The hole represents the focus where new expressions can be added.
- // The context is implemented by 'root' which is the root of the expression
- // and 'current' which is the expression that immediately contains the hole.
- // Not all expressions have a hole (e.g., invocations, which always occur in
- // tail position, do not have a hole). Expressions with a hole have a plug
- // method.
- //
- // Conceptually, visiting a statement takes a context as input and returns
- // either a new context or else an expression without a hole if all
- // control-flow paths through the statement have exited. An expression
- // without a hole is represented by a (root, current) pair where root is the
- // expression and current is null.
- //
- // Conceptually again, visiting an expression takes a context as input and
- // returns either a pair of a new context and a definition denoting
- // the expression's value, or else an expression without a hole if all
- // control-flow paths through the expression have exited.
- //
- // We do not pass contexts as arguments or return them. Rather we use the
- // current context (root, current) as the visitor state and mutate current.
- // Visiting a statement returns null; visiting an expression returns the
- // primitive denoting its value.
-
- ir.Expression _root = null;
- ir.Expression _current = null;
-
- IrBuilder(ConstantSystem constantSystem,
- FunctionElement currentFunction,
- Iterable<Entity> closureLocals)
- : this.state = new IrBuilderSharedState(
- constantSystem, currentFunction, closureLocals),
- this.environment = new Environment.empty();
-
- /// Construct a delimited visitor for visiting a subtree.
- ///
- /// The delimited visitor has its own compile-time environment mapping
- /// local variables to their values, which is initially a copy of the parent
- /// environment. It has its own context for building an IR expression, so
- /// the built expression is not plugged into the parent's context.
- IrBuilder.delimited(IrBuilder parent)
- : this.state = parent.state,
- this.environment = new Environment.from(parent.environment);
-
- /// Construct a visitor for a recursive continuation.
- ///
- /// The recursive continuation builder has fresh parameters (i.e. SSA phis)
- /// for all the local variables in the parent, because the invocation sites
- /// of the continuation are not all known when the builder is created. The
- /// recursive invocations will be passed values for all the local variables,
- /// which may be eliminated later if they are redundant---if they take on
- /// the same value at all invocation sites.
- IrBuilder.recursive(IrBuilder parent)
- : this.state = parent.state,
- this.environment = new Environment.empty() {
- parent.environment.index2variable.forEach(createParameter);
- }
-
-
- bool get isOpen => _root == null || _current != null;
-
- /// Create a parameter for [parameterElement] and add it to the current
- /// environment.
- ///
- /// [isClosureVariable] marks whether [parameterElement] is accessed from an
- /// inner function.
- void createParameter(LocalElement parameterElement,
- {bool isClosureVariable: false}) {
- ir.Parameter parameter = new ir.Parameter(parameterElement);
- _parameters.add(parameter);
- if (isClosureVariable) {
- add(new ir.SetClosureVariable(parameterElement, parameter));
- } else {
- environment.extend(parameterElement, parameter);
- }
- }
-
- /// Add the constant [variableElement] to the environment with [value] as its
- /// constant value.
- void declareLocalConstant(LocalVariableElement variableElement,
- ConstantExpression value) {
- state.localConstants.add(new ConstDeclaration(variableElement, value));
- }
-
- /// Add [variableElement] to the environment with [initialValue] as its
- /// initial value.
- ///
- /// [isClosureVariable] marks whether [variableElement] is accessed from an
- /// inner function.
- void declareLocalVariable(LocalVariableElement variableElement,
- {ir.Primitive initialValue,
- bool isClosureVariable: false}) {
- assert(isOpen);
- if (initialValue == null) {
- // TODO(kmillikin): Consider pooling constants.
- // The initial value is null.
- initialValue = makePrimConst(state.constantSystem.createNull());
- add(new ir.LetPrim(initialValue));
- }
- if (isClosureVariable) {
- add(new ir.SetClosureVariable(variableElement,
- initialValue,
- isDeclaration: true));
- } else {
- // In case a primitive was introduced for the initializer expression,
- // use this variable element to help derive a good name for it.
- initialValue.useElementAsHint(variableElement);
- environment.extend(variableElement, initialValue);
- }
- }
-
- // Plug an expression into the 'hole' in the context being accumulated. The
- // empty context (just a hole) is represented by root (and current) being
- // null. Since the hole in the current context is filled by this function,
- // the new hole must be in the newly added expression---which becomes the
- // new value of current.
- void add(ir.Expression expr) {
- assert(isOpen);
- if (_root == null) {
- _root = _current = expr;
- } else {
- _current = _current.plug(expr);
- }
- }
-
- ir.Primitive continueWithExpression(ir.Expression build(ir.Continuation k)) {
- ir.Parameter v = new ir.Parameter(null);
- ir.Continuation k = new ir.Continuation([v]);
- ir.Expression expression = build(k);
- add(new ir.LetCont(k, expression));
- return v;
- }
-
- ir.Constant makeConst(ConstantExpression exp) {
- return new ir.Constant(exp);
- }
-
- ir.Constant makePrimConst(PrimitiveConstantValue value) {
- return makeConst(new PrimitiveConstantExpression(value));
- }
-
- // TODO(johnniwinther): Build constants directly through [ConstExp] when these
- // are created from analyzer2dart.
- ir.Node buildPrimConst(PrimitiveConstantValue constant) {
- assert(isOpen);
- ir.Node prim = makePrimConst(constant);
- add(new ir.LetPrim(prim));
- return prim;
- }
-
- /// Create an integer literal.
- ir.Constant buildIntegerLiteral(int value) {
- return buildPrimConst(state.constantSystem.createInt(value));
- }
-
- /// Create an double literal.
- ir.Constant buildDoubleLiteral(double value) {
- return buildPrimConst(state.constantSystem.createDouble(value));
- }
-
- /// Create an bool literal.
- ir.Constant buildBooleanLiteral(bool value) {
- return buildPrimConst(state.constantSystem.createBool(value));
- }
-
- /// Create an null literal.
- ir.Constant buildNullLiteral() {
- return buildPrimConst(state.constantSystem.createNull());
- }
-
- /// Create a string literal.
- ir.Constant buildStringLiteral(String value) {
- return buildPrimConst(
- state.constantSystem.createString(new ast.DartString.literal(value)));
- }
-
- /// Create a get access of [local].
- ir.Primitive buildLocalGet(Element local) {
- assert(isOpen);
- return environment.lookup(local);
- }
-
- /// Create a get access of the static [element].
- ir.Primitive buildStaticGet(Element element, Selector selector) {
- assert(isOpen);
- assert(selector.isGetter);
- return continueWithExpression(
- (k) => new ir.InvokeStatic(
- element, selector, k, const <ir.Definition>[]));
- }
-
- /// Create a dynamic get access on [receiver] where the property is defined
- /// by the getter [selector].
- ir.Primitive buildDynamicGet(ir.Primitive receiver, Selector selector) {
- assert(isOpen);
- assert(selector.isGetter);
- return continueWithExpression(
- (k) => new ir.InvokeMethod(
- receiver, selector, k, const <ir.Definition>[]));
- }
-
- /**
- * Add an explicit `return null` for functions that don't have a return
- * statement on each branch. This includes functions with an empty body,
- * such as `foo(){ }`.
- */
- void ensureReturn() {
- if (!isOpen) return;
- ir.Constant constant = makePrimConst(state.constantSystem.createNull());
- add(new ir.LetPrim(constant));
- add(new ir.InvokeContinuation(state.returnContinuation, [constant]));
- _current = null;
- }
-
- /// Create a [ir.FunctionDefinition] for [element] using [_root] as the body.
- ///
- /// Parameters must be created before the construction of the body using
- /// [createParameter].
- ir.FunctionDefinition buildFunctionDefinition(
- FunctionElement element,
- List<ConstantExpression> defaults) {
- if (!element.isAbstract) {
- ensureReturn();
- return new ir.FunctionDefinition(
- element, state.returnContinuation, _parameters, _root,
- state.localConstants, defaults);
- } else {
- assert(invariant(element, _root == null,
- message: "Non-empty body for abstract method $element: $_root"));
- assert(invariant(element, state.localConstants.isEmpty,
- message: "Local constants for abstract method $element: "
- "${state.localConstants}"));
- return new ir.FunctionDefinition.abstract(
- element, _parameters, defaults);
- }
- }
-
-
- /// Create a super invocation with method name and arguments structure defined
- /// by [selector] and argument values defined by [arguments].
- ir.Primitive buildSuperInvocation(Selector selector,
- List<ir.Definition> arguments) {
- assert(isOpen);
- return continueWithExpression(
- (k) => new ir.InvokeSuperMethod(selector, k, arguments));
-
- }
-
- /// Create a dynamic invocation on [receiver] with method name and arguments
- /// structure defined by [selector] and argument values defined by
- /// [arguments].
- ir.Primitive buildDynamicInvocation(ir.Definition receiver,
- Selector selector,
- List<ir.Definition> arguments) {
- assert(isOpen);
- return continueWithExpression(
- (k) => new ir.InvokeMethod(receiver, selector, k, arguments));
- }
-
- /// Create a static invocation of [element] with arguments structure defined
- /// by [selector] and argument values defined by [arguments].
- ir.Primitive buildStaticInvocation(Element element,
- Selector selector,
- List<ir.Definition> arguments) {
- return continueWithExpression(
- (k) => new ir.InvokeStatic(element, selector, k, arguments));
- }
-
- /// Create a return statement `return value;` or `return;` if [value] is
- /// null.
- void buildReturn([ir.Primitive value]) {
- // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
- // where (C', x) = Build(e, C)
- //
- // Return without a subexpression is translated as if it were return null.
- assert(isOpen);
- if (value == null) {
- value = makePrimConst(state.constantSystem.createNull());
- add(new ir.LetPrim(value));
- }
- add(new ir.InvokeContinuation(state.returnContinuation, [value]));
- _current = null;
- }
-
- // Build(BreakStatement L, C) = C[InvokeContinuation(...)]
- //
- // The continuation and arguments are filled in later after translating
- // the body containing the break.
- bool buildBreak(JumpTarget target) {
- return buildJumpInternal(target, state.breakCollectors);
- }
-
- // Build(ContinueStatement L, C) = C[InvokeContinuation(...)]
- //
- // The continuation and arguments are filled in later after translating
- // the body containing the continue.
- bool buildContinue(JumpTarget target) {
- return buildJumpInternal(target, state.continueCollectors);
- }
-
- bool buildJumpInternal(JumpTarget target,
- Iterable<JumpCollector> collectors) {
- assert(isOpen);
- for (JumpCollector collector in collectors) {
- if (target == collector.target) {
- collector.addJump(this);
- return true;
- }
- }
- return false;
- }
-}
-
/**
* A tree visitor that builds [IrNodes]. The visit methods add statements using
* to the [builder] and return the last added statement for trees that represent
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698