/*
 * 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.impl;

import static com.google.gwt.dev.js.JsUtils.createAssignment;
import static com.google.gwt.dev.js.JsUtils.createInvocationOrPropertyAccess;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.linker.impl.StandardSymbolData;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.MinimalRebuildCache;
import com.google.gwt.dev.PrecompileTaskOptions;
import com.google.gwt.dev.cfg.PermutationProperties;
import com.google.gwt.dev.common.InliningMode;
import com.google.gwt.dev.javac.JsInteropUtil;
import com.google.gwt.dev.jjs.HasSourceInfo;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.HasEnclosingType;
import com.google.gwt.dev.jjs.ast.HasJsInfo.JsMemberType;
import com.google.gwt.dev.jjs.ast.HasName;
import com.google.gwt.dev.jjs.ast.JAbstractMethodBody;
import com.google.gwt.dev.jjs.ast.JArrayLength;
import com.google.gwt.dev.jjs.ast.JArrayRef;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JBreakStatement;
import com.google.gwt.dev.jjs.ast.JCaseStatement;
import com.google.gwt.dev.jjs.ast.JCastMap;
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.JConditional;
import com.google.gwt.dev.jjs.ast.JConstructor;
import com.google.gwt.dev.jjs.ast.JContinueStatement;
import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JDoStatement;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JExpressionStatement;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JFieldRef;
import com.google.gwt.dev.jjs.ast.JForStatement;
import com.google.gwt.dev.jjs.ast.JIfStatement;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JLabel;
import com.google.gwt.dev.jjs.ast.JLabeledStatement;
import com.google.gwt.dev.jjs.ast.JLiteral;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JMember;
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.JNameOf;
import com.google.gwt.dev.jjs.ast.JNewInstance;
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JNullLiteral;
import com.google.gwt.dev.jjs.ast.JNumericEntry;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JParameterRef;
import com.google.gwt.dev.jjs.ast.JPermutationDependentValue;
import com.google.gwt.dev.jjs.ast.JPostfixOperation;
import com.google.gwt.dev.jjs.ast.JPrefixOperation;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JReturnStatement;
import com.google.gwt.dev.jjs.ast.JRunAsync;
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JSwitchStatement;
import com.google.gwt.dev.jjs.ast.JThisRef;
import com.google.gwt.dev.jjs.ast.JThrowStatement;
import com.google.gwt.dev.jjs.ast.JTransformer;
import com.google.gwt.dev.jjs.ast.JTryStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JUnaryOperator;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.ast.JWhileStatement;
import com.google.gwt.dev.jjs.ast.RuntimeConstants;
import com.google.gwt.dev.jjs.ast.js.JDebuggerStatement;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.jjs.ast.js.JsniClassLiteral;
import com.google.gwt.dev.jjs.ast.js.JsniFieldRef;
import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
import com.google.gwt.dev.jjs.ast.js.JsonArray;
import com.google.gwt.dev.jjs.impl.ResolveRuntimeTypeReferences.TypeMapper;
import com.google.gwt.dev.js.JsStackEmulator;
import com.google.gwt.dev.js.JsUtils;
import com.google.gwt.dev.js.JsUtils.InvocationStyle;
import com.google.gwt.dev.js.ast.JsArrayAccess;
import com.google.gwt.dev.js.ast.JsArrayLiteral;
import com.google.gwt.dev.js.ast.JsBinaryOperation;
import com.google.gwt.dev.js.ast.JsBinaryOperator;
import com.google.gwt.dev.js.ast.JsBlock;
import com.google.gwt.dev.js.ast.JsBreak;
import com.google.gwt.dev.js.ast.JsCase;
import com.google.gwt.dev.js.ast.JsCatch;
import com.google.gwt.dev.js.ast.JsConditional;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsContinue;
import com.google.gwt.dev.js.ast.JsDebugger;
import com.google.gwt.dev.js.ast.JsDefault;
import com.google.gwt.dev.js.ast.JsDoWhile;
import com.google.gwt.dev.js.ast.JsEmpty;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFor;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsIf;
import com.google.gwt.dev.js.ast.JsInvocation;
import com.google.gwt.dev.js.ast.JsLabel;
import com.google.gwt.dev.js.ast.JsLiteral;
import com.google.gwt.dev.js.ast.JsModVisitor;
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.JsNew;
import com.google.gwt.dev.js.ast.JsNode;
import com.google.gwt.dev.js.ast.JsNormalScope;
import com.google.gwt.dev.js.ast.JsNullLiteral;
import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsNumericEntry;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsParameter;
import com.google.gwt.dev.js.ast.JsPositionMarker;
import com.google.gwt.dev.js.ast.JsPositionMarker.Type;
import com.google.gwt.dev.js.ast.JsPostfixOperation;
import com.google.gwt.dev.js.ast.JsPrefixOperation;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsReturn;
import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.js.ast.JsScope;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsStringLiteral;
import com.google.gwt.dev.js.ast.JsSwitch;
import com.google.gwt.dev.js.ast.JsSwitchMember;
import com.google.gwt.dev.js.ast.JsThisRef;
import com.google.gwt.dev.js.ast.JsThrow;
import com.google.gwt.dev.js.ast.JsTry;
import com.google.gwt.dev.js.ast.JsUnaryOperator;
import com.google.gwt.dev.js.ast.JsVars;
import com.google.gwt.dev.js.ast.JsVars.JsVar;
import com.google.gwt.dev.js.ast.JsWhile;
import com.google.gwt.dev.util.Pair;
import com.google.gwt.dev.util.StringInterner;
import com.google.gwt.dev.util.arg.OptionMethodNameDisplayMode;
import com.google.gwt.dev.util.arg.OptionOptimize;
import com.google.gwt.dev.util.collect.Stack;
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.thirdparty.guava.common.base.Function;
import com.google.gwt.thirdparty.guava.common.base.Joiner;
import com.google.gwt.thirdparty.guava.common.base.Predicate;
import com.google.gwt.thirdparty.guava.common.base.Predicates;
import com.google.gwt.thirdparty.guava.common.collect.FluentIterable;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSortedSet;
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.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Sets;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeMap;

/**
 * Creates a JavaScript AST from a <code>JProgram</code> node.
 */
public class GenerateJavaScriptAST {

  /**
   * Finds the nodes that are targets of JNameOf so that a name is assigned to them.
   */
  private class FindNameOfTargets extends JVisitor {
    @Override
    public void endVisit(JNameOf x, Context ctx) {
      nameOfTargets.add(x.getNode());
    }
  }

  private class CreateNamesAndScopesVisitor extends JVisitor {

    /**
     * Cache of computed Java source file names to URI strings for symbol
     * export. By using a cache we also ensure the miminum number of String
     * instances are serialized.
     */
    private final Map<String, String> fileNameToUriString = Maps.newHashMap();

    private final Stack<JsScope> scopeStack = new Stack<JsScope>();

    private JMethod currentMethod;

    @Override
    public boolean visit(JProgram x, Context ctx) {
      // Scopes and name objects need to be calculated within all types, even reference-only ones.
      // This information is used to be able to detect and avoid name collisions during pretty or
      // obfuscated JS variable name generation.
      x.visitAllTypes(this);
      return false;
    }

    @Override
    public void endVisit(JArrayType x, Context ctx) {
      JsName name = topScope.declareName(x.getName());
      names.put(x, name);
      recordSymbol(x, name);
    }

    @Override
    public void endVisit(JClassType x, Context ctx) {
      scopeStack.pop();
    }

    @Override
    public void endVisit(JField x, Context ctx) {
      JsName jsName;
      if (x.isStatic()) {
        jsName = topScope.declareName(mangleName(x), x.getName());
      } else {
        jsName = JjsUtils.exposesJsName(x)
                ? scopeStack.peek().declareUnobfuscatableName(x.getJsName())
                : scopeStack.peek().declareName(mangleName(x), x.getName());
      }
      names.put(x, jsName);
      recordSymbol(x, jsName);
    }

    @Override
    public void endVisit(JInterfaceType x, Context ctx) {
      scopeStack.pop();
    }

    @Override
    public void endVisit(JLabel x, Context ctx) {
      if (names.get(x) != null) {
        return;
      }
      names.put(x, scopeStack.peek().declareName(x.getName()));
    }

    @Override
    public void endVisit(JLocal x, Context ctx) {
      // locals can conflict, that's okay just reuse the same variable
      JsScope scope = scopeStack.peek();
      JsName jsName = scope.declareName(x.getName());
      names.put(x, jsName);
    }

    @Override
    public void endVisit(JMethod x, Context ctx) {
      if (doesNotHaveConcreteImplementation(x)) {
        return;
      }
      scopeStack.pop();
    }

    @Override
    public void endVisit(JParameter x, Context ctx) {
      if (x.isVarargs() && currentMethod.isJsMethodVarargs()) {
        names.put(x, scopeStack.peek().declareUnobfuscatableName("arguments"));
        return;
      }
      names.put(x, scopeStack.peek().declareName(x.getName()));
    }

    @Override
    public void endVisit(JProgram x, Context ctx) {
      /*
       * put the null method and field into objectScope since they can be
       * referenced as instance on null-types (as determined by type flow)
       */
      JMethod nullMethod = x.getNullMethod();
      polymorphicNames.put(nullMethod, objectScope.declareName("$_nullMethod"));
      JField nullField = x.getNullField();
      JsName nullFieldName = objectScope.declareName("$_nullField");
      names.put(nullField, nullFieldName);

      /*
       * Create names for instantiable array types since JProgram.traverse()
       * doesn't iterate over them.
       */
      for (JArrayType arrayType : program.getAllArrayTypes()) {
        if (program.typeOracle.isInstantiatedType(arrayType)) {
          accept(arrayType);
        }
      }
    }

    @Override
    public boolean visit(JClassType x, Context ctx) {
      // have I already been visited as a super type?
      JsScope myScope = classScopes.get(x);
      if (myScope != null) {
        scopeStack.push(myScope);
        return false;
      }

      // My seed function name
      JsName jsName = topScope.declareName(JjsUtils.mangledNameString(x), x.getShortName());
      names.put(x, jsName);
      recordSymbol(x, jsName);

      // My class scope
      if (x.getSuperClass() == null) {
        myScope = objectScope;
      } else {
        JsScope parentScope = classScopes.get(x.getSuperClass());
        // Run my superclass first!
        if (parentScope == null) {
          accept(x.getSuperClass());
        }
        parentScope = classScopes.get(x.getSuperClass());
        assert (parentScope != null);
        /*
         * WEIRD: we wedge the global interface scope in between object and all
         * of its subclasses; this ensures that interface method names trump all
         * (except Object method names)
         */
        if (parentScope == objectScope) {
          parentScope = interfaceScope;
        }
        myScope = new JsNormalScope(parentScope, "class " + x.getShortName());
      }
      classScopes.put(x, myScope);

      scopeStack.push(myScope);
      return true;
    }

    @Override
    public boolean visit(JInterfaceType x, Context ctx) {
      // interfaces have no name at run time
      scopeStack.push(interfaceScope);
      return true;
    }

    @Override
    public boolean visit(JMethod x, Context ctx) {
      currentMethod = x;
      // my polymorphic name
      String name = x.getName();
      if (x.needsDynamicDispatch()) {
        if (polymorphicNames.get(x) == null) {
          JsName polyName = JjsUtils.exposesJsName(x)
                  ? interfaceScope.declareUnobfuscatableName(x.getJsName())
                  : interfaceScope.declareName(mangleNameForPoly(x), name);
          polymorphicNames.put(x, polyName);
        }
      }

      if (doesNotHaveConcreteImplementation(x)) {
        return false;
      }

      // my global name
      JsName globalName = null;
      assert x.getEnclosingType() != null;
      String mangleName = mangleNameForGlobal(x);

      if (JProgram.isClinit(x)) {
        name = name + "_" + x.getEnclosingType().getShortName();
      }

      /*
       * Only allocate a name for a function if it is native, not polymorphic,
       * is a JNameOf target or stack-stripping is disabled.
       */
      if (!stripStack || !polymorphicNames.containsKey(x) || x.isJsniMethod()
          || nameOfTargets.contains(x)) {
        globalName = topScope.declareName(mangleName, name);
        names.put(x, globalName);
        recordSymbol(x, globalName);
      }
      JsFunction function;
      if (x.isJsniMethod()) {
        // set the global name of the JSNI peer
        JsniMethodBody body = (JsniMethodBody) x.getBody();
        function = body.getFunc();
        function.setName(globalName);
      } else {
        /*
         * It would be more correct here to check for an inline assignment, such
         * as var foo = function blah() {} and introduce a separate scope for
         * the function's name according to EcmaScript-262, but this would mess
         * up stack traces by allowing two inner scope function names to
         * obfuscate to the same identifier, making function names no longer a
         * 1:1 mapping to obfuscated symbols. Leaving them in global scope
         * causes no harm.
         */
        function = new JsFunction(x.getSourceInfo(), topScope, globalName, !x.isJsNative());
      }

      jsFunctionsByJavaMethodBody.put(x.getBody(), function);
      scopeStack.push(function.getScope());

      // Don't traverse the method body of methods in referenceOnly types since those method bodies
      // only exist in JS output of other modules it is their responsibility to handle their naming.
      return !program.isReferenceOnly(x.getEnclosingType());
    }

    @Override
    public boolean visit(JTryStatement x, Context ctx) {
      accept(x.getTryBlock());
      for (JTryStatement.CatchClause clause : x.getCatchClauses()) {
        JLocalRef arg = clause.getArg();
        JBlock catchBlock = clause.getBlock();
        JsCatch jsCatch =
            new JsCatch(x.getSourceInfo(), scopeStack.peek(), arg.getTarget().getName());
        JsParameter jsParam = jsCatch.getParameter();
        names.put(arg.getTarget(), jsParam.getName());
        catchMap.put(catchBlock, jsCatch);
        catchParamIdentifiers.add(jsParam.getName());

        scopeStack.push(jsCatch.getScope());
        accept(catchBlock);
        scopeStack.pop();
      }

      // TODO: normalize this so it's never null?
      if (x.getFinallyBlock() != null) {
        accept(x.getFinallyBlock());
      }
      return false;
    }

    /**
     * Generate a file name URI string for a source info, for symbol data
     * export.
     */
    private String makeUriString(HasSourceInfo x) {
      String fileName = x.getSourceInfo().getFileName();
      if (fileName == null) {
        return null;
      }
      String uriString = fileNameToUriString.get(fileName);
      if (uriString == null) {
        uriString = StandardSymbolData.toUriString(fileName);
        fileNameToUriString.put(fileName, uriString);
      }
      return uriString;
    }

