Conditionally optimize precompile based on entry point.

This change yields a net savings in the Compiler command line entry point by
doing more optimization in the precompile phase.  The Precompile entry point
will continue to do minimal optimization.  In additional, -draftCompile will
prevent the optimization loop that happened during the precompile as well.

Review by: spoon

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5546 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/Compiler.java b/dev/core/src/com/google/gwt/dev/Compiler.java
index 385baca..9de717c 100644
--- a/dev/core/src/com/google/gwt/dev/Compiler.java
+++ b/dev/core/src/com/google/gwt/dev/Compiler.java
@@ -188,6 +188,8 @@
           TreeLogger branch = logger.branch(TreeLogger.INFO,
               "Compiling module " + moduleName);
 
+          // Optimize early since permutation compiles will run in process.
+          options.setOptimizePrecompile(true);
           Precompilation precompilation = Precompile.precompile(branch,
               options, module, options.getGenDir(), compilerWorkDir,
               options.getDumpSignatureFile());
diff --git a/dev/core/src/com/google/gwt/dev/GWTCompiler.java b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
index 4a1cc19..9f90509 100644
--- a/dev/core/src/com/google/gwt/dev/GWTCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/GWTCompiler.java
@@ -181,6 +181,8 @@
           logger = logger.branch(TreeLogger.INFO, "Compiling module "
               + moduleName);
 
+          // Optimize early since permutation compiles will run in process.
+          options.setOptimizePrecompile(true);
           Precompilation precompilation = Precompile.precompile(logger,
               options, module, options.getGenDir(), compilerWorkDir,
               options.getDumpSignatureFile());
diff --git a/dev/core/src/com/google/gwt/dev/Precompile.java b/dev/core/src/com/google/gwt/dev/Precompile.java
index 2344216..5c28b9e 100644
--- a/dev/core/src/com/google/gwt/dev/Precompile.java
+++ b/dev/core/src/com/google/gwt/dev/Precompile.java
@@ -180,6 +180,10 @@
       return jjsOptions.isEnableAssertions();
     }
 
+    public boolean isOptimizePrecompile() {
+      return jjsOptions.isOptimizePrecompile();
+    }
+
     public boolean isRunAsyncEnabled() {
       return jjsOptions.isRunAsyncEnabled();
     }
@@ -236,6 +240,10 @@
       this.maxPermsPerPrecompile = maxPermsPerPrecompile;
     }
 
+    public void setOptimizePrecompile(boolean optimize) {
+      jjsOptions.setOptimizePrecompile(optimize);
+    }
+
     public void setOutput(JsOutputOption output) {
       jjsOptions.setOutput(output);
     }
@@ -427,6 +435,8 @@
           module, compilationState, generatorArtifacts,
           new PropertyPermutations(module.getProperties()), genDir,
           generatorResourcesDir);
+      // Never optimize on a validation run.
+      jjsOptions.setOptimizePrecompile(false);
       JavaToJavaScriptCompiler.precompile(logger, module, rpo, declEntryPts,
           additionalRootTypes, jjsOptions, true);
       return true;
