/** * 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); }