| Index: pkg/compiler/lib/src/cps_ir/type_propagation.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
|
| index 839e666b56f68b23f078efcf1b942caa4ad99e04..5784bba24b79215f51d5a284fc2fa9d3c17bc5fc 100644
|
| --- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
|
| +++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
|
| @@ -555,7 +555,6 @@ class TransformingVisitor extends LeafVisitor {
|
| JavaScriptBackend get backend => compiler.backend;
|
| TypeMaskSystem get typeSystem => lattice.typeSystem;
|
| types.DartTypes get dartTypes => lattice.dartTypes;
|
| - Set<Node> get reachable => analyzer.reachableNodes;
|
| Map<Node, AbstractValue> get values => analyzer.values;
|
|
|
| final dart2js.InternalErrorFunction internalError;
|
| @@ -1451,7 +1450,6 @@ class TransformingVisitor extends LeafVisitor {
|
|
|
| case AbstractBool.False:
|
| // Cast always fails, remove unreachable continuation body.
|
| - assert(!reachable.contains(cont));
|
| replaceSubtree(cont.body, new Unreachable());
|
| break;
|
| }
|
| @@ -1633,11 +1631,11 @@ class TypePropagationVisitor implements Visitor {
|
| // TODO(jgruber): Storing reachability per-edge instead of per-node would
|
| // allow for further optimizations.
|
| final List<Node> nodeWorklist = <Node>[];
|
| - final Set<Node> reachableNodes = new Set<Node>();
|
| + final Set<Continuation> reachableContinuations = new Set<Continuation>();
|
|
|
| // The definition workset stores all definitions which need to be reprocessed
|
| // since their lattice value has changed.
|
| - final Set<Definition> defWorkset = new Set<Definition>();
|
| + final List<Definition> defWorklist = <Definition>[];
|
|
|
| final ConstantPropagationLattice lattice;
|
| final dart2js.InternalErrorFunction internalError;
|
| @@ -1666,17 +1664,17 @@ class TypePropagationVisitor implements Visitor {
|
| this.internalError);
|
|
|
| void analyze(FunctionDefinition root) {
|
| - reachableNodes.clear();
|
| + reachableContinuations.clear();
|
|
|
| // Initially, only the root node is reachable.
|
| - setReachable(root);
|
| + push(root);
|
|
|
| iterateWorklist();
|
| }
|
|
|
| void reanalyzeSubtree(Node node) {
|
| - new ResetAnalysisInfo(reachableNodes, values).visit(node);
|
| - setReachable(node);
|
| + new ResetAnalysisInfo(reachableContinuations, values).visit(node);
|
| + push(node);
|
| iterateWorklist();
|
| }
|
|
|
| @@ -1686,10 +1684,9 @@ class TypePropagationVisitor implements Visitor {
|
| // Process a new reachable expression.
|
| Node node = nodeWorklist.removeLast();
|
| visit(node);
|
| - } else if (defWorkset.isNotEmpty) {
|
| + } else if (defWorklist.isNotEmpty) {
|
| // Process all usages of a changed definition.
|
| - Definition def = defWorkset.first;
|
| - defWorkset.remove(def);
|
| + Definition def = defWorklist.removeLast();
|
|
|
| // Visit all uses of this definition. This might add new entries to
|
| // [nodeWorklist], for example by visiting a newly-constant usage within
|
| @@ -1703,12 +1700,16 @@ class TypePropagationVisitor implements Visitor {
|
| }
|
| }
|
|
|
| + /// Adds [node] to the worklist.
|
| + void push(Node node) {
|
| + nodeWorklist.add(node);
|
| + }
|
| +
|
| /// If the passed node is not yet reachable, mark it reachable and add it
|
| /// to the work list.
|
| - void setReachable(Node node) {
|
| - if (!reachableNodes.contains(node)) {
|
| - reachableNodes.add(node);
|
| - nodeWorklist.add(node);
|
| + void setReachable(Continuation cont) {
|
| + if (reachableContinuations.add(cont)) {
|
| + push(cont);
|
| }
|
| }
|
|
|
| @@ -1734,7 +1735,7 @@ class TypePropagationVisitor implements Visitor {
|
| assert(newValue.kind >= oldValue.kind);
|
|
|
| values[node] = newValue;
|
| - defWorkset.add(node);
|
| + defWorklist.add(node);
|
| }
|
|
|
| // -------------------------- Visitor overrides ------------------------------
|
| @@ -1746,21 +1747,21 @@ class TypePropagationVisitor implements Visitor {
|
| nonConstant(typeSystem.getReceiverType(node.element)));
|
| }
|
| node.parameters.forEach(visit);
|
| - setReachable(node.body);
|
| + push(node.body);
|
| }
|
|
|
| void visitLetPrim(LetPrim node) {
|
| visit(node.primitive); // No reason to delay visits to primitives.
|
| - setReachable(node.body);
|
| + push(node.body);
|
| }
|
|
|
| void visitLetCont(LetCont node) {
|
| // The continuation is only marked as reachable on use.
|
| - setReachable(node.body);
|
| + push(node.body);
|
| }
|
|
|
| void visitLetHandler(LetHandler node) {
|
| - setReachable(node.body);
|
| + push(node.body);
|
| // The handler is assumed to be reachable (we could instead treat it as
|
| // unreachable unless we find something reachable that might throw in the
|
| // body --- it's not clear if we want to do that here or in some other
|
| @@ -1777,7 +1778,7 @@ class TypePropagationVisitor implements Visitor {
|
|
|
| void visitLetMutable(LetMutable node) {
|
| setValue(node.variable, getValue(node.value.definition));
|
| - setReachable(node.body);
|
| + push(node.body);
|
| }
|
|
|
| void visitInvokeStatic(InvokeStatic node) {
|
| @@ -2093,10 +2094,7 @@ class TypePropagationVisitor implements Visitor {
|
| }
|
|
|
| void visitCreateFunction(CreateFunction node) {
|
| - setReachable(node.definition);
|
| - ConstantValue constant =
|
| - new FunctionConstantValue(node.definition.element);
|
| - setValue(node, constantValue(constant, typeSystem.functionType));
|
| + throw 'CreateFunction is not used';
|
| }
|
|
|
| void visitGetMutable(GetMutable node) {
|
| @@ -2143,7 +2141,7 @@ class TypePropagationVisitor implements Visitor {
|
| node.parameters.forEach(visit);
|
|
|
| if (node.body != null) {
|
| - setReachable(node.body);
|
| + push(node.body);
|
| }
|
| }
|
|
|
| @@ -2172,7 +2170,7 @@ class TypePropagationVisitor implements Visitor {
|
| }
|
|
|
| void visitInterceptor(Interceptor node) {
|
| - setReachable(node.input.definition);
|
| + push(node.input.definition);
|
| AbstractValue value = getValue(node.input.definition);
|
| if (!value.isNothing) {
|
| setValue(node, nonConstant(typeSystem.nonNullType));
|
| @@ -2335,14 +2333,21 @@ class OriginalLengthEntity extends Entity {
|
| }
|
|
|
| class ResetAnalysisInfo extends RecursiveVisitor {
|
| - Set<Node> reachableNodes;
|
| + Set<Continuation> reachableContinuations;
|
| Map<Definition, AbstractValue> values;
|
|
|
| - ResetAnalysisInfo(this.reachableNodes, this.values);
|
| + ResetAnalysisInfo(this.reachableContinuations, this.values);
|
| +
|
| + processContinuation(Continuation cont) {
|
| + reachableContinuations.remove(cont);
|
| + cont.parameters.forEach(values.remove);
|
| + }
|
| +
|
| + processLetPrim(LetPrim node) {
|
| + values.remove(node.primitive);
|
| + }
|
|
|
| - visit(Node node) {
|
| - reachableNodes.remove(node);
|
| - if (node is Definition) values.remove(node);
|
| - node.accept(this);
|
| + processLetMutable(LetMutable node) {
|
| + values.remove(node.variable);
|
| }
|
| }
|
|
|