use of com.google.javascript.jscomp.graph.GraphColoring.GreedyGraphColoring in project closure-compiler by google.
the class AmbiguateProperties method process.
@Override
public void process(Node externs, Node root) {
// Find all property references and record the types on which they occur.
// Populate stringNodesToRename, propertyMap, quotedNames.
NodeTraversal.traverseEs6(compiler, root, new ProcessProperties());
ImmutableSet.Builder<String> reservedNames = ImmutableSet.<String>builder().addAll(externedNames).addAll(quotedNames);
int numRenamedPropertyNames = 0;
int numSkippedPropertyNames = 0;
ArrayList<PropertyGraphNode> nodes = new ArrayList<>(propertyMap.size());
for (Property prop : propertyMap.values()) {
if (prop.skipAmbiguating) {
++numSkippedPropertyNames;
reservedNames.add(prop.oldName);
} else {
++numRenamedPropertyNames;
nodes.add(new PropertyGraphNode(prop));
}
}
PropertyGraph graph = new PropertyGraph(nodes);
GraphColoring<Property, Void> coloring = new GreedyGraphColoring<>(graph, FREQUENCY_COMPARATOR);
int numNewPropertyNames = coloring.color();
// Generate new names for the properties that will be renamed.
NameGenerator nameGen = new DefaultNameGenerator(reservedNames.build(), "", reservedFirstCharacters, reservedNonFirstCharacters);
String[] colorMap = new String[numNewPropertyNames];
for (int i = 0; i < numNewPropertyNames; ++i) {
colorMap[i] = nameGen.generateNextName();
}
// Translate the color of each Property instance to a name.
for (PropertyGraphNode node : graph.getNodes()) {
node.getValue().newName = colorMap[node.getAnnotation().hashCode()];
if (renamingMap != null) {
renamingMap.put(node.getValue().oldName, node.getValue().newName);
}
}
// Actually assign the new names to the relevant STRING nodes in the AST.
for (Node n : stringNodesToRename) {
String oldName = n.getString();
Property p = propertyMap.get(oldName);
if (p != null && p.newName != null) {
checkState(oldName.equals(p.oldName));
if (!p.newName.equals(oldName)) {
n.setString(p.newName);
compiler.reportChangeToEnclosingScope(n);
}
}
}
if (logger.isLoggable(Level.FINE)) {
logger.fine("Collapsed " + numRenamedPropertyNames + " properties into " + numNewPropertyNames + " and skipped renaming " + numSkippedPropertyNames + " properties.");
}
}
use of com.google.javascript.jscomp.graph.GraphColoring.GreedyGraphColoring in project closure-compiler by google.
the class AmbiguateProperties method process.
@Override
public void process(Node externs, Node root) {
this.graphNodeFactory = ColorGraphNodeFactory.createFactory(this.colorRegistry);
// Find all property references and record the types on which they occur.
// Populate stringNodesToRename, propertyMap, quotedNames.
NodeTraversal.traverse(compiler, root, new ProcessPropertiesAndConstructors());
ColorGraphBuilder graphBuilder = new ColorGraphBuilder(graphNodeFactory, LowestCommonAncestorFinder::new, this.colorRegistry);
graphBuilder.addAll(graphNodeFactory.getAllKnownTypes());
DiGraph<ColorGraphNode, Object> colorGraph = graphBuilder.build();
for (ColorGraphNode node : graphNodeFactory.getAllKnownTypes()) {
// Init subtyping as reflexive.
node.getSubtypeIndices().set(node.getIndex());
}
FixedPointGraphTraversal.<ColorGraphNode, Object>newReverseTraversal((subtype, e, supertype) -> {
/**
* Cheap path for when we're sure there's going to be a change.
*
* <p>Since bits only ever turn on, using more bits means there are definitely more
* elements. This prevents of from needing to check cardinality or equality, which
* would otherwise dominate the cost of computing the fixed point.
*
* <p>We're guaranteed to converge because the sizes will be euqal after the OR
* operation.
*/
if (subtype.getSubtypeIndices().size() > supertype.getSubtypeIndices().size()) {
supertype.getSubtypeIndices().or(subtype.getSubtypeIndices());
return true;
}
int startSize = supertype.getSubtypeIndices().cardinality();
supertype.getSubtypeIndices().or(subtype.getSubtypeIndices());
return supertype.getSubtypeIndices().cardinality() > startSize;
}).computeFixedPoint(colorGraph);
// Fill in all transitive edges in subtyping graph per property
for (Property prop : propertyMap.values()) {
if (prop.relatedColorsSeeds == null) {
continue;
}
for (ColorGraphNode color : prop.relatedColorsSeeds.keySet()) {
prop.relatedColors.or(color.getSubtypeIndices());
}
prop.relatedColorsSeeds = null;
}
ImmutableSet.Builder<String> reservedNames = ImmutableSet.<String>builder().addAll(externedNames).addAll(quotedNames);
int numRenamedPropertyNames = 0;
int numSkippedPropertyNames = 0;
ArrayList<PropertyGraphNode> nodes = new ArrayList<>(propertyMap.size());
for (Property prop : propertyMap.values()) {
if (prop.skipAmbiguating) {
++numSkippedPropertyNames;
reservedNames.add(prop.oldName);
} else {
++numRenamedPropertyNames;
nodes.add(new PropertyGraphNode(prop));
}
}
PropertyGraph propertyGraph = new PropertyGraph(nodes);
GraphColoring<Property, Void> coloring = new GreedyGraphColoring<>(propertyGraph, FREQUENCY_COMPARATOR);
int numNewPropertyNames = coloring.color();
// Generate new names for the properties that will be renamed.
NameGenerator nameGen = new DefaultNameGenerator(reservedNames.build(), "", reservedFirstCharacters, reservedNonFirstCharacters);
String[] colorMap = new String[numNewPropertyNames];
for (int i = 0; i < numNewPropertyNames; ++i) {
colorMap[i] = nameGen.generateNextName();
}
// Translate the color of each Property instance to a name.
for (PropertyGraphNode node : propertyGraph.getNodes()) {
node.getValue().newName = colorMap[node.getAnnotation().hashCode()];
if (renamingMap != null) {
renamingMap.put(node.getValue().oldName, node.getValue().newName);
}
}
// Actually assign the new names to the relevant STRING nodes in the AST.
for (Node n : stringNodesToRename) {
String oldName = n.getString();
Property p = propertyMap.get(oldName);
if (p != null && p.newName != null) {
checkState(oldName.equals(p.oldName));
if (!p.newName.equals(oldName)) {
n.setString(p.newName);
compiler.reportChangeToEnclosingScope(n);
}
}
}
// We may have renamed getter / setter properties.
// TODO(b/161947315): this shouldn't be the responsibility of AmbiguateProperties
GatherGetterAndSetterProperties.update(compiler, externs, root);
if (logger.isLoggable(Level.FINE)) {
logger.fine("Collapsed " + numRenamedPropertyNames + " properties into " + numNewPropertyNames + " and skipped renaming " + numSkippedPropertyNames + " properties.");
}
}
use of com.google.javascript.jscomp.graph.GraphColoring.GreedyGraphColoring 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);
}
Aggregations