Search in sources :

Example 1 with AllVarsDeclaredInFunction

use of com.google.javascript.jscomp.NodeUtil.AllVarsDeclaredInFunction in project closure-compiler by google.

the class ReachingUseDefTester method computeReachingDef.

/**
 * Runs `MustBeReachingVariableDef` pass to compute and store the must-be-reaching definition for
 * all uses of each variable in the test source.
 */
void computeReachingDef(String src) {
    Node script = parseScript(src, /*async=*/
    false);
    root = script.getFirstChild();
    Scope funcBlockScope = computeFunctionBlockScope(script, root);
    ControlFlowGraph<Node> cfg = computeCfg(root);
    HashSet<Var> escaped = new HashSet<>();
    AllVarsDeclaredInFunction allVarsDeclaredInFunction = NodeUtil.getAllVarsDeclaredInFunction(compiler, scopeCreator, funcBlockScope.getParent());
    Map<String, Var> allVarsInFn = allVarsDeclaredInFunction.getAllVariables();
    DataFlowAnalysis.computeEscaped(funcBlockScope.getParent(), escaped, compiler, scopeCreator, allVarsInFn);
    reachingDef = new MustBeReachingVariableDef(cfg, compiler, escaped, allVarsInFn);
    reachingDef.analyze();
}
Also used : AllVarsDeclaredInFunction(com.google.javascript.jscomp.NodeUtil.AllVarsDeclaredInFunction) Node(com.google.javascript.rhino.Node) HashSet(java.util.HashSet)

Example 2 with AllVarsDeclaredInFunction

use of com.google.javascript.jscomp.NodeUtil.AllVarsDeclaredInFunction in project closure-compiler by google.

the class CoalesceVariableNames method enterScope.

@Override
public void enterScope(NodeTraversal t) {
    AllVarsDeclaredInFunction allVarsDeclaredInFunction = shouldOptimizeScope(t);
    if (allVarsDeclaredInFunction == null) {
        shouldOptimizeScopeStack.push(false);
        return;
    }
    shouldOptimizeScopeStack.push(true);
    Scope scope = t.getScope();
    checkState(scope.isFunctionScope(), scope);
    // live variables analysis is based off of the control flow graph
    ControlFlowGraph<Node> cfg = t.getControlFlowGraph();
    liveness = new LiveVariablesAnalysis(cfg, scope, null, compiler, this.scopeCreator, allVarsDeclaredInFunction);
    if (FeatureSet.ES3.contains(compiler.getOptions().getOutputFeatureSet())) {
        // If the function has exactly 2 params, mark them as escaped. This is a work-around for a
        // bug in IE 8 and below, where it throws an exception if you write to the parameters of the
        // callback in a sort(). See http://blickly.github.io/closure-compiler-issues/#58 and
        // https://www.zachleat.com/web/array-sort/
        Node enclosingFunction = scope.getRootNode();
        if (NodeUtil.getFunctionParameters(enclosingFunction).hasTwoChildren()) {
            liveness.markAllParametersEscaped();
        }
    }
    liveness.analyze();
    liveAnalyses.push(liveness);
    // The interference graph has the function's variables as its nodes and any interference
    // between the variables as the edges. Interference between two variables means that they are
    // alive at overlapping times, which means that their variable names cannot be coalesced.
    UndiGraph<Var, Void> interferenceGraph = computeVariableNamesInterferenceGraph(cfg, liveness.getEscapedLocals());
    // Color any interfering variables with different colors and any variables that can be safely
    // coalesced wih the same color.
    GraphColoring<Var, Void> coloring = new GreedyGraphColoring<>(interferenceGraph, coloringTieBreaker);
    coloring.color();
    colorings.push(coloring);
}
Also used : AllVarsDeclaredInFunction(com.google.javascript.jscomp.NodeUtil.AllVarsDeclaredInFunction) GraphNode(com.google.javascript.jscomp.graph.GraphNode) Node(com.google.javascript.rhino.Node) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) GreedyGraphColoring(com.google.javascript.jscomp.graph.GraphColoring.GreedyGraphColoring)

