/*
 * 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.JAbsentArrayDimension;
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.JInstanceOf;
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.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());
      } else if (x.getOp() == JBinaryOperator.ASG) {
        // Don't rescue variables that are merely assigned to and never read
        boolean doSkip = false;
        JExpression lhs = x.getLhs();
        if (lhs.hasSideEffects() || isVolatileField(lhs)) {
          /*
           * If the lhs has side effects, skipping it would lose the side
           * effect. If the lhs is volatile, also keep it. This behavior
           * provides a useful idiom for test cases to prevent code from being
           * pruned.
           */
        } else if (lhs instanceof JLocalRef) {
          // locals are ok to skip
          doSkip = true;
        } else if (lhs instanceof JParameterRef) {
          // parameters are ok to skip
          doSkip = true;
        } else if (lhs instanceof JFieldRef) {
          // fields must rescue the qualifier
          doSkip = true;
          JFieldRef fieldRef = (JFieldRef) lhs;
          JExpression instance = fieldRef.getInstance();
          if (instance != null) {
            accept(instance);
          }
        }

        if (doSkip) {
          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(JInstanceOf x, Context ctx) {
      JReferenceType targetType = x.getTestType();
      if (program.typeOracle.isJsType(targetType) || program.typeOracle.isJsFunction(targetType)) {
        // keep alive JsType used in instanceof so it is not pruned and re-written as null check.
        rescue(targetType, true);
      }
      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.isNative()) {
        // 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.dims != null) {
        // rescue my type and all the implicitly nested types (with fewer dims)
        int nDims = arrayType.getDims();
        JType leafType = arrayType.getLeafType();
        assert (newArray.dims.size() == nDims);
        for (int i = 0; i < nDims; ++i) {
          if (newArray.dims.get(i) instanceof JAbsentArrayDimension) {
            break;
          }
          rescue(program.getOrCreateArrayType(leafType, nDims - 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.isJavaLangString(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.isNative()) {
          // Returning from this method passes a value from JavaScript into Java.
          maybeRescueJavaScriptObjectPassingIntoJava(method.getType());
        }
        if (method.isExported() || method.isJsTypeMember() || method.isJsFunctionMethod()) {
          for (JParameter param : method.getParams()) {
            // Parameters in JsExport, JsType, JsFunction methods should not be pruned in order to
            // keep the API intact.
            rescue(param);
          }
        }
        rescueOverridingMethods(method);
        if (method == getClassMethod) {
          rescueClassLiteralsIfGetClassIsLive();
        }

        if (program.isJsTypePrototype(method.getEnclosingType())) {
          // for JsInterface Prototype methods, rescue all parameters
          // because these are stub methods and the parameters would get pruned ordinarily
          for (JParameter param : method.getParams()) {
            rescue(param);
          }
        }
        if (method.getSpecialization() != null) {
          rescue(method.getSpecialization().getTargetMethod());
        }
      }
    }

    private void maybeRescueJsTypeArray(JType type) {
      if (!(type instanceof JArrayType)) {
        return;
      }
      JArrayType arrayType = (JArrayType) type;
      if (program.typeOracle.isJsType(arrayType.getLeafType()) ||
          program.typeOracle.isJsFunction(arrayType.getLeafType())) {
        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 (!program.typeOracle.isJsType(type) && !program.typeOracle.isJsFunction(type)) {
        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.isJsTypeMember() || method.isJsFunctionMethod()) {
          rescue(method);
        }
      }
      for (JField field : declaredType.getFields()) {
        if (field.isJsTypeMember()) {
          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)
            // rescue any args of JsInterface Prototype methods
            || program.isJsTypePrototype(method.getEnclosingType())) {
          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("Object.toString");
        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() || type.isJsFunction() || type.isJsType()
        || 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.newHashSet();
  private Set<JReferenceType> instantiatedTypes = Sets.newHashSet();
  private Set<JNode> liveFieldsAndMethods = Sets.newHashSet();
  private Set<String> liveStrings = Sets.newHashSet();

  /**
   * 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;
    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);
    }
    getClassField = program.getIndexedField("Object.___clazz");
    getClassMethod = program.getIndexedMethod("Object.getClass");
    rescuer = new RescueVisitor();
  }

  public ControlFlowAnalyzer(JProgram program) {
    this.program = program;
    asyncFragmentOnLoad = program.getIndexedMethod("AsyncFragmentLoader.onLoad");
    runAsyncOnsuccess = program.getIndexedMethod("RunAsyncCallback.onSuccess");
    getClassField = program.getIndexedField("Object.___clazz");
    getClassMethod = program.getIndexedMethod("Object.getClass");
    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 instanceof JInterfaceType && (type.isJsType() || type.isJsFunction())) {
        rescuer.rescue(type, true);
      }

      // first time through, record all exported methods
      for (JMethod method : type.getMethods()) {
        if (method.isExported()) {
          // 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.isExported()) {
          rescuer.rescue(field.getEnclosingType(), true);
          rescuer.rescue(field);
        }
      }
    }

    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);
    }
  }
}
