Пример #1
0
  /**
   * Split a block into sub methods.
   *
   * @param block Block or function to split.
   * @return new weight for the resulting block.
   */
  private Block splitBlock(final Block block, final FunctionNode function) {

    final List<Statement> splits = new ArrayList<>();
    List<Statement> statements = new ArrayList<>();
    long statementsWeight = 0;

    for (final Statement statement : block.getStatements()) {
      final long weight = WeighNodes.weigh(statement, weightCache);

      if (statementsWeight + weight >= SPLIT_THRESHOLD || statement.isTerminal()) {
        if (!statements.isEmpty()) {
          splits.add(createBlockSplitNode(block, function, statements, statementsWeight));
          statements = new ArrayList<>();
          statementsWeight = 0;
        }
      }

      if (statement.isTerminal()) {
        splits.add(statement);
      } else {
        statements.add(statement);
        statementsWeight += weight;
      }
    }

    if (!statements.isEmpty()) {
      splits.add(createBlockSplitNode(block, function, statements, statementsWeight));
    }

    return block.setStatements(lc, splits);
  }
Пример #2
0
  @SuppressWarnings("rawtypes")
  @Override
  public Node leaveLiteralNode(final LiteralNode literal) {
    long weight = WeighNodes.weigh(literal);

    if (weight < SPLIT_THRESHOLD) {
      return literal;
    }

    final FunctionNode functionNode = lc.getCurrentFunction();

    lc.setFlag(functionNode, FunctionNode.IS_SPLIT);

    if (literal instanceof ArrayLiteralNode) {
      final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode) literal;
      final Node[] value = arrayLiteralNode.getValue();
      final int[] postsets = arrayLiteralNode.getPostsets();
      final List<ArrayUnit> units = new ArrayList<>();

      long totalWeight = 0;
      int lo = 0;

      for (int i = 0; i < postsets.length; i++) {
        final int postset = postsets[i];
        final Node element = value[postset];

        weight = WeighNodes.weigh(element);
        totalWeight += WeighNodes.AASTORE_WEIGHT + weight;

        if (totalWeight >= SPLIT_THRESHOLD) {
          final CompileUnit unit = compiler.findUnit(totalWeight - weight);
          units.add(new ArrayUnit(unit, lo, i));
          lo = i;
          totalWeight = weight;
        }
      }

      if (lo != postsets.length) {
        final CompileUnit unit = compiler.findUnit(totalWeight);
        units.add(new ArrayUnit(unit, lo, postsets.length));
      }

      return arrayLiteralNode.setUnits(lc, units);
    }

    return literal;
  }
Пример #3
0
  @Override
  public Node leaveBlock(final Block block) {
    assert !block.isCatchBlock();

    Block newBlock = block;

    // Block was heavier than SLIT_THRESHOLD in enter, but a sub-block may have
    // been split already, so weigh again before splitting.
    long weight = WeighNodes.weigh(block, weightCache);
    if (weight >= SPLIT_THRESHOLD) {
      final FunctionNode currentFunction = lc.getCurrentFunction();
      newBlock = splitBlock(block, currentFunction);
      weight = WeighNodes.weigh(newBlock, weightCache);
      lc.setFlag(currentFunction, FunctionNode.IS_SPLIT);
    }
    weightCache.put(newBlock, weight);
    return newBlock;
  }
Пример #4
0
  @Override
  public boolean enterBlock(final Block block) {
    if (block.isCatchBlock()) {
      return false;
    }

    final long weight = WeighNodes.weigh(block, weightCache);

    if (weight < SPLIT_THRESHOLD) {
      weightCache.put(block, weight);
      return false;
    }

    return true;
  }
Пример #5
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);
  }