Example 3 with AllVarsDeclaredInFunction

use of com.google.javascript.jscomp.NodeUtil.AllVarsDeclaredInFunction in project closure-compiler by google.

the class FlowSensitiveInlineVariables method enterScope.

@Override
public void enterScope(NodeTraversal t) {
    if (t.inGlobalScope()) {
        // Don't even brother. All global variables are likely escaped.
        return;
    }
    if (!t.getScope().isFunctionBlockScope()) {
        // Only want to do the following if its a function block scope.
        return;
    }
    Node functionScopeRoot = t.getScopeRoot().getParent();
    if (!isCandidateFunction(functionScopeRoot)) {
        return;
    }
    if (LiveVariablesAnalysis.MAX_VARIABLES_TO_ANALYZE < t.getScope().getVarCount()) {
        return;
    }
    SyntacticScopeCreator scopeCreator = (SyntacticScopeCreator) t.getScopeCreator();
    // Compute the forward reaching definition.
    ControlFlowAnalysis cfa = new ControlFlowAnalysis(compiler, false, true);
    // Process the body of the function.
    cfa.process(null, functionScopeRoot);
    cfg = cfa.getCfg();
    HashSet<Var> escaped = new HashSet<>();
    Scope scope = t.getScope();
    AllVarsDeclaredInFunction allVarsDeclaredInFunction = NodeUtil.getAllVarsDeclaredInFunction(compiler, scopeCreator, scope.getParent());
    Map<String, Var> allVarsInFn = allVarsDeclaredInFunction.getAllVariables();
    DataFlowAnalysis.computeEscaped(scope.getParent(), escaped, compiler, scopeCreator, allVarsInFn);
    reachingDef = new MustBeReachingVariableDef(cfg, compiler, escaped, allVarsInFn);
    reachingDef.analyze();
    candidates = new LinkedHashSet<>();
    // Using the forward reaching definition search to find all the inline
    // candidates
    NodeTraversal.traverse(compiler, t.getScopeRoot(), new GatherCandidates());
    // Compute the backward reaching use. The CFG and per-function variable info can be reused.
    reachingUses = new MaybeReachingVariableUse(cfg, escaped, allVarsInFn);
    reachingUses.analyze();
    while (!candidates.isEmpty()) {
        Candidate c = candidates.iterator().next();
        Var candidateVar = checkNotNull(allVarsInFn.get(c.varName));
        if (c.canInline(candidateVar.getScope())) {
            c.inlineVariable();
            candidates.remove(c);
            // dependencies cannot contain all of "c"'s dependencies.
            if (!c.defMetadata.depends.isEmpty()) {
                for (Iterator<Candidate> it = candidates.iterator(); it.hasNext(); ) {
                    Candidate other = it.next();
                    if (other.defMetadata.depends.contains(t.getScope().getVar(c.varName)) && !other.defMetadata.depends.containsAll(c.defMetadata.depends)) {
                        it.remove();
                    }
                }
            }
        } else {
            candidates.remove(c);
        }
    }
}
Also used : AllVarsDeclaredInFunction(com.google.javascript.jscomp.NodeUtil.AllVarsDeclaredInFunction) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) Node(com.google.javascript.rhino.Node) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 4 with AllVarsDeclaredInFunction

use of com.google.javascript.jscomp.NodeUtil.AllVarsDeclaredInFunction in project closure-compiler by google.

the class DeadAssignmentsElimination method eliminateDeadAssignments.

