nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java
changeset 17756 daaa1e643f71
parent 17525 6582a7788183
child 17769 14ea7feaf658
equal deleted inserted replaced
17755:0150d0415000 17756:daaa1e643f71
     9 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SPLIT;
     9 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SPLIT;
    10 
    10 
    11 import java.io.File;
    11 import java.io.File;
    12 import java.io.FileOutputStream;
    12 import java.io.FileOutputStream;
    13 import java.io.IOException;
    13 import java.io.IOException;
       
    14 import java.util.ArrayDeque;
       
    15 import java.util.ArrayList;
       
    16 import java.util.Deque;
    14 import java.util.EnumSet;
    17 import java.util.EnumSet;
    15 import java.util.HashSet;
    18 import java.util.HashSet;
       
    19 import java.util.List;
    16 import java.util.Set;
    20 import java.util.Set;
       
    21 
       
    22 import jdk.nashorn.internal.codegen.types.Range;
    17 import jdk.nashorn.internal.codegen.types.Type;
    23 import jdk.nashorn.internal.codegen.types.Type;
    18 import jdk.nashorn.internal.ir.Block;
    24 import jdk.nashorn.internal.ir.Block;
    19 import jdk.nashorn.internal.ir.CallNode;
    25 import jdk.nashorn.internal.ir.CallNode;
    20 import jdk.nashorn.internal.ir.FunctionNode;
    26 import jdk.nashorn.internal.ir.FunctionNode;
       
    27 import jdk.nashorn.internal.ir.ReturnNode;
       
    28 import jdk.nashorn.internal.ir.Symbol;
    21 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
    29 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
    22 import jdk.nashorn.internal.ir.LexicalContext;
    30 import jdk.nashorn.internal.ir.LexicalContext;
    23 import jdk.nashorn.internal.ir.Node;
    31 import jdk.nashorn.internal.ir.Node;
    24 import jdk.nashorn.internal.ir.TemporarySymbols;
    32 import jdk.nashorn.internal.ir.TemporarySymbols;
    25 import jdk.nashorn.internal.ir.debug.ASTWriter;
    33 import jdk.nashorn.internal.ir.debug.ASTWriter;
   172     ATTRIBUTION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED)) {
   180     ATTRIBUTION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED)) {
   173         @Override
   181         @Override
   174         FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
   182         FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
   175             final TemporarySymbols ts = compiler.getTemporarySymbols();
   183             final TemporarySymbols ts = compiler.getTemporarySymbols();
   176             final FunctionNode newFunctionNode = (FunctionNode)enterAttr(fn, ts).accept(new Attr(ts));
   184             final FunctionNode newFunctionNode = (FunctionNode)enterAttr(fn, ts).accept(new Attr(ts));
   177             if(compiler.getEnv()._print_mem_usage) {
   185             if (compiler.getEnv()._print_mem_usage) {
   178                 Compiler.LOG.info("Attr temporary symbol count: " + ts.getTotalSymbolCount());
   186                 Compiler.LOG.info("Attr temporary symbol count: " + ts.getTotalSymbolCount());
   179             }
   187             }
   180             return newFunctionNode;
   188             return newFunctionNode;
   181         }
   189         }
   182 
   190 
   206             return "[Type Attribution]";
   214             return "[Type Attribution]";
   207         }
   215         }
   208     },
   216     },
   209 
   217 
   210     /*
   218     /*
       
   219      * Range analysis
       
   220      *    Conservatively prove that certain variables can be narrower than
       
   221      *    the most generic number type
       
   222      */
       
   223     RANGE_ANALYSIS_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR)) {
       
   224         @Override
       
   225         FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
       
   226             if (!compiler.getEnv()._range_analysis) {
       
   227                 return fn;
       
   228             }
       
   229 
       
   230             FunctionNode newFunctionNode = (FunctionNode)fn.accept(new RangeAnalyzer());
       
   231             final List<ReturnNode> returns = new ArrayList<>();
       
   232 
       
   233             newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor() {
       
   234                 private final Deque<ArrayList<ReturnNode>> returnStack = new ArrayDeque<>();
       
   235 
       
   236                 @Override
       
   237                 public boolean enterFunctionNode(final FunctionNode functionNode) {
       
   238                     returnStack.push(new ArrayList<ReturnNode>());
       
   239                     return true;
       
   240                 }
       
   241 
       
   242                 @Override
       
   243                 public Node leaveFunctionNode(final FunctionNode functionNode) {
       
   244                     Type returnType = Type.UNKNOWN;
       
   245                     for (final ReturnNode ret : returnStack.pop()) {
       
   246                         if (ret.getExpression() == null) {
       
   247                             returnType = Type.OBJECT;
       
   248                             break;
       
   249                         }
       
   250                         returnType = Type.widest(returnType, ret.getExpression().getType());
       
   251                     }
       
   252                     return functionNode.setReturnType(getLexicalContext(), returnType);
       
   253                 }
       
   254 
       
   255                 @Override
       
   256                 public Node leaveReturnNode(final ReturnNode returnNode) {
       
   257                     final ReturnNode result = (ReturnNode)leaveDefault(returnNode);
       
   258                     returns.add(result);
       
   259                     return result;
       
   260                 }
       
   261 
       
   262                 @Override
       
   263                 public Node leaveDefault(final Node node) {
       
   264                     final Symbol symbol = node.getSymbol();
       
   265                     if (symbol != null) {
       
   266                         final Range range  = symbol.getRange();
       
   267                         final Type  symbolType = symbol.getSymbolType();
       
   268                         if (!symbolType.isNumeric()) {
       
   269                             return node;
       
   270                         }
       
   271                         final Type  rangeType  = range.getType();
       
   272                         if (!Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range
       
   273                             RangeAnalyzer.LOG.info("[", getLexicalContext().getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
       
   274                             return node.setSymbol(getLexicalContext(), symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols()));
       
   275                         }
       
   276                     }
       
   277                     return node;
       
   278                 }
       
   279             });
       
   280 
       
   281             Type returnType = Type.UNKNOWN;
       
   282             for (final ReturnNode node : returns) {
       
   283                 if (node.getExpression() != null) {
       
   284                     returnType = Type.widest(returnType, node.getExpression().getType());
       
   285                 } else {
       
   286                     returnType = Type.OBJECT;
       
   287                     break;
       
   288                 }
       
   289             }
       
   290 
       
   291             return newFunctionNode.setReturnType(null, returnType);
       
   292         }
       
   293 
       
   294         @Override
       
   295         public String toString() {
       
   296             return "[Range Analysis]";
       
   297         }
       
   298     },
       
   299 
       
   300 
       
   301     /*
   211      * Splitter Split the AST into several compile units based on a size
   302      * Splitter Split the AST into several compile units based on a size
   212      * heuristic Splitter needs attributed AST for weight calculations (e.g. is
   303      * heuristic Splitter needs attributed AST for weight calculations (e.g. is
   213      * a + b a ScriptRuntime.ADD with call overhead or a dadd with much less).
   304      * a + b a ScriptRuntime.ADD with call overhead or a dadd with much less).
   214      * Split IR can lead to scope information being changed.
   305      * Split IR can lead to scope information being changed.
   215      */
   306      */
   216     SPLITTING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR)) {
   307     SPLITTING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR)) {
   217         @Override
   308         @Override
   218         FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
   309         FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
   219             final CompileUnit outermostCompileUnit = compiler.addCompileUnit(compiler.firstCompileUnitName());
   310             final CompileUnit outermostCompileUnit = compiler.addCompileUnit(compiler.firstCompileUnitName());
   220 
   311 
   221 //            assert fn.isProgram() ;
       
   222             final FunctionNode newFunctionNode = new Splitter(compiler, fn, outermostCompileUnit).split(fn);
   312             final FunctionNode newFunctionNode = new Splitter(compiler, fn, outermostCompileUnit).split(fn);
   223 
   313 
   224             assert newFunctionNode.getCompileUnit() == outermostCompileUnit : "fn.compileUnit (" + newFunctionNode.getCompileUnit() + ") != " + outermostCompileUnit;
   314             assert newFunctionNode.getCompileUnit() == outermostCompileUnit : "fn.compileUnit (" + newFunctionNode.getCompileUnit() + ") != " + outermostCompileUnit;
   225 
   315 
   226             if (newFunctionNode.isStrict()) {
   316             if (newFunctionNode.isStrict()) {