/*
 * 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 com.google.gwt.dev.jjs.ast.Context;
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.JCastOperation;
import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JConstructor;
import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JFieldRef;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JNewArray;
import com.google.gwt.dev.jjs.ast.JNewInstance;
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JParameterRef;
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.JRunAsync;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.JVariableRef;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.ast.RuntimeConstants;
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.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsVisitor;
import com.google.gwt.thirdparty.guava.common.collect.ArrayListMultimap;
import com.google.gwt.thirdparty.guava.common.collect.ListMultimap;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Sets;

import java.util.List;
import java.util.Set;

/**
 * This class finds out what code in a program is live based on starting
 * execution at a specified location.
 */
public class ControlFlowAnalyzer {

  /**
   * A callback for recording control-flow dependencies as they are discovered.
   * See {@link ControlFlowAnalyzer#setDependencyRecorder(DependencyRecorder)}.
   */
  public interface DependencyRecorder {
    /**
     * Used to record the dependencies of a specific method.
     */
    void methodIsLiveBecause(JMethod liveMethod, List<JMethod> dependencyChain);
  }

  /**
   * Marks as "referenced" any types, methods, and fields that are reachable.
   * Also marks as "instantiable" any classes and interfaces that can possibly
   * be instantiated.
   *
   * TODO(later): make RescueVisitor use less stack?
   */
  private class RescueVisitor extends JVisitor {
    private final List<JMethod> curMethodStack = Lists.newArrayList();

    @Override
    public boolean visit(JArrayRef arrayRef, Context ctx) {
      maybeRescueJsTypeArray(arrayRef.getInstance().getType());
      return true;
    }

    @Override
    public boolean visit(JArrayLength arrayLength, Context ctx) {
      maybeRescueJsTypeArray(arrayLength.getInstance().getType());
      return true;
    }

    @Override
    public boolean visit(JArrayType type, Context ctx) {
      assert (referencedTypes.contains(type));
      boolean isInstantiated = instantiatedTypes.contains(type);

      JType leafType = type.getLeafType();
      int dims = type.getDims();

      // Rescue my super array type
      boolean didSuperType = false;
      if (leafType instanceof JClassType) {
        JClassType superClass = ((JClassType) leafType).getSuperClass();
        if (superClass != null) {
          // FooSub[] -> Foo[]
          rescue(program.getOrCreateArrayType(superClass, dims), isInstantiated);
          didSuperType = true;
        }
      } else if (leafType instanceof JInterfaceType) {
        // Intf[] -> Object[]
        rescue(program.getOrCreateArrayType(program.getTypeJavaLangObject(), dims),
            isInstantiated);
        didSuperType = true;
      }
      if (!didSuperType) {
        if (dims > 1) {
          // anything[][] -> Object[]
          rescue(program.getOrCreateArrayType(program.getTypeJavaLangObject(), dims - 1),
              isInstantiated);
        } else {
          // anything[] -> Object
          rescue(program.getTypeJavaLangObject(), isInstantiated);
        }
      }

      // Rescue super interface array types.
      if (leafType instanceof JDeclaredType) {
        JDeclaredType dLeafType = (JDeclaredType) leafType;
        for (JInterfaceType intfType : dLeafType.getImplements()) {
          JArrayType intfArray = program.getOrCreateArrayType(intfType, dims);
          rescue(intfArray, isInstantiated);
        }
      }

      return false;
    }

    @Override
    public boolean visit(JBinaryOperation x, Context ctx) {
      if (x.isAssignment() && x.getLhs() instanceof JFieldRef) {
        fieldsWritten.add(((JFieldRef) x.getLhs()).getField());
      }

      // special string concat handling
      if ((x.getOp() == JBinaryOperator.CONCAT || x.getOp() == JBinaryOperator.ASG_CONCAT)) {
        rescueByConcat(x.getLhs().getType());
        rescueByConcat(x.getRhs().getType());
      }

      JExpression lhs = x.getLhs();
      if (x.getOp() != JBinaryOperator.ASG || lhs.hasSideEffects() || isVolatileField(lhs)) {
        // Continue the normal visitor process for lhs and rhs.
        return true;
      }

      // Assignments where the lhs does not have side effects (save for volatile fields) are special
      // treated here. The idea is to not consider live a field/local/parameter that is only
      // written to.
      if (lhs instanceof JLocalRef || lhs instanceof JParameterRef) {
        // if the lhs is a local or parameter, do not consider it live just because it is being
        // written to.
        accept(x.getRhs());
        return false;
      } else if (lhs instanceof JFieldRef) {
        JFieldRef fieldRef = (JFieldRef) lhs;
        JField field = fieldRef.getField();
        if (field.canBeImplementedExternally()) {
          // Proceed normally to consider native fields live even if they are only written to.
          return true;
        }

        // Fields that are only written to still need to process their qualifier.
        JExpression instance = fieldRef.getInstance();
        if (instance != null) {
          accept(instance);
        }
        accept(x.getRhs());
        return false;
      }
      return true;
    }

