Make the GWT compiler pluggable through an experimental "x.compiler.class" configuration property.
This allows experimenting with the GWT compile chain.
Review by: spoon
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@6052 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/CompilePerms.java b/dev/core/src/com/google/gwt/dev/CompilePerms.java
index 8fef668..d033f5d 100644
--- a/dev/core/src/com/google/gwt/dev/CompilePerms.java
+++ b/dev/core/src/com/google/gwt/dev/CompilePerms.java
@@ -18,7 +18,6 @@
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.CompileTaskRunner.CompileTask;
-import com.google.gwt.dev.jjs.JavaToJavaScriptCompiler;
import com.google.gwt.dev.jjs.PermutationResult;
import com.google.gwt.dev.jjs.UnifiedAst;
import com.google.gwt.dev.util.FileBackedObject;
@@ -185,7 +184,7 @@
public static PermutationResult compile(TreeLogger logger,
Permutation permutation, UnifiedAst unifiedAst)
throws UnableToCompleteException {
- return JavaToJavaScriptCompiler.compilePermutation(logger, unifiedAst,
+ return unifiedAst.compilePermutation(logger,
permutation.getRebindAnswers(), permutation.getPropertyOracles(),
permutation.getId());
}
diff --git a/dev/core/src/com/google/gwt/dev/Permutation.java b/dev/core/src/com/google/gwt/dev/Permutation.java
index 28bacf7..c0319b1 100644
--- a/dev/core/src/com/google/gwt/dev/Permutation.java
+++ b/dev/core/src/com/google/gwt/dev/Permutation.java
@@ -19,9 +19,10 @@
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
-import java.util.Set;
import java.util.SortedMap;
+import java.util.SortedSet;
import java.util.TreeMap;
/**
@@ -58,11 +59,17 @@
}
public SortedMap<String, String> getRebindAnswers() {
- return rebindAnswers;
+ return Collections.unmodifiableSortedMap(rebindAnswers);
}
- public void mergeFrom(Permutation other) {
- assert rebindAnswers.equals(other.rebindAnswers);
+ public void mergeFrom(Permutation other, SortedSet<String> liveRebindRequests) {
+ if (getClass().desiredAssertionStatus()) {
+ for (String rebindRequest : liveRebindRequests) {
+ String myAnswer = rebindAnswers.get(rebindRequest);
+ String otherAnswer = other.rebindAnswers.get(rebindRequest);
+ assert myAnswer.equals(otherAnswer);
+ }
+ }
assert !propertyOracles.isEmpty();
assert !other.propertyOracles.isEmpty();
propertyOracles.addAll(other.propertyOracles);
@@ -72,8 +79,4 @@
public void putRebindAnswer(String requestType, String resultType) {
rebindAnswers.put(requestType, resultType);
}
-
- public void reduceRebindAnswers(Set<String> liveRebindRequests) {
- rebindAnswers.keySet().retainAll(liveRebindRequests);
- }
}
diff --git a/dev/core/src/com/google/gwt/dev/Precompile.java b/dev/core/src/com/google/gwt/dev/Precompile.java
index a529f16..811892d 100644
--- a/dev/core/src/com/google/gwt/dev/Precompile.java
+++ b/dev/core/src/com/google/gwt/dev/Precompile.java
@@ -31,9 +31,10 @@
import com.google.gwt.dev.javac.StandardGeneratorContext;
import com.google.gwt.dev.jdt.RebindOracle;
import com.google.gwt.dev.jdt.RebindPermutationOracle;
+import com.google.gwt.dev.jjs.AbstractCompiler;
import com.google.gwt.dev.jjs.JJSOptions;
import com.google.gwt.dev.jjs.JJSOptionsImpl;
-import com.google.gwt.dev.jjs.JavaToJavaScriptCompiler;
+import com.google.gwt.dev.jjs.JavaScriptCompiler;
import com.google.gwt.dev.jjs.JsOutputOption;
import com.google.gwt.dev.jjs.UnifiedAst;
import com.google.gwt.dev.shell.CheckForUpdates;
@@ -448,7 +449,7 @@
generatorResourcesDir);
// Never optimize on a validation run.
jjsOptions.setOptimizePrecompile(false);
- JavaToJavaScriptCompiler.precompile(logger, module, rpo, declEntryPts,
+ getCompiler(module).precompile(logger, module, rpo, declEntryPts,
additionalRootTypes, jjsOptions, true);
return true;
} catch (UnableToCompleteException e) {
@@ -457,6 +458,28 @@
}
}
+ private static AbstractCompiler getCompiler(ModuleDef module) {
+ ConfigurationProperty compilerClassProp = module.getProperties().createConfiguration(
+ "x.compiler.class", false);
+ String compilerClassName = compilerClassProp.getValue();
+ if (compilerClassName == null || compilerClassName.length() == 0) {
+ return new JavaScriptCompiler();
+ }
+ Throwable caught;
+ try {
+ Class<?> compilerClass = Class.forName(compilerClassName);
+ return (AbstractCompiler) compilerClass.newInstance();
+ } catch (ClassNotFoundException e) {
+ caught = e;
+ } catch (InstantiationException e) {
+ caught = e;
+ } catch (IllegalAccessException e) {
+ caught = e;
+ }
+ throw new RuntimeException("Unable to instantiate compiler class '"
+ + compilerClassName + "'", caught);
+ }
+
private static Precompilation precompile(TreeLogger logger,
JJSOptions jjsOptions, ModuleDef module, int permutationBase,
PropertyPermutations allPermutations, File genDir,
@@ -481,7 +504,7 @@
module, compilationState, generatedArtifacts, allPermutations,
genDir, generatorResourcesDir);
PerfLogger.start("Precompile");
- UnifiedAst unifiedAst = JavaToJavaScriptCompiler.precompile(logger,
+ UnifiedAst unifiedAst = getCompiler(module).precompile(logger,
module, rpo, declEntryPts, null, jjsOptions,
rpo.getPermuationCount() == 1);
PerfLogger.end();
@@ -490,15 +513,18 @@
Permutation[] permutations = rpo.getPermutations();
// Sort the permutations by an ordered key to ensure determinism.
SortedMap<String, Permutation> merged = new TreeMap<String, Permutation>();
+ SortedSet<String> liveRebindRequests = unifiedAst.getRebindRequests();
for (Permutation permutation : permutations) {
- permutation.reduceRebindAnswers(unifiedAst.getRebindRequests());
- // Arbitrarily choose as a key the stringified map of rebind answers.
- String rebindResultsString = permutation.getRebindAnswers().toString();
- if (merged.containsKey(rebindResultsString)) {
- Permutation existing = merged.get(rebindResultsString);
- existing.mergeFrom(permutation);
+ // Construct a key from the stringified map of live rebind answers.
+ SortedMap<String, String> rebindAnswers = new TreeMap<String, String>(
+ permutation.getRebindAnswers());
+ rebindAnswers.keySet().retainAll(liveRebindRequests);
+ String key = rebindAnswers.toString();
+ if (merged.containsKey(key)) {
+ Permutation existing = merged.get(key);
+ existing.mergeFrom(permutation, liveRebindRequests);
} else {
- merged.put(rebindResultsString, permutation);
+ merged.put(key, permutation);
}
}
return new Precompilation(unifiedAst, merged.values(), permutationBase,
diff --git a/dev/core/src/com/google/gwt/dev/jjs/AbstractCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/AbstractCompiler.java
new file mode 100644
index 0000000..f1d94bb
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/jjs/AbstractCompiler.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jjs;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.cfg.ModuleDef;
+import com.google.gwt.dev.jdt.RebindPermutationOracle;
+
+/**
+ * A Compiler used to compile a GWT project into artifacts.
+ */
+public interface AbstractCompiler {
+ /**
+ * Performs a precompilation, returning an object that can then be used to
+ * compile individual permutations..
+ *
+ * @param logger the logger to use
+ * @param module the module to compile
+ * @param rpo the RebindPermutationOracle
+ * @param declEntryPts the set of entry classes declared in a GWT module;
+ * these will be automatically rebound
+ * @param additionalRootTypes additional classes that should serve as code
+ * roots; will not be rebound; may be <code>null</code>
+ * @param options the compiler options
+ * @param singlePermutation if true, do not pre-optimize the resulting AST or
+ * allow serialization of the result
+ * @return the unified AST used to drive permutation compiles
+ * @throws UnableToCompleteException if an error other than
+ * {@link OutOfMemoryError} occurs
+ */
+ UnifiedAst precompile(TreeLogger logger, ModuleDef module,
+ RebindPermutationOracle rpo, String[] declEntryPts,
+ String[] additionalRootTypes, JJSOptions options,
+ boolean singlePermutation) throws UnableToCompleteException;
+}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaScriptCompiler.java
new file mode 100644
index 0000000..a3b9976
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaScriptCompiler.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jjs;
+
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.dev.cfg.ModuleDef;
+import com.google.gwt.dev.jdt.RebindPermutationOracle;
+
+/**
+ * Uses the default compiler {@link JavaToJavaScriptCompiler}.
+ */
+public class JavaScriptCompiler implements AbstractCompiler {
+
+ public UnifiedAst precompile(TreeLogger logger, ModuleDef module,
+ RebindPermutationOracle rpo, String[] declEntryPts,
+ String[] additionalRootTypes, JJSOptions options,
+ boolean singlePermutation) throws UnableToCompleteException {
+ return JavaToJavaScriptCompiler.precompile(logger, module, rpo,
+ declEntryPts, additionalRootTypes, options, singlePermutation);
+ }
+
+}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index da19855..a689889 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -191,9 +191,10 @@
* @param unifiedAst the result of a
* {@link #precompile(TreeLogger, WebModeCompilerFrontEnd, String[], JJSOptions, boolean)}
* @param rebindAnswers the set of rebind answers to resolve all outstanding
- * rebind decisions
- * @param propertyOracles All property oracles corresponding to this
- * permutation.
+ * rebind decisions for this permutation
+ * @param propertyOracles all property oracles corresponding to this
+ * permutation
+ * @param permutationId the unique id of this permutation
* @return the output JavaScript
* @throws UnableToCompleteException if an error other than
* {@link OutOfMemoryError} occurs
diff --git a/dev/core/src/com/google/gwt/dev/jjs/UnifiedAst.java b/dev/core/src/com/google/gwt/dev/jjs/UnifiedAst.java
index d0d2e6d..a33b8e8 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/UnifiedAst.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/UnifiedAst.java
@@ -15,6 +15,9 @@
*/
package com.google.gwt.dev.jjs;
+import com.google.gwt.core.ext.PropertyOracle;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.util.PerfLogger;
@@ -26,6 +29,7 @@
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Collections;
+import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -34,7 +38,7 @@
* Represents a unified, non-permutation specific AST. This AST is used to drive
* per-permutation compiles.
*/
-public final class UnifiedAst implements Serializable {
+public class UnifiedAst implements Serializable {
/**
* Encapsulates the combined programs.
@@ -130,6 +134,37 @@
}
/**
+ * Copy constructor, invalidates the original.
+ */
+ UnifiedAst(UnifiedAst other) {
+ this.options = other.options;
+ this.initialAst = other.initialAst;
+ other.initialAst = null; // steal its copy
+ this.rebindRequests = other.rebindRequests;
+ this.serializedAst = other.serializedAst;
+ }
+
+ /**
+ * Compiles a particular permutation.
+ *
+ * @param logger the logger to use
+ * @param rebindAnswers the set of rebind answers to resolve all outstanding
+ * rebind decisions for this permutation
+ * @param propertyOracles all property oracles corresponding to this
+ * permutation
+ * @param permutationId the unique id of this permutation
+ * @return the permutation result
+ * @throws UnableToCompleteException if an error other than
+ * {@link OutOfMemoryError} occurs
+ */
+ public PermutationResult compilePermutation(TreeLogger logger,
+ Map<String, String> rebindAnswers, PropertyOracle[] propertyOracles,
+ int permutationId) throws UnableToCompleteException {
+ return JavaToJavaScriptCompiler.compilePermutation(logger, this,
+ rebindAnswers, propertyOracles, permutationId);
+ }
+
+ /**
* Returns the active set of JJS options associated with this compile.
*/
public JJSOptions getOptions() {