    private void recordSymbol(JReferenceType type, JsName jsName) {
      if (getRuntimeTypeReference(type) == null || !program.typeOracle.isInstantiatedType(type)) {
        return;
      }

      String typeId = getRuntimeTypeReference(type).toSource();
      StandardSymbolData symbolData =
          StandardSymbolData.forClass(type.getName(), type.getSourceInfo().getFileName(),
              type.getSourceInfo().getStartLine(), typeId);
      assert !symbolTable.containsKey(symbolData);
      symbolTable.put(symbolData, jsName);
    }

    private <T extends HasEnclosingType & HasName & HasSourceInfo> void recordSymbol(T member,
        JsName jsName) {
      /*
       * NB: The use of member.getName() can produce confusion in cases where a type
       * has both polymorphic and static dispatch for a method, because you
       * might see HashSet::$add() and HashSet::add(). Logically, these methods
       * should be treated equally, however they will be implemented with
       * separate global functions and must be recorded independently.
       *
       * Automated systems that process the symbol information can easily map
       * the statically-dispatched function by looking for method names that
       * begin with a dollar-sign and whose first parameter is the enclosing
       * type.
       */

      String methodSignature = null;
      if (member instanceof JMethod) {
        JMethod method = ((JMethod) member);
        methodSignature =
            StringInterner.get().intern(method.getSignature().substring(method.getName().length()));
      }

      StandardSymbolData symbolData =
          StandardSymbolData.forMember(member.getEnclosingType().getName(), member.getName(),
              methodSignature,  makeUriString(member), member.getSourceInfo().getStartLine());
      assert !symbolTable.containsKey(symbolData) : "Duplicate symbol recorded " + jsName.getIdent()
          + " for " + member.getName() + " and key " + symbolData.getJsniIdent();
      symbolTable.put(symbolData, jsName);
    }
  }

  private class GenerateJavaScriptTransformer extends JTransformer<JsNode> {

    public static final String GOOG_ABSTRACT_METHOD = "goog.abstractMethod";
    public static final String GOOG_INHERITS = "goog.inherits";
    public static final String GOOG_OBJECT_CREATE_SET = "goog.object.createSet";

    private final Set<JDeclaredType> alreadyRan = Sets.newLinkedHashSet();

    private final Map<JDeclaredType, JsFunction> clinitFunctionForType = Maps.newHashMap();

    private JMethod currentMethod = null;

    private final JsName arrayLength = objectScope.declareUnobfuscatableName("length");
    private final JsName globalTemp = topScope.declareUnobfuscatableName("_");
    private final JsName prototype = objectScope.declareUnobfuscatableName("prototype");

    @Override
    public JsExpression transformArrayLength(JArrayLength expression) {
      assert expression.getInstance() != null : "Can't access the length of a null array";
      return arrayLength.makeQualifiedRef(expression.getSourceInfo(),
          transform(expression.getInstance()));
    }

    @Override
    public JsExpression transformArrayRef(JArrayRef arrayRef) {
      JsArrayAccess jsArrayAccess = new JsArrayAccess(arrayRef.getSourceInfo());
      jsArrayAccess.setIndexExpr(transform(arrayRef.getIndexExpr()));
      jsArrayAccess.setArrayExpr(transform(arrayRef.getInstance()));
      return jsArrayAccess;
    }

    @Override
    public JsExpression transformBinaryOperation(JBinaryOperation binaryOperation) {
      JsExpression lhs = transform(binaryOperation.getLhs());
      JsExpression rhs = transform(binaryOperation.getRhs());
      JsBinaryOperator op = JavaToJsOperatorMap.get(binaryOperation.getOp());

      /*
       * Use === and !== on reference types, or else you can get wrong answers
       * when Object.toString() == 'some string'.
       */
      if (binaryOperation.getLhs().getType() instanceof JReferenceType
          && binaryOperation.getRhs().getType() instanceof JReferenceType) {
        switch (op) {
          case EQ:
            op = JsBinaryOperator.REF_EQ;
            break;
          case NEQ:
            op = JsBinaryOperator.REF_NEQ;
            break;
        }
      }
      return new JsBinaryOperation(binaryOperation.getSourceInfo(), op, lhs, rhs);
    }

    @Override
    public JsStatement transformBlock(JBlock block) {
      JsBlock jsBlock = new JsBlock(block.getSourceInfo());
      List<JsStatement> stmts = jsBlock.getStatements();

      transformIntoExcludingNulls(block.getStatements(), stmts);
      Iterables.removeIf(stmts, Predicates.instanceOf(JsEmpty.class));
      return jsBlock;
    }

    @Override
    public JsNode transformBreakStatement(JBreakStatement breakStatement) {
      SourceInfo info = breakStatement.getSourceInfo();
      return new JsBreak(info, transformIntoLabelReference(info, breakStatement.getLabel()));
    }

    @Override
    public JsNode transformCaseStatement(JCaseStatement caseStatement) {
      if (caseStatement.getExpr() == null) {
        return new JsDefault(caseStatement.getSourceInfo());
      } else {
        JsCase jsCase = new JsCase(caseStatement.getSourceInfo());
        jsCase.setCaseExpr(transform(caseStatement.getExpr()));
        return jsCase;
      }
    }

    @Override
    public JsNode transformCastOperation(JCastOperation castOperation) {
      // These are left in when cast checking is disabled.
      return transform(castOperation.getExpr());
    }

    @Override
    public JsNode transformClassLiteral(JClassLiteral classLiteral) {
      JsName classLit = names.get(classLiteral.getField());
      return classLit.makeRef(classLiteral.getSourceInfo());
    }

    @Override
    public JsNode transformDeclaredType(JDeclaredType type) {
      // Don't generate JS for types not in current module if separate compilation is on.
      if (program.isReferenceOnly(type)) {
        return null;
      }

      if (alreadyRan.contains(type)) {
        return null;
      }

      alreadyRan.add(type);

      if (type.isJsNative()) {
        // Emit JsOverlay static methods for native JsTypes.
        emitStaticMethods(type);
        // Emit JsOverlay (static) fields for native JsTypes.
        emitFields(type);
        return null;
      }

      checkForDuplicateMethods(type);

      assert program.getTypeClassLiteralHolder() != type;
      assert !program.immortalCodeGenTypes.contains(type);
      // Super classes should be emitted before the actual class.
      assert type.getSuperClass() == null || program.isReferenceOnly(type.getSuperClass()) ||
          alreadyRan.contains(type.getSuperClass());

      emitStaticMethods(type);

      generateTypeSetup(type);

      emitFields(type);
      return null;
    }

    @Override
    public JsNode transformConditional(JConditional conditional) {
      JsExpression ifTest = transform(conditional.getIfTest());
      JsExpression thenExpr = transform(conditional.getThenExpr());
      JsExpression elseExpr = transform(conditional.getElseExpr());
      return new JsConditional(conditional.getSourceInfo(), ifTest, thenExpr, elseExpr);
    }

    @Override
    public JsNode transformContinueStatement(JContinueStatement continueStatement) {
      SourceInfo info = continueStatement.getSourceInfo();
      return new JsContinue(info, transformIntoLabelReference(info, continueStatement.getLabel()));
    }

    @Override
    public JsNode transformDebuggerStatement(JDebuggerStatement debuggerStatement) {
      return new JsDebugger(debuggerStatement.getSourceInfo());
    }

    @Override
    public JsNode transformDeclarationStatement(JDeclarationStatement declarationStatement) {
      if (declarationStatement.getInitializer() == null) {
        return null;
      }

      JVariable target = declarationStatement.getVariableRef().getTarget();
      if (target instanceof JField && initializeAtTopScope((JField) target)) {
        // Will initialize at top scope; no need to double-initialize.
        return null;
      }

      JsExpression initializer = transform(declarationStatement.getInitializer());
      JsNameRef localRef = transform(declarationStatement.getVariableRef());

      SourceInfo info = declarationStatement.getSourceInfo();
      return JsUtils.createAssignment(info, localRef, initializer).makeStmt();
    }

    @Override
    public JsNode transformDoStatement(JDoStatement doStatement) {
      JsDoWhile stmt = new JsDoWhile(doStatement.getSourceInfo());
      stmt.setCondition(transform(doStatement.getTestExpr()));
      stmt.setBody(jsEmptyIfNull(doStatement.getSourceInfo(), transform(doStatement.getBody())));
      return stmt;
    }

    @Override
    public JsNode transformExpressionStatement(JExpressionStatement statement) {
      return ((JsExpression) transform(statement.getExpr())).makeStmt();
    }

    @Override
    public JsNode transformFieldRef(JFieldRef fieldRef) {
      JsExpression qualifier = transform(fieldRef.getInstance());
      boolean isStatic = fieldRef.getField().isStatic();
      return isStatic ? dispatchToStaticField(fieldRef, qualifier)
          : dispatchToInstanceField(fieldRef, qualifier);
    }

    private JsExpression dispatchToStaticField(
        JFieldRef fieldRef, JsExpression unnecessaryQualifier) {
      /*
       * Note: the comma expressions here would cause an illegal tree state if
       * the result expression ended up on the lhs of an assignment.
       * {@link JsNormalizer} will fix this situation.
       */

      JsExpression result = createStaticReference(fieldRef.getField(), fieldRef.getSourceInfo());

      return JsUtils.createCommaExpression(
          unnecessaryQualifier, maybeCreateClinitCall(fieldRef.getField()), result);
    }

    private JsExpression dispatchToInstanceField(JFieldRef x, JsExpression instance) {
      return names.get(x.getField()).makeQualifiedRef(x.getSourceInfo(), instance);
    }

    @Override
    public JsNode transformForStatement(JForStatement forStatement) {
      JsFor result = new JsFor(forStatement.getSourceInfo());

      JsExpression initExpr = null;
      List<JsExprStmt> initStmts = transform(forStatement.getInitializers());
      for (int i = 0; i < initStmts.size(); ++i) {
        JsExprStmt initStmt = initStmts.get(i);
        if (initStmt != null) {
          initExpr = JsUtils.createCommaExpression(initExpr, initStmt.getExpression());
        }
      }
      result.setInitExpr(initExpr);
      result.setCondition(transform(forStatement.getCondition()));
      result.setIncrExpr(transform(forStatement.getIncrements()));
      result.setBody(jsEmptyIfNull(forStatement.getSourceInfo(), transform(forStatement.getBody())));

      return result;
    }

    @Override
    public JsNode transformIfStatement(JIfStatement ifStatement) {
      JsIf result = new JsIf(ifStatement.getSourceInfo());

      result.setIfExpr(transform(ifStatement.getIfExpr()));
      result.setThenStmt(jsEmptyIfNull(ifStatement.getSourceInfo(),
          transform(ifStatement.getThenStmt())));
      result.setElseStmt(transform(ifStatement.getElseStmt()));

      return result;
    }

    @Override
    public JsLabel transformLabel(JLabel label) {
      return new JsLabel(label.getSourceInfo(), names.get(label));
    }

    @Override
    public JsStatement transformLabeledStatement(JLabeledStatement labeledStatement) {
      JsLabel label = transform(labeledStatement.getLabel());
      label.setStmt(transform(labeledStatement.getBody()));
      return label;
    }

    @Override
    public JsLiteral transformLiteral(JLiteral literal) {
      return JjsUtils.translateLiteral(literal);
    }

    @Override
    public JsNode transformLocalRef(JLocalRef localRef) {
      return names.get(localRef.getTarget()).makeRef(localRef.getSourceInfo());
    }

    @Override
    public JsNode transformMethod(JMethod method) {
      if (method.isAbstract()) {
        return generateAbstractMethodDefinition(method);
      } else if (doesNotHaveConcreteImplementation(method)) {
        return null;
      }
      currentMethod = method;

      JsFunction function = transform(method.getBody());
      function.setInliningMode(method.getInliningMode());

      if (!method.isJsniMethod()) {
        // Setup params on the generated function. A native method already got
        // its jsParams set when parsed from JSNI.
        List<JParameter> parameterList = method.getParams();
        if (method.isJsMethodVarargs()) {
          parameterList = parameterList.subList(0, parameterList.size() - 1);
        }
        transformInto(parameterList, function.getParameters());
      }

      JsInvocation jsInvocation = maybeCreateClinitCall(method);
      if (jsInvocation != null) {
        function.getBody().getStatements().add(0, jsInvocation.makeStmt());
      }

      if (JProgram.isClinit(method)) {
        function.markAsClinit();
      }

      currentMethod = null;
      return function;
    }

    @Override
    public JsNode transformMethodBody(JMethodBody methodBody) {

      JsBlock body = transform(methodBody.getBlock());

      JsFunction function = jsFunctionsByJavaMethodBody.get(methodBody);
      function.setBody(body);

      /*
       * Emit a statement to declare the method's complete set of local
       * variables. JavaScript doesn't have the same concept of lexical scoping
       * as Java, so it's okay to just predeclare all local vars at the top of
       * the function, which saves us having to use the "var" keyword over and
       * over.
       *
       * Note: it's fine to use the same JS ident to represent two different
       * Java locals of the same name since they could never conflict with each
       * other in Java. We use the alreadySeen set to make sure we don't declare
       * the same-named local var twice.
       */
      JsVars vars = new JsVars(methodBody.getSourceInfo());
      Set<String> alreadySeen = Sets.newHashSet();
      for (JLocal local : methodBody.getLocals()) {
        JsName name = names.get(local);
        String ident = name.getIdent();
        if (!alreadySeen.contains(ident)
            // Catch block params don't need var declarations
            && !catchParamIdentifiers.contains(name)) {
          alreadySeen.add(ident);
          vars.add(new JsVar(methodBody.getSourceInfo(), name));
        }
      }

      if (!vars.isEmpty()) {
        function.getBody().getStatements().add(0, vars);
      }

      return function;
    }

    @Override
    public JsNode transformMethodCall(JMethodCall methodCall) {
      JMethod method = methodCall.getTarget();
      if (JProgram.isClinit(method)) {
        /*
         * It is possible for clinits to be referenced here that have actually
         * been retargeted (see {@link
         * JTypeOracle.recomputeAfterOptimizations}). Most of the time, these
         * will get cleaned up by other optimization passes prior to this point,
         * but it's not guaranteed. In this case we need to replace the method
         * call with the replaced clinit, unless the replacement is null, in
         * which case we generate a JsNullLiteral as a place-holder expression.
         */
        JDeclaredType type = method.getEnclosingType();
        JDeclaredType clinitTarget = type.getClinitTarget();
        if (clinitTarget == null) {
          // generate a null expression, which will get optimized out
          return JsNullLiteral.INSTANCE;
        }
        method = clinitTarget.getClinitMethod();
      }

      JsExpression qualifier = transform(methodCall.getInstance());
      List<JsExpression> args = transform(methodCall.getArgs());
      SourceInfo sourceInfo = methodCall.getSourceInfo();
      if (method.isStatic()) {
        return dispatchToStatic(qualifier, method, args, sourceInfo);
      } else if (methodCall.isStaticDispatchOnly()) {
        return dispatchToSuper(qualifier, method, args, sourceInfo);
      } else if (method.isOrOverridesJsFunctionMethod()) {
        return dispatchToJsFunction(qualifier, method, args, sourceInfo);
      } else {
        return dispatchToInstanceMethod(qualifier, method, args, sourceInfo);
      }
    }

