/*
 * 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 static com.google.gwt.dev.js.JsUtils.createQualifiedNameRef;

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.JUnsafeTypeCoercion;
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.requiresJsName(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.requiresJsName(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");
    private final JsName wnd = topScope.declareUnobfuscatableName("$wnd");
    private final JsName goog = topScope.declareUnobfuscatableName("goog");
    private final JsName global = topScope.declareUnobfuscatableName("global");

    @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 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 transformUnsafeTypeCoercion(JUnsafeTypeCoercion unsafeTypeCoercion) {
      return transform(unsafeTypeCoercion.getExpression());
    }

    @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) {
      SourceInfo programSourceInfo = jsProgram.getSourceInfo();

      // Reserve the "_" identifier.
      JsVars vars = new JsVars(programSourceInfo, new JsVar(programSourceInfo, globalTemp));
      addVarsIfNotEmpty(vars);

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

      // Generate the assignment to goog.global.
      generateGoogGlobalInitialization(programSourceInfo);

      //  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 void generateGoogGlobalInitialization(SourceInfo programSourceInfo) {
      // $wnd.goog = $wnd.goog || {}
      JsNameRef wndGoog  = goog.makeQualifiedRef(programSourceInfo, wnd.makeRef(programSourceInfo));
      generatePropertyInitialization(
          programSourceInfo, wndGoog, JsObjectLiteral.builder(programSourceInfo).build());

      // $wnd.goog.global = $wnd.goog.global || $wnd
      JsNameRef wndGoogGlobal  = global.makeQualifiedRef(programSourceInfo, wndGoog);
      generatePropertyInitialization(
          programSourceInfo, wndGoogGlobal, wnd.makeRef(programSourceInfo));
    }

    private void generatePropertyInitialization(
        SourceInfo sourceInfo, JsNameRef qualifiedNameRef, JsExpression initializer) {
      getGlobalStatements().add(
          new JsBinaryOperation(sourceInfo, JsBinaryOperator.ASG, qualifiedNameRef,
              new JsBinaryOperation(sourceInfo, JsBinaryOperator.OR,
                  qualifiedNameRef, initializer)).makeStmt());
    }

    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();
          assert ref.getQualifier() == null;

          JConstructor constructor = (JConstructor) nodeByJsniReference.get(ident);
          JsNameRef constructorJsName = createStaticReference(constructor, x.getSourceInfo());

          ctx.replaceMe(new JsNew(x.getSourceInfo(), constructorJsName, x.getArguments()));
        }

        @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;

            if (field.isStatic() && field.isJsNative()) {
              ctx.replaceMe(createQualifiedNameRef(field.getQualifiedJsName(), x.getSourceInfo()));
              return;
            }

            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 constructor = (JConstructor) node;
              SourceInfo info = x.getSourceInfo();

              JsNameRef constructorJsNameRef = createStaticReference(constructor, info);

              JsFunction anonymousFunction = new JsFunction(info, function.getScope());
              for (JParameter p : constructor.getParams()) {
                JsName name = anonymousFunction.getScope().declareName(p.getName());
                anonymousFunction.getParameters().add(new JsParameter(info, name));
              }
              JsNew jsNew = new JsNew(info, constructorJsNameRef);
              for (JsParameter p : anonymousFunction.getParameters()) {
                jsNew.getArguments().add(p.getName().makeRef(info));
              }
              anonymousFunction.setBody(new JsBlock(info));
              anonymousFunction.getBody().getStatements().add(new JsReturn(info, jsNew));
              ctx.replaceMe(anonymousFunction);
            }
          } else {
            JMethod method = (JMethod) node;
            if (!method.needsDynamicDispatch() && method.isJsNative()) {
              ctx.replaceMe(createGlobalQualifier(method.getQualifiedJsName(), x.getSourceInfo()));
              return;
            }
            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.needsDynamicDispatch();
      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);
  }
}
