001: /*
002: * @(#)ConstantPool.java 1.2 06/08/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: package com.sun.jumpimpl.ixc;
028:
029: import java.util.Iterator;
030: import java.util.HashMap;
031: import java.util.ArrayList;
032: import java.io.DataOutputStream;
033: import java.io.IOException;
034:
035: /**
036: * This utility class is used in generating a stub. An instance of
037: * this class represents the constant pool of the class being generated.
038: **/
039:
040: class ConstantPool {
041: // We write the CP out in this order: classes, methods, fields,
042: // nameAndType, strings, longs.
043:
044: /**
045: * HashMap[String, String], becomes HashMap[String, Integer]
046: * on write.
047: **/
048: private HashMap classes = new HashMap(11);
049:
050: private ArrayList fields = new ArrayList(); // ArrayList<String[3]>
051: private ArrayList methods = new ArrayList(); // ArrayList<String[3]>
052: private ArrayList ifMethods = new ArrayList(); // Interface methods
053: private ArrayList nameAndType = new ArrayList(); // ArrayList<String[2]>
054:
055: /**
056: *This is the list of CONSTANT_String_info things
057: * HashMap<String, String>, becomes HashMap<String, Integer>
058: * on write
059: **/
060: private HashMap stringConstants = new HashMap();
061:
062: /**
063: * HashMap<String, String>, becomes HashMap<String, Integer>
064: * on write
065: **/
066: private HashMap strings = new HashMap();
067:
068: /**
069: * HashMap<String, String>, becomes HashMap<String, Integer>
070: * on write
071: **/
072: private HashMap longConstants = new HashMap();
073:
074: void addStringConstant(String s) {
075: addString(s);
076: stringConstants.put(s, s);
077: }
078:
079: void addString(String s) {
080: strings.put(s, s);
081: }
082:
083: void addClass(String s) {
084: addString(s);
085: classes.put(s, s);
086: }
087:
088: boolean hasClass(String s) {
089: return classes.get(s) != null;
090: }
091:
092: private void addNameAndType(String name, String type) {
093: addString(name);
094: addString(type);
095: nameAndType.add(new String[] { name, type });
096: }
097:
098: void addLong(Long longValue) {
099: longConstants.put(longValue, longValue);
100: }
101:
102: int lookupString(Object s) {
103: Integer i = (Integer) strings.get(s);
104: if (i == null) {
105: throw new RuntimeException("" + s
106: + " not found in constant pool");
107: }
108: return i.intValue();
109: }
110:
111: int lookupStringConstant(Object s) {
112: Integer i = (Integer) stringConstants.get(s);
113: if (i == null) {
114: throw new RuntimeException("string constant " + s
115: + " not found in constant pool");
116: }
117: return i.intValue();
118: }
119:
120: int lookupLongConstant(Object s) {
121: Integer i = (Integer) longConstants.get(s);
122: if (i == null) {
123: throw new RuntimeException("long " + s
124: + " not found in constant pool");
125: }
126: return i.intValue();
127: }
128:
129: int lookupClass(Object s) {
130: Integer i = (Integer) classes.get(s);
131: if (i == null) {
132: throw new RuntimeException("class " + s
133: + " not found in constant pool");
134: }
135: return i.intValue();
136: }
137:
138: int lookupMethod(String className, String name, String type) {
139: for (int i = 0; i < methods.size(); i++) {
140: String[] el = (String[]) methods.get(i);
141: if (className.equals(el[0]) && name.equals(el[1])
142: && type.equals(el[2])) {
143: return 1 + classes.size() + fields.size() + i;
144: }
145: }
146: throw new RuntimeException("Method <" + className + ". " + name
147: + " : " + type + "> not found in constant pool");
148: }
149:
150: int lookupField(String className, String name, String type) {
151: for (int i = 0; i < fields.size(); i++) {
152: String[] el = (String[]) fields.get(i);
153: if (className.equals(el[0]) && name.equals(el[1])
154: && type.equals(el[2])) {
155: return 1 + classes.size() + i;
156: }
157: }
158: throw new RuntimeException("Field <" + className + ". " + name
159: + " : " + type + "> not found in constant pool");
160: }
161:
162: int lookupNameAndType(String name, String type) {
163: for (int i = 0; i < nameAndType.size(); i++) {
164: String[] el = (String[]) nameAndType.get(i);
165: if (name.equals(el[0]) && type.equals(el[1])) {
166: return 1 + classes.size() + fields.size()
167: + methods.size() + ifMethods.size() + i;
168: }
169: }
170: throw new RuntimeException("Name and type <" + name + ", "
171: + type + "> not found in constant pool");
172: }
173:
174: void addField(String className, String name, String type) {
175: addString(className);
176: addNameAndType(name, type);
177: fields.add(new String[] { className, name, type });
178: }
179:
180: void addMethodReference(String className, String name, String type) {
181: addString(className);
182: addNameAndType(name, type);
183: methods.add(new String[] { className, name, type });
184: }
185:
186: /**
187: * Add an interface method reference
188: **/
189: void addIfMethodReference(String className, String name, String type) {
190: addString(className);
191: addNameAndType(name, type);
192: ifMethods.add(new String[] { className, name, type });
193: }
194:
195: void write(DataOutputStream dos) throws IOException {
196: // Assign an entry number to each class, stringConstant and string
197: // CP entry. Remmeber, counting starts at 1!
198:
199: int num = 1;
200: String[] classesArr = new String[classes.size()];
201: {
202: int i = 0;
203: for (Iterator it = classes.keySet().iterator(); it
204: .hasNext();) {
205: String key = (String) it.next();
206: classesArr[i++] = key;
207: classes.put(key, new Integer(num++));
208: }
209: }
210:
211: num += fields.size() + methods.size() + ifMethods.size()
212: + nameAndType.size();
213:
214: String[] stringConstantArr = new String[stringConstants.size()];
215: {
216: int i = 0;
217: for (Iterator it = stringConstants.keySet().iterator(); it
218: .hasNext();) {
219: String key = (String) it.next();
220: stringConstantArr[i++] = key;
221: stringConstants.put(key, new Integer(num++));
222: }
223: }
224:
225: String[] stringArr = new String[strings.size()];
226: {
227: int i = 0;
228: for (Iterator it = strings.keySet().iterator(); it
229: .hasNext();) {
230: String key = (String) it.next();
231: stringArr[i++] = key;
232: strings.put(key, new Integer(num++));
233: }
234: }
235:
236: long[] longArr = new long[longConstants.size()];
237: {
238: int i = 0;
239: for (Iterator it = longConstants.keySet().iterator(); it
240: .hasNext();) {
241: //for (int i = 0; i < longConstants.size(); i++) {
242: Long key = (Long) it.next();
243: longArr[i++] = key.longValue();
244: longConstants.put(key, new Integer(num));
245: //Longs take 2 slots
246: num += 2;
247: }
248: }
249:
250: // Now num is the correct constant_pool_count, one greater than
251: // the number of entries. Yes, entires really are numbered
252: // 1..(constant_pool_count-1)!
253: dos.writeShort(num);
254:
255: for (int i = 0; i < classesArr.length; i++) {
256: dos.writeByte(7); // CONSTANT_Class
257: dos.writeShort(lookupString(classesArr[i]));
258: }
259: for (int i = 0; i < fields.size(); i++) {
260: String[] sa = (String[]) fields.get(i);
261: dos.writeByte(9); // CONSTANT_Fieldref
262: dos.writeShort(lookupClass(sa[0]));
263: dos.writeShort(lookupNameAndType(sa[1], sa[2]));
264: }
265: for (int i = 0; i < methods.size(); i++) {
266: String[] sa = (String[]) methods.get(i);
267: dos.writeByte(10); // CONSTANT_Methodref
268: dos.writeShort(lookupClass(sa[0]));
269: dos.writeShort(lookupNameAndType(sa[1], sa[2]));
270: }
271: for (int i = 0; i < ifMethods.size(); i++) {
272: String[] sa = (String[]) ifMethods.get(i);
273: dos.writeByte(11); // CONSTANT_InterfaceMethodref
274: dos.writeShort(lookupClass(sa[0]));
275: dos.writeShort(lookupNameAndType(sa[1], sa[2]));
276: }
277: for (int i = 0; i < nameAndType.size(); i++) {
278: String[] sa = (String[]) nameAndType.get(i);
279: dos.writeByte(12); // CONSTANT_NameAndtype
280: dos.writeShort(lookupString(sa[0]));
281: dos.writeShort(lookupString(sa[1]));
282: }
283: for (int i = 0; i < stringConstantArr.length; i++) {
284: dos.writeByte(0x8); // CONSTANT_String_info
285: dos.writeShort(lookupString(stringConstantArr[i]));
286: }
287: for (int i = 0; i < stringArr.length; i++) {
288: dos.writeByte(1); // CONSTANT_Utf8
289: dos.writeUTF(stringArr[i]);
290: }
291: for (int i = 0; i < longArr.length; i++) {
292: dos.writeByte(0x5); // CONSTANT_Long
293: dos.writeLong(longArr[i]);
294: }
295: }
296: }
|