25 26 package jdk.nashorn.internal.codegen; 27 28 import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX; 29 30 import java.util.ArrayList; 31 import java.util.HashMap; 32 import java.util.List; 33 import java.util.Map; 34 import jdk.nashorn.internal.ir.Block; 35 import jdk.nashorn.internal.ir.FunctionNode; 36 import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 37 import jdk.nashorn.internal.ir.LexicalContext; 38 import jdk.nashorn.internal.ir.LiteralNode; 39 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 40 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit; 41 import jdk.nashorn.internal.ir.Node; 42 import jdk.nashorn.internal.ir.SplitNode; 43 import jdk.nashorn.internal.ir.Statement; 44 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 45 import jdk.nashorn.internal.runtime.logging.DebugLogger; 46 import jdk.nashorn.internal.runtime.options.Options; 47 48 /** 49 * Split the IR into smaller compile units. 50 */ 51 final class Splitter extends NodeVisitor<LexicalContext> { 52 /** Current compiler. */ 53 private final Compiler compiler; 54 55 /** IR to be broken down. */ 56 private final FunctionNode outermost; 57 58 /** Compile unit for the main script. */ 59 private final CompileUnit outermostCompileUnit; 60 61 /** Cache for calculated block weights. */ 62 private final Map<Node, Long> weightCache = new HashMap<>(); 63 64 /** Weight threshold for when to start a split. */ 65 public static final long SPLIT_THRESHOLD = Options.getIntProperty("nashorn.compiler.splitter.threshold", 32 * 1024); 66 67 private final DebugLogger log; 68 69 /** 70 * Constructor. 71 * 72 * @param compiler the compiler 73 * @param functionNode function node to split 74 * @param outermostCompileUnit compile unit for outermost function, if non-lazy this is the script's compile unit 75 */ 76 public Splitter(final Compiler compiler, final FunctionNode functionNode, final CompileUnit outermostCompileUnit) { 77 super(new LexicalContext()); 78 this.compiler = compiler; 79 this.outermost = functionNode; 80 this.outermostCompileUnit = outermostCompileUnit; 81 this.log = compiler.getLogger(); 82 } 83 84 /** 85 * Execute the split. 86 * @param fn the function to split 87 * @param top whether this is the topmost compiled function (it's either a program, or we're doing a recompilation). 88 */ 89 FunctionNode split(final FunctionNode fn, final boolean top) { 90 FunctionNode functionNode = fn; 91 92 log.finest("Initiating split of '", functionNode.getName(), "'"); 93 94 long weight = WeighNodes.weigh(functionNode); 95 96 // We know that our LexicalContext is empty outside the call to functionNode.accept(this) below, 97 // so we can pass null to all methods expecting a LexicalContext parameter. 98 assert lc.isEmpty() : "LexicalContext not empty"; 99 100 if (weight >= SPLIT_THRESHOLD) { 101 log.finest("Splitting '", functionNode.getName(), "' as its weight ", weight, " exceeds split threshold ", SPLIT_THRESHOLD); 102 functionNode = (FunctionNode)functionNode.accept(this); 103 104 if (functionNode.isSplit()) { 105 // Weight has changed so weigh again, this time using block weight cache 106 weight = WeighNodes.weigh(functionNode, weightCache); 107 functionNode = functionNode.setBody(null, functionNode.getBody().setNeedsScope(null)); 108 } 109 110 if (weight >= SPLIT_THRESHOLD) { 111 functionNode = functionNode.setBody(null, splitBlock(functionNode.getBody(), functionNode)); 112 functionNode = functionNode.setFlag(null, FunctionNode.IS_SPLIT); 113 weight = WeighNodes.weigh(functionNode.getBody(), weightCache); 114 } 115 } 116 117 assert functionNode.getCompileUnit() == null : "compile unit already set for " + functionNode.getName(); 118 119 if (top) { 120 assert outermostCompileUnit != null : "outermost compile unit is null"; 121 functionNode = functionNode.setCompileUnit(null, outermostCompileUnit); | 25 26 package jdk.nashorn.internal.codegen; 27 28 import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX; 29 30 import java.util.ArrayList; 31 import java.util.HashMap; 32 import java.util.List; 33 import java.util.Map; 34 import jdk.nashorn.internal.ir.Block; 35 import jdk.nashorn.internal.ir.FunctionNode; 36 import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 37 import jdk.nashorn.internal.ir.LexicalContext; 38 import jdk.nashorn.internal.ir.LiteralNode; 39 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 40 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit; 41 import jdk.nashorn.internal.ir.Node; 42 import jdk.nashorn.internal.ir.SplitNode; 43 import jdk.nashorn.internal.ir.Statement; 44 import jdk.nashorn.internal.ir.visitor.NodeVisitor; 45 import jdk.nashorn.internal.runtime.Context; 46 import jdk.nashorn.internal.runtime.logging.DebugLogger; 47 import jdk.nashorn.internal.runtime.logging.Loggable; 48 import jdk.nashorn.internal.runtime.logging.Logger; 49 import jdk.nashorn.internal.runtime.options.Options; 50 51 /** 52 * Split the IR into smaller compile units. 53 */ 54 @Logger(name="splitter") 55 final class Splitter extends NodeVisitor<LexicalContext> implements Loggable { 56 /** Current compiler. */ 57 private final Compiler compiler; 58 59 /** IR to be broken down. */ 60 private final FunctionNode outermost; 61 62 /** Compile unit for the main script. */ 63 private final CompileUnit outermostCompileUnit; 64 65 /** Cache for calculated block weights. */ 66 private final Map<Node, Long> weightCache = new HashMap<>(); 67 68 /** Weight threshold for when to start a split. */ 69 public static final long SPLIT_THRESHOLD = Options.getIntProperty("nashorn.compiler.splitter.threshold", 32 * 1024); 70 71 private final DebugLogger log; 72 73 /** 74 * Constructor. 75 * 76 * @param compiler the compiler 77 * @param functionNode function node to split 78 * @param outermostCompileUnit compile unit for outermost function, if non-lazy this is the script's compile unit 79 */ 80 public Splitter(final Compiler compiler, final FunctionNode functionNode, final CompileUnit outermostCompileUnit) { 81 super(new LexicalContext()); 82 this.compiler = compiler; 83 this.outermost = functionNode; 84 this.outermostCompileUnit = outermostCompileUnit; 85 this.log = initLogger(compiler.getContext()); 86 } 87 88 @Override 89 public DebugLogger initLogger(final Context context) { 90 return context.getLogger(this.getClass()); 91 } 92 93 @Override 94 public DebugLogger getLogger() { 95 return log; 96 } 97 98 /** 99 * Execute the split. 100 * @param fn the function to split 101 * @param top whether this is the topmost compiled function (it's either a program, or we're doing a recompilation). 102 */ 103 FunctionNode split(final FunctionNode fn, final boolean top) { 104 FunctionNode functionNode = fn; 105 106 log.fine("Initiating split of '", functionNode.getName(), "'"); 107 108 long weight = WeighNodes.weigh(functionNode); 109 110 // We know that our LexicalContext is empty outside the call to functionNode.accept(this) below, 111 // so we can pass null to all methods expecting a LexicalContext parameter. 112 assert lc.isEmpty() : "LexicalContext not empty"; 113 114 if (weight >= SPLIT_THRESHOLD) { 115 log.info("Splitting '", functionNode.getName(), "' as its weight ", weight, " exceeds split threshold ", SPLIT_THRESHOLD); 116 functionNode = (FunctionNode)functionNode.accept(this); 117 118 if (functionNode.isSplit()) { 119 // Weight has changed so weigh again, this time using block weight cache 120 weight = WeighNodes.weigh(functionNode, weightCache); 121 functionNode = functionNode.setBody(null, functionNode.getBody().setNeedsScope(null)); 122 } 123 124 if (weight >= SPLIT_THRESHOLD) { 125 functionNode = functionNode.setBody(null, splitBlock(functionNode.getBody(), functionNode)); 126 functionNode = functionNode.setFlag(null, FunctionNode.IS_SPLIT); 127 weight = WeighNodes.weigh(functionNode.getBody(), weightCache); 128 } 129 } 130 131 assert functionNode.getCompileUnit() == null : "compile unit already set for " + functionNode.getName(); 132 133 if (top) { 134 assert outermostCompileUnit != null : "outermost compile unit is null"; 135 functionNode = functionNode.setCompileUnit(null, outermostCompileUnit); |