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

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.impl.OptimizerStats;
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.JsBooleanLiteral;
import com.google.gwt.dev.js.ast.JsCase;
import com.google.gwt.dev.js.ast.JsConditional;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsDefault;
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.JsForIn;
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.JsModVisitor;
import com.google.gwt.dev.js.ast.JsName;
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.JsNullLiteral;
import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsParameter;
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.JsProgramFragment;
import com.google.gwt.dev.js.ast.JsRegExp;
import com.google.gwt.dev.js.ast.JsReturn;
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.JsSwitchMember;
import com.google.gwt.dev.js.ast.JsThisRef;
import com.google.gwt.dev.js.ast.JsVars;
import com.google.gwt.dev.js.ast.JsVars.JsVar;
import com.google.gwt.dev.js.ast.JsVisitor;
import com.google.gwt.dev.js.ast.JsWhile;
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 java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

/**
 * Perform inlining optimizations on the JavaScript AST.
 * 
 * TODO(bobv): remove anything that's duplicating work with {@link JsStaticEval}
 * migrate other stuff to that class perhaps.
 */
public class JsInliner {
  private static final String NAME = JsInliner.class.getSimpleName();

  /**
   * Determines if the evaluation of a JsNode may be affected by side effects.
   */
  private static class AffectedBySideEffectsVisitor extends JsVisitor {
    private boolean affectedBySideEffects;
    private final JsProgram program;
    private final JsScope safeScope;

    public AffectedBySideEffectsVisitor(JsProgram program, JsScope safeScope) {
      this.program = program;
      this.safeScope = safeScope;
    }

    public boolean affectedBySideEffects() {
      return affectedBySideEffects;
    }

    @Override
    public void endVisit(JsArrayLiteral x, JsContext<JsExpression> ctx) {
      affectedBySideEffects = true;
    }

    @Override
    public void endVisit(JsFunction x, JsContext<JsExpression> ctx) {
      affectedBySideEffects = true;
    }

    @Override
    public void endVisit(JsInvocation x, JsContext<JsExpression> ctx) {
      /*
       * We could make this more accurate by analyzing the function that's being
       * executed, but we'll bank on subsequent passes inlining simple function
       * invocations.
       */
      affectedBySideEffects = true;
    }

    @Override
    public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
      if (x.getQualifier() == null && x.getName() != null) {
        // Special case the undefined literal.
        if (x.getName() == program.getUndefinedLiteral().getName()) {
          return;
        }
        // Locals in a safe scope are unaffected.
        if (x.getName().getEnclosing() == safeScope) {
          return;
        }
      }

      /*
       * We can make this more accurate if we had single-assignment information
       * (e.g. static final fields).
       */
      affectedBySideEffects = true;
    }