    private JsExpression dispatchToStatic(JsExpression unnecessaryQualifier, JMethod method,
        List<JsExpression> args, SourceInfo sourceInfo) {
      JsNameRef methodName = createStaticReference(method, sourceInfo);
      return JsUtils.createCommaExpression(
          unnecessaryQualifier,
          createInvocationOrPropertyAccess(
              InvocationStyle.NORMAL, sourceInfo, method, null, methodName, args));
    }

    private JsExpression dispatchToSuper(
        JsExpression instance, JMethod method, List<JsExpression> args, SourceInfo sourceInfo) {
      JsNameRef methodNameRef;
      if (method.isJsNative()) {
        // Construct Constructor.prototype.jsname or Constructor.
        methodNameRef = createGlobalQualifier(method.getQualifiedJsName(), sourceInfo);
      } else if (method.isConstructor()) {
        /*
         * Constructor calls through {@code this} and {@code super} are always dispatched statically
         * using the constructor function name (constructors are always defined as top level
         * functions).
         *
         * Because constructors are modeled like instance methods they have an implicit {@code this}
         * parameter, hence they are invoked like: "constructor.call(this, ...)".
         */
        methodNameRef = names.get(method).makeRef(sourceInfo);
      } else {
        // These are regular super method call. These calls are always dispatched statically and
        // optimizations will devirtualize them (except in a few cases, like being target of
        // {@link Impl.getNameOf} or calls to the native classes.

        JDeclaredType superClass = method.getEnclosingType();
        JsExpression protoRef = getPrototypeQualifierViaLookup(superClass, sourceInfo);
        methodNameRef = polymorphicNames.get(method).makeQualifiedRef(sourceInfo, protoRef);
      }

      return JsUtils.createInvocationOrPropertyAccess(InvocationStyle.SUPER,
          sourceInfo, method, instance, methodNameRef, args);
    }

    private JsExpression getPrototypeQualifierViaLookup(JDeclaredType type, SourceInfo sourceInfo) {
      if (closureCompilerFormatEnabled) {
        return getPrototypeQualifierOf(type, type.getSourceInfo());
      } else {
        // Construct JCHSU.getPrototypeFor(type).polyname
        // TODO(rluble): Ideally we would want to construct the inheritance chain the JS way and
        // then we could do Type.prototype.polyname.call(this, ...). Currently prototypes do not
        // have global names instead they are stuck into the prototypesByTypeId array.
        return constructInvocation(sourceInfo, RuntimeConstants.RUNTIME_GET_CLASS_PROTOTYPE,
            (JsExpression) transform(getRuntimeTypeReference(type)));
      }
    }

    private JsExpression dispatchToJsFunction(JsExpression instance, JMethod method,
        List<JsExpression> args, SourceInfo sourceInfo) {
      return createInvocationOrPropertyAccess(
          InvocationStyle.FUNCTION, sourceInfo, method, instance, null, args);
    }

    private JsExpression dispatchToInstanceMethod(JsExpression instance, JMethod method,
        List<JsExpression> args, SourceInfo sourceInfo) {
      JsNameRef reference = polymorphicNames.get(method).makeQualifiedRef(sourceInfo, instance);
      return createInvocationOrPropertyAccess(
          InvocationStyle.NORMAL, sourceInfo, method, instance, reference, args);
    }

    @Override
    public JsNode transformMultiExpression(JMultiExpression multiExpression) {
      if (multiExpression.isEmpty()) {
        // the multi-expression was empty; use undefined
        return JsRootScope.INSTANCE.getUndefined().makeRef(multiExpression.getSourceInfo());
      }

      List<JsExpression> exprs = transform(multiExpression.getExpressions());
      JsExpression cur = null;
      for (int i = 0; i < exprs.size(); ++i) {
        JsExpression next = exprs.get(i);
        cur = JsUtils.createCommaExpression(cur, next);
      }
      return cur;
    }

    @Override
    public JsNode transformNameOf(JNameOf nameof) {
      JsName name = names.get(nameof.getNode());
      if (name == null) {
        return JsRootScope.INSTANCE.getUndefined().makeRef(nameof.getSourceInfo());
      }
      return new JsNameOf(nameof.getSourceInfo(), name);
    }

    @Override
    public JsNode transformNewInstance(JNewInstance newInstance) {
      SourceInfo sourceInfo = newInstance.getSourceInfo();
      JConstructor ctor = newInstance.getTarget();
      JsName ctorName = names.get(ctor);
      JsNameRef  reference = ctor.isJsNative()
          ? createGlobalQualifier(ctor.getQualifiedJsName(), sourceInfo)
          : ctorName.makeRef(sourceInfo);
      List<JsExpression> arguments = transform(newInstance.getArgs());

      if (newInstance.getClassType().isJsFunctionImplementation()) {
        // Synthesize makeLambdaFunction(samMethodReference, constructorReference, ctorArguments)
        // which will create the function instance and run the constructor on it.
        // TODO(rluble): optimize the constructor call away if it is empty.
        return constructJsFunctionObject(
            sourceInfo,
            newInstance.getClassType(),
            ctorName,
            reference,
            new JsArrayLiteral(sourceInfo, arguments));
      }

      return JsUtils.createInvocationOrPropertyAccess(
          InvocationStyle.NEWINSTANCE, sourceInfo, ctor, null, reference, arguments);
    }

    private JsExpression constructJsFunctionObject(SourceInfo sourceInfo, JClassType type,
        JsName ctorName, JsNameRef ctorReference, JsExpression ctorArguments) {
      // Foo.prototype.functionMethodName
      JMethod jsFunctionMethod = getJsFunctionMethod(type);
      JsNameRef funcNameRef = JsUtils.createQualifiedNameRef(sourceInfo,
          ctorName, prototype, polymorphicNames.get(jsFunctionMethod));

      // makeLambdaFunction(Foo.prototype.functionMethodName, new Foo(...))
      return constructInvocation(sourceInfo, RuntimeConstants.RUNTIME_MAKE_LAMBDA_FUNCTION,
          funcNameRef, ctorReference, ctorArguments);
    }

    private JMethod getJsFunctionMethod(JClassType type) {
      for (JMethod method : type.getMethods()) {
        if (method.isOrOverridesJsFunctionMethod()) {
          return method;
        }
      }
      throw new AssertionError("Should never reach here.");
    }

    @Override
    public JsNode transformNumericEntry(JNumericEntry entry) {
      return new JsNumericEntry(entry.getSourceInfo(), entry.getKey(), entry.getValue());
    }

    @Override
    public JsNode transformParameter(JParameter parameter) {
      assert !(currentMethod.isJsMethodVarargs() && parameter.isVarargs());
      return new JsParameter(parameter.getSourceInfo(), names.get(parameter));
    }

    @Override
    public JsNode transformParameterRef(JParameterRef parameterRef) {
      return names.get(parameterRef.getTarget()).makeRef(parameterRef.getSourceInfo());
    }

    @Override
    public JsNode transformPermutationDependentValue(JPermutationDependentValue dependentValue) {
      throw new AssertionError("AST should not contain permutation dependent values at " +
          "this point but contains " + dependentValue);
    }

    @Override
    public JsNode transformPostfixOperation(JPostfixOperation expression) {
      return new JsPostfixOperation(expression.getSourceInfo(), JavaToJsOperatorMap.get(expression.getOp()),
          transform(expression.getArg()));
    }

    @Override
    public JsNode transformPrefixOperation(JPrefixOperation expression) {
      return new JsPrefixOperation(expression.getSourceInfo(),
          JavaToJsOperatorMap.get(expression.getOp()), transform(expression.getArg()));
    }

    /**
     * Embeds properties into permProps for easy access from JavaScript.
     */
    private void embedBindingProperties() {
      SourceInfo sourceInfo = SourceOrigin.UNKNOWN;

      // Generates a list of lists of pairs: [[["key", "value"], ...], ...]
      // The outermost list is indexed by soft permutation id. Each item represents
      // a map from binding properties to their values, but is stored as a list of pairs
      // for easy iteration.
      JsArrayLiteral permutationProperties = new JsArrayLiteral(sourceInfo);
      for (Map<String, String> propertyValueByPropertyName :
          properties.findEmbeddedProperties(TreeLogger.NULL)) {
        JsArrayLiteral entryList = new JsArrayLiteral(sourceInfo);
        for (Entry<String, String> entry : propertyValueByPropertyName.entrySet()) {
          JsArrayLiteral pair = new JsArrayLiteral(sourceInfo,
              new JsStringLiteral(sourceInfo, entry.getKey()),
              new JsStringLiteral(sourceInfo, entry.getValue()));
          entryList.getExpressions().add(pair);
        }
        permutationProperties.getExpressions().add(entryList);
      }

      getGlobalStatements().add(
          constructInvocation(sourceInfo, "ModuleUtils.setGwtProperty",
              new JsStringLiteral(sourceInfo, "permProps"), permutationProperties).makeStmt());
    }

    @Override
    public JsNode transformReturnStatement(JReturnStatement returnStatement) {
      return new JsReturn(returnStatement.getSourceInfo(), transform(returnStatement.getExpr()));
    }

    @Override
    public JsNode transformRunAsync(JRunAsync runAsync) {
      return transform(runAsync.getRunAsyncCall());
    }

    @Override
    public JsNode transformCastMap(JCastMap castMap) {
      SourceInfo sourceInfo = castMap.getSourceInfo();
      List<JsExpression> jsCastToTypes = transform(castMap.getCanCastToTypes());
      return buildJsCastMapLiteral(jsCastToTypes, sourceInfo);
    }

    @Override
    public JsNameRef transformJsniMethodRef(JsniMethodRef jsniMethodRef) {
      JMethod method = jsniMethodRef.getTarget();
      if (method.isJsNative()) {
        // Construct Constructor.prototype.jsname or Constructor.
        return createGlobalQualifier(method.getQualifiedJsName(), jsniMethodRef.getSourceInfo());
      }
      return names.get(method).makeRef(jsniMethodRef.getSourceInfo());
    }

    @Override
    public JsArrayLiteral transformJsonArray(JsonArray jsonArray) {
      JsArrayLiteral jsArrayLiteral = new JsArrayLiteral(jsonArray.getSourceInfo());
      transformInto(jsonArray.getExpressions(), jsArrayLiteral.getExpressions());
      return jsArrayLiteral;
    }

    @Override
    public JsNode transformThisRef(JThisRef thisRef) {
      return new JsThisRef(thisRef.getSourceInfo());
    }

    @Override
    public JsNode transformThrowStatement(JThrowStatement throwStatement) {
      return new JsThrow(throwStatement.getSourceInfo(), transform(throwStatement.getExpr()));
    }

    @Override
    public JsNode transformTryStatement(JTryStatement tryStatement) {
      JsTry jsTry = new JsTry(tryStatement.getSourceInfo());

      jsTry.setTryBlock(transform(tryStatement.getTryBlock()));

      int size = tryStatement.getCatchClauses().size();
      assert (size < 2);
      if (size == 1) {
        JBlock block = tryStatement.getCatchClauses().get(0).getBlock();
        JsCatch jsCatch = catchMap.get(block);
        jsCatch.setBody(transform(block));
        jsTry.getCatches().add(jsCatch);
      }

      JsBlock finallyBlock = transform(tryStatement.getFinallyBlock());
      if (finallyBlock != null && finallyBlock.getStatements().size() > 0) {
        jsTry.setFinallyBlock(finallyBlock);
      }

      return jsTry;
    }

    @Override
    public JsNode transformWhileStatement(JWhileStatement whileStatement) {
      SourceInfo info = whileStatement.getSourceInfo();
      JsWhile stmt = new JsWhile(info);
      stmt.setCondition(transform(whileStatement.getTestExpr()));
      stmt.setBody(jsEmptyIfNull(info, transform(whileStatement.getBody())));
      return stmt;
    }

    public JsStatement jsEmptyIfNull(SourceInfo info, JsStatement statement) {
      return statement != null ? statement : new JsEmpty(info);
    }

    private void insertInTopologicalOrder(JDeclaredType type,
        Set<JDeclaredType> topologicallySortedSet) {
      if (type == null || topologicallySortedSet.contains(type) || program.isReferenceOnly(type)) {
        return;
      }
      insertInTopologicalOrder(type.getSuperClass(), topologicallySortedSet);

      for (JInterfaceType intf : type.getImplements()) {
        if (program.typeOracle.isInstantiatedType(type)) {
          insertInTopologicalOrder(intf, topologicallySortedSet);
        }
      }

      topologicallySortedSet.add(type);
    }

    @Override
    public JsNode transformProgram(JProgram program) {
      // Handle the visiting here as we need to slightly change the order.
      // 1.1 (preamble) Immortal code gentypes.
      // 1.2 (preamble) Classes in the preamble, i.e. all the classes that are needed
      //                to support creation of class literals (reachable through Class.createFor* ).
      // 1.3 (preamble) Class literals for classes in the preamble.
      // 2.  (body)     Normal classes, each with its corresponding class literal (if live).
      // 3.  (epilogue) Code to start the execution of the program (gwtOnLoad, etc).

      Set<JDeclaredType> preambleTypes = generatePreamble(program);

      if (incremental) {
        // Record the names of preamble types so that it's possible to invalidate caches when the
        // preamble types are known to have become stale.
        if (!minimalRebuildCache.hasPreambleTypeNames()) {
          Set<String> preambleTypeNames =  Sets.newHashSet();
          for (JDeclaredType preambleType : preambleTypes) {
            preambleTypeNames.add(preambleType.getName());
          }
          minimalRebuildCache.setPreambleTypeNames(logger, preambleTypeNames);
        }
      }

      // Sort normal types according to superclass relationship.
      Set<JDeclaredType> topologicallySortedBodyTypes = Sets.newLinkedHashSet();
      for (JDeclaredType type : program.getModuleDeclaredTypes()) {
        insertInTopologicalOrder(type, topologicallySortedBodyTypes);
      }
      // Remove all preamble types that might have been inserted here.
      topologicallySortedBodyTypes.removeAll(preambleTypes);

      // Iterate over each type in the right order.
      markPosition("Program", Type.PROGRAM_START);
      for (JDeclaredType type : topologicallySortedBodyTypes) {
        markPosition(type.getName(), Type.CLASS_START);
        transform(type);
        maybeGenerateClassLiteral(type);
        installClassLiterals(Arrays.asList(type));
        markPosition(type.getName(), Type.CLASS_END);
      }
      markPosition("Program", Type.PROGRAM_END);

      generateEpilogue();

      // All done, do not visit children.
      return null;
    }