    @Override
    public boolean visit(JCastOperation x, Context ctx) {
      // Rescue any JavaScriptObject type that is the target of a cast.
      JType targetType = x.getCastType();

      if (!canBeInstantiatedInJavaScript(targetType)) {
        return true;
      }
      rescue((JReferenceType) targetType, true);
      JType exprType = x.getExpr().getType();
      if (program.typeOracle.isSingleJsoImpl(targetType)) {
        /*
         * It's a JSO interface, check if the source expr can be a live JSO:
         * 1) source is java.lang.Object (JSO could have been assigned to it)
         * 2) source is JSO
         * 3) source is SingleJSO interface whose implementor is live
         */
        if (program.getTypeJavaLangObject() == exprType
            || program.typeOracle.canBeJavaScriptObject(exprType)) {
          // source is JSO or SingleJso interface whose implementor is live
          JClassType jsoImplementor =
              program.typeOracle.getSingleJsoImpl((JReferenceType) targetType);
          rescue(jsoImplementor, true);
        }
      }

      return true;
    }

    @Override
    public boolean visit(JClassLiteral x, Context ctx) {
      JField field = x.getField();
      assert field != null;
      rescue(field);
      return true;
    }

    @Override
    public boolean visit(JClassType type, Context ctx) {
      assert (referencedTypes.contains(type));
      boolean isInstantiated = instantiatedTypes.contains(type);

      // Rescue my super type
      rescue(type.getSuperClass(), isInstantiated);

      // Rescue my clinit (it won't ever be explicitly referenced)
      if (type.hasClinit()) {
        rescue(type.getClinitMethod());
      }

      // If I'm instantiated, let's mark super interfaces as instantiated.
      if (isInstantiated) {
        rescueMembersAndInstantiateSuperInterfaces(type);
      }

      return false;
    }

    @Override
    public boolean visit(JDeclarationStatement x, Context ctx) {
      /*
       * A declaration by itself doesn't rescue a local (even if it has an
       * initializer). Writes don't count, only reads.
       */
      if (x.getInitializer() != null &&
          !isStaticFieldInitializedToLiteral(x.getVariableRef().getTarget())) {
        /*
         * Don't traverse literal initializers, because those become live when
         * the variable is accessed, not when its declaration runs.
         */
        accept(x.getInitializer());

        if (x.getVariableRef().getTarget() instanceof JField) {
          fieldsWritten.add((JField) x.getVariableRef().getTarget());
        }
      }

      // If the lhs is a field ref, we have to visit its qualifier.
      JVariableRef variableRef = x.getVariableRef();
      if (variableRef instanceof JFieldRef) {
        JFieldRef fieldRef = (JFieldRef) variableRef;
        JExpression instance = fieldRef.getInstance();
        if (instance != null) {
          accept(instance);
        }
      }
      return false;
    }

    @Override
    public boolean visit(JFieldRef ref, Context ctx) {
      JField target = ref.getField();

      /*
       * JLS 12.4.1: references to static, non-final, or
       * non-compile-time-constant fields rescue the enclosing class. JDT
       * already folds in compile-time constants as literals, so we must rescue
       * the enclosing types for any static fields that make it here.
       */
      if (target.isStatic()) {
        rescue(target.getEnclosingType(), false);
      }
      if (target.isStatic() || instantiatedTypes.contains(target.getEnclosingType())) {
        rescue(target);
      } else {
        // It's a field whose class is not instantiable
        if (!liveFieldsAndMethods.contains(target)) {
          membersToRescueIfTypeIsInstantiated.add(target);
        }
      }
      return true;
    }

    @Override
    public boolean visit(JInterfaceType type, Context ctx) {
      boolean isReferenced = referencedTypes.contains(type);
      boolean isInstantiated = instantiatedTypes.contains(type);
      assert (isReferenced || isInstantiated);

      // Rescue my clinit (it won't ever be explicitly referenced)
      if (type.hasClinit()) {
        rescue(type.getClinitMethod());
      }

      // If I'm instantiated, let's mark super interfaces as instantiated.
      if (isInstantiated) {
        rescueMembersAndInstantiateSuperInterfaces(type);
      }

      return false;
    }

