CompileUnit.java revision 1036:f0b5e3900a10
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 */
25
26package jdk.nashorn.internal.codegen;
27
28import java.util.Set;
29import java.util.TreeSet;
30
31/**
32 * Used to track split class compilation.
33 */
34public final class CompileUnit implements Comparable<CompileUnit> {
35    /** Current class name */
36    private final String className;
37
38    /** Current class generator */
39    private ClassEmitter classEmitter;
40
41    private long weight;
42
43    private Class<?> clazz;
44
45    private boolean isUsed;
46
47    private static int emittedUnitCount;
48
49    CompileUnit(final String className, final ClassEmitter classEmitter, final long initialWeight) {
50        this.className    = className;
51        this.weight       = initialWeight;
52        this.classEmitter = classEmitter;
53    }
54
55    static Set<CompileUnit> createCompileUnitSet() {
56        return new TreeSet<>();
57    }
58
59    static void increaseEmitCount() {
60        emittedUnitCount++;
61    }
62
63    /**
64     * Get the amount of emitted compile units so far in the system
65     * @return emitted compile unit count
66     */
67    public static int getEmittedUnitCount() {
68        return emittedUnitCount;
69    }
70
71    /**
72     * Check if this compile unit is used
73     * @return true if tagged as in use - i.e active code that needs to be generated
74     */
75    public boolean isUsed() {
76        return isUsed;
77    }
78
79    /**
80     * Check if a compile unit has code, not counting inits and clinits
81     * @return true of if there is "real code" in the compile unit
82     */
83    public boolean hasCode() {
84        return (classEmitter.getMethodCount() - classEmitter.getInitCount() - classEmitter.getClinitCount()) > 0;
85    }
86
87    /**
88     * Tag this compile unit as used
89     */
90    public void setUsed() {
91        this.isUsed = true;
92    }
93
94    /**
95     * Return the class that contains the code for this unit, null if not
96     * generated yet
97     *
98     * @return class with compile unit code
99     */
100    public Class<?> getCode() {
101        return clazz;
102    }
103
104    /**
105     * Set class when it exists. Only accessible from compiler
106     * @param clazz class with code for this compile unit
107     */
108    void setCode(final Class<?> clazz) {
109        clazz.getClass(); // null check
110        this.clazz = clazz;
111        // Revisit this - refactor to avoid null-ed out non-final fields
112        // null out emitter
113        this.classEmitter = null;
114    }
115
116    /**
117     * Add weight to this compile unit
118     * @param w weight to add
119     */
120    void addWeight(final long w) {
121        this.weight += w;
122    }
123
124    /**
125     * Get the current weight of the compile unit.
126     * @return the unit's weight
127     */
128    long getWeight() {
129        return weight;
130    }
131
132    /**
133     * Check if this compile unit can hold {@code weight} more units of weight
134     * @param w weight to check if can be added
135     * @return true if weight fits in this compile unit
136     */
137    public boolean canHold(final long w) {
138        return (this.weight + w) < Splitter.SPLIT_THRESHOLD;
139    }
140
141    /**
142     * Get the class emitter for this compile unit
143     * @return class emitter
144     */
145    public ClassEmitter getClassEmitter() {
146        return classEmitter;
147    }
148
149    /**
150     * Get the class name for this compile unit
151     * @return the class name
152     */
153    public String getUnitClassName() {
154        return className;
155    }
156
157    private static String shortName(final String name) {
158        return name.lastIndexOf('/') == -1 ? name : name.substring(name.lastIndexOf('/') + 1);
159    }
160
161    @Override
162    public String toString() {
163        final String methods = classEmitter != null ? classEmitter.getMethodNames().toString() : "<anon>";
164        return "[CompileUnit className=" + shortName(className) + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + " hasCode=" + methods + ']';
165    }
166
167    @Override
168    public int compareTo(final CompileUnit o) {
169        return className.compareTo(o.className);
170    }
171}
172