    private Set<JDeclaredType> generatePreamble(JProgram program) {
      // Reserve the "_" identifier.
      JsVars vars = new JsVars(jsProgram.getSourceInfo());
      vars.add(new JsVar(jsProgram.getSourceInfo(), globalTemp));
      addVarsIfNotEmpty(vars);

      // Generate immortal types in the preamble.
      generateImmortalTypes(vars);

      //  Perform necessary polyfills.
      addTypeDefinitionStatement(
          program.getIndexedType(RuntimeConstants.RUNTIME),
          constructInvocation(program.getSourceInfo(), RuntimeConstants.RUNTIME_BOOTSTRAP)
              .makeStmt());

      Set<JDeclaredType> alreadyProcessed =
          Sets.<JDeclaredType>newLinkedHashSet(program.immortalCodeGenTypes);
      alreadyProcessed.add(program.getTypeClassLiteralHolder());
      alreadyRan.addAll(alreadyProcessed);

      List<JDeclaredType> classLiteralSupportClasses =
          computeClassLiteralsSupportClasses(program, alreadyProcessed);

      // Make sure immortal classes are not doubly processed.
      classLiteralSupportClasses.removeAll(alreadyProcessed);
      for (JDeclaredType type : classLiteralSupportClasses) {
        transform(type);
      }
      generateClassLiterals(classLiteralSupportClasses);
      installClassLiterals(classLiteralSupportClasses);

      Set<JDeclaredType> preambleTypes = Sets.newLinkedHashSet(alreadyProcessed);
      preambleTypes.addAll(classLiteralSupportClasses);
      return preambleTypes;
    }

    private JsNameRef transformIntoLabelReference(SourceInfo info, JLabel label) {
      if (label == null) {
        return null;
      }

      return  ((JsLabel) transform(label)).getName().makeRef(info);
    }

    private void installClassLiterals(List<JDeclaredType> classLiteralTypesToInstall) {
      if (!closureCompilerFormatEnabled) {
        // let createForClass() install them until a follow on CL
        // TODO(cromwellian) remove after approval from rluble in follow up CL
        return;
      }

      for (JDeclaredType type : classLiteralTypesToInstall) {
        if (shouldNotEmitTypeDefinition(type)) {
          continue;
        }

        JsNameRef classLiteralRef = createClassLiteralReference(type);
        if (classLiteralRef == null) {
          continue;
        }

        SourceInfo sourceInfo = type.getSourceInfo();
        JsExpression protoRef = getPrototypeQualifierOf(type, sourceInfo);
        JsNameRef clazzField =
            getIndexedFieldJsName(RuntimeConstants.OBJECT_CLAZZ).makeRef(sourceInfo);
        clazzField.setQualifier(protoRef);
        JsExprStmt stmt = createAssignment(clazzField, classLiteralRef).makeStmt();
        addTypeDefinitionStatement(type, stmt);
      }
    }

    private boolean shouldNotEmitTypeDefinition(JDeclaredType type) {
      // Interfaces, Unboxed Types, JSOs, Native Types, JsFunction, and uninstantiated types
      // Do not have vtables/prototype setup
      return type instanceof JInterfaceType && !closureCompilerFormatEnabled
          || program.isRepresentedAsNativeJsPrimitive(type)
          || !program.typeOracle.isInstantiatedType(type)
          || type.isJsoType()
          || type.isJsNative()
          || type.isJsFunction();
    }

    private List<JDeclaredType> computeClassLiteralsSupportClasses(JProgram program,
        Set<JDeclaredType> alreadyProcessedTypes) {
      if (program.isReferenceOnly(program.getIndexedType("Class"))) {
        return Collections.emptyList();
      }
      // Include in the preamble all classes that are reachable for Class.createForClass,
      // Class.createForInterface
      SortedSet<JDeclaredType> reachableClasses =
          computeReachableTypes(METHODS_PROVIDED_BY_PREAMBLE);

      assert !incremental || checkCoreModulePreambleComplete(program,
          program.getTypeClassLiteralHolder().getClinitMethod());

      Set<JDeclaredType> orderedPreambleClasses = Sets.newLinkedHashSet();
      for (JDeclaredType type : reachableClasses) {
        if (alreadyProcessedTypes.contains(type)) {
          continue;
        }
        insertInTopologicalOrder(type, orderedPreambleClasses);
      }

      // TODO(rluble): The set of preamble types might be overly large, in particular will include
      // JSOs that need clinit. This is due to {@link ControlFlowAnalyzer} making all JSOs live if
      // there is a cast to that type anywhere in the program. See the use of
      // {@link JTypeOracle.getInstantiatedJsoTypesViaCast} in the constructor.
      return Lists.newArrayList(orderedPreambleClasses);
    }

    /**
     * Check that in modular compiles the preamble is complete.
     * <p>
     * In modular compiles the preamble has to include code for creating all 4 types of class
     * literals.
     */
    private boolean checkCoreModulePreambleComplete(JProgram program,
        JMethod classLiteralInitMethod) {
      final Set<JMethod> calledMethods = Sets.newHashSet();
      new JVisitor() {
        @Override
        public void endVisit(JMethodCall x, Context ctx) {
          calledMethods.add(x.getTarget());
        }
      }.accept(classLiteralInitMethod);

      for (String createForMethodName : METHODS_PROVIDED_BY_PREAMBLE) {
        if (!calledMethods.contains(program.getIndexedMethod(createForMethodName))) {
          return false;
        }
      }
      return true;
    }

    /**
     * Computes the set of types whose methods or fields are reachable from {@code methods}.
     */
    private SortedSet<JDeclaredType> computeReachableTypes(Iterable<String> methodNames) {
      ControlFlowAnalyzer cfa = new ControlFlowAnalyzer(program);
      for (String methodName : methodNames) {
        JMethod method = program.getIndexedMethodOrNull(methodName);
        // Only traverse it if it has not been pruned.
        if (method != null) {
          cfa.traverseFrom(method);
        }
      }

      // Get the list of enclosing classes that were not excluded.
      SortedSet<JDeclaredType> reachableTypes =
          ImmutableSortedSet.copyOf(HasName.BY_NAME_COMPARATOR,
              Iterables.filter(
                  Iterables.transform(cfa.getLiveFieldsAndMethods(),
                      new Function<JNode, JDeclaredType>() {
                        @Override
                        public JDeclaredType apply(JNode member) {
                          if (member instanceof JMethod) {
                            return ((JMethod) member).getEnclosingType();
                          } else if (member instanceof JField) {
                            return ((JField) member).getEnclosingType();
                          } else {
                            assert member instanceof JParameter || member instanceof JLocal;
                            // Discard locals and parameters, only need the enclosing instances of reachable
                            // fields and methods.
                            return null;
                          }
                        }
                      }), Predicates.notNull()));
      return reachableTypes;
    }

    private JsExpression generateAbstractMethodDefinition(JMethod method) {
      return (closureCompilerFormatEnabled) ?
          JsUtils.createQualifiedNameRef(GOOG_ABSTRACT_METHOD, method.getSourceInfo()) : null;
    }

    private void generateEpilogue() {
      generateRemainingClassLiterals();

      // add all @JsExport assignments
      generateExports();

      // Generate entry methods. Needs to be after class literal insertion since class literal will
      // be referenced by runtime rebind and property provider bootstrapping.
      setupGwtOnLoad();

      embedBindingProperties();
    }

    private void generateRemainingClassLiterals() {
      if (!incremental) {
        // Emit classliterals that are references but whose classes are not live.
        generateClassLiterals(Iterables.filter(classLiteralDeclarationsByType.keySet(),
            Predicates.not(Predicates.<JType>in(alreadyRan))));
        return;
      }

      // In incremental, class literal references to class literals that were not generated
      // as part of the current compile have to be from reference only classes.
      assert FluentIterable.from(classLiteralDeclarationsByType.keySet())
          .filter(Predicates.instanceOf(JDeclaredType.class))
          .filter(Predicates.not(Predicates.<JType>in(alreadyRan)))
          .filter(
              new Predicate<JType>() {
                @Override
                public boolean apply(JType type) {
                  return !program.isReferenceOnly((JDeclaredType) type);
                }
              })
          .isEmpty();

      // In incremental only the class literals for the primitive types should be part of the
      // epilogue.
      generateClassLiterals(JPrimitiveType.types);
    }

    private void generateClassLiterals(Iterable<? extends JType> orderedTypes) {
      for (JType type : orderedTypes) {
        maybeGenerateClassLiteral(type);
      }
    }

    private void generateExports() {
      Map<String, Object> exportedMembersByExportName = new TreeMap<String, Object>();
      Set<JDeclaredType> hoistedClinits = Sets.newHashSet();
      JsInteropExportsGenerator exportGenerator =
          closureCompilerFormatEnabled
              ? new ClosureJsInteropExportsGenerator(getGlobalStatements(), names)
              : new DefaultJsInteropExportsGenerator(getGlobalStatements(), globalTemp,
                  getIndexedMethodJsName(RuntimeConstants.RUNTIME_PROVIDE));

      // Gather exported things in JsNamespace order.
      for (JDeclaredType type : program.getDeclaredTypes()) {
        if (type.isJsNative()) {
          // JsNative types have no implementation and so shouldn't export anything.
          continue;
        }

        if (type.isJsType()) {
          exportedMembersByExportName.put(type.getQualifiedJsName(), type);
        }

        for (JMember member : type.getMembers()) {
          if (member.isJsInteropEntryPoint()) {
            if (member.getJsMemberType() == JsMemberType.PROPERTY && !member.isFinal()) {
              // TODO(goktug): Remove the warning when we export via Object.defineProperty
              logger.log(
                  TreeLogger.Type.WARN,
                  "Exporting effectively non-final field "
                      + member.getQualifiedName()
                      + ". Due to the way exporting works, the value of the"
                      + " exported field will not be reflected across Java/JavaScript border.");
            }
            exportedMembersByExportName.put(member.getQualifiedJsName(), member);
          }
        }
      }

      // Output the exports.
      for (Object exportedEntity : exportedMembersByExportName.values()) {
        if (exportedEntity instanceof JDeclaredType) {
          exportGenerator.exportType((JDeclaredType) exportedEntity);
        } else {
          JMember member = (JMember) exportedEntity;
          maybeHoistClinit(hoistedClinits, member);
          exportGenerator.exportMember(member, names.get(member).makeRef(member.getSourceInfo()));
        }
      }
    }

    private void maybeHoistClinit(Set<JDeclaredType> hoistedClinits, JMember member) {
      JDeclaredType enclosingType = member.getEnclosingType();
      if (hoistedClinits.contains(enclosingType)) {
        return;
      }

      JsInvocation clinitCall = member instanceof JMethod ? maybeCreateClinitCall((JMethod) member)
          : maybeCreateClinitCall((JField) member);
      if (clinitCall != null) {
        hoistedClinits.add(enclosingType);
        getGlobalStatements().add(clinitCall.makeStmt());
      }
    }

    @Override
    public JsFunction transformJsniMethodBody(JsniMethodBody jsniMethodBody) {
      final Map<String, JNode> nodeByJsniReference = Maps.newHashMap();
      for (JsniClassLiteral ref : jsniMethodBody.getClassRefs()) {
        nodeByJsniReference.put(ref.getIdent(), ref.getField());
      }
      for (JsniFieldRef ref : jsniMethodBody.getJsniFieldRefs()) {
        nodeByJsniReference.put(ref.getIdent(), ref.getField());
      }
      for (JsniMethodRef ref : jsniMethodBody.getJsniMethodRefs()) {
        nodeByJsniReference.put(ref.getIdent(), ref.getTarget());
      }

      final JsFunction function = jsniMethodBody.getFunc();

      // replace all JSNI idents with a real JsName now that we know it
      new JsModVisitor() {

        /**
         * Marks a ctor that is a direct child of an invocation. Instead of
         * replacing the ctor with a tear-off, we replace the invocation with a
         * new operation.
         */
        private JsNameRef dontReplaceCtor;

        @Override
        public void endVisit(JsInvocation x, JsContext ctx) {
          // TODO(rluble): this fixup should be done during the initial JSNI processing in
          // GwtAstBuilder.JsniReferenceCollector.
          if (!(x.getQualifier() instanceof JsNameRef)) {
            // If the invocation does not have a name as a qualifier (it might be an expression).
            return;
          }
          JsNameRef ref = (JsNameRef) x.getQualifier();
          if (!ref.isJsniReference()) {
            // The invocation is not to a JSNI method.
            return;
          }
          // Only constructors reach this point, all other JSNI references in the method body
          // would have already been replaced at endVisit(JsNameRef).

          // Replace invocation to ctor with a new op.
          String ident = ref.getIdent();
          JNode node = nodeByJsniReference.get(ident);
          assert node instanceof JConstructor;
          assert ref.getQualifier() == null;
          JsName jsName = names.get(node);
          assert (jsName != null);
          ref.resolve(jsName);
          JsNew jsNew = new JsNew(x.getSourceInfo(), ref);
          jsNew.getArguments().addAll(x.getArguments());
          ctx.replaceMe(jsNew);
        }

        @Override
        public void endVisit(JsNameRef x, JsContext ctx) {
          if (!x.isJsniReference()) {
            return;
          }

          String ident = x.getIdent();
          JNode node = nodeByJsniReference.get(ident);
          assert (node != null);
          if (node instanceof JField) {
            JField field = (JField) node;
            JsName jsName = names.get(field);
            assert (jsName != null);
            x.resolve(jsName);

            // See if we need to add a clinit call to a static field ref
            JsInvocation clinitCall = maybeCreateClinitCall(field);
            if (clinitCall != null) {
              JsExpression commaExpr = JsUtils.createCommaExpression(clinitCall, x);
              ctx.replaceMe(commaExpr);
            }
          } else if (node instanceof JConstructor) {
            if (x == dontReplaceCtor) {
              // Do nothing, parent will handle.
            } else {
              // Replace with a local closure function.
              // function(a,b,c){return new Obj(a,b,c);}
              JConstructor ctor = (JConstructor) node;
              JsName jsName = names.get(ctor);
              assert (jsName != null);
              x.resolve(jsName);
              SourceInfo info = x.getSourceInfo();
              JsFunction closureFunc = new JsFunction(info, function.getScope());
              for (JParameter p : ctor.getParams()) {
                JsName name = closureFunc.getScope().declareName(p.getName());
                closureFunc.getParameters().add(new JsParameter(info, name));
              }
              JsNew jsNew = new JsNew(info, x);
              for (JsParameter p : closureFunc.getParameters()) {
                jsNew.getArguments().add(p.getName().makeRef(info));
              }
              JsBlock block = new JsBlock(info);
              block.getStatements().add(new JsReturn(info, jsNew));
              closureFunc.setBody(block);
              ctx.replaceMe(closureFunc);
            }
          } else {
            JMethod method = (JMethod) node;
            if (x.getQualifier() == null) {
              JsName jsName = names.get(method);
              assert (jsName != null);
              x.resolve(jsName);
            } else {
              JsName jsName = polymorphicNames.get(method);
              if (jsName == null) {
                // this can occur when JSNI references an instance method on a
                // type that was never actually instantiated.
                jsName = getIndexedMethodJsName(RuntimeConstants.RUNTIME_EMPTY_METHOD);
              }
              x.resolve(jsName);
            }
          }
        }

        @Override
        public boolean visit(JsInvocation x, JsContext ctx) {
          if (x.getQualifier() instanceof JsNameRef) {
            dontReplaceCtor = (JsNameRef) x.getQualifier();
          }
          return true;
        }
      }.accept(function);

      return function;
    }

