| Index: pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
|
| index a6017cbb0454226ec6fa6f9e4aa07b6abc4c049f..c06046b3cabbb77801c8616058cfc9fc9a77db14 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
|
| @@ -24,6 +24,9 @@ class ShrinkingReducer extends Pass {
|
| _worklist = new List<_ReductionTask>();
|
| _RedexVisitor redexVisitor = new _RedexVisitor(_worklist);
|
|
|
| + // Set all parent pointers.
|
| + new ParentVisitor().visit(root);
|
| +
|
| // Sweep over the term, collecting redexes into the worklist.
|
| redexVisitor.visit(root);
|
|
|
| @@ -51,9 +54,16 @@ class ShrinkingReducer extends Pass {
|
| void _removeContinuation(Continuation cont) {
|
| LetCont parent = cont.parent;
|
| if (parent.continuations.length == 1) {
|
| + assert(cont.parent_index == 0);
|
| _removeNode(parent);
|
| } else {
|
| - parent.continuations.remove(cont);
|
| + List<Continuation> continuations = parent.continuations;
|
| + for (int i = cont.parent_index; i < continuations.length - 1; ++i) {
|
| + Continuation current = continuations[i + 1];
|
| + continuations[i] = current;
|
| + current.parent_index = i;
|
| + }
|
| + continuations.removeLast();
|
| }
|
| cont.parent = _DELETED;
|
| }
|
| @@ -194,8 +204,7 @@ class ShrinkingReducer extends Pass {
|
|
|
| Parameter parameter = task.node;
|
| Continuation continuation = parameter.parent;
|
| - int index = continuation.parameters.indexOf(parameter);
|
| - assert(index != -1);
|
| + int index = parameter.parentIndex;
|
|
|
| // Remove the index'th argument from each invocation.
|
| Reference<Continuation> current = continuation.firstRef;
|
| @@ -220,7 +229,14 @@ class ShrinkingReducer extends Pass {
|
| invoke.arguments.removeAt(index);
|
| current = current.next;
|
| }
|
| - continuation.parameters.removeAt(index);
|
| + // Copy the parameters above index down.
|
| + List<Parameter> parameters = continuation.parameters;
|
| + for (int i = index; i < parameters.length - 1; ++i) {
|
| + Parameter p = parameters[i + 1];
|
| + parameters[i] = p;
|
| + p.parentIndex = i;
|
| + }
|
| + parameters.removeLast();
|
|
|
| // Removing an unused parameter can create an eta-redex.
|
| if (_isEtaCont(continuation)) {
|
| @@ -382,7 +398,7 @@ bool _isDeadParameter(Parameter parameter) {
|
| }
|
|
|
| /// Traverses a term and adds any found redexes to the worklist.
|
| -class _RedexVisitor extends TrampolineRecursiveVisitor {
|
| +class _RedexVisitor extends RecursiveVisitor {
|
| final List<_ReductionTask> worklist;
|
|
|
| _RedexVisitor(this.worklist);
|
| @@ -428,7 +444,7 @@ class _RedexVisitor extends TrampolineRecursiveVisitor {
|
| /// Deleted nodes that might participate in a reduction task are marked so that
|
| /// any corresponding tasks can be skipped. Nodes are marked so by setting
|
| /// their parent to the deleted sentinel.
|
| -class _RemovalVisitor extends TrampolineRecursiveVisitor {
|
| +class _RemovalVisitor extends RecursiveVisitor {
|
| final List<_ReductionTask> worklist;
|
|
|
| _RemovalVisitor(this.worklist);
|
| @@ -474,7 +490,224 @@ class _RemovalVisitor extends TrampolineRecursiveVisitor {
|
| }
|
| }
|
|
|
| +/// Traverses the CPS term and sets node.parent for each visited node.
|
| +class ParentVisitor extends RecursiveVisitor {
|
| + processFunctionDefinition(FunctionDefinition node) {
|
| + node.body.parent = node;
|
| + if (node.thisParameter != null) node.thisParameter.parent = node;
|
| + int index = 0;
|
| + node.parameters.forEach((Definition parameter) {
|
| + parameter.parent = node;
|
| + if (parameter is Parameter) parameter.parentIndex = index++;
|
| + });
|
| + node.returnContinuation.parent = node;
|
| + node.body.parent = node;
|
| + }
|
| +
|
| + processLetPrim(LetPrim node) {
|
| + node.primitive.parent = node;
|
| + node.body.parent = node;
|
| + }
|
| +
|
| + processLetCont(LetCont node) {
|
| + int index = 0;
|
| + node.continuations.forEach((Continuation continuation) {
|
| + continuation.parent = node;
|
| + continuation.parent_index = index++;
|
| + });
|
| + node.body.parent = node;
|
| + }
|
| +
|
| + processLetHandler(LetHandler node) {
|
| + node.handler.parent = node;
|
| + node.body.parent = node;
|
| + }
|
| +
|
| + processLetMutable(LetMutable node) {
|
| + node.variable.parent = node;
|
| + node.value.parent = node;
|
| + node.body.parent = node;
|
| + }
|
| +
|
| + processInvokeStatic(InvokeStatic node) {
|
| + node.arguments.forEach((Reference ref) => ref.parent = node);
|
| + node.continuation.parent = node;
|
| + }
|
| +
|
| + processInvokeContinuation(InvokeContinuation node) {
|
| + node.continuation.parent = node;
|
| + node.arguments.forEach((Reference ref) => ref.parent = node);
|
| + }
|
| +
|
| + processInvokeMethod(InvokeMethod node) {
|
| + node.receiver.parent = node;
|
| + node.continuation.parent = node;
|
| + node.arguments.forEach((Reference ref) => ref.parent = node);
|
| + }
|
| +
|
| + processInvokeMethodDirectly(InvokeMethodDirectly node) {
|
| + node.receiver.parent = node;
|
| + node.continuation.parent = node;
|
| + node.arguments.forEach((Reference ref) => ref.parent = node);
|
| + }
|
| +
|
| + processInvokeConstructor(InvokeConstructor node) {
|
| + node.continuation.parent = node;
|
| + node.arguments.forEach((Reference ref) => ref.parent = node);
|
| + }
|
| +
|
| + processBranch(Branch node) {
|
| + node.condition.parent = node;
|
| + node.trueContinuation.parent = node;
|
| + node.falseContinuation.parent = node;
|
| + }
|
| +
|
| + processTypeCast(TypeCast node) {
|
| + node.typeArguments.forEach((Reference ref) => ref.parent = node);
|
| + node.continuation.parent = node;
|
| + node.value.parent = node;
|
| + }
|
| +
|
| + processTypeTest(TypeTest node) {
|
| + node.typeArguments.forEach((Reference ref) => ref.parent = node);
|
| + node.value.parent = node;
|
| + if (node.interceptor != null) node.interceptor.parent = node;
|
| + }
|
| +
|
| + processTypeTestViaFlag(TypeTestViaFlag node) {
|
| + node.interceptor.parent = node;
|
| + }
|
| +
|
| + processSetMutable(SetMutable node) {
|
| + node.variable.parent = node;
|
| + node.value.parent = node;
|
| + }
|
| +
|
| + processThrow(Throw node) {
|
| + node.value.parent = node;
|
| + }
|
| +
|
| + processGetLazyStatic(GetLazyStatic node) {
|
| + node.continuation.parent = node;
|
| + }
|
| +
|
| + processLiteralList(LiteralList node) {
|
| + node.values.forEach((Reference ref) => ref.parent = node);
|
| + }
|
| +
|
| + processLiteralMap(LiteralMap node) {
|
| + node.entries.forEach((LiteralMapEntry entry) {
|
| + entry.key.parent = node;
|
| + entry.value.parent = node;
|
| + });
|
| + }
|
| +
|
| + processCreateFunction(CreateFunction node) {
|
| + node.definition.parent = node;
|
| + }
|
| +
|
| + processContinuation(Continuation node) {
|
| + if (node.body != null) node.body.parent = node;
|
| + int index = 0;
|
| + node.parameters.forEach((Parameter parameter) {
|
| + parameter.parent = node;
|
| + parameter.parentIndex = index++;
|
| + });
|
| + }
|
|
|
| + processInterceptor(Interceptor node) {
|
| + node.input.parent = node;
|
| + }
|
| +
|
| + processSetField(SetField node) {
|
| + node.object.parent = node;
|
| + node.value.parent = node;
|
| + }
|
| +
|
| + processGetField(GetField node) {
|
| + node.object.parent = node;
|
| + }
|
| +
|
| + processGetStatic(GetStatic node) {
|
| + }
|
| +
|
| + processSetStatic(SetStatic node) {
|
| + node.value.parent = node;
|
| + }
|
| +
|
| + processGetMutable(GetMutable node) {
|
| + node.variable.parent = node;
|
| + }
|
| +
|
| + processCreateInstance(CreateInstance node) {
|
| + node.arguments.forEach((Reference ref) => ref.parent = node);
|
| + node.typeInformation.forEach((Reference ref) => ref.parent = node);
|
| + }
|
| +
|
| + processCreateBox(CreateBox node) {
|
| + }
|
| +
|
| + processReifyRuntimeType(ReifyRuntimeType node) {
|
| + node.value.parent = node;
|
| + }
|
| +
|
| + processReadTypeVariable(ReadTypeVariable node) {
|
| + node.target.parent = node;
|
| + }
|
| +
|
| + processTypeExpression(TypeExpression node) {
|
| + node.arguments.forEach((Reference ref) => ref.parent = node);
|
| + }
|
| +
|
| + processCreateInvocationMirror(CreateInvocationMirror node) {
|
| + node.arguments.forEach((Reference ref) => ref.parent = node);
|
| + }
|
| +
|
| + processApplyBuiltinOperator(ApplyBuiltinOperator node) {
|
| + node.arguments.forEach((Reference ref) => ref.parent = node);
|
| + }
|
| +
|
| + processApplyBuiltinMethod(ApplyBuiltinMethod node) {
|
| + node.receiver.parent = node;
|
| + node.arguments.forEach((Reference ref) => ref.parent = node);
|
| + }
|
| +
|
| + processForeignCode(ForeignCode node) {
|
| + if (node.continuation != null) {
|
| + node.continuation.parent = node;
|
| + }
|
| + node.arguments.forEach((Reference ref) => ref.parent = node);
|
| + }
|
| +
|
| + processGetLength(GetLength node) {
|
| + node.object.parent = node;
|
| + }
|
| +
|
| + processGetIndex(GetIndex node) {
|
| + node.object.parent = node;
|
| + node.index.parent = node;
|
| + }
|
| +
|
| + processSetIndex(SetIndex node) {
|
| + node.object.parent = node;
|
| + node.index.parent = node;
|
| + node.value.parent = node;
|
| + }
|
| +
|
| + processAwait(Await node) {
|
| + node.continuation.parent = node;
|
| + node.input.parent = node;
|
| + }
|
| +
|
| + processRefinement(Refinement node) {
|
| + node.value.parent = node;
|
| + }
|
| +
|
| + processYield(Yield node) {
|
| + node.continuation.parent = node;
|
| + node.input.parent = node;
|
| + }
|
| +}
|
|
|
| class _ReductionKind {
|
| final String name;
|
| @@ -518,6 +751,5 @@ class _ReductionTask {
|
| /// A dummy class used solely to mark nodes as deleted once they are removed
|
| /// from a term.
|
| class _DeletedNode extends Node {
|
| - accept(_) {}
|
| - setParentPointers() {}
|
| + accept(_) => null;
|
| }
|
|
|