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).
|
shouldTraverseclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitshouldTraverseprivate 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)
CompilerPassprocess in interface CompilerPassexterns - Top of external JS treeroot - Top of JS treeprivate static boolean shouldOptimizeScope(Scope scope)
public void enterScope(NodeTraversal t)
NodeTraversal.ScopedCallbackenterScope in interface NodeTraversal.ScopedCallbackpublic void exitScope(NodeTraversal t)
NodeTraversal.ScopedCallbackexitScope in interface NodeTraversal.ScopedCallbackpublic void visit(NodeTraversal t, Node n, Node parent)
NodeTraversal.CallbackVisits 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.Callbackprivate UndiGraph<Var,java.lang.Void> computeVariableNamesInterferenceGraph(NodeTraversal t, ControlFlowGraph<Node> cfg, java.util.Set<Var> escaped)
private static void removeVarDeclaration(Node name)