Thu, 05 Feb 2015 19:08:00 +0530
8072595: nashorn should not use obj.getClass() for null checks
Reviewed-by: hannesw, attila
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.Objects;
30 import java.util.Set;
31 import java.util.TreeSet;
32 import jdk.nashorn.internal.ir.CompileUnitHolder;
34 /**
35 * Used to track split class compilation. Note that instances of the class are serializable, but all fields are
36 * transient, making the serialized version of the class only useful for tracking the referential topology of other
37 * AST nodes referencing the same or different compile units. We do want to preserve this topology though as
38 * {@link CompileUnitHolder}s in a deserialized AST will undergo reinitialization.
39 */
40 public final class CompileUnit implements Comparable<CompileUnit>, Serializable {
41 private static final long serialVersionUID = 1L;
43 /** Current class name */
44 private transient final String className;
46 /** Current class generator */
47 private transient ClassEmitter classEmitter;
49 private transient long weight;
51 private transient Class<?> clazz;
53 private transient boolean isUsed;
55 private static int emittedUnitCount;
57 CompileUnit(final String className, final ClassEmitter classEmitter, final long initialWeight) {
58 this.className = className;
59 this.weight = initialWeight;
60 this.classEmitter = classEmitter;
61 }
63 static Set<CompileUnit> createCompileUnitSet() {
64 return new TreeSet<>();
65 }
67 static void increaseEmitCount() {
68 emittedUnitCount++;
69 }
71 /**
72 * Get the amount of emitted compile units so far in the system
73 * @return emitted compile unit count
74 */
75 public static int getEmittedUnitCount() {
76 return emittedUnitCount;
77 }
79 /**
80 * Check if this compile unit is used
81 * @return true if tagged as in use - i.e active code that needs to be generated
82 */
83 public boolean isUsed() {
84 return isUsed;
85 }
87 /**
88 * Check if a compile unit has code, not counting inits and clinits
89 * @return true of if there is "real code" in the compile unit
90 */
91 public boolean hasCode() {
92 return (classEmitter.getMethodCount() - classEmitter.getInitCount() - classEmitter.getClinitCount()) > 0;
93 }
95 /**
96 * Tag this compile unit as used
97 */
98 public void setUsed() {
99 this.isUsed = true;
100 }
102 /**
103 * Return the class that contains the code for this unit, null if not
104 * generated yet
105 *
106 * @return class with compile unit code
107 */
108 public Class<?> getCode() {
109 return clazz;
110 }
112 /**
113 * Set class when it exists. Only accessible from compiler
114 * @param clazz class with code for this compile unit
115 */
116 void setCode(final Class<?> clazz) {
117 Objects.requireNonNull(clazz);
118 this.clazz = clazz;
119 // Revisit this - refactor to avoid null-ed out non-final fields
120 // null out emitter
121 this.classEmitter = null;
122 }
124 /**
125 * Add weight to this compile unit
126 * @param w weight to add
127 */
128 void addWeight(final long w) {
129 this.weight += w;
130 }
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 }
141 /**
142 * Get the class emitter for this compile unit
143 * @return class emitter
144 */
145 public ClassEmitter getClassEmitter() {
146 return classEmitter;
147 }
149 /**
150 * Get the class name for this compile unit
151 * @return the class name
152 */
153 public String getUnitClassName() {
154 return className;
155 }
157 private static String shortName(final String name) {
158 return name == null ? null : name.lastIndexOf('/') == -1 ? name : name.substring(name.lastIndexOf('/') + 1);
159 }
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 }
167 @Override
168 public int compareTo(final CompileUnit o) {
169 return className.compareTo(o.className);
170 }
171 }