KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > alt > jiapi > reflect > InstructionFactory


1 package alt.jiapi.reflect;
2
3 import java.lang.reflect.Modifier JavaDoc;
4 import java.util.List JavaDoc;
5
6 import alt.jiapi.file.ConstantPool;
7 import alt.jiapi.file.ConstantPool.ClassInfo;
8 import alt.jiapi.file.Field;
9 import alt.jiapi.file.Method;
10
11 import alt.jiapi.reflect.instruction.CPInstruction;
12 import alt.jiapi.reflect.instruction.FieldAccess;
13 import alt.jiapi.reflect.instruction.Invocation;
14 import alt.jiapi.reflect.instruction.Opcodes;
15
16 /**
17  * Class InstructionFactory.
18  *
19  * @author Mika Riekkinen
20  */

21 public class InstructionFactory {
22     private ConstantPool cp;
23
24     public InstructionFactory() {
25         this.cp = new ConstantPool();
26     }
27
28
29     /**
30      */

31     InstructionFactory(ConstantPool cp) {
32         this.cp = cp;
33     }
34
35     /**
36      * Parse bytecode and create a List of Instructions out
37      * of it.
38      *
39      * @return a List of Instructions.
40      * @exception
41      */

42     List JavaDoc createInstructionList(byte[] byteCode) {
43         InstructionParser ip = new InstructionParser();
44         return ip.createInstructionList(byteCode, cp);
45     }
46
47
48     public Instruction pushConstant(float constant) {
49         short index = cp.addFloatInfo((int)constant).getEntryIndex();
50         byte[] bytes = createLDC(index);
51         
52         return new CPInstruction(bytes, cp);//new Constant.StringConstant(bytes, index, clazz);
53
}
54
55     public Instruction pushConstant(int constant) {
56         switch(constant) {
57         case 0:
58             return new Instruction(new byte[] {Opcodes.ICONST_0});
59         case 1:
60             return new Instruction(new byte[] {Opcodes.ICONST_1});
61         case 2:
62             return new Instruction(new byte[] {Opcodes.ICONST_2});
63         case 3:
64             return new Instruction(new byte[] {Opcodes.ICONST_3});
65         case 4:
66             return new Instruction(new byte[] {Opcodes.ICONST_4});
67         case 5:
68             return new Instruction(new byte[] {Opcodes.ICONST_5});
69         }
70
71         short index = cp.addIntegerInfo(constant).getEntryIndex();
72         byte[] bytes = createLDC(index);
73         
74         return new CPInstruction(bytes, cp);
75     }
76
77     public Instruction pushConstant(String JavaDoc constant) {
78         short index = cp.addStringInfo(constant).getEntryIndex();
79         byte[] bytes = createLDC(index);
80         
81         return new CPInstruction(bytes, cp);//new Constant.StringConstant(bytes, index, clazz);
82
}
83
84     public Instruction newClass(String JavaDoc className) {
85         short index = cp.addClassInfo(className).getEntryIndex();
86         byte[] bytes = new byte[3];
87         bytes[0] = Opcodes.NEW;
88         bytes[1] = (byte) (index >> 8);
89         bytes[2] = (byte) (index & 255);
90
91         //return new Instruction(bytes);
92
return new CPInstruction(bytes, cp);
93     }
94
95
96     /**
97      * Creates a cast.
98      * It will create an InstructionList containing:
99      * <blockquote>
100      * <i>checkcast</i> #ref
101      * </blockquote>
102      *
103      * @param type type of the cast
104      * @return an InstructionList
105      */

106     public Instruction cast(String JavaDoc type) {
107         ClassInfo ci = cp.addClassInfo(type);
108         short index = ci.getEntryIndex();
109
110         byte[] bytes = new byte[3];
111         bytes[0] = Opcodes.CHECKCAST;
112         bytes[1] = (byte) (index >> 8);
113         bytes[2] = (byte) (index & 255);
114
115         return new CPInstruction(bytes, cp);
116     }
117
118
119     public Instruction pushNull() {
120         return new Instruction(new byte[] { Opcodes.ACONST_NULL });
121     }
122
123     public Instruction pushThis() {
124         return new Instruction(new byte[] { Opcodes.ALOAD_0 });
125     }
126
127
128     public Instruction returnMethod(JiapiMethod jm) {
129         String JavaDoc retType = jm.getSignature().getReturnType();
130         Instruction ins = null;
131         
132         if ("void".equals(retType)) {
133             ins = new Instruction(new byte[] { Opcodes.RETURN });
134         }
135         else if ("boolean".equals(retType) ||
136                  "int".equals(retType) ||
137                  "short".equals(retType) ||
138                  "byte".equals(retType)) {
139             ins = new Instruction(new byte[] { Opcodes.IRETURN });
140         }
141         else if ("long".equals(retType)) {
142             ins = new Instruction(new byte[] { Opcodes.LRETURN });
143         }
144         else if ("float".equals(retType)) {
145             ins = new Instruction(new byte[] { Opcodes.FRETURN });
146         }
147         else if ("double".equals(retType)) {
148             ins = new Instruction(new byte[] { Opcodes.DRETURN });
149         }
150         else {
151             ins = new Instruction(new byte[] { Opcodes.ARETURN });
152         }
153
154         return ins;
155     }
156
157
158
159     public Instruction invoke(int mods, String JavaDoc className, String JavaDoc methodName,
160                               Signature s) {
161         short index = ConstantPoolHelper.addMethodReference(cp, className,
162                                                             methodName, s);
163         
164         byte[] bytes;
165
166         if (Modifier.isStatic(mods)) {
167             bytes = new byte[3];
168             bytes[0] = Opcodes.INVOKESTATIC;
169             bytes[1] = (byte) (index >> 8);
170             bytes[2] = (byte) (index & 255);
171         }
172         else if (Modifier.isInterface(mods)) {
173             bytes = new byte[5];
174             bytes[0] = Opcodes.INVOKEINTERFACE;
175             bytes[1] = (byte) (index >> 8);
176             bytes[2] = (byte) (index & 255);
177             bytes[3] = (byte) s.getParameters().length;
178             bytes[4] = (byte) 0;
179         }
180         else if ("<init>".equals(methodName)) {
181             bytes = new byte[3];
182             bytes[0] = Opcodes.INVOKESPECIAL;
183             bytes[1] = (byte) (index >> 8);
184             bytes[2] = (byte) (index & 255);
185         }
186         else {
187             bytes = new byte[3];
188             bytes[0] = Opcodes.INVOKEVIRTUAL;
189             bytes[1] = (byte) (index >> 8);
190             bytes[2] = (byte) (index & 255);
191         }
192
193         Instruction instruction = new Invocation(bytes, cp);
194
195         return instruction;
196     }
197
198
199     public Instruction invoke(JiapiMethod jm) {
200         String JavaDoc[] params = jm.getParameterTypeNames();
201
202         short index = ConstantPoolHelper.addReference(cp, jm);
203
204         byte[] bytes;
205         int stackUsage = 1 + params.length; // object ref + params
206

207         if (Modifier.isStatic(jm.getModifiers())) {
208             bytes = new byte[3];
209             bytes[0] = Opcodes.INVOKESTATIC;
210             bytes[1] = (byte) (index >> 8);
211             bytes[2] = (byte) (index & 255);
212         }
213         else if (Modifier.isInterface(jm.getModifiers())) {
214             bytes = new byte[5];
215             bytes[0] = Opcodes.INVOKEINTERFACE;
216             bytes[1] = (byte) (index >> 8);
217             bytes[2] = (byte) (index & 255);
218             bytes[3] = (byte) params.length;
219             bytes[4] = (byte) 0;
220         }
221         else if ("<init>".equals(jm.getName())) {
222             bytes = new byte[3];
223             bytes[0] = Opcodes.INVOKESPECIAL;
224             bytes[1] = (byte) (index >> 8);
225             bytes[2] = (byte) (index & 255);
226         }
227         else {
228             bytes = new byte[3];
229             bytes[0] = Opcodes.INVOKEVIRTUAL;
230             bytes[1] = (byte) (index >> 8);
231             bytes[2] = (byte) (index & 255);
232         }
233
234         Instruction instruction = new Invocation(bytes, cp); // new Instruction(bytes);
235

236         return instruction;
237     }
238
239
240     private byte[] createLDC(short index) {
241         byte[] bytes;
242         if (index > 255) {
243             bytes = new byte[3];
244             bytes[0] = Opcodes.LDC_W;
245             bytes[1] = (byte) (index >> 8);
246             bytes[2] = (byte) (index & 255);
247         }
248         else {
249             bytes = new byte[2];
250             bytes[0] = Opcodes.LDC;
251             bytes[1] = (byte)index;
252         }
253
254         return bytes;
255     }
256
257     private byte[] createLDC_longDouble(short index) {
258         byte[] bytes = new byte[3];
259
260         bytes[0] = Opcodes.LDC2_W;
261         bytes[1] = (byte) (index >> 8);
262         bytes[2] = (byte) (index & 255);
263
264         return bytes;
265     }
266
267
268
269     public Instruction getField(int modifiers, String JavaDoc className,
270                                 String JavaDoc fieldName,
271                                 String JavaDoc fieldType) {
272         ConstantPool.ClassInfo ci =
273             cp.addClassInfo(className);
274         ConstantPool.FieldRefInfo fri =
275             cp.addFieldRefInfo(ci, fieldName, fieldType);
276
277         int index = fri.getEntryIndex();
278         byte[] bytes = new byte[3];
279
280         if (Modifier.isStatic(modifiers)) {
281             bytes[0] = Opcodes.GETSTATIC;
282             bytes[1] = (byte) (index >> 8);
283             bytes[2] = (byte) (index & 255);
284         }
285         else {
286             bytes[0] = Opcodes.GETFIELD;
287             bytes[1] = (byte) (index >> 8);
288             bytes[2] = (byte) (index & 255);
289         }
290
291         Instruction instruction = new FieldAccess(bytes, cp);
292         return instruction;
293     }
294
295     public Instruction getField(JiapiField field) {
296         ConstantPool cp =
297             field.getDeclaringClass().getConstantPool();
298
299         ConstantPool.ClassInfo ci =
300             cp.addClassInfo(field.getDeclaringClass().getName());
301         ConstantPool.FieldRefInfo fri =
302             cp.addFieldRefInfo(ci, field.getName(), field.getDescriptor());
303
304         int index = fri.getEntryIndex();
305
306         int modifiers = field.getModifiers();
307         byte[] bytes = new byte[3];
308
309         if (Modifier.isStatic(modifiers)) {
310             bytes[0] = Opcodes.GETSTATIC;
311             bytes[1] = (byte) (index >> 8);
312             bytes[2] = (byte) (index & 255);
313         }
314         else {
315             bytes[0] = Opcodes.GETFIELD;
316             bytes[1] = (byte) (index >> 8);
317             bytes[2] = (byte) (index & 255);
318         }
319
320         Instruction instruction = new FieldAccess(bytes, cp);
321         return instruction;
322     }
323
324     /**
325      * Sets a field reference to stack.
326      * It will create an InstructionList containing:
327      *
328      * <blockquote>
329      * <i>putstatic</i> #ref
330      * </blockquote>
331      *
332      * if the field is static field or:
333      *
334      * <blockquote>
335      * <i>putfield</i> #ref
336      * </blockquote>
337      *
338      * if the field is an instance field.
339      *
340      * @param field a JiapiField which will be set
341      * @return an InstructionList
342      */

343     public Instruction setField(JiapiField field) {
344         // NOTE: We could return InstructionList
345
// and do a checkcast before putfield or pustatic
346
ConstantPool cp =
347             field.getDeclaringClass().getConstantPool();
348
349         ConstantPool.ClassInfo ci =
350             cp.addClassInfo(field.getDeclaringClass().getName());
351         ConstantPool.FieldRefInfo fri =
352             cp.addFieldRefInfo(ci, field.getName(), field.getDescriptor());
353
354         int index = fri.getEntryIndex();
355
356
357         int modifiers = field.getModifiers();
358         byte[] bytes = new byte[3];
359
360         if (Modifier.isStatic(modifiers)) {
361             bytes[0] = Opcodes.PUTSTATIC;
362             bytes[1] = (byte) (index >> 8);
363             bytes[2] = (byte) (index & 255);
364         }
365         else {
366             bytes[0] = Opcodes.PUTFIELD;
367             bytes[1] = (byte) (index >> 8);
368             bytes[2] = (byte) (index & 255);
369         }
370
371         Instruction instruction = new FieldAccess(bytes, cp);
372         return instruction;
373     }
374
375     
376     public Instruction aload(int idx) {
377         // NOTE: <wide> support missing
378
switch(idx) {
379         case 0:
380             return new Instruction(new byte[] {Opcodes.ALOAD_0});
381         case 1:
382             return new Instruction(new byte[] {Opcodes.ALOAD_1});
383         case 2:
384             return new Instruction(new byte[] {Opcodes.ALOAD_2});
385         case 3:
386             return new Instruction(new byte[] {Opcodes.ALOAD_3});
387         default:
388             return new Instruction(new byte[] {Opcodes.ALOAD, (byte)idx});
389         }
390     }
391     
392     public Instruction iload(int idx) {
393         // NOTE: <wide> support missing
394
switch(idx) {
395         case 0:
396             return new Instruction(new byte[] {Opcodes.ILOAD_0});
397         case 1:
398             return new Instruction(new byte[] {Opcodes.ILOAD_1});
399         case 2:
400             return new Instruction(new byte[] {Opcodes.ILOAD_2});
401         case 3:
402             return new Instruction(new byte[] {Opcodes.ILOAD_3});
403         default:
404             return new Instruction(new byte[] {Opcodes.ILOAD, (byte)idx});
405         }
406     }
407
408     public Instruction lload(int idx) {
409         // NOTE: <wide> support missing
410
switch(idx) {
411         case 0:
412             return new Instruction(new byte[] {Opcodes.LLOAD_0});
413         case 1:
414             return new Instruction(new byte[] {Opcodes.LLOAD_1});
415         case 2:
416             return new Instruction(new byte[] {Opcodes.LLOAD_2});
417         case 3:
418             return new Instruction(new byte[] {Opcodes.LLOAD_3});
419         default:
420             return new Instruction(new byte[] {Opcodes.LLOAD, (byte)idx});
421         }
422     }
423
424     public Instruction dload(int idx) {
425         // NOTE: <wide> support missing
426
switch(idx) {
427         case 0:
428             return new Instruction(new byte[] {Opcodes.DLOAD_0});
429         case 1:
430             return new Instruction(new byte[] {Opcodes.DLOAD_1});
431         case 2:
432             return new Instruction(new byte[] {Opcodes.DLOAD_2});
433         case 3:
434             return new Instruction(new byte[] {Opcodes.DLOAD_3});
435         default:
436             return new Instruction(new byte[] {Opcodes.DLOAD, (byte)idx});
437         }
438     }
439
440     public Instruction fload(int idx) {
441         // NOTE: <wide> support missing
442
switch(idx) {
443         case 0:
444             return new Instruction(new byte[] {Opcodes.FLOAD_0});
445         case 1:
446             return new Instruction(new byte[] {Opcodes.FLOAD_1});
447         case 2:
448             return new Instruction(new byte[] {Opcodes.FLOAD_2});
449         case 3:
450             return new Instruction(new byte[] {Opcodes.FLOAD_3});
451         default:
452             return new Instruction(new byte[] {Opcodes.FLOAD, (byte)idx});
453         }
454     }
455
456     public Instruction astore(int idx) {
457         // NOTE: <wide> support missing
458
switch(idx) {
459         case 0:
460             return new Instruction(new byte[] {Opcodes.ASTORE_0});
461         case 1:
462             return new Instruction(new byte[] {Opcodes.ASTORE_1});
463         case 2:
464             return new Instruction(new byte[] {Opcodes.ASTORE_2});
465         case 3:
466             return new Instruction(new byte[] {Opcodes.ASTORE_3});
467         default:
468             return new Instruction(new byte[] {Opcodes.ASTORE, (byte)idx});
469         }
470     }
471
472     public Instruction istore(int idx) {
473         // NOTE: <wide> support missing
474
switch(idx) {
475         case 0:
476             return new Instruction(new byte[] {Opcodes.ISTORE_0});
477         case 1:
478             return new Instruction(new byte[] {Opcodes.ISTORE_1});
479         case 2:
480             return new Instruction(new byte[] {Opcodes.ISTORE_2});
481         case 3:
482             return new Instruction(new byte[] {Opcodes.ISTORE_3});
483         default:
484             return new Instruction(new byte[] {Opcodes.ISTORE, (byte)idx});
485         }
486     }
487
488     public Instruction lstore(int idx) {
489         // NOTE: <wide> support missing
490
switch(idx) {
491         case 0:
492             return new Instruction(new byte[] {Opcodes.LSTORE_0});
493         case 1:
494             return new Instruction(new byte[] {Opcodes.LSTORE_1});
495         case 2:
496             return new Instruction(new byte[] {Opcodes.LSTORE_2});
497         case 3:
498             return new Instruction(new byte[] {Opcodes.LSTORE_3});
499         default:
500             return new Instruction(new byte[] {Opcodes.LSTORE, (byte)idx});
501         }
502     }
503
504     public Instruction fstore(int idx) {
505         // NOTE: <wide> support missing
506
switch(idx) {
507         case 0:
508             return new Instruction(new byte[] {Opcodes.FSTORE_0});
509         case 1:
510             return new Instruction(new byte[] {Opcodes.FSTORE_1});
511         case 2:
512             return new Instruction(new byte[] {Opcodes.FSTORE_2});
513         case 3:
514             return new Instruction(new byte[] {Opcodes.FSTORE_3});
515         default:
516             return new Instruction(new byte[] {Opcodes.FSTORE, (byte)idx});
517         }
518     }
519     
520     public Instruction dstore(int idx) {
521         // NOTE: <wide> support missing
522
switch(idx) {
523         case 0:
524             return new Instruction(new byte[] {Opcodes.DSTORE_0});
525         case 1:
526             return new Instruction(new byte[] {Opcodes.DSTORE_1});
527         case 2:
528             return new Instruction(new byte[] {Opcodes.DSTORE_2});
529         case 3:
530             return new Instruction(new byte[] {Opcodes.DSTORE_3});
531         default:
532             return new Instruction(new byte[] {Opcodes.DSTORE, (byte)idx});
533         }
534     }
535
536     public Instruction aastore() {
537         return new Instruction(new byte[] {Opcodes.AASTORE});
538     }
539
540     public Instruction dup() {
541         return new Instruction(new byte[] {Opcodes.DUP});
542     }
543     public Instruction dup2() {
544         return new Instruction(new byte[] {Opcodes.DUP2});
545     }
546
547     public InstructionList newArray(String JavaDoc type, int size) {
548         InstructionList il = new InstructionList(cp);
549         il.add(pushConstant(size));
550
551         if (SignatureUtil.isPrimitive(type)) {
552             throw new RuntimeException JavaDoc("NOT implemented: new array for primitive types");
553         }
554         else {
555             ClassInfo ci = cp.addClassInfo("java.lang.Object");
556             short idx = ci.getEntryIndex();
557
558             il.add(new CPInstruction(new byte[] {Opcodes.ANEWARRAY,
559                                                  (byte)(idx >> 8),
560                                                  (byte)(idx& 0xff)},
561                                      cp));
562         }
563
564         return il;
565     }
566
567
568 // public Instruction objectArrayStore(int idx) {
569

570 // }
571

572 // /**
573
// * Swap the top two values on the operand stack.
574
// */
575
// public Instruction swap() {
576
// return new Instruction(new byte[] {Opcodes.SWAP});
577
// }
578
}
579
Popular Tags