Example #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);
  }
  // entry point for translator
  CompilationUnitTree translate(final FunctionNode node) {
    if (node == null) {
      return null;
    }

    assert (node.getKind() == FunctionNode.Kind.SCRIPT) : "script function expected";

    final Block body = node.getBody();
    return new CompilationUnitTreeImpl(
        node, translateStats(body != null ? getOrderedStatements(body.getStatements()) : null));
  }
 @Override
 public boolean enterBlockStatement(final BlockStatement blockStatement) {
   final Block block = blockStatement.getBlock();
   if (blockStatement.isSynthetic()) {
     assert block != null && block.getStatements() != null && block.getStatements().size() == 1;
     curStat = translateStat(block.getStatements().get(0));
   } else {
     curStat =
         new BlockTreeImpl(
             blockStatement, translateStats(block != null ? block.getStatements() : null));
   }
   return false;
 }
Example #4
0
  /**
   * Create a new split node from statements contained in a parent block.
   *
   * @param parent Parent block.
   * @param statements Statements to include.
   * @return New split node.
   */
  private SplitNode createBlockSplitNode(
      final Block parent,
      final FunctionNode function,
      final List<Statement> statements,
      final long weight) {
    final long token = parent.getToken();
    final int finish = parent.getFinish();
    final String name = function.uniqueName(SPLIT_PREFIX.symbolName());

    final Block newBlock = new Block(token, finish, statements);

    return new SplitNode(name, newBlock, compiler.findUnit(weight + WeighNodes.FUNCTION_WEIGHT));
  }
  @Override
  public boolean enterSwitchNode(final SwitchNode switchNode) {
    final List<CaseNode> caseNodes = switchNode.getCases();
    final List<CaseTreeImpl> caseTrees = new ArrayList<>(caseNodes.size());
    for (final CaseNode caseNode : caseNodes) {
      final Block body = caseNode.getBody();
      caseTrees.add(
          new CaseTreeImpl(
              caseNode,
              translateExpr(caseNode.getTest()),
              translateStats(body != null ? body.getStatements() : null)));
    }

    curStat = new SwitchTreeImpl(switchNode, translateExpr(switchNode.getExpression()), caseTrees);
    return false;
  }
  private boolean handleBlock(final Block block, final boolean sortStats) {
    // FIXME: revisit this!
    if (block.isSynthetic()) {
      final int statCount = block.getStatementCount();
      switch (statCount) {
        case 0:
          {
            final EmptyNode emptyNode = new EmptyNode(-1, block.getToken(), block.getFinish());
            curStat = new EmptyStatementTreeImpl(emptyNode);
            return false;
          }
        case 1:
          {
            curStat = translateStat(block.getStatements().get(0));
            return false;
          }
        default:
          {
            // fall through
            break;
          }
      }
    }

    final List<? extends Statement> stats = block.getStatements();
    curStat =
        new BlockTreeImpl(block, translateStats(sortStats ? getOrderedStatements(stats) : stats));
    return false;
  }
Example #7
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;
  }
Example #8
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;
  }
Example #9
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);
  }