001: /***
002: * ASM: a very small and fast Java bytecode manipulation framework
003: * Copyright (C) 2000 INRIA, France Telecom
004: * Copyright (C) 2002 France Telecom
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * Contact: Eric.Bruneton@rd.francetelecom.com
021: *
022: * Author: Eric Bruneton
023: */package bsh.org.objectweb.asm;
024:
025: /**
026: * A {@link ClassVisitor ClassVisitor} that generates Java class files. More
027: * precisely this visitor generates a byte array conforming to the Java class
028: * file format. It can be used alone, to generate a Java class "from scratch",
029: * or with one or more {@link ClassReader ClassReader} and adapter class
030: * visitor to generate a modified class from one or more existing Java classes.
031: */
032:
033: public class ClassWriter implements ClassVisitor {
034:
035: /**
036: * The type of CONSTANT_Class constant pool items.
037: */
038:
039: final static int CLASS = 7;
040:
041: /**
042: * The type of CONSTANT_Fieldref constant pool items.
043: */
044:
045: final static int FIELD = 9;
046:
047: /**
048: * The type of CONSTANT_Methodref constant pool items.
049: */
050:
051: final static int METH = 10;
052:
053: /**
054: * The type of CONSTANT_InterfaceMethodref constant pool items.
055: */
056:
057: final static int IMETH = 11;
058:
059: /**
060: * The type of CONSTANT_String constant pool items.
061: */
062:
063: final static int STR = 8;
064:
065: /**
066: * The type of CONSTANT_Integer constant pool items.
067: */
068:
069: final static int INT = 3;
070:
071: /**
072: * The type of CONSTANT_Float constant pool items.
073: */
074:
075: final static int FLOAT = 4;
076:
077: /**
078: * The type of CONSTANT_Long constant pool items.
079: */
080:
081: final static int LONG = 5;
082:
083: /**
084: * The type of CONSTANT_Double constant pool items.
085: */
086:
087: final static int DOUBLE = 6;
088:
089: /**
090: * The type of CONSTANT_NameAndType constant pool items.
091: */
092:
093: final static int NAME_TYPE = 12;
094:
095: /**
096: * The type of CONSTANT_Utf8 constant pool items.
097: */
098:
099: final static int UTF8 = 1;
100:
101: /**
102: * Index of the next item to be added in the constant pool.
103: */
104:
105: private short index;
106:
107: /**
108: * The constant pool of this class.
109: */
110:
111: private ByteVector pool;
112:
113: /**
114: * The constant pool's hash table data.
115: */
116:
117: private Item[] table;
118:
119: /**
120: * The threshold of the constant pool's hash table.
121: */
122:
123: private int threshold;
124:
125: /**
126: * The access flags of this class.
127: */
128:
129: private int access;
130:
131: /**
132: * The constant pool item that contains the internal name of this class.
133: */
134:
135: private int name;
136:
137: /**
138: * The constant pool item that contains the internal name of the super class
139: * of this class.
140: */
141:
142: private int super Name;
143:
144: /**
145: * Number of interfaces implemented or extended by this class or interface.
146: */
147:
148: private int interfaceCount;
149:
150: /**
151: * The interfaces implemented or extended by this class or interface. More
152: * precisely, this array contains the indexes of the constant pool items
153: * that contain the internal names of these interfaces.
154: */
155:
156: private int[] interfaces;
157:
158: /**
159: * The constant pool item that contains the name of the source file from
160: * which this class was compiled.
161: */
162:
163: private Item sourceFile;
164:
165: /**
166: * Number of fields of this class.
167: */
168:
169: private int fieldCount;
170:
171: /**
172: * The fields of this class.
173: */
174:
175: private ByteVector fields;
176:
177: /**
178: * <tt>true</tt> if the maximum stack size and number of local variables must
179: * be automatically computed.
180: */
181:
182: private boolean computeMaxs;
183:
184: /**
185: * The methods of this class. These methods are stored in a linked list of
186: * {@link CodeWriter CodeWriter} objects, linked to each other by their {@link
187: * CodeWriter#next} field. This field stores the first element of this list.
188: */
189:
190: CodeWriter firstMethod;
191:
192: /**
193: * The methods of this class. These methods are stored in a linked list of
194: * {@link CodeWriter CodeWriter} objects, linked to each other by their {@link
195: * CodeWriter#next} field. This field stores the last element of this list.
196: */
197:
198: CodeWriter lastMethod;
199:
200: /**
201: * The number of entries in the InnerClasses attribute.
202: */
203:
204: private int innerClassesCount;
205:
206: /**
207: * The InnerClasses attribute.
208: */
209:
210: private ByteVector innerClasses;
211:
212: /**
213: * A reusable key used to look for items in the hash {@link #table table}.
214: */
215:
216: Item key;
217:
218: /**
219: * A reusable key used to look for items in the hash {@link #table table}.
220: */
221:
222: Item key2;
223:
224: /**
225: * A reusable key used to look for items in the hash {@link #table table}.
226: */
227:
228: Item key3;
229:
230: /**
231: * The type of instructions without any label.
232: */
233:
234: final static int NOARG_INSN = 0;
235:
236: /**
237: * The type of instructions with an signed byte label.
238: */
239:
240: final static int SBYTE_INSN = 1;
241:
242: /**
243: * The type of instructions with an signed short label.
244: */
245:
246: final static int SHORT_INSN = 2;
247:
248: /**
249: * The type of instructions with a local variable index label.
250: */
251:
252: final static int VAR_INSN = 3;
253:
254: /**
255: * The type of instructions with an implicit local variable index label.
256: */
257:
258: final static int IMPLVAR_INSN = 4;
259:
260: /**
261: * The type of instructions with a type descriptor argument.
262: */
263:
264: final static int TYPE_INSN = 5;
265:
266: /**
267: * The type of field and method invocations instructions.
268: */
269:
270: final static int FIELDORMETH_INSN = 6;
271:
272: /**
273: * The type of the INVOKEINTERFACE instruction.
274: */
275:
276: final static int ITFMETH_INSN = 7;
277:
278: /**
279: * The type of instructions with a 2 bytes bytecode offset label.
280: */
281:
282: final static int LABEL_INSN = 8;
283:
284: /**
285: * The type of instructions with a 4 bytes bytecode offset label.
286: */
287:
288: final static int LABELW_INSN = 9;
289:
290: /**
291: * The type of the LDC instruction.
292: */
293:
294: final static int LDC_INSN = 10;
295:
296: /**
297: * The type of the LDC_W and LDC2_W instructions.
298: */
299:
300: final static int LDCW_INSN = 11;
301:
302: /**
303: * The type of the IINC instruction.
304: */
305:
306: final static int IINC_INSN = 12;
307:
308: /**
309: * The type of the TABLESWITCH instruction.
310: */
311:
312: final static int TABL_INSN = 13;
313:
314: /**
315: * The type of the LOOKUPSWITCH instruction.
316: */
317:
318: final static int LOOK_INSN = 14;
319:
320: /**
321: * The type of the MULTIANEWARRAY instruction.
322: */
323:
324: final static int MANA_INSN = 15;
325:
326: /**
327: * The type of the WIDE instruction.
328: */
329:
330: final static int WIDE_INSN = 16;
331:
332: /**
333: * The instruction types of all JVM opcodes.
334: */
335:
336: static byte[] TYPE;
337:
338: // --------------------------------------------------------------------------
339: // Static initializer
340: // --------------------------------------------------------------------------
341:
342: /**
343: * Computes the instruction types of JVM opcodes.
344: */
345:
346: static {
347: int i;
348: byte[] b = new byte[220];
349: String s = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADDDDDEEEEEEEEE"
350: + "EEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA"
351: + "AAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAAAAAAGGGGGGGHAFBFAAFFAAQPIIJJII"
352: + "IIIIIIIIIIIIIIII";
353: for (i = 0; i < b.length; ++i) {
354: b[i] = (byte) (s.charAt(i) - 'A');
355: }
356: TYPE = b;
357:
358: /* code to generate the above string
359:
360: // SBYTE_INSN instructions
361: b[Constants.NEWARRAY] = SBYTE_INSN;
362: b[Constants.BIPUSH] = SBYTE_INSN;
363:
364: // SHORT_INSN instructions
365: b[Constants.SIPUSH] = SHORT_INSN;
366:
367: // (IMPL)VAR_INSN instructions
368: b[Constants.RET] = VAR_INSN;
369: for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
370: b[i] = VAR_INSN;
371: }
372: for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
373: b[i] = VAR_INSN;
374: }
375: for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
376: b[i] = IMPLVAR_INSN;
377: }
378: for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
379: b[i] = IMPLVAR_INSN;
380: }
381:
382: // TYPE_INSN instructions
383: b[Constants.NEW] = TYPE_INSN;
384: b[Constants.ANEWARRAY] = TYPE_INSN;
385: b[Constants.CHECKCAST] = TYPE_INSN;
386: b[Constants.INSTANCEOF] = TYPE_INSN;
387:
388: // (Set)FIELDORMETH_INSN instructions
389: for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
390: b[i] = FIELDORMETH_INSN;
391: }
392: b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
393:
394: // LABEL(W)_INSN instructions
395: for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
396: b[i] = LABEL_INSN;
397: }
398: b[Constants.IFNULL] = LABEL_INSN;
399: b[Constants.IFNONNULL] = LABEL_INSN;
400: b[200] = LABELW_INSN; // GOTO_W
401: b[201] = LABELW_INSN; // JSR_W
402: // temporary opcodes used internally by ASM - see Label and CodeWriter
403: for (i = 202; i < 220; ++i) {
404: b[i] = LABEL_INSN;
405: }
406:
407: // LDC(_W) instructions
408: b[Constants.LDC] = LDC_INSN;
409: b[19] = LDCW_INSN; // LDC_W
410: b[20] = LDCW_INSN; // LDC2_W
411:
412: // special instructions
413: b[Constants.IINC] = IINC_INSN;
414: b[Constants.TABLESWITCH] = TABL_INSN;
415: b[Constants.LOOKUPSWITCH] = LOOK_INSN;
416: b[Constants.MULTIANEWARRAY] = MANA_INSN;
417: b[196] = WIDE_INSN; // WIDE
418:
419: for (i = 0; i < b.length; ++i) {
420: System.err.print((char)('A' + b[i]));
421: }
422: System.err.println();
423: */
424: }
425:
426: // --------------------------------------------------------------------------
427: // Constructor
428: // --------------------------------------------------------------------------
429:
430: /**
431: * Constructs a new {@link ClassWriter ClassWriter} object.
432: *
433: * @param computeMaxs <tt>true</tt> if the maximum stack size and the maximum
434: * number of local variables must be automatically computed. If this flag
435: * is <tt>true</tt>, then the arguments of the {@link
436: * CodeVisitor#visitMaxs visitMaxs} method of the {@link CodeVisitor
437: * CodeVisitor} returned by the {@link #visitMethod visitMethod} method
438: * will be ignored, and computed automatically from the signature and
439: * the bytecode of each method.
440: */
441:
442: public ClassWriter(final boolean computeMaxs) {
443: index = 1;
444: pool = new ByteVector();
445: table = new Item[64];
446: threshold = (int) (0.75d * table.length);
447: key = new Item();
448: key2 = new Item();
449: key3 = new Item();
450: this .computeMaxs = computeMaxs;
451: }
452:
453: // --------------------------------------------------------------------------
454: // Implementation of the ClassVisitor interface
455: // --------------------------------------------------------------------------
456:
457: public void visit(final int access, final String name,
458: final String super Name, final String[] interfaces,
459: final String sourceFile) {
460: this .access = access;
461: this .name = newClass(name).index;
462: this .super Name = super Name == null ? 0
463: : newClass(super Name).index;
464: if (interfaces != null && interfaces.length > 0) {
465: interfaceCount = interfaces.length;
466: this .interfaces = new int[interfaceCount];
467: for (int i = 0; i < interfaceCount; ++i) {
468: this .interfaces[i] = newClass(interfaces[i]).index;
469: }
470: }
471: if (sourceFile != null) {
472: newUTF8("SourceFile");
473: this .sourceFile = newUTF8(sourceFile);
474: }
475: if ((access & Constants.ACC_DEPRECATED) != 0) {
476: newUTF8("Deprecated");
477: }
478: }
479:
480: public void visitInnerClass(final String name,
481: final String outerName, final String innerName,
482: final int access) {
483: if (innerClasses == null) {
484: newUTF8("InnerClasses");
485: innerClasses = new ByteVector();
486: }
487: ++innerClassesCount;
488: innerClasses.put2(name == null ? 0 : newClass(name).index);
489: innerClasses.put2(outerName == null ? 0
490: : newClass(outerName).index);
491: innerClasses.put2(innerName == null ? 0
492: : newUTF8(innerName).index);
493: innerClasses.put2(access);
494: }
495:
496: public void visitField(final int access, final String name,
497: final String desc, final Object value) {
498: ++fieldCount;
499: if (fields == null) {
500: fields = new ByteVector();
501: }
502: fields.put2(access).put2(newUTF8(name).index).put2(
503: newUTF8(desc).index);
504: int attributeCount = 0;
505: if (value != null) {
506: ++attributeCount;
507: }
508: if ((access & Constants.ACC_SYNTHETIC) != 0) {
509: ++attributeCount;
510: }
511: if ((access & Constants.ACC_DEPRECATED) != 0) {
512: ++attributeCount;
513: }
514: fields.put2(attributeCount);
515: if (value != null) {
516: fields.put2(newUTF8("ConstantValue").index);
517: fields.put4(2).put2(newCst(value).index);
518: }
519: if ((access & Constants.ACC_SYNTHETIC) != 0) {
520: fields.put2(newUTF8("Synthetic").index).put4(0);
521: }
522: if ((access & Constants.ACC_DEPRECATED) != 0) {
523: fields.put2(newUTF8("Deprecated").index).put4(0);
524: }
525: }
526:
527: public CodeVisitor visitMethod(final int access, final String name,
528: final String desc, final String[] exceptions) {
529: CodeWriter cw = new CodeWriter(this , computeMaxs);
530: cw.init(access, name, desc, exceptions);
531: return cw;
532: }
533:
534: public void visitEnd() {
535: }
536:
537: // --------------------------------------------------------------------------
538: // Other public methods
539: // --------------------------------------------------------------------------
540:
541: /**
542: * Returns the bytecode of the class that was build with this class writer.
543: *
544: * @return the bytecode of the class that was build with this class writer.
545: */
546:
547: public byte[] toByteArray() {
548: // computes the real size of the bytecode of this class
549: int size = 24 + 2 * interfaceCount;
550: if (fields != null) {
551: size += fields.length;
552: }
553: int nbMethods = 0;
554: CodeWriter cb = firstMethod;
555: while (cb != null) {
556: ++nbMethods;
557: size += cb.getSize();
558: cb = cb.next;
559: }
560: size += pool.length;
561: int attributeCount = 0;
562: if (sourceFile != null) {
563: ++attributeCount;
564: size += 8;
565: }
566: if ((access & Constants.ACC_DEPRECATED) != 0) {
567: ++attributeCount;
568: size += 6;
569: }
570: if (innerClasses != null) {
571: ++attributeCount;
572: size += 8 + innerClasses.length;
573: }
574: // allocates a byte vector of this size, in order to avoid unnecessary
575: // arraycopy operations in the ByteVector.enlarge() method
576: ByteVector out = new ByteVector(size);
577: out.put4(0xCAFEBABE).put2(3).put2(45);
578: out.put2(index).putByteArray(pool.data, 0, pool.length);
579: out.put2(access).put2(name).put2(super Name);
580: out.put2(interfaceCount);
581: for (int i = 0; i < interfaceCount; ++i) {
582: out.put2(interfaces[i]);
583: }
584: out.put2(fieldCount);
585: if (fields != null) {
586: out.putByteArray(fields.data, 0, fields.length);
587: }
588: out.put2(nbMethods);
589: cb = firstMethod;
590: while (cb != null) {
591: cb.put(out);
592: cb = cb.next;
593: }
594: out.put2(attributeCount);
595: if (sourceFile != null) {
596: out.put2(newUTF8("SourceFile").index).put4(2).put2(
597: sourceFile.index);
598: }
599: if ((access & Constants.ACC_DEPRECATED) != 0) {
600: out.put2(newUTF8("Deprecated").index).put4(0);
601: }
602: if (innerClasses != null) {
603: out.put2(newUTF8("InnerClasses").index);
604: out.put4(innerClasses.length + 2).put2(innerClassesCount);
605: out.putByteArray(innerClasses.data, 0, innerClasses.length);
606: }
607: return out.data;
608: }
609:
610: // --------------------------------------------------------------------------
611: // Utility methods: constant pool management
612: // --------------------------------------------------------------------------
613:
614: /**
615: * Adds a number or string constant to the constant pool of the class being
616: * build. Does nothing if the constant pool already contains a similar item.
617: *
618: * @param cst the value of the constant to be added to the constant pool. This
619: * parameter must be an {@link java.lang.Integer Integer}, a {@link
620: * java.lang.Float Float}, a {@link java.lang.Long Long}, a {@link
621: java.lang.Double Double} or a {@link String String}.
622: * @return a new or already existing constant item with the given value.
623: */
624:
625: Item newCst(final Object cst) {
626: if (cst instanceof Integer) {
627: int val = ((Integer) cst).intValue();
628: return newInteger(val);
629: } else if (cst instanceof Float) {
630: float val = ((Float) cst).floatValue();
631: return newFloat(val);
632: } else if (cst instanceof Long) {
633: long val = ((Long) cst).longValue();
634: return newLong(val);
635: } else if (cst instanceof Double) {
636: double val = ((Double) cst).doubleValue();
637: return newDouble(val);
638: } else if (cst instanceof String) {
639: return newString((String) cst);
640: } else {
641: throw new IllegalArgumentException("value " + cst);
642: }
643: }
644:
645: /**
646: * Adds an UTF string to the constant pool of the class being build. Does
647: * nothing if the constant pool already contains a similar item.
648: *
649: * @param value the String value.
650: * @return a new or already existing UTF8 item.
651: */
652:
653: Item newUTF8(final String value) {
654: key.set(UTF8, value, null, null);
655: Item result = get(key);
656: if (result == null) {
657: pool.put1(UTF8).putUTF(value);
658: result = new Item(index++, key);
659: put(result);
660: }
661: return result;
662: }
663:
664: /**
665: * Adds a class reference to the constant pool of the class being build. Does
666: * nothing if the constant pool already contains a similar item.
667: *
668: * @param value the internal name of the class.
669: * @return a new or already existing class reference item.
670: */
671:
672: Item newClass(final String value) {
673: key2.set(CLASS, value, null, null);
674: Item result = get(key2);
675: if (result == null) {
676: pool.put12(CLASS, newUTF8(value).index);
677: result = new Item(index++, key2);
678: put(result);
679: }
680: return result;
681: }
682:
683: /**
684: * Adds a field reference to the constant pool of the class being build. Does
685: * nothing if the constant pool already contains a similar item.
686: *
687: * @param owner the internal name of the field's owner class.
688: * @param name the field's name.
689: * @param desc the field's descriptor.
690: * @return a new or already existing field reference item.
691: */
692:
693: Item newField(final String owner, final String name,
694: final String desc) {
695: key3.set(FIELD, owner, name, desc);
696: Item result = get(key3);
697: if (result == null) {
698: put122(FIELD, newClass(owner).index,
699: newNameType(name, desc).index);
700: result = new Item(index++, key3);
701: put(result);
702: }
703: return result;
704: }
705:
706: /**
707: * Adds a method reference to the constant pool of the class being build. Does
708: * nothing if the constant pool already contains a similar item.
709: *
710: * @param owner the internal name of the method's owner class.
711: * @param name the method's name.
712: * @param desc the method's descriptor.
713: * @return a new or already existing method reference item.
714: */
715:
716: Item newMethod(final String owner, final String name,
717: final String desc) {
718: key3.set(METH, owner, name, desc);
719: Item result = get(key3);
720: if (result == null) {
721: put122(METH, newClass(owner).index,
722: newNameType(name, desc).index);
723: result = new Item(index++, key3);
724: put(result);
725: }
726: return result;
727: }
728:
729: /**
730: * Adds an interface method reference to the constant pool of the class being
731: * build. Does nothing if the constant pool already contains a similar item.
732: *
733: * @param ownerItf the internal name of the method's owner interface.
734: * @param name the method's name.
735: * @param desc the method's descriptor.
736: * @return a new or already existing interface method reference item.
737: */
738:
739: Item newItfMethod(final String ownerItf, final String name,
740: final String desc) {
741: key3.set(IMETH, ownerItf, name, desc);
742: Item result = get(key3);
743: if (result == null) {
744: put122(IMETH, newClass(ownerItf).index, newNameType(name,
745: desc).index);
746: result = new Item(index++, key3);
747: put(result);
748: }
749: return result;
750: }
751:
752: /**
753: * Adds an integer to the constant pool of the class being build. Does nothing
754: * if the constant pool already contains a similar item.
755: *
756: * @param value the int value.
757: * @return a new or already existing int item.
758: */
759:
760: private Item newInteger(final int value) {
761: key.set(value);
762: Item result = get(key);
763: if (result == null) {
764: pool.put1(INT).put4(value);
765: result = new Item(index++, key);
766: put(result);
767: }
768: return result;
769: }
770:
771: /**
772: * Adds a float to the constant pool of the class being build. Does nothing if
773: * the constant pool already contains a similar item.
774: *
775: * @param value the float value.
776: * @return a new or already existing float item.
777: */
778:
779: private Item newFloat(final float value) {
780: key.set(value);
781: Item result = get(key);
782: if (result == null) {
783: pool.put1(FLOAT).put4(Float.floatToIntBits(value));
784: result = new Item(index++, key);
785: put(result);
786: }
787: return result;
788: }
789:
790: /**
791: * Adds a long to the constant pool of the class being build. Does nothing if
792: * the constant pool already contains a similar item.
793: *
794: * @param value the long value.
795: * @return a new or already existing long item.
796: */
797:
798: private Item newLong(final long value) {
799: key.set(value);
800: Item result = get(key);
801: if (result == null) {
802: pool.put1(LONG).put8(value);
803: result = new Item(index, key);
804: put(result);
805: index += 2;
806: }
807: return result;
808: }
809:
810: /**
811: * Adds a double to the constant pool of the class being build. Does nothing
812: * if the constant pool already contains a similar item.
813: *
814: * @param value the double value.
815: * @return a new or already existing double item.
816: */
817:
818: private Item newDouble(final double value) {
819: key.set(value);
820: Item result = get(key);
821: if (result == null) {
822: pool.put1(DOUBLE).put8(Double.doubleToLongBits(value));
823: result = new Item(index, key);
824: put(result);
825: index += 2;
826: }
827: return result;
828: }
829:
830: /**
831: * Adds a string to the constant pool of the class being build. Does nothing
832: * if the constant pool already contains a similar item.
833: *
834: * @param value the String value.
835: * @return a new or already existing string item.
836: */
837:
838: private Item newString(final String value) {
839: key2.set(STR, value, null, null);
840: Item result = get(key2);
841: if (result == null) {
842: pool.put12(STR, newUTF8(value).index);
843: result = new Item(index++, key2);
844: put(result);
845: }
846: return result;
847: }
848:
849: /**
850: * Adds a name and type to the constant pool of the class being build. Does
851: * nothing if the constant pool already contains a similar item.
852: *
853: * @param name a name.
854: * @param desc a type descriptor.
855: * @return a new or already existing name and type item.
856: */
857:
858: private Item newNameType(final String name, final String desc) {
859: key2.set(NAME_TYPE, name, desc, null);
860: Item result = get(key2);
861: if (result == null) {
862: put122(NAME_TYPE, newUTF8(name).index, newUTF8(desc).index);
863: result = new Item(index++, key2);
864: put(result);
865: }
866: return result;
867: }
868:
869: /**
870: * Returns the constant pool's hash table item which is equal to the given
871: * item.
872: *
873: * @param key a constant pool item.
874: * @return the constant pool's hash table item which is equal to the given
875: * item, or <tt>null</tt> if there is no such item.
876: */
877:
878: private Item get(final Item key) {
879: Item tab[] = table;
880: int hashCode = key.hashCode;
881: int index = (hashCode & 0x7FFFFFFF) % tab.length;
882: for (Item i = tab[index]; i != null; i = i.next) {
883: if (i.hashCode == hashCode && key.isEqualTo(i)) {
884: return i;
885: }
886: }
887: return null;
888: }
889:
890: /**
891: * Puts the given item in the constant pool's hash table. The hash table
892: * <i>must</i> not already contains this item.
893: *
894: * @param i the item to be added to the constant pool's hash table.
895: */
896:
897: private void put(final Item i) {
898: if (index > threshold) {
899: int oldCapacity = table.length;
900: Item oldMap[] = table;
901: int newCapacity = oldCapacity * 2 + 1;
902: Item newMap[] = new Item[newCapacity];
903: threshold = (int) (newCapacity * 0.75);
904: table = newMap;
905: for (int j = oldCapacity; j-- > 0;) {
906: for (Item old = oldMap[j]; old != null;) {
907: Item e = old;
908: old = old.next;
909: int index = (e.hashCode & 0x7FFFFFFF) % newCapacity;
910: e.next = newMap[index];
911: newMap[index] = e;
912: }
913: }
914: }
915: int index = (i.hashCode & 0x7FFFFFFF) % table.length;
916: i.next = table[index];
917: table[index] = i;
918: }
919:
920: /**
921: * Puts one byte and two shorts into the constant pool.
922: *
923: * @param b a byte.
924: * @param s1 a short.
925: * @param s2 another short.
926: */
927:
928: private void put122(final int b, final int s1, final int s2) {
929: pool.put12(b, s1).put2(s2);
930: }
931: }
|