/*
 * 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.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.ReplaceDefenderMethodReferences;
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 defender method references
      ReplaceDefenderMethodReferences.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()) {
      // 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;
    }
  }
}
