001: /*
002: * @(#)CVMDataType.java 1.9 06/10/10
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: * CVM has a complex scheme for representing types as 16-bit
029: * cookies. This code mimics the run-time code and thus builds the
030: * corresponding data structures, to be ROMed.
031: */
032:
033: package vm;
034:
035: import java.util.Vector;
036: import java.util.Enumeration;
037:
038: public abstract class CVMDataType implements CVMTypeCode,
039: util.ClassFileConst {
040:
041: /* instance data */
042: /* Instances of this only appear in the
043: * table. The only run-time external representation is
044: * the cookie that references a table entry. Here are
045: * the fields of the table.
046: */
047: public int entryNo;
048: public int typeNo;
049: public CVMDataType next; // hash chain
050:
051: /* see also the sub-types which contain all the interesting instance data */
052:
053: /* static data */
054: public static Vector dataTypes = new Vector();
055: static int nextEntryNo = 0;
056: static int nextTypeNo = CVMtypeLastScalar + 1;
057:
058: /* constructor &c */
059:
060: static synchronized void enlist(CVMDataType x) {
061: x.entryNo = nextEntryNo++;
062: x.typeNo = nextTypeNo++;
063: dataTypes.addElement(x);
064: }
065:
066: CVMDataType() {
067: enlist(this );
068: }
069:
070: /* instance methods */
071:
072: /* static methods */
073:
074: /*
075: * These really belong in CVMTypeCode...
076: */
077: public static boolean isArray(int t) {
078: return (((t) & CVMtypeArrayMask) != 0);
079: }
080:
081: public static boolean typeEquals(int t1, int t2) {
082: return ((t1) == (t2));
083: }
084:
085: public static boolean isBigArray(int t) {
086: return (((t) & CVMtypeArrayMask) == CVMtypeBigArray);
087: }
088:
089: /*
090: * Return count of table entries.
091: */
092: public static int nTableEntries() {
093: return dataTypes.size();
094: }
095:
096: /*
097: * We use a very simple minded name hashing scheme.
098: * Based on the LAST few letters of the name, which are
099: * the most likely to differ, I believe.
100: */
101: public static int computeHash(String name) {
102: int v = 0;
103: int t = name.length();
104: int n = Math.min(t, 7);
105: t -= n;
106: while (n-- > 0) {
107: v = (v * 19) + name.charAt(t + n) - '/';
108: }
109: return v;
110: }
111:
112: /*
113: * Class name is just a name, stripped of any envelopping
114: * L...;
115: */
116: static CVMClassDataType referenceClass(String className) {
117: // parse into class and package
118: // package may be null, of course.
119: // lookup package, use as primary key to finding
120: // the class.
121: int endPkg = className.lastIndexOf(SIGC_PACKAGE);
122: String pkgName;
123: String classInPkg;
124: if (endPkg < 0) {
125: pkgName = "";
126: classInPkg = className;
127: } else {
128: pkgName = className.substring(0, endPkg);
129: classInPkg = className.substring(endPkg + 1);
130: }
131: classInPkg = classInPkg.intern();
132: CVMpkg this Pkg = CVMpkg.lookup(pkgName);
133: //
134: // have a package, have a class-name-in-package.
135: // do simple lookup.
136: int nameHash = computeHash(classInPkg);
137: /* make sure % is unsigned! */
138: int bucket = (int) ((((long) nameHash) & 0xffffffffL) % CVMpkg.NCLASSHASH);
139: CVMDataType prev = null;
140: for (CVMDataType d = this Pkg.typeData[bucket]; d != null; d = d.next) {
141: if (d instanceof CVMClassDataType) {
142: CVMClassDataType c = (CVMClassDataType) d;
143: if (c.classInPackage == classInPkg)
144: return c;
145: }
146: prev = d;
147: }
148: // not there. add it.
149: CVMClassDataType c = new CVMClassDataType(this Pkg, classInPkg);
150: // at end of the chain, NOT AT HEAD.
151: if (prev == null) {
152: this Pkg.typeData[bucket] = c;
153: c.next = null;
154: } else {
155: prev.next = c;
156: c.next = null;
157: }
158: return c;
159: }
160:
161: static CVMArrayDataType referenceArray(int depth, int baseType) {
162: return referenceArray(depth, baseType, CVMpkg.nullPackage, 0);
163: }
164:
165: static CVMArrayDataType referenceArray(int depth, CVMClassDataType d) {
166: return referenceArray(depth, d.typeNo, d.pkg,
167: computeHash(d.classInPackage));
168: }
169:
170: static CVMArrayDataType referenceArray(int depth, int baseType,
171: CVMpkg this Pkg, int nameHash) {
172: //
173: // have a package,
174: // do simple lookup.
175: // make sure % is unsigned!
176: int bucket = (int) ((((long) nameHash) & 0xffffffffL) % CVMpkg.NCLASSHASH);
177: for (CVMDataType d = this Pkg.typeData[bucket]; d != null; d = d.next) {
178: if (d instanceof CVMArrayDataType) {
179: CVMArrayDataType a = (CVMArrayDataType) d;
180: if (a.depth == depth && a.baseType == baseType)
181: return a;
182: }
183: }
184: // not there. add it.
185: CVMArrayDataType a = new CVMArrayDataType(depth, baseType);
186: // at end...
187: a.next = this Pkg.typeData[bucket];
188: this Pkg.typeData[bucket] = a;
189: return a;
190: }
191:
192: public static int CVMtypeArrayDepth(int t) {
193: if (!isBigArray(t)) {
194: return t >> CVMtypeArrayShift;
195: }
196: CVMArrayDataType d = (CVMArrayDataType) (dataTypes.elementAt(t
197: & CVMtypeBasetypeMask));
198: return d.depth;
199: }
200:
201: public static int CVMtypeArrayBasetype(int t) {
202: if (!isBigArray(t)) {
203: return t & CVMtypeBasetypeMask;
204: }
205: CVMArrayDataType d = (CVMArrayDataType) (dataTypes.elementAt(t
206: & CVMtypeBasetypeMask));
207: return d.baseType;
208: }
209:
210: public static int parseSignature(String sig) {
211: int sigLength = sig.length();
212: int sigIndex = 0;
213:
214: int arrayDepth = 0;
215: int baseType = 0;
216:
217: CVMClassDataType d = null;
218:
219: while ((sigIndex < sigLength)
220: && (sig.charAt(sigIndex) == SIGC_ARRAY)) {
221: sigIndex += 1;
222: arrayDepth += 1;
223: }
224: if (sigIndex >= sigLength)
225: return CVM_T_ERROR;
226: switch (sig.charAt(sigIndex++)) {
227: case SIGC_VOID:
228: baseType = CVM_T_VOID;
229: break;
230: case SIGC_INT:
231: baseType = CVM_T_INT;
232: break;
233: case SIGC_SHORT:
234: baseType = CVM_T_SHORT;
235: break;
236: case SIGC_LONG:
237: baseType = CVM_T_LONG;
238: break;
239: case SIGC_BYTE:
240: baseType = CVM_T_BYTE;
241: break;
242: case SIGC_CHAR:
243: baseType = CVM_T_CHAR;
244: break;
245: case SIGC_FLOAT:
246: baseType = CVM_T_FLOAT;
247: break;
248: case SIGC_DOUBLE:
249: baseType = CVM_T_DOUBLE;
250: break;
251: case SIGC_BOOLEAN:
252: baseType = CVM_T_BOOLEAN;
253: break;
254: case SIGC_CLASS:
255: d = referenceClass(sig.substring(sigIndex, sigLength - 1));
256: baseType = d.typeNo;
257: break;
258: default:
259: return CVM_T_ERROR;
260: }
261: if (arrayDepth <= CVMtypeMaxSmallArray)
262: return (arrayDepth << CVMtypeArrayShift) + baseType;
263: /*
264: * Here for a deep array.
265: */
266: if (d == null) {
267: baseType = referenceArray(arrayDepth, baseType).typeNo;
268: } else {
269: baseType = referenceArray(arrayDepth, d).typeNo;
270: }
271: return CVMtypeBigArray | baseType;
272: }
273:
274: /*
275: * Take either a stripped classname (no L...;)
276: * or an array pseudo-classname (starts with [)
277: * Return a type cookie.
278: */
279: public static int lookupClassname(String name) {
280: if (name.charAt(0) == SIGC_ARRAY)
281: return parseSignature(name);
282: else
283: return referenceClass(name).typeNo;
284: }
285:
286: }
|