class CoalesceVariableNames extends NodeTraversal.AbstractPostOrderCallback implements CompilerPass, NodeTraversal.ScopedCallback
For example, from The pass operates similar to a typical register allocator found in an
optimizing compiler by first computing live ranges with
var x = 1; print(x); var y = 2; print(y);
to var x = 1; print(x); x = 2; print(x)
. The benefits are
slightly shorter code because of the removed var
declaration,
less unique variables in hope for better renaming, and finally better gzip
compression.
LiveVariablesAnalysis
and a variable interference graph. Then it uses
graph coloring in GraphColoring
to determine which two variables can
be merge together safely.
Modifier and Type | Class and Description |
---|---|
private static class |
CoalesceVariableNames.CombinedLiveRangeChecker
A simple wrapper calls to call two AbstractCfgNodeTraversalCallback
callback during the same traversal.
|
private static class |
CoalesceVariableNames.LiveRangeChecker |
Modifier and Type | Field and Description |
---|---|
private java.util.Deque<GraphColoring<Var,java.lang.Void>> |
colorings |
private static java.util.Comparator<Var> |
coloringTieBreaker |
private AbstractCompiler |
compiler |
private boolean |
usePseudoNames |
Constructor and Description |
---|
CoalesceVariableNames(AbstractCompiler compiler,
boolean usePseudoNames) |
Modifier and Type | Method and Description |
---|---|
private UndiGraph<Var,java.lang.Void> |
computeVariableNamesInterferenceGraph(NodeTraversal t,
ControlFlowGraph<Node> cfg,
java.util.Set<Var> escaped) |
void |
enterScope(NodeTraversal t)
Called immediately after entering a new scope.
|
void |
exitScope(NodeTraversal t)
Called immediately before exiting a scope.
|
void |
process(Node externs,
Node root)
Process the JS with root node root.
|
private static void |
removeVarDeclaration(Node name)
Tries to remove variable declaration if the variable has been coalesced
with another variable that has already been declared.
|
private static boolean |
shouldOptimizeScope(Scope scope) |
void |
visit(NodeTraversal t,
Node n,
Node parent)
Visits a node in postorder (after its children have been visited).
|
shouldTraverse
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
shouldTraverse
private final AbstractCompiler compiler
private final java.util.Deque<GraphColoring<Var,java.lang.Void>> colorings
private final boolean usePseudoNames
private static final java.util.Comparator<Var> coloringTieBreaker
CoalesceVariableNames(AbstractCompiler compiler, boolean usePseudoNames)
usePseudoNames
- For debug purposes, when merging variable foo and bar
to foo, rename both variable to foo_bar.public void process(Node externs, Node root)
CompilerPass
process
in interface CompilerPass
externs
- Top of external JS treeroot
- Top of JS treeprivate static boolean shouldOptimizeScope(Scope scope)
public void enterScope(NodeTraversal t)
NodeTraversal.ScopedCallback
enterScope
in interface NodeTraversal.ScopedCallback
public void exitScope(NodeTraversal t)
NodeTraversal.ScopedCallback
exitScope
in interface NodeTraversal.ScopedCallback
public void visit(NodeTraversal t, Node n, Node parent)
NodeTraversal.Callback
Visits a node in postorder (after its children have been visited).
A node is visited only if all its parents should be traversed
(NodeTraversal.Callback.shouldTraverse(NodeTraversal, Node, Node)
).
Implementations can have side effects (e.g. modifying the parse tree).
visit
in interface NodeTraversal.Callback
private UndiGraph<Var,java.lang.Void> computeVariableNamesInterferenceGraph(NodeTraversal t, ControlFlowGraph<Node> cfg, java.util.Set<Var> escaped)
private static void removeVarDeclaration(Node name)