1 /*
2 * Copyright 2000-2007 Sun Microsystems, Inc. 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25 package sun.jvm.hotspot.oops;
26
27 import java.io.*;
28 import java.util.*;
29 import sun.jvm.hotspot.debugger.*;
30 import sun.jvm.hotspot.runtime.*;
31 import sun.jvm.hotspot.types.*;
32 import sun.jvm.hotspot.utilities.*;
33
34 public class Klass extends Oop implements ClassConstants {
35 static {
36 VM.registerVMInitializedObserver(new Observer() {
37 public void update(Observable o, Object data) {
38 initialize(VM.getVM().getTypeDataBase());
39 }
40 });
41 }
42
43 // anon-enum constants for _layout_helper.
44 public static int LH_FLAGS_BITS;
45 public static int LH_FLAGS_SHIFT;
46 public static int LH_FLAGS_LOW_BITS;
47 public static int LH_VARIABLE_FLAG;
48 public static int LH_ARRAY_FLAG;
49 public static int LH_FLAGS_EBT_MASK;
50 public static int LH_ELEMENT_SIZE_BITS;
51 public static int LH_ELEMENT_SIZE_SHIFT;
52 public static int LH_ELEMENT_SCALE_BITS;
53 public static int LH_ELEMENT_SIZEM_BITS;
54 public static int LH_ELEMENT_SIZEM_MASK_IP;
55 public static int LH_SIZE_LOW_BITS;
56 public static int LH_SLOW_PATH_LOW_BIT;
57 public static int LH_HEADER_SIZE_BITS;
58 public static int LH_HEADER_SIZE_SHIFT;
59 public static int LH_FIXED_SIZE_BITS;
60 public static int LH_FIXED_SIZE_SHIFT;
61
62
63 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
64 Type type = db.lookupType("Klass");
65 javaMirror = new OopField(type.getOopField("_java_mirror"), Oop.getHeaderSize());
66 superField = new OopField(type.getOopField("_super"), Oop.getHeaderSize());
67 layoutHelper = new IntField(type.getJIntField("_layout_helper"), Oop.getHeaderSize());
68 name = new OopField(type.getOopField("_name"), Oop.getHeaderSize());
69 accessFlags = new CIntField(type.getCIntegerField("_access_flags"), Oop.getHeaderSize());
70 subklass = new OopField(type.getOopField("_subklass"), Oop.getHeaderSize());
71 nextSibling = new OopField(type.getOopField("_next_sibling"), Oop.getHeaderSize());
72 allocCount = new CIntField(type.getCIntegerField("_alloc_count"), Oop.getHeaderSize());
73
74 LH_FLAGS_BITS = db.lookupIntConstant("LayoutHelper::_flags_bits").intValue();
75 LH_FLAGS_SHIFT = db.lookupIntConstant("LayoutHelper::_flags_shift").intValue();
76 LH_FLAGS_LOW_BITS = db.lookupIntConstant("LayoutHelper::_flags_low_bits").intValue();
77 LH_VARIABLE_FLAG = db.lookupIntConstant("LayoutHelper::_variable_flag").intValue();
78 LH_ARRAY_FLAG = db.lookupIntConstant("LayoutHelper::_array_flag").intValue();
79 LH_FLAGS_EBT_MASK = db.lookupIntConstant("LayoutHelper::_flags_ebt_mask").intValue();
80 LH_ELEMENT_SIZE_BITS = db.lookupIntConstant("LayoutHelper::_element_size_bits").intValue();
81 LH_ELEMENT_SIZE_SHIFT = db.lookupIntConstant("LayoutHelper::_element_size_shift").intValue();
82 LH_ELEMENT_SCALE_BITS = db.lookupIntConstant("LayoutHelper::_element_scale_bits").intValue();
83 LH_ELEMENT_SIZEM_BITS = db.lookupIntConstant("LayoutHelper::_element_sizem_bits").intValue();
84 LH_ELEMENT_SIZEM_MASK_IP = db.lookupIntConstant("LayoutHelper::_element_sizem_mask_ip").intValue();
85 LH_SIZE_LOW_BITS = db.lookupIntConstant("LayoutHelper::_fixed_size_low_bits").intValue();
86 LH_SLOW_PATH_LOW_BIT = db.lookupIntConstant("LayoutHelper::_slow_path_low_bit").intValue();
87 LH_HEADER_SIZE_BITS = db.lookupIntConstant("LayoutHelper::_header_size_bits").intValue();
88 LH_HEADER_SIZE_SHIFT = db.lookupIntConstant("LayoutHelper::_header_size_shift").intValue();
89 LH_FIXED_SIZE_BITS = db.lookupIntConstant("LayoutHelper::_fixed_size_bits").intValue();
90 LH_FIXED_SIZE_SHIFT = db.lookupIntConstant("LayoutHelper::_fixed_size_shift").intValue();
91 }
92
93 Klass(OopHandle handle, ObjectHeap heap) {
94 super(handle, heap);
95 }
96
97 // jvmdi support - see also class_status in VM code
98 public int getClassStatus() {
99 return 0; // overridden in derived classes
100 }
101
102 public boolean isKlass() { return true; }
103
104 // Fields
105 private static OopField javaMirror;
106 private static OopField superField;
107 private static IntField layoutHelper;
108 private static OopField name;
109 private static CIntField accessFlags;
110 private static OopField subklass;
111 private static OopField nextSibling;
112 private static CIntField allocCount;
113
114 // Accessors for declared fields
115 public Instance getJavaMirror() { return (Instance) javaMirror.getValue(this); }
116 public Klass getSuper() { return (Klass) superField.getValue(this); }
117 public Klass getJavaSuper() { return null; }
118 public int getLayoutHelper() { return (int) layoutHelper.getValue(this); }
119 public Symbol getName() { return (Symbol) name.getValue(this); }
120 public long getAccessFlags() { return accessFlags.getValue(this); }
121 // Convenience routine
122 public AccessFlags getAccessFlagsObj(){ return new AccessFlags(getAccessFlags()); }
123 public Klass getSubklassKlass() { return (Klass) subklass.getValue(this); }
124 public Klass getNextSiblingKlass() { return (Klass) nextSibling.getValue(this); }
125 public long getAllocCount() { return allocCount.getValue(this); }
126
127 public boolean isVariableObject() { return getLayoutHelper() < 0; }
128 public boolean isFixedInstance() { return getLayoutHelper() > 0; }
129
130 public long getHeaderSizeInBytes() {
131 if (Assert.ASSERTS_ENABLED) {
132 Assert.that(isVariableObject(), "layout helper initialized for variable class");
133 }
134 return Bits.maskBits(getLayoutHelper() >> LH_HEADER_SIZE_SHIFT,
135 (Bits.rightNBits(LH_HEADER_SIZE_BITS)
136 - Bits.rightNBits(LH_SIZE_LOW_BITS)));
137 }
138
139 public int getElementSize() {
140 if (Assert.ASSERTS_ENABLED) {
141 Assert.that(isVariableObject(), "layout helper initialized for variable class");
142 }
143 int lh = getLayoutHelper();
144 int scale = Bits.maskBits(lh >> LH_ELEMENT_SIZE_SHIFT,
145 Bits.rightNBits(LH_ELEMENT_SCALE_BITS));
146 int sizem = Bits.maskBits(lh >> (LH_ELEMENT_SIZE_SHIFT + LH_ELEMENT_SCALE_BITS),
147 Bits.rightNBits(LH_ELEMENT_SIZEM_BITS));
148 return (sizem + 1) << scale;
149 }
150
151 public int getElementType() {
152 if (Assert.ASSERTS_ENABLED) {
153 Assert.that(isVariableObject(), "layout helper initialized for variable class");
154 }
155 return Bits.maskBits(getLayoutHelper() >> LH_FLAGS_SHIFT,
156 Bits.rightNBits(LH_FLAGS_EBT_MASK));
157 }
158
159 // computed access flags - takes care of inner classes etc.
160 // This is closer to actual source level than getAccessFlags() etc.
161 public long computeModifierFlags() {
162 return 0L; // Unless overridden, modifier_flags is 0.
163 }
164
165 // same as JVM_GetClassModifiers
166 public final long getClassModifiers() {
167 // unlike the VM counterpart we never have to deal with primitive type,
168 // because we operator on Klass and not an instance of java.lang.Class.
169 long flags = computeModifierFlags();
170 if (isSuper()) {
171 flags |= JVM_ACC_SUPER;
172 }
173 return flags;
174 }
175
176 // subclass check
177 public boolean isSubclassOf(Klass k) {
178 if (k != null) {
179 Klass t = this;
180 // Run up the super chain and check
181 while (t != null) {
182 if (t.equals(k)) return true;
183 t = t.getSuper();
184 }
185 }
186 return false;
187 }
188
189 // subtype check
190 public boolean isSubtypeOf(Klass k) {
191 return computeSubtypeOf(k);
192 }
193
194 boolean computeSubtypeOf(Klass k) {
195 return isSubclassOf(k);
196 }
197
198 // Find LCA (Least Common Ancester) in class heirarchy
199 public Klass lca( Klass k2 ) {
200 Klass k1 = this;
201 while ( true ) {
202 if ( k1.isSubtypeOf(k2) ) return k2;
203 if ( k2.isSubtypeOf(k1) ) return k1;
204 k1 = k1.getSuper();
205 k2 = k2.getSuper();
206 }
207 }
208
209 public void printValueOn(PrintStream tty) {
210 tty.print("Klass");
211 }
212
213 public void iterateFields(OopVisitor visitor, boolean doVMFields) {
214 super.iterateFields(visitor, doVMFields);
215 if (doVMFields) {
216 visitor.doOop(javaMirror, true);
217 visitor.doOop(superField, true);
218 visitor.doInt(layoutHelper, true);
219 visitor.doOop(name, true);
220 visitor.doCInt(accessFlags, true);
221 visitor.doOop(subklass, true);
222 visitor.doOop(nextSibling, true);
223 visitor.doCInt(allocCount, true);
224 }
225 }
226
227 public long getObjectSize() {
228 throw new RuntimeException("should not reach here");
229 }
230
231 /** Array class with specific rank */
232 public Klass arrayKlass(int rank) { return arrayKlassImpl(false, rank); }
233 /** Array class with this klass as element type */
234 public Klass arrayKlass() { return arrayKlassImpl(false); }
235 /** These will return null instead of allocating on the heap */
236 public Klass arrayKlassOrNull(int rank) { return arrayKlassImpl(true, rank); }
237 public Klass arrayKlassOrNull() { return arrayKlassImpl(true); }
238
239 public Klass arrayKlassImpl(boolean orNull, int rank) {
240 throw new RuntimeException("array_klass should be dispatched to instanceKlass, objArrayKlass or typeArrayKlass");
241 }
242
243 public Klass arrayKlassImpl(boolean orNull) {
244 throw new RuntimeException("array_klass should be dispatched to instanceKlass, objArrayKlass or typeArrayKlass");
245 }
246
247 // This returns the name in the form java/lang/String which isn't really a signature
248 // The subclasses override this to produce the correct form, eg
249 // Ljava/lang/String; For ArrayKlasses getName itself is the signature.
250 public String signature() { return getName().asString(); }
251
252 // Convenience routines
253 public boolean isPublic() { return getAccessFlagsObj().isPublic(); }
254 public boolean isFinal() { return getAccessFlagsObj().isFinal(); }
255 public boolean isInterface() { return getAccessFlagsObj().isInterface(); }
256 public boolean isAbstract() { return getAccessFlagsObj().isAbstract(); }
257 public boolean isSuper() { return getAccessFlagsObj().isSuper(); }
258 public boolean isSynthetic() { return getAccessFlagsObj().isSynthetic(); }
259 public boolean hasFinalizer() { return getAccessFlagsObj().hasFinalizer(); }
260 public boolean isCloneable() { return getAccessFlagsObj().isCloneable(); }
261 public boolean hasVanillaConstructor() { return getAccessFlagsObj().hasVanillaConstructor(); }
262 public boolean hasMirandaMethods () { return getAccessFlagsObj().hasMirandaMethods(); }
263 }