Fix MimimalRebuildCache leak when compiling multiple modules.
Bug: #9155
Bug-Link: https://github.com/gwtproject/gwt/issues/9155
Change-Id: I324b15c26ceb3dfcff6b1e1bd7aedec3c2be1e94
diff --git a/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java b/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java
index 3e8c7a0..94c5c60 100644
--- a/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java
+++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java
@@ -359,7 +359,7 @@
job.setCompileStrategy(minimalRebuildCache.isPopulated() ? CompileStrategy.INCREMENTAL
: CompileStrategy.FULL);
- boolean success = new Compiler(runOptions, minimalRebuildCache).run(compileLogger, module);
+ boolean success = Compiler.compile(compileLogger, runOptions, minimalRebuildCache, module);
if (success) {
publishedCompileDir = compileDir;
previousInputSummary = inputSummary;
diff --git a/dev/core/src/com/google/gwt/dev/Compiler.java b/dev/core/src/com/google/gwt/dev/Compiler.java
index bf5b2ab..9496222 100644
--- a/dev/core/src/com/google/gwt/dev/Compiler.java
+++ b/dev/core/src/com/google/gwt/dev/Compiler.java
@@ -46,6 +46,7 @@
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.FutureTask;
@@ -114,7 +115,7 @@
updater = CheckForUpdates.checkForUpdatesInBackgroundThread(logger,
CheckForUpdates.ONE_DAY);
}
- boolean success = new Compiler(options).run(logger);
+ boolean success = Compiler.compile(logger, options);
if (success) {
CheckForUpdates.logUpdateAvailable(logger, updater);
}
@@ -129,35 +130,39 @@
// Exit w/ non-success code.
System.exit(1);
}
- private CompilerContext compilerContext;
- private final CompilerContext.Builder compilerContextBuilder;
- private final CompilerOptionsImpl options;
-
- public Compiler(CompilerOptions compilerOptions) {
- this(compilerOptions, compilerOptions.isIncrementalCompileEnabled() ? new MinimalRebuildCache()
- : new NullRebuildCache());
- }
-
- public Compiler(CompilerOptions compilerOptions, MinimalRebuildCache minimalRebuildCache) {
- this.options = new CompilerOptionsImpl(compilerOptions);
- this.compilerContextBuilder = new CompilerContext.Builder();
- this.compilerContext = compilerContextBuilder.options(options)
- .minimalRebuildCache(minimalRebuildCache).build();
- }
-
- public boolean run(TreeLogger logger) throws UnableToCompleteException {
- ModuleDef[] modules = new ModuleDef[options.getModuleNames().size()];
- int i = 0;
- for (String moduleName : options.getModuleNames()) {
- ModuleDef module = ModuleDefLoader.loadFromClassPath(logger, moduleName, true);
- modules[i++] = module;
- }
- return run(logger, modules);
- }
-
- public boolean run(TreeLogger logger, ModuleDef... modules)
+ public static boolean compile(
+ TreeLogger logger, CompilerOptions compilerOptions)
throws UnableToCompleteException {
+ List<ModuleDef> moduleDefs = new ArrayList<>();
+ for (String moduleName : compilerOptions.getModuleNames()) {
+ moduleDefs.add(ModuleDefLoader.loadFromClassPath(logger, moduleName, true));
+ }
+
+ boolean result = true;
+ for (ModuleDef moduleDef : moduleDefs) {
+ result &= compile(logger, compilerOptions, moduleDef);
+ }
+ return result;
+ }
+
+ public static boolean compile(
+ TreeLogger logger, CompilerOptions compilerOptions, ModuleDef moduleDef)
+ throws UnableToCompleteException {
+ MinimalRebuildCache minimalRebuildCache = compilerOptions.isIncrementalCompileEnabled()
+ ? new MinimalRebuildCache()
+ : new NullRebuildCache();
+ return compile(logger, compilerOptions, minimalRebuildCache, moduleDef);
+ }
+
+ public static boolean compile(
+ TreeLogger logger,
+ CompilerOptions compilerOptions,
+ MinimalRebuildCache minimalRebuildCache,
+ ModuleDef moduleDef)
+ throws UnableToCompleteException {
+
+ CompilerOptionsImpl options = new CompilerOptionsImpl(compilerOptions);
boolean tempWorkDir = false;
try {
if (options.getWorkDir() == null) {
@@ -179,69 +184,70 @@
options.setNamespace(JsNamespaceOption.NONE);
}
- compilerContext =
- compilerContextBuilder.unitCache(getOrCreateUnitCache(logger, options)).build();
-
- for (ModuleDef module : modules) {
- compilerContext = compilerContextBuilder.module(module).build();
- String moduleName = module.getCanonicalName();
- if (options.isValidateOnly()) {
- if (!Precompile.validate(logger, compilerContext)) {
- return false;
- }
- } else {
- long beforeCompileMs = System.currentTimeMillis();
- TreeLogger branch = logger.branch(TreeLogger.INFO,
- "Compiling module " + moduleName);
-
- Precompilation precompilation = Precompile.precompile(branch, compilerContext);
- if (precompilation == null) {
- return false;
- }
- // TODO: move to precompile() after params are refactored
- if (!options.shouldSaveSource()) {
- precompilation.removeSourceArtifacts(branch);
- }
-
- Event compilePermutationsEvent =
- SpeedTracerLogger.start(CompilerEventType.COMPILE_PERMUTATIONS);
- Permutation[] allPerms = precompilation.getPermutations();
- List<PersistenceBackedObject<PermutationResult>> resultFiles =
- CompilePerms.makeResultFiles(
- options.getCompilerWorkDir(moduleName), allPerms, options);
- CompilePerms.compile(branch, compilerContext, precompilation, allPerms,
- options.getLocalWorkers(), resultFiles);
- compilePermutationsEvent.end();
-
- ArtifactSet generatedArtifacts = precompilation.getGeneratedArtifacts();
- PrecompileTaskOptions precompileOptions = precompilation.getUnifiedAst().getOptions();
-
- precompilation = null; // No longer needed, so save the memory
- long afterCompileMs = System.currentTimeMillis();
- double compileSeconds = (afterCompileMs - beforeCompileMs) / 1000d;
- branch.log(TreeLogger.INFO,
- String.format("Compilation succeeded -- %.3fs", compileSeconds));
-
- long beforeLinkMs = System.currentTimeMillis();
- Event linkEvent = SpeedTracerLogger.start(CompilerEventType.LINK);
- File absPath = new File(options.getWarDir(), module.getName());
- absPath = absPath.getAbsoluteFile();
-
- String logMessage = "Linking into " + absPath;
- if (options.getExtraDir() != null) {
- File absExtrasPath = new File(options.getExtraDir(),
- module.getName());
- absExtrasPath = absExtrasPath.getAbsoluteFile();
- logMessage += "; Writing extras to " + absExtrasPath;
- }
- Link.link(logger.branch(TreeLogger.TRACE, logMessage), module,
- module.getPublicResourceOracle(), generatedArtifacts, allPerms, resultFiles,
- Sets.<PermutationResult>newHashSet(), precompileOptions, options);
- linkEvent.end();
- long afterLinkMs = System.currentTimeMillis();
- double linkSeconds = (afterLinkMs - beforeLinkMs) / 1000d;
- branch.log(TreeLogger.INFO, String.format("Linking succeeded -- %.3fs", linkSeconds));
+ CompilerContext compilerContext =
+ new CompilerContext.Builder()
+ .options(options)
+ .minimalRebuildCache(minimalRebuildCache)
+ .unitCache(getOrCreateUnitCache(logger, options))
+ .module(moduleDef)
+ .build();
+ String moduleName = moduleDef.getCanonicalName();
+ if (options.isValidateOnly()) {
+ if (!Precompile.validate(logger, compilerContext)) {
+ return false;
}
+ } else {
+ long beforeCompileMs = System.currentTimeMillis();
+ TreeLogger branch = logger.branch(TreeLogger.INFO,
+ "Compiling module " + moduleName);
+
+ Precompilation precompilation = Precompile.precompile(branch, compilerContext);
+ if (precompilation == null) {
+ return false;
+ }
+ // TODO: move to precompile() after params are refactored
+ if (!options.shouldSaveSource()) {
+ precompilation.removeSourceArtifacts(branch);
+ }
+
+ Event compilePermutationsEvent =
+ SpeedTracerLogger.start(CompilerEventType.COMPILE_PERMUTATIONS);
+ Permutation[] allPerms = precompilation.getPermutations();
+ List<PersistenceBackedObject<PermutationResult>> resultFiles =
+ CompilePerms.makeResultFiles(
+ options.getCompilerWorkDir(moduleName), allPerms, options);
+ CompilePerms.compile(branch, compilerContext, precompilation, allPerms,
+ options.getLocalWorkers(), resultFiles);
+ compilePermutationsEvent.end();
+
+ ArtifactSet generatedArtifacts = precompilation.getGeneratedArtifacts();
+ PrecompileTaskOptions precompileOptions = precompilation.getUnifiedAst().getOptions();
+
+ precompilation = null; // No longer needed, so save the memory
+ long afterCompileMs = System.currentTimeMillis();
+ double compileSeconds = (afterCompileMs - beforeCompileMs) / 1000d;
+ branch.log(TreeLogger.INFO,
+ String.format("Compilation succeeded -- %.3fs", compileSeconds));
+
+ long beforeLinkMs = System.currentTimeMillis();
+ Event linkEvent = SpeedTracerLogger.start(CompilerEventType.LINK);
+ File absPath = new File(options.getWarDir(), moduleDef.getName());
+ absPath = absPath.getAbsoluteFile();
+
+ String logMessage = "Linking into " + absPath;
+ if (options.getExtraDir() != null) {
+ File absExtrasPath = new File(options.getExtraDir(),
+ moduleDef.getName());
+ absExtrasPath = absExtrasPath.getAbsoluteFile();
+ logMessage += "; Writing extras to " + absExtrasPath;
+ }
+ Link.link(logger.branch(TreeLogger.TRACE, logMessage), moduleDef,
+ moduleDef.getPublicResourceOracle(), generatedArtifacts, allPerms, resultFiles,
+ Sets.<PermutationResult>newHashSet(), precompileOptions, options);
+ linkEvent.end();
+ long afterLinkMs = System.currentTimeMillis();
+ double linkSeconds = (afterLinkMs - beforeLinkMs) / 1000d;
+ branch.log(TreeLogger.INFO, String.format("Linking succeeded -- %.3fs", linkSeconds));
}
} catch (IOException e) {
diff --git a/dev/core/test/com/google/gwt/core/ext/linker/SourceMapTest.java b/dev/core/test/com/google/gwt/core/ext/linker/SourceMapTest.java
index 248ec65..5ee4712 100644
--- a/dev/core/test/com/google/gwt/core/ext/linker/SourceMapTest.java
+++ b/dev/core/test/com/google/gwt/core/ext/linker/SourceMapTest.java
@@ -23,6 +23,7 @@
import com.google.gwt.core.ext.soyc.coderef.EntityDescriptorJsonTranslator;
import com.google.gwt.core.ext.soyc.coderef.EntityRecorder;
import com.google.gwt.core.ext.soyc.coderef.MethodDescriptor;
+import com.google.gwt.dev.Compiler;
import com.google.gwt.dev.CompilerOptionsImpl;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
@@ -520,7 +521,7 @@
options.setExtraDir(new File(work, "extra"));
PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
logger.setMaxDetail(TreeLogger.ERROR);
- new com.google.gwt.dev.Compiler(options).run(logger);
+ Compiler.compile(logger, options);
// Change parentDir for cached/pre-built reports
String parentDir = options.getExtraDir() + "/" + benchmark;
testSymbolMapsCorrespondence(new File(parentDir + "/symbolMaps/"));
diff --git a/dev/core/test/com/google/gwt/core/ext/linker/SymbolMapTest.java b/dev/core/test/com/google/gwt/core/ext/linker/SymbolMapTest.java
index 8b9beb0..a0a774a 100644
--- a/dev/core/test/com/google/gwt/core/ext/linker/SymbolMapTest.java
+++ b/dev/core/test/com/google/gwt/core/ext/linker/SymbolMapTest.java
@@ -17,6 +17,7 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.Compiler;
import com.google.gwt.dev.CompilerOptionsImpl;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.OptionOptimize;
@@ -217,7 +218,7 @@
options.setOptimizationLevel(optimizeLevel);
PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
logger.setMaxDetail(TreeLogger.ERROR);
- new com.google.gwt.dev.Compiler(options).run(logger);
+ Compiler.compile(logger, options);
// Change parentDir for cached/pre-built reports
String parentDir = options.getExtraDir() + "/" + benchmark;
for (Map<String, SimpleSymbolData> symbolDataByJsniIdentifier :
diff --git a/dev/core/test/com/google/gwt/dev/CompilerTest.java b/dev/core/test/com/google/gwt/dev/CompilerTest.java
index b41cda7..e6aa553 100644
--- a/dev/core/test/com/google/gwt/dev/CompilerTest.java
+++ b/dev/core/test/com/google/gwt/dev/CompilerTest.java
@@ -19,6 +19,7 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.UnstableNestedAnonymousGenerator.OutputVersion;
import com.google.gwt.dev.cfg.EntryMethodHolderGenerator;
+import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.ModuleDefLoader;
import com.google.gwt.dev.cfg.ResourceLoader;
import com.google.gwt.dev.cfg.ResourceLoaders;
@@ -2341,7 +2342,7 @@
options.setExtraDir(new File(compileWorkDir, "extra"));
// Run the compiler once here.
- new Compiler(options).run(logger);
+ Compiler.compile(logger, options);
} finally {
Util.recursiveDelete(compileWorkDir, false);
if (oldPersistentUnitCacheValue == null) {
@@ -2369,14 +2370,14 @@
TreeLogger logger = TreeLogger.NULL;
// Run the compiler once here.
- new Compiler(options).run(logger);
+ Compiler.compile(logger, options);
Set<String> firstTimeOutput =
Sets.newHashSet(new File(options.getWarDir() + "/hello").list());
options.setWarDir(new File(secondCompileWorkDir, "war"));
options.setExtraDir(new File(secondCompileWorkDir, "extra"));
// Run the compiler for a second time here.
- new Compiler(options).run(logger);
+ Compiler.compile(logger, options);
Set<String> secondTimeOutput =
Sets.newHashSet(new File(options.getWarDir() + "/hello").list());
@@ -2520,11 +2521,10 @@
// Cause the module to be cached with a reference to the prefixed resource loader so that the
// compile process will see those resources.
ModuleDefLoader.clearModuleCache();
- ModuleDefLoader.loadFromResources(logger, moduleName, resourceLoader, true);
+ ModuleDef moduleDef = ModuleDefLoader.loadFromResources(logger, moduleName, resourceLoader, true);
// Run the compile.
- Compiler compiler = new Compiler(compilerOptions, minimalRebuildCache);
- compiler.run(logger);
+ Compiler.compile(logger, compilerOptions, minimalRebuildCache, moduleDef);
// Find, read and return the created JS.
File outputJsFile = null;
diff --git a/dev/core/test/com/google/gwt/dev/SoycTest.java b/dev/core/test/com/google/gwt/dev/SoycTest.java
index 382008f..18afe86 100644
--- a/dev/core/test/com/google/gwt/dev/SoycTest.java
+++ b/dev/core/test/com/google/gwt/dev/SoycTest.java
@@ -42,7 +42,7 @@
options.setExtraDir(new File(work, "extra"));
PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
logger.setMaxDetail(TreeLogger.ERROR);
- new Compiler(options).run(logger);
+ Compiler.compile(logger, options);
// make sure the files have been produced
assertTrue(new File(options.getExtraDir() + "/hello/soycReport/compile-report/index.html").exists());
diff --git a/user/src/com/google/gwt/junit/JUnitShell.java b/user/src/com/google/gwt/junit/JUnitShell.java
index e4f1653..3cbbc4b 100644
--- a/user/src/com/google/gwt/junit/JUnitShell.java
+++ b/user/src/com/google/gwt/junit/JUnitShell.java
@@ -1089,7 +1089,7 @@
boolean success = false;
try {
- success = new Compiler(options).run(getTopLogger(), module);
+ success = Compiler.compile(getTopLogger(), options, module);
} catch (Exception e) {
getTopLogger().log(Type.ERROR, "Compiler aborted with an exception ", e);
}