    @Override
    public JsStatement transformSwitchStatement(JSwitchStatement switchStatement) {
      /*
       * What a pain.. JSwitchStatement and JsSwitch are modeled completely
       * differently. Here we try to resolve those differences.
       */
      JsSwitch jsSwitch = new JsSwitch(switchStatement.getSourceInfo());
      jsSwitch.setExpr(transform(switchStatement.getExpr()));

      List<JStatement> bodyStmts = switchStatement.getBody().getStatements();
      List<JsStatement> curStatements = null;
      for (JStatement stmt : bodyStmts) {
        if (stmt instanceof JCaseStatement) {
          // create a new switch member
          JsSwitchMember switchMember = transform((JNode) stmt);
          jsSwitch.getCases().add(switchMember);
          curStatements = switchMember.getStmts();
        } else {
          // add to statements for current case
          assert (curStatements != null);
          JsStatement newStmt = transform(stmt);
          if (newStmt != null) {
            // Empty JDeclarationStatement produces a null
            curStatements.add(newStmt);
          }
        }
      }

      return jsSwitch;
    }

    private JsExpression buildJsCastMapLiteral(List<JsExpression> runtimeTypeIdLiterals,
        SourceInfo sourceInfo) {
      if (JjsUtils.closureStyleLiteralsNeeded(incremental, closureCompilerFormatEnabled)) {
        return buildClosureStyleCastMapFromArrayLiteral(runtimeTypeIdLiterals, sourceInfo);
      }

      JsNumberLiteral one = new JsNumberLiteral(sourceInfo, 1);
      JsObjectLiteral.Builder objectLiteralBuilder = JsObjectLiteral.builder(sourceInfo)
          .setInternable();
      for (JsExpression runtimeTypeIdLiteral : runtimeTypeIdLiterals) {
        objectLiteralBuilder.add(runtimeTypeIdLiteral, one);
      }
      return objectLiteralBuilder.build();
    }

    private JsExpression buildClosureStyleCastMapFromArrayLiteral(
        List<JsExpression> runtimeTypeIdLiterals, SourceInfo sourceInfo) {
      /*
       * goog.object.createSet('foo', 'bar', 'baz') is optimized by closure compiler into
       * {'foo': !0, 'bar': !0, baz: !0}
       */
      JsNameRef createSet = new JsNameRef(sourceInfo, GOOG_OBJECT_CREATE_SET);
      JsInvocation jsInvocation = new JsInvocation(sourceInfo, createSet);

      for (JsExpression expr : runtimeTypeIdLiterals) {
        jsInvocation.getArguments().add(expr);
      }

      return jsInvocation;
    }

    private void checkForDuplicateMethods(JDeclaredType type) {
      // Sanity check to see that all methods are uniquely named.
      List<JMethod> methods = type.getMethods();
      Set<String> methodSignatures = Sets.newHashSet();
      for (JMethod method : methods) {
        String sig = method.getSignature();
        if (methodSignatures.contains(sig)) {
          throw new InternalCompilerException("Signature collision in Type " + type.getName()
              + " for method " + sig);
        }
        methodSignatures.add(sig);
      }
    }

    private JsNameRef createStaticReference(JMember member, SourceInfo sourceInfo) {
      assert member.isStatic();
      return member.isJsNative()
          ? createGlobalQualifier(member.getQualifiedJsName(), sourceInfo)
          : names.get(member).makeRef(sourceInfo);
    }

    private void emitFields(JDeclaredType type) {
      JsVars vars = new JsVars(type.getSourceInfo());
      for (JField field : type.getFields()) {
        if (field.isJsNative()) {
          // Nothing to output for native fields.
          continue;
        }
        JsExpression initializer = null;
        // if we need an initial value, create an assignment
        if (initializeAtTopScope(field)) {
          // setup the constant value
          initializer = transform(field.getLiteralInitializer());
        } else if (field.getType().getDefaultValue() == JNullLiteral.INSTANCE) {
          // Fields whose default value is null are left uninitialized and will
          // have a JS value of undefined.
        } else {
          // setup the default value, see Issue 380
          initializer = transform(field.getType().getDefaultValue());
        }

        JsName name = names.get(field);

        if (field.isStatic()) {
          // setup a var for the static
          JsVar var = new JsVar(type.getSourceInfo(), name);
          var.setInitExpr(initializer);
          vars.add(var);
        } else if (initializer != null) {
          // Instance field initilized at top.
          JsNameRef fieldRef =
              name.makeQualifiedRef(field.getSourceInfo(), getPrototypeQualifierOf(field));
          addTypeDefinitionStatement(type, createAssignment(fieldRef, initializer).makeStmt());
        }
      }
      addVarsIfNotEmpty(vars);
    }

    private void emitStaticMethods(JDeclaredType type) {
      // declare all methods into the global scope
      for (JMethod method : type.getMethods()) {
        if (method.needsDynamicDispatch()) {
          continue;
        }

        JsFunction function = transform(method);
        if (function == null) {
          continue;
        }

        if (JProgram.isClinit(method)) {
          handleClinit(type, function);
        }

        emitMethodImplementation(method,
            function.getName().makeRef(function.getSourceInfo()), function.makeStmt());
      }
    }

    private JsExpression generateCastableTypeMap(JDeclaredType type) {
      JCastMap castMap = program.getCastMap(type);
      JsName castableTypeMapName = getIndexedFieldJsName(RuntimeConstants.OBJECT_CASTABLE_TYPE_MAP);

      if (castMap != null && castableTypeMapName != null) {
        return transform(castMap);
      }
      return JsObjectLiteral.EMPTY;
    }

    private JField getClassLiteralField(JType type) {
      JDeclarationStatement decl = classLiteralDeclarationsByType.get(type);
      if (decl == null) {
        return null;
      }

      return (JField) decl.getVariableRef().getTarget();
    }

    private void maybeGenerateClassLiteral(JType type) {

      JField field = getClassLiteralField(type);
      if (field == null) {
        return;
      }

      // TODO(rluble): refactor so that all output related to a class is decided together.
      if (type != null && type instanceof JDeclaredType
          && program.isReferenceOnly((JDeclaredType) type)) {
        // Only generate class literals for classes in the current module.
        // TODO(rluble): In separate compilation some class literals will be duplicated, which if
        // not done with care might violate java semantics of getClass(). There are class literals
        // for primitives and arrays. Currently, because they will be assigned to the same field
        // the one defined later will be the one used and Java semantics are preserved.
        return;
      }

      JsVars vars = new JsVars(jsProgram.getSourceInfo());
      JsName jsName = names.get(field);
      JsExpression classLiteralObject = transform(field.getInitializer());
      JsVar var = new JsVar(field.getSourceInfo(), jsName);
      var.setInitExpr(classLiteralObject);
      vars.add(var);
      addVarsIfNotEmpty(vars);
    }

    private JsNameRef createClassLiteralReference(JType type) {
      JField field = getClassLiteralField(type);
      if (field == null) {
        return null;
      }
      JsName jsName = names.get(field);
      return jsName.makeRef(type.getSourceInfo());
    }

    private void generateTypeSetup(JDeclaredType type) {
      if (program.isRepresentedAsNativeJsPrimitive(type)
          && program.typeOracle.isInstantiatedType(type)) {
        setupCastMapForUnboxedType(type,
            program.getRepresentedAsNativeTypesDispatchMap().get(type).getCastMapField());
        return;
      }

      if (shouldNotEmitTypeDefinition(type)) {
        return;
      }

      generateClassDefinition(type);
      generatePrototypeDefinitions(type);

      maybeGenerateObjectMethodsAliases(type);
    }

    private void markPosition(String name, Type type) {
      getGlobalStatements().add(new JsPositionMarker(SourceOrigin.UNKNOWN, name, type));
    }

    /**
     * Sets up gwtOnLoad bootstrapping code. Unusually, the created code is executed as part of
     * source loading and runs in the global scope (not inside of any function scope).
     */
    private void setupGwtOnLoad() {
      /**
       * <pre>
       * var $entry = Impl.registerEntry();
       * var gwtOnLoad = ModuleUtils.gwtOnLoad();
       * ModuleUtils.addInitFunctions(init1, init2,...)
       * </pre>
       */

      final SourceInfo sourceInfo = SourceOrigin.UNKNOWN;

      // var $entry = ModuleUtils.registerEntry();
      JsStatement entryVars = constructFunctionCallStatement(
          topScope.declareName("$entry"), "ModuleUtils.registerEntry");
      getGlobalStatements().add(entryVars);

      // var gwtOnLoad = ModuleUtils.gwtOnLoad;
      JsName gwtOnLoad = topScope.findExistingUnobfuscatableName("gwtOnLoad");
      JsVar varGwtOnLoad = new JsVar(sourceInfo, gwtOnLoad);
      varGwtOnLoad.setInitExpr(createAssignment(gwtOnLoad.makeRef(sourceInfo),
          getIndexedMethodJsName(RuntimeConstants.MODULE_UTILS_GWT_ON_LOAD).makeRef(sourceInfo)));
      getGlobalStatements().add(new JsVars(sourceInfo, varGwtOnLoad));

      // ModuleUtils.addInitFunctions(init1, init2,...)
      List<JsExpression> arguments = Lists.newArrayList();
      for (JMethod entryPointMethod : program.getEntryMethods()) {
        JsFunction entryFunction = getJsFunctionFor(entryPointMethod);
        arguments.add(entryFunction.getName().makeRef(sourceInfo));
      }

      JsStatement createGwtOnLoadFunctionCall =
          constructInvocation("ModuleUtils.addInitFunctions", arguments).makeStmt();

      getGlobalStatements().add(createGwtOnLoadFunctionCall);
    }

    /**
     * Creates a (var) assignment a statement for a function call to an indexed function.
     */
    private JsStatement constructFunctionCallStatement(JsName assignToVariableName,
        String indexedFunctionName, JsExpression... args) {
      return constructFunctionCallStatement(assignToVariableName, indexedFunctionName,
          Arrays.asList(args));
    }

    /**
     * Creates a (var) assignment a statement for a function call to an indexed function.
     */
    private JsStatement constructFunctionCallStatement(JsName assignToVariableName,
        String indexedFunctionName, List<JsExpression> args) {

      SourceInfo sourceInfo = SourceOrigin.UNKNOWN;
      JsInvocation invocation = constructInvocation(indexedFunctionName, args);
      JsVar var = new JsVar(sourceInfo, assignToVariableName);
      var.setInitExpr(invocation);
      JsVars entryVars = new JsVars(sourceInfo);
      entryVars.add(var);
      return entryVars;
    }

    /**
     * Constructs an invocation for an indexed function.
     */
    private JsInvocation constructInvocation(SourceInfo sourceInfo,
        String indexedFunctionName, JsExpression... args) {
      return constructInvocation(sourceInfo, indexedFunctionName, Arrays.asList(args));
    }

    /**
     * Constructs an invocation for an indexed function.
     */
    private JsInvocation constructInvocation(String indexedFunctionName,
        List<JsExpression> args) {
      SourceInfo sourceInfo = SourceOrigin.UNKNOWN;
      return constructInvocation(sourceInfo, indexedFunctionName, args);
    }

    /**
     * Constructs an invocation for an indexed function.
     */
    private JsInvocation constructInvocation(SourceInfo sourceInfo,
        String indexedFunctionName, List<JsExpression> args) {
      JsName functionToInvoke = getIndexedMethodJsName(indexedFunctionName);
      return new JsInvocation(sourceInfo, functionToInvoke.makeRef(sourceInfo), args);
    }

    private void generateImmortalTypes(JsVars globals) {
      List<JClassType> immortalTypesReversed = Lists.reverse(program.immortalCodeGenTypes);
      // visit in reverse order since insertions start at head
      for (JClassType x : immortalTypesReversed) {
        // Don't generate JS for referenceOnly types.
        if (program.isReferenceOnly(x)) {
          continue;
        }
        // should not be pruned
        assert x.getMethods().size() > 0;
        // insert all static methods
        for (JMethod method : x.getMethods()) {
          /*
           * Skip virtual methods and constructors. Even in cases where there is no constructor
           * defined, the compiler will synthesize a default constructor which invokes
           * a synthesized $init() method. We must skip both of these inserted methods.
           */
          if (method.needsDynamicDispatch() || method instanceof JConstructor
              || doesNotHaveConcreteImplementation(method)) {
            continue;
          }
          // add after var declaration, but before everything else
          JsFunction function = transform(method);
          assert function.getName() != null;
          addMethodDefinitionStatement(1, method, function.makeStmt());
        }

        // insert fields into global var declaration
        for (JField field : x.getFields()) {
          assert field.isStatic() : "'" + field.getName()
              + "' is not static. Only static fields are allowed on immortal types";
          assert field.getInitializer() == field.getLiteralInitializer() : "'" + field.getName()
              + "' is not initilialized to a literal."
              + " Only literal initializers are allowed on immortal types";

          JsVar var = new JsVar(x.getSourceInfo(), names.get(field));
          var.setInitExpr(transform(field.getLiteralInitializer()));
          globals.add(var);
        }
      }
    }