    @Override
    public boolean visit(JLocalRef ref, Context ctx) {
      JLocal target = ref.getLocal();
      rescue(target);
      return true;
    }

    @Override
    public boolean visit(final JMethod x, Context ctx) {
      JReferenceType enclosingType = x.getEnclosingType();
      if (enclosingType.isJsoType()) {
        // Calls to JavaScriptObject types rescue those types.
        boolean instance = !x.isStatic() || program.isStaticImpl(x);
        rescue(enclosingType, instance);
      } else if (x.isStatic()) {
        // JLS 12.4.1: references to static methods rescue the enclosing class
        rescue(enclosingType, false);
      }

      if (x.isJsniMethod()) {
        // Manually rescue native parameter references
        final JsniMethodBody body = (JsniMethodBody) x.getBody();
        final JsFunction func = body.getFunc();

        new JsVisitor() {
          @Override
          public void endVisit(JsNameRef nameRef, JsContext ctx) {
            JsName ident = nameRef.getName();

            if (ident != null) {
              // If we're referencing a parameter, rescue the associated
              // JParameter
              int index = func.getParameters().indexOf(ident.getStaticRef());
              if (index != -1) {
                rescue(x.getParams().get(index));
              }
            }
          }
        }.accept(func);
      }

      return true;
    }

    @Override
    public boolean visit(JMethodCall call, Context ctx) {
      JMethod method = call.getTarget();
      if (call.isVolatile() && method == runAsyncOnSuccess) {
        /*
         * Note: In order to preserve code splitting, don't allow code flow from the
         * AsyncFragmentLoader implementation back into the
         * callback.onSuccess(). If we did, the rescue path would look like
         * JRunAsync -> AsyncFragmentLoader.runAsync() -> callback.onSuccess().
         * This would completely defeat code splitting as all the code on the
         * other side of the barrier would become reachable.
         *
         * Code flow analysis is run separately on methods which implement
         * RunAsyncCallback.onSuccess() as top-level entry points.
         */
        return true;
      }
      if (method.isStatic() || isTypeInstantiatedOrJso(method.getEnclosingType())) {
        rescue(method);
      } else {
        // It's a virtual method whose class is not instantiable
        if (!liveFieldsAndMethods.contains(method)) {
          membersToRescueIfTypeIsInstantiated.add(method);
        }
      }

      if (argsToRescueIfParameterRead == null || method.canBePolymorphic()
          || call instanceof JsniMethodRef) {
        return true;
      }

      if (program.instanceMethodForStaticImpl(method) != null) {
        // CleanUpRefsVisitor does not prune these params, must rescue.
        return true;
      }

      if (call.getInstance() != null) {
        // Explicitly visit instance since we're returning false below.
        this.accept(call.getInstance());
      }

      rescueArgumentsIfParametersCanBeRead(call);
      return false;
    }

    @Override
    public boolean visit(JNewArray newArray, Context ctx) {
      // rescue and instantiate the array type
      JArrayType arrayType = newArray.getArrayType();
      if (newArray.getDimensionExpressions() != null) {
        // rescue my type and all the implicitly nested types (with fewer dims)
        int arrayDimensions = arrayType.getDims();
        int initializedDimensions = newArray.getDimensionExpressions().size();
        JType leafType = arrayType.getLeafType();
        assert (initializedDimensions <= arrayDimensions);
        for (int i = 0; i < initializedDimensions; ++i) {
          rescue(program.getOrCreateArrayType(leafType, arrayDimensions - i), true);
        }
      } else {
        // just rescue my own specific type
        rescue(arrayType, true);
      }
      return true;
    }

    @Override
    public boolean visit(JNewInstance x, Context ctx) {
      // rescue and instantiate the target class!
      rescue(x.getClassType(), true);
      return super.visit(x, ctx);
    }

    @Override
    public boolean visit(JParameterRef x, Context ctx) {
      // rescue the parameter for future pruning purposes
      rescue(x.getParameter());
      return true;
    }

    @Override
    public boolean visit(JsniFieldRef x, Context ctx) {
      /*
       * SPECIAL: this could be an assignment that passes a value from
       * JavaScript into Java.
       */
      if (x.isLvalue()) {
        maybeRescueJavaScriptObjectPassingIntoJava(x.getField().getType());
      }
      // JsniFieldRef rescues as JFieldRef
      return visit((JFieldRef) x, ctx);
    }

