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 8999b560ac409ab9ed3bfebc9346aa88dbe8a664..02b963eb6b3231088104bb2d22cc68af3c6c179b 100644 |
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart |
@@ -4,7 +4,6 @@ |
library dart2js.ir_nodes; |
import 'dart:collection'; |
-import 'cps_fragment.dart' show CpsFragment; |
import '../constants/values.dart' as values; |
import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; |
import '../elements/elements.dart'; |
@@ -204,7 +203,18 @@ class EffectiveUseIterable extends IterableBase<Reference<Primitive>> { |
/// |
/// All primitives except [Parameter] must be bound by a [LetPrim]. |
abstract class Primitive extends Variable<Primitive> { |
- Primitive() : super(null); |
+ /// The [VariableElement] or [ParameterElement] from which the primitive |
+ /// binding originated. |
+ Entity hint; |
+ |
+ /// 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(Entity hint) { |
+ if (this.hint == null) { |
+ this.hint = hint; |
+ } |
+ } |
/// True if this primitive has a value that can be used by other expressions. |
bool get hasValue; |
@@ -285,23 +295,6 @@ abstract class Primitive extends Variable<Primitive> { |
newDefinition.parent = let; |
newDefinition.useElementAsHint(hint); |
} |
- |
- /// Replaces this definition with a CPS fragment (a term with a hole in it), |
- /// given the value to replace the uses of the definition with. |
- /// |
- /// This can be thought of as substituting: |
- /// |
- /// let x = OLD in BODY |
- /// ==> |
- /// FRAGMENT[BODY{newPrimitive/x}] |
- void replaceWithFragment(CpsFragment fragment, Primitive newPrimitive) { |
- assert(this is! Parameter); |
- replaceUsesWith(newPrimitive); |
- destroy(); |
- LetPrim let = parent; |
- fragment.insertBelow(let); |
- let.remove(); |
- } |
} |
/// A primitive that is generally not safe for elimination, but may be marked |
@@ -471,43 +464,6 @@ class LetMutable extends InteriorExpression { |
} |
} |
-enum CallingConvention { |
- /// JS receiver is the Dart receiver, there are no extra arguments. |
- /// |
- /// This includes cases (e.g., static functions, constructors) where there |
- /// is no receiver. |
- /// |
- /// For example: `foo.bar$1(x)` |
- Normal, |
- |
- /// JS receiver is an interceptor, the first argument is the Dart receiver. |
- /// |
- /// For example: `getInterceptor(foo).bar$1(foo, x)` |
- Intercepted, |
- |
- /// JS receiver is the Dart receiver, the first argument is a dummy value. |
- /// |
- /// For example: `foo.bar$1(0, x)` |
- DummyIntercepted, |
- |
- /// JS receiver is the Dart receiver, there are no extra arguments. |
- /// |
- /// Compiles to a one-shot interceptor, e.g: `J.bar$1(foo, x)` |
- OneShotIntercepted, |
-} |
- |
-/// Base class of function invocations. |
-/// |
-/// This class defines the common interface of function invocations. |
-abstract class InvocationPrimitive extends UnsafePrimitive { |
- Reference<Primitive> get receiver => null; |
- List<Reference<Primitive>> get arguments; |
- SourceInformation get sourceInformation; |
- |
- Reference<Primitive> get dartReceiverReference => null; |
- CallingConvention get callingConvention => CallingConvention.Normal; |
-} |
- |
/// Invoke a static function. |
/// |
/// All optional arguments declared by [target] are passed in explicitly, and |
@@ -516,7 +472,7 @@ abstract class InvocationPrimitive extends UnsafePrimitive { |
/// Discussion: |
/// All information in the [selector] is technically redundant; it will likely |
/// be removed. |
-class InvokeStatic extends InvocationPrimitive { |
+class InvokeStatic extends UnsafePrimitive { |
final FunctionElement target; |
final Selector selector; |
final List<Reference<Primitive>> arguments; |
@@ -542,6 +498,28 @@ class InvokeStatic extends InvocationPrimitive { |
} |
} |
+enum CallingConvention { |
+ /// JS receiver is the Dart receiver, there are no extra arguments. |
+ /// |
+ /// For example: `foo.bar$1(x)` |
+ Normal, |
+ |
+ /// JS receiver is an interceptor, the first argument is the Dart receiver. |
+ /// |
+ /// For example: `getInterceptor(foo).bar$1(foo, x)` |
+ Intercepted, |
+ |
+ /// JS receiver is the Dart receiver, the first argument is a dummy value. |
+ /// |
+ /// For example: `foo.bar$1(0, x)` |
+ DummyIntercepted, |
+ |
+ /// JS receiver is the Dart receiver, there are no extra arguments. |
+ /// |
+ /// Compiles to a one-shot interceptor, e.g: `J.bar$1(foo, x)` |
+ OneShotIntercepted, |
+} |
+ |
/// Invoke a method on an object. |
/// |
/// This includes getters, setters, operators, and index getter/setters. |
@@ -551,7 +529,7 @@ class InvokeStatic extends InvocationPrimitive { |
/// |
/// The [selector] records the names of named arguments. The value of named |
/// arguments occur at the end of the [arguments] list, in normalized order. |
-class InvokeMethod extends InvocationPrimitive { |
+class InvokeMethod extends UnsafePrimitive { |
Reference<Primitive> receiver; |
Selector selector; |
TypeMask mask; |
@@ -628,7 +606,7 @@ class InvokeMethod extends InvocationPrimitive { |
/// |
/// All optional arguments declared by [target] are passed in explicitly, and |
/// occur at the end of [arguments] list, in normalized order. |
-class InvokeMethodDirectly extends InvocationPrimitive { |
+class InvokeMethodDirectly extends UnsafePrimitive { |
Reference<Primitive> receiver; |
final FunctionElement target; |
final Selector selector; |
@@ -686,7 +664,7 @@ class InvokeMethodDirectly extends InvocationPrimitive { |
/// |
/// Note that [InvokeConstructor] does it itself allocate an object. |
/// The invoked constructor will do that using [CreateInstance]. |
-class InvokeConstructor extends InvocationPrimitive { |
+class InvokeConstructor extends UnsafePrimitive { |
final DartType dartType; |
final ConstructorElement target; |
final List<Reference<Primitive>> arguments; |
@@ -1710,24 +1688,13 @@ abstract class Variable<T extends Variable<T>> extends Definition<T> { |
/// |
/// Is `null` until initialized by type propagation. |
TypeMask type; |
- |
- /// The [VariableElement] or [ParameterElement] from which the variable |
- /// binding originated. |
- Entity hint; |
- |
- Variable(this.hint); |
- |
- /// 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(Entity hint) { |
- this.hint ??= hint; |
- } |
} |
/// Identifies a mutable variable. |
class MutableVariable extends Variable<MutableVariable> { |
- MutableVariable(Entity hint) : super(hint); |
+ Entity hint; |
+ |
+ MutableVariable(this.hint); |
accept(Visitor v) => v.visitMutableVariable(this); |
@@ -1907,23 +1874,23 @@ abstract class Visitor<T> { |
T visitLetHandler(LetHandler node); |
T visitLetMutable(LetMutable node); |
T visitInvokeContinuation(InvokeContinuation node); |
- T visitThrow(Throw node); |
- T visitRethrow(Rethrow node); |
- T visitBranch(Branch node); |
- T visitUnreachable(Unreachable node); |
- |
- // Definitions. |
T visitInvokeStatic(InvokeStatic node); |
T visitInvokeMethod(InvokeMethod node); |
T visitInvokeMethodDirectly(InvokeMethodDirectly node); |
T visitInvokeConstructor(InvokeConstructor node); |
+ T visitThrow(Throw node); |
+ T visitRethrow(Rethrow node); |
+ T visitBranch(Branch node); |
T visitTypeCast(TypeCast node); |
T visitSetMutable(SetMutable node); |
T visitSetStatic(SetStatic node); |
- T visitSetField(SetField node); |
T visitGetLazyStatic(GetLazyStatic node); |
+ T visitSetField(SetField node); |
+ T visitUnreachable(Unreachable node); |
T visitAwait(Await node); |
T visitYield(Yield node); |
+ |
+ // Definitions. |
T visitLiteralList(LiteralList node); |
T visitLiteralMap(LiteralMap node); |
T visitConstant(Constant node); |
@@ -2425,373 +2392,3 @@ class RemovalVisitor extends TrampolineRecursiveVisitor { |
(new RemovalVisitor()).visit(node); |
} |
} |
- |
-/// A visitor to copy instances of [Definition] or its subclasses, except for |
-/// instances of [Continuation]. |
-/// |
-/// The visitor maintains a map from original definitions to their copies. |
-/// When the [copy] method is called for a non-Continuation definition, |
-/// a copy is created, added to the map and returned as the result. Copying a |
-/// definition assumes that the definitions of all references have already |
-/// been copied by the same visitor. |
-class DefinitionCopyingVisitor extends Visitor<Definition> { |
- Map<Definition, Definition> _copies = <Definition, Definition>{}; |
- |
- /// Put a copy into the map. |
- /// |
- /// This method should be used instead of directly adding copies to the map. |
- Definition putCopy(Definition original, Definition copy) { |
- if (copy is Variable) { |
- Variable originalVariable = original; |
- copy.type = originalVariable.type; |
- copy.hint = originalVariable.hint; |
- } |
- return _copies[original] = copy; |
- } |
- |
- /// Get the copy of a [Reference]'s definition from the map. |
- Definition getCopy(Reference reference) => _copies[reference.definition]; |
- |
- /// Map a list of [Reference]s to the list of their definition's copies. |
- List<Definition> getList(List<Reference> list) => list.map(getCopy).toList(); |
- |
- /// Copy a non-[Continuation] [Definition]. |
- Definition copy(Definition node) { |
- assert (node is! Continuation); |
- return putCopy(node, visit(node)); |
- } |
- |
- Definition visit(Node node) => node.accept(this); |
- |
- Definition visitFunctionDefinition(FunctionDefinition node) {} |
- Definition visitLetPrim(LetPrim node) {} |
- Definition visitLetCont(LetCont node) {} |
- Definition visitLetHandler(LetHandler node) {} |
- Definition visitLetMutable(LetMutable node) {} |
- Definition visitInvokeContinuation(InvokeContinuation node) {} |
- Definition visitThrow(Throw node) {} |
- Definition visitRethrow(Rethrow node) {} |
- Definition visitBranch(Branch node) {} |
- Definition visitUnreachable(Unreachable node) {} |
- Definition visitContinuation(Continuation node) {} |
- |
- Definition visitInvokeStatic(InvokeStatic node) { |
- return new InvokeStatic(node.target, node.selector, getList(node.arguments), |
- node.sourceInformation); |
- } |
- |
- Definition visitInvokeMethod(InvokeMethod node) { |
- return new InvokeMethod(getCopy(node.receiver), node.selector, node.mask, |
- getList(node.arguments), |
- node.sourceInformation); |
- } |
- |
- Definition visitInvokeMethodDirectly(InvokeMethodDirectly node) { |
- return new InvokeMethodDirectly(getCopy(node.receiver), node.target, |
- node.selector, |
- getList(node.arguments), |
- node.sourceInformation); |
- } |
- |
- Definition visitInvokeConstructor(InvokeConstructor node) { |
- return new InvokeConstructor(node.dartType, node.target, node.selector, |
- getList(node.arguments), |
- node.sourceInformation); |
- } |
- |
- Definition visitTypeCast(TypeCast node) { |
- return new TypeCast(getCopy(node.value), node.dartType, |
- getList(node.typeArguments)); |
- } |
- |
- Definition visitSetMutable(SetMutable node) { |
- return new SetMutable(getCopy(node.variable), getCopy(node.value)); |
- } |
- |
- Definition visitSetStatic(SetStatic node) { |
- return new SetStatic(node.element, getCopy(node.value), |
- node.sourceInformation); |
- } |
- |
- Definition visitSetField(SetField node) { |
- return new SetField(getCopy(node.object), node.field, getCopy(node.value)); |
- } |
- |
- Definition visitGetLazyStatic(GetLazyStatic node) { |
- return new GetLazyStatic(node.element, node.sourceInformation); |
- } |
- |
- Definition visitAwait(Await node) { |
- return new Await(getCopy(node.input)); |
- } |
- |
- Definition visitYield(Yield node) { |
- return new Yield(getCopy(node.input), node.hasStar); |
- } |
- |
- Definition visitLiteralList(LiteralList node) { |
- return new LiteralList(node.dartType, getList(node.values)); |
- } |
- |
- Definition visitLiteralMap(LiteralMap node) { |
- List<LiteralMapEntry> entries = node.entries.map((LiteralMapEntry entry) { |
- return new LiteralMapEntry(getCopy(entry.key), getCopy(entry.value)); |
- }).toList(); |
- return new LiteralMap(node.dartType, entries); |
- } |
- |
- Definition visitConstant(Constant node) { |
- return new Constant(node.value, sourceInformation: node.sourceInformation); |
- } |
- |
- Definition visitGetMutable(GetMutable node) { |
- return new GetMutable(getCopy(node.variable)); |
- } |
- |
- Definition visitParameter(Parameter node) { |
- return new Parameter(node.hint); |
- } |
- |
- Definition visitMutableVariable(MutableVariable node) { |
- return new MutableVariable(node.hint); |
- } |
- |
- Definition visitGetStatic(GetStatic node) { |
- return new GetStatic(node.element, node.sourceInformation); |
- } |
- |
- Definition visitInterceptor(Interceptor node) { |
- return new Interceptor(getCopy(node.input), node.sourceInformation) |
- ..interceptedClasses.addAll(node.interceptedClasses); |
- } |
- |
- Definition visitCreateInstance(CreateInstance node) { |
- return new CreateInstance(node.classElement, getList(node.arguments), |
- getList(node.typeInformation), |
- node.sourceInformation); |
- } |
- |
- Definition visitGetField(GetField node) { |
- return new GetField(getCopy(node.object), node.field); |
- } |
- |
- Definition visitCreateBox(CreateBox node) { |
- return new CreateBox(); |
- } |
- |
- Definition visitReifyRuntimeType(ReifyRuntimeType node) { |
- return new ReifyRuntimeType(getCopy(node.value), node.sourceInformation); |
- } |
- |
- Definition visitReadTypeVariable(ReadTypeVariable node) { |
- return new ReadTypeVariable(node.variable, getCopy(node.target), |
- node.sourceInformation); |
- } |
- |
- Definition visitTypeExpression(TypeExpression node) { |
- return new TypeExpression(node.dartType, getList(node.arguments)); |
- } |
- |
- Definition visitCreateInvocationMirror(CreateInvocationMirror node) { |
- return new CreateInvocationMirror(node.selector, getList(node.arguments)); |
- } |
- |
- Definition visitTypeTest(TypeTest node) { |
- return new TypeTest(getCopy(node.value), node.dartType, |
- getList(node.typeArguments)); |
- } |
- |
- Definition visitTypeTestViaFlag(TypeTestViaFlag node) { |
- return new TypeTestViaFlag(getCopy(node.interceptor), node.dartType); |
- } |
- |
- Definition visitApplyBuiltinOperator(ApplyBuiltinOperator node) { |
- return new ApplyBuiltinOperator(node.operator, getList(node.arguments), |
- node.sourceInformation); |
- } |
- |
- Definition visitApplyBuiltinMethod(ApplyBuiltinMethod node) { |
- return new ApplyBuiltinMethod(node.method, getCopy(node.receiver), |
- getList(node.arguments), |
- node.sourceInformation, |
- receiverIsNotNull: node.receiverIsNotNull); |
- } |
- |
- Definition visitGetLength(GetLength node) { |
- return new GetLength(getCopy(node.object)); |
- } |
- |
- Definition visitGetIndex(GetIndex node) { |
- return new GetIndex(getCopy(node.object), getCopy(node.index)); |
- } |
- |
- Definition visitSetIndex(SetIndex node) { |
- return new SetIndex(getCopy(node.object), getCopy(node.index), |
- getCopy(node.value)); |
- } |
- |
- Definition visitRefinement(Refinement node) { |
- return new Refinement(getCopy(node.value), node.refineType); |
- } |
- |
- Definition visitBoundsCheck(BoundsCheck node) { |
- if (node.hasNoChecks) { |
- return new BoundsCheck.noCheck(getCopy(node.object), |
- node.sourceInformation); |
- } else { |
- return new BoundsCheck(getCopy(node.object), getCopy(node.index), |
- getCopy(node.length), |
- node.checks, |
- node.sourceInformation); |
- } |
- } |
- |
- Definition visitNullCheck(NullCheck node) { |
- return new NullCheck(getCopy(node.value), node.sourceInformation); |
- } |
- |
- Definition visitForeignCode(ForeignCode node) { |
- return new ForeignCode(node.codeTemplate, node.type, |
- getList(node.arguments), |
- node.nativeBehavior, |
- dependency: node.dependency); |
- } |
-} |
- |
-/// A trampolining visitor to copy [FunctionDefinition]s. |
-class CopyingVisitor extends TrampolineRecursiveVisitor { |
- // The visitor maintains a map from original continuations to their copies. |
- Map<Continuation, Continuation> _copies = <Continuation, Continuation>{}; |
- |
- // The visitor uses an auxiliary visitor to copy definitions. |
- DefinitionCopyingVisitor _definitions = new DefinitionCopyingVisitor(); |
- |
- // While copying a block, the state of the visitor is a 'linked list' of |
- // the expressions in the block's body, with a pointer to the last element |
- // of the list. |
- Expression _first = null; |
- Expression _current = null; |
- |
- void plug(Expression body) { |
- if (_first == null) { |
- _first = body; |
- } else { |
- assert(_current != null); |
- InteriorExpression interior = _current; |
- interior.body = body; |
- } |
- _current = body; |
- } |
- |
- // Continuations are added to the visitor's stack to be visited after copying |
- // the current block is finished. The stack action saves the current block, |
- // copies the continuation's body, sets the body on the copy of the |
- // continuation, and restores the current block. |
- // |
- // Note that continuations are added to the copy map before the stack action |
- // to visit them is performed. |
- void push(Continuation cont) { |
- assert(!cont.isReturnContinuation); |
- _stack.add(() { |
- Expression savedFirst = _first; |
- _first = _current = null; |
- _processBlock(cont.body); |
- _copies[cont].body = _first; |
- _first = savedFirst; |
- _current = null; |
- }); |
- } |
- |
- FunctionDefinition copy(FunctionDefinition node) { |
- assert(_first == null && _current == null); |
- _first = _current = null; |
- // Definitions are copied where they are bound, before processing |
- // expressions in the scope of their binding. |
- Parameter thisParameter = node.thisParameter == null |
- ? null |
- : _definitions.copy(node.thisParameter); |
- List<Parameter> parameters = |
- node.parameters.map(_definitions.copy).toList(); |
- // Though the return continuation's parameter does not have any uses, |
- // we still make a proper copy to ensure that hints, type, etc. are |
- // copied. |
- Parameter returnParameter = |
- _definitions.copy(node.returnContinuation.parameters.first); |
- Continuation returnContinuation = _copies[node.returnContinuation] = |
- new Continuation([returnParameter]); |
- |
- visit(node.body); |
- FunctionDefinition copy = new FunctionDefinition(node.element, |
- thisParameter, |
- parameters, |
- returnContinuation, |
- _first); |
- _first = _current = null; |
- return copy; |
- } |
- |
- Node visit(Node node) => node.accept(this); |
- |
- Expression traverseLetCont(LetCont node) { |
- // Continuations are copied where they are bound, before processing |
- // expressions in the scope of their binding. |
- List<Continuation> continuations = node.continuations.map((Continuation c) { |
- push(c); |
- return _copies[c] = |
- new Continuation(c.parameters.map(_definitions.copy).toList()); |
- }).toList(); |
- plug(new LetCont.many(continuations, null)); |
- return node.body; |
- } |
- |
- Expression traverseLetHandler(LetHandler node) { |
- // Continuations are copied where they are bound, before processing |
- // expressions in the scope of their binding. |
- push(node.handler); |
- Continuation handler = _copies[node.handler] = |
- new Continuation(node.handler.parameters.map(_definitions.copy) |
- .toList()); |
- plug(new LetHandler(handler, null)); |
- return node.body; |
- } |
- |
- Expression traverseLetPrim(LetPrim node) { |
- plug(new LetPrim(_definitions.copy(node.primitive))); |
- return node.body; |
- } |
- |
- Expression traverseLetMutable(LetMutable node) { |
- plug(new LetMutable(_definitions.copy(node.variable), |
- _definitions.getCopy(node.value))); |
- return node.body; |
- } |
- |
- // Tail expressions do not have references, so we do not need to map them |
- // to their copies. |
- visitInvokeContinuation(InvokeContinuation node) { |
- plug(new InvokeContinuation(_copies[node.continuation.definition], |
- _definitions.getList(node.arguments), |
- isRecursive: node.isRecursive, |
- isEscapingTry: node.isEscapingTry, |
- sourceInformation: node.sourceInformation)); |
- } |
- |
- Node visitThrow(Throw node) { |
- plug(new Throw(_definitions.getCopy(node.value))); |
- } |
- |
- Node visitRethrow(Rethrow node) { |
- plug(new Rethrow()); |
- } |
- |
- Node visitBranch(Branch node) { |
- plug(new Branch.loose(_definitions.getCopy(node.condition), |
- _copies[node.trueContinuation.definition], |
- _copies[node.falseContinuation.definition]) |
- ..isStrictCheck = node.isStrictCheck); |
- } |
- |
- Node visitUnreachable(Unreachable node) { |
- plug(new Unreachable()); |
- } |
-} |