001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package vm;
028:
029: /*
030: * VM-specific internal representation of
031: * a class. Target-machine independent.
032: * There is a references from each instance of components.ClassInfo to
033: * one of these, and a reference back as well.
034: *
035: * See also JDKVM for VM-specific info not associated directly with a class.
036: */
037: import components.*;
038: import util.*;
039: import jcc.Const;
040: import jcc.Str2ID;
041: import java.util.Enumeration;
042: import java.util.Vector;
043: import java.util.Hashtable;
044: import java.util.StringTokenizer;
045:
046: public class ClassClass {
047: public ClassInfo ci;
048: public InterfaceMethodTable inf;
049: public boolean impureConstants = false;
050: public int nGCStatics = 0;
051: public boolean hasStaticInitializer = false;
052:
053: protected static int finalizerID = Str2ID.sigHash.getID(
054: /*NOI18N*/"finalize", /*NOI18N*/"()V");
055:
056: public MethodConstant findFinalizer() {
057: if (ci == null)
058: return null;
059: if (ci.refMethodtable == null)
060: return null;
061: int n = ci.refMethodtable.length;
062: for (int i = 0; i < n; i++) {
063: MethodConstant mc = ci.refMethodtable[i];
064: if (mc.getID() == finalizerID) {
065: if (mc.find().parent.super Class == null) {
066: /*
067: * since we know that java.lang.Object's
068: * finalizer does nothing, we can ignore
069: * its existence!
070: */
071: return null;
072: }
073: return mc;
074: }
075: }
076: return null;
077: }
078:
079: public static void setTypes() {
080: classFactory.setTypes();
081: }
082:
083: /*
084: * Make the class list into a vector
085: * ordered s.t. superclasses precede their
086: * subclasses.
087: */
088: private static ClassClass[] cvector;
089: private static int cindex;
090: private static VMClassFactory classFactory;
091:
092: // this is the recursive part
093: private static void insertClassElement(ClassInfo e) {
094: if (e.vmClass != null)
095: return; // already in place.
096: ClassInfo sup = e.super ClassInfo;
097: // make sure our super precedes us.
098: if ((sup != null) && (sup.vmClass == null))
099: insertClassElement(sup);
100: ClassClass newVmClass = classFactory.newVMClass(e);
101: cvector[cindex++] = newVmClass;
102: //
103: // If the superclass of class C has a <clinit> method, C must
104: // be marked as having a static initializer too.
105: //
106: if (!newVmClass.hasStaticInitializer && (sup != null)
107: && sup.vmClass.hasStaticInitializer) {
108: newVmClass.hasStaticInitializer = true;
109: }
110: }
111:
112: // this is the entry point for vector building.
113: public static ClassClass[] getClassVector(VMClassFactory ftry) {
114: if (cvector != null)
115: return cvector; // just once, at most.
116: classFactory = ftry;
117: cvector = new ClassClass[ClassInfo.nClasses()];
118: cindex = 0;
119: Enumeration classlist = ClassInfo.allClasses();
120: while (classlist.hasMoreElements()) {
121: ClassInfo e = (ClassInfo) classlist.nextElement();
122: if (e.vmClass == null)
123: insertClassElement(e);
124: }
125: return cvector;
126: }
127:
128: public static void appendClassElement(ClassInfo c) {
129: // foo. Have a cvector in place, must now
130: // add a new entry at the end. "c" is it.
131: if (cvector == null)
132: return; // ...never mind
133: ClassClass[] oldCvector = cvector;
134: cvector = new ClassClass[cindex + 1];
135: System.arraycopy(oldCvector, 0, cvector, 0, cindex);
136: cvector[cindex] = classFactory.newVMClass(c);
137: }
138:
139: /**
140: * Size of an instance in WORDS.
141: */
142: public int instanceSize() {
143: FieldConstant rft[] = ci.refFieldtable;
144: if (rft == null || rft.length == 0)
145: return 0;
146: FieldInfo lastField = rft[rft.length - 1].find();
147: return (lastField.instanceOffset + lastField.nSlots);
148: }
149:
150: public boolean isInterface() {
151: return (ci.access & Const.ACC_INTERFACE) != 0;
152: }
153:
154: public boolean hasMethodtable() {
155: return ((!isInterface()) && (ci.refMethodtable != null));
156: }
157:
158: public boolean isArrayClass() {
159: return (ci instanceof ArrayClassInfo);
160: }
161:
162: public boolean isPrimitiveClass() {
163: return (ci instanceof PrimitiveClassInfo);
164: }
165:
166: public int nmethods() {
167: return (ci.methods == null) ? 0 : ci.methods.length;
168: }
169:
170: public int nfields() {
171: return (ci.fields == null) ? 0 : ci.fields.length;
172: }
173:
174: /**
175: * In the current definition of module (.mclass) files,
176: * many sorts of constants are put in the shared constant
177: * pool, and never in the per-class constant pool. This includes
178: * Unicode constants and NameAndType constants. This is fine
179: * as long as all symbols in the per-class constant pools get
180: * resolved, as they won't be missed. However, if we wish to
181: * process classes with symbol references that are not fully
182: * resolved, we will have to add such elements into the constant
183: * pool. We do this by sweeping over the per-class constants,
184: * looking for method, field, and class references that are not
185: * resolved, and adding the necessary entries.
186: */
187: public void adjustSymbolicConstants() {
188: ConstantObject consts[] = ci.constants;
189: if (!isPartiallyResolved(consts)) {
190: return;
191: }
192: //
193: // we have work to do. This is unfortunate.
194: // we use a LocalConstantPool to manage the pool we're re-building.
195: // Because order matters, we collect the new entries to add at end.
196: //
197: //System.err.println(Localizer.getString("classclass.warning_class_has_an_impure_constant_pool", ci.className));
198: ci.constants = makeResolvable(consts).getConstants();
199: impureConstants = true;
200: }
201:
202: public static boolean isPartiallyResolved(ConstantObject[] consts) {
203: if (consts == null)
204: return false; // no const!
205: int nconst = consts.length;
206: if (nconst == 0)
207: return false; // no const!
208:
209: // first see if we have anything that needs our attention.
210: int nsymbolic = 0;
211: for (int i = 1; i < nconst; i += consts[i].nSlots) {
212: ConstantObject o = consts[i];
213: if (!o.isResolved()) {
214: return true;
215: }
216: }
217: return false;
218: }
219:
220: static public ConstantPool makeResolvable(ConstantPool cp) {
221: //
222: // we use a LocalConstantPool to manage the pool we're re-building.
223: // Because order matters, we collect the new entries to add at end.
224: //
225: System.err
226: .println(Localizer
227: .getString("classclass.warning_it_has_an_impure_shared_constant_pool"));
228: return makeResolvable(cp.getConstants());
229: }
230:
231: static private ConstantPool makeResolvable(ConstantObject[] consts) {
232:
233: LocalConstantPool newPool = new LocalConstantPool();
234: Vector newEntries = new Vector();
235: int nconst = consts.length;
236: for (int i = 1; i < nconst; i += consts[i].nSlots) {
237: ConstantObject o;
238: o = consts[i];
239: newPool.append(o);
240: if (!o.isResolved())
241: newEntries.addElement(o);
242: }
243: Enumeration newlist = newEntries.elements();
244: while (newlist.hasMoreElements()) {
245: ConstantObject o = (ConstantObject) newlist.nextElement();
246: switch (o.tag) {
247: case Const.CONSTANT_CLASS:
248: ClassConstant co = (ClassConstant) o;
249: System.err.println(Localizer.getString(
250: "classclass.class", co.name.string));
251: co.name = (UnicodeConstant) newPool.add(co.name);
252: continue;
253: case Const.CONSTANT_FIELD:
254: case Const.CONSTANT_METHOD:
255: case Const.CONSTANT_INTERFACEMETHOD:
256: FMIrefConstant fo = (FMIrefConstant) o;
257: if (fo.clas.isResolved() && false) {
258: // This is a missing member of a resolved class.
259: // Print this out
260: // To print all the references to a totally missing
261: // class would be redundant and noisy.
262: if (fo.tag == Const.CONSTANT_FIELD) {
263: System.err.print(Localizer
264: .getString("classclass.field"));
265: } else {
266: System.err.print(Localizer
267: .getString("classclass.method"));
268: }
269: System.err.println(Localizer.getString(
270: "classclass.of_class", fo.sig.name.string,
271: fo.sig.type.string, fo.clas.name.string));
272: }
273: // as NameAndTypeConstant entries are always "resolved",
274: // the strings they nominally point to need not be present:
275: // they will get written out as a hash ID.
276: fo.sig = (NameAndTypeConstant) newPool.add(fo.sig);
277: fo.clas.name = (UnicodeConstant) newPool
278: .add(fo.clas.name);
279: fo.clas = (ClassConstant) newPool.add(fo.clas);
280: continue;
281: }
282: }
283: newPool.impureConstants = true;
284: return newPool;
285: }
286:
287: }
288:
289: /*
290: * Like a constant pool, but with simpler semantics.
291: * Perhaps this and components.ConstantPool should be related.
292: * The important difference is in "add", which never shares
293: * and which always clones if it must insert!
294: * Also append, which is even simpler, as it assumes that we're
295: * loading up this constant pool from an already-existing list.
296: */
297: final class LocalConstantPool extends components.ConstantPool {
298:
299: public LocalConstantPool() {
300: super ();
301: }
302:
303: /**
304: * Return the ConstantObject in constant table corresponding to
305: * the given ConstantObject s.
306: * Duplicates and inserts s if it is not already there.
307: * The index member of the returned value (which
308: * will not be the object s!) will be set to its index in our
309: * table. There will be no element of index 0.
310: */
311: public ConstantObject add(ConstantObject s) {
312: ConstantObject r = (ConstantObject) h.get(s);
313: if (r == null) {
314: r = (ConstantObject) s.clone();
315: r.index = n;
316: n += r.nSlots;
317: h.put(r, r);
318: t.addElement(r);
319: for (int i = r.nSlots; i > 1; i--)
320: t.addElement(null); // place holder.
321: }
322: r.references += 1;
323: return r;
324: }
325:
326: public void append(ConstantObject s) {
327: if (h.get(s) != null) {
328: throw new Error(Localizer.getString(
329: "classclass.append.error_already_in_pool", s));
330: }
331: if (s.index != n) {
332: throw new Error(Localizer.getString(
333: "classclass.append.error_out_of_order", s));
334: }
335: h.put(s, s);
336: t.addElement(s);
337: s.references += 1;
338: for (int i = s.nSlots; i > 1; i--)
339: t.addElement(null); // place holder.
340: n += s.nSlots;
341: }
342: }
|