Пример #1
0
  /**
   * Execute the split.
   *
   * @param fn the function to split
   * @param top whether this is the topmost compiled function (it's either a program, or we're doing
   *     a recompilation).
   */
  FunctionNode split(final FunctionNode fn, final boolean top) {
    FunctionNode functionNode = fn;

    log.finest("Initiating split of '", functionNode.getName(), "'");

    long weight = WeighNodes.weigh(functionNode);

    // We know that our LexicalContext is empty outside the call to functionNode.accept(this) below,
    // so we can pass null to all methods expecting a LexicalContext parameter.
    assert lc.isEmpty() : "LexicalContext not empty";

    if (weight >= SPLIT_THRESHOLD) {
      log.finest(
          "Splitting '",
          functionNode.getName(),
          "' as its weight ",
          weight,
          " exceeds split threshold ",
          SPLIT_THRESHOLD);
      functionNode = (FunctionNode) functionNode.accept(this);

      if (functionNode.isSplit()) {
        // Weight has changed so weigh again, this time using block weight cache
        weight = WeighNodes.weigh(functionNode, weightCache);
        functionNode = functionNode.setBody(null, functionNode.getBody().setNeedsScope(null));
      }

      if (weight >= SPLIT_THRESHOLD) {
        functionNode = functionNode.setBody(null, splitBlock(functionNode.getBody(), functionNode));
        functionNode = functionNode.setFlag(null, FunctionNode.IS_SPLIT);
        weight = WeighNodes.weigh(functionNode.getBody(), weightCache);
      }
    }

    assert functionNode.getCompileUnit() == null
        : "compile unit already set for " + functionNode.getName();

    if (top) {
      assert outermostCompileUnit != null : "outermost compile unit is null";
      functionNode = functionNode.setCompileUnit(null, outermostCompileUnit);
      outermostCompileUnit.addWeight(weight + WeighNodes.FUNCTION_WEIGHT);
    } else {
      functionNode = functionNode.setCompileUnit(null, findUnit(weight));
    }

    final Block body = functionNode.getBody();
    final List<FunctionNode> dc = directChildren(functionNode);

    final Block newBody =
        (Block)
            body.accept(
                new NodeVisitor<LexicalContext>(new LexicalContext()) {
                  @Override
                  public boolean enterFunctionNode(final FunctionNode nestedFunction) {
                    return dc.contains(nestedFunction);
                  }

                  @Override
                  public Node leaveFunctionNode(final FunctionNode nestedFunction) {
                    final FunctionNode split =
                        new Splitter(compiler, nestedFunction, outermostCompileUnit)
                            .split(nestedFunction, false);
                    lc.replace(nestedFunction, split);
                    return split;
                  }
                });
    functionNode = functionNode.setBody(null, newBody);

    assert functionNode.getCompileUnit() != null;

    return functionNode.setState(null, CompilationState.SPLIT);
  }