/*
 * Copyright 2008 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.core.ext.linker.Artifact;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.CompilationMetricsArtifact;
import com.google.gwt.core.ext.linker.EmittedArtifact;
import com.google.gwt.core.ext.linker.EmittedArtifact.Visibility;
import com.google.gwt.core.ext.linker.ModuleMetricsArtifact;
import com.google.gwt.core.ext.linker.PrecompilationMetricsArtifact;
import com.google.gwt.core.ext.linker.StatementRanges;
import com.google.gwt.core.ext.linker.SymbolData;
import com.google.gwt.core.ext.linker.SyntheticArtifact;
import com.google.gwt.core.ext.linker.impl.StandardSymbolData;
import com.google.gwt.core.ext.soyc.SourceMapRecorder;
import com.google.gwt.core.ext.soyc.coderef.DependencyGraphRecorder;
import com.google.gwt.core.ext.soyc.coderef.EntityRecorder;
import com.google.gwt.core.ext.soyc.impl.DependencyRecorder;
import com.google.gwt.core.ext.soyc.impl.SizeMapRecorder;
import com.google.gwt.core.ext.soyc.impl.SplitPointRecorder;
import com.google.gwt.core.ext.soyc.impl.StoryRecorder;
import com.google.gwt.core.linker.SoycReportLinker;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.MinimalRebuildCache;
import com.google.gwt.dev.Permutation;
import com.google.gwt.dev.PrecompileTaskOptions;
import com.google.gwt.dev.cfg.ConfigurationProperties;
import com.google.gwt.dev.cfg.EntryMethodHolderGenerator;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.PermutationProperties;
import com.google.gwt.dev.javac.CompilationProblemReporter;
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.javac.StandardGeneratorContext;
import com.google.gwt.dev.javac.typemodel.TypeOracle;
import com.google.gwt.dev.jdt.RebindPermutationOracle;
import com.google.gwt.dev.jjs.UnifiedAst.AST;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JTypeOracle.StandardTypes;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.impl.ArrayNormalizer;
import com.google.gwt.dev.jjs.impl.AssertionNormalizer;
import com.google.gwt.dev.jjs.impl.AssertionRemover;
import com.google.gwt.dev.jjs.impl.AstDumper;
import com.google.gwt.dev.jjs.impl.CatchBlockNormalizer;
import com.google.gwt.dev.jjs.impl.CompileTimeConstantsReplacer;
import com.google.gwt.dev.jjs.impl.ComputeCastabilityInformation;
import com.google.gwt.dev.jjs.impl.ComputeExhaustiveCastabilityInformation;
import com.google.gwt.dev.jjs.impl.ControlFlowAnalyzer;
import com.google.gwt.dev.jjs.impl.ControlFlowRecorder;
import com.google.gwt.dev.jjs.impl.DeadCodeElimination;
import com.google.gwt.dev.jjs.impl.DevirtualizeDefaultMethodForwarding;
import com.google.gwt.dev.jjs.impl.Devirtualizer;
import com.google.gwt.dev.jjs.impl.EnumNameObfuscator;
import com.google.gwt.dev.jjs.impl.EnumOrdinalizer;
import com.google.gwt.dev.jjs.impl.EqualityNormalizer;
import com.google.gwt.dev.jjs.impl.Finalizer;
import com.google.gwt.dev.jjs.impl.FixAssignmentsToUnboxOrCast;
import com.google.gwt.dev.jjs.impl.FullOptimizerContext;
import com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST;
import com.google.gwt.dev.jjs.impl.HandleCrossFragmentReferences;
import com.google.gwt.dev.jjs.impl.ImplementCastsAndTypeChecks;
import com.google.gwt.dev.jjs.impl.ImplementClassLiteralsAsFields;
import com.google.gwt.dev.jjs.impl.ImplementJsVarargs;
import com.google.gwt.dev.jjs.impl.JavaAstVerifier;
import com.google.gwt.dev.jjs.impl.JavaToJavaScriptMap;
import com.google.gwt.dev.jjs.impl.JjsUtils;
import com.google.gwt.dev.jjs.impl.JsAbstractTextTransformer;
import com.google.gwt.dev.jjs.impl.JsFunctionClusterer;
import com.google.gwt.dev.jjs.impl.JsInteropRestrictionChecker;
import com.google.gwt.dev.jjs.impl.JsNoopTransformer;
import com.google.gwt.dev.jjs.impl.JsTypeLinker;
import com.google.gwt.dev.jjs.impl.JsniRestrictionChecker;
import com.google.gwt.dev.jjs.impl.LongCastNormalizer;
import com.google.gwt.dev.jjs.impl.LongEmulationNormalizer;
import com.google.gwt.dev.jjs.impl.MakeCallsStatic;
import com.google.gwt.dev.jjs.impl.MethodCallSpecializer;
import com.google.gwt.dev.jjs.impl.MethodCallTightener;
import com.google.gwt.dev.jjs.impl.MethodInliner;
import com.google.gwt.dev.jjs.impl.OptimizerContext;
import com.google.gwt.dev.jjs.impl.OptimizerStats;
import com.google.gwt.dev.jjs.impl.PostOptimizationCompoundAssignmentNormalizer;
import com.google.gwt.dev.jjs.impl.Pruner;
import com.google.gwt.dev.jjs.impl.RecordRebinds;
import com.google.gwt.dev.jjs.impl.RemoveEmptySuperCalls;
import com.google.gwt.dev.jjs.impl.RemoveSpecializations;
import com.google.gwt.dev.jjs.impl.ReplaceCallsToNativeJavaLangObjectOverrides;
import com.google.gwt.dev.jjs.impl.ReplaceGetClassOverrides;
import com.google.gwt.dev.jjs.impl.ResolvePermutationDependentValues;
import com.google.gwt.dev.jjs.impl.ResolveRuntimeTypeReferences;
import com.google.gwt.dev.jjs.impl.ResolveRuntimeTypeReferences.ClosureUniqueIdTypeMapper;
import com.google.gwt.dev.jjs.impl.ResolveRuntimeTypeReferences.IntTypeMapper;
import com.google.gwt.dev.jjs.impl.ResolveRuntimeTypeReferences.StringTypeMapper;
import com.google.gwt.dev.jjs.impl.ResolveRuntimeTypeReferences.TypeMapper;
import com.google.gwt.dev.jjs.impl.ResolveRuntimeTypeReferences.TypeOrder;
import com.google.gwt.dev.jjs.impl.RewriteConstructorCallsForUnboxedTypes;
import com.google.gwt.dev.jjs.impl.SameParameterValueOptimizer;
import com.google.gwt.dev.jjs.impl.SourceInfoCorrelator;
import com.google.gwt.dev.jjs.impl.TypeCoercionNormalizer;
import com.google.gwt.dev.jjs.impl.TypeReferencesRecorder;
import com.google.gwt.dev.jjs.impl.TypeTightener;
import com.google.gwt.dev.jjs.impl.UnifyAst;
import com.google.gwt.dev.jjs.impl.codesplitter.CodeSplitter;
import com.google.gwt.dev.jjs.impl.codesplitter.CodeSplitters;
import com.google.gwt.dev.jjs.impl.codesplitter.MultipleDependencyGraphRecorder;
import com.google.gwt.dev.jjs.impl.codesplitter.ReplaceRunAsyncs;
import com.google.gwt.dev.jjs.impl.gflow.DataflowOptimizer;
import com.google.gwt.dev.js.BaselineCoverageGatherer;
import com.google.gwt.dev.js.CoverageInstrumentor;
import com.google.gwt.dev.js.DuplicateClinitRemover;
import com.google.gwt.dev.js.EvalFunctionsAtTopScope;
import com.google.gwt.dev.js.FreshNameGenerator;
import com.google.gwt.dev.js.JsBreakUpLargeVarStatements;
import com.google.gwt.dev.js.JsDuplicateCaseFolder;
import com.google.gwt.dev.js.JsDuplicateFunctionRemover;
import com.google.gwt.dev.js.JsForceInliningChecker;
import com.google.gwt.dev.js.JsIncrementalNamer;
import com.google.gwt.dev.js.JsInliner;
import com.google.gwt.dev.js.JsLiteralInterner;
import com.google.gwt.dev.js.JsNamer.IllegalNameException;
import com.google.gwt.dev.js.JsNamespaceChooser;
import com.google.gwt.dev.js.JsNamespaceOption;
import com.google.gwt.dev.js.JsNormalizer;
import com.google.gwt.dev.js.JsObfuscateNamer;
import com.google.gwt.dev.js.JsPrettyNamer;
import com.google.gwt.dev.js.JsReportGenerationVisitor;
import com.google.gwt.dev.js.JsStackEmulator;
import com.google.gwt.dev.js.JsStaticEval;
import com.google.gwt.dev.js.JsSymbolResolver;
import com.google.gwt.dev.js.JsUnusedFunctionRemover;
import com.google.gwt.dev.js.JsVerboseNamer;
import com.google.gwt.dev.js.SizeBreakdown;
import com.google.gwt.dev.js.ast.JavaScriptVerifier;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsForIn;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsLabel;
import com.google.gwt.dev.js.ast.JsLiteral;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsNameOf;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNode;
import com.google.gwt.dev.js.ast.JsParameter;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsVars;
import com.google.gwt.dev.js.ast.JsVisitor;
import com.google.gwt.dev.util.DefaultTextOutput;
import com.google.gwt.dev.util.Memory;
import com.google.gwt.dev.util.Name.SourceName;
import com.google.gwt.dev.util.Pair;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.OptionOptimize;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.soyc.SoycDashboard;
import com.google.gwt.soyc.io.ArtifactsOutputDirectory;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableMap;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;
import com.google.gwt.thirdparty.guava.common.collect.Sets;

import org.xml.sax.SAXException;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.zip.GZIPInputStream;

import javax.xml.parsers.ParserConfigurationException;

/**
 * A base for classes that compile Java <code>JProgram</code> representations into corresponding Js
 * source.<br />
 *
 * Work is split between a precompile() stage which is only called once and compilePerms() stage
 * which is called once per permutation. This allow build systems the option of distributing and
 * parallelizing some of the work.
 */