    private void generateCallToDefineClass(JClassType type, List<JsNameRef> constructorArgs) {
      JClassType superClass = type.getSuperClass();
      JExpression superTypeId = (superClass == null) ? JNullLiteral.INSTANCE :
          getRuntimeTypeReference(superClass);
      String jsPrototype = getSuperPrototype(type);

      List<JsExpression> defineClassArguments = Lists.newArrayList();

      defineClassArguments.add(transform(getRuntimeTypeReference(type)));
      defineClassArguments.add(jsPrototype == null ? transform(superTypeId) :
          createGlobalQualifier(jsPrototype, type.getSourceInfo()));
      defineClassArguments.add(generateCastableTypeMap(type));
      defineClassArguments.addAll(constructorArgs);

      // Runtime.defineClass(typeId, superTypeId, castableMap, constructors)
      JsStatement defineClassStatement = constructInvocation(type.getSourceInfo(),
          RuntimeConstants.RUNTIME_DEFINE_CLASS, defineClassArguments).makeStmt();
      addTypeDefinitionStatement(type, defineClassStatement);

      maybeCopyJavaLangObjectProperties(
          type,
          getPrototypeQualifierViaLookup(program.getTypeJavaLangObject(), type.getSourceInfo()),
          globalTemp.makeRef(type.getSourceInfo()));
    }

    private void maybeCopyJavaLangObjectProperties(
        JDeclaredType type, JsExpression javaLangObjectPrototype, JsExpression toPrototype) {
      if (getSuperPrototype(type) != null && !type.isJsFunctionImplementation()) {
        JsStatement statement =
            constructInvocation(
                type.getSourceInfo(),
                RuntimeConstants.RUNTIME_COPY_OBJECT_PROPERTIES,
                javaLangObjectPrototype,
                toPrototype
            ).makeStmt();
        addTypeDefinitionStatement(type, statement);
      }
    }

    private String getSuperPrototype(JDeclaredType type) {
      if (type.isJsFunctionImplementation()) {
        return "Function";
      }
      JClassType superClass = type.getSuperClass();
      if (superClass != null && superClass.isJsNative()) {
        return superClass.getQualifiedJsName();
      }
      return null;
    }

    private void generateClassDefinition(JDeclaredType type) {
      assert !program.isRepresentedAsNativeJsPrimitive(type);

      if (closureCompilerFormatEnabled) {
        generateClosureTypeDefinition(type);
      } else {
        generateJsClassDefinition((JClassType) type);
      }
    }

    /*
     * Class definition for regular output looks like:
     *
     * defineClass(id, superId, castableTypeMap, ctor1, ctor2, ctor3);
     * _.method1 = function() { ... }
     * _.method2 = function() { ... }
     */
    private void generateJsClassDefinition(JClassType classType) {
      // Add constructors as varargs to define class.
      List<JsNameRef> constructorArgs = Lists.newArrayList();
      for (JMethod method : getPotentiallyAliveConstructors(classType)) {
        constructorArgs.add(names.get(method).makeRef(classType.getSourceInfo()));
      }

      // defineClass(..., Ctor1, Ctor2, ...)
      generateCallToDefineClass(classType, constructorArgs);
    }

    /*
     * Class definition for closure output looks like:
     *
     * function ClassName() {}
     * ClassName.prototype.method1 = function() { ... };
     * ClassName.prototype.method2 = function() { ... };
     * ClassName.prototype.castableTypeMap = {...}
     * ClassName.prototype.___clazz = classLit;
     * function Ctor1() {}
     * function Ctor2() {}
     *
     * goog$inherits(Ctor1, ClassName);
     * goog$inherits(Ctor2, ClassName);
     *
     * The primary change is to make the prototype assignment look like regular closure code to help
     * the compiler disambiguate which methods belong to which type. Elimination of defineClass()
     * makes the setup more transparent and eliminates a global table holding a reference to
     * every prototype.
     */
    private void generateClosureTypeDefinition(JDeclaredType type) {
      // function ClassName(){}
      JsName classVar = declareSynthesizedClosureConstructor(type);
      generateInlinedDefineClass(type, classVar);

       /*
       * Closure style prefers 1 single ctor per type. To model this without radical changes,
       * we simply model each concrete ctor as a subtype. This works because GWT doesn't use the
       * native instanceof operator. So for example, class A() { A(int type){}, A(String s){} }
       * becomes (pseudo code):
       *
       * function A() {}
       * A.prototype.method = ...
       *
       * function A_int(x) {}
       * function A_String(s) {}
       * goog$inherits(A_int, A);
       * goog$inherits(A_string, A);
       *
       */
      for (JMethod method : getPotentiallyAliveConstructors(type)) {
        SourceInfo typeSourceInfo = type.getSourceInfo();
        JsNameRef googInherits = JsUtils.createQualifiedNameRef(GOOG_INHERITS, typeSourceInfo);

        SourceInfo methodSourceInfo = method.getSourceInfo();
        JsExprStmt callGoogInherits = new JsInvocation(typeSourceInfo, googInherits,
            names.get(method).makeRef(methodSourceInfo),
            names.get(method.getEnclosingType()).makeRef(methodSourceInfo)).makeStmt();
        addMethodDefinitionStatement(method, callGoogInherits);
      }
    }

    /**
     * Does everything JCHSU.defineClass does, but inlined into global statements. Roughly
     * parallels argument order of generateCallToDefineClass.
     */
    private void generateInlinedDefineClass(JDeclaredType type, JsName classVar) {
      if (type instanceof JInterfaceType) {
        return;
      }
      JClassType superClass = type.getSuperClass();
      // check if there's an overriding prototype
      String jsPrototype = getSuperPrototype(type);
      SourceInfo info = type.getSourceInfo();
      JsNameRef parentCtor = jsPrototype != null ?
          createGlobalQualifier(jsPrototype, info) :
            superClass != null ?
              names.get(superClass).makeRef(info) :
              null;

      if (parentCtor != null) {
        JsNameRef googInherits = JsUtils.createQualifiedNameRef(GOOG_INHERITS, info);
        // Use goog$inherits(ChildCtor, ParentCtor) to setup inheritance
        JsExprStmt callGoogInherits = new JsInvocation(info, googInherits,
            classVar.makeRef(info), parentCtor).makeStmt();
        addTypeDefinitionStatement(type, callGoogInherits);
      }

      if (type == program.getTypeJavaLangObject()) {
        setupTypeMarkerOnJavaLangObjectPrototype(type);
      }

      // inline assignment of castableTypeMap field instead of using defineClass()
      setupCastMapOnPrototype(type);
      maybeCopyJavaLangObjectProperties(
          type,
          getPrototypeQualifierOf(program.getTypeJavaLangObject(), info),
          getPrototypeQualifierOf(type, info));
    }

    private void setupCastMapOnPrototype(JDeclaredType type) {
      JsExpression castMap = generateCastableTypeMap(type);
      generatePrototypeAssignmentForJavaField(type, "Object.castableTypeMap", castMap);
    }

    private void setupTypeMarkerOnJavaLangObjectPrototype(JDeclaredType type) {
      JsName typeMarkerMethod = getIndexedMethodJsName(RuntimeConstants.RUNTIME_TYPE_MARKER_FN);
      generatePrototypeAssignmentForJavaField(type, RuntimeConstants.OBJECT_TYPEMARKER,
          typeMarkerMethod.makeRef(type.getSourceInfo()));
    }

    private void generatePrototypeAssignmentForJavaField(JDeclaredType type, String javaField,
        JsExpression rhs) {
      SourceInfo sourceInfo = type.getSourceInfo();
      JsNameRef protoRef = getPrototypeQualifierOf(type, sourceInfo);
      JsNameRef fieldRef = getIndexedFieldJsName(javaField).makeQualifiedRef(sourceInfo, protoRef);
      addTypeDefinitionStatement(type, createAssignment(fieldRef, rhs).makeStmt());
    }

    private void addMethodDefinitionStatement(JMethod method,
        JsExprStmt methodDefinitionStatement) {
      getGlobalStatements().add(methodDefinitionStatement);
      methodByGlobalStatement.put(methodDefinitionStatement, method);
    }

    private void addMethodDefinitionStatement(int position, JMethod method,
        JsExprStmt methodDefinitionStatement) {
      getGlobalStatements().add(position, methodDefinitionStatement);
      methodByGlobalStatement.put(methodDefinitionStatement, method);
    }

    private void addTypeDefinitionStatement(JDeclaredType x, JsStatement statement) {
      getGlobalStatements().add(statement);
      javaTypeByGlobalStatement.put(statement, x);
    }

    /*
     * Declare an empty synthesized constructor that looks like:
     * function ClassName(){}
     *
     * Closure Compiler's RewriteFunctionExpressions pass can be enabled to turn these back
     * into a factory method after optimizations.
     *
     * TODO(goktug): throw Error in the body to prevent instantiation via this constructor.
     */
    private JsName declareSynthesizedClosureConstructor(JDeclaredType x) {
      SourceInfo sourceInfo = x.getSourceInfo();
      JsName classVar = topScope.declareName(JjsUtils.mangledNameString(x));
      JsFunction closureCtor = JsUtils.createEmptyFunctionLiteral(sourceInfo, topScope, classVar);
      JsExprStmt statement = closureCtor.makeStmt();
      // This synthetic statement must be in the initial fragment, do not add to typeDefinitions
      getGlobalStatements().add(statement);
      names.put(x, classVar);
      return classVar;
    }

    /*
     * Sets up the castmap for type X
     */
    private void setupCastMapForUnboxedType(JDeclaredType type, String castMapField) {
      //  Cast.[castMapName] = /* cast map */ { ..:1, ..:1}
      JsName castableTypeMapName = getIndexedFieldJsName(castMapField);
      JsNameRef castMapVarRef = castableTypeMapName.makeRef(type.getSourceInfo());

      JsExpression castMapLiteral = generateCastableTypeMap(type);
      addTypeDefinitionStatement(type, createAssignment(castMapVarRef, castMapLiteral).makeStmt());
    }

    private void maybeGenerateObjectMethodsAliases(JDeclaredType type) {
      if (type == program.getTypeJavaLangObject()) {
        // special: setup a "toString" alias for java.lang.Object.toString()
        Set<JMethod> overridableJavaLangObjectMethods = ImmutableSet.of(
            program.getIndexedMethodOrNull(RuntimeConstants.OBJECT_EQUALS),
            program.getIndexedMethodOrNull(RuntimeConstants.OBJECT_HASHCODE),
            program.getIndexedMethodOrNull(RuntimeConstants.OBJECT_TO_STRING));

        for (JMethod method : type.getMethods()) {
          if (overridableJavaLangObjectMethods.contains(method)) {
            JsName methodJsName = objectScope.declareUnobfuscatableName(method.getName());
            generatePrototypeDefinitionAlias(method, methodJsName);
          }
        }
      }
    }

    private void generatePrototypeAssignment(JMethod method, JsName name, JsExpression rhs) {
      generatePrototypeAssignment(method, name, rhs, method.getJsMemberType());
    }

    /**
     * Create a vtable assignment of the form _.polyname = rhs; and register the line as
     * created for {@code method}.
     */
    private void generatePrototypeAssignment(JMethod method, JsName name, JsExpression rhs,
        JsMemberType memberType) {
      SourceInfo sourceInfo = method.getSourceInfo();
      JsNameRef prototypeQualifierOf = getPrototypeQualifierOf(method);
      JsNameRef lhs = name.makeQualifiedRef(sourceInfo, prototypeQualifierOf);
      switch (memberType) {
        case GETTER:
        case SETTER:
          emitPropertyImplementation(method, prototypeQualifierOf, name.makeRef(sourceInfo), rhs);
          break;
        default:
          emitMethodImplementation(method, lhs, createAssignment(lhs, rhs).makeStmt());
          break;
      }
    }

    private void emitPropertyImplementation(JMethod method, JsNameRef prototype, JsNameRef name,
        JsExpression methodDefinitionStatement) {
      SourceInfo sourceInfo = method.getSourceInfo();

      // We use Object.defineProperties instead of Object.defineProperty to make sure the
      // property name appears as an identifier and not as a string.
      // Some JS optimizers, e.g. the closure compiler, relies on this subtle difference for
      // obfuscating property names.
      JsNameRef definePropertyMethod =
          getIndexedMethodJsName(RuntimeConstants.RUNTIME_DEFINE_PROPERTIES).makeRef(sourceInfo);

      JsObjectLiteral definePropertyLiteral =
          JsObjectLiteral.builder(sourceInfo)
              // {name: {get: function() { ..... }} or {set : function (v) {....}}}
              .add(name, JsObjectLiteral.builder(sourceInfo)
                  // {get: function() { ..... }} or {set : function (v) {....}}
                  .add(method.getJsMemberType().getPropertyAccessorKey(), methodDefinitionStatement)
                  .build())
              .build();

      addMethodDefinitionStatement(method, new JsInvocation(sourceInfo, definePropertyMethod,
          prototype, definePropertyLiteral).makeStmt());
    }

    private void emitMethodImplementation(JMethod method, JsNameRef functionNameRef,
        JsExprStmt methodDefinitionStatement) {
      addMethodDefinitionStatement(method, methodDefinitionStatement);

      if (shouldEmitDisplayNames()) {
        JsExprStmt displayNameAssignment = outputDisplayName(functionNameRef, method);
        addMethodDefinitionStatement(method, displayNameAssignment);
      }
    }

    private void generatePrototypeDefinitionAlias(JMethod method, JsName alias) {
      JsName polyName = polymorphicNames.get(method);
      JsExpression bridge = JsUtils.createBridge(method, polyName, topScope);
      // Aliases are never property accessors.
      generatePrototypeAssignment(method, alias, bridge, JsMemberType.NONE);
    }

    private JsExprStmt outputDisplayName(JsNameRef function, JMethod method) {
      JsNameRef displayName = new JsNameRef(function.getSourceInfo(), "displayName");
      displayName.setQualifier(function);
      String displayStringName = getDisplayName(method);
      JsStringLiteral displayMethodName =
          new JsStringLiteral(function.getSourceInfo(), displayStringName);
      return createAssignment(displayName, displayMethodName).makeStmt();
    }

    private boolean shouldEmitDisplayNames() {
      return methodNameMappingMode != OptionMethodNameDisplayMode.Mode.NONE;
    }

    private String getDisplayName(JMethod method) {
      switch (methodNameMappingMode) {
        case ONLY_METHOD_NAME:
          return method.getName();
        case ABBREVIATED:
          return method.getEnclosingType().getShortName() + "." + method.getName();
        case FULL:
          return method.getEnclosingType().getName() + "." + method.getName();
        default:
          assert false : "Invalid display mode option " + methodNameMappingMode;
      }
      return null;
    }

