src/com/google/javascript/jscomp/FunctionInjector.java
/**
   * Determines whether a function can be inlined at a particular call site.
   * - Don't inline if the calling function contains an inner function and
   * inlining would introduce new globals.
   */
Determines whether a function can be inlined at a particular call site.
- Don't inline if the calling function contains an inner function and
inlining would introduce new globals.
Determines whether a function can be inlined at a particular call site . - Don ' t inline if the calling function contains an inner function and inlining would introduce new globals .
private boolean callMeetsBlockInliningRequirements(
      Reference ref, final Node fnNode, ImmutableSet<String> namesToAlias) {
    boolean fnContainsVars = NodeUtil.has(
        NodeUtil.getFunctionBody(fnNode),
        new NodeUtil.MatchDeclaration(),
        new NodeUtil.MatchShallowStatement());
    boolean forbidTemps = false;
    if (!ref.scope.getClosestHoistScope().isGlobal()) {
      Node fnCallerBody = ref.scope.getClosestHoistScope().getRootNode();
      Predicate<Node> match = new Predicate<Node>(){
        @Override
        public boolean apply(Node n) {
          if (n.isName()) {
            return n.getString().equals("eval");
          }
          if (!assumeMinimumCapture && n.isFunction()) {
            return n != fnNode;
          }
          return false;
        }
      };
      forbidTemps = NodeUtil.has(fnCallerBody, match, NodeUtil.MATCH_NOT_FUNCTION);
    }
    if (fnContainsVars && forbidTemps) {
      return false;
    }
    if (forbidTemps) {
      ImmutableMap<String, Node> args =
          FunctionArgumentInjector.getFunctionCallParameterMap(
              fnNode, ref.callNode, this.safeNameIdSupplier);
      boolean hasArgs = !args.isEmpty();
      if (hasArgs) {
        Set<String> allNamesToAlias = new HashSet<>(namesToAlias);
        FunctionArgumentInjector.maybeAddTempsForCallArguments(
            fnNode, args, allNamesToAlias, compiler.getCodingConvention());
        if (!allNamesToAlias.isEmpty()) {
          return false;
        }
      }
    }
    return true;
  }
private boolean callMeetsBlockInliningRequirements ( Reference ref , final Node fnNode , ImmutableSet < String > namesToAlias ) { boolean fnContainsVars = NodeUtil . has ( NodeUtil . getFunctionBody ( fnNode ) , new NodeUtil . MatchDeclaration ( ) , new NodeUtil . MatchShallowStatement ( ) ) ; boolean forbidTemps = false ; if ( ! ref . scope . getClosestHoistScope ( ) . isGlobal ( ) ) { Node fnCallerBody = ref . scope . getClosestHoistScope ( ) . getRootNode ( ) ; Predicate < Node > match = new Predicate < Node > ( ) { @ Override public boolean apply ( Node n ) { if ( n . isName ( ) ) { return n . getString ( ) . equals ( "eval" ) ; } if ( ! assumeMinimumCapture && n . isFunction ( ) ) { return n != fnNode ; } return false ; } } ; forbidTemps = NodeUtil . has ( fnCallerBody , match , NodeUtil . MATCH_NOT_FUNCTION ) ; } if ( fnContainsVars && forbidTemps ) { return false ; } if ( forbidTemps ) { ImmutableMap < String , Node > args = FunctionArgumentInjector . getFunctionCallParameterMap ( fnNode , ref . callNode , this . safeNameIdSupplier ) ; boolean hasArgs = ! args . isEmpty ( ) ; if ( hasArgs ) { Set < String > allNamesToAlias = new HashSet < > ( namesToAlias ) ; FunctionArgumentInjector . maybeAddTempsForCallArguments ( fnNode , args , allNamesToAlias , compiler . getCodingConvention ( ) ) ; if ( ! allNamesToAlias . isEmpty ( ) ) { return false ; } } } return true ; }
Determines whether a function can be inlined at a particular call site.
Determines whether a function can be inlined at a particular call site .
// Note: functions that contain function definitions are filtered out // in isCandidateFunction. // TODO(johnlenz): Determining if the called function contains VARs // or if the caller contains inner functions accounts for 20% of the // run-time cost of this pass. // Don't inline functions with var declarations into a scope with inner // functions as the new vars would leak into the inner function and // cause memory leaks. // Don't allow any new vars into a scope that contains eval or one // that contains functions (excluding the function being inlined). // If the caller contains functions or evals, verify we aren't adding any // additional VAR declarations because aliasing is needed. // Limit the inlining