src/jdk/nashorn/internal/codegen/CompileUnit.java

Mon, 27 Apr 2015 12:50:21 +0200

author
hannesw
date
Mon, 27 Apr 2015 12:50:21 +0200
changeset 1337
248dc4f11e5b
parent 1231
701c1dcdf733
child 1399
22640d19073c
permissions
-rw-r--r--

8053905: Eager code generation fails for earley boyer with split threshold set to 1000
Reviewed-by: attila, lagergren

     1 /*
     2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package jdk.nashorn.internal.codegen;
    28 import java.io.Serializable;
    29 import java.util.Collection;
    30 import java.util.Collections;
    31 import java.util.IdentityHashMap;
    32 import java.util.Map;
    33 import java.util.Objects;
    34 import java.util.Set;
    35 import java.util.TreeSet;
    36 import jdk.nashorn.internal.ir.CompileUnitHolder;
    37 import jdk.nashorn.internal.ir.FunctionNode;
    38 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
    40 /**
    41   * Used to track split class compilation. Note that instances of the class are serializable, but all fields are
    42   * transient, making the serialized version of the class only useful for tracking the referential topology of other
    43   * AST nodes referencing the same or different compile units. We do want to preserve this topology though as
    44   * {@link CompileUnitHolder}s in a deserialized AST will undergo reinitialization.
    45   */
    46 public final class CompileUnit implements Comparable<CompileUnit>, Serializable {
    47     private static final long serialVersionUID = 1L;
    49     /** Current class name */
    50     private transient final String className;
    52     /** Current class generator */
    53     private transient ClassEmitter classEmitter;
    55     private transient long weight;
    57     private transient Class<?> clazz;
    59     private transient Map<FunctionNode, RecompilableScriptFunctionData> functions = new IdentityHashMap<>();
    61     private transient boolean isUsed;
    63     private static int emittedUnitCount;
    65     CompileUnit(final String className, final ClassEmitter classEmitter, final long initialWeight) {
    66         this.className    = className;
    67         this.weight       = initialWeight;
    68         this.classEmitter = classEmitter;
    69     }
    71     static Set<CompileUnit> createCompileUnitSet() {
    72         return new TreeSet<>();
    73     }
    75     static void increaseEmitCount() {
    76         emittedUnitCount++;
    77     }
    79     /**
    80      * Get the amount of emitted compile units so far in the system
    81      * @return emitted compile unit count
    82      */
    83     public static int getEmittedUnitCount() {
    84         return emittedUnitCount;
    85     }
    87     /**
    88      * Check if this compile unit is used
    89      * @return true if tagged as in use - i.e active code that needs to be generated
    90      */
    91     public boolean isUsed() {
    92         return isUsed;
    93     }
    95     /**
    96      * Check if a compile unit has code, not counting inits and clinits
    97      * @return true of if there is "real code" in the compile unit
    98      */
    99     public boolean hasCode() {
   100         return (classEmitter.getMethodCount() - classEmitter.getInitCount() - classEmitter.getClinitCount()) > 0;
   101     }
   103     /**
   104      * Tag this compile unit as used
   105      */
   106     public void setUsed() {
   107         this.isUsed = true;
   108     }
   110     /**
   111      * Return the class that contains the code for this unit, null if not
   112      * generated yet
   113      *
   114      * @return class with compile unit code
   115      */
   116     public Class<?> getCode() {
   117         return clazz;
   118     }
   120     /**
   121      * Set class when it exists. Only accessible from compiler
   122      * @param clazz class with code for this compile unit
   123      */
   124     void setCode(final Class<?> clazz) {
   125         Objects.requireNonNull(clazz);
   126         this.clazz = clazz;
   127         // Revisit this - refactor to avoid null-ed out non-final fields
   128         // null out emitter
   129         this.classEmitter = null;
   130     }
   132     void addFunctionInitializer(final RecompilableScriptFunctionData data, final FunctionNode functionNode) {
   133         functions.put(functionNode, data);
   134     }
   136     /**
   137      * Returns true if this compile unit is responsible for initializing the specified function data with specified
   138      * function node.
   139      * @param data the function data to check
   140      * @param functionNode the function node to check
   141      * @return true if this unit is responsible for initializing the function data with the function node, otherwise
   142      * false
   143      */
   144     public boolean isInitializing(final RecompilableScriptFunctionData data, final FunctionNode functionNode) {
   145         return functions.get(functionNode) == data;
   146     }
   148     void initializeFunctionsCode() {
   149         for(final Map.Entry<FunctionNode, RecompilableScriptFunctionData> entry : functions.entrySet()) {
   150             entry.getValue().initializeCode(entry.getKey());
   151         }
   152     }
   154     Collection<FunctionNode> getFunctionNodes() {
   155         return Collections.unmodifiableCollection(functions.keySet());
   156     }
   158     /**
   159      * Add weight to this compile unit
   160      * @param w weight to add
   161      */
   162     void addWeight(final long w) {
   163         this.weight += w;
   164     }
   166     /**
   167      * Check if this compile unit can hold {@code weight} more units of weight
   168      * @param w weight to check if can be added
   169      * @return true if weight fits in this compile unit
   170      */
   171     public boolean canHold(final long w) {
   172         return (this.weight + w) < Splitter.SPLIT_THRESHOLD;
   173     }
   175     /**
   176      * Get the class emitter for this compile unit
   177      * @return class emitter
   178      */
   179     public ClassEmitter getClassEmitter() {
   180         return classEmitter;
   181     }
   183     /**
   184      * Get the class name for this compile unit
   185      * @return the class name
   186      */
   187     public String getUnitClassName() {
   188         return className;
   189     }
   191     private static String shortName(final String name) {
   192         return name == null ? null : name.lastIndexOf('/') == -1 ? name : name.substring(name.lastIndexOf('/') + 1);
   193     }
   195     @Override
   196     public String toString() {
   197         final String methods = classEmitter != null ? classEmitter.getMethodNames().toString() : "<anon>";
   198         return "[CompileUnit className=" + shortName(className) + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + " hasCode=" + methods + ']';
   199     }
   201     @Override
   202     public int compareTo(final CompileUnit o) {
   203         return className.compareTo(o.className);
   204     }
   205 }

mercurial