    /**
     * Creates the assignment for all polynames for a certain class, assumes that the global
     * variable _ points the JavaScript prototype for {@code type}.
     */
    private void generatePrototypeDefinitions(JDeclaredType type) {
      assert !program.isRepresentedAsNativeJsPrimitive(type);

      // Emit synthetic methods first. In JsInterop we allow a more user written method to be named
      // with the same name as a synthetic bridge (required due to generics) relying that the
      // synthetic method is output first into the prototype slot and rewritten in this situation.
      // TODO(rluble): this is a band aid. The user written method (and its overrides) should be
      // automatically JsIgnored. Otherwise some semantics become looser. E.g. the synthetic bridge
      // method may be casting some of the parameters. Such casts are lost in this scheme.
      Iterable<JMethod> orderedInstanceMethods = Iterables.concat(
          Iterables.filter(type.getMethods(),
              Predicates.and(
                  JjsPredicates.IS_SYNTHETIC,
                  JjsPredicates.NEEDS_DYNAMIC_DISPATCH)),
          Iterables.filter(type.getMethods(),
              Predicates.and(
                  Predicates.not(JjsPredicates.IS_SYNTHETIC),
                  JjsPredicates.NEEDS_DYNAMIC_DISPATCH)));

      for (JMethod method : orderedInstanceMethods) {
        generatePrototypeDefinition(method, (JsExpression) transformMethod(method));
      }
    }

    private void generatePrototypeDefinition(JMethod method, JsExpression functionDefinition) {
      if (functionDefinition != null) {
        generatePrototypeAssignment(method, polymorphicNames.get(method), functionDefinition);
      }

      if (method.exposesNonJsMember()) {
        JsName internalMangledName = interfaceScope.declareName(mangleNameForPoly(method),
            method.getName());
        generatePrototypeDefinitionAlias(method, internalMangledName);
      }

      if (method.exposesPackagePrivateMethod()) {
        // Here is the situation where this is needed:
        //
        // class a.A { m() {} }
        // class b.B extends a.A { m() {} }
        // interface I { m(); }
        // class a.C {
        //  { A a = new b.B();  a.m() // calls A::m()} }
        //  { I i = new b.B();  a.m() // calls B::m()} }
        // }
        //
        // Up to this point it is clear that package private names need to be different than
        // public names.
        //
        // Add class a.D extends a.A implements I { public m() }
        //
        // a.D collapses A::m and I::m into the same function and it was clear that two
        // two different names were already needed, hence when creating the vtable for a.D
        // both names have to point to the same function.
        generatePrototypeDefinitionAlias(method, getPackagePrivateName(method));
      }
    }

    /**
     * Returns either _ or ClassCtor.prototype depending on output mode.
     */
    private JsNameRef getPrototypeQualifierOf(JMember member) {
      return getPrototypeQualifierOf(member.getEnclosingType(), member.getSourceInfo());
    }

    /**
     * Returns either _ or ClassCtor.prototype depending on output mode.
     */
    private JsNameRef getPrototypeQualifierOf(JDeclaredType type, SourceInfo info) {
      return closureCompilerFormatEnabled
          ? prototype.makeQualifiedRef(info, names.get(type).makeRef(info))
          : globalTemp.makeRef(info);
    }

    /**
     * Returns the package private JsName for {@code method}.
     */
    private JsName getPackagePrivateName(JMethod method) {
      for (JMethod overridenMethod : method.getOverriddenMethods()) {
        if (overridenMethod.isPackagePrivate()) {
          JsName name = polymorphicNames.get(overridenMethod);
          assert name != null;
          return name;
        }
      }
      throw new AssertionError(
          method.toString() + " overrides a package private method but was not found.");
    }

    private void handleClinit(JDeclaredType type, JsFunction clinitFunction) {
      clinitFunctionForType.put(type, clinitFunction);
      JDeclaredType superClass = type.getSuperClass();
      JsFunction superClinitFunction = superClass == null
          ? null : clinitFunctionForType.get(superClass.getClinitTarget());

      clinitFunction.setSuperClinit(superClinitFunction);
      List<JsStatement> statements = clinitFunction.getBody().getStatements();
      SourceInfo sourceInfo = clinitFunction.getSourceInfo();
      // Self-assign to the global noop method immediately (to prevent reentrancy). In incremental
      // mode the more costly Object constructor function is used as the noop method since doing so
      // provides a better debug experience that does not step into already used clinits.

      JsName emptyFunctionFnName = incremental ? objectConstructorFunction.getName()
          : getIndexedMethodJsName(RuntimeConstants.RUNTIME_EMPTY_METHOD);
      JsExpression assignment = createAssignment(clinitFunction.getName().makeRef(sourceInfo),
          emptyFunctionFnName.makeRef(sourceInfo));
      statements.add(0, assignment.makeStmt());
    }

    private boolean isMethodPotentiallyCalledAcrossClasses(JMethod method) {
      assert incremental || crossClassTargets != null;
      return crossClassTargets == null || crossClassTargets.contains(method)
          || method.isJsInteropEntryPoint();
    }

    private Iterable<JMethod> getPotentiallyAliveConstructors(JDeclaredType x) {
      return Iterables.filter(x.getMethods(), new Predicate<JMethod>() {
        @Override
        public boolean apply(JMethod m) {
          return isMethodPotentiallyALiveConstructor(m);
        }
      });
    }

    /**
     * Whether a method is a constructor that is actually newed. Note that in absence of whole
     * world knowledge evey constructor is potentially live.
     */
    private boolean isMethodPotentiallyALiveConstructor(JMethod method) {
      if (!(method instanceof JConstructor)) {
        return false;
      }
      assert incremental || liveCtors != null;
      return liveCtors == null || liveCtors.contains(method);
    }

    private JsInvocation maybeCreateClinitCall(JField x) {
      if (!x.isStatic() || x.isCompileTimeConstant()) {
        // Access to compile time constants do not trigger class initialization (JLS 12.4.1).
        return null;
      }

      JDeclaredType targetType = x.getEnclosingType().getClinitTarget();
      if (targetType == null
          || targetType == program.getTypeClassLiteralHolder()
          // When  currentMethod == null, the clinit is being hoisted to the global scope.
          || (currentMethod != null
             && !currentMethod.getEnclosingType().checkClinitTo(targetType))) {
        return null;
      }

      JMethod clinitMethod = targetType.getClinitMethod();
      SourceInfo sourceInfo = x.getSourceInfo();
      return new JsInvocation(sourceInfo, names.get(clinitMethod).makeRef(sourceInfo));
    }

    private JsInvocation maybeCreateClinitCall(JMethod method) {
      if (!isMethodPotentiallyCalledAcrossClasses(method)) {
        // Global optimized compile can prune some clinit calls.
        return null;
      }
      JDeclaredType enclosingType = method.getEnclosingType();
      if (method.canBePolymorphic() || (program.isStaticImpl(method) &&
          !method.isJsOverlay())) {
        return null;
      }
      if (enclosingType == null || !enclosingType.hasClinit()) {
        return null;
      }
      // Avoid recursion sickness.
      if (JProgram.isClinit(method)) {
        return null;
      }

      JMethod clinitMethod = enclosingType.getClinitTarget().getClinitMethod();
      SourceInfo sourceInfo = method.getSourceInfo();
      return new JsInvocation(sourceInfo, names.get(clinitMethod).makeRef(sourceInfo));
    }

    /**
     * If a field is a literal, we can potentially treat it as immutable and assign it once on the
     * prototype, to be reused by all instances of the class, instead of re-assigning the same
     * literal in each constructor.
     */
    private boolean initializeAtTopScope(JField x) {
      if (x.getEnclosingType().isJsFunctionImplementation()) {
        // JsFunction implementation are plain JS functions with no class prototype, fields
        // need to be initialized and placed on the instance itself.
        return false;
      }
      if (x.getLiteralInitializer() == null) {
        return false;
      }
      if (x.isFinal() || x.isStatic() || x.isCompileTimeConstant()) {
        // we can definitely initialize at top-scope, as JVM does so as well
        return true;
      }

      return !uninitializedValuePotentiallyObservable.apply(x);
    }

    /**
     * Helpers to avoid casting (can be removed when compiling in Java 8).
     */
    private <T extends JsExpression> T transform(JExpression expression) {
      return transform((JNode) expression);
    }

    private <T extends JsStatement> T transform(JStatement statement) {
      return transform((JNode) statement);
    }

    private JsBlock transform(JBlock statement) {
      return transform((JNode) statement);
    }
  }

  private void addVarsIfNotEmpty(JsVars vars) {
    if (!vars.isEmpty()) {
      getGlobalStatements().add(vars);
    }
  }

  private List<JsStatement> getGlobalStatements() {
    return jsProgram.getGlobalBlock().getStatements();
  }

  /**
   * Return false if the method needs to be generated. Some methods do not need any output,
   * in particular abstract methods and static intializers that are never called.
   */
  private static boolean doesNotHaveConcreteImplementation(JMethod method) {
    return method.isAbstract()
        || method.isJsNative()
        || JjsUtils.isJsMemberUnnecessaryAccidentalOverride(method)
        || (JProgram.isClinit(method)
            && method.getEnclosingType().getClinitTarget() != method.getEnclosingType());
  }

  private static class JavaToJsOperatorMap {
    private static final Map<JBinaryOperator, JsBinaryOperator> bOpMap =
        Maps.newEnumMap(JBinaryOperator.class);
    private static final Map<JUnaryOperator, JsUnaryOperator> uOpMap =
        Maps.newEnumMap(JUnaryOperator.class);

    static {
      bOpMap.put(JBinaryOperator.MUL, JsBinaryOperator.MUL);
      bOpMap.put(JBinaryOperator.DIV, JsBinaryOperator.DIV);
      bOpMap.put(JBinaryOperator.MOD, JsBinaryOperator.MOD);
      bOpMap.put(JBinaryOperator.ADD, JsBinaryOperator.ADD);
      bOpMap.put(JBinaryOperator.CONCAT, JsBinaryOperator.ADD);
      bOpMap.put(JBinaryOperator.SUB, JsBinaryOperator.SUB);
      bOpMap.put(JBinaryOperator.SHL, JsBinaryOperator.SHL);
      bOpMap.put(JBinaryOperator.SHR, JsBinaryOperator.SHR);
      bOpMap.put(JBinaryOperator.SHRU, JsBinaryOperator.SHRU);
      bOpMap.put(JBinaryOperator.LT, JsBinaryOperator.LT);
      bOpMap.put(JBinaryOperator.LTE, JsBinaryOperator.LTE);
      bOpMap.put(JBinaryOperator.GT, JsBinaryOperator.GT);
      bOpMap.put(JBinaryOperator.GTE, JsBinaryOperator.GTE);
      bOpMap.put(JBinaryOperator.EQ, JsBinaryOperator.EQ);
      bOpMap.put(JBinaryOperator.NEQ, JsBinaryOperator.NEQ);
      bOpMap.put(JBinaryOperator.BIT_AND, JsBinaryOperator.BIT_AND);
      bOpMap.put(JBinaryOperator.BIT_XOR, JsBinaryOperator.BIT_XOR);
      bOpMap.put(JBinaryOperator.BIT_OR, JsBinaryOperator.BIT_OR);
      bOpMap.put(JBinaryOperator.AND, JsBinaryOperator.AND);
      bOpMap.put(JBinaryOperator.OR, JsBinaryOperator.OR);
      bOpMap.put(JBinaryOperator.ASG, JsBinaryOperator.ASG);
      bOpMap.put(JBinaryOperator.ASG_ADD, JsBinaryOperator.ASG_ADD);
      bOpMap.put(JBinaryOperator.ASG_CONCAT, JsBinaryOperator.ASG_ADD);
      bOpMap.put(JBinaryOperator.ASG_SUB, JsBinaryOperator.ASG_SUB);
      bOpMap.put(JBinaryOperator.ASG_MUL, JsBinaryOperator.ASG_MUL);
      bOpMap.put(JBinaryOperator.ASG_DIV, JsBinaryOperator.ASG_DIV);
      bOpMap.put(JBinaryOperator.ASG_MOD, JsBinaryOperator.ASG_MOD);
      bOpMap.put(JBinaryOperator.ASG_SHL, JsBinaryOperator.ASG_SHL);
      bOpMap.put(JBinaryOperator.ASG_SHR, JsBinaryOperator.ASG_SHR);
      bOpMap.put(JBinaryOperator.ASG_SHRU, JsBinaryOperator.ASG_SHRU);
      bOpMap.put(JBinaryOperator.ASG_BIT_AND, JsBinaryOperator.ASG_BIT_AND);
      bOpMap.put(JBinaryOperator.ASG_BIT_OR, JsBinaryOperator.ASG_BIT_OR);
      bOpMap.put(JBinaryOperator.ASG_BIT_XOR, JsBinaryOperator.ASG_BIT_XOR);

      uOpMap.put(JUnaryOperator.INC, JsUnaryOperator.INC);
      uOpMap.put(JUnaryOperator.DEC, JsUnaryOperator.DEC);
      uOpMap.put(JUnaryOperator.NEG, JsUnaryOperator.NEG);
      uOpMap.put(JUnaryOperator.NOT, JsUnaryOperator.NOT);
      uOpMap.put(JUnaryOperator.BIT_NOT, JsUnaryOperator.BIT_NOT);
    }

    public static JsBinaryOperator get(JBinaryOperator op) {
      return bOpMap.get(op);
    }

    public static JsUnaryOperator get(JUnaryOperator op) {
      return uOpMap.get(op);
    }
  }

  private class CollectJsFunctionsForInlining extends JVisitor {

    // JavaScript functions that arise from methods that were not inlined in the Java AST
    // NOTE: We use a LinkedHashSet to preserve the order of insertion. So that the following passes
    // that use this result are deterministic.
    private Set<JsNode> functionsForJsInlining = Sets.newLinkedHashSet();
    private JMethod currentMethod;

    @Override
    public void endVisit(JMethod x, Context ctx) {
      if (x.isJsniMethod()) {
        // These are methods whose bodies where not traversed by the Java method inliner.
        JsFunction function = jsFunctionsByJavaMethodBody.get(x.getBody());
        if (function != null && function.getBody() != null) {
          functionsForJsInlining.add(function);
        }
        // Add all functions declared inside JSNI blocks as well.
        assert function != null;
        new JsModVisitor() {
          @Override
          public void endVisit(JsFunction x, JsContext ctx) {
            functionsForJsInlining.add(x);
          }
        }.accept(function);
      }

      currentMethod = null;
    }

    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      JMethod target = x.getTarget();
      if (target.isInliningAllowed() && (target.isJsniMethod()
          || program.getIndexedTypes().contains(target.getEnclosingType())
          || target.getInliningMode() == InliningMode.FORCE_INLINE)) {
        // These are either: 1) callsites to JSNI functions, in which case MethodInliner did not
        // attempt to inline; 2) inserted by normalizations passes AFTER all inlining or 3)
        // calls to methods annotated with @ForceInline that were not inlined by the simple
        // MethodInliner.
        JsFunction function = jsFunctionsByJavaMethodBody.get(currentMethod.getBody());
        if (function != null && function.getBody() != null) {
          functionsForJsInlining.add(function);
        }
      }
    }

