KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > bcel > internal > generic > InstructionFactory


1 package com.sun.org.apache.bcel.internal.generic;
2
3 /* ====================================================================
4  * The Apache Software License, Version 1.1
5  *
6  * Copyright (c) 2001 The Apache Software Foundation. All rights
7  * reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed by the
24  * Apache Software Foundation (http://www.apache.org/)."
25  * Alternately, this acknowledgment may appear in the software itself,
26  * if and wherever such third-party acknowledgments normally appear.
27  *
28  * 4. The names "Apache" and "Apache Software Foundation" and
29  * "Apache BCEL" must not be used to endorse or promote products
30  * derived from this software without prior written permission. For
31  * written permission, please contact apache@apache.org.
32  *
33  * 5. Products derived from this software may not be called "Apache",
34  * "Apache BCEL", nor may "Apache" appear in their name, without
35  * prior written permission of the Apache Software Foundation.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48  * SUCH DAMAGE.
49  * ====================================================================
50  *
51  * This software consists of voluntary contributions made by many
52  * individuals on behalf of the Apache Software Foundation. For more
53  * information on the Apache Software Foundation, please see
54  * <http://www.apache.org/>.
55  */

56 import com.sun.org.apache.bcel.internal.Constants;
57
58 /**
59  * Instances of this class may be used, e.g., to generate typed
60  * versions of instructions. Its main purpose is to be used as the
61  * byte code generating backend of a compiler. You can subclass it to
62  * add your own create methods.
63  *
64  * @version $Id: InstructionFactory.java,v 1.1.1.1 2001/10/29 20:00:19 jvanzyl Exp $
65  * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
66  * @see Constants
67  */

