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();
}
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);
}
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);
}
}
}
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);
}
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();
}
Aggregations