    @Override
    public boolean visit(JMethod x, Context ctx) {
      currentMethod = x;
      return true;
    }

    public Set<JsNode> getFunctionsForJsInlining() {
      accept(program);
      return functionsForJsInlining;
    }
  }

  /**
   * Computes:<p>
   * <ul>
   * <li> 1. whether a constructors are live directly (through being in a new operation) or
   * indirectly (only called by other constructors). Only directly live constructors become
   * JS constructor, otherwise they will behave like regular static functions.
   * </li> 2. whether there exists cross class (static) calls or accesses that would need clinits to
   * be triggered. If not clinits need only be called in constructors.
   * <li>
   * </li>
   * </ul>
   */
  private class RecordCrossClassCallsAndConstructorLiveness extends JVisitor {
    // TODO(rluble): This analysis should be extracted from GenerateJavaScriptAST into its own
    // JAVA optimization pass. Constructors that are not newed can be transformed into statified
    // regular methods; and methods that are not called from outside the class boundary can be
    // privatized. Currently we do not use the private modifier to avoid emitting clinits, instead
    // we use the result of this analysis (private methods CAN be called from JSNI in an unrelated
    // class, touche!).
    {
      crossClassTargets =  Sets.newHashSet();
      liveCtors = Sets.newIdentityHashSet();
    }

    private JMethod currentMethod;

    @Override
    public void endVisit(JMethod x, Context ctx) {
      // methods which are exported or static indexed methods may be called externally
      if (x.isJsInteropEntryPoint()
          || (x.isStatic() && program.getIndexedMethods().contains(x))) {
        if (x instanceof JConstructor) {
          // exported ctors always considered live
          liveCtors.add((JConstructor) x);
        }
        // could be called from JS, so clinit must be called from body
        crossClassTargets.add(x);
      }
      currentMethod = null;
    }

    @Override
    public void endVisit(JMethodCall x, Context ctx) {
      JDeclaredType sourceType = currentMethod.getEnclosingType();
      JDeclaredType targetType = x.getTarget().getEnclosingType();
      if (sourceType.checkClinitTo(targetType)) {
        crossClassTargets.add(x.getTarget());
      }
    }

    @Override
    public void endVisit(JNewInstance x, Context ctx) {
      super.endVisit(x, ctx);
      liveCtors.add(x.getTarget());
    }

    @Override
    public void endVisit(JProgram x, Context ctx) {
      // Entry methods can be called externally, so they must run clinit.
      crossClassTargets.addAll(x.getEntryMethods());
    }

    @Override
    public void endVisit(JsniMethodRef x, Context ctx) {
      if (x.getTarget() instanceof JConstructor) {
        liveCtors.add((JConstructor) x.getTarget());
      }

      endVisit((JMethodCall) x, ctx);
    }

    @Override
    public boolean visit(JMethod x, Context ctx) {
      currentMethod = x;
      return true;
    }
  }

  private static class SortVisitor extends JVisitor {

    @Override
    public void endVisit(JClassType x, Context ctx) {
      x.sortFields(HasName.BY_NAME_COMPARATOR);
      x.sortMethods(JMethod.BY_SIGNATURE_COMPARATOR);
    }

    @Override
    public void endVisit(JInterfaceType x, Context ctx) {
      x.sortFields(HasName.BY_NAME_COMPARATOR);
      x.sortMethods(JMethod.BY_SIGNATURE_COMPARATOR);
    }

    @Override
    public void endVisit(JMethodBody x, Context ctx) {
      x.sortLocals(HasName.BY_NAME_COMPARATOR);
    }

    @Override
    public void endVisit(JProgram x, Context ctx) {
      Collections.sort(x.getEntryMethods(), JMethod.BY_SIGNATURE_COMPARATOR);
      Collections.sort(x.getDeclaredTypes(), HasName.BY_NAME_COMPARATOR);
    }

    @Override
    public boolean visit(JMethodBody x, Context ctx) {
      // No need to visit method bodies.
      return false;
    }
  }

  /**
   * This is the main entry point for the translation from Java to JavaScript. Starts from a
   * Java AST and constructs a JavaScript AST while collecting other useful information that
   * is used in subsequent passes.
   *
   * @param logger            a TreeLogger
   * @param program           a Java AST
   * @param jsProgram         an (empty) JavaScript AST
   * @param symbolTable       an (empty) symbol table that will be populated here
   *
   * @return A pair containing a JavaToJavaScriptMap and a Set of JsFunctions that need to be
   *         considered for inlining.
   */
  public static Pair<JavaToJavaScriptMap, Set<JsNode>> exec(TreeLogger logger, JProgram program,
      JsProgram jsProgram, CompilerContext compilerContext, TypeMapper<?> typeMapper,
      Map<StandardSymbolData, JsName> symbolTable, PermutationProperties props) {

    Event event = SpeedTracerLogger.start(CompilerEventType.GENERATE_JS_AST);
    try {
      GenerateJavaScriptAST generateJavaScriptAST = new GenerateJavaScriptAST(logger, program,
          jsProgram, compilerContext, typeMapper, symbolTable, props);
      return generateJavaScriptAST.execImpl();
    } finally {
      event.end();
    }
  }

  private static final ImmutableList<String> METHODS_PROVIDED_BY_PREAMBLE = ImmutableList.of(
      "Class.createForClass", "Class.createForPrimitive", "Class.createForInterface",
      "Class.createForEnum");

  private final Map<JBlock, JsCatch> catchMap = Maps.newIdentityHashMap();

  private final Set<JsName> catchParamIdentifiers = Sets.newHashSet();

  private final Map<JClassType, JsScope> classScopes = Maps.newIdentityHashMap();

  /**
   * A list of methods that are called from another class (ie might need to
   * clinit).
   */
  private Set<JMethod> crossClassTargets = null;

  /**
   * Contains JsNames for all interface methods. A special scope is needed so
   * that independent classes will obfuscate their interface implementation
   * methods the same way.
   */
  private final JsScope interfaceScope;

  private final JsProgram jsProgram;

  private Set<JConstructor> liveCtors = null;

  /**
   * Classes that could potentially see uninitialized values for fields that are initialized in the
   * declaration.
   */
  private Predicate<JField> uninitializedValuePotentiallyObservable;

  private final Map<JAbstractMethodBody, JsFunction> jsFunctionsByJavaMethodBody =
      Maps.newIdentityHashMap();
  private final Map<HasName, JsName> names = Maps.newIdentityHashMap();

  /**
   * Contains JsNames for the Object instance methods, such as equals, hashCode,
   * and toString. All other class scopes have this scope as an ultimate parent.
   */
  private final JsScope objectScope;
  private final Map<JMethod, JsName> polymorphicNames = Maps.newIdentityHashMap();
  private final JProgram program;

  /**
   * SEt of all targets of JNameOf.
   */
  private Set<HasName> nameOfTargets = Sets.newHashSet();

  private final TreeLogger logger;

  /**
   * Maps JsNames to machine-usable identifiers.
   */
  private final Map<StandardSymbolData, JsName> symbolTable;

  /**
   * Contains JsNames for all globals, such as static fields and methods.
   */
  private final JsScope topScope;

  private final Map<JsStatement, JDeclaredType> javaTypeByGlobalStatement = Maps.newHashMap();

  private final Map<JsStatement, JMethod> methodByGlobalStatement = Maps.newHashMap();

  private final TypeMapper<?> typeMapper;

  private final MinimalRebuildCache minimalRebuildCache;

  private final PermutationProperties properties;

  private JsFunction objectConstructorFunction;

  private OptionMethodNameDisplayMode.Mode methodNameMappingMode;

  private final boolean closureCompilerFormatEnabled;

  private final boolean optimize;

  // This is also used to do some final optimizations.
  // TODO(rluble) move optimizations to a Java AST optimization pass.
  private final boolean incremental;

  /**
   * If true, polymorphic functions are made anonymous vtable declarations and
   * not assigned topScope identifiers.
   */
  private final boolean stripStack;

  private GenerateJavaScriptAST(TreeLogger logger, JProgram program, JsProgram jsProgram,
      CompilerContext compilerContext, TypeMapper<?> typeMapper,
      Map<StandardSymbolData, JsName> symbolTable, PermutationProperties properties) {
    this.logger = logger;
    this.program = program;
    this.jsProgram = jsProgram;
    this.topScope = jsProgram.getScope();
    this.objectScope = jsProgram.getObjectScope();
    this.interfaceScope = new JsNormalScope(objectScope, "Interfaces");
    this.minimalRebuildCache = compilerContext.getMinimalRebuildCache();
    this.symbolTable = symbolTable;
    this.typeMapper = typeMapper;
    this.properties = properties;

    PrecompileTaskOptions options = compilerContext.getOptions();
    this.optimize = options.getOptimizationLevel() > OptionOptimize.OPTIMIZE_LEVEL_DRAFT;
    this.methodNameMappingMode = options.getMethodNameDisplayMode();
    assert methodNameMappingMode != null;
    this.incremental = options.isIncrementalCompileEnabled();

    this.stripStack = JsStackEmulator.getStackMode(properties) == JsStackEmulator.StackMode.STRIP;
    this.closureCompilerFormatEnabled = options.isClosureCompilerFormatEnabled();
    this.objectConstructorFunction =
        new JsFunction(SourceOrigin.UNKNOWN, topScope, topScope.findExistingName("Object"));
  }

  /**
   * Retrieves the runtime typeId for {@code type}.
   */
  JExpression getRuntimeTypeReference(JReferenceType type) {
    return typeMapper.get(type);
  }

  private String mangleName(JField x) {
    return JjsUtils.mangleMemberName(x.getEnclosingType().getName(), x.getName());
  }

  private String mangleNameForGlobal(JMethod method) {
    String s =
        JjsUtils.mangleMemberName(method.getEnclosingType().getName(), method.getName()) + "__";
    for (JType type : method.getOriginalParamTypes()) {
      s += type.getJavahSignatureName();
    }
    s += method.getOriginalReturnType().getJavahSignatureName();
    return StringInterner.get().intern(s);
  }

  private String mangleNameForPackagePrivatePoly(JMethod method) {
    assert method.isPackagePrivate() && !method.isStatic();
    /*
     * Package private instance methods in different package should not override each
     * other, so they must have distinct polymorphic names. Therefore, add the
     * package to the mangled name.
     */
    String mangledName = Joiner.on("$").join(
        "package_private",
        JjsUtils.mangledNameString(method.getEnclosingType().getPackageName()),
        JjsUtils.mangledNameString(method));
    return StringInterner.get().intern(JjsUtils.constructManglingSignature(method, mangledName));
  }

  private String mangleNameForPoly(JMethod method) {
    if (method.isPrivate()) {
      return mangleNameForPrivatePoly(method);
    } else if (method.isPackagePrivate()) {
      return mangleNameForPackagePrivatePoly(method);
    } else {
      return mangleNameForPublicPoly(method);
    }
  }

  private String mangleNameForPublicPoly(JMethod method) {
    return StringInterner.get().intern(
        JjsUtils.constructManglingSignature(method, JjsUtils.mangledNameString(method)));
  }

  private String mangleNameForPrivatePoly(JMethod method) {
    assert method.isPrivate() && !method.isStatic();
    /*
     * Private instance methods in different classes should not override each
     * other, so they must have distinct polymorphic names. Therefore, add the
     * class name to the mangled name.
     */
    String mangledName = Joiner.on("$").join(
        "private",
        JjsUtils.mangledNameString(method.getEnclosingType()),
        JjsUtils.mangledNameString(method));

    return StringInterner.get().intern(JjsUtils.constructManglingSignature(method, mangledName));
  }

  private final Map<JType, JDeclarationStatement> classLiteralDeclarationsByType =
      Maps.newLinkedHashMap();

  private void contructTypeToClassLiteralDeclarationMap() {
      /*
       * Must execute in clinit statement order, NOT field order, so that back
       * refs to super classes are preserved.
       */
    JMethodBody clinitBody =
        (JMethodBody) program.getTypeClassLiteralHolder().getClinitMethod().getBody();
    for (JStatement stmt : clinitBody.getStatements()) {
      if (!(stmt instanceof JDeclarationStatement)) {
        continue;
      }
      JDeclarationStatement classLiteralDeclaration = (JDeclarationStatement) stmt;

      JType type = program.getTypeByClassLiteralField(
          (JField) ((JDeclarationStatement) stmt).getVariableRef().getTarget());

      assert !classLiteralDeclarationsByType.containsKey(type);
      classLiteralDeclarationsByType.put(type, classLiteralDeclaration);
    }
  }

  private Pair<JavaToJavaScriptMap, Set<JsNode>> execImpl() {
    NameClashesFixer.exec(program);
    uninitializedValuePotentiallyObservable = optimize
        ? ComputePotentiallyObservableUninitializedValues.analyze(program)
        : Predicates.<JField>alwaysTrue();
    new FindNameOfTargets().accept(program);
    new SortVisitor().accept(program);
    if (!incremental) {
      // TODO(rluble): pull out this analysis and make it a Java AST optimization pass.
      new RecordCrossClassCallsAndConstructorLiveness().accept(program);
    }

    // Map class literals to their respective types.
    contructTypeToClassLiteralDeclarationMap();

    new CreateNamesAndScopesVisitor().accept(program);
    new GenerateJavaScriptTransformer().transform(program);

    // TODO(spoon): Instead of gathering the information here, get it via
    // SourceInfo
    JavaToJavaScriptMap jjsMap = new JavaToJavaScriptMapImpl(program.getDeclaredTypes(),
        names, javaTypeByGlobalStatement, methodByGlobalStatement);

    Set<JsNode> functionsForJsInlining = incremental ? Collections.<JsNode>emptySet() :
        new CollectJsFunctionsForInlining().getFunctionsForJsInlining();

    return Pair.create(jjsMap, functionsForJsInlining);
  }

  private JsFunction getJsFunctionFor(JMethod jMethod) {
    return jsFunctionsByJavaMethodBody.get(jMethod.getBody());
  }

  private JsName getIndexedMethodJsName(String indexedName) {
    return names.get(program.getIndexedMethod(indexedName));
  }

  private JsName getIndexedFieldJsName(String indexedName) {
    return names.get(program.getIndexedField(indexedName));
  }

  private static JsNameRef createGlobalQualifier(String qualifier, SourceInfo sourceInfo) {
     return JsUtils.createQualifiedNameRef(JsInteropUtil.normalizeQualifier(qualifier), sourceInfo);
  }
}
