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: import java.util.Hashtable;
030: import java.util.Enumeration;
031: import components.ClassInfo;
032: import components.MethodInfo;
033: import components.MethodConstant;
034: import jcc.Const;
035:
036: /*
037: * This class will build
038: * the imethodtable, used by JDK1.1 for a quicker implementation
039: * of invokeinterface_quick.
040: *
041: * This class should be subclassed in a target-machine-specific way
042: * to provide writing out the data structure we build here.
043: * See also InterfaceMethodFactory for the mechanism used to call back
044: * into that target-specific body of code.
045: *
046: * Each ClassInfo is already decorated with a vector of
047: * all the interfaces it implements. In addition, each
048: * ClassInfo's allInterfaces vector has its parent's vector as prefix.
049: * So:
050: * A) a class which implements the same number of interfaces as its parent
051: * necessarily implements the same set of interfaces, and can use its
052: * parent's table, by reference.
053: * B) for those classes for which a table must indeed be built,
054: * Only the interface elements associated with the present
055: * ClassInfo need to have a method index table built.
056: */
057: public abstract class InterfaceMethodTable {
058:
059: public ClassClass parent;
060: public String name;
061: public InterfaceVector iv[];
062:
063: protected InterfaceMethodTable(ClassClass c, String n,
064: InterfaceVector v[]) {
065: parent = c;
066: name = n;
067: iv = v;
068: }
069:
070: private static MethodInfo findSlot(MethodConstant t[], MethodInfo m) {
071: if (t != null) {
072: MethodInfo v;
073: int nt = t.length;
074: int ID = m.getID();
075: for (int i = 0; i < nt; i++) {
076: if ((v = t[i].find()).getID() == ID)
077: return v;
078: }
079: }
080: return null;
081: }
082:
083: /*
084: * Iterate through the methods of an interface.
085: * For the non-static members (i.e. the non-<clinit> )
086: * assign a zero-based index, and use the methodTableIndex field
087: * to keep it in.
088: */
089: public void indexInterfaceMethods(ClassInfo c) {
090: if ((c.access & Const.ACC_INTERFACE) == 0) {
091: System.err
092: .println("InterfaceMethodTable.indexInterfaceMethods: "
093: + c.className + " is not an interface");
094: return; // this is bad
095: }
096: int j = 0;
097: MethodInfo m[] = c.methods;
098: if (m == null)
099: return; // no methods here.
100: int n = m.length;
101: for (int i = 0; i < n; i++) {
102: MethodInfo t = m[i];
103: if ((t.access & Const.ACC_STATIC) != 0)
104: continue; // don't number statics.
105: if ((t.access & Const.ACC_ABSTRACT) == 0) {
106: System.err
107: .println("InterfaceMethodTable.indexInterfaceMethods: "
108: + t + " is not abstract");
109: // but keep going anyway...
110: }
111: t.methodTableIndex = j++;
112: }
113: }
114:
115: private static InterfaceMethodTable generateTablesForInterface(
116: ClassInfo c, String imtName, InterfaceMethodFactory imf) {
117: //
118: // We generate a thing like an imethodtable for interfaces, too.
119: // But its different enough that I'm treating it separately, here.
120: //
121: // It is complex to share our imethotable with our superclass,
122: // as it must at least include ourselves!
123: //
124: // struct imethodtable {
125: // int icount;
126: // struct {
127: // ClassClass *classdescriptor;
128: // unsigned long *offsets = 0;
129: // } itable[1];
130: // }
131: ClassClass me = c.vmClass;
132: int ntotal = c.allInterfaces.size();
133: InterfaceVector ivec[] = new InterfaceVector[ntotal + 1];
134:
135: // first the entry for ourselves.
136: ivec[0] = new InterfaceVector(me, c, null);
137: // now all the others (if any)
138: for (int i = 0; i < ntotal; i++) {
139: ClassInfo intf = (ClassInfo) c.allInterfaces.elementAt(i);
140: ivec[i + 1] = new InterfaceVector(me, intf, null);
141: }
142: return imf.newInterfaceMethodTable(me, imtName, ivec);
143: }
144:
145: public static InterfaceMethodTable generateInterfaceTable(
146: ClassClass cc, InterfaceMethodFactory imf) {
147: ClassInfo c = cc.ci;
148: if (c.allInterfaces == null)
149: c.findAllInterfaces();
150: String imtName = c.getGenericNativeName() + "_intfMethodtable";
151: ClassInfo sup = c.super ClassInfo;
152: int ntotal = c.allInterfaces.size();
153: int nsuper = 0;
154:
155: if ((c.access & Const.ACC_INTERFACE) != 0) {
156: return generateTablesForInterface(c, imtName, imf);
157: }
158: if (sup != null) {
159: nsuper = sup.allInterfaces.size();
160: if (nsuper == ntotal) {
161: // use other class's tables entirely.
162: // we have nothing further to add.
163: return sup.vmClass.inf;
164: }
165: }
166: //
167: // generate the offset tables, or symbolic references
168: // to them.
169: InterfaceVector vec[] = new InterfaceVector[ntotal];
170: if (nsuper != 0) {
171: // borrow some from superclass. They are the same.
172: System.arraycopy(sup.vmClass.inf.iv, 0, vec, 0, nsuper );
173: }
174:
175: // compute the rest of the thing ourselves.
176: for (int i = nsuper ; i < ntotal; i++) {
177: ClassInfo intf = (ClassInfo) c.allInterfaces.elementAt(i);
178: MethodConstant mtab[] = intf.refMethodtable;
179: int nmethods = mtab.length;
180: short ivec[] = new short[nmethods];
181: for (int j = 0; j < nmethods; j++) {
182: MethodInfo target = mtab[j].find();
183: if ((target.access & Const.ACC_STATIC) != 0) {
184: // should never happen.
185: System.err
186: .println("Interface "
187: + intf.className
188: + " has a static method in its methodtable:! "
189: + target);
190: continue;
191: }
192: MethodInfo v = findSlot(c.refMethodtable, target);
193: if (v == null) {
194: System.err.println("Class " + c.className
195: + " does not implement interface "
196: + intf.className + " because it lacks "
197: + target);
198: ivec[j] = 0;
199: } else {
200: ivec[j] = (short) v.methodTableIndex;
201: }
202: }
203: vec[i] = new InterfaceVector(cc, intf, ivec);
204: }
205:
206: return imf.newInterfaceMethodTable(cc, imtName, vec);
207: }
208: }
|