68 public class InstructionFactory implements InstructionConstants {
69   protected ClassGen cg;
70   protected ConstantPoolGen cp;
71
72   public InstructionFactory(ClassGen cg, ConstantPoolGen cp) {
73     this.cg = cg;
74     this.cp = cp;
75   }
76
77   /** Initialize with ClassGen object
78    */

79   public InstructionFactory(ClassGen cg) {
80     this(cg, cg.getConstantPool());
81   }
82
83   /** Initialize just with ConstantPoolGen object
84    */

85   public InstructionFactory(ConstantPoolGen cp) {
86     this(null, cp);
87   }
88
89   /** Create an invoke instruction.
90    *
91    * @param class_name name of the called class
92    * @param name name of the called method
93    * @param ret_type return type of method
94    * @param arg_types argument types of method
95    * @param kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL,
96    * or INVOKESPECIAL
97    * @see Constants
98    */

99   public InvokeInstruction createInvoke(String JavaDoc class_name, String JavaDoc name, Type ret_type,
100                     Type[] arg_types, short kind) {
101     int index;
102     int nargs = 0;
103     String JavaDoc signature = Type.getMethodSignature(ret_type, arg_types);
104
105     for(int i=0; i < arg_types.length; i++) // Count size of arguments
106
nargs += arg_types[i].getSize();
107
108     if(kind == Constants.INVOKEINTERFACE)
109       index = cp.addInterfaceMethodref(class_name, name, signature);
110     else
111       index = cp.addMethodref(class_name, name, signature);
112
113     switch(kind) {
114     case Constants.INVOKESPECIAL: return new INVOKESPECIAL(index);
115     case Constants.INVOKEVIRTUAL: return new INVOKEVIRTUAL(index);
116     case Constants.INVOKESTATIC: return new INVOKESTATIC(index);
117     case Constants.INVOKEINTERFACE: return new INVOKEINTERFACE(index, nargs + 1);
118     default:
119       throw new RuntimeException JavaDoc("Oops: Unknown invoke kind:" + kind);
120     }
121   }
122
123   /** Create a call to the most popular System.out.println() method.
124    *
125    * @param s the string to print
126    */

127   public InstructionList createPrintln(String JavaDoc s) {
128     InstructionList il = new InstructionList();
129     int out = cp.addFieldref("java.lang.System", "out",
130                          "Ljava/io/PrintStream;");
131     int println = cp.addMethodref("java.io.PrintStream", "println",
132                           "(Ljava/lang/String;)V");
133
134     il.append(new GETSTATIC(out));
135     il.append(new PUSH(cp, s));
136     il.append(new INVOKEVIRTUAL(println));
137
138     return il;
139   }
140
141   private static class MethodObject {
142     Type[] arg_types;
143     Type result_type;
144     String JavaDoc[] arg_names;
145     String JavaDoc class_name;
146     String JavaDoc name;
147     int access;
148
149     MethodObject(String JavaDoc c, String JavaDoc n, Type r, Type[] a, int acc) {
150       class_name = c;
151       name = n;
152       result_type = r;
153       arg_types = a;
154       access = acc;
155     }
156   }
157
158   private InvokeInstruction createInvoke(MethodObject m, short kind) {
159     return createInvoke(m.class_name, m.name, m.result_type, m.arg_types, kind);
160   }
161
162   private static MethodObject[] append_mos = {
163     new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
164              new Type[] { Type.STRING }, Constants.ACC_PUBLIC),
165     new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
166              new Type[] { Type.OBJECT }, Constants.ACC_PUBLIC),
167     null, null, // indices 2, 3
168
new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
169              new Type[] { Type.BOOLEAN }, Constants.ACC_PUBLIC),
170     new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
171              new Type[] { Type.CHAR }, Constants.ACC_PUBLIC),
172     new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
173              new Type[] { Type.FLOAT }, Constants.ACC_PUBLIC),
174     new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
175              new Type[] { Type.DOUBLE }, Constants.ACC_PUBLIC),
176     new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
177              new Type[] { Type.INT }, Constants.ACC_PUBLIC),
178     new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(byte)
179
new Type[] { Type.INT }, Constants.ACC_PUBLIC),
180     new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(short)
181
new Type[] { Type.INT }, Constants.ACC_PUBLIC),
182     new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
183              new Type[] { Type.LONG }, Constants.ACC_PUBLIC)
184   };
185
186   private static final boolean isString(Type type) {
187     return ((type instanceof ObjectType) &&
188             ((ObjectType)type).getClassName().equals("java.lang.String"));
189   }
190
191   public Instruction createAppend(Type type) {
192     byte t = type.getType();
193
194     if(isString(type))
195       return createInvoke(append_mos[0], Constants.INVOKEVIRTUAL);
196
197     switch(t) {
198     case Constants.T_BOOLEAN:
199     case Constants.T_CHAR:
200     case Constants.T_FLOAT:
201     case Constants.T_DOUBLE:
202     case Constants.T_BYTE:
203     case Constants.T_SHORT:
204     case Constants.T_INT:
205     case Constants.T_LONG
206       : return createInvoke(append_mos[t], Constants.INVOKEVIRTUAL);
207     case Constants.T_ARRAY:
208     case Constants.T_OBJECT:
209       return createInvoke(append_mos[1], Constants.INVOKEVIRTUAL);
210     default:
211       throw new RuntimeException JavaDoc("Oops: No append for this type? " + type);
212     }
213   }
214
215   /** Create a field instruction.
216    *
217    * @param class_name name of the accessed class
218    * @param name name of the referenced field
219    * @param type type of field
220    * @param kind how to access, i.e., GETFIELD, PUTFIELD, GETSTATIC, PUTSTATIC
221    * @see Constants
222    */

223   public FieldInstruction createFieldAccess(String JavaDoc class_name, String JavaDoc name, Type type, short kind) {
224     int index;
225     String JavaDoc signature = type.getSignature();
226
227     index = cp.addFieldref(class_name, name, signature);
228
229     switch(kind) {
230     case Constants.GETFIELD: return new GETFIELD(index);
231     case Constants.PUTFIELD: return new PUTFIELD(index);
232     case Constants.GETSTATIC: return new GETSTATIC(index);
233     case Constants.PUTSTATIC: return new PUTSTATIC(index);
234
235     default:
236       throw new RuntimeException JavaDoc("Oops: Unknown getfield kind:" + kind);
237     }
238   }
239
240   /** Create reference to `this'
241    */

242   public static Instruction createThis() {
243     return new ALOAD(0);
244   }
245
246   /** Create typed return
247    */