public final class JavaToJavaScriptCompiler {

  /**
   * Ending optimization passes when the rate of change has reached this value results in gaining
   * nearly all of the impact while avoiding the long tail of costly but low-impact passes.
   */
  private static final float EFFICIENT_CHANGE_RATE = 0.01f;
  /**
   * Continuing to apply optimizations till the rate of change reaches this value causes the AST to
   * reach a fixed point.
   */
  private static final int FIXED_POINT_CHANGE_RATE = 0;
  /**
   * Limits the number of optimization passes against the possible danger of an AST that does not
   * converge.
   */
  private static final int MAX_PASSES = 100;

  static {
    // Preload the internal compiler exception just in case we run out of memory?.
    InternalCompilerException.preload();
  }

  private final CompilerContext compilerContext;
  private final TreeLogger logger;
  private final ModuleDef module;
  private final PrecompileTaskOptions options;
  private JsProgram jsProgram;
  private JProgram jprogram;

  public JavaToJavaScriptCompiler(TreeLogger logger, CompilerContext compilerContext) {
    this.logger = logger;
    this.compilerContext = compilerContext;
    this.module = compilerContext.getModule();
    this.options = compilerContext.getOptions();
  }

  public static UnifiedAst precompile(TreeLogger logger, CompilerContext compilerContext,
      PrecompilationContext precompilationContext)
      throws UnableToCompleteException {
    return new JavaToJavaScriptCompiler(logger, compilerContext).precompile(precompilationContext);
  }

  /**
   * Compiles a particular permutation.
   *
   * @param logger the logger to use
   * @param compilerContext shared read only compiler state
   * @param permutation the permutation to compile
   * @return the permutation result
   * @throws UnableToCompleteException if an error other than {@link OutOfMemoryError} occurs
   */
  public static PermutationResult compilePermutation(UnifiedAst unifiedAst,
      TreeLogger logger, CompilerContext compilerContext, Permutation permutation)
      throws UnableToCompleteException {
    JavaToJavaScriptCompiler javaToJavaScriptCompiler =
        new JavaToJavaScriptCompiler(logger, compilerContext);
    return javaToJavaScriptCompiler.compilePermutation(permutation, unifiedAst);
  }

  /**
   * Takes as input an unresolved Java AST (a Java AST wherein all rebind result classes are
   * available and have not yet been pruned down to the set applicable for a particular permutation)
   * that was previously constructed by the Precompiler and from that constructs output Js source
   * code and related information. This Js source and related information is packaged into a
   * Permutation instance and then returned.
   *
   * Permutation compilation is INTENDED to progress as a series of stages:
   *
   * <pre>
   * 1. initialize local state
   * 2. transform unresolved Java AST to resolved Java AST
   * 3. normalize the resolved Java AST
   * 4. optimize the resolved Java AST
   * 5. construct the Js AST
   * 6. normalize the Js AST
   * 7. optimize the Js AST
   * 8. generate Js source
   * 9. construct and return a value
   * </pre>
   *
   * There are some other types of work here (mostly metrics and data gathering) which do not serve
   * the goal of output program construction. This work should really be moved into subclasses or
   * some sort of callback or plugin system so as not to visually pollute the real compile logic.<br
   * />
   *
   * Significant amounts of visitors implementing the intended above stages are triggered here but
   * in the wrong order. They have been noted for future cleanup.
   */
  private PermutationResult compilePermutation(Permutation permutation, UnifiedAst unifiedAst)
      throws UnableToCompleteException {
    Event jjsCompilePermutationEvent = SpeedTracerLogger.start(
        CompilerEventType.JJS_COMPILE_PERMUTATION, "name", permutation.getProperties().prettyPrint()
    );
    /*
     * Do not introduce any new pass here unless it is logically a part of one of the 9 defined
     * stages and is physically located in that stage.
     */

    long permStartMs = System.currentTimeMillis();
    try {
      Event javaEvent = SpeedTracerLogger.start(CompilerEventType.PERMUTATION_JAVA);

      // (1) Initialize local state.
      long startTimeMs = System.currentTimeMillis();
      PermutationProperties properties = permutation.getProperties();
      int permutationId = permutation.getId();
      AST ast = unifiedAst.getFreshAst();
      jprogram = ast.getJProgram();
      jsProgram = ast.getJsProgram();
      Map<StandardSymbolData, JsName> symbolTable =
          new TreeMap<StandardSymbolData, JsName>(new SymbolData.ClassIdentComparator());

      // TODO(stalcup): hide metrics gathering in a callback or subclass
      logger.log(TreeLogger.INFO, "Compiling permutation " + permutationId + "...");

      // (2) Transform unresolved Java AST to resolved Java AST
      ResolvePermutationDependentValues
          .exec(jprogram, properties, permutation.getPropertyAndBindingInfos());

      // TODO(stalcup): hide metrics gathering in a callback or subclass
      // This has to happen before optimizations because functions might
      // be optimized out; we want those marked as "not executed", not "not
      // instrumentable".
      Multimap<String, Integer> instrumentableLines = null;
      if (CoverageInstrumentor.isCoverageEnabled()) {
        instrumentableLines = BaselineCoverageGatherer.exec(jprogram);
      }

      // Record initial set of type->type references.
      // type->type references need to be collected in two phases, 1) before any process to the
      // AST has happened (to record for example reference to types declaring compile-time
      // constants) and 2) after all normalizations to collect synthetic references (e.g. to
      // record references to runtime classes like LongLib).
      maybeRecordReferencesAndControlFlow(false);

      // Rewrite calls to from boxed constructor types to specialized unboxed methods
      RewriteConstructorCallsForUnboxedTypes.exec(jprogram);

      // Replace compile time constants by their values.
      // TODO(rluble): eventually move to normizeSemantics.
      CompileTimeConstantsReplacer.exec(jprogram);

      // TODO(stalcup): move to after normalize.
      // (3) Optimize the resolved Java AST
      optimizeJava();

      // TODO(stalcup): move to before optimize.
      // (4) Normalize the resolved Java AST
      TypeMapper<?> typeMapper = normalizeSemantics();

      // TODO(stalcup): this stage shouldn't exist, move into optimize.
      postNormalizationOptimizeJava();

      // Now that the AST has stopped mutating update with the final references.
      maybeRecordReferencesAndControlFlow(true);

      javaEvent.end();

      Event javaScriptEvent = SpeedTracerLogger.start(CompilerEventType.PERMUTATION_JAVASCRIPT);

      // (5) Construct the Js AST
      Pair<? extends JavaToJavaScriptMap, Set<JsNode>> jjsMapAndInlineableFunctions =
          GenerateJavaScriptAST.exec(logger, jprogram, jsProgram,
              compilerContext, typeMapper, symbolTable, properties);
      JavaToJavaScriptMap jjsmap = jjsMapAndInlineableFunctions.getLeft();

      // TODO(stalcup): hide metrics gathering in a callback or subclass
      if (CoverageInstrumentor.isCoverageEnabled()) {
        CoverageInstrumentor.exec(jprogram, jsProgram, jjsmap, instrumentableLines);
      }

      // (6) Normalize the Js AST
      JsNormalizer.exec(jsProgram);

      // TODO(stalcup): move to AST construction
      JsSymbolResolver.exec(jsProgram);

      if (options.getNamespace() == JsNamespaceOption.PACKAGE) {
        if (!jprogram.getRunAsyncs().isEmpty()) {
          options.setNamespace(JsNamespaceOption.NONE);
          logger.log(TreeLogger.Type.WARN,
              "Namespace option is not compatible with CodeSplitter, turning it off.");
        } else {
          JsNamespaceChooser.exec(jprogram, jsProgram, jjsmap);
        }
      }

      // TODO(stalcup): move to normalization
      Pair<SyntheticArtifact, MultipleDependencyGraphRecorder> dependenciesAndRecorder =
          splitJsIntoFragments(properties, permutationId, jjsmap);

      // TODO(stalcup): move to normalization
      EvalFunctionsAtTopScope.exec(jsProgram, jjsmap);

      // (7) Optimize the JS AST.
      final Set<JsNode> inlinableJsFunctions = jjsMapAndInlineableFunctions.getRight();
      optimizeJs(inlinableJsFunctions);
      if (options.getOptimizationLevel() > OptionOptimize.OPTIMIZE_LEVEL_DRAFT) {
        JsForceInliningChecker.check(logger, jjsmap, jsProgram);
      }

      // TODO(stalcup): move to normalization
      // Must run before code splitter and namer.
      JsStackEmulator.exec(jprogram, jsProgram, properties, jjsmap);

      // TODO(stalcup): move to optimize.
      Map<JsName, JsLiteral> internedLiteralByVariableName = renameJsSymbols(properties, jjsmap);

      // No new JsNames or references to JSNames can be introduced after this
      // point.
      HandleCrossFragmentReferences.exec(jsProgram, properties);

      // TODO(stalcup): move to normalization
      JsBreakUpLargeVarStatements.exec(jsProgram, properties.getConfigurationProperties());

      if (!options.isIncrementalCompileEnabled()) {
        // Verifies consistency between jsProgram and jjsmap if assertions are enabled.
        // TODO(rluble): make it work for incremental compiles.
        JavaScriptVerifier.verify(jsProgram, jjsmap);
      }

      // (8) Generate Js source
      List<JsSourceMap> sourceInfoMaps = new ArrayList<JsSourceMap>();
      boolean isSourceMapsEnabled = properties.isTrueInAnyPermutation("compiler.useSourceMaps");
      String[] jsFragments = new String[jsProgram.getFragmentCount()];
      StatementRanges[] ranges = new StatementRanges[jsFragments.length];
      SizeBreakdown[] sizeBreakdowns = options.isJsonSoycEnabled() || options.isSoycEnabled()
          || options.isCompilerMetricsEnabled() ? new SizeBreakdown[jsFragments.length] : null;
      generateJavaScriptCode(jjsmap, jsFragments, ranges, sizeBreakdowns, sourceInfoMaps,
          isSourceMapsEnabled || options.isJsonSoycEnabled());

      javaScriptEvent.end();

      // (9) Construct and return a value
      PermutationResult permutationResult =
          new PermutationResultImpl(jsFragments, permutation, makeSymbolMap(symbolTable), ranges);

      // TODO(stalcup): hide metrics gathering in a callback or subclass
      addSyntheticArtifacts(unifiedAst, permutation, startTimeMs, permutationId, jjsmap,
          dependenciesAndRecorder, internedLiteralByVariableName, isSourceMapsEnabled, jsFragments,
          sizeBreakdowns, sourceInfoMaps, permutationResult);
      return permutationResult;
    } catch (Throwable e) {
      throw CompilationProblemReporter.logAndTranslateException(logger, e);
    } finally {
      jjsCompilePermutationEvent.end();
      if (logger.isLoggable(TreeLogger.TRACE)) {
        logger.log(TreeLogger.TRACE,
            "Permutation took " + (System.currentTimeMillis() - permStartMs) + " ms");
      }
    }
  }