    @Override
    public boolean visit(JsniMethodBody body, Context ctx) {
      liveStrings.addAll(body.getUsedStrings());
      return true;
    }

    @Override
    public boolean visit(JsniMethodRef x, Context ctx) {
      /*
       * SPECIAL: each argument of the call passes a value from JavaScript into
       * Java.
       */
      for (JParameter param : x.getTarget().getParams()) {
        maybeRescueJavaScriptObjectPassingIntoJava(param.getType());

        /*
         * Because we're not currently tracking methods through JSNI, we need to
         * assume that it's not safe to prune parameters of a method referenced
         * as such.
         *
         * A better solution would be to perform basic escape analysis to ensure
         * that the function reference never escapes, or at minimum, ensure that
         * the method is immediately called after retrieving the method
         * reference.
         */
        rescue(param);
      }
      // JsniMethodRef rescues as a JMethodCall
      if (x.getTarget() instanceof JConstructor) {
        // But if a constructor is targeted, there is an implicit 'new' op.
        JConstructor ctor = (JConstructor) x.getTarget();
        rescue(ctor.getEnclosingType(), true);
      }
      return visit((JMethodCall) x, ctx);
    }

    @Override
    public boolean visit(JStringLiteral literal, Context ctx) {
      liveStrings.add(literal.getValue());

      // rescue and instantiate java.lang.String
      rescue(program.getTypeJavaLangString(), true);
      return true;
    }

    private boolean canBeInstantiatedInJavaScript(JType type) {
      // Technically, JsType/JsFunction are also instantiatable in JavaScript but we don't track
      // them using similar to JSO as if we do that then after cast normalization, they got pruned.
      if (program.typeOracle.canBeJavaScriptObject(type)
          || program.isRepresentedAsNativeJsPrimitive(type)) {
        return true;
      }

      /*
       * Hackish: in our own JRE we sometimes create "not quite baked" arrays
       * in JavaScript for expediency.
       */
      if (type instanceof JArrayType) {
        return true;
      }

      return false;
    }

    private JMethod getStringValueOfCharMethod() {
      JPrimitiveType charType = program.getTypePrimitiveChar();
      JClassType stringType = program.getTypeJavaLangString();
      if (stringValueOfChar != null) {
        return stringValueOfChar;
      }

      for (JMethod method : stringType.getMethods()) {
        if (method.getName().equals("valueOf") &&
            method.getOriginalParamTypes().size() == 1 &&
            method.getOriginalParamTypes().get(0) == charType) {
          stringValueOfChar = method;
          return stringValueOfChar;
        }
      }
      assert false;
      return null;
    }

    private boolean isStaticFieldInitializedToLiteral(JVariable var) {
      if (!(var instanceof JField)) {
        return false;
      }

      JField field = (JField) var;
      return field.isStatic() && field.getLiteralInitializer() != null;
    }

    private boolean isVolatileField(JExpression x) {
      if (!(x instanceof JFieldRef)) {
        return false;
      }

      JFieldRef xFieldRef = (JFieldRef) x;
      return xFieldRef.getField().isVolatile();
    }

    private void maybeRescueClassLiteral(JReferenceType type) {
      if (liveFieldsAndMethods.contains(getClassMethod) ||
          liveFieldsAndMethods.contains(getClassField)) {
        // getClass() already live so rescue class literal immediately
        rescue(program.getClassLiteralField(type));
      } else {
        // getClass() not live yet, so mark for later rescue
        classLiteralsToBeRescuedIfGetClassIsLive.add(type);
      }
    }

    /**
     * Subclasses of JavaScriptObject are never instantiated directly. They are implicitly created
     * when a JSNI method passes a reference to an existing JS object into Java code. If any point
     * in the program can pass a value from JS into Java which could potentially be cast to
     * JavaScriptObject, we must rescue JavaScriptObject.
     *
     * @param type The type of the value passing from Java to JavaScript.
     * @see com.google.gwt.core.client.JavaScriptObject
     */
    private void maybeRescueJavaScriptObjectPassingIntoJava(JType type) {
      if (!canBeInstantiatedInJavaScript(type)) {
        return;
      }
      rescue((JReferenceType) type, true);
      if (program.typeOracle.isSingleJsoImpl(type)) {
        // Cast of JSO into SingleJso interface, rescue the implementor if exists
        JClassType singleJsoImpl = program.typeOracle.getSingleJsoImpl((JReferenceType) type);
        rescue(singleJsoImpl, true);
      }
    }