248   public static ReturnInstruction createReturn(Type type) {
249     switch(type.getType()) {
250     case Constants.T_ARRAY:
251     case Constants.T_OBJECT: return ARETURN;
252     case Constants.T_INT:
253     case Constants.T_SHORT:
254     case Constants.T_BOOLEAN:
255     case Constants.T_CHAR:
256     case Constants.T_BYTE: return IRETURN;
257     case Constants.T_FLOAT: return FRETURN;
258     case Constants.T_DOUBLE: return DRETURN;
259     case Constants.T_LONG: return LRETURN;
260     case Constants.T_VOID: return RETURN;
261
262     default:
263       throw new RuntimeException JavaDoc("Invalid type: " + type);
264     }
265   }
266   
267   private static final ArithmeticInstruction createBinaryIntOp(char first, String JavaDoc op) {
268     switch(first) {
269     case '-' : return ISUB;
270     case '+' : return IADD;
271     case '%' : return IREM;
272     case '*' : return IMUL;
273     case '/' : return IDIV;
274     case '&' : return IAND;
275     case '|' : return IOR;
276     case '^' : return IXOR;
277     case '<' : return ISHL;
278     case '>' : return op.equals(">>>")? (ArithmeticInstruction)IUSHR :
279       (ArithmeticInstruction)ISHR;
280     default: throw new RuntimeException JavaDoc("Invalid operand " + op);
281     }
282   }
283
284   private static final ArithmeticInstruction createBinaryLongOp(char first, String JavaDoc op) {
285     switch(first) {
286     case '-' : return LSUB;
287     case '+' : return LADD;
288     case '%' : return LREM;
289     case '*' : return LMUL;
290     case '/' : return LDIV;
291     case '&' : return LAND;
292     case '|' : return LOR;
293     case '^' : return LXOR;
294     case '<' : return LSHL;
295     case '>' : return op.equals(">>>")? (ArithmeticInstruction)LUSHR :
296       (ArithmeticInstruction)LSHR;
297     default: throw new RuntimeException JavaDoc("Invalid operand " + op);
298     }
299   }
300
301   private static final ArithmeticInstruction createBinaryFloatOp(char op) {
302     switch(op) {
303     case '-' : return FSUB;
304     case '+' : return FADD;
305     case '*' : return FMUL;
306     case '/' : return FDIV;
307     default: throw new RuntimeException JavaDoc("Invalid operand " + op);
308     }
309   }
310
311   private static final ArithmeticInstruction createBinaryDoubleOp(char op) {
312     switch(op) {
313     case '-' : return DSUB;
314     case '+' : return DADD;
315     case '*' : return DMUL;
316     case '/' : return DDIV;
317     default: throw new RuntimeException JavaDoc("Invalid operand " + op);
318     }
319   }
320
321   /**
322    * Create binary operation for simple basic types, such as int and float.
323    *
324    * @param op operation, such as "+", "*", "<<", etc.
325    */

326   public static ArithmeticInstruction createBinaryOperation(String JavaDoc op, Type type) {
327     char first = op.toCharArray()[0];
328
329     switch(type.getType()) {
330     case Constants.T_BYTE:
331     case Constants.T_SHORT:
332     case Constants.T_INT:
333     case Constants.T_CHAR: return createBinaryIntOp(first, op);
334     case Constants.T_LONG: return createBinaryLongOp(first, op);
335     case Constants.T_FLOAT: return createBinaryFloatOp(first);
336     case Constants.T_DOUBLE: return createBinaryDoubleOp(first);
337     default: throw new RuntimeException JavaDoc("Invalid type " + type);
338     }
339   }
340
341   /**
342    * @param size size of operand, either 1 (int, e.g.) or 2 (double)
343    */

344   public static StackInstruction createPop(int size) {
345     return (size == 2)? (StackInstruction)POP2 :
346       (StackInstruction)POP;
347   }
348
349   /**
350    * @param size size of operand, either 1 (int, e.g.) or 2 (double)
351    */

352   public static StackInstruction createDup(int size) {
353     return (size == 2)? (StackInstruction)DUP2 :
354       (StackInstruction)DUP;
355   }
356
357   /**
358    * @param size size of operand, either 1 (int, e.g.) or 2 (double)
359    */

360   public static StackInstruction createDup_2(int size) {
361     return (size == 2)? (StackInstruction)DUP2_X2 :
362       (StackInstruction)DUP_X2;
363   }
364
365   /**
366    * @param size size of operand, either 1 (int, e.g.) or 2 (double)
367    */

368   public static StackInstruction createDup_1(int size) {
369     return (size == 2)? (StackInstruction)DUP2_X1 :
370       (StackInstruction)DUP_X1;
371   }
372
373   /**
374    * @param index index of local variable
375    */

376   public static LocalVariableInstruction createStore(Type type, int index) {
377     switch(type.getType()) {
378     case Constants.T_BOOLEAN:
379     case Constants.T_CHAR:
380     case Constants.T_BYTE:
381     case Constants.T_SHORT:
382     case Constants.T_INT: return new ISTORE(index);
383     case Constants.T_FLOAT: return new FSTORE(index);
384     case Constants.T_DOUBLE: return new DSTORE(index);
385     case Constants.T_LONG: return new LSTORE(index);
386     case Constants.T_ARRAY:
387     case Constants.T_OBJECT: return new ASTORE(index);
388     default: throw new RuntimeException JavaDoc("Invalid type " + type);
389     }
390   }
391
392   /**
393    * @param index index of local variable
394    */

