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

Unified Diff: pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart

Issue 2246623002: Delete CPS IR (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 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: pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
deleted file mode 100644
index a152f3b787987f28160974093851bcbb98f8e767..0000000000000000000000000000000000000000
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ /dev/null
@@ -1,773 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// 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 tree_ir_builder;
-
-import '../common.dart';
-import '../constants/values.dart';
-import '../cps_ir/cps_ir_nodes.dart' as cps_ir;
-import '../elements/elements.dart';
-import '../io/source_information.dart';
-import '../js_backend/codegen/glue.dart';
-import 'tree_ir_nodes.dart';
-
-typedef Statement NodeCallback(Statement next);
-
-/**
- * Builder translates from CPS-based IR to direct-style Tree.
- *
- * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced
- * non-exit continuation `Cont(v, body)` is translated into a direct-style call
- * whose value is bound in the continuation body:
- *
- * `LetVal(v, Invoke(fun, args), body)`
- *
- * and the continuation definition is eliminated. A similar translation is
- * applied to continuation invocations where the continuation is
- * singly-referenced, though such invocations should not appear in optimized
- * IR.
- *
- * A call `Invoke(fun, cont, args)`, where cont is multiply referenced, is
- * translated into a call followed by a jump with an argument:
- *
- * `Jump L(Invoke(fun, args))`
- *
- * and the continuation is translated into a named block that takes an
- * argument:
- *
- * `LetLabel(L, v, body)`
- *
- * Block arguments are later replaced with data flow during the Tree-to-Tree
- * translation out of SSA. Jumps are eliminated during the Tree-to-Tree
- * control-flow recognition.
- *
- * Otherwise, the output of Builder looks very much like the input. In
- * particular, intermediate values and blocks used for local control flow are
- * still all named.
- */
-class Builder implements cps_ir.Visitor/*<NodeCallback|Node>*/ {
- final InternalErrorFunction internalError;
- final Glue glue;
-
- final Map<cps_ir.Primitive, Variable> primitive2variable =
- <cps_ir.Primitive, Variable>{};
- final Map<cps_ir.MutableVariable, Variable> mutable2variable =
- <cps_ir.MutableVariable, Variable>{};
- final Set<cps_ir.Constant> inlinedConstants = new Set<cps_ir.Constant>();
-
- // Continuations with more than one use are replaced with Tree labels. This
- // is the mapping from continuations to labels.
- final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{};
-
- ExecutableElement currentElement;
-
- /// The parameter to be translated to 'this'. This can either be the receiver
- /// parameter, the interceptor parameter, or null if the method has neither.
- cps_ir.Parameter thisParameter;
- cps_ir.Continuation returnContinuation;
-
- Builder(this.internalError, this.glue);
-
- /// Variable used in [buildPhiAssignments] as a temporary when swapping
- /// variables.
- Variable phiTempVar;
-
- Variable addMutableVariable(cps_ir.MutableVariable irVariable) {
- assert(!mutable2variable.containsKey(irVariable));
- Variable variable = new Variable(currentElement, irVariable.hint);
- mutable2variable[irVariable] = variable;
- return variable;
- }
-
- Variable getMutableVariable(cps_ir.MutableVariable mutableVariable) {
- return mutable2variable[mutableVariable];
- }
-
- VariableUse getMutableVariableUse(
- cps_ir.Reference<cps_ir.MutableVariable> reference,
- SourceInformation sourceInformation) {
- Variable variable = getMutableVariable(reference.definition);
- return new VariableUse(variable, sourceInformation: sourceInformation);
- }
-
- /// Obtains the variable representing the given primitive. Returns null for
- /// primitives that have no reference and do not need a variable.
- Variable getVariable(cps_ir.Primitive primitive) {
- primitive = primitive.effectiveDefinition;
- return primitive2variable.putIfAbsent(
- primitive, () => new Variable(currentElement, primitive.hint));
- }
-
- /// Obtains a reference to the tree Variable corresponding to the IR primitive
- /// referred to by [reference].
- /// This increments the reference count for the given variable, so the
- /// returned expression must be used in the tree.
- Expression getVariableUse(cps_ir.Reference<cps_ir.Primitive> reference,
- {SourceInformation sourceInformation}) {
- cps_ir.Primitive prim = reference.definition.effectiveDefinition;
- if (prim is cps_ir.Constant && inlinedConstants.contains(prim)) {
- return new Constant(prim.value);
- }
- if (thisParameter != null && prim == thisParameter) {
- return new This();
- }
- return new VariableUse(getVariable(prim),
- sourceInformation: sourceInformation);
- }
-
- Expression getVariableUseOrNull(
- cps_ir.Reference<cps_ir.Primitive> reference) {
- return reference == null ? null : getVariableUse(reference);
- }
-
- Label getLabel(cps_ir.Continuation cont) {
- return labels.putIfAbsent(cont, () => new Label());
- }
-
- FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) {
- currentElement = node.element;
- List<Variable> parameters = node.parameters.map(getVariable).toList();
- if (node.interceptorParameter != null) {
- parameters.insert(0, getVariable(node.receiverParameter));
- thisParameter = glue.methodUsesReceiverArgument(node.element)
- ? node.interceptorParameter
- : node.receiverParameter;
- } else {
- thisParameter = node.receiverParameter;
- }
- returnContinuation = node.returnContinuation;
- phiTempVar = new Variable(node.element, null);
- Statement body = translateExpression(node.body);
- return new FunctionDefinition(node.element, parameters, body,
- sourceInformation: node.sourceInformation);
- }
-
- /// Returns a list of variables corresponding to the arguments to a method
- /// call or similar construct.
- ///
- /// The `readCount` for these variables will be incremented.
- ///
- /// The list will be typed as a list of [Expression] to allow inplace updates
- /// on the list during the rewrite phases.
- List<Expression> translateArguments(List<cps_ir.Reference> args) {
- return new List<Expression>.generate(
- args.length, (int index) => getVariableUse(args[index]),
- growable: false);
- }
-
- /// Simultaneously assigns each argument to the corresponding parameter,
- /// then continues at the statement created by [buildRest].
- Statement buildPhiAssignments(List<cps_ir.Parameter> parameters,
- List<Expression> arguments, Statement buildRest()) {
- assert(parameters.length == arguments.length);
- // We want a parallel assignment to all parameters simultaneously.
- // Since we do not have parallel assignments in dart_tree, we must linearize
- // the assignments without attempting to read a previously-overwritten
- // value. For example {x,y = y,x} cannot be linearized to {x = y; y = x},
- // for this we must introduce a temporary variable: {t = x; x = y; y = t}.
-
- // [rightHand] is the inverse of [arguments], that is, it maps variables
- // to the assignments on which is occurs as the right-hand side.
- Map<Variable, List<int>> rightHand = <Variable, List<int>>{};
- for (int i = 0; i < parameters.length; i++) {
- Variable param = getVariable(parameters[i]);
- Expression arg = arguments[i];
- if (arg is VariableUse) {
- if (param == null || param == arg.variable) {
- // No assignment necessary.
- --arg.variable.readCount;
- continue;
- }
- // v1 = v0
- List<int> list = rightHand[arg.variable];
- if (list == null) {
- rightHand[arg.variable] = list = <int>[];
- }
- list.add(i);
- } else {
- // v1 = this;
- }
- }
-
- Statement first, current;
- void addAssignment(Variable dst, Expression src) {
- if (first == null) {
- first = current = Assign.makeStatement(dst, src);
- } else {
- current = current.next = Assign.makeStatement(dst, src);
- }
- }
-
- List<Expression> assignmentSrc = new List<Expression>(parameters.length);
- List<bool> done = new List<bool>.filled(parameters.length, false);
- void visitAssignment(int i) {
- if (done[i]) {
- return;
- }
- Variable param = getVariable(parameters[i]);
- Expression arg = arguments[i];
- if (param == null || (arg is VariableUse && param == arg.variable)) {
- return; // No assignment necessary.
- }
- if (assignmentSrc[i] != null) {
- // Cycle found; store argument in a temporary variable.
- // The temporary will then be used as right-hand side when the
- // assignment gets added.
- VariableUse source = assignmentSrc[i];
- if (source.variable != phiTempVar) {
- // Only move to temporary once.
- assignmentSrc[i] = new VariableUse(phiTempVar);
- addAssignment(phiTempVar, arg);
- }
- return;
- }
- assignmentSrc[i] = arg;
- List<int> paramUses = rightHand[param];
- if (paramUses != null) {
- for (int useIndex in paramUses) {
- visitAssignment(useIndex);
- }
- }
- addAssignment(param, assignmentSrc[i]);
- done[i] = true;
- }
-
- for (int i = 0; i < parameters.length; i++) {
- if (!done[i]) {
- visitAssignment(i);
- }
- }
-
- if (first == null) {
- first = buildRest();
- } else {
- current.next = buildRest();
- }
- return first;
- }
-
- visit(cps_ir.Node node) => throw 'Use translateXXX instead of visit';
-
- /// Translates a CPS expression into a tree statement.
- ///
- /// To avoid deep recursion, we traverse each basic blocks without
- /// recursion.
- ///
- /// Non-tail expressions evaluate to a callback to be invoked once the
- /// successor statement has been constructed. These callbacks are stored
- /// in a stack until the block's tail expression has been translated.
- Statement translateExpression(cps_ir.Expression node) {
- List<NodeCallback> stack = <NodeCallback>[];
- while (node is! cps_ir.TailExpression) {
- stack.add(node.accept(this));
- node = node.next;
- }
- Statement result = node.accept(this); // Translate the tail expression.
- for (NodeCallback fun in stack.reversed) {
- result = fun(result);
- }
- return result;
- }
-
- /// Translates a CPS primitive to a tree expression.
- ///
- /// This simply calls the visit method for the primitive.
- translatePrimitive(cps_ir.Primitive prim) {
- return prim.accept(this);
- }
-
- /************************ CONSTANT COPYING *****************************/
-
- /// Estimate of the number of characters needed to emit a use of the given
- /// constant.
- int constantSize(PrimitiveConstantValue value) {
- // TODO(asgerf): We could interface with the emitter to get the exact size.
- if (value is StringConstantValue) {
- // Account for the quotes, but ignore the cost of encoding non-ASCII
- // characters to avoid traversing the string and depending on encoding.
- return value.length + 2;
- } else if (value is BoolConstantValue) {
- return 2; // Printed as !0 and !1 when minified
- } else {
- // TODO(asgerf): Get the exact length of numbers using '1e10' notation.
- return '${value.primitiveValue}'.length;
- }
- }
-
- /// The number of uses [prim] has, or `-1` if it is used in a phi assignment.
- int countNonPhiUses(cps_ir.Primitive prim) {
- int count = 0;
- for (cps_ir.Reference ref = prim.firstRef; ref != null; ref = ref.next) {
- cps_ir.Node use = ref.parent;
- if (use is cps_ir.InvokeContinuation) {
- return -1;
- }
- count++;
- }
- return count;
- }
-
- /// True if the given [constant] should be copied to every use site.
- bool shouldCopyToUses(cps_ir.Constant constant) {
- if (!constant.value.isPrimitive) return false;
- if (constant.hasAtMostOneUse) return true;
- int uses = countNonPhiUses(constant);
- if (uses == -1) return false; // Copying might prevent elimination of a phi.
- int size = constantSize(constant.value);
- // Compare the expected code size output of copying vs sharing.
- const int USE = 2; // Minified locals usually have length 2.
- const int ASSIGN = USE + 2; // Variable and '=' and ';'
- const int BIAS = 2; // Artificial bias to slightly favor copying.
- int costOfSharing = USE * uses + size + ASSIGN + BIAS;
- int costOfCopying = size * uses;
- return costOfCopying <= costOfSharing;
- }
-
- /************************ INTERIOR EXPRESSIONS ************************/
- //
- // Visit methods for interior expressions must return a function:
- //
- // (Statement next) => <result statement>
- //
-
- NodeCallback visitLetPrim(cps_ir.LetPrim node) {
- if (node.primitive is cps_ir.Constant && shouldCopyToUses(node.primitive)) {
- inlinedConstants.add(node.primitive);
- return (Statement next) => next;
- }
- Variable variable = getVariable(node.primitive);
- var value = translatePrimitive(node.primitive);
- if (value is Expression) {
- if (node.primitive.hasAtLeastOneUse) {
- return (Statement next) => Assign.makeStatement(variable, value, next);
- } else {
- return (Statement next) => new ExpressionStatement(value, next);
- }
- } else {
- assert(value is NodeCallback);
- return value;
- }
- }
-
- // Continuations are bound at the same level, but they have to be
- // translated as if nested. This is because the body can invoke any
- // of them from anywhere, so it must be nested inside all of them.
- //
- // The continuation bodies are not always translated directly here because
- // they may have been already translated:
- // * For singly-used continuations, the continuation's body is
- // translated at the site of the continuation invocation.
- // * For recursive continuations, there is a single non-recursive
- // invocation. The continuation's body is translated at the site
- // of the non-recursive continuation invocation.
- // See [visitInvokeContinuation] for the implementation.
- NodeCallback visitLetCont(cps_ir.LetCont node) => (Statement next) {
- for (cps_ir.Continuation continuation in node.continuations) {
- // This happens after the body of the LetCont has been translated.
- // Labels are created on-demand if the continuation could not be inlined,
- // so the existence of the label indicates if a labeled statement should
- // be emitted.
- Label label = labels[continuation];
- if (label != null && !continuation.isRecursive) {
- // Recursively build the body. We only do this for join continuations,
- // so we should not risk overly deep recursion.
- next = new LabeledStatement(
- label, next, translateExpression(continuation.body));
- }
- }
- return next;
- };
-
- NodeCallback visitLetHandler(cps_ir.LetHandler node) => (Statement next) {
- List<Variable> catchParameters =
- node.handler.parameters.map(getVariable).toList();
- Statement catchBody = translateExpression(node.handler.body);
- return new Try(next, catchParameters, catchBody);
- };
-
- NodeCallback visitLetMutable(cps_ir.LetMutable node) {
- Variable variable = addMutableVariable(node.variable);
- Expression value = getVariableUse(node.valueRef);
- return (Statement next) => Assign.makeStatement(variable, value, next);
- }
-
- /************************** TAIL EXPRESSIONS **************************/
- //
- // Visit methods for tail expressions must return a statement directly
- // (not a function like interior and call expressions).
-
- Statement visitThrow(cps_ir.Throw node) {
- Expression value = getVariableUse(node.valueRef);
- return new Throw(value);
- }
-
- Statement visitUnreachable(cps_ir.Unreachable node) {
- return new Unreachable();
- }
-
- Statement visitInvokeContinuation(cps_ir.InvokeContinuation node) {
- // Invocations of the return continuation are translated to returns.
- // Other continuation invocations are replaced with assignments of the
- // arguments to formal parameter variables, followed by the body if
- // the continuation is singly reference or a break if it is multiply
- // referenced.
- cps_ir.Continuation cont = node.continuation;
- if (cont == returnContinuation) {
- assert(node.argumentRefs.length == 1);
- return new Return(getVariableUse(node.argumentRefs.single),
- sourceInformation: node.sourceInformation);
- } else {
- List<Expression> arguments = translateArguments(node.argumentRefs);
- return buildPhiAssignments(cont.parameters, arguments, () {
- // Translate invocations of recursive and non-recursive
- // continuations differently.
- // * Non-recursive continuations
- // - If there is one use, translate the continuation body
- // inline at the invocation site.
- // - If there are multiple uses, translate to Break.
- // * Recursive continuations
- // - There is a single non-recursive invocation. Translate
- // the continuation body inline as a labeled loop at the
- // invocation site.
- // - Translate the recursive invocations to Continue.
- if (cont.isRecursive) {
- return node.isRecursive
- ? new Continue(getLabel(cont))
- : new WhileTrue(getLabel(cont), translateExpression(cont.body));
- } else {
- return cont.hasExactlyOneUse && !node.isEscapingTry
- ? translateExpression(cont.body)
- : new Break(getLabel(cont));
- }
- });
- }
- }
-
- /// Translates a branch condition to a tree expression.
- Expression translateCondition(cps_ir.Branch branch) {
- Expression value = getVariableUse(branch.conditionRef,
- sourceInformation: branch.sourceInformation);
- if (branch.isStrictCheck) {
- return new ApplyBuiltinOperator(
- BuiltinOperator.StrictEq,
- <Expression>[value, new Constant(new TrueConstantValue())],
- branch.sourceInformation);
- } else {
- return value;
- }
- }
-
- Statement visitBranch(cps_ir.Branch node) {
- Expression condition = translateCondition(node);
- Statement thenStatement, elseStatement;
- cps_ir.Continuation cont = node.trueContinuation;
- assert(cont.parameters.isEmpty);
- thenStatement = cont.hasExactlyOneUse
- ? translateExpression(cont.body)
- : new Break(labels[cont]);
- cont = node.falseContinuation;
- assert(cont.parameters.isEmpty);
- elseStatement = cont.hasExactlyOneUse
- ? translateExpression(cont.body)
- : new Break(labels[cont]);
- return new If(
- condition, thenStatement, elseStatement, node.sourceInformation);
- }
-
- /************************** PRIMITIVES **************************/
- //
- // Visit methods for primitives must return an expression.
- //
-
- Expression visitSetField(cps_ir.SetField node) {
- return new SetField(getVariableUse(node.objectRef), node.field,
- getVariableUse(node.valueRef), node.sourceInformation);
- }
-
- Expression visitInterceptor(cps_ir.Interceptor node) {
- return new Interceptor(getVariableUse(node.inputRef),
- node.interceptedClasses, node.sourceInformation);
- }
-
- Expression visitCreateInstance(cps_ir.CreateInstance node) {
- return new CreateInstance(
- node.classElement,
- translateArguments(node.argumentRefs),
- getVariableUseOrNull(node.typeInformationRef),
- node.sourceInformation);
- }
-
- Expression visitGetField(cps_ir.GetField node) {
- return new GetField(
- getVariableUse(node.objectRef), node.field, node.sourceInformation,
- objectIsNotNull: !node.object.type.isNullable);
- }
-
- Expression visitCreateBox(cps_ir.CreateBox node) {
- return new CreateBox();
- }
-
- Expression visitCreateInvocationMirror(cps_ir.CreateInvocationMirror node) {
- return new CreateInvocationMirror(
- node.selector, translateArguments(node.argumentRefs));
- }
-
- Expression visitGetMutable(cps_ir.GetMutable node) {
- return getMutableVariableUse(node.variableRef, node.sourceInformation);
- }
-
- Expression visitSetMutable(cps_ir.SetMutable node) {
- Variable variable = getMutableVariable(node.variable);
- Expression value = getVariableUse(node.valueRef);
- return new Assign(variable, value,
- sourceInformation: node.sourceInformation);
- }
-
- Expression visitConstant(cps_ir.Constant node) {
- return new Constant(node.value, sourceInformation: node.sourceInformation);
- }
-
- Expression visitLiteralList(cps_ir.LiteralList node) {
- return new LiteralList(node.dartType, translateArguments(node.valueRefs));
- }
-
- Expression visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) {
- return new ReifyRuntimeType(
- getVariableUse(node.valueRef), node.sourceInformation);
- }
-
- Expression visitReadTypeVariable(cps_ir.ReadTypeVariable node) {
- return new ReadTypeVariable(
- node.variable, getVariableUse(node.targetRef), node.sourceInformation);
- }
-
- Expression visitTypeExpression(cps_ir.TypeExpression node) {
- return new TypeExpression(node.kind, node.dartType,
- node.argumentRefs.map(getVariableUse).toList());
- }
-
- Expression visitTypeTest(cps_ir.TypeTest node) {
- Expression value = getVariableUse(node.valueRef);
- List<Expression> typeArgs = translateArguments(node.typeArgumentRefs);
- return new TypeOperator(value, node.dartType, typeArgs, isTypeTest: true);
- }
-
- Expression visitTypeTestViaFlag(cps_ir.TypeTestViaFlag node) {
- Expression value = getVariableUse(node.interceptorRef);
- // TODO(sra): Move !! to cps_ir level.
- return new Not(new Not(new GetTypeTestProperty(value, node.dartType)));
- }
-
- Expression visitGetStatic(cps_ir.GetStatic node) {
- return new GetStatic(node.element, node.sourceInformation);
- }
-
- Expression visitSetStatic(cps_ir.SetStatic node) {
- return new SetStatic(
- node.element, getVariableUse(node.valueRef), node.sourceInformation);
- }
-
- Expression visitApplyBuiltinOperator(cps_ir.ApplyBuiltinOperator node) {
- if (node.operator == BuiltinOperator.IsFalsy) {
- return new Not(getVariableUse(node.argumentRefs.single));
- }
- return new ApplyBuiltinOperator(node.operator,
- translateArguments(node.argumentRefs), node.sourceInformation);
- }
-
- Expression visitApplyBuiltinMethod(cps_ir.ApplyBuiltinMethod node) {
- return new ApplyBuiltinMethod(node.method, getVariableUse(node.receiverRef),
- translateArguments(node.argumentRefs),
- receiverIsNotNull: !node.receiver.type.isNullable);
- }
-
- Expression visitGetLength(cps_ir.GetLength node) {
- return new GetLength(getVariableUse(node.objectRef));
- }
-
- Expression visitGetIndex(cps_ir.GetIndex node) {
- return new GetIndex(
- getVariableUse(node.objectRef), getVariableUse(node.indexRef));
- }
-
- Expression visitSetIndex(cps_ir.SetIndex node) {
- return new SetIndex(getVariableUse(node.objectRef),
- getVariableUse(node.indexRef), getVariableUse(node.valueRef));
- }
-
- Expression visitInvokeStatic(cps_ir.InvokeStatic node) {
- List<Expression> arguments = translateArguments(node.argumentRefs);
- return new InvokeStatic(
- node.target, node.selector, arguments, node.sourceInformation);
- }
-
- List<Expression> insertReceiverArgument(
- Expression receiver, List<Expression> arguments) {
- return new List<Expression>.generate(
- arguments.length + 1, (n) => n == 0 ? receiver : arguments[n - 1],
- growable: false);
- }
-
- Expression visitInvokeMethod(cps_ir.InvokeMethod node) {
- switch (node.callingConvention) {
- case cps_ir.CallingConvention.Normal:
- InvokeMethod invoke = new InvokeMethod(
- getVariableUse(node.receiverRef),
- node.selector,
- node.mask,
- translateArguments(node.argumentRefs),
- node.sourceInformation);
- invoke.receiverIsNotNull = !node.receiver.type.isNullable;
- return invoke;
-
- case cps_ir.CallingConvention.Intercepted:
- List<Expression> arguments = insertReceiverArgument(
- getVariableUse(node.receiverRef),
- translateArguments(node.argumentRefs));
- InvokeMethod invoke = new InvokeMethod(
- getVariableUse(node.interceptorRef),
- node.selector,
- node.mask,
- arguments,
- node.sourceInformation);
- // Sometimes we know the Dart receiver is non-null because it has been
- // refined, which implies that the JS receiver also can not be null at
- // the use-site. Interceptors are not refined, so this information is
- // not always available on the JS receiver.
- // Also check the JS receiver's type, however, because sometimes we know
- // an interceptor is non-null because it intercepts JSNull.
- invoke.receiverIsNotNull =
- !node.receiver.type.isNullable || !node.interceptor.type.isNullable;
- return invoke;
-
- case cps_ir.CallingConvention.DummyIntercepted:
- List<Expression> arguments = insertReceiverArgument(
- new Constant(new IntConstantValue(0)),
- translateArguments(node.argumentRefs));
- InvokeMethod invoke = new InvokeMethod(getVariableUse(node.receiverRef),
- node.selector, node.mask, arguments, node.sourceInformation);
- invoke.receiverIsNotNull = !node.receiver.type.isNullable;
- return invoke;
-
- case cps_ir.CallingConvention.OneShotIntercepted:
- List<Expression> arguments = insertReceiverArgument(
- getVariableUse(node.receiverRef),
- translateArguments(node.argumentRefs));
- return new OneShotInterceptor(
- node.selector, node.mask, arguments, node.sourceInformation);
- }
- }
-
- Expression visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) {
- if (node.interceptorRef != null) {
- return new InvokeMethodDirectly(
- getVariableUse(node.interceptorRef),
- node.target,
- node.selector,
- insertReceiverArgument(getVariableUse(node.receiverRef),
- translateArguments(node.argumentRefs)),
- node.sourceInformation);
- } else {
- return new InvokeMethodDirectly(
- getVariableUse(node.receiverRef),
- node.target,
- node.selector,
- translateArguments(node.argumentRefs),
- node.sourceInformation);
- }
- }
-
- Expression visitTypeCast(cps_ir.TypeCast node) {
- Expression value = getVariableUse(node.valueRef);
- List<Expression> typeArgs = translateArguments(node.typeArgumentRefs);
- return new TypeOperator(value, node.dartType, typeArgs, isTypeTest: false);
- }
-
- Expression visitInvokeConstructor(cps_ir.InvokeConstructor node) {
- List<Expression> arguments = translateArguments(node.argumentRefs);
- return new InvokeConstructor(node.dartType, node.target, node.selector,
- arguments, node.sourceInformation);
- }
-
- visitForeignCode(cps_ir.ForeignCode node) {
- List<Expression> arguments =
- node.argumentRefs.map(getVariableUse).toList(growable: false);
- List<bool> nullableArguments = node.argumentRefs
- .map((argument) => argument.definition.type.isNullable)
- .toList(growable: false);
- if (node.codeTemplate.isExpression) {
- return new ForeignExpression(
- node.codeTemplate,
- node.type,
- arguments,
- node.nativeBehavior,
- nullableArguments,
- node.dependency,
- node.sourceInformation);
- } else {
- return (Statement next) {
- assert(next is Unreachable); // We are not using the `next` statement.
- return new ForeignStatement(
- node.codeTemplate,
- node.type,
- arguments,
- node.nativeBehavior,
- nullableArguments,
- node.dependency,
- node.sourceInformation);
- };
- }
- }
-
- visitReceiverCheck(cps_ir.ReceiverCheck node) => (Statement next) {
- // The CPS IR uses 'isNullCheck' because the semantics are important.
- // In the Tree IR, syntax is more important, so the receiver check uses
- // "useInvoke" to denote if an invocation should be emitted.
- return new ReceiverCheck(
- condition: getVariableUseOrNull(node.conditionRef),
- value: getVariableUse(node.valueRef),
- selector: node.selector,
- useSelector: node.useSelector,
- useInvoke: !node.isNullCheck,
- next: next,
- sourceInformation: node.sourceInformation);
- };
-
- Expression visitGetLazyStatic(cps_ir.GetLazyStatic node) {
- return new GetStatic.lazy(node.element, node.sourceInformation);
- }
-
- @override
- NodeCallback visitYield(cps_ir.Yield node) {
- return (Statement next) {
- return new Yield(getVariableUse(node.inputRef), node.hasStar, next);
- };
- }
-
- @override
- Expression visitAwait(cps_ir.Await node) {
- return new Await(getVariableUse(node.inputRef));
- }
-
- @override
- visitRefinement(cps_ir.Refinement node) {
- return (Statement next) => next; // Compile to nothing.
- }
-
- /********** UNUSED VISIT METHODS *************/
-
- unexpectedNode(cps_ir.Node node) {
- internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node');
- }
-
- visitFunctionDefinition(cps_ir.FunctionDefinition node) {
- unexpectedNode(node);
- }
-
- visitParameter(cps_ir.Parameter node) => unexpectedNode(node);
- visitContinuation(cps_ir.Continuation node) => unexpectedNode(node);
- visitMutableVariable(cps_ir.MutableVariable node) => unexpectedNode(node);
- visitRethrow(cps_ir.Rethrow node) => unexpectedNode(node);
- visitBoundsCheck(cps_ir.BoundsCheck node) => unexpectedNode(node);
-}
« no previous file with comments | « pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart ('k') | pkg/compiler/lib/src/tree_ir/tree_ir_integrity.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698