    private void rescue(JMethod method) {
      if (method == null) {
        return;
      }

      if (liveFieldsAndMethods.add(method)) {
        membersToRescueIfTypeIsInstantiated.remove(method);
        if (dependencyRecorder != null) {
          curMethodStack.add(method);
          dependencyRecorder.methodIsLiveBecause(method, curMethodStack);
        }
        accept(method);
        if (dependencyRecorder != null) {
          curMethodStack.remove(curMethodStack.size() - 1);
        }
        if (method.isJsniMethod()) {
          // Returning from this method passes a value from JavaScript into Java.
          maybeRescueJavaScriptObjectPassingIntoJava(method.getType());
        }
        if (method.canBeReferencedExternally() || method.canBeImplementedExternally()) {
          for (JParameter param : method.getParams()) {
            // Parameters in JsExport, JsType, JsFunction methods should not be pruned in order to
            // keep the API intact.
            rescue(param);
            if (param.isVarargs()) {
              assert method.isJsMethodVarargs();
              // Rescue the (array) type of varargs parameters as the array creation is implicit.
              JArrayType paramType = (JArrayType) param.getType().getUnderlyingType();
              rescue(paramType, true);
              // Rescue the class literal for the array type as it will be needed when
              // ImplementJsVarargs inserts the method prelude to support the JS vararg calling
              // convention.
              rescue(program.getClassLiteralField(paramType.getLeafType()));
            }
          }
        }
        rescueOverridingMethods(method);
        if (method == getClassMethod) {
          rescueClassLiteralsIfGetClassIsLive();
        }

        if (method.getSpecialization() != null) {
          rescue(method.getSpecialization().getTargetMethod());
        }
      }
    }

    private void maybeRescueJsTypeArray(JType type) {
      if (!(type instanceof JArrayType)) {
        return;
      }
      JArrayType arrayType = (JArrayType) type;
      if (arrayType.canBeImplementedExternally()) {
        rescue(arrayType, true);
        maybeRescueJsTypeArray(arrayType.getElementType());
      }
    }

    private void rescue(JReferenceType type, boolean isInstantiated) {
      if (type == null) {
        return;
      }

      /*
       * Track references and instantiability at the granularity of run-time
       * types. For example, ignore nullness.
       */
      type = type.getUnderlyingType();

      boolean doVisit = false;
      if (isInstantiated && instantiatedTypes.add(type)) {
        maybeRescueClassLiteral(type);
        doVisit = true;
      }

      if (referencedTypes.add(type)) {
        doVisit = true;
      }

      if (!doVisit) {
        return;
      }

      accept(type);

      if (!(type instanceof JDeclaredType)) {
        return;
      }

      /*
       * We rescue all JsType member and JsFunction methods because we don't know if they'll be
       * called from JS or not.
       */
      JDeclaredType declaredType = (JDeclaredType) type;

      for (JMethod method : declaredType.getMethods()) {
        if (method.canBeReferencedExternally()
            || declaredType.isJsNative() && method.isJsConstructor()) {
          rescue(method);
        }
      }
      for (JField field : declaredType.getFields()) {
        if (field.canBeReferencedExternally()) {
          rescue(field);
        }
      }
    }

    private void rescue(JVariable var) {
      if (var == null) {
        return;
      }
      if (!liveFieldsAndMethods.add(var)) {
        // Already rescued.
        return;
      }
      membersToRescueIfTypeIsInstantiated.remove(var);
      if (var == getClassField) {
        rescueClassLiteralsIfGetClassIsLive();
      }

      if (isStaticFieldInitializedToLiteral(var)) {
        /*
         * Rescue literal initializers when the field is rescued, not when
         * the static initializer runs. This allows fields initialized to
         * string literals to only need the string literals when the field
         * itself becomes live.
         *
         * NOTE: needs to be in sync with {@link JTypeOracle.CheckClinitVistior}.
         */
        accept(((JField) var).getLiteralInitializer());
      } else if (var instanceof JField
          && (program.getTypeClassLiteralHolder().equals(((JField) var).getEnclosingType()))) {
        /*
         * Rescue just slightly less than what would normally be rescued for
         * a field reference to the literal's field. Rescue the field
         * itself, and its initializer, but do NOT rescue the whole
         * enclosing class. That would pull in the clinit of that class,
         * which has initializers for all the class literals, which in turn
         * have all of the strings of all of the class names.
         *
         * This work is done in rescue() to allow JSNI references to class
         * literals (via the @Foo::class syntax) to correctly rescue class
         * literal initializers.
         *
         * TODO: Model ClassLiteral access a different way to avoid special
         * handling. See
         *  Pruner.transformToNullFieldRef()/transformToNullMethodCall().
         */
        JField field = (JField) var;
        accept(field.getInitializer());
        referencedTypes.add(field.getEnclosingType());
        liveFieldsAndMethods.add(field.getEnclosingType().getClinitMethod());
      } else if (argsToRescueIfParameterRead != null && var instanceof JParameter) {
        List<JExpression> list = argsToRescueIfParameterRead.removeAll(var);
        for (JExpression arg : list) {
          this.accept(arg);
        }
      }
    }