private void eliminateDeadAssignments(NodeTraversal t) {
    checkArgument(t.inFunctionBlockScope());
    checkState(!functionStack.isEmpty());
    // Skip unchanged functions (note that the scope root is the function block, not the function).
    if (!compiler.hasScopeChanged(t.getScopeRoot().getParent())) {
        return;
    }
    BailoutInformation currentFunction = functionStack.peekFirst();
    // closure, ALL the variables are saved (escaped).
    if (currentFunction.containsFunction) {
        return;
    }
    // to eliminate. :)
    if (!currentFunction.containsRemovableAssign) {
        return;
    }
    Scope blockScope = t.getScope();
    Scope functionScope = blockScope.getParent();
    if (LiveVariablesAnalysis.MAX_VARIABLES_TO_ANALYZE < blockScope.getVarCount() + functionScope.getVarCount()) {
        return;
    }
    // Computes liveness information first.
    ControlFlowGraph<Node> cfg = t.getControlFlowGraph();
    SyntacticScopeCreator scopeCreator = new SyntacticScopeCreator(compiler);
    AllVarsDeclaredInFunction allVarsDeclaredInFunction = NodeUtil.getAllVarsDeclaredInFunction(compiler, scopeCreator, functionScope);
    liveness = new LiveVariablesAnalysis(cfg, functionScope, blockScope, compiler, scopeCreator, allVarsDeclaredInFunction);
    liveness.analyze();
    Map<String, Var> allVarsInFn = liveness.getAllVariables();
    tryRemoveDeadAssignments(t, cfg, allVarsInFn);
}
Also used : AllVarsDeclaredInFunction(com.google.javascript.jscomp.NodeUtil.AllVarsDeclaredInFunction) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) Node(com.google.javascript.rhino.Node)

Example 5 with AllVarsDeclaredInFunction

use of com.google.javascript.jscomp.NodeUtil.AllVarsDeclaredInFunction in project closure-compiler by google.

the class DataFlowAnalysisTest method computeEscapedLocals.

// test computeEscaped helper method that returns the liveness analysis performed by the
// LiveVariablesAnalysis class
public Set<? extends Var> computeEscapedLocals(String... lines) {
    // Set up compiler
    Compiler compiler = new Compiler();
    CompilerOptions options = new CompilerOptions();
    options.setCodingConvention(new GoogleCodingConvention());
    compiler.initOptions(options);
    compiler.setLifeCycleStage(LifeCycleStage.NORMALIZED);
    String src = CompilerTestCase.lines(lines);
    Node n = compiler.parseTestCode(src).removeFirstChild();
    Node script = new Node(Token.SCRIPT, n);
    script.setInputId(new InputId("test"));
    assertThat(compiler.getErrors()).isEmpty();
    // Create scopes
    SyntacticScopeCreator scopeCreator = new SyntacticScopeCreator(compiler);
    Scope scope = scopeCreator.createScope(n, Scope.createGlobalScope(script));
    Scope childScope;
    if (script.getFirstChild().isFunction()) {
        childScope = scopeCreator.createScope(NodeUtil.getFunctionBody(n), scope);
    } else {
        childScope = null;
    }
    // Control flow graph
    ControlFlowAnalysis cfa = new ControlFlowAnalysis(compiler, false, true);
    cfa.process(null, script);
    ControlFlowGraph<Node> cfg = cfa.getCfg();
    // All variables declared in function
    AllVarsDeclaredInFunction allVarsDeclaredInFunction = NodeUtil.getAllVarsDeclaredInFunction(compiler, scopeCreator, scope);
    // Compute liveness of variables
    LiveVariablesAnalysis analysis = new LiveVariablesAnalysis(cfg, scope, childScope, compiler, scopeCreator, allVarsDeclaredInFunction);
    analysis.analyze();
    return analysis.getEscapedLocals();
}
Also used : AllVarsDeclaredInFunction(com.google.javascript.jscomp.NodeUtil.AllVarsDeclaredInFunction) GraphNode(com.google.javascript.jscomp.graph.GraphNode) Node(com.google.javascript.rhino.Node) InputId(com.google.javascript.rhino.InputId)

Aggregations

AllVarsDeclaredInFunction (com.google.javascript.jscomp.NodeUtil.AllVarsDeclaredInFunction)7 Node (com.google.javascript.rhino.Node)7 DiGraphNode (com.google.javascript.jscomp.graph.DiGraph.DiGraphNode)3 HashSet (java.util.HashSet)3 GraphNode (com.google.javascript.jscomp.graph.GraphNode)2 InputId (com.google.javascript.rhino.InputId)2 GreedyGraphColoring (com.google.javascript.jscomp.graph.GraphColoring.GreedyGraphColoring)1 LinkedHashSet (java.util.LinkedHashSet)1