395   public static LocalVariableInstruction createLoad(Type type, int index) {
396     switch(type.getType()) {
397     case Constants.T_BOOLEAN:
398     case Constants.T_CHAR:
399     case Constants.T_BYTE:
400     case Constants.T_SHORT:
401     case Constants.T_INT: return new ILOAD(index);
402     case Constants.T_FLOAT: return new FLOAD(index);
403     case Constants.T_DOUBLE: return new DLOAD(index);
404     case Constants.T_LONG: return new LLOAD(index);
405     case Constants.T_ARRAY:
406     case Constants.T_OBJECT: return new ALOAD(index);
407     default: throw new RuntimeException JavaDoc("Invalid type " + type);
408     }
409   }
410
411   /**
412    * @param type type of elements of array, i.e., array.getElementType()
413    */

414   public static ArrayInstruction createArrayLoad(Type type) {
415     switch(type.getType()) {
416     case Constants.T_BOOLEAN:
417     case Constants.T_BYTE: return BALOAD;
418     case Constants.T_CHAR: return CALOAD;
419     case Constants.T_SHORT: return SALOAD;
420     case Constants.T_INT: return IALOAD;
421     case Constants.T_FLOAT: return FALOAD;
422     case Constants.T_DOUBLE: return DALOAD;
423     case Constants.T_LONG: return LALOAD;
424     case Constants.T_ARRAY:
425     case Constants.T_OBJECT: return AALOAD;
426     default: throw new RuntimeException JavaDoc("Invalid type " + type);
427     }
428   }
429
430   /**
431    * @param type type of elements of array, i.e., array.getElementType()
432    */

433   public static ArrayInstruction createArrayStore(Type type) {
434     switch(type.getType()) {
435     case Constants.T_BOOLEAN:
436     case Constants.T_BYTE: return BASTORE;
437     case Constants.T_CHAR: return CASTORE;
438     case Constants.T_SHORT: return SASTORE;
439     case Constants.T_INT: return IASTORE;
440     case Constants.T_FLOAT: return FASTORE;
441     case Constants.T_DOUBLE: return DASTORE;
442     case Constants.T_LONG: return LASTORE;
443     case Constants.T_ARRAY:
444     case Constants.T_OBJECT: return AASTORE;
445     default: throw new RuntimeException JavaDoc("Invalid type " + type);
446     }
447   }
448
449
450   /** Create conversion operation for two stack operands, this may be an I2C, instruction, e.g.,
451    * if the operands are basic types and CHECKCAST if they are reference types.
452    */

453   public Instruction createCast(Type src_type, Type dest_type) {
454     if((src_type instanceof BasicType) && (dest_type instanceof BasicType)) {
455       byte dest = dest_type.getType();
456       byte src = src_type.getType();
457
458       if(dest == Constants.T_LONG && (src == Constants.T_CHAR || src == Constants.T_BYTE ||
459                       src == Constants.T_SHORT))
460     src = Constants.T_INT;
461
462       String JavaDoc[] short_names = { "C", "F", "D", "B", "S", "I", "L" };
463
464       String JavaDoc name = "com.sun.org.apache.bcel.internal.generic." + short_names[src - Constants.T_CHAR] +
465     "2" + short_names[dest - Constants.T_CHAR];
466       
467       Instruction i = null;
468       try {
469     i = (Instruction)java.lang.Class.forName(name).newInstance();
470       } catch(Exception JavaDoc e) {
471     throw new RuntimeException JavaDoc("Could not find instruction: " + name);
472       }
473
474       return i;
475     } else if((src_type instanceof ReferenceType) && (dest_type instanceof ReferenceType)) {
476       if(dest_type instanceof ArrayType)
477     return new CHECKCAST(cp.addArrayClass((ArrayType)dest_type));
478       else
479     return new CHECKCAST(cp.addClass(((ObjectType)dest_type).getClassName()));
480     }
481     else
482       throw new RuntimeException JavaDoc("Can not cast " + src_type + " to " + dest_type);
483   }
484
485   public GETFIELD createGetField(String JavaDoc class_name, String JavaDoc name, Type t) {
486     return new GETFIELD(cp.addFieldref(class_name, name, t.getSignature()));
487   }
488
489   public GETSTATIC createGetStatic(String JavaDoc class_name, String JavaDoc name, Type t) {
490     return new GETSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
491   }
492
493   public PUTFIELD createPutField(String JavaDoc class_name, String JavaDoc name, Type t) {
494     return new PUTFIELD(cp.addFieldref(class_name, name, t.getSignature()));
495   }
496
497   public PUTSTATIC createPutStatic(String JavaDoc class_name, String JavaDoc name, Type t) {
498     return new PUTSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
499   }
500
501   public CHECKCAST createCheckCast(ReferenceType t) {
502     if(t instanceof ArrayType)
503       return new CHECKCAST(cp.addArrayClass((ArrayType)t));
504     else
505       return new CHECKCAST(cp.addClass((ObjectType)t));
506   }
507
508   public NEW createNew(ObjectType t) {
509     return new NEW(cp.addClass(t));
510   }
511
512   public NEW createNew(String JavaDoc s) {
513     return createNew(new ObjectType(s));
514   }
515
516   /** Create new array of given size and type.
517    */