  private void maybeRecordReferencesAndControlFlow(boolean onlyUpdate) {
    if (options.isIncrementalCompileEnabled()) {
      // Per file compilation needs the type reference graph to construct the set of reachable
      // types when linking.
      TypeReferencesRecorder.exec(jprogram, getMinimalRebuildCache(), onlyUpdate);
      ControlFlowRecorder.exec(jprogram, getMinimalRebuildCache().getTypeEnvironment(),
          onlyUpdate);
    }
  }

  /**
   * Transform patterns that can't be represented in JS (such as multiple catch blocks) into
   * equivalent but compatible patterns and take JVM semantics (such as numeric casts) that are not
   * explicit in the AST and make them explicit.<br />
   *
   * These passes can not be reordering because of subtle interdependencies.
   */
  protected TypeMapper<?> normalizeSemantics() {
    Event event = SpeedTracerLogger.start(CompilerEventType.JAVA_NORMALIZERS);
    try {
      Devirtualizer.exec(jprogram);
      CatchBlockNormalizer.exec(jprogram);
      PostOptimizationCompoundAssignmentNormalizer.exec(jprogram);
      LongCastNormalizer.exec(jprogram);
      LongEmulationNormalizer.exec(jprogram);
      TypeCoercionNormalizer.exec(jprogram);

      if (options.isIncrementalCompileEnabled()) {
        // Per file compilation reuses type JS even as references (like casts) in other files
        // change, which means all legal casts need to be allowed now before they are actually
        // used later.
        ComputeExhaustiveCastabilityInformation.exec(jprogram);
      } else {
        // If trivial casts are pruned then one can use smaller runtime castmaps.
        ComputeCastabilityInformation.exec(jprogram, !shouldOptimize() /* recordTrivialCasts */);
      }

      ImplementCastsAndTypeChecks.exec(jprogram, shouldOptimize() /* pruneTrivialCasts */);
      ImplementJsVarargs.exec(jprogram);
      ArrayNormalizer.exec(jprogram);
      EqualityNormalizer.exec(jprogram);

      TypeMapper<?> typeMapper = getTypeMapper();
      ResolveRuntimeTypeReferences.exec(jprogram, typeMapper, getTypeOrder());

      return typeMapper;
    } finally {
      event.end();
    }
  }

  private void optimizeJava() throws InterruptedException {
    if (shouldOptimize()) {
      optimizeJavaToFixedPoint();
      RemoveEmptySuperCalls.exec(jprogram);
    }
  }

  private void optimizeJs(Set<JsNode> inlinableJsFunctions) throws InterruptedException {
    if (shouldOptimize()) {
      optimizeJsLoop(inlinableJsFunctions);
      JsDuplicateCaseFolder.exec(jsProgram);
    }
  }

  private void postNormalizationOptimizeJava() {
    Event event = SpeedTracerLogger.start(CompilerEventType.JAVA_POST_NORMALIZER_OPTIMIZERS);
    try {
      if (shouldOptimize()) {
        RemoveSpecializations.exec(jprogram);
        Pruner.exec(jprogram, false);
        // Last Java optimization step, update type oracle accordingly.
        jprogram.typeOracle.recomputeAfterOptimizations(jprogram.getDeclaredTypes());
      }
      ReplaceGetClassOverrides.exec(jprogram);
    } finally {
      event.end();
    }
  }

  private Map<JsName, JsLiteral> runDetailedNamer(ConfigurationProperties config)
      throws IllegalNameException {
    Map<JsName, JsLiteral> internedTextByVariableName =
        maybeInternLiterals(JsLiteralInterner.INTERN_ALL);
    JsVerboseNamer.exec(jsProgram, config);
    return internedTextByVariableName;
  }

  private Map<JsName, JsLiteral> maybeInternLiterals(int interningMask) {
    if (!shouldOptimize()) {
      return null;
    }
    // Only perform the interning optimization when optimizations are enabled.
    if (options.isClosureCompilerFormatEnabled()) {
      // Do no intern strings in closure format as it breaks goog.provides, etc.
      interningMask &= ~JsLiteralInterner.INTERN_STRINGS;
    }
    return JsLiteralInterner.exec(jprogram, jsProgram, interningMask);
  }

  private Pair<SyntheticArtifact, MultipleDependencyGraphRecorder> splitJsIntoFragments(
      PermutationProperties properties, int permutationId, JavaToJavaScriptMap jjsmap) {
    Pair<SyntheticArtifact, MultipleDependencyGraphRecorder> dependenciesAndRecorder;
    MultipleDependencyGraphRecorder dependencyRecorder = null;
    SyntheticArtifact dependencies = null;
    if (options.isRunAsyncEnabled()) {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();

      int expectedFragmentCount = options.getFragmentCount();
      // -1 is the default value, we trap 0 just in case (0 is not a legal value in any case)
      if (expectedFragmentCount <= 0) {
        // Fragment count not set check fragments merge.
        int numberOfMerges = options.getFragmentsMerge();
        if (numberOfMerges > 0) {
          // + 1 for left over, + 1 for initial gave us the total number
          // of fragments without splitting.
          expectedFragmentCount =
              Math.max(0, jprogram.getRunAsyncs().size() + 2 - numberOfMerges);
        }
      }

      int minFragmentSize = properties.getConfigurationProperties()
          .getInteger(CodeSplitters.MIN_FRAGMENT_SIZE, 0);

      dependencyRecorder = chooseDependencyRecorder(baos);
      CodeSplitter.exec(logger, jprogram, jsProgram, jjsmap, expectedFragmentCount,
          minFragmentSize, dependencyRecorder);

      if (baos.size() == 0) {
        dependencyRecorder = recordNonSplitDependencies(baos);
      }
      if (baos.size() > 0) {
        dependencies = new SyntheticArtifact(
            SoycReportLinker.class, "dependencies" + permutationId + ".xml.gz",
            baos.toByteArray());
      }
    } else if (options.isSoycEnabled() || options.isJsonSoycEnabled()) {
      dependencyRecorder = recordNonSplitDependencies(new ByteArrayOutputStream());
    }
    dependenciesAndRecorder = Pair.create(dependencies, dependencyRecorder);

    return dependenciesAndRecorder;
  }