    /**
     * The code is very tightly tied to the behavior of Pruner.CleanupRefsVisitor.
     * CleanUpRefsVisitor will prune unread parameters, and also prune any matching arguments that
     * don't have side effects. We want to make control flow congruent to pruning, to avoid the need
     * to iterate over Pruner until reaching a stable point, so we avoid actually rescuing such
     * arguments until/unless the parameter is read.
     */
    private void rescueArgumentsIfParametersCanBeRead(JMethodCall call) {
      JMethod method = call.getTarget();
      assert !method.canBePolymorphic();

      List<JExpression> args = call.getArgs();
      List<JParameter> params = method.getParams();
      int i = 0;
      for (int c = params.size(); i < c; ++i) {
        JExpression arg = args.get(i);
        JParameter param = params.get(i);
        if (arg.hasSideEffects() || liveFieldsAndMethods.contains(param)) {
          this.accept(arg);
          continue;
        }
        argsToRescueIfParameterRead.put(param, arg);
      }
      // Visit any "extra" arguments that exceed the param list.
      for (int c = args.size(); i < c; ++i) {
        this.accept(args.get(i));
      }
    }

    /**
     * Handle special rescues needed implicitly to support concat.
     */
    private void rescueByConcat(JType type) {
      JPrimitiveType charType = program.getTypePrimitiveChar();
      JClassType stringType = program.getTypeJavaLangString();
      if (type instanceof JReferenceType
          && !program.typeOracle.castSucceedsTrivially((JReferenceType) type, stringType)
          && !type.isNullType()) {
        /*
         * Any reference types (except String, which works by default) that take
         * part in a concat must rescue java.lang.Object.toString().
         *
         * TODO: can we narrow the focus by walking up the type hierarchy or
         * doing explicit toString calls?
         */
        JMethod toStringMethod = program.getIndexedMethod(RuntimeConstants.OBJECT_TO_STRING);
        rescue(toStringMethod);
      } else if (type == charType) {
        /*
         * Characters must rescue String.valueOf(char)
         */
        rescue(getStringValueOfCharMethod());
      }
    }

    private void rescueClassLiteralsIfGetClassIsLive() {
      if (classLiteralsToBeRescuedIfGetClassIsLive != null) {
        // guard against re-entrant calls. This only needs to run once.
        Set<JReferenceType> toRescue = classLiteralsToBeRescuedIfGetClassIsLive;
        classLiteralsToBeRescuedIfGetClassIsLive = null;

        for (JReferenceType classLit : toRescue) {
          maybeRescueClassLiteral(classLit);
        }
      }
    }

    private void rescueMembersAndInstantiateSuperInterfaces(JDeclaredType type) {
      for (JInterfaceType intfType : type.getImplements()) {
        rescue(intfType, true);
      }
      rescueMembers(type);
    }

    /**
     * Rescues any of type's virtual methods that a previously seen method call could call.
     */
    private void rescueMembers(JDeclaredType type) {
      assert instantiatedTypes.contains(type);

      for (JMethod method : type.getMethods()) {
        if (!method.isStatic() && membersToRescueIfTypeIsInstantiated.contains(method)) {
          rescue(method);
        }
      }
      for (JField field : type.getFields()) {
        if (!field.isStatic() && membersToRescueIfTypeIsInstantiated.contains(field)) {
          rescue(field);
        }
      }
    }