    @Override
    public void endVisit(JsObjectLiteral x, JsContext<JsExpression> ctx) {
      affectedBySideEffects = true;
    }
  }

  /**
   * Make comma binary operations left-nested since commas are naturally
   * left-associative. We will define the comma-normal form such that a comma
   * expression should never have a comma expression as its RHS and contains no
   * side-effect-free expressions save for the outer, right-hand expression.
   * This form has a nice side-effect of minimizing the number of generated
   * parentheses.
   * 
   * <pre>
   * (X, b) is unchanged
   * (X, (b, c) becomes ((X, b), c); b is guaranteed to have a side-effect
   * (X, ((b, c), d)) becomes (((X, b), c), d)
   * </pre>
   */
  private static class CommaNormalizer extends JsModVisitor {

    /**
     * Returns an expression as a JsBinaryOperation if it is a comma expression.
     */
    private static JsBinaryOperation isComma(JsExpression x) {
      if (!(x instanceof JsBinaryOperation)) {
        return null;
      }
      JsBinaryOperation op = (JsBinaryOperation) x;

      return op.getOperator().equals(JsBinaryOperator.COMMA) ? op : null;
    }

    private final List<JsName> localVariableNames;

    public CommaNormalizer(List<JsName> localVariableNames) {
      this.localVariableNames = localVariableNames;
    }

    @Override
    public void endVisit(JsBinaryOperation x, JsContext<JsExpression> ctx) {
      if (isComma(x) == null) {
        return;
      }

      // If (X, a) and X has no side effects, replace with a
      if (!x.getArg1().hasSideEffects()) {
        ctx.replaceMe(x.getArg2());
        return;
      }

      JsBinaryOperation toUpdate = isComma(x.getArg2());
      if (toUpdate == null) {
        /*
         * We have a JsBinaryOperation that's structurally normal: (X, a). Now
         * it may be the case that the inner expression X is a comma expression
         * (Y, b). If b creates no side-effects, we can remove it, leaving (Y,
         * a) as the expression.
         */
        JsBinaryOperation inner = isComma(x.getArg1());
        if (inner != null && !inner.getArg2().hasSideEffects()) {
          x.setArg1(inner.getArg1());
          didChange = true;
        }

        /*
         * Eliminate the pattern (localVar = expr, localVar). This tends to
         * occur when a method interacted with pruned fields or had statements
         * removed.
         */
        JsName assignmentRef = null;
        JsExpression expr = null;
        JsName returnRef = null;

        if (x.getArg1() instanceof JsBinaryOperation) {
          JsBinaryOperation op = (JsBinaryOperation) x.getArg1();
          if (op.getOperator() == JsBinaryOperator.ASG
              && op.getArg1() instanceof JsNameRef) {
            JsNameRef nameRef = (JsNameRef) op.getArg1();
            if (nameRef.getQualifier() == null) {
              assignmentRef = nameRef.getName();
              expr = op.getArg2();
            }
          }
        }

        if (x.getArg2() instanceof JsNameRef) {
          JsNameRef nameRef = (JsNameRef) x.getArg2();
          if (nameRef.getQualifier() == null) {
            returnRef = nameRef.getName();
          }
        }

        if (assignmentRef != null && assignmentRef.equals(returnRef)
            && localVariableNames.contains(assignmentRef)) {
          assert expr != null;
          localVariableNames.remove(assignmentRef);
          ctx.replaceMe(expr);
        }
        return;
      }

      // Find the left-most, nested comma expression
      while (isComma(toUpdate.getArg1()) != null) {
        toUpdate = (JsBinaryOperation) toUpdate.getArg1();
      }

      /*
       * Create a new comma expression with the original LHS and the LHS of the
       * nested comma expression.
       */
      JsBinaryOperation newOp = new JsBinaryOperation(
          x.getSourceInfo().makeChild(CommaNormalizer.class,
              "Simplifying comma expression"), JsBinaryOperator.COMMA);
      newOp.setArg1(x.getArg1());
      newOp.setArg2(toUpdate.getArg1());

      // Set the LHS of the nested comma expression to the new comma expression
      toUpdate.setArg1(newOp);

      // Replace the original node with its updated RHS
      ctx.replaceMe(x.getArg2());
    }
  }

  /**
   * Provides a relative metric by which the syntactic complexity of a
   * JsExpression can be gauged.
   */
  private static class ComplexityEstimator extends JsVisitor {
    /**
     * The current measure of complexity. This measures the number of
     * expressions that have been encountered by the visitor.
     */
    private int complexity = 0;

    @Override
    public void endVisit(JsArrayAccess x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsArrayLiteral x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsBinaryOperation x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsBooleanLiteral x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsConditional x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsFunction x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsInvocation x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsNew x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsNullLiteral x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsNumberLiteral x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsObjectLiteral x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsPostfixOperation x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsPrefixOperation x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsRegExp x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsStringLiteral x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    @Override
    public void endVisit(JsThisRef x, JsContext<JsExpression> ctx) {
      complexity++;
    }

    public int getComplexity() {
      return complexity;
    }
  }

  /**
   * This is used to clean up duplication invocations of functions that should
   * only be executed once, such as clinit functions. Whenever there is a
   * possible branch in program flow, the remover will create a new instance of
   * itself to handle the possible branches.
   * 
   * We don't look at combining branch choices. This will not produce the most
   * efficient elimination of duplicated calls, but it handles the general case
   * and is simple to verify.
   */
  private static class DuplicateXORemover extends JsModVisitor {
    /*
     * TODO: Most of the special casing below can be removed if complex
     * statements always use blocks, rather than plain statements.
     */

    /**
     * Retains the the functions that we know have been called.
     */
    private final Set<JsFunction> called;
    private final JsProgram program;

    public DuplicateXORemover(JsProgram program) {
      this.program = program;
      called = new HashSet<JsFunction>();
    }

    public DuplicateXORemover(JsProgram program, Set<JsFunction> alreadyCalled) {
      this.program = program;
      called = new HashSet<JsFunction>(alreadyCalled);
    }

    /**
     * Look for comma expressions that contain duplicate calls and handle the
     * conditional-evaluation case of logical and/or operations.
     */
    @Override
    public boolean visit(JsBinaryOperation x, JsContext<JsExpression> ctx) {
      if (x.getOperator() == JsBinaryOperator.COMMA) {

        boolean left = isDuplicateCall(x.getArg1());
        boolean right = isDuplicateCall(x.getArg2());

        if (left && right) {
          /*
           * (clinit(), clinit()) --> delete or null.
           * 
           * This construct is very unlikely since the InliningVisitor builds
           * the comma expressions in a right-nested manner.
           */
          if (ctx.canRemove()) {
            ctx.removeMe();
            return false;
          } else {
            // The return value from an XO function is never used
            ctx.replaceMe(program.getNullLiteral());
            return false;
          }

        } else if (left) {
          // (clinit(), xyz) --> xyz
          // This is the common case
          ctx.replaceMe(accept(x.getArg2()));
          return false;

        } else if (right) {
          // (xyz, clinit()) --> xyz
          // Possible if a clinit() were the last element
          ctx.replaceMe(accept(x.getArg1()));
          return false;
        }

      } else if (x.getOperator().equals(JsBinaryOperator.AND)
          || x.getOperator().equals(JsBinaryOperator.OR)) {
        x.setArg1(accept(x.getArg1()));
        // Possibility of conditional evaluation of second parameter
        x.setArg2(branch(x.getArg2()));
        return false;
      }

      return true;
    }

    /**
     * Most of the branching statements (as well as JsFunctions) will visit with
     * a JsBlock, so we don't need to explicitly enumerate all JsStatement
     * subtypes.
     */
    @Override
    public boolean visit(JsBlock x, JsContext<JsStatement> ctx) {
      branch(x.getStatements());
      return false;
    }

    @Override
    public boolean visit(JsCase x, JsContext<JsSwitchMember> ctx) {
      x.setCaseExpr(accept(x.getCaseExpr()));
      branch(x.getStmts());
      return false;
    }

    @Override
    public boolean visit(JsConditional x, JsContext<JsExpression> ctx) {
      x.setTestExpression(accept(x.getTestExpression()));
      x.setThenExpression(branch(x.getThenExpression()));
      x.setElseExpression(branch(x.getElseExpression()));
      return false;
    }

    @Override
    public boolean visit(JsDefault x, JsContext<JsSwitchMember> ctx) {
      branch(x.getStmts());
      return false;
    }

    @Override
    public boolean visit(JsExprStmt x, JsContext<JsStatement> ctx) {
      if (isDuplicateCall(x.getExpression())) {
        if (ctx.canRemove()) {
          ctx.removeMe();
        } else {
          ctx.replaceMe(program.getEmptyStmt());
        }
        return false;

      } else {
        return true;
      }
    }

    @Override
    public boolean visit(JsFor x, JsContext<JsStatement> ctx) {
      // The JsFor may have an expression xor a variable declaration.
      if (x.getInitExpr() != null) {
        x.setInitExpr(accept(x.getInitExpr()));
      } else if (x.getInitVars() != null) {
        x.setInitVars(accept(x.getInitVars()));
      }

      // The condition is optional
      if (x.getCondition() != null) {
        x.setCondition(accept(x.getCondition()));
      }

      // The increment expression is optional
      if (x.getIncrExpr() != null) {
        x.setIncrExpr(branch(x.getIncrExpr()));
      }

      // The body is not guaranteed to be a JsBlock
      x.setBody(branch(x.getBody()));
      return false;
    }

    @Override
    public boolean visit(JsForIn x, JsContext<JsStatement> ctx) {
      if (x.getIterExpr() != null) {
        x.setIterExpr(accept(x.getIterExpr()));
      }

      x.setObjExpr(accept(x.getObjExpr()));

      // The body is not guaranteed to be a JsBlock
      x.setBody(branch(x.getBody()));
      return false;
    }

    @Override
    public boolean visit(JsIf x, JsContext<JsStatement> ctx) {
      x.setIfExpr(accept(x.getIfExpr()));

      x.setThenStmt(branch(x.getThenStmt()));
      if (x.getElseStmt() != null) {
        x.setElseStmt(branch(x.getElseStmt()));
      }

      return false;
    }

    /**
     * Possibly record that we've seen a call in the current context.
     */
    @Override
    public boolean visit(JsInvocation x, JsContext<JsExpression> ctx) {
      JsFunction func = isExecuteOnce(x);
      while (func != null) {
        called.add(func);
        func = func.getImpliedExecute();
      }
      return true;
    }

    @Override
    public boolean visit(JsWhile x, JsContext<JsStatement> ctx) {
      x.setCondition(accept(x.getCondition()));

      // The body is not guaranteed to be a JsBlock
      x.setBody(branch(x.getBody()));
      return false;
    }

    private <T extends JsNode<T>> void branch(List<T> x) {
      DuplicateXORemover dup = new DuplicateXORemover(program, called);
      dup.acceptWithInsertRemove(x);
      didChange |= dup.didChange();
    }

    private <T extends JsNode<T>> T branch(T x) {
      DuplicateXORemover dup = new DuplicateXORemover(program, called);
      T toReturn = dup.accept(x);

      if ((toReturn != x) && !dup.didChange()) {
        throw new InternalCompilerException(
            "node replacement should imply didChange()");
      }

      didChange |= dup.didChange();
      return toReturn;
    }

    private boolean isDuplicateCall(JsExpression x) {
      if (!(x instanceof JsInvocation)) {
        return false;
      }

      JsFunction func = isExecuteOnce((JsInvocation) x);
      return (func != null && called.contains(func));
    }
  }

  /**
   * Determines that a list of names is guaranteed to be evaluated in a
   * particular order. Also ensures that all names are evaluated before any
   * invocations occur.
   */
  private static class EvaluationOrderVisitor extends JsVisitor {
    public static final JsName THIS_NAME = (new JsScope("fake scope") {
    }).declareName("this");

    private boolean maintainsOrder = true;
    private final List<JsName> toEvaluate;
    private final List<JsName> unevaluated;

    public EvaluationOrderVisitor(List<JsName> toEvaluate) {
      this.toEvaluate = toEvaluate;
      this.unevaluated = new ArrayList<JsName>(toEvaluate);
    }

    @Override
    public void endVisit(JsBinaryOperation x, JsContext<JsExpression> ctx) {
      JsBinaryOperator op = x.getOperator();

      /*
       * We don't care about the left-hand expression, because it is guaranteed
       * to be evaluated.
       */
      boolean rightStrict = refersToRequiredName(x.getArg2());
      boolean conditionalEvaluation = JsBinaryOperator.AND.equals(op)
          || JsBinaryOperator.OR.equals(op);

      if (rightStrict && conditionalEvaluation) {
        maintainsOrder = false;
      }
    }

    /**
     * If the condition would cause conditional evaluation of strict parameters,
     * don't allow inlining.
     */
    @Override
    public void endVisit(JsConditional x, JsContext<JsExpression> ctx) {
      boolean thenStrict = refersToRequiredName(x.getThenExpression());
      boolean elseStrict = refersToRequiredName(x.getElseExpression());

      if (thenStrict || elseStrict) {
        maintainsOrder = false;
      }
    }

    /**
     * The statement declares a function closure. This makes actual evaluation
     * order of the parameters difficult or impossible to determine, so we'll
     * just ignore them.
     */
    @Override
    public void endVisit(JsFunction x, JsContext<JsExpression> ctx) {
      maintainsOrder = false;
    }

    /**
     * The innermost invocation we see must consume all presently unevaluated
     * parameters to ensure that an exception does not prevent their evaluation.
     * 
     * In the case of a nested invocation, such as
     * <code>F(r1, r2, G(r3, r4), f1);</code> the evaluation order is guaranteed
     * to be maintained, provided that no required parameters occur after the
     * nested invocation.
     */
    @Override
    public void endVisit(JsInvocation x, JsContext<JsExpression> ctx) {
      /*
       * The check for isExecuteOnce() is potentially incorrect here, however
       * the original Java semantics of the clinit would have made the code
       * incorrect anyway.
       */
      if ((isExecuteOnce(x) == null) && unevaluated.size() > 0) {
        maintainsOrder = false;
      }
    }
    
    @Override
    public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
      checkName(x.getName());
    }

    @Override
    public void endVisit(JsNew x, JsContext<JsExpression> ctx) {
      /*
       * Unless all arguments have already been evaluated, assume
       * that invoking the new expression might interfere with
       * the evaluation of the argument.
       *
       * It would be possible to allow this if the invoked function
       * either does nothing or does nothing that affects the 
       * remaining arguments.  However, currently there is no
       * analysis of the invoked function.
       */
      if (unevaluated.size() > 0) {
        maintainsOrder = false;
      }
    }

    @Override
    public void endVisit(JsThisRef x, JsContext<JsExpression> ctx) {
      checkName(THIS_NAME);
    }

    public boolean maintainsOrder() {
      return maintainsOrder && unevaluated.size() == 0;
    }

    private void checkName(JsName name) {
      if (!toEvaluate.contains(name)) {
        return;
      }

      if (unevaluated.size() == 0 || !unevaluated.remove(0).equals(name)) {
        maintainsOrder = false;
      }
    }

    /**
     * Determine if an expression contains a reference to a strict parameter.
     */
    private boolean refersToRequiredName(JsExpression e) {
      RefersToNameVisitor v = new RefersToNameVisitor(toEvaluate);
      v.accept(e);
      return v.refersToName();
    }
  }

  /**
   * Collect all of the idents used in an AST node. The collector can be
   * configured to collect idents from qualified xor unqualified JsNameRefs.
   */
  private static class IdentCollector extends JsVisitor {
    private final boolean collectQualified;
    private final Set<String> idents = new HashSet<String>();

    public IdentCollector(boolean collectQualified) {
      this.collectQualified = collectQualified;
    }

    @Override
    public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
      boolean hasQualifier = x.getQualifier() != null;

      if ((collectQualified && !hasQualifier)
          || (!collectQualified && hasQualifier)) {
        return;
      }

      assert x.getIdent() != null;
      idents.add(x.getIdent());
    }

    public Set<String> getIdents() {
      return idents;
    }
  }

  /**
   * This class looks for function invocations that can be inlined and performs
   * the replacement by replacing the JsInvocation with a comma expression
   * consisting of the expressions evaluated by the target function. A second
   * step may convert the expressions in the comma expression back to multiple
   * statements if the context of the invocation would allow this.
   */
  private static class InliningVisitor extends JsModVisitor {
    private final Set<JsFunction> blacklist = new HashSet<JsFunction>();
    /**
     * This reflects the functions that are currently being inlined to prevent
     * infinite expansion.
     */
    private final Stack<JsFunction> inlining = new Stack<JsFunction>();
    /**
     * This reflects which function the visitor is currently visiting.
     */
    private final Stack<JsFunction> functionStack = new Stack<JsFunction>();
    private final InvocationCountingVisitor invocationCountingVisitor = new InvocationCountingVisitor();
    private final Stack<List<JsName>> newLocalVariableStack = new Stack<List<JsName>>();
    private final JsProgram program;

    /**
     * A map containing the next integer to try as an identifier suffix for a
     * given JsScope.
     */
    private IdentityHashMap<JsScope, HashMap<String, Integer>> startIdentForScope = new IdentityHashMap<JsScope, HashMap<String, Integer>>();

    /**
     * Not a stack because program fragments aren't nested.
     */
    private JsFunction programFunction;

    public InliningVisitor(JsProgram program) {
      this.program = program;
      invocationCountingVisitor.accept(program);
    }

    /**
     * Add to the list of JsFunctions that should not be inlined, regardless of
     * whether or not they would normally be inlinable.
     */
    public void blacklist(Collection<JsFunction> functions) {
      blacklist.addAll(functions);
    }

    /**
     * This normalizes the comma expressions into multiple statements and
     * removes statements with no side-effects.
     */
    @Override
    public void endVisit(JsExprStmt x, JsContext<JsStatement> ctx) {
      JsExpression e = x.getExpression();

      // We will occasionally create JsExprStmts that have no side-effects.
      if (ctx.canRemove() && !x.getExpression().hasSideEffects()) {
        ctx.removeMe();
        return;
      }

      List<JsExprStmt> statements = new ArrayList<JsExprStmt>();

      /*
       * Assemble the expressions back into a list of JsExprStmts. We will
       * iteratively disassemble the nested comma expressions, stopping when the
       * LHS is not a comma expression.
       */
      while (e instanceof JsBinaryOperation) {
        JsBinaryOperation op = (JsBinaryOperation) e;

        if (!op.getOperator().equals(JsBinaryOperator.COMMA)) {
          break;
        }

        /*
         * We can ignore intermediate expressions as long as they have no
         * side-effects.
         */
        if (op.getArg2().hasSideEffects()) {
          statements.add(0, op.getArg2().makeStmt());
        }

        e = op.getArg1();
      }

      /*
       * We know the return value from the original invocation was ignored, so
       * it may be possible to ignore the final expressions as long as it has no
       * side-effects.
       */
      if (e.hasSideEffects()) {
        statements.add(0, e.makeStmt());
      }

      if (statements.size() == 0) {
        // The expression contained no side effects at all.
        if (ctx.canRemove()) {
          ctx.removeMe();
        } else {
          ctx.replaceMe(program.getEmptyStmt());
        }

      } else if (x.getExpression() != statements.get(0).getExpression()) {
        // Something has changed

        if (!ctx.canInsert()) {
          /*
           * This indicates that the function was attached to a clause of a
           * control function and not into an existing block. We'll replace the
           * single JsExprStmt with a JsBlock that contains all of the
           * statements.
           */
          JsBlock b = new JsBlock(x.getSourceInfo().makeChild(
              InliningVisitor.class, "Block required for control function"));
          b.getStatements().addAll(statements);
          ctx.replaceMe(b);
          return;

        } else {
          // Insert the new statements into the original context
          for (JsStatement s : statements) {
            ctx.insertBefore(s);
          }
          ctx.removeMe();
        }
      }
    }

    @Override
    public void endVisit(JsFunction x, JsContext<JsExpression> ctx) {
      if (!functionStack.pop().equals(x)) {
        throw new InternalCompilerException("Unexpected function popped");
      }

      JsBlock body = x.getBody();
      List<JsName> newLocalVariables = newLocalVariableStack.pop();

      addVars(x, body, newLocalVariables);
    }

    @Override
    public void endVisit(JsInvocation x, JsContext<JsExpression> ctx) {
      if (functionStack.isEmpty()) {
        return;
      }
      JsFunction callerFunction = functionStack.peek();

      /*
       * We only want to look at invocations of things that we statically know
       * to be functions. Otherwise, we can't know what statements the
       * invocation would actually invoke. The static reference would be null
       * when trying operate on references to external functions, or functions
       * as arguments to another function.
       */
      JsFunction invokedFunction = isFunction(x.getQualifier());
      if (invokedFunction == null) {
        return;
      }

      /*
       * Don't inline huge functions into huge multi-expressions. Some JS
       * engines will blow up.
       */
      if (invokedFunction.getBody().getStatements().size() > 50) {
        return;
      }

      // Don't inline blacklisted functions
      if (blacklist.contains(invokedFunction)) {
        return;
      }

      /*
       * The current function has been mutated so as to be self-recursive. Ban
       * it from any future inlining to prevent infinite expansion.
       */
      if (invokedFunction == callerFunction) {
        blacklist.add(invokedFunction);
        return;
      }

      /*
       * We are already in the middle of attempting to inline a call to this
       * function. This check prevents infinite expansion across
       * mutually-recursive, inlinable functions. Any invocation skipped by this
       * logic will be re-visited in the <code>op = accept(op)</code> call in
       * the outermost JsInvocation.
       */
      if (inlining.contains(invokedFunction)) {
        return;
      }

      inlining.push(invokedFunction);
      x = tryToUnravelExplicitCall(x);
      JsExpression op = process(x, callerFunction, invokedFunction);

      if (x != op) {
        /*
         * See if any further inlining can be performed in the current context.
         * By attempting to maximize the level of inlining now, we can reduce
         * the total number of passes required to finalize the AST.
         */
        op = accept(op);
        ctx.replaceMe(op);
      }

      if (inlining.pop() != invokedFunction) {
        throw new RuntimeException("Unexpected function popped");
      }
    }

    @Override
    public void endVisit(JsProgramFragment x, JsContext<JsProgramFragment> ctx) {
      if (!functionStack.pop().equals(programFunction)) {
        throw new InternalCompilerException("Unexpected function popped");
      }

      assert programFunction.getBody().getStatements().size() == 0 : "Should not have moved statements into program";

      List<JsName> newLocalVariables = newLocalVariableStack.pop();
      assert newLocalVariables.size() == 0 : "Should not have tried to create variables in program";
    }

    @Override
    public boolean visit(JsExprStmt x, JsContext<JsStatement> ctx) {
      if (functionStack.peek() == programFunction) {
        /* Don't inline top-level invocations. */
        if (x.getExpression() instanceof JsInvocation) {
          return false;
        }
      }
      return true;
    }

    @Override
    public boolean visit(JsFunction x, JsContext<JsExpression> ctx) {
      functionStack.push(x);
      newLocalVariableStack.push(new ArrayList<JsName>());
      return true;
    }

    /**
     * Create a synthetic context to attempt to simplify statements in the
     * top-level of the program.
     */
    @Override
    public boolean visit(JsProgramFragment x, JsContext<JsProgramFragment> ctx) {
      programFunction = new JsFunction(program.getSourceInfo(),
          program.getScope());
      programFunction.setBody(new JsBlock(x.getSourceInfo()));
      functionStack.push(programFunction);
      newLocalVariableStack.push(new ArrayList<JsName>());
      return true;
    }

    private void addVars(HasSourceInfo x, JsBlock body,
        List<JsName> newLocalVariables) {
      // Nothing to do
      if (newLocalVariables.isEmpty()) {
        return;
      }

      List<JsStatement> statements = body.getStatements();

      // The body can't be empty if we have local variables to create
      assert !statements.isEmpty();

      // Find or create the JsVars as the first statement
      SourceInfo sourceInfo = x.getSourceInfo().makeChild(
          InliningVisitor.class, "Synthetic locals");
      JsVars vars;
      if (statements.get(0) instanceof JsVars) {
        vars = (JsVars) statements.get(0);
      } else {
        vars = new JsVars(sourceInfo);
        statements.add(0, vars);
      }

      // Add all variables
      for (JsName name : newLocalVariables) {
        vars.add(new JsVar(sourceInfo, name));
      }
    }

    private boolean isInvokedMoreThanOnce(JsFunction f) {
      Integer count = invocationCountingVisitor.invocationCount(f);
      return count == null || count > 1;
    }

    /**
     * Determine if <code>invokedFunction</code> can be inlined into
     * <code>callerFunction</code> at callsite <code>x</code>.
     * 
     * @return An expression equivalent to <code>x</code>
     */
    private JsExpression process(JsInvocation x, JsFunction callerFunction,
        JsFunction invokedFunction) {
      List<JsStatement> statements;
      if (invokedFunction.getBody() != null) {
        statements = new ArrayList<JsStatement>(
            invokedFunction.getBody().getStatements());
      } else {
        /*
         * Will see this with certain classes whose clinits are folded into the
         * main JsProgram body.
         */
        statements = Collections.emptyList();
      }

      List<JsExpression> hoisted = new ArrayList<JsExpression>(
          statements.size());
      JsExpression thisExpr = ((JsNameRef) x.getQualifier()).getQualifier();
      List<JsName> localVariableNames = new ArrayList<JsName>();
      boolean sawReturnStatement = false;

      for (JsStatement statement : statements) {
        if (sawReturnStatement) {
          /*
           * We've already seen a return statement, but there are still more
           * statements. The target is unsafe to inline, so bail. Note: in most
           * cases JsStaticEval will have removed any statements following a
           * return statement.
           * 
           * The reason we have to bail is that the return statement's
           * expression MUST be the last thing evaluated.
           * 
           * TODO(bobv): maybe it could still be inlined with smart
           * transformation?
           */
          return x;
        }

        /*
         * Create replacement expressions to use in place of the original
         * statements. It is important that the replacement is newly-minted and
         * therefore not referenced by any other AST nodes. Consider the case of
         * a common, delegating function. If the hoisted expressions were not
         * distinct objects, it would not be possible to substitute different
         * JsNameRefs at different call sites.
         */
        JsExpression h = hoistedExpression(program, statement,
            localVariableNames);
        if (h == null) {
          return x;
        }

        if (isReturnStatement(statement)) {
          sawReturnStatement = true;
          hoisted.add(h);
        } else if (hasSideEffects(Collections.singletonList(h))) {
          hoisted.add(h);
        }
      }

      /*
       * If the inlined method has no return statement, synthesize an undefined
       * reference. It will be reclaimed if the method call is from a
       * JsExprStmt.
       */
      if (!sawReturnStatement) {
        hoisted.add(program.getUndefinedLiteral());
      }

      assert (hoisted.size() > 0);

      /*
       * Build up the new comma expression from right-to-left; building the
       * rightmost comma expressions first. Bootstrapping with i.previous()
       * ensures that this logic will function correctly in the case of a single
       * expression.
       */
      SourceInfo sourceInfo = x.getSourceInfo().makeChild(
          InliningVisitor.class, "Inlined invocation");
      ListIterator<JsExpression> i = hoisted.listIterator(hoisted.size());
      JsExpression op = i.previous();
      while (i.hasPrevious()) {
        JsBinaryOperation outerOp = new JsBinaryOperation(sourceInfo,
            JsBinaryOperator.COMMA);
        outerOp.setArg1(i.previous());
        outerOp.setArg2(op);
        op = outerOp;
      }

      // Confirm that the expression conforms to the desired heuristics
      if (!isInlinable(program, callerFunction, invokedFunction, thisExpr,
          x.getArguments(), op)) {
        return x;
      }

      // Perform the name replacement
      NameRefReplacerVisitor v = new NameRefReplacerVisitor(thisExpr,
          x.getArguments(), invokedFunction.getParameters());
      for (ListIterator<JsName> nameIterator = localVariableNames.listIterator(); nameIterator.hasNext();) {
        JsName name = nameIterator.next();

        /*
         * Find an unused identifier in the caller's scope. It's possible that
         * the same function has been inlined in multiple places within the
         * function so we'll use a counter for disambiguation.
         */
        String ident;
        String base = invokedFunction.getName() + "_" + name.getIdent();
        JsScope scope = callerFunction.getScope();
        HashMap<String, Integer> startIdent = startIdentForScope.get(scope);
        if (startIdent == null) {
          startIdent = new HashMap<String, Integer>();
          startIdentForScope.put(scope, startIdent);
        }

        Integer s = startIdent.get(base);
        int suffix = (s == null) ? 0 : s.intValue();
        do {
          ident = base + "_" + suffix++;
        } while (scope.findExistingName(ident) != null);
        startIdent.put(base, suffix);

        JsName newName = scope.declareName(ident, name.getShortIdent());
        v.setReplacementName(name, newName);
        nameIterator.set(newName);
      }
      op = v.accept(op);

      // Normalize any nested comma expressions that we may have generated.
      op = (new CommaNormalizer(localVariableNames)).accept(op);

      /*
       * Compare the relative complexity of the original invocation versus the
       * inlined form.
       */
      int originalComplexity = complexity(x);
      int inlinedComplexity = complexity(op);
      double ratio = ((double) inlinedComplexity) / originalComplexity;
      if (ratio > MAX_COMPLEXITY_INCREASE
          && isInvokedMoreThanOnce(invokedFunction)) {
        return x;
      }

      if (callerFunction == programFunction && localVariableNames.size() > 0) {
        // Don't add additional variables to the top-level program.
        return x;
      }

      // We've committed to the inlining, ensure the vars are created
      newLocalVariableStack.peek().addAll(localVariableNames);

      // update invocation counts according to this inlining
      invocationCountingVisitor.removeCountsFor(x);
      invocationCountingVisitor.accept(op);
      return op;
    }
  }

  /**
   * Counts the number of times a function is invoked. Functions that only have
   * a single call site in the whole program are inlined, regardless of
   * complexity.
   */
  private static class InvocationCountingVisitor extends JsVisitor {
    private boolean removingCounts = false;
    private final Map<JsFunction, Integer> invocationCount = new IdentityHashMap<JsFunction, Integer>();

    @Override
    public void endVisit(JsInvocation x, JsContext<JsExpression> ctx) {
      checkFunctionCall(x.getQualifier());
    }

    @Override
    public void endVisit(JsNew x, JsContext<JsExpression> ctx) {
      checkFunctionCall(x.getConstructorExpression());
    }

    public Integer invocationCount(JsFunction f) {
      return invocationCount.get(f);
    }

    /**
     * Like accept(), but remove counts for all invocations in expr.
     */
    public void removeCountsFor(JsExpression expr) {
      assert (!removingCounts);
      removingCounts = true;
      accept(expr);
      removingCounts = false;
    }

    private void checkFunctionCall(JsExpression qualifier) {
      JsFunction function = isFunction(qualifier);
      if (function != null) {
        Integer count = invocationCount.get(function);
        if (count == null) {
          assert (!removingCounts);
          count = 1;
        } else {
          if (removingCounts) {
            count -= 1;
          } else {
            count += 1;
          }
        }
        invocationCount.put(function, count);
      }
    }
  }

  /**
   * Replace references to JsNames with the inlined JsExpression.
   */
  private static class NameRefReplacerVisitor extends JsModVisitor {
    /**
     * Set up a map to record name replacements to perform.
     */
    final Map<JsName, JsName> nameReplacements = new IdentityHashMap<JsName, JsName>();

    /**
     * Set up a map of parameter names back to the expressions that will be
     * passed in from the outer call site.
     */
    final Map<JsName, JsExpression> paramsToArgsMap = new IdentityHashMap<JsName, JsExpression>();

    /**
     * A replacement expression for this references.
     */
    private JsExpression thisExpr;

    public NameRefReplacerVisitor(JsExpression thisExpr,
        List<JsExpression> arguments, List<JsParameter> parameters) {
      this.thisExpr = thisExpr;
      if (parameters.size() != arguments.size()) {
        // This shouldn't happen if the cloned JsInvocation has been properly
        // configured
        throw new InternalCompilerException(
            "Mismatch on parameters and arguments");
      }

      for (int i = 0; i < parameters.size(); i++) {
        JsParameter p = parameters.get(i);
        JsExpression e = arguments.get(i);
        paramsToArgsMap.put(p.getName(), e);
      }
    }

    /**
     * Replace JsNameRefs that refer to parameters with the expression passed
     * into the function invocation.
     */
    @Override
    public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
      if (x.getQualifier() != null) {
        return;
      }

      JsExpression replacement = tryGetReplacementExpression(
          x.getSourceInfo().makeChild(NameRefReplacerVisitor.class,
              "Inlined expression"), x.getName());

      if (replacement != null) {
        ctx.replaceMe(replacement);
      }
    }

    @Override
    public void endVisit(JsThisRef x, JsContext<JsExpression> ctx) {
      assert thisExpr != null;
      ctx.replaceMe(thisExpr);
    }

    /**
     * Set a replacement JsName for all references to a JsName.
     * 
     * @param name the name to replace
     * @param newName the new name that should be used in place of references to
     *          <code>name</code>
     * @return the previous JsName the name would have been replaced with or
     *         <code>null</code> if one was not previously set
     */
    public JsName setReplacementName(JsName name, JsName newName) {
      return nameReplacements.put(name, newName);
    }

    /**
     * Determine the replacement expression to use in place of a reference to a
     * given name. Returns <code>null</code> if no replacement has been set for
     * the name.
     */
    private JsExpression tryGetReplacementExpression(SourceInfo sourceInfo,
        JsName name) {
      if (paramsToArgsMap.containsKey(name)) {
        /*
         * TODO if we ever allow mutable JsExpression types to be considered
         * always flexible, then it would be necessary to clone the expression.
         */
        return paramsToArgsMap.get(name);

      } else if (nameReplacements.containsKey(name)) {
        return nameReplacements.get(name).makeRef(sourceInfo);

      } else {
        return null;
      }
    }
  }

  /**
   * Detects function declarations.
   */
  private static class NestedFunctionVisitor extends JsVisitor {

    private boolean containsNestedFunctions = false;

    public boolean containsNestedFunctions() {
      return containsNestedFunctions;
    }

    @Override
    public void endVisit(JsFunction x, JsContext<JsExpression> ctx) {
      containsNestedFunctions = true;
    }
  }

  /**
   * Detects uses of parameters that would produce incorrect results if inlined.
   * Generally speaking, we disallow the use of parameters as lvalues. Also
   * detects trying to inline a method which references 'this' where the call
   * site has no qualifier.
   */
  private static class ParameterUsageVisitor extends JsVisitor {
    private final boolean hasThisExpr;
    private final Set<JsName> parameterNames;
    private boolean violation = false;

    public ParameterUsageVisitor(boolean hasThisExpr, Set<JsName> parameterNames) {
      this.hasThisExpr = hasThisExpr;
      this.parameterNames = parameterNames;
    }

    @Override
    public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
      if (ctx.isLvalue() && isParameter(x)) {
        violation = true;
      }
    }

    @Override
    public void endVisit(JsThisRef x, JsContext<JsExpression> ctx) {
      if (!hasThisExpr) {
        violation = true;
      }
    }

    public boolean hasViolation() {
      return violation;
    }

    /**
     * Determine if a JsExpression is a JsNameRef that refers to a parameter.
     */
    private boolean isParameter(JsNameRef ref) {
      if (ref.getQualifier() != null) {
        return false;
      }

      JsName name = ref.getName();
      return parameterNames.contains(name);
    }
  }

  /**
   * Collect self-recursive functions. This visitor does not look for
   * mutually-recursive functions because inlining one of the functions into the
   * other would make the single resultant function self-recursive and not
   * eligible for inlining in a subsequent pass.
   */
  private static class RecursionCollector extends JsVisitor {
    private final Stack<JsFunction> functionStack = new Stack<JsFunction>();
    private final Set<JsFunction> recursive = new HashSet<JsFunction>();

    @Override
    public void endVisit(JsFunction x, JsContext<JsExpression> ctx) {
      if (!functionStack.pop().equals(x)) {
        throw new InternalCompilerException("Unexpected function popped");
      }
    }

    @Override
    public void endVisit(JsInvocation x, JsContext<JsExpression> ctx) {
      /*
       * Because functions can encapsulate other functions, we look at the
       * entire stack and not just the top element. This would prevent inlining
       * 
       * function a() { function b() { a(); } b(); }
       * 
       * in the case that we generally allow nested functions to be inlinable.
       */
      JsFunction f = isFunction(x.getQualifier());
      if (functionStack.contains(f)) {
        recursive.add(f);
      }
    }

    public Set<JsFunction> getRecursive() {
      return recursive;
    }

    @Override
    public boolean visit(JsFunction x, JsContext<JsExpression> ctx) {
      functionStack.push(x);
      return true;
    }
  }

  /**
   * Determine which functions should not be inlined because they are redefined
   * during program execution. This would violate the assumption that the
   * statements to be executed by any given function invocation are stable over
   * the lifetime of the program.
   */
  private static class RedefinedFunctionCollector extends JsVisitor {
    private final Map<JsName, JsFunction> nameMap = new IdentityHashMap<JsName, JsFunction>();
    private final Set<JsFunction> redefined = new HashSet<JsFunction>();

    /**
     * Look for assignments to JsNames whose static references are JsFunctions.
     */
    @Override
    public void endVisit(JsBinaryOperation x, JsContext<JsExpression> ctx) {

      if (!x.getOperator().equals(JsBinaryOperator.ASG)) {
        return;
      }

      JsFunction f = isFunction(x.getArg1());
      if (f != null) {
        redefined.add(f);
      }
    }

    /**
     * Look for the case where a function is declared with the same name as an
     * existing function.
     */
    @Override
    public void endVisit(JsFunction x, JsContext<JsExpression> ctx) {
      JsName name = x.getName();

      if (name == null) {
        // Ignore anonymous functions
        return;

      } else if (nameMap.containsKey(name)) {
        /*
         * We have to add the current function as well as the original
         * JsFunction that was declared to use that name.
         */
        redefined.add(nameMap.get(name));
        redefined.add(x);
      } else {
        nameMap.put(name, x);
      }
    }

    public Collection<JsFunction> getRedefined() {
      return redefined;
    }
  }

  /**
   * Given a collection of JsNames, determine if an AST node refers to any of
   * those names.
   */
  private static class RefersToNameVisitor extends JsVisitor {
    private final Collection<JsName> names;
    private boolean refersToName;
    private boolean refersToUnbound;

    public RefersToNameVisitor(Collection<JsName> names) {
      this.names = names;
    }

    @Override
    public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
      JsName name = x.getName();

      if (name == null) {
        refersToUnbound = true;
      } else {
        refersToName = refersToName || names.contains(name);
      }
    }

    public boolean refersToName() {
      return refersToName;
    }

    public boolean refersToUnbound() {
      return refersToUnbound;
    }
  }

  /**
   * This ensures that changing the scope of an expression from its enclosing
   * function into the scope of the call site will not cause unqualified
   * identifiers to resolve to different values.
   */
  private static class StableNameChecker extends JsVisitor {
    private final JsScope calleeScope;
    private final JsScope callerScope;
    private final Collection<JsName> parameterNames;
    private boolean stable = true;

    public StableNameChecker(JsScope callerScope, JsScope calleeScope,
        Collection<JsName> parameterNames) {
      this.callerScope = callerScope;
      this.calleeScope = calleeScope;
      this.parameterNames = parameterNames;
    }

    @Override
    public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
      /*
       * We can ignore qualified reference, since their scope is always that of
       * the qualifier.
       */
      if (x.getQualifier() != null) {
        return;
      }

      /*
       * Attempt to resolve the ident in both scopes
       */
      JsName callerName = callerScope.findExistingName(x.getIdent());
      JsName calleeName = calleeScope.findExistingName(x.getIdent());

      if (callerName == null && calleeName == null) {
        // They both reference out-of-module names

      } else if (parameterNames.contains(calleeName)) {
        // A reference to a parameter, which will be replaced by an argument

      } else if (callerName != null && callerName.equals(calleeName)) {
        // The names are known to us and are the same

      } else if (calleeName.getEnclosing().equals(calleeScope)) {
        // It's a local variable in the callee

      } else {
        stable = false;
      }
    }

    public boolean isStable() {
      return stable;
    }
  }

  /**
   * When attempting to inline an invocation, this constant determines the
   * maximum allowable ratio of potential inlined complexity to initial
   * complexity. This acts as a brake on very large expansions from bloating the
   * the generated output. Increasing this number will allow larger sections of
   * code to be inlined, but at a cost of larger JS output.
   */
  private static final int MAX_COMPLEXITY_INCREASE = 5;

  /**
   * Static entry point used by JavaToJavaScriptCompiler.
   */
  public static OptimizerStats exec(JsProgram program) {
    Event optimizeJsEvent = SpeedTracerLogger.start(CompilerEventType.OPTIMIZE_JS, 
        "optimizer", NAME);
    OptimizerStats stats = execImpl(program);
    optimizeJsEvent.end("didChange", "" + stats.didChange());
    return stats;
  }

  /**
   * Determine whether or not a list of AST nodes are affected by side effects.
   * The context parameter provides a scope in which local (and therefore
   * immutable) variables are defined.
   */
  private static boolean affectedBySideEffects(JsProgram program,
      List<JsExpression> list, JsFunction context) {
    /*
     * If the caller contains no nested functions, none of its locals can
     * possibly be affected by side effects.
     */
    JsScope safeScope = null;
    if (context != null && !containsNestedFunctions(context)) {
      safeScope = context.getScope();
    }
    AffectedBySideEffectsVisitor v = new AffectedBySideEffectsVisitor(program,
        safeScope);
    v.acceptList(list);
    return v.affectedBySideEffects();
  }

  /**
   * Generate an estimated measure of the syntactic complexity of a JsNode.
   */
  private static int complexity(JsNode<?> toEstimate) {
    ComplexityEstimator e = new ComplexityEstimator();
    e.accept(toEstimate);
    return e.getComplexity();
  }

  /**
   * Examine a JsFunction to determine if it contains nested functions.
   */
  private static boolean containsNestedFunctions(JsFunction func) {
    NestedFunctionVisitor v = new NestedFunctionVisitor();
    v.accept(func.getBody());
    return v.containsNestedFunctions();
  }

  /**
   * @param program
   * @return
   */
  private static OptimizerStats execImpl(JsProgram program) {
    OptimizerStats stats = new OptimizerStats(NAME);
    RedefinedFunctionCollector d = new RedefinedFunctionCollector();
    d.accept(program);

    RecursionCollector rc = new RecursionCollector();
    rc.accept(program);

    InliningVisitor v = new InliningVisitor(program);
    v.blacklist(d.getRedefined());
    v.blacklist(rc.getRecursive());
    v.accept(program);
    if (v.didChange()) {
      stats.recordModified();
    }

    DuplicateXORemover r = new DuplicateXORemover(program);
    r.accept(program);
    if (r.didChange()) {
      stats.recordModified();
    }
    return stats;
  }

  /**
   * Check to see if the to-be-inlined statement shares any idents with the
   * call-side arguments. Two passes are made: the first one looks for qualified
   * names; the second pass looks for unqualified names, but ignores identifiers
   * that refer to function parameters.
   */
  private static boolean hasCommonIdents(List<JsExpression> arguments,
      JsNode<?> toInline, Collection<String> parameterIdents) {

    // This is a fire-twice loop
    boolean checkQualified = false;
    do {
      checkQualified = !checkQualified;

      // Collect the idents used in the arguments and the statement
      IdentCollector argCollector = new IdentCollector(checkQualified);
      argCollector.acceptList(arguments);
      IdentCollector statementCollector = new IdentCollector(checkQualified);
      statementCollector.accept(toInline);

      Set<String> idents = argCollector.getIdents();

      // Unqualified idents may be references to parameters, thus ignored
      if (!checkQualified) {
        idents.removeAll(parameterIdents);
      }

      // Perform the set difference
      idents.retainAll(statementCollector.getIdents());

      if (idents.size() > 0) {
        return true;
      }
    } while (checkQualified);

    return false;
  }

  /**
   * Determine whether or not a list of AST nodes have side effects.
   */
  private static boolean hasSideEffects(List<JsExpression> list) {
    for (JsExpression expr : list) {
      if (expr.hasSideEffects()) {
        return true;
      }
    }
    return false;
  }

  /**
   * Given a delegated JsStatement, construct an expression to hoist into the
   * outer caller. This does not perform any name replacement, but simply
   * constructs a mutable copy of the expression that can be manipulated
   * at-will.
   * 
   * @param program the enclosing JsProgram
   * @param statement the statement from which to extract the expressions
   * @param localVariableNames accumulates any local varables declared by
   *          <code>statement</code>
   * @return a JsExpression representing all expressions that would have been
   *         evaluated by the statement
   */
  private static JsExpression hoistedExpression(JsProgram program,
      JsStatement statement, List<JsName> localVariableNames) {
    JsExpression expression;
    if (statement instanceof JsExprStmt) {
      // Extract the expression
      JsExprStmt exprStmt = (JsExprStmt) statement;
      expression = exprStmt.getExpression();

    } else if (statement instanceof JsReturn) {
      // Extract the return value
      JsReturn ret = (JsReturn) statement;
      expression = ret.getExpr();
      if (expression == null) {
        expression = program.getUndefinedLiteral();
      }

    } else if (statement instanceof JsVars) {
      // Create a comma expression for variable initializers
      JsVars vars = (JsVars) statement;

      // Rely on comma expression cleanup to remove this later.
      expression = program.getNullLiteral();

      for (JsVar var : vars) {
        // Record the locally-defined variable
        localVariableNames.add(var.getName());

        // Extract the initialization expression
        JsExpression init = var.getInitExpr();
        if (init != null) {
          SourceInfo sourceInfo = var.getSourceInfo().makeChild(
              JsInliner.class, "Hoisted initializer into inline site");
          JsBinaryOperation assignment = new JsBinaryOperation(sourceInfo,
              JsBinaryOperator.ASG);
          assignment.setArg1(var.getName().makeRef(sourceInfo));
          assignment.setArg2(init);

          // Multiple initializers go into a comma expression
          JsBinaryOperation comma = new JsBinaryOperation(sourceInfo,
              JsBinaryOperator.COMMA);
          comma.setArg1(expression);
          comma.setArg2(assignment);
          expression = comma;
        }
      }
    } else {
      return null;
    }

    assert expression != null;
    return JsHoister.hoist(expression);
  }

  /**
   * Given a JsInvocation, determine if it is invoking a JsFunction that is
   * specified to be executed only once during the program's lifetime.
   */
  private static JsFunction isExecuteOnce(JsInvocation invocation) {
    JsFunction f = isFunction(invocation.getQualifier());
    if (f != null && f.getExecuteOnce()) {
      return f;
    }
    return null;
  }

  /**
   * Given an expression, determine if it it is a JsNameRef that refers to a
   * statically-defined JsFunction.
   */
  // Javac 1.6.0_01 barfs if staticRef is a JsNode<?>
  @SuppressWarnings("unchecked")
  private static JsFunction isFunction(JsExpression e) {
    if (e instanceof JsNameRef) {
      JsNameRef ref = (JsNameRef) e;

      // Unravel foo.call(...).
      if (!ref.getName().isObfuscatable() && "call".equals(ref.getIdent())) {
        if (ref.getQualifier() instanceof JsNameRef) {
          ref = (JsNameRef) ref.getQualifier();
        }
      }

      JsNode staticRef = ref.getName().getStaticRef();
      if (staticRef instanceof JsFunction) {
        return (JsFunction) staticRef;
      }
    }

    return null;
  }

  /**
   * Determine if a statement can be inlined into a call site.
   */
  private static boolean isInlinable(JsProgram program, JsFunction caller,
      JsFunction callee, JsExpression thisExpr, List<JsExpression> arguments,
      JsNode<?> toInline) {

    /*
     * This will happen with varargs-style JavaScript functions that rely on the
     * "arguments" array. The reference to arguments would be detected in
     * BoundedScopeVisitor, but the code below assumes the same number of
     * parameters and arguments.
     */
    if (arguments.size() != callee.getParameters().size()) {
      return false;
    }

    // Build up a list of all parameter names
    Set<JsName> parameterNames = new HashSet<JsName>();
    Set<String> parameterIdents = new HashSet<String>();
    for (JsParameter param : callee.getParameters()) {
      parameterNames.add(param.getName());
      parameterIdents.add(param.getName().getIdent());
    }

    /*
     * Make sure that inlining won't change the final name of non-parameter
     * idents due to the change of scope. The most likely cause would be the use
     * of an unqualified variable reference in a JSNI block that happened to
     * conflict with a Java-derived identifier.
     */
    StableNameChecker detector = new StableNameChecker(caller.getScope(),
        callee.getScope(), parameterNames);
    detector.accept(toInline);
    if (!detector.isStable()) {
      return false;
    }

    /*
     * Ensure that the names referred to by the argument list and the statement
     * are disjoint. This prevents inlining of the following:
     * 
     * static int i; public void add(int a) { i += a; }; add(i++);
     */
    if (hasCommonIdents(arguments, toInline, parameterIdents)) {
      return false;
    }

    List<JsExpression> evalArgs;
    if (thisExpr == null) {
      evalArgs = arguments;
    } else {
      evalArgs = new ArrayList<JsExpression>(1 + arguments.size());
      evalArgs.add(thisExpr);
      evalArgs.addAll(arguments);
    }

    /*
     * Determine if the evaluation of the invocation's arguments may create side
     * effects. This will determine how aggressively the parameters may be
     * reordered.
     */
    if (isVolatile(program, evalArgs, caller)) {
      /*
       * Determine the order in which the parameters must be evaluated. This
       * will vary between call sites, based on whether or not the invocation's
       * arguments can be repeated without ill effect.
       */
      List<JsName> requiredOrder = new ArrayList<JsName>();
      if (thisExpr != null && isVolatile(program, thisExpr, callee)) {
        requiredOrder.add(EvaluationOrderVisitor.THIS_NAME);
      }
      for (int i = 0; i < arguments.size(); i++) {
        JsExpression e = arguments.get(i);
        JsParameter p = callee.getParameters().get(i);

        if (isVolatile(program, e, callee)) {
          requiredOrder.add(p.getName());
        }
      }

      // This would indicate that isVolatile changed its output between
      // the if statement and the loop.
      assert requiredOrder.size() > 0;

      /*
       * Verify that the non-reorderable arguments are evaluated in the right
       * order.
       */
      EvaluationOrderVisitor orderVisitor = new EvaluationOrderVisitor(
          requiredOrder);
      orderVisitor.accept(toInline);
      if (!orderVisitor.maintainsOrder()) {
        return false;
      }
    }

    // Check that parameters aren't used in such a way as to prohibit inlining
    ParameterUsageVisitor v = new ParameterUsageVisitor(thisExpr != null,
        parameterNames);
    v.accept(toInline);
    if (v.hasViolation()) {
      return false;
    }

    // Hooray!
    return true;
  }

  /**
   * This is used in combination with {@link #hoistedExpression(JsStatement)} to
   * indicate if a given statement would terminate the list of hoisted
   * expressions.
   */
  private static boolean isReturnStatement(JsStatement statement) {
    return statement instanceof JsReturn;
  }

  /**
   * Indicates if an expression would create side effects or possibly be
   * affected by side effects when evaluated within a particular function
   * context.
   */
  private static boolean isVolatile(JsProgram program, JsExpression e,
      JsFunction context) {
    return isVolatile(program, Collections.singletonList(e), context);
  }

  /**
   * Indicates if a list of expressions would create side effects or possibly be
   * affected by side effects when evaluated within a particular function
   * context.
   */
  private static boolean isVolatile(JsProgram program, List<JsExpression> list,
      JsFunction context) {
    return hasSideEffects(list)
        || affectedBySideEffects(program, list, context);
  }

  /**
   * Transforms any <code>foo.call(this)</code> into <code>this.foo()</code> to
   * be compatible with our inlining algorithm.
   */
  private static JsInvocation tryToUnravelExplicitCall(JsInvocation x) {
    if (!(x.getQualifier() instanceof JsNameRef)) {
      return x;
    }
    JsNameRef ref = (JsNameRef) x.getQualifier();
    if (ref.getName().isObfuscatable() || !"call".equals(ref.getIdent())) {
      return x;
    }
    List<JsExpression> oldArgs = x.getArguments();
    if (oldArgs.size() < 1) {
      return x;
    }

    JsNameRef oldTarget = (JsNameRef) ref.getQualifier();
    JsNameRef newTarget = new JsNameRef(oldTarget.getSourceInfo(),
        oldTarget.getName());
    newTarget.setQualifier(oldArgs.get(0));
    JsInvocation newCall = new JsInvocation(x.getSourceInfo());
    newCall.setQualifier(newTarget);
    // Don't have to clone because the returned invocation is transient.
    newCall.getArguments().addAll(oldArgs.subList(1, oldArgs.size()));
    return newCall;
  }

  /**
   * Utility class.
   */
  private JsInliner() {
  }
}
