view src/clojure/asm/commons/AnalyzerAdapter.java @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
line wrap: on
line source
1 /***
2 * ASM: a very small and fast Java bytecode manipulation framework
3 * Copyright (c) 2000-2005 INRIA, France Telecom
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 package clojure.asm.commons;
32 import java.util.ArrayList;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
37 import clojure.asm.Label;
38 import clojure.asm.MethodAdapter;
39 import clojure.asm.MethodVisitor;
40 import clojure.asm.Opcodes;
41 import clojure.asm.Type;
43 /**
44 * A {@link MethodAdapter} that keeps track of stack map frame changes between
45 * {@link #visitFrame(int,int,Object[],int,Object[]) visitFrame} calls. This
46 * adapter must be used with the
47 * {@link clojure.asm.ClassReader#EXPAND_FRAMES} option. Each visit<i>XXX</i>
48 * instruction delegates to the next visitor in the chain, if any, and then
49 * simulates the effect of this instruction on the stack map frame, represented
50 * by {@link #locals} and {@link #stack}. The next visitor in the chain can get
51 * the state of the stack map frame <i>before</i> each instruction by reading
52 * the value of these fields in its visit<i>XXX</i> methods (this requires a
53 * reference to the AnalyzerAdapter that is before it in the chain).
54 *
55 * @author Eric Bruneton
56 */
57 public class AnalyzerAdapter extends MethodAdapter{
59 /**
60 * <code>List</code> of the local variable slots for current execution
61 * frame. Primitive types are represented by {@link Opcodes#TOP},
62 * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
63 * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
64 * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by a
65 * two elements, the second one being TOP). Reference types are represented
66 * by String objects (representing internal names, or type descriptors for
67 * array types), and uninitialized types by Label objects (this label
68 * designates the NEW instruction that created this uninitialized value).
69 * This field is <tt>null</tt> for unreacheable instructions.
70 */
71 public List locals;
73 /**
74 * <code>List</code> of the operand stack slots for current execution
75 * frame. Primitive types are represented by {@link Opcodes#TOP},
76 * {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
77 * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
78 * {@link Opcodes#UNINITIALIZED_THIS} (long and double are represented by a
79 * two elements, the second one being TOP). Reference types are represented
80 * by String objects (representing internal names, or type descriptors for
81 * array types), and uninitialized types by Label objects (this label
82 * designates the NEW instruction that created this uninitialized value).
83 * This field is <tt>null</tt> for unreacheable instructions.
84 */
85 public List stack;
87 /**
88 * The labels that designate the next instruction to be visited. May be
89 * <tt>null</tt>.
90 */
91 private List labels;
93 /**
94 * Information about uninitialized types in the current execution frame.
95 * This map associates internal names to Label objects. Each label
96 * designates a NEW instruction that created the currently uninitialized
97 * types, and the associated internal name represents the NEW operand, i.e.
98 * the final, initialized type value.
99 */
100 private Map uninitializedTypes;
102 /**
103 * The maximum stack size of this method.
104 */
105 private int maxStack;
107 /**
108 * The maximum number of local variables of this method.
109 */
110 private int maxLocals;
112 /**
113 * Creates a new {@link AnalyzerAdapter}.
114 *
115 * @param owner the owner's class name.
116 * @param access the method's access flags (see {@link Opcodes}).
117 * @param name the method's name.
118 * @param desc the method's descriptor (see {@link Type Type}).
119 * @param mv the method visitor to which this adapter delegates calls. May
120 * be <tt>null</tt>.
121 */
122 public AnalyzerAdapter(
123 final String owner,
124 final int access,
125 final String name,
126 final String desc,
127 final MethodVisitor mv){
128 super(mv);
129 locals = new ArrayList();
130 stack = new ArrayList();
131 uninitializedTypes = new HashMap();
133 if((access & Opcodes.ACC_STATIC) == 0)
134 {
135 if(name.equals("<init>"))
136 {
137 locals.add(Opcodes.UNINITIALIZED_THIS);
138 }
139 else
140 {
141 locals.add(owner);
142 }
143 }
144 Type[] types = Type.getArgumentTypes(desc);
145 for(int i = 0; i < types.length; ++i)
146 {
147 Type type = types[i];
148 switch(type.getSort())
149 {
150 case Type.BOOLEAN:
151 case Type.CHAR:
152 case Type.BYTE:
153 case Type.SHORT:
154 case Type.INT:
155 locals.add(Opcodes.INTEGER);
156 break;
157 case Type.FLOAT:
158 locals.add(Opcodes.FLOAT);
159 break;
160 case Type.LONG:
161 locals.add(Opcodes.LONG);
162 locals.add(Opcodes.TOP);
163 break;
164 case Type.DOUBLE:
165 locals.add(Opcodes.DOUBLE);
166 locals.add(Opcodes.TOP);
167 break;
168 case Type.ARRAY:
169 locals.add(types[i].getDescriptor());
170 break;
171 // case Type.OBJECT:
172 default:
173 locals.add(types[i].getInternalName());
174 }
175 }
176 }
178 public void visitFrame(
179 final int type,
180 final int nLocal,
181 final Object[] local,
182 final int nStack,
183 final Object[] stack){
184 if(type != Opcodes.F_NEW)
185 { // uncompressed frame
186 throw new IllegalStateException("ClassReader.accept() should be called with EXPAND_FRAMES flag");
187 }
189 if(mv != null)
190 {
191 mv.visitFrame(type, nLocal, local, nStack, stack);
192 }
194 if(this.locals != null)
195 {
196 this.locals.clear();
197 this.stack.clear();
198 }
199 else
200 {
201 this.locals = new ArrayList();
202 this.stack = new ArrayList();
203 }
204 visitFrameTypes(nLocal, local, this.locals);
205 visitFrameTypes(nStack, stack, this.stack);
206 maxStack = Math.max(maxStack, this.stack.size());
207 }
209 private void visitFrameTypes(
210 final int n,
211 final Object[] types,
212 final List result){
213 for(int i = 0; i < n; ++i)
214 {
215 Object type = types[i];
216 result.add(type);
217 if(type == Opcodes.LONG || type == Opcodes.DOUBLE)
218 {
219 result.add(Opcodes.TOP);
220 }
221 }
222 }
224 public void visitInsn(final int opcode){
225 if(mv != null)
226 {
227 mv.visitInsn(opcode);
228 }
229 execute(opcode, 0, null);
230 if((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
231 || opcode == Opcodes.ATHROW)
232 {
233 this.locals = null;
234 this.stack = null;
235 }
236 }
238 public void visitIntInsn(final int opcode, final int operand){
239 if(mv != null)
240 {
241 mv.visitIntInsn(opcode, operand);
242 }
243 execute(opcode, operand, null);
244 }
246 public void visitVarInsn(final int opcode, final int var){
247 if(mv != null)
248 {
249 mv.visitVarInsn(opcode, var);
250 }
251 execute(opcode, var, null);
252 }
254 public void visitTypeInsn(final int opcode, final String desc){
255 if(opcode == Opcodes.NEW)
256 {
257 if(labels == null)
258 {
259 Label l = new Label();
260 labels = new ArrayList(3);
261 labels.add(l);
262 if(mv != null)
263 {
264 mv.visitLabel(l);
265 }
266 }
267 for(int i = 0; i < labels.size(); ++i)
268 {
269 uninitializedTypes.put(labels.get(i), desc);
270 }
271 }
272 if(mv != null)
273 {
274 mv.visitTypeInsn(opcode, desc);
275 }
276 execute(opcode, 0, desc);
277 }
279 public void visitFieldInsn(
280 final int opcode,
281 final String owner,
282 final String name,
283 final String desc){
284 if(mv != null)
285 {
286 mv.visitFieldInsn(opcode, owner, name, desc);
287 }
288 execute(opcode, 0, desc);
289 }
291 public void visitMethodInsn(
292 final int opcode,
293 final String owner,
294 final String name,
295 final String desc){
296 if(mv != null)
297 {
298 mv.visitMethodInsn(opcode, owner, name, desc);
299 }
300 pop(desc);
301 if(opcode != Opcodes.INVOKESTATIC)
302 {
303 Object t = pop();
304 if(opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<')
305 {
306 Object u;
307 if(t == Opcodes.UNINITIALIZED_THIS)
308 {
309 u = owner;
310 }
311 else
312 {
313 u = uninitializedTypes.get(t);
314 }
315 for(int i = 0; i < locals.size(); ++i)
316 {
317 if(locals.get(i) == t)
318 {
319 locals.set(i, u);
320 }
321 }
322 for(int i = 0; i < stack.size(); ++i)
323 {
324 if(stack.get(i) == t)
325 {
326 stack.set(i, u);
327 }
328 }
329 }
330 }
331 pushDesc(desc);
332 labels = null;
333 }
335 public void visitJumpInsn(final int opcode, final Label label){
336 if(mv != null)
337 {
338 mv.visitJumpInsn(opcode, label);
339 }
340 execute(opcode, 0, null);
341 if(opcode == Opcodes.GOTO)
342 {
343 this.locals = null;
344 this.stack = null;
345 }
346 }
348 public void visitLabel(final Label label){
349 if(mv != null)
350 {
351 mv.visitLabel(label);
352 }
353 if(labels == null)
354 {
355 labels = new ArrayList(3);
356 }
357 labels.add(label);
358 }
360 public void visitLdcInsn(final Object cst){
361 if(mv != null)
362 {
363 mv.visitLdcInsn(cst);
364 }
365 if(cst instanceof Integer)
366 {
367 push(Opcodes.INTEGER);
368 }
369 else if(cst instanceof Long)
370 {
371 push(Opcodes.LONG);
372 push(Opcodes.TOP);
373 }
374 else if(cst instanceof Float)
375 {
376 push(Opcodes.FLOAT);
377 }
378 else if(cst instanceof Double)
379 {
380 push(Opcodes.DOUBLE);
381 push(Opcodes.TOP);
382 }
383 else if(cst instanceof String)
384 {
385 push("java/lang/String");
386 }
387 else if(cst instanceof Type)
388 {
389 push("java/lang/Class");
390 }
391 else
392 {
393 throw new IllegalArgumentException();
394 }
395 labels = null;
396 }
398 public void visitIincInsn(final int var, final int increment){
399 if(mv != null)
400 {
401 mv.visitIincInsn(var, increment);
402 }
403 execute(Opcodes.IINC, var, null);
404 }
406 public void visitTableSwitchInsn(
407 final int min,
408 final int max,
409 final Label dflt,
410 final Label labels[]){
411 if(mv != null)
412 {
413 mv.visitTableSwitchInsn(min, max, dflt, labels);
414 }
415 execute(Opcodes.TABLESWITCH, 0, null);
416 this.locals = null;
417 this.stack = null;
418 }
420 public void visitLookupSwitchInsn(
421 final Label dflt,
422 final int keys[],
423 final Label labels[]){
424 if(mv != null)
425 {
426 mv.visitLookupSwitchInsn(dflt, keys, labels);
427 }
428 execute(Opcodes.LOOKUPSWITCH, 0, null);
429 this.locals = null;
430 this.stack = null;
431 }
433 public void visitMultiANewArrayInsn(final String desc, final int dims){
434 if(mv != null)
435 {
436 mv.visitMultiANewArrayInsn(desc, dims);
437 }
438 execute(Opcodes.MULTIANEWARRAY, dims, desc);
439 }
441 public void visitMaxs(final int maxStack, final int maxLocals){
442 if(mv != null)
443 {
444 this.maxStack = Math.max(this.maxStack, maxStack);
445 this.maxLocals = Math.max(this.maxLocals, maxLocals);
446 mv.visitMaxs(this.maxStack, this.maxLocals);
447 }
448 }
450 // ------------------------------------------------------------------------
452 private Object get(final int local){
453 maxLocals = Math.max(maxLocals, local);
454 return local < locals.size() ? locals.get(local) : Opcodes.TOP;
455 }
457 private void set(final int local, final Object type){
458 maxLocals = Math.max(maxLocals, local);
459 while(local >= locals.size())
460 {
461 locals.add(Opcodes.TOP);
462 }
463 locals.set(local, type);
464 }
466 private void push(final Object type){
467 stack.add(type);
468 maxStack = Math.max(maxStack, stack.size());
469 }
471 private void pushDesc(final String desc){
472 int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
473 switch(desc.charAt(index))
474 {
475 case'V':
476 return;
477 case'Z':
478 case'C':
479 case'B':
480 case'S':
481 case'I':
482 push(Opcodes.INTEGER);
483 return;
484 case'F':
485 push(Opcodes.FLOAT);
486 return;
487 case'J':
488 push(Opcodes.LONG);
489 push(Opcodes.TOP);
490 return;
491 case'D':
492 push(Opcodes.DOUBLE);
493 push(Opcodes.TOP);
494 return;
495 case'[':
496 if(index == 0)
497 {
498 push(desc);
499 }
500 else
501 {
502 push(desc.substring(index, desc.length()));
503 }
504 break;
505 // case 'L':
506 default:
507 if(index == 0)
508 {
509 push(desc.substring(1, desc.length() - 1));
510 }
511 else
512 {
513 push(desc.substring(index + 1, desc.length() - 1));
514 }
515 return;
516 }
517 }
519 private Object pop(){
520 return stack.remove(stack.size() - 1);
521 }
523 private void pop(final int n){
524 int size = stack.size();
525 int end = size - n;
526 for(int i = size - 1; i >= end; --i)
527 {
528 stack.remove(i);
529 }
530 }
532 private void pop(final String desc){
533 char c = desc.charAt(0);
534 if(c == '(')
535 {
536 int n = 0;
537 Type[] types = Type.getArgumentTypes(desc);
538 for(int i = 0; i < types.length; ++i)
539 {
540 n += types[i].getSize();
541 }
542 pop(n);
543 }
544 else if(c == 'J' || c == 'D')
545 {
546 pop(2);
547 }
548 else
549 {
550 pop(1);
551 }
552 }
554 private void execute(final int opcode, final int iarg, final String sarg){
555 if(this.locals == null)
556 {
557 return;
558 }
559 Object t1, t2, t3, t4;
560 switch(opcode)
561 {
562 case Opcodes.NOP:
563 case Opcodes.INEG:
564 case Opcodes.LNEG:
565 case Opcodes.FNEG:
566 case Opcodes.DNEG:
567 case Opcodes.I2B:
568 case Opcodes.I2C:
569 case Opcodes.I2S:
570 case Opcodes.GOTO:
571 case Opcodes.RETURN:
572 break;
573 case Opcodes.ACONST_NULL:
574 push(Opcodes.NULL);
575 break;
576 case Opcodes.ICONST_M1:
577 case Opcodes.ICONST_0:
578 case Opcodes.ICONST_1:
579 case Opcodes.ICONST_2:
580 case Opcodes.ICONST_3:
581 case Opcodes.ICONST_4:
582 case Opcodes.ICONST_5:
583 case Opcodes.BIPUSH:
584 case Opcodes.SIPUSH:
585 push(Opcodes.INTEGER);
586 break;
587 case Opcodes.LCONST_0:
588 case Opcodes.LCONST_1:
589 push(Opcodes.LONG);
590 push(Opcodes.TOP);
591 break;
592 case Opcodes.FCONST_0:
593 case Opcodes.FCONST_1:
594 case Opcodes.FCONST_2:
595 push(Opcodes.FLOAT);
596 break;
597 case Opcodes.DCONST_0:
598 case Opcodes.DCONST_1:
599 push(Opcodes.DOUBLE);
600 push(Opcodes.TOP);
601 break;
602 case Opcodes.ILOAD:
603 case Opcodes.FLOAD:
604 case Opcodes.ALOAD:
605 push(get(iarg));
606 break;
607 case Opcodes.LLOAD:
608 case Opcodes.DLOAD:
609 push(get(iarg));
610 push(Opcodes.TOP);
611 break;
612 case Opcodes.IALOAD:
613 case Opcodes.BALOAD:
614 case Opcodes.CALOAD:
615 case Opcodes.SALOAD:
616 pop(2);
617 push(Opcodes.INTEGER);
618 break;
619 case Opcodes.LALOAD:
620 case Opcodes.D2L:
621 pop(2);
622 push(Opcodes.LONG);
623 push(Opcodes.TOP);
624 break;
625 case Opcodes.FALOAD:
626 pop(2);
627 push(Opcodes.FLOAT);
628 break;
629 case Opcodes.DALOAD:
630 case Opcodes.L2D:
631 pop(2);
632 push(Opcodes.DOUBLE);
633 push(Opcodes.TOP);
634 break;
635 case Opcodes.AALOAD:
636 pop(1);
637 t1 = pop();
638 pushDesc(((String) t1).substring(1));
639 break;
640 case Opcodes.ISTORE:
641 case Opcodes.FSTORE:
642 case Opcodes.ASTORE:
643 t1 = pop();
644 set(iarg, t1);
645 if(iarg > 0)
646 {
647 t2 = get(iarg - 1);
648 if(t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE)
649 {
650 set(iarg - 1, Opcodes.TOP);
651 }
652 }
653 break;
654 case Opcodes.LSTORE:
655 case Opcodes.DSTORE:
656 pop(1);
657 t1 = pop();
658 set(iarg, t1);
659 set(iarg + 1, Opcodes.TOP);
660 if(iarg > 0)
661 {
662 t2 = get(iarg - 1);
663 if(t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE)
664 {
665 set(iarg - 1, Opcodes.TOP);
666 }
667 }
668 break;
669 case Opcodes.IASTORE:
670 case Opcodes.BASTORE:
671 case Opcodes.CASTORE:
672 case Opcodes.SASTORE:
673 case Opcodes.FASTORE:
674 case Opcodes.AASTORE:
675 pop(3);
676 break;
677 case Opcodes.LASTORE:
678 case Opcodes.DASTORE:
679 pop(4);
680 break;
681 case Opcodes.POP:
682 case Opcodes.IFEQ:
683 case Opcodes.IFNE:
684 case Opcodes.IFLT:
685 case Opcodes.IFGE:
686 case Opcodes.IFGT:
687 case Opcodes.IFLE:
688 case Opcodes.IRETURN:
689 case Opcodes.FRETURN:
690 case Opcodes.ARETURN:
691 case Opcodes.TABLESWITCH:
692 case Opcodes.LOOKUPSWITCH:
693 case Opcodes.ATHROW:
694 case Opcodes.MONITORENTER:
695 case Opcodes.MONITOREXIT:
696 case Opcodes.IFNULL:
697 case Opcodes.IFNONNULL:
698 pop(1);
699 break;
700 case Opcodes.POP2:
701 case Opcodes.IF_ICMPEQ:
702 case Opcodes.IF_ICMPNE:
703 case Opcodes.IF_ICMPLT:
704 case Opcodes.IF_ICMPGE:
705 case Opcodes.IF_ICMPGT:
706 case Opcodes.IF_ICMPLE:
707 case Opcodes.IF_ACMPEQ:
708 case Opcodes.IF_ACMPNE:
709 case Opcodes.LRETURN:
710 case Opcodes.DRETURN:
711 pop(2);
712 break;
713 case Opcodes.DUP:
714 t1 = pop();
715 push(t1);
716 push(t1);
717 break;
718 case Opcodes.DUP_X1:
719 t1 = pop();
720 t2 = pop();
721 push(t1);
722 push(t2);
723 push(t1);
724 break;
725 case Opcodes.DUP_X2:
726 t1 = pop();
727 t2 = pop();
728 t3 = pop();
729 push(t1);
730 push(t3);
731 push(t2);
732 push(t1);
733 break;
734 case Opcodes.DUP2:
735 t1 = pop();
736 t2 = pop();
737 push(t2);
738 push(t1);
739 push(t2);
740 push(t1);
741 break;
742 case Opcodes.DUP2_X1:
743 t1 = pop();
744 t2 = pop();
745 t3 = pop();
746 push(t2);
747 push(t1);
748 push(t3);
749 push(t2);
750 push(t1);
751 break;
752 case Opcodes.DUP2_X2:
753 t1 = pop();
754 t2 = pop();
755 t3 = pop();
756 t4 = pop();
757 push(t2);
758 push(t1);
759 push(t4);
760 push(t3);
761 push(t2);
762 push(t1);
763 break;
764 case Opcodes.SWAP:
765 t1 = pop();
766 t2 = pop();
767 push(t1);
768 push(t2);
769 break;
770 case Opcodes.IADD:
771 case Opcodes.ISUB:
772 case Opcodes.IMUL:
773 case Opcodes.IDIV:
774 case Opcodes.IREM:
775 case Opcodes.IAND:
776 case Opcodes.IOR:
777 case Opcodes.IXOR:
778 case Opcodes.ISHL:
779 case Opcodes.ISHR:
780 case Opcodes.IUSHR:
781 case Opcodes.L2I:
782 case Opcodes.D2I:
783 case Opcodes.FCMPL:
784 case Opcodes.FCMPG:
785 pop(2);
786 push(Opcodes.INTEGER);
787 break;
788 case Opcodes.LADD:
789 case Opcodes.LSUB:
790 case Opcodes.LMUL:
791 case Opcodes.LDIV:
792 case Opcodes.LREM:
793 case Opcodes.LAND:
794 case Opcodes.LOR:
795 case Opcodes.LXOR:
796 pop(4);
797 push(Opcodes.LONG);
798 push(Opcodes.TOP);
799 break;
800 case Opcodes.FADD:
801 case Opcodes.FSUB:
802 case Opcodes.FMUL:
803 case Opcodes.FDIV:
804 case Opcodes.FREM:
805 case Opcodes.L2F:
806 case Opcodes.D2F:
807 pop(2);
808 push(Opcodes.FLOAT);
809 break;
810 case Opcodes.DADD:
811 case Opcodes.DSUB:
812 case Opcodes.DMUL:
813 case Opcodes.DDIV:
814 case Opcodes.DREM:
815 pop(4);
816 push(Opcodes.DOUBLE);
817 push(Opcodes.TOP);
818 break;
819 case Opcodes.LSHL:
820 case Opcodes.LSHR:
821 case Opcodes.LUSHR:
822 pop(3);
823 push(Opcodes.LONG);
824 push(Opcodes.TOP);
825 break;
826 case Opcodes.IINC:
827 set(iarg, Opcodes.INTEGER);
828 break;
829 case Opcodes.I2L:
830 case Opcodes.F2L:
831 pop(1);
832 push(Opcodes.LONG);
833 push(Opcodes.TOP);
834 break;
835 case Opcodes.I2F:
836 pop(1);
837 push(Opcodes.FLOAT);
838 break;
839 case Opcodes.I2D:
840 case Opcodes.F2D:
841 pop(1);
842 push(Opcodes.DOUBLE);
843 push(Opcodes.TOP);
844 break;
845 case Opcodes.F2I:
846 case Opcodes.ARRAYLENGTH:
847 case Opcodes.INSTANCEOF:
848 pop(1);
849 push(Opcodes.INTEGER);
850 break;
851 case Opcodes.LCMP:
852 case Opcodes.DCMPL:
853 case Opcodes.DCMPG:
854 pop(4);
855 push(Opcodes.INTEGER);
856 break;
857 case Opcodes.JSR:
858 case Opcodes.RET:
859 throw new RuntimeException("JSR/RET are not supported");
860 case Opcodes.GETSTATIC:
861 pushDesc(sarg);
862 break;
863 case Opcodes.PUTSTATIC:
864 pop(sarg);
865 break;
866 case Opcodes.GETFIELD:
867 pop(1);
868 pushDesc(sarg);
869 break;
870 case Opcodes.PUTFIELD:
871 pop(sarg);
872 pop();
873 break;
874 case Opcodes.NEW:
875 push(labels.get(0));
876 break;
877 case Opcodes.NEWARRAY:
878 pop();
879 switch(iarg)
880 {
881 case Opcodes.T_BOOLEAN:
882 pushDesc("[Z");
883 break;
884 case Opcodes.T_CHAR:
885 pushDesc("[C");
886 break;
887 case Opcodes.T_BYTE:
888 pushDesc("[B");
889 break;
890 case Opcodes.T_SHORT:
891 pushDesc("[S");
892 break;
893 case Opcodes.T_INT:
894 pushDesc("[I");
895 break;
896 case Opcodes.T_FLOAT:
897 pushDesc("[F");
898 break;
899 case Opcodes.T_DOUBLE:
900 pushDesc("[D");
901 break;
902 // case Opcodes.T_LONG:
903 default:
904 pushDesc("[J");
905 break;
906 }
907 break;
908 case Opcodes.ANEWARRAY:
909 pop();
910 if(sarg.charAt(0) == '[')
911 {
912 pushDesc("[" + sarg);
913 }
914 else
915 {
916 pushDesc("[L" + sarg + ";");
917 }
918 break;
919 case Opcodes.CHECKCAST:
920 pop();
921 if(sarg.charAt(0) == '[')
922 {
923 pushDesc(sarg);
924 }
925 else
926 {
927 push(sarg);
928 }
929 break;
930 // case Opcodes.MULTIANEWARRAY:
931 default:
932 pop(iarg);
933 pushDesc(sarg);
934 break;
935 }
936 labels = null;
937 }
938 }