    /**
     * Assume that <code>method</code> is live. Rescue any overriding methods that might be called
     * if <code>method</code> is called through virtual dispatch.
     */
    private void rescueOverridingMethods(JMethod method) {
      if (method.isStatic()) {
        return;
      }

      for (JMethod overridingMethod : method.getOverridingMethods()) {
        if (liveFieldsAndMethods.contains(overridingMethod)) {
          // The override is already alive, do nothing.
        } else if (instantiatedTypes.contains(overridingMethod.getEnclosingType())) {
          // The enclosing class is alive, make my override reachable.
          rescue(overridingMethod);
        } else {
          // The enclosing class is not yet alive, put override in limbo.
          membersToRescueIfTypeIsInstantiated.add(overridingMethod);
        }
      }
    }
  }

  private boolean isTypeInstantiatedOrJso(JDeclaredType type) {
    if (type == null) {
      return false;
    }

    return type.isJsoType() || instantiatedTypes.contains(type);
  }

  /**
   * These are arguments that have not yet been rescued on account of the
   * associated parameter not having been read yet. If the parameter becomes
   * read, we will need to rescue the associated arguments. See comments in
   * {@link #rescueArgumentsIfParametersCanBeRead}.
   */
  private ListMultimap<JParameter, JExpression> argsToRescueIfParameterRead;

  private final JMethod asyncFragmentOnLoad;

  /**
   * Schrodinger set of classLiterals to be rescued if type is instantiated AND getClass()
   * is live.
   */
  private Set<JReferenceType> classLiteralsToBeRescuedIfGetClassIsLive = Sets.newHashSet();

  private DependencyRecorder dependencyRecorder;
  private Set<JField> fieldsWritten = Sets.newLinkedHashSet();
  private Set<JReferenceType> instantiatedTypes = Sets.newLinkedHashSet();
  private Set<JNode> liveFieldsAndMethods = Sets.newLinkedHashSet();
  private Set<String> liveStrings = Sets.newLinkedHashSet();

  /**
   * Schrodinger's members... aka "limbo". :) These are instance methods and
   * fields that seem to be reachable, only their enclosing type is
   * uninstantiable. We place these methods into purgatory until/unless the
   * enclosing type is found to be instantiable.
   */
  private Set<JNode> membersToRescueIfTypeIsInstantiated = Sets.newHashSet();

  private final JField getClassField;
  private final JMethod getClassMethod;
  private final JProgram program;
  private Set<JReferenceType> referencedTypes = Sets.newHashSet();
  private final RescueVisitor rescuer;
  private final JMethod runAsyncOnSuccess;
  private JMethod stringValueOfChar = null;

  public ControlFlowAnalyzer(ControlFlowAnalyzer cfa) {
    program = cfa.program;
    asyncFragmentOnLoad = cfa.asyncFragmentOnLoad;
    runAsyncOnSuccess = cfa.runAsyncOnSuccess;
    getClassField = cfa.getClassField;
    getClassMethod = cfa.getClassMethod;
    fieldsWritten = Sets.newHashSet(cfa.fieldsWritten);
    instantiatedTypes = Sets.newHashSet(cfa.instantiatedTypes);
    liveFieldsAndMethods = Sets.newHashSet(cfa.liveFieldsAndMethods);
    referencedTypes = Sets.newHashSet(cfa.referencedTypes);
    stringValueOfChar = cfa.stringValueOfChar;
    liveStrings = Sets.newHashSet(cfa.liveStrings);
    membersToRescueIfTypeIsInstantiated =
        Sets.newHashSet(cfa.membersToRescueIfTypeIsInstantiated);
    if (cfa.argsToRescueIfParameterRead != null) {
      argsToRescueIfParameterRead =
          ArrayListMultimap.create(cfa.argsToRescueIfParameterRead);
    }
    rescuer = new RescueVisitor();
  }

  public ControlFlowAnalyzer(JProgram program) {
    this.program = program;
    asyncFragmentOnLoad = program.getIndexedMethod(RuntimeConstants.ASYNC_FRAGMENT_LOADER_ON_LOAD);
    runAsyncOnSuccess = program.getIndexedMethod(RuntimeConstants.RUN_ASYNC_CALLBACK_ON_SUCCESS);
    getClassField = program.getIndexedField(RuntimeConstants.OBJECT_CLAZZ);
    getClassMethod = program.getIndexedMethod(RuntimeConstants.OBJECT_GET_CLASS);
    rescuer = new RescueVisitor();
  }

  /**
   * Return the set of all fields that are written.
   */
  public Set<JField> getFieldsWritten() {
    return fieldsWritten;
  }