@@ -500,6 +510,8 @@
 
   public boolean run(TreeLogger logger) throws UnableToCompleteException {
     boolean originalCompilationStateRetained = options.isCompilationStateRetained();
+    // Avoid early optimizations since permutation compiles will run separately.
+    options.setOptimizePrecompile(false);
 
     for (String moduleName : options.getModuleNames()) {
       File compilerWorkDir = options.getCompilerWorkDir(moduleName);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java b/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java
index 9ca8436..f9ff12c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java
@@ -21,6 +21,7 @@
 import com.google.gwt.dev.util.arg.OptionDisableClassMetadata;
 import com.google.gwt.dev.util.arg.OptionDraftCompile;
 import com.google.gwt.dev.util.arg.OptionEnableAssertions;
+import com.google.gwt.dev.util.arg.OptionOptimizePrecompile;
 import com.google.gwt.dev.util.arg.OptionRunAsyncEnabled;
 import com.google.gwt.dev.util.arg.OptionScriptStyle;
 import com.google.gwt.dev.util.arg.OptionSoycEnabled;
@@ -31,5 +32,5 @@
 public interface JJSOptions extends OptionAggressivelyOptimize,
     OptionDisableClassMetadata, OptionDisableCastChecking, OptionDraftCompile,
     OptionEnableAssertions, OptionRunAsyncEnabled, OptionScriptStyle,
-    OptionSoycEnabled, OptionCompilationStateRetained {
+    OptionSoycEnabled, OptionCompilationStateRetained, OptionOptimizePrecompile {
 }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java b/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java
index 569e1ad..80c49f5 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java
@@ -28,6 +28,7 @@
   private boolean disableClassMetadata = false;
   private boolean draftCompile = false;
   private boolean enableAssertions;
+  private boolean optimizePrecompile = false;
   private JsOutputOption output = JsOutputOption.OBFUSCATED;
   private boolean runAsyncEnabled = true;
   private boolean soycEnabled = false;
@@ -79,6 +80,10 @@
     return enableAssertions;
   }
 
+  public boolean isOptimizePrecompile() {
+    return optimizePrecompile;
+  }
+
   public boolean isRunAsyncEnabled() {
     return runAsyncEnabled;
   }
@@ -111,6 +116,10 @@
     this.enableAssertions = enableAssertions;
   }
 
+  public void setOptimizePrecompile(boolean optimize) {
+    optimizePrecompile = optimize;
+  }
+
   public void setOutput(JsOutputOption output) {
     this.output = output;
   }
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 743472b..282e4a1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -517,17 +517,31 @@
       JavaScriptObjectNormalizer.exec(jprogram);
 
       /*
-       * (4) Minimally optimize the normalized Java AST for the common AST. By
-       * doing a few optimizations early in the multiple permutation scenario,
-       * we can save some work. However, we don't do full optimizations because
-       * our optimizer is currently superlinear, which can lead to net losses
-       * for big apps. We can't fully optimize because we don't yet know the
-       * deferred binding decisions.
+       * 4) Possibly optimize some.
        * 
-       * Don't bother optimizing early if there's only one permutation.
+       * Don't optimizing early if this is a draft compile, or if there's only
+       * one permutation.
        */
-      if (!singlePermutation) {
-        optimizeLoop(jprogram, false);
+      if (!options.isDraftCompile() && !singlePermutation) {
+        if (options.isOptimizePrecompile()) {
+          /*
+           * Go ahead and optimize early, so that each permutation will run
+           * faster. This code path is used by the Compiler entry point. We
+           * assume that we will not be able to perfectly parallelize the
+           * permutation compiles, so let's optimize as much as possible the
+           * common AST. In some cases, this might also have the side benefit of
+           * reducing the total permutation count.
+           */
+          optimize(options, jprogram);
+        } else {
+          /*
+           * Do only minimal early optimizations. This code path is used by the
+           * Precompile entry point. The external system might be able to
+           * perfectly parallelize the permutation compiles, so let's avoid
+           * doing potentially superlinear optimizations on the unified AST.
+           */
+          optimizeLoop(jprogram, false);
+        }
       }
 
       Set<String> rebindRequests = new HashSet<String>();
diff --git a/dev/core/src/com/google/gwt/dev/util/arg/OptionOptimizePrecompile.java b/dev/core/src/com/google/gwt/dev/util/arg/OptionOptimizePrecompile.java
new file mode 100755
index 0000000..e2a6d7b
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/util/arg/OptionOptimizePrecompile.java
@@ -0,0 +1,27 @@
+/*
+ * 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.util.arg;
+
+/**
+ * Option to early optimize the unified AST during a precompile. Does not
+ * correspond to any command line option. This is used directly by compiler
+ * clients to specify whether or not to optimize early.
+ */
+public interface OptionOptimizePrecompile {
+  boolean isOptimizePrecompile();
+
+  void setOptimizePrecompile(boolean optimize);
+}