  private MultipleDependencyGraphRecorder chooseDependencyRecorder(OutputStream out) {
    MultipleDependencyGraphRecorder dependencyRecorder =
        MultipleDependencyGraphRecorder.NULL_RECORDER;
    if (options.isSoycEnabled() && options.isJsonSoycEnabled()) {
      dependencyRecorder = new DependencyGraphRecorder(out, jprogram);
    } else if (options.isSoycEnabled()) {
      dependencyRecorder = new DependencyRecorder(out);
    } else if (options.isJsonSoycEnabled()) {
      dependencyRecorder = new DependencyGraphRecorder(out, jprogram);
    }
    return dependencyRecorder;
  }

  /**
   * Dependency information is normally recorded during code splitting, and it results in multiple
   * dependency graphs. If the code splitter doesn't run, then this method can be used instead to
   * record a single dependency graph for the whole program.
   */
  private DependencyRecorder recordNonSplitDependencies(OutputStream out) {
    DependencyRecorder deps;
    if (options.isSoycEnabled() && options.isJsonSoycEnabled()) {
      deps = new DependencyGraphRecorder(out, jprogram);
    } else if (options.isSoycEnabled()) {
      deps = new DependencyRecorder(out);
    } else if (options.isJsonSoycEnabled()) {
      deps = new DependencyGraphRecorder(out, jprogram);
    } else {
      return null;
    }
    deps.open();
    deps.startDependencyGraph("initial", null);

    ControlFlowAnalyzer cfa = new ControlFlowAnalyzer(jprogram);
    cfa.setDependencyRecorder(deps);
    cfa.traverseEntryMethods();
    deps.endDependencyGraph();
    deps.close();
    return deps;
  }

  private CompilationMetricsArtifact addCompilerMetricsArtifact(UnifiedAst unifiedAst,
      Permutation permutation, long startTimeMs, SizeBreakdown[] sizeBreakdowns,
      PermutationResult permutationResult) {
    CompilationMetricsArtifact compilationMetrics = null;
    if (options.isCompilerMetricsEnabled()) {
      compilationMetrics = new CompilationMetricsArtifact(permutation.getId());
      compilationMetrics.setCompileElapsedMilliseconds(
          System.currentTimeMillis() - startTimeMs);
      compilationMetrics.setElapsedMilliseconds(
          System.currentTimeMillis() - ManagementFactory.getRuntimeMXBean().getStartTime());
      compilationMetrics.setJsSize(sizeBreakdowns);
      compilationMetrics.setPermutationDescription(permutation.getProperties().prettyPrint());
      permutationResult.addArtifacts(Lists.newArrayList(
          unifiedAst.getModuleMetrics(), unifiedAst.getPrecompilationMetrics(),
          compilationMetrics));
    }
    return compilationMetrics;
  }

  private void addSourceMapArtifacts(int permutationId, JavaToJavaScriptMap jjsmap,
      Pair<SyntheticArtifact, MultipleDependencyGraphRecorder> dependenciesAndRecorder,
      boolean isSourceMapsEnabled, SizeBreakdown[] sizeBreakdowns,
      List<JsSourceMap> sourceInfoMaps, PermutationResult permutationResult) {
    if (options.isJsonSoycEnabled()) {
      // Is a super set of SourceMapRecorder.makeSourceMapArtifacts().
      permutationResult.addArtifacts(EntityRecorder.makeSoycArtifacts(
          permutationId, sourceInfoMaps, options.getSourceMapFilePrefix(),
          jjsmap, sizeBreakdowns,
          ((DependencyGraphRecorder) dependenciesAndRecorder.getRight()), jprogram));
    } else if (isSourceMapsEnabled) {
      logger.log(TreeLogger.INFO, "Source Maps Enabled");
      permutationResult.addArtifacts(SourceMapRecorder.exec(permutationId, sourceInfoMaps,
          options.getSourceMapFilePrefix()));
    }
  }

  /**
   * Adds generated artifacts from previous compiles when doing per-file compiles. <p> All
   * generators are run on first compile but only some very small subset are rerun on recompiles.
   * Care must be taken to ensure that all generated artifacts (such as png/html/css files) are
   * still registered for output even when no generators are run in the current compile.
   */
  private void maybeAddGeneratedArtifacts(PermutationResult permutationResult) {
    if (options.isIncrementalCompileEnabled()) {
      permutationResult.addArtifacts(
          compilerContext.getMinimalRebuildCache().getGeneratedArtifacts());
    }
  }

  private void addSoycArtifacts(UnifiedAst unifiedAst, int permutationId,
      JavaToJavaScriptMap jjsmap,
      Pair<SyntheticArtifact, MultipleDependencyGraphRecorder> dependenciesAndRecorder,
      Map<JsName, JsLiteral> internedLiteralByVariableName, String[] js,
      SizeBreakdown[] sizeBreakdowns,
      List<JsSourceMap> sourceInfoMaps, PermutationResult permutationResult,
      CompilationMetricsArtifact compilationMetrics)
      throws IOException, UnableToCompleteException {
    permutationResult.addArtifacts(makeSoycArtifacts(permutationId, js, sizeBreakdowns,
        options.isSoycExtra() ? sourceInfoMaps : null, dependenciesAndRecorder.getLeft(),
        jjsmap, internedLiteralByVariableName, unifiedAst.getModuleMetrics(),
        unifiedAst.getPrecompilationMetrics(), compilationMetrics,
        options.isSoycHtmlDisabled()));
  }

  private void addSyntheticArtifacts(UnifiedAst unifiedAst, Permutation permutation,
      long startTimeMs, int permutationId, JavaToJavaScriptMap jjsmap,
      Pair<SyntheticArtifact, MultipleDependencyGraphRecorder> dependenciesAndRecorder,
      Map<JsName, JsLiteral> internedLiteralByVariableName, boolean isSourceMapsEnabled,
      String[] jsFragments, SizeBreakdown[] sizeBreakdowns,
      List<JsSourceMap> sourceInfoMaps, PermutationResult permutationResult)
      throws IOException, UnableToCompleteException {

    assert internedLiteralByVariableName != null;

    Event event = SpeedTracerLogger.start(CompilerEventType.PERMUTATION_ARTIFACTS);

    CompilationMetricsArtifact compilationMetrics = addCompilerMetricsArtifact(
        unifiedAst, permutation, startTimeMs, sizeBreakdowns, permutationResult);
    addSoycArtifacts(unifiedAst, permutationId, jjsmap, dependenciesAndRecorder,
        internedLiteralByVariableName, jsFragments, sizeBreakdowns, sourceInfoMaps,
        permutationResult, compilationMetrics);
    addSourceMapArtifacts(permutationId, jjsmap, dependenciesAndRecorder, isSourceMapsEnabled,
        sizeBreakdowns, sourceInfoMaps, permutationResult);
    maybeAddGeneratedArtifacts(permutationResult);

    event.end();
  }

