MustBeReachingVariableDef( ControlFlowGraph<Node> cfg, Scope jsScope, AbstractCompiler compiler) { super(cfg, new MustDefJoin()); this.jsScope = jsScope; this.compiler = compiler; this.escaped = new HashSet<Var>(); computeEscaped(jsScope, escaped, compiler); }
@Override MustDef flowThrough(Node n, MustDef input) { // TODO(user): We are doing a straight copy from input to output. There // might be some opportunities to cut down overhead. MustDef output = new MustDef(input); // TODO(user): This must know about ON_EX edges but it should handle // it better than what we did in liveness. Because we are in a forward mode, // we can used the branched forward analysis. computeMustDef(n, n, output, false); return output; }
/** * Gets the must reaching definition of a given node. * * @param name name of the variable. It can only be names of local variable * that are not function parameters, escaped variables or variables * declared in catch. * @param useNode the location of the use where the definition reaches. */ Definition getDef(String name, Node useNode) { checkArgument(getCfg().hasNode(useNode)); GraphNode<Node, Branch> n = getCfg().getNode(useNode); FlowState<MustDef> state = n.getAnnotation(); return state.getIn().reachingDef.get(allVarsInFn.get(name)); }
case DO: case IF: computeMustDef( NodeUtil.getConditionExpression(n), cfgNode, output, conditional); return; computeMustDef(NodeUtil.getConditionExpression(n), cfgNode, output, conditional); return; addToDefIfLocal(lhs.getString(), cfgNode, rhs, output); } else if (lhs.isDestructuringLhs()) { lhs = lhs.getFirstChild(); computeMustDef(lhs, cfgNode, output, true); computeMustDef(n.getFirstChild(), cfgNode, output, conditional); computeMustDef(n.getLastChild(), cfgNode, output, true); return; computeMustDef(n.getFirstChild(), cfgNode, output, conditional); computeMustDef(n.getSecondChild(), cfgNode, output, true); computeMustDef(n.getLastChild(), cfgNode, output, true); return; if (c.hasChildren()) { if (c.isName()) { computeMustDef(c.getFirstChild(), cfgNode, output, conditional); addToDefIfLocal(c.getString(), conditional ? null : cfgNode, c.getFirstChild(), output);
@Override public void visit(NodeTraversal t, Node n, Node parent) { if (n.isName()) { // n.getParent() isn't null. This just the case where n is the root // node that gatherCb started at. if (parent == null) { return; } // Make sure that the name node is purely a read. if ((NodeUtil.isAssignmentOp(parent) && parent.getFirstChild() == n) || parent.isVar() || parent.isInc() || parent.isDec() || parent.isParamList() || parent.isCatch()) { return; } String name = n.getString(); if (compiler.getCodingConvention().isExported(name)) { return; } Definition def = reachingDef.getDef(name, cfgNode); // TODO(nicksantos): We need to add some notion of @const outer // scope vars. We can inline those just fine. if (def != null && !reachingDef.dependsOnOuterScopeVars(def)) { candidates.add(new Candidate(name, def, n, cfgNode)); } } } };
cfa.process(null, t.getScopeRoot()); cfg = cfa.getCfg(); reachingDef = new MustBeReachingVariableDef(cfg, t.getScope(), compiler); reachingDef.analyze(); candidates = new LinkedHashSet<Candidate>();
Node getDefNode(String name, Node useNode) { Definition def = getDef(name, useNode); return def == null ? null : def.node; }
Definition definition = new Definition(node); if (rValue != null) { computeDependence(definition, rValue);
case Token.DO: case Token.IF: computeMustDef( NodeUtil.getConditionExpression(n), cfgNode, output, conditional); return; computeMustDef( NodeUtil.getConditionExpression(n), cfgNode, output, conditional); } else { addToDefIfLocal(lhs.getString(), cfgNode, rhs, output); computeMustDef(n.getFirstChild(), cfgNode, output, conditional); computeMustDef(n.getLastChild(), cfgNode, output, true); return; computeMustDef(n.getFirstChild(), cfgNode, output, conditional); computeMustDef(n.getSecondChild(), cfgNode, output, true); computeMustDef(n.getLastChild(), cfgNode, output, true); return; for (Node c = n.getFirstChild(); c != null; c = c.getNext()) { if (c.hasChildren()) { computeMustDef(c.getFirstChild(), cfgNode, output, conditional); addToDefIfLocal(c.getString(), conditional ? null : cfgNode, c.getFirstChild(), output); if (n.getFirstChild().isName()) { Node name = n.getFirstChild();
Definition def = reachingDef.getDef(name, cfgNode); if (def != null && !reachingDef.dependsOnOuterScopeVars(def)) { candidates.add(new Candidate(name, def, n, cfgNode));
cfg = cfa.getCfg(); reachingDef = new MustBeReachingVariableDef(cfg, t.getScope(), compiler, scopeCreator); reachingDef.analyze(); candidates = new LinkedHashSet<>();
Node getDefNode(String name, Node useNode) { Definition def = getDef(name, useNode); return def == null ? null : def.node; }
Definition definition = new Definition(node); if (rValue != null) { computeDependence(definition, rValue);
@Override MustDef flowThrough(Node n, MustDef input) { // TODO(user): We are doing a straight copy from input to output. There // might be some opportunities to cut down overhead. MustDef output = new MustDef(input); // TODO(user): This must know about ON_EX edges but it should handle // it better than what we did in liveness. Because we are in a forward mode, // we can used the branched forward analysis. computeMustDef(n, n, output, false); return output; }
MustBeReachingVariableDef( ControlFlowGraph<Node> cfg, Scope jsScope, AbstractCompiler compiler, Es6SyntacticScopeCreator scopeCreator) { super(cfg, new MustDefJoin()); this.compiler = compiler; this.escaped = new HashSet<>(); this.allVarsInFn = new HashMap<>(); this.orderedVars = new ArrayList<>(); computeEscaped(jsScope.getParent(), escaped, compiler, scopeCreator); NodeUtil.getAllVarsDeclaredInFunction( allVarsInFn, orderedVars, compiler, scopeCreator, jsScope.getParent()); }
/** * Gets the must reaching definition of a given node. * * @param name name of the variable. It can only be names of local variable * that are not function parameters, escaped variables or variables * declared in catch. * @param useNode the location of the use where the definition reaches. */ Definition getDef(String name, Node useNode) { Preconditions.checkArgument(getCfg().hasNode(useNode)); GraphNode<Node, Branch> n = getCfg().getNode(useNode); FlowState<MustDef> state = n.getAnnotation(); return state.getIn().reachingDef.get(jsScope.getVar(name)); }