/*
 * 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.JsCatchScope;
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.JsEmpty;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFor;
import com.google.gwt.dev.js.ast.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.JsRegExp;
import com.google.gwt.dev.js.ast.JsReturn;
import com.google.gwt.dev.js.ast.JsRootScope;
import com.google.gwt.dev.js.ast.JsScope;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsStringLiteral;
import com.google.gwt.dev.js.ast.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 JsScope safeScope;

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

    public boolean affectedBySideEffects() {
      return affectedBySideEffects;
    }

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

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

    @Override
    public void endVisit(JsInvocation x, JsContext 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 ctx) {
      if (x.getQualifier() == null && x.getName() != null) {
        // Special case the undefined literal.
        if (x.getName() == JsRootScope.INSTANCE.getUndefined()) {
          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 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 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(),
          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 ctx) {
      complexity++;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    @Override
    public void endVisit(JsThisRef x, JsContext 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 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(JsNullLiteral.INSTANCE);
            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 ctx) {
      branch(x.getStatements());
      return false;
    }

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

    @Override
    public boolean visit(JsConditional x, JsContext 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 ctx) {
      branch(x.getStmts());
      return false;
    }

    @Override
    public boolean visit(JsExprStmt x, JsContext ctx) {
      if (isDuplicateCall(x.getExpression())) {
        if (ctx.canRemove()) {
          ctx.removeMe();
        } else {
          ctx.replaceMe(new JsEmpty(x.getSourceInfo()));
        }
        return false;

      } else {
        return true;
      }
    }

    @Override
    public boolean visit(JsFor x, JsContext 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 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 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 ctx) {
      JsFunction func = isExecuteOnce(x);
      while (func != null) {
        called.add(func);
        func = func.getImpliedExecute();
      }
      return true;
    }

    @Override
    public boolean visit(JsWhile x, JsContext 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> void branch(List<T> x) {
      DuplicateXORemover dup = new DuplicateXORemover(program, called);
      dup.acceptWithInsertRemove(x);
      didChange |= dup.didChange();
    }

    private <T extends JsNode> 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 {
    /**
     * A dummy name to represent 'this' refs.
     */
    public static final JsName THIS_NAME = new JsCatchScope(
        JsRootScope.INSTANCE, "this").getAllNames().next();

    private boolean maintainsOrder = true;
    private final List<JsName> toEvaluate;
    private final List<JsName> unevaluated;
    private final Set<JsName> paramsOrLocals = new HashSet<JsName>();

    public EvaluationOrderVisitor(List<JsName> toEvaluate, JsFunction callee) {
      this.toEvaluate = toEvaluate;
      this.unevaluated = new ArrayList<JsName>(toEvaluate);
      // collect params and locals from callee function
      new JsVisitor() {
        @Override
        public void endVisit(JsParameter x, JsContext ctx) {
          paramsOrLocals.add(x.getName());
        }

        @Override
        public boolean visit(JsVar x, JsContext ctx) {
          // record this before visiting initializer
          paramsOrLocals.add(x.getName());
          return true;
        }
      }.accept(callee);
    }

    @Override
    public void endVisit(JsBinaryOperation x, JsContext 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 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 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 ctx) {
      if (unevaluated.size() > 0) {
        maintainsOrder = false;
      }
    }

    @Override
    public void endVisit(JsNameRef x, JsContext ctx) {
      checkName(x.getName());
    }

    @Override
    public void endVisit(JsNew x, JsContext 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 ctx) {
      checkName(THIS_NAME);
    }

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

    /**
     * Check to see if the evaluation of this JsName will break program order assumptions given
     * the parameters left to be substituted.
     *
     * The cases are as follows:
     * 1) JsName is a function parameter name which has side effects or is affected by side effects
     * (hereafter called 'volatile'), so it will be in 'toEvaluate'
     * 2) JsName is a function parameter which is not volatile (not in toEvaluate)
     * 3) JsName is a reference to a global variable
     * 4) JsName is a reference to a local variable
     *
     * A reference to a global while there are still parameters left to evaluate / substitute
     * implies an order violation.
     *
     * A reference to a volatile parameter is ok if it is the next parameter in sequence to
     * be evaluated (beginning of unevaluated list). Else, it is either being evaluated out of
     * order with respect to other parameters, or it is being evaluated more than once.
     */
    private void checkName(JsName name) {
      if (!toEvaluate.contains(name)) {
        // if the name is a non-local/non-parameter (e.g. global) and there are params left to eval
        if (!paramsOrLocals.contains(name) && unevaluated.size() > 0) {
          maintainsOrder = false;
        }
        // else this may be a local, or all volatile params have already been evaluated, so it's ok.
        return;
      }

      // either this param is being evaled twice, or out of order
      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 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>>();

    /**
     * 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) {
      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 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(new JsEmpty(x.getSourceInfo()));
        }

      } 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());
          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 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 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(JsProgram x, JsContext 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 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 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(JsProgram x, JsContext ctx) {
      programFunction = new JsFunction(x.getSourceInfo(), x.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();
      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(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(new JsNameRef(x.getSourceInfo(),
            JsRootScope.INSTANCE.getUndefined()));
      }

      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();
      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(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 ctx) {
      checkFunctionCall(x.getQualifier());
    }

    @Override
    public void endVisit(JsNew x, JsContext 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 ctx) {
      if (x.getQualifier() != null) {
        return;
      }

      JsExpression replacement = tryGetReplacementExpression(x.getSourceInfo(),
          x.getName());

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

    @Override
    public void endVisit(JsThisRef x, JsContext 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 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 ctx) {
      if (ctx.isLvalue() && isParameter(x)) {
        violation = true;
      }
    }

    @Override
    public void endVisit(JsThisRef x, JsContext 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 ctx) {
      if (!functionStack.pop().equals(x)) {
        throw new InternalCompilerException("Unexpected function popped");
      }
    }

    @Override
    public void endVisit(JsInvocation x, JsContext 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 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 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 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 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 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 double MAX_COMPLEXITY_INCREASE = Double.parseDouble(System.getProperty(
      "gwt.jsinlinerRatio", "1.7"));

  /**
   * 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(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(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(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 = new JsNameRef(ret.getSourceInfo(),
            JsRootScope.INSTANCE.getUndefined());
      }

    } 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 = JsNullLiteral.INSTANCE;

      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();
          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.
   */
  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(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(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(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(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, callee);
      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(JsExpression e, JsFunction context) {
    return isVolatile(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(List<JsExpression> list, JsFunction context) {
    return hasSideEffects(list) || affectedBySideEffects(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() {
  }
}
