Search in sources :

Example 1 with GreedyGraphColoring

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.");
    }
}
Also used : GraphNode(com.google.javascript.jscomp.graph.GraphNode) Node(com.google.javascript.rhino.Node) ArrayList(java.util.ArrayList) ImmutableSet(com.google.common.collect.ImmutableSet) GreedyGraphColoring(com.google.javascript.jscomp.graph.GraphColoring.GreedyGraphColoring)

Example 2 with GreedyGraphColoring

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.");
    }
}
Also used : DefaultNameGenerator(com.google.javascript.jscomp.DefaultNameGenerator) GatherGetterAndSetterProperties(com.google.javascript.jscomp.GatherGetterAndSetterProperties) SubGraph(com.google.javascript.jscomp.graph.SubGraph) GraphNode(com.google.javascript.jscomp.graph.GraphNode) HashMap(java.util.HashMap) NameGenerator(com.google.javascript.jscomp.NameGenerator) ArrayList(java.util.ArrayList) Level(java.util.logging.Level) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) Map(java.util.Map) StandardColors(com.google.javascript.jscomp.colors.StandardColors) CompilerPass(com.google.javascript.jscomp.CompilerPass) AdjacencyGraph(com.google.javascript.jscomp.graph.AdjacencyGraph) DiGraph(com.google.javascript.jscomp.graph.DiGraph) FixedPointGraphTraversal(com.google.javascript.jscomp.graph.FixedPointGraphTraversal) Node(com.google.javascript.rhino.Node) GreedyGraphColoring(com.google.javascript.jscomp.graph.GraphColoring.GreedyGraphColoring) LowestCommonAncestorFinder(com.google.javascript.jscomp.graph.LowestCommonAncestorFinder) ImmutableSet(com.google.common.collect.ImmutableSet) IdentityHashMap(java.util.IdentityHashMap) NodeTraversal(com.google.javascript.jscomp.NodeTraversal) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) Set(java.util.Set) ColorRegistry(com.google.javascript.jscomp.colors.ColorRegistry) Logger(java.util.logging.Logger) Preconditions.checkState(com.google.common.base.Preconditions.checkState) AbstractPostOrderCallback(com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback) NodeUtil(com.google.javascript.jscomp.NodeUtil) List(java.util.List) Color(com.google.javascript.jscomp.colors.Color) Annotation(com.google.javascript.jscomp.graph.Annotation) AbstractCompiler(com.google.javascript.jscomp.AbstractCompiler) GraphColoring(com.google.javascript.jscomp.graph.GraphColoring) BitSet(java.util.BitSet) Comparator(java.util.Comparator) LowestCommonAncestorFinder(com.google.javascript.jscomp.graph.LowestCommonAncestorFinder) GraphNode(com.google.javascript.jscomp.graph.GraphNode) Node(com.google.javascript.rhino.Node) ArrayList(java.util.ArrayList) DefaultNameGenerator(com.google.javascript.jscomp.DefaultNameGenerator) DefaultNameGenerator(com.google.javascript.jscomp.DefaultNameGenerator) NameGenerator(com.google.javascript.jscomp.NameGenerator) ImmutableSet(com.google.common.collect.ImmutableSet) GreedyGraphColoring(com.google.javascript.jscomp.graph.GraphColoring.GreedyGraphColoring)

Example 3 with GreedyGraphColoring

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

Aggregations

GreedyGraphColoring (com.google.javascript.jscomp.graph.GraphColoring.GreedyGraphColoring)3 GraphNode (com.google.javascript.jscomp.graph.GraphNode)3 Node (com.google.javascript.rhino.Node)3 ImmutableSet (com.google.common.collect.ImmutableSet)2 ArrayList (java.util.ArrayList)2 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)1 Preconditions.checkNotNull (com.google.common.base.Preconditions.checkNotNull)1 Preconditions.checkState (com.google.common.base.Preconditions.checkState)1 AbstractCompiler (com.google.javascript.jscomp.AbstractCompiler)1 CompilerPass (com.google.javascript.jscomp.CompilerPass)1 DefaultNameGenerator (com.google.javascript.jscomp.DefaultNameGenerator)1 GatherGetterAndSetterProperties (com.google.javascript.jscomp.GatherGetterAndSetterProperties)1 NameGenerator (com.google.javascript.jscomp.NameGenerator)1 NodeTraversal (com.google.javascript.jscomp.NodeTraversal)1 AbstractPostOrderCallback (com.google.javascript.jscomp.NodeTraversal.AbstractPostOrderCallback)1 NodeUtil (com.google.javascript.jscomp.NodeUtil)1 AllVarsDeclaredInFunction (com.google.javascript.jscomp.NodeUtil.AllVarsDeclaredInFunction)1 Color (com.google.javascript.jscomp.colors.Color)1 ColorRegistry (com.google.javascript.jscomp.colors.ColorRegistry)1 StandardColors (com.google.javascript.jscomp.colors.StandardColors)1