518   public AllocationInstruction createNewArray(Type t, short dim) {
519     if(dim == 1) {
520       if(t instanceof ObjectType)
521     return new ANEWARRAY(cp.addClass((ObjectType)t));
522       else if(t instanceof ArrayType)
523     return new ANEWARRAY(cp.addArrayClass((ArrayType)t));
524       else
525     return new NEWARRAY(((BasicType)t).getType());
526     } else {
527       ArrayType at;
528
529       if(t instanceof ArrayType)
530     at = (ArrayType)t;
531       else
532     at = new ArrayType(t, dim);
533
534       return new MULTIANEWARRAY(cp.addArrayClass(at), dim);
535     }
536   }
537
538   /** Create "null" value for reference types, 0 for basic types like int
539    */

540   public static Instruction createNull(Type type) {
541     switch(type.getType()) {
542     case Constants.T_ARRAY:
543     case Constants.T_OBJECT: return ACONST_NULL;
544     case Constants.T_INT:
545     case Constants.T_SHORT:
546     case Constants.T_BOOLEAN:
547     case Constants.T_CHAR:
548     case Constants.T_BYTE: return ICONST_0;
549     case Constants.T_FLOAT: return FCONST_0;
550     case Constants.T_DOUBLE: return DCONST_0;
551     case Constants.T_LONG: return LCONST_0;
552     case Constants.T_VOID: return NOP;
553
554     default:
555       throw new RuntimeException JavaDoc("Invalid type: " + type);
556     }
557   }
558
559   /** Create branch instruction by given opcode, except LOOKUPSWITCH and TABLESWITCH.
560    * For those you should use the SWITCH compeund instruction.
561    */

562   public static BranchInstruction createBranchInstruction(short opcode, InstructionHandle target) {
563     switch(opcode) {
564     case Constants.IFEQ: return new IFEQ(target);
565     case Constants.IFNE: return new IFNE(target);
566     case Constants.IFLT: return new IFLT(target);
567     case Constants.IFGE: return new IFGE(target);
568     case Constants.IFGT: return new IFGT(target);
569     case Constants.IFLE: return new IFLE(target);
570     case Constants.IF_ICMPEQ: return new IF_ICMPEQ(target);
571     case Constants.IF_ICMPNE: return new IF_ICMPNE(target);
572     case Constants.IF_ICMPLT: return new IF_ICMPLT(target);
573     case Constants.IF_ICMPGE: return new IF_ICMPGE(target);
574     case Constants.IF_ICMPGT: return new IF_ICMPGT(target);
575     case Constants.IF_ICMPLE: return new IF_ICMPLE(target);
576     case Constants.IF_ACMPEQ: return new IF_ACMPEQ(target);
577     case Constants.IF_ACMPNE: return new IF_ACMPNE(target);
578     case Constants.GOTO: return new GOTO(target);
579     case Constants.JSR: return new JSR(target);
580     case Constants.IFNULL: return new IFNULL(target);
581     case Constants.IFNONNULL: return new IFNONNULL(target);
582     case Constants.GOTO_W: return new GOTO_W(target);
583     case Constants.JSR_W: return new JSR_W(target);
584     default:
585     throw new RuntimeException JavaDoc("Invalid opcode: " + opcode);
586     }
587   }
588
589   public void setClassGen(ClassGen c) { cg = c; }
590   public ClassGen getClassGen() { return cg; }
591   public void setConstantPool(ConstantPoolGen c) { cp = c; }
592   public ConstantPoolGen getConstantPool() { return cp; }
593 }
594
Popular Tags