  /**
   * Return the complete set of types that have been instantiated.
   */
  public Set<JReferenceType> getInstantiatedTypes() {
    return instantiatedTypes;
  }

  /**
   * Return all methods that could be executed, and all variables that could be
   * read, based on the given entry points so far.
   */
  public Set<? extends JNode> getLiveFieldsAndMethods() {
    return liveFieldsAndMethods;
  }

  public Set<String> getLiveStrings() {
    return liveStrings;
  }

  /**
   * Return the complete set of types that have been referenced.
   */
  public Set<? extends JReferenceType> getReferencedTypes() {
    return referencedTypes;
  }

  /**
   * Specify the {@link DependencyRecorder} to be used for future traversals.
   * Specifying <code>null</code> means to stop recording dependencies.
   */
  public void setDependencyRecorder(DependencyRecorder dr) {
    if (dependencyRecorder != null && dr != null) {
      throw new IllegalArgumentException("Attempting to set multiple dependency recorders");
    }
    this.dependencyRecorder = dr;
  }

  public void setForPruning() {
    assert argsToRescueIfParameterRead == null;
    argsToRescueIfParameterRead = ArrayListMultimap.create();
  }

  /**
   * Traverse the program entry points, but don't traverse any runAsync
   * fragments.
   */
  public void traverseEntryMethods() {
    for (JMethod method : program.getEntryMethods()) {
      traverseFrom(method);
    }

    /*
     * All exported methods must be treated as entry points. We need to invent a way to
     * scope this down via flags or module properties.
     */
    List<JDeclaredType> declaredTypes = program.getDeclaredTypes();
    for (JDeclaredType type : declaredTypes) {
      // We rescue any JsType/JsFunction interfaces immediately. Although it is not precise, as
      // interfaces are mostly free, we are fine. This is simpler than tracking where the objects
      // may enter the system.
      // More appropriate solution is to track casts and JSNI methods (see
      // #canBeInstantiatedInJavaScript) but unfortunately casts are replaced at a later stage
      // that causes type and all calls to be pruned.
      if (type.canBeImplementedExternally()) {
        rescuer.rescue(type, true);
      }

      // first time through, record all exported methods
      for (JMethod method : type.getMethods()) {
        if (method.isJsInteropEntryPoint() || method.canBeImplementedExternally()) {
          // treat class as instantiated, since a ctor may be called from JS export
          rescuer.rescue(method.getEnclosingType(), true);
          traverseFrom(method);
        }
      }
      for (JField field : type.getFields()) {
        if (field.isJsInteropEntryPoint() || field.canBeImplementedExternally()) {
          rescuer.rescue(field.getEnclosingType(), true);
          rescuer.rescue(field);
        }
      }
    }

    for (JArrayType arrayType : program.getAllArrayTypes()) {
      if (arrayType.canBeImplementedExternally()) {
        rescuer.rescue(arrayType, true);
      }
    }

    if (program.getRunAsyncs().size() > 0) {
      /*
       * Explicitly rescue AsyncFragmentLoader.onLoad(). It is never explicitly
       * called anyway, until late code gen. Also, we want it in the initial
       * fragment so all other fragments can share the code.
       */
      traverseFrom(asyncFragmentOnLoad);
    }
  }

  public void traverseEverything() {
    traverseEntryMethods();
    traverseFromRunAsyncs();
    /*
     * Keep callback.onSuccess() from being pruned since we explicitly avoid
     * visiting it.
     */
    liveFieldsAndMethods.add(runAsyncOnSuccess);
  }

  /**
   * Assume <code>method</code> is live, and find out what else might execute.
   */
  public void traverseFrom(JMethod method) {
    rescuer.rescue(method);
  }

  /**
   * Assume <code>type</code> is instantiated, and find out what else will
   * execute as a result.
   */
  public void traverseFromInstantiationOf(JDeclaredType type) {
    rescuer.rescue(type, true);
  }

  public void traverseFromReferenceTo(JDeclaredType type) {
    rescuer.rescue(type, false);
  }

  /**
   * Traverse the fragment for a specific runAsync.
   */
  public void traverseFromRunAsync(JRunAsync runAsync) {
    runAsync.traverseOnSuccess(rescuer);
  }

  /**
   * Traverse the fragments for all runAsyncs.
   */
  public void traverseFromRunAsyncs() {
    for (JRunAsync runAsync : program.getRunAsyncs()) {
      traverseFromRunAsync(runAsync);
    }
  }
}