  /**
   * Generate Js code from the given Js ASTs. Also produces information about that transformation.
   */
  private void generateJavaScriptCode(JavaToJavaScriptMap jjsMap, String[] jsFragments,
      StatementRanges[] ranges, SizeBreakdown[] sizeBreakdowns,
      List<JsSourceMap> sourceInfoMaps, boolean sourceMapsEnabled) {

    Event generateJavascriptEvent =
        SpeedTracerLogger.start(CompilerEventType.GENERATE_JAVASCRIPT);

    for (int i = 0; i < jsFragments.length; i++) {
      DefaultTextOutput out = new DefaultTextOutput(!options.isIncrementalCompileEnabled() &&
          options.getOutput().shouldMinimize());
      JsReportGenerationVisitor v = new JsReportGenerationVisitor(out, jjsMap,
          options.isJsonSoycEnabled());
      v.accept(jsProgram.getFragmentBlock(i));

      StatementRanges statementRanges = v.getStatementRanges();
      String code = out.toString();
      JsSourceMap infoMap = (sourceInfoMaps != null) ? v.getSourceInfoMap() : null;

      JsAbstractTextTransformer transformer =
          new JsNoopTransformer(code, statementRanges, infoMap);

      /**
       * Cut generated JS up on class boundaries and re-link the source (possibly making use of
       * source from previous compiles, thus making it possible to perform partial recompiles).
       */
      if (options.isIncrementalCompileEnabled()) {
        transformer = new JsTypeLinker(logger, transformer, v.getClassRanges(),
            v.getProgramClassRange(), getMinimalRebuildCache(), jprogram.typeOracle);
        transformer.exec();
      }

      /**
       * Reorder function decls to improve compression ratios. Also restructures the top level
       * blocks into sub-blocks if they exceed 32767 statements.
       */
      Event functionClusterEvent = SpeedTracerLogger.start(CompilerEventType.FUNCTION_CLUSTER);
      // TODO(cromwellian) move to the Js AST optimization, re-enable sourcemaps + clustering
      if (!sourceMapsEnabled && !options.isClosureCompilerFormatEnabled()
          && options.shouldClusterSimilarFunctions()
          && options.getNamespace() == JsNamespaceOption.NONE
          && options.getOutput() == JsOutputOption.OBFUSCATED) {
        transformer = new JsFunctionClusterer(transformer);
        transformer.exec();
      }
      functionClusterEvent.end();

      jsFragments[i] = transformer.getJs();
      ranges[i] = transformer.getStatementRanges();
      if (sizeBreakdowns != null) {
        sizeBreakdowns[i] = v.getSizeBreakdown();
      }
      if (sourceInfoMaps != null) {
        sourceInfoMaps.add(transformer.getSourceInfoMap());
      }
    }

    generateJavascriptEvent.end();
  }

  private Collection<? extends Artifact<?>> makeSoycArtifacts(int permutationId, String[] js,
      SizeBreakdown[] sizeBreakdowns, List<JsSourceMap> sourceInfoMaps,
      SyntheticArtifact dependencies, JavaToJavaScriptMap jjsmap,
      Map<JsName, JsLiteral> internedLiteralByVariableName,
      ModuleMetricsArtifact moduleMetricsArtifact,
      PrecompilationMetricsArtifact precompilationMetricsArtifact,
      CompilationMetricsArtifact compilationMetrics, boolean htmlReportsDisabled)
      throws IOException, UnableToCompleteException {
    Memory.maybeDumpMemory("makeSoycArtifactsStart");
    List<SyntheticArtifact> soycArtifacts = new ArrayList<SyntheticArtifact>();

    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    Event soycEvent = SpeedTracerLogger.start(CompilerEventType.MAKE_SOYC_ARTIFACTS);

    Event recordSplitPoints = SpeedTracerLogger.start(
        CompilerEventType.MAKE_SOYC_ARTIFACTS, "phase", "recordSplitPoints");
    SplitPointRecorder.recordSplitPoints(jprogram, baos, logger);
    SyntheticArtifact splitPoints = new SyntheticArtifact(
        SoycReportLinker.class, "splitPoints" + permutationId + ".xml.gz", baos.toByteArray());
    soycArtifacts.add(splitPoints);
    recordSplitPoints.end();

    SyntheticArtifact sizeMaps = null;
    if (sizeBreakdowns != null) {
      Event recordSizeMap = SpeedTracerLogger.start(
          CompilerEventType.MAKE_SOYC_ARTIFACTS, "phase", "recordSizeMap");
      baos.reset();
      SizeMapRecorder.recordMap(logger, baos, sizeBreakdowns, jjsmap,
          internedLiteralByVariableName);
      sizeMaps = new SyntheticArtifact(
          SoycReportLinker.class, "stories" + permutationId + ".xml.gz", baos.toByteArray());
      soycArtifacts.add(sizeMaps);
      recordSizeMap.end();
    }

    if (sourceInfoMaps != null) {
      Event recordStories = SpeedTracerLogger.start(
          CompilerEventType.MAKE_SOYC_ARTIFACTS, "phase", "recordStories");
      baos.reset();
      StoryRecorder.recordStories(logger, baos, sourceInfoMaps, js);
      soycArtifacts.add(new SyntheticArtifact(
          SoycReportLinker.class, "detailedStories" + permutationId + ".xml.gz",
          baos.toByteArray()));
      recordStories.end();
    }

    if (dependencies != null) {
      soycArtifacts.add(dependencies);
    }

    // Set all of the main SOYC artifacts private.
    for (SyntheticArtifact soycArtifact : soycArtifacts) {
      soycArtifact.setVisibility(Visibility.Private);
    }

    if (!htmlReportsDisabled && sizeBreakdowns != null) {
      Event generateCompileReport = SpeedTracerLogger.start(
          CompilerEventType.MAKE_SOYC_ARTIFACTS, "phase", "generateCompileReport");
      ArtifactsOutputDirectory outDir = new ArtifactsOutputDirectory();
      SoycDashboard dashboard = new SoycDashboard(outDir);
      dashboard.startNewPermutation(Integer.toString(permutationId));
      try {
        dashboard.readSplitPoints(openWithGunzip(splitPoints));
        if (sizeMaps != null) {
          dashboard.readSizeMaps(openWithGunzip(sizeMaps));
        }
        if (dependencies != null) {
          dashboard.readDependencies(openWithGunzip(dependencies));
        }
        Memory.maybeDumpMemory("soycReadDependenciesEnd");
      } catch (ParserConfigurationException e) {
        throw new InternalCompilerException(
            "Error reading compile report information that was just generated", e);
      } catch (SAXException e) {
        throw new InternalCompilerException(
            "Error reading compile report information that was just generated", e);
      }
      dashboard.generateForOnePermutation();
      if (moduleMetricsArtifact != null && precompilationMetricsArtifact != null
          && compilationMetrics != null) {
        dashboard.generateCompilerMetricsForOnePermutation(
            moduleMetricsArtifact, precompilationMetricsArtifact, compilationMetrics);
      }
      soycArtifacts.addAll(outDir.getArtifacts());
      generateCompileReport.end();
    }

    soycEvent.end();

    return soycArtifacts;
  }

  private SymbolData[] makeSymbolMap(Map<StandardSymbolData, JsName> symbolTable) {
    // Keep tracks of a list of referenced name. If it is not used, don't
    // add it to symbol map.
    final Set<String> nameUsed = new HashSet<String>();
    final Map<JsName, Integer> nameToFragment = new HashMap<JsName, Integer>();

    for (int i = 0; i < jsProgram.getFragmentCount(); i++) {
      final Integer fragId = i;
      new JsVisitor() {
        @Override
        public void endVisit(JsForIn x, JsContext ctx) {
          if (x.getIterVarName() != null) {
            nameUsed.add(x.getIterVarName().getIdent());
          }
        }

        @Override
        public void endVisit(JsFunction x, JsContext ctx) {
          if (x.getName() != null) {
            nameToFragment.put(x.getName(), fragId);
            nameUsed.add(x.getName().getIdent());
          }
        }

        @Override
        public void endVisit(JsLabel x, JsContext ctx) {
          nameUsed.add(x.getName().getIdent());
        }

        @Override
        public void endVisit(JsNameOf x, JsContext ctx) {
          if (x.getName() != null) {
            nameUsed.add(x.getName().getIdent());
          }
        }

        @Override
        public void endVisit(JsNameRef x, JsContext ctx) {
          // Obviously this isn't even that accurate. Some of them are
          // variable names, some of the are property. At least this
          // this give us a safe approximation. Ideally we need
          // the code removal passes to remove stuff in the scope objects.
          if (x.isResolved()) {
            nameUsed.add(x.getName().getIdent());
          }
        }

        @Override
        public void endVisit(JsParameter x, JsContext ctx) {
          nameUsed.add(x.getName().getIdent());
        }

        @Override

        public void endVisit(JsVars.JsVar x, JsContext ctx) {
          nameUsed.add(x.getName().getIdent());
        }
      }.accept(jsProgram.getFragmentBlock(i));
    }

    // TODO(acleung): This is a temp fix. Once we know this is safe. We
    // new to rewrite it to avoid extra ArrayList creations.
    // Or we should just consider serializing it as an ArrayList if
    // it is that much trouble to determine the true size.
    List<SymbolData> result = new ArrayList<SymbolData>();

    for (Map.Entry<StandardSymbolData, JsName> entry : symbolTable.entrySet()) {
      StandardSymbolData symbolData = entry.getKey();
      symbolData.setSymbolName(entry.getValue().getShortIdent());
      Integer fragNum = nameToFragment.get(entry.getValue());
      if (fragNum != null) {
        symbolData.setFragmentNumber(fragNum);
      }
      if (nameUsed.contains(entry.getValue().getIdent()) || entry.getKey().isClass()) {
        result.add(symbolData);
      }
    }

    return result.toArray(new SymbolData[result.size()]);
  }

