001: /*
002: * @(#)CVMClass.java 1.34 06/10/22
003: *
004: * Copyright 1990-2006 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:
028: package vm;
029:
030: /*
031: * CVM-specific internal representation of
032: * a class. Target-machine independent.
033: * There is a references from each instance of components.ClassInfo to
034: * one of these, and a reference back as well.
035: * Derived from the JDK-specific ClassClass
036: *
037: * !!See also CVMVM for VM-specific info not associated directly with a class.
038: */
039: import components.*;
040: import util.*;
041: import consts.Const;
042: import consts.CVMConst;
043: import java.util.Enumeration;
044: import java.util.Vector;
045: import java.util.Hashtable;
046: import java.util.StringTokenizer;
047:
048: public class CVMClass extends ClassClass implements Const, CVMConst,
049: CVMTypeCode {
050: public CVMMethodInfo methods[];
051: private String myNativeName;
052: protected int typeCode = 0;
053: protected int classId = CVM_T_ERROR;
054:
055: public int nStaticWords;
056: public int nStaticRef;
057: public FieldInfo statics[];
058:
059: //
060: // Most methods are compressible, which makes their enclosing class
061: // compressible
062: //
063: private boolean isCompressible = true;
064:
065: public CVMClass(ClassInfo c) {
066: ci = c;
067: c.vmClass = this ;
068:
069: if (c.methods != null) {
070: // per-method, CVM-specific info.
071: methods = new CVMMethodInfo[c.methods.length];
072: for (int i = 0; i < methods.length; i++) {
073: components.MethodInfo m = c.methods[i];
074: methods[i] = new CVMMethodInfo(m);
075: if (!hasStaticInitializer && m.isStaticMember()
076: && m.name.string.equals(/*NOI18N*/"<clinit>")) {
077: hasStaticInitializer = true;
078: }
079: }
080: }
081: }
082:
083: public void setCompressible(boolean isCompressible) {
084: this .isCompressible = isCompressible;
085: }
086:
087: public boolean isCompressible() {
088: return this .isCompressible;
089: }
090:
091: public String getNativeName() {
092: if (myNativeName == null) {
093: if (ci instanceof ArrayClassInfo) {
094: ArrayClassInfo aci = (ArrayClassInfo) ci;
095: if (aci.depth == 1) {
096: /*
097: * There are some special arrays of well-known basic
098: * types here.
099: */
100: if (aci.baseType != Const.T_CLASS) {
101: myNativeName = "manufacturedArrayOf"
102: + aci.getNativeName();
103: } else if (aci.baseClass.find().super ClassInfo == null) {
104: myNativeName = "manufacturedArrayOfObject";
105: } else {
106: myNativeName = "manufacturedArrayClass"
107: + aci.arrayClassNumber;
108: }
109: } else {
110: myNativeName = "manufacturedArrayClass"
111: + aci.arrayClassNumber;
112: }
113: } else {
114: myNativeName = ci.getGenericNativeName();
115: }
116: }
117: return myNativeName;
118: }
119:
120: public int CVMflags() {
121: int flagval = 0;
122: int a = ci.access;
123: if ((a & ACC_PUBLIC) != 0)
124: flagval |= CVM_CLASS_ACC_PUBLIC;
125: if ((a & ACC_FINAL) != 0)
126: flagval |= CVM_CLASS_ACC_FINAL;
127: if ((a & ACC_SUPER) != 0)
128: flagval |= CVM_CLASS_ACC_SUPER;
129: if ((a & ACC_INTERFACE) != 0)
130: flagval |= CVM_CLASS_ACC_INTERFACE;
131: if ((a & ACC_ABSTRACT) != 0)
132: flagval |= CVM_CLASS_ACC_ABSTRACT;
133: if (isPrimitiveClass())
134: flagval |= CVM_CLASS_ACC_PRIMITIVE;
135: if (ci.hasNonTrivialFinalizer)
136: flagval |= CVM_CLASS_ACC_FINALIZABLE;
137: if (ci.isReference())
138: flagval |= CVM_CLASS_ACC_REFERENCE;
139: return flagval;
140:
141: }
142:
143: public int typecode() {
144: return typeCode;
145: }
146:
147: public int classid() {
148: return classId;
149: }
150:
151: public void orderStatics() {
152: // count statics.
153: // arranged them ref-first
154: // do not assign offsets.
155: FieldInfo f[] = ci.fields;
156: nStaticWords = 0;
157: if ((f == null) || (f.length == 0))
158: return; // nothing to do.
159: int nFields = f.length;
160: int nStatic = 0;
161: int nRef = 0;
162: for (int i = 0; i < nFields; i++) {
163: FieldInfo fld = f[i];
164: if (fld.isStaticMember()) {
165: nStatic += 1;
166: char toptype = fld.type.string.charAt(0);
167: if ((toptype == 'L') || (toptype == '['))
168: nRef += 1;
169: }
170: }
171: int refOff = 0;
172: int scalarOff = nRef;
173: int totalStaticWords = nRef;
174: statics = new FieldInfo[nStatic];
175: for (int i = 0; i < nFields; i++) {
176: FieldInfo fld = f[i];
177: if (fld.isStaticMember()) {
178: char toptype = fld.type.string.charAt(0);
179: if ((toptype == 'L') || (toptype == '[')) {
180: statics[refOff] = fld;
181: refOff += 1;
182: } else {
183: statics[scalarOff] = fld;
184: scalarOff += 1;
185: totalStaticWords += fld.nSlots;
186: }
187: }
188: }
189: nStaticWords = totalStaticWords;
190: nStaticRef = nRef;
191: }
192:
193: /* Inline all the methods in this code object */
194: public void getInlining() {
195: for (int i = 0; i < methods.length; i++) {
196: methods[i].getInlining();
197: }
198: }
199:
200: public boolean adjustSymbolicConstants(
201: UnresolvedReferenceList missingReferences) {
202: ConstantPool cp = ci.getConstantPool();
203:
204: if (!isPartiallyResolved(cp)) {
205: return true;
206: }
207: makeResolvable(cp, missingReferences, ci.className);
208: impureConstants = true;
209: return false;
210: }
211:
212: public static void makeResolvable(ConstantPool cp,
213: UnresolvedReferenceList missingReferences, String source) {
214: //
215: // This is easy.
216: // There is no change to the structure of the constant pool.
217: // Mark the pool as impure and emit a bunch of warning
218: // messages. We don't need to add utf8's to the pool!
219: //
220: ConstantObject consts[] = cp.getConstants();
221: int nconst = cp.getLength();
222: for (int i = 1; i < nconst; i += consts[i].nSlots) {
223: ConstantObject o;
224: String className;
225: o = consts[i];
226: if (o.isResolved()) {
227: continue;
228: }
229: switch (o.tag) {
230: case Const.CONSTANT_CLASS:
231: ClassConstant co = (ClassConstant) o;
232: className = co.name.string;
233: missingReferences.add(o, source);
234: continue;
235: case Const.CONSTANT_FIELD:
236: case Const.CONSTANT_METHOD:
237: case Const.CONSTANT_INTERFACEMETHOD:
238: FMIrefConstant fo = (FMIrefConstant) o;
239: if (fo.clas.isResolved()) {
240: // This is a missing member of a resolved class.
241: // Print this out
242: // To print all the references to a totally missing
243: // Add it to the list.
244: missingReferences.add(o, source);
245:
246: }
247: /* else ...
248: * we will also stumble across the unresolved ClassConstant
249: * object and will add it to the list in the above case.
250: */
251:
252: /*
253: * If this memberRef constant is in the shared pool,
254: * the the constants it references had better be as well.
255: * If it is not, then they had better not be either.
256: */
257: if (fo.shared) {
258: ClassConstant cc = fo.clas;
259: NameAndTypeConstant sig = fo.sig;
260: if (cc.shared) {
261: // This is not likely at all.
262: if (cc.containingPool != fo.containingPool) {
263: throw new ValidationException(
264: "MemberRef and Class in different pools "
265: + fo);
266: }
267: } else {
268: // oops. Need to make sure I can reference a shared
269: // class constant.
270: cc = (ClassConstant) fo.containingPool
271: .lookup(cc);
272: if (cc == null) {
273: throw new ValidationException(
274: "Shared MemberRef referenced Class not in shared pool "
275: + fo);
276: }
277: fo.clas = cc;
278: }
279: if (sig.shared) {
280: // This is not likely at all.
281: if (sig.containingPool != fo.containingPool) {
282: throw new ValidationException(
283: "MemberRef and NameAndType in different pools "
284: + fo);
285: }
286: } else {
287: // oops. Need to make sure I can reference a shared
288: // NameAndType constant.
289: sig = (NameAndTypeConstant) fo.containingPool
290: .lookup(sig);
291: if (sig == null) {
292: throw new ValidationException(
293: "Shared MemberRef referenced NameAndType not in shared pool "
294: + fo);
295: }
296: fo.sig = sig;
297: }
298: } else if (fo.clas.shared || fo.sig.shared) {
299: throw new ValidationException(
300: "Shared clas/sig referenced from unshared memberRef "
301: + fo);
302: }
303: continue;
304: }
305: }
306: }
307:
308: /*
309: * Moved globals to CVMROMGlobals.
310: * This requires that we can identify classes that contain writeable
311: * methods.
312: * The code to decide about writeability is copied from
313: * CVMWriter.writeMethods().
314: */
315: public boolean hasWritableMethods() {
316: for (int i = 0; i < methods.length; i++) {
317: if (methods[i].codeHasJsr())
318: return true;
319: }
320:
321: return false;
322: }
323: }
|