com.google.javascript.jscomp
Class SpecializeModule

java.lang.Object
  extended by com.google.javascript.jscomp.SpecializeModule
All Implemented Interfaces:
CompilerPass

public class SpecializeModule
extends Object
implements CompilerPass

Beginnings of an optimization to specialize the initial module at the cost of increasing code in later modules. This is still very experimental. High-level overview: This optimization replaces functions in the initial module with specialized versions that are only safe in the initial module. The original, general, versions of the functions are "fixed up" in later modules. This optimization can shrink the initial module significantly but the fixup code in later modules increases overall code size. Implementation approach: We take a ridiculously naive approach: remove the initial module from the rest of the AST, optimize it with existing optimization passes (recording which functions have been specialized), put it back in the AST, and add fixups restoring the general versions of the functions in each module that depends on the initial module. Since it is only safe to specialize functions that can be fixed up, we don't allow specialization of local functions and functions that are aliased. We currently run three optimizations on the isolated AST: InlineFunctions, DevirtualizePrototypeMethods, and RemoveUnusedPrototypeProperties. These optimizations rely on a coarse-grained name-based analysis to maintain safety properties and thus are likely to see some benefit when applied in isolation. InlineFunctions is truly specializing -- it replaces functions with versions that have calls to other functions inlined into them, while RemoveUnusedPrototypeProperties is really just removing properties that aren't used in the initial module and adding copies further down in the module graph. It would probably be more elegant to give CrossModuleMethodMotion permission to make copies of methods instead. There are additional passes that might benefit from being made specialization-aware: - OptimizeParameters - Any pass that is too slow to run over the entire AST but might be acceptable on only the initial module: - RemoveUnusedNames - Also, any pass that uses the results of PureFunctionIdentifier to determine when it is safe to remove code might benefit (e.g. the peephole passes), since PureFunctionIdentifier relies on SimpleDefinitionFinder, which would be more precise when running on only the initial module.


Nested Class Summary
static class SpecializeModule.SpecializationState
          A class to hold state during SpecializeModule.
 
Constructor Summary
SpecializeModule(AbstractCompiler compiler, PassFactory... specializationPassFactories)
           
 
Method Summary
 Collection<JSModule> getDirectDependents(JSModule module)
          Returns a list of modules that directly depend on the given module.
 void process(Node externs, Node root)
          Performs initial module specialization.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

SpecializeModule

public SpecializeModule(AbstractCompiler compiler,
                        PassFactory... specializationPassFactories)
Method Detail

process

public void process(Node externs,
                    Node root)
Performs initial module specialization. The process is as follows: 1) Make a copy of each of the inputs in the initial root and put them in a fake AST that looks like it is the whole program. 2) Run the specializing compiler passes over the fake initial module AST until it reaches a fixed point, recording which functions are specialized or removed. 3) Replace the original input roots with the specialized input roots 4) For each module that directly depends on the initial module, add fixups for the specialized and removed functions. Right now we add fixups for for every function that was specialzed or removed -- we could be smarter about this and for each dependent module only add the functions that it needs. 5) Add dummy variables declaring the removed function to the end of the now-specialized initial module. This is needed to keep VarCheck from complaining.

Specified by:
process in interface CompilerPass
Parameters:
externs - Top of external JS tree
root - Top of JS tree

getDirectDependents

public Collection<JSModule> getDirectDependents(JSModule module)
Returns a list of modules that directly depend on the given module. This probably deserves to be in JSModuleGraph.