  /**
   * Open an emitted artifact and gunzip its contents.
   */
  private InputStream openWithGunzip(EmittedArtifact artifact)
      throws IOException, UnableToCompleteException {
    return new BufferedInputStream(new GZIPInputStream(artifact.getContents(TreeLogger.NULL)));
  }

  private void optimizeJsLoop(Collection<JsNode> toInline) throws InterruptedException {
    int optimizationLevel = options.getOptimizationLevel();
    List<OptimizerStats> allOptimizerStats = Lists.newArrayList();
    int counter = 0;
    while (true) {
      counter++;
      if (Thread.interrupted()) {
        throw new InterruptedException();
      }
      Event optimizeJsEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE_JS);

      OptimizerStats stats = new OptimizerStats("Pass " + counter);

      // Remove unused functions if possible.
      stats.add(JsStaticEval.exec(jsProgram));
      // Inline Js function invocations
      stats.add(JsInliner.exec(jsProgram, toInline));
      // Remove unused functions if possible.
      stats.add(JsUnusedFunctionRemover.exec(jsProgram));

      // Save the stats to print out after optimizers finish.
      allOptimizerStats.add(stats);

      optimizeJsEvent.end();
      if ((optimizationLevel < OptionOptimize.OPTIMIZE_LEVEL_MAX && counter > optimizationLevel)
          || !stats.didChange()) {
        break;
      }
    }

    if (optimizationLevel > OptionOptimize.OPTIMIZE_LEVEL_DRAFT) {
      DuplicateClinitRemover.exec(jsProgram);
    }
  }

  private Map<JsName, JsLiteral> renameJsSymbols(PermutationProperties properties,
      JavaToJavaScriptMap jjsmap) throws UnableToCompleteException {
    Map<JsName, JsLiteral> internedLiteralByVariableName = null;
    try {
      switch (options.getOutput()) {
        case OBFUSCATED:
          internedLiteralByVariableName = runObfuscateNamer(options, properties, jjsmap);
          break;
        case PRETTY:
          internedLiteralByVariableName = runPrettyNamer(options, properties, jjsmap);
          break;
        case DETAILED:
          internedLiteralByVariableName = runDetailedNamer(properties.getConfigurationProperties());
          break;
        default:
          throw new InternalCompilerException("Unknown output mode");
      }
    } catch (IllegalNameException e) {
      logger.log(TreeLogger.ERROR, e.getMessage(), e);
      throw new UnableToCompleteException();
    }
    return internedLiteralByVariableName == null ?
        ImmutableMap.<JsName, JsLiteral>of() : internedLiteralByVariableName;
  }

  private Map<JsName, JsLiteral> runObfuscateNamer(JJSOptions options,
      PermutationProperties properties, JavaToJavaScriptMap jjsmap)
      throws IllegalNameException {
    if (options.isIncrementalCompileEnabled()) {
      runIncrementalNamer(options, properties.getConfigurationProperties(), jjsmap);
      return null;
    }

    Map<JsName, JsLiteral> internedLiteralByVariableName =
        maybeInternLiterals(JsLiteralInterner.INTERN_ALL);
    FreshNameGenerator freshNameGenerator =
        JsObfuscateNamer.exec(jsProgram, properties.getConfigurationProperties());
    if (options.shouldRemoveDuplicateFunctions()
        && JsStackEmulator.getStackMode(properties) == JsStackEmulator.StackMode.STRIP) {
      JsDuplicateFunctionRemover.exec(jsProgram, freshNameGenerator);
    }
    return internedLiteralByVariableName;
  }

  private Map<JsName, JsLiteral> runPrettyNamer(JJSOptions options,
      PermutationProperties properties, JavaToJavaScriptMap jjsmap)
      throws IllegalNameException {
    if (options.isIncrementalCompileEnabled()) {
      runIncrementalNamer(options, properties.getConfigurationProperties(), jjsmap);
      return null;
    }
    // We don't intern strings in pretty mode to improve readability
    Map<JsName, JsLiteral> internedLiteralByVariableName =
        maybeInternLiterals(JsLiteralInterner.INTERN_ALL & ~JsLiteralInterner.INTERN_STRINGS);

    JsPrettyNamer.exec(jsProgram, properties.getConfigurationProperties());
    return internedLiteralByVariableName;
  }

  private void runIncrementalNamer(JJSOptions options,
      ConfigurationProperties configurationProperties, JavaToJavaScriptMap jjsmap)
    throws IllegalNameException {
    JsIncrementalNamer.exec(jsProgram, configurationProperties,
        compilerContext.getMinimalRebuildCache().getPersistentPrettyNamerState(), jjsmap,
        options.getOutput() == JsOutputOption.OBFUSCATED);
  }

  /**
   * Takes as input a CompilationState and transforms that into a unified by not yet resolved Java
   * AST (a Java AST wherein cross-class references have been connected and all rebind result
   * classes are available and have not yet been pruned down to the set applicable for a particular
   * permutation). This AST is packaged into a UnifiedAst instance and then returned.
   *
   * Precompilation is INTENDED to progress as a series of stages:
   *
   * <pre>
   * 1. initialize local state
   * 2. assert preconditions
   * 3. construct and unify the unresolved Java AST
   * 4. normalize the unresolved Java AST  // arguably should be removed
   * 5. optimize the unresolved Java AST  // arguably should be removed
   * 6. construct and return a value
   * </pre>
   *
   * There are some other types of work here (mostly metrics and data gathering) which do not serve
   * the goal of output program construction. This work should really be moved into subclasses or
   * some sort of callback or plugin system so as not to visually pollute the real compile logic.<br
   * />
   *
   * Significant amounts of visitors implementing the intended above stages are triggered here but
   * in the wrong order. They have been noted for future cleanup.
   */
  private UnifiedAst precompile(PrecompilationContext precompilationContext)
      throws UnableToCompleteException {
    try {

      // (0) Assert preconditions
      if (precompilationContext.getEntryPoints().length +
          precompilationContext.getAdditionalRootTypes().length == 0) {
        throw new IllegalArgumentException("entry point(s) required");
      }

      boolean singlePermutation = precompilationContext.getPermutations().length == 1;
      PrecompilationMetricsArtifact precompilationMetrics =
          precompilationContext.getPrecompilationMetricsArtifact();
      /*
       * Do not introduce any new pass here unless it is logically a part of one of the 6 defined
       * stages and is physically located in that stage.
       */

      // (1) Initialize local state
      jprogram = new JProgram(compilerContext.getMinimalRebuildCache());
      // Synchronize JTypeOracle with compile optimization behavior.
      jprogram.typeOracle.setOptimize(
          options.getOptimizationLevel() > OptionOptimize.OPTIMIZE_LEVEL_DRAFT);

      jsProgram = new JsProgram();

      // (2) Construct and unify the unresolved Java AST
      CompilationState compilationState =
          constructJavaAst(precompilationContext);

      // TODO(stalcup): hide metrics gathering in a callback or subclass
      JsniRestrictionChecker.exec(logger, jprogram);
      JsInteropRestrictionChecker.exec(logger, jprogram, getMinimalRebuildCache());
      logTypeOracleMetrics(precompilationMetrics, compilationState);
      Memory.maybeDumpMemory("AstOnly");
      AstDumper.maybeDumpAST(jprogram);

      // TODO(stalcup): is in wrong place, move to optimization stage
      ConfigurationProperties configurationProperties = new ConfigurationProperties(module);
      EnumNameObfuscator.exec(jprogram, logger, configurationProperties, options);

      // (3) Normalize the unresolved Java AST
      // Replace default methods by static implementations.
      DevirtualizeDefaultMethodForwarding.exec(jprogram);
      // Replace calls to native overrides of object methods.
      ReplaceCallsToNativeJavaLangObjectOverrides.exec(jprogram);

      FixAssignmentsToUnboxOrCast.exec(jprogram);
      if (options.isEnableAssertions()) {
        AssertionNormalizer.exec(jprogram);
      } else {
        AssertionRemover.exec(jprogram);
      }
      if (module != null && options.isRunAsyncEnabled()) {
        ReplaceRunAsyncs.exec(logger, jprogram);
        ConfigurationProperties config = new ConfigurationProperties(module);
        CodeSplitters.pickInitialLoadSequence(logger, jprogram, config);
      }
      ImplementClassLiteralsAsFields.exec(jprogram, shouldOptimize());

      // TODO(stalcup): hide metrics gathering in a callback or subclass
      logAstTypeMetrics(precompilationMetrics);

      // (4) Construct and return a value.
      Event createUnifiedAstEvent = SpeedTracerLogger.start(CompilerEventType.CREATE_UNIFIED_AST);
      UnifiedAst result = new UnifiedAst(
          options, new AST(jprogram, jsProgram), singlePermutation, RecordRebinds.exec(jprogram));
      createUnifiedAstEvent.end();
      return result;
    } catch (Throwable e) {
      throw CompilationProblemReporter.logAndTranslateException(logger, e);
    }
  }

  /**
   * Creates (and returns the name for) a new class to serve as the container for the invocation of
   * registered entry point methods as part of module bootstrapping.<br />
   *
   * The resulting class will be invoked during bootstrapping like FooEntryMethodHolder.init(). By
   * generating the class on the fly and naming it to match the current module, the resulting holder
   * class can work in both monolithic and separate compilation schemes.
   */
  private String buildEntryMethodHolder(StandardGeneratorContext context,
      String[] entryPointTypeNames, Set<String> allRootTypes)
      throws UnableToCompleteException {
    // If there are no entry points.
    if (entryPointTypeNames.length == 0) {
      // Then there's no need to generate an EntryMethodHolder class to launch them.
      return null;
    }

    EntryMethodHolderGenerator entryMethodHolderGenerator = new EntryMethodHolderGenerator();
    String entryMethodHolderTypeName =
        entryMethodHolderGenerator.generate(logger, context, module.getCanonicalName());
    context.finish(logger);
    // Ensures that unification traverses and keeps the class.
    allRootTypes.add(entryMethodHolderTypeName);
    // Ensures that JProgram knows to index this class's methods so that later bootstrap
    // construction code is able to locate the FooEntryMethodHolder.init() function.
    jprogram.addIndexedTypeName(entryMethodHolderTypeName);
    return entryMethodHolderTypeName;
  }

  private CompilationState constructJavaAst(PrecompilationContext precompilationContext)
      throws UnableToCompleteException {
    RebindPermutationOracle rpo = precompilationContext.getRebindPermutationOracle();

    CompilationState compilationState = rpo.getCompilationState();
    Memory.maybeDumpMemory("CompStateBuilt");
    recordJsoTypes(compilationState.getTypeOracle());
    unifyJavaAst(precompilationContext);
    if (options.isSoycEnabled() || options.isJsonSoycEnabled()) {
      SourceInfoCorrelator.exec(jprogram);
    }

    // Free up memory.
    rpo.clear();
    Set<String> deletedTypeNames = options.isIncrementalCompileEnabled()
        ? getMinimalRebuildCache().computeDeletedTypeNames() : Sets.<String>newHashSet();
    jprogram.typeOracle.computeBeforeAST(StandardTypes.createFrom(jprogram),
        jprogram.getDeclaredTypes(), jprogram.getModuleDeclaredTypes(), deletedTypeNames);
    return compilationState;
  }

  /**
   * This method can be used to fetch the list of referenced class.
   *
   * This method is intended to support compiler metrics.
   */
  private String[] getReferencedJavaClasses() {
    class ClassNameVisitor extends JVisitor {
      List<String> classNames = new ArrayList<String>();

      @Override
      public boolean visit(JClassType x, Context ctx) {
        classNames.add(x.getName());
        return true;
      }
    }
    ClassNameVisitor v = new ClassNameVisitor();
    v.accept(jprogram);
    return v.classNames.toArray(new String[v.classNames.size()]);
  }

  private void logAstTypeMetrics(PrecompilationMetricsArtifact precompilationMetrics) {
    if (options.isCompilerMetricsEnabled()) {
      precompilationMetrics.setAstTypes(getReferencedJavaClasses());
    }
  }

  private void logTypeOracleMetrics(
      PrecompilationMetricsArtifact precompilationMetrics, CompilationState compilationState) {
    if (precompilationMetrics != null) {
      List<String> finalTypeOracleTypes = Lists.newArrayList();
      for (com.google.gwt.core.ext.typeinfo.JClassType type :
          compilationState.getTypeOracle().getTypes()) {
        finalTypeOracleTypes.add(type.getPackage().getName() + "." + type.getName());
      }
      precompilationMetrics.setFinalTypeOracleTypes(finalTypeOracleTypes);
    }
  }

  private Set<String> computeRootTypes(String[] entryPointTypeNames,
      String[] additionalRootTypes, CompilationState compilationState) {

    Set<String> allRootTypes = Sets.newTreeSet();
    Iterables.addAll(allRootTypes, compilationState.getQualifiedJsInteropRootTypesNames());
    Collections.addAll(allRootTypes, entryPointTypeNames);
    Collections.addAll(allRootTypes, additionalRootTypes);
    allRootTypes.addAll(JProgram.CODEGEN_TYPES_SET);
    allRootTypes.addAll(jprogram.getTypeNamesToIndex());
    /*
     * Add all SingleJsoImpl types that we know about. It's likely that the concrete types are
     * never explicitly referenced.
     */
    TypeOracle typeOracle = compilationState.getTypeOracle();
    for (com.google.gwt.core.ext.typeinfo.JClassType singleJsoIntf :
        typeOracle.getSingleJsoImplInterfaces()) {
      allRootTypes.add(typeOracle.getSingleJsoImpl(singleJsoIntf).getQualifiedSourceName());
    }
    return allRootTypes;
  }

  private void recordJsoTypes(TypeOracle typeOracle) {
    if (!options.isIncrementalCompileEnabled()) {
      return;
    }

    // Add names of JSO subtypes.
    Set<String> jsoTypeNames = Sets.newHashSet();
    for (com.google.gwt.dev.javac.typemodel.JClassType subtype :
        typeOracle.getJavaScriptObject().getSubtypes()) {
      jsoTypeNames.add(subtype.getQualifiedBinaryName());
    }

    // Add names of interfaces that are always of a JSO (aka there are no non-JSO implementors).
    Set<String> singleJsoImplInterfaceNames = Sets.newHashSet();
    for (com.google.gwt.core.ext.typeinfo.JClassType singleJsoImplInterface :
        typeOracle.getSingleJsoImplInterfaces()) {
      singleJsoImplInterfaceNames.add(singleJsoImplInterface.getQualifiedBinaryName());
    }

    // Add names of interfaces that are only sometimes a JSO (aka there are both JSO and non-JSO
    // imlementors).
    Set<String> dualJsoImplInterfaceNames = Sets.newHashSet();
    for (com.google.gwt.core.ext.typeinfo.JClassType dualJsoImplInterface :
        typeOracle.getDualJsoImplInterfaces()) {
      dualJsoImplInterfaceNames.add(dualJsoImplInterface.getQualifiedBinaryName());
    }

    compilerContext.getMinimalRebuildCache().setJsoTypeNames(jsoTypeNames,
        singleJsoImplInterfaceNames, dualJsoImplInterfaceNames);
  }

  private void synthesizeEntryMethodHolderInit(UnifyAst unifyAst, String[] entryPointTypeNames,
      String entryMethodHolderTypeName) throws UnableToCompleteException {
    // Get type references.
    JDeclaredType entryMethodHolderType =
        unifyAst.findType(entryMethodHolderTypeName, unifyAst.getSourceNameBasedTypeLocator());
    JDeclaredType gwtType = unifyAst.findType("com.google.gwt.core.client.GWT",
        unifyAst.getSourceNameBasedTypeLocator());
    JDeclaredType entryPointType = unifyAst.findType("com.google.gwt.core.client.EntryPoint",
        unifyAst.getSourceNameBasedTypeLocator());

    // Get method references.
    JMethod initMethod = entryMethodHolderType.findMethod("init()V", false);
    JMethod gwtCreateMethod =
        gwtType.findMethod("create(Ljava/lang/Class;)Ljava/lang/Object;", false);

    // Synthesize all onModuleLoad() calls.
    JBlock initMethodBlock = ((JMethodBody) initMethod.getBody()).getBlock();
    SourceInfo origin = initMethodBlock.getSourceInfo().makeChild();
    for (String entryPointTypeName : entryPointTypeNames) {
      // Get type and onModuleLoad function for the current entryPointTypeName.
      JDeclaredType specificEntryPointType =
          unifyAst.findType(entryPointTypeName, unifyAst.getSourceNameBasedTypeLocator());
      if (specificEntryPointType == null) {
        logger.log(TreeLogger.ERROR,
            "Could not find module entry point class '" + entryPointTypeName + "'", null);
        throw new UnableToCompleteException();
      }
      JMethod onModuleLoadMethod =
          entryPointType.findMethod("onModuleLoad()V", true);
      JMethod specificOnModuleLoadMethod =
          specificEntryPointType.findMethod("onModuleLoad()V", true);

      if (specificOnModuleLoadMethod != null && specificOnModuleLoadMethod.isStatic()) {
        // Synthesize a static invocation FooEntryPoint.onModuleLoad(); call.
        JMethodCall staticOnModuleLoadCall =
            new JMethodCall(origin, null, specificOnModuleLoadMethod);
        initMethodBlock.addStmt(staticOnModuleLoadCall.makeStatement());
      } else {
        // Synthesize ((EntryPoint)GWT.create(FooEntryPoint.class)).onModuleLoad();
        JClassLiteral entryPointTypeClassLiteral =
            new JClassLiteral(origin, specificEntryPointType);
        JMethodCall createInstanceCall =
            new JMethodCall(origin, null, gwtCreateMethod, entryPointTypeClassLiteral);
        JCastOperation castToEntryPoint =
            new JCastOperation(origin, entryPointType, createInstanceCall);
        JMethodCall instanceOnModuleLoadCall =
            new JMethodCall(origin, castToEntryPoint, onModuleLoadMethod);
        initMethodBlock.addStmt(instanceOnModuleLoadCall.makeStatement());
      }
    }
  }

  private void unifyJavaAst(PrecompilationContext precompilationContext)
      throws UnableToCompleteException {

    Event event = SpeedTracerLogger.start(CompilerEventType.UNIFY_AST);

    RebindPermutationOracle rpo = precompilationContext.getRebindPermutationOracle();
    String[] entryPointTypeNames = precompilationContext.getEntryPoints();
    String[] additionalRootTypes = precompilationContext.getAdditionalRootTypes();

    Set<String> allRootTypes = computeRootTypes(entryPointTypeNames, additionalRootTypes,
        rpo.getCompilationState());

    String entryMethodHolderTypeName =
        buildEntryMethodHolder(rpo.getGeneratorContext(), entryPointTypeNames, allRootTypes);

    UnifyAst unifyAst =
        new UnifyAst(logger, compilerContext, jprogram, jsProgram, precompilationContext);
    // Makes JProgram aware of these types so they can be accessed via index.
    unifyAst.addRootTypes(allRootTypes);
    // Must synthesize entryPoint.onModuleLoad() calls because some EntryPoint classes are
    // private.
    if (entryMethodHolderTypeName != null) {
      // Only synthesize the init method in the EntryMethodHolder class, if there is an
      // EntryMethodHolder class.
      synthesizeEntryMethodHolderInit(unifyAst, entryPointTypeNames, entryMethodHolderTypeName);
    }
    if (entryMethodHolderTypeName != null) {
      // Only register the init method in the EntryMethodHolder class as an entry method, if there
      // is an EntryMethodHolder class.
      jprogram.addEntryMethod(jprogram.getIndexedMethod(
          SourceName.getShortClassName(entryMethodHolderTypeName) + ".init"));
    }
    unifyAst.exec();

    event.end();
  }

  private void optimizeJavaToFixedPoint() throws InterruptedException {
    Event optimizeEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE);

    List<OptimizerStats> allOptimizerStats = Lists.newArrayList();
    int passCount = 0;
    int nodeCount = jprogram.getNodeCount();
    int lastNodeCount;

    boolean atMaxLevel = options.getOptimizationLevel() == OptionOptimize.OPTIMIZE_LEVEL_MAX;
    int passLimit = atMaxLevel ? MAX_PASSES : options.getOptimizationLevel();
    float minChangeRate = atMaxLevel ? FIXED_POINT_CHANGE_RATE : EFFICIENT_CHANGE_RATE;
    OptimizerContext optimizerCtx = new FullOptimizerContext(jprogram);
    while (true) {
      passCount++;
      if (passCount > passLimit) {
        break;
      }
      if (Thread.interrupted()) {
        optimizeEvent.end();
        throw new InterruptedException();
      }
      AstDumper.maybeDumpAST(jprogram);
      OptimizerStats stats = optimizeJavaOneTime("Pass " + passCount, nodeCount, optimizerCtx);
      allOptimizerStats.add(stats);
      lastNodeCount = nodeCount;
      nodeCount = jprogram.getNodeCount();

      float nodeChangeRate = stats.getNumMods() / (float) lastNodeCount;
      float sizeChangeRate = (lastNodeCount - nodeCount) / (float) lastNodeCount;
      if (nodeChangeRate <= minChangeRate && sizeChangeRate <= minChangeRate) {
        break;
      }
    }

    if (options.shouldOptimizeDataflow()) {
      logger.log(TreeLogger.Type.WARN,
          "Unsafe dataflow optimization enabled, disable with -XdisableOptimizeDataflow.");
      // Just run it once, because it is very time consuming
      allOptimizerStats.add(DataflowOptimizer.exec(jprogram));
    }

    optimizeEvent.end();
  }

  private boolean shouldOptimize() {
    return options.getOptimizationLevel() > OptionOptimize.OPTIMIZE_LEVEL_DRAFT;
  }

  private TypeMapper getTypeMapper() {

    // Used to stabilize output for DeltaJS
    if (JjsUtils.closureStyleLiteralsNeeded(this.options)) {
      return new ClosureUniqueIdTypeMapper(jprogram);
    }

    if (this.options.useDetailedTypeIds()) {
      return new StringTypeMapper(jprogram);
    }
    return this.options.isIncrementalCompileEnabled() ?
        compilerContext.getMinimalRebuildCache().getTypeMapper() :
        new IntTypeMapper();
  }

  private TypeOrder getTypeOrder() {

    // Used to stabilize output for DeltaJS
    if (JjsUtils.closureStyleLiteralsNeeded(this.options)) {
      return TypeOrder.ALPHABETICAL;
    }

    if (this.options.useDetailedTypeIds()) {
      return TypeOrder.NONE;
    }
    return this.options.isIncrementalCompileEnabled() ? TypeOrder.ALPHABETICAL
        : TypeOrder.FREQUENCY;
  }

  private OptimizerStats optimizeJavaOneTime(String passName, int numNodes,
      OptimizerContext optimizerCtx) {
    Event optimizeEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE, "phase", "loop");
    // Clinits might have become empty become empty.
    jprogram.typeOracle.recomputeAfterOptimizations(jprogram.getDeclaredTypes());
    OptimizerStats stats = new OptimizerStats(passName);
    JavaAstVerifier.assertProgramIsConsistent(jprogram);
    stats.add(Pruner.exec(jprogram, true, optimizerCtx).recordVisits(numNodes));
    stats.add(Finalizer.exec(jprogram, optimizerCtx).recordVisits(numNodes));
    stats.add(MakeCallsStatic.exec(jprogram, options.shouldAddRuntimeChecks(), optimizerCtx)
        .recordVisits(numNodes));
    stats.add(TypeTightener.exec(jprogram, optimizerCtx).recordVisits(numNodes));
    stats.add(MethodCallTightener.exec(jprogram, optimizerCtx).recordVisits(numNodes));
    // Note: Specialization should be done before inlining.
    stats.add(MethodCallSpecializer.exec(jprogram, optimizerCtx).recordVisits(numNodes));
    stats.add(DeadCodeElimination.exec(jprogram, optimizerCtx).recordVisits(numNodes));
    stats.add(MethodInliner.exec(jprogram, optimizerCtx).recordVisits(numNodes));
    if (options.shouldInlineLiteralParameters()) {
      stats.add(SameParameterValueOptimizer.exec(jprogram, optimizerCtx).recordVisits(numNodes));
    }
    if (options.shouldOrdinalizeEnums()) {
      stats.add(EnumOrdinalizer.exec(jprogram, optimizerCtx).recordVisits(numNodes));
    }
    optimizeEvent.end();
    return stats;
  }

  private MinimalRebuildCache getMinimalRebuildCache() {
    return compilerContext.getMinimalRebuildCache();
  }

  private static class PermutationResultImpl implements PermutationResult {

    private final ArtifactSet artifacts = new ArtifactSet();
    private final byte[][] js;
    private final String jsStrongName;
    private final Permutation permutation;
    private final byte[] serializedSymbolMap;
    private final StatementRanges[] statementRanges;

    public PermutationResultImpl(String[] jsFragments, Permutation permutation,
        SymbolData[] symbolMap, StatementRanges[] statementRanges) {
      byte[][] bytes = new byte[jsFragments.length][];
      for (int i = 0; i < jsFragments.length; ++i) {
        bytes[i] = Util.getBytes(jsFragments[i]);
      }
      this.js = bytes;
      this.jsStrongName = Util.computeStrongName(bytes);
      this.permutation = permutation;
      try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Util.writeObjectToStream(baos, (Object) symbolMap);
        this.serializedSymbolMap = baos.toByteArray();
      } catch (IOException e) {
        throw new RuntimeException("Should never happen with in-memory stream", e);
      }
      this.statementRanges = statementRanges;
    }

    @Override
    public void addArtifacts(Collection<? extends Artifact<?>> newArtifacts) {
      this.artifacts.addAll(newArtifacts);
    }

    @Override
    public ArtifactSet getArtifacts() {
      return artifacts;
    }

    @Override
    public byte[][] getJs() {
      return js;
    }

    @Override
    public String getJsStrongName() {
      return jsStrongName;
    }

    @Override
    public Permutation getPermutation() {
      return permutation;
    }

    @Override
    public byte[] getSerializedSymbolMap() {
      return serializedSymbolMap;
    }

    @Override
    public StatementRanges[] getStatementRanges() {
      return statementRanges;
    }
  }
}
