Mercurial > lasercutter
comparison 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 |
comparison
equal
deleted
inserted
replaced
9:35cf337adfcf | 10:ef7dbbd6452c |
---|---|
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; | |
31 | |
32 import java.util.ArrayList; | |
33 import java.util.HashMap; | |
34 import java.util.List; | |
35 import java.util.Map; | |
36 | |
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; | |
42 | |
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{ | |
58 | |
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; | |
72 | |
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; | |
86 | |
87 /** | |
88 * The labels that designate the next instruction to be visited. May be | |
89 * <tt>null</tt>. | |
90 */ | |
91 private List labels; | |
92 | |
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; | |
101 | |
102 /** | |
103 * The maximum stack size of this method. | |
104 */ | |
105 private int maxStack; | |
106 | |
107 /** | |
108 * The maximum number of local variables of this method. | |
109 */ | |
110 private int maxLocals; | |
111 | |
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(); | |
132 | |
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 } | |
177 | |
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 } | |
188 | |
189 if(mv != null) | |
190 { | |
191 mv.visitFrame(type, nLocal, local, nStack, stack); | |
192 } | |
193 | |
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 } | |
208 | |
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 } | |
223 | |
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 } | |
237 | |
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 } | |
245 | |
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 } | |
253 | |
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 } | |
278 | |
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 } | |
290 | |
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 } | |
334 | |
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 } | |
347 | |
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 } | |
359 | |
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 } | |
397 | |
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 } | |
405 | |
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 } | |
419 | |
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 } | |
432 | |
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 } | |
440 | |
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 } | |
449 | |
450 // ------------------------------------------------------------------------ | |
451 | |
452 private Object get(final int local){ | |
453 maxLocals = Math.max(maxLocals, local); | |
454 return local < locals.size() ? locals.get(local) : Opcodes.TOP; | |
455 } | |
456 | |
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 } | |
465 | |
466 private void push(final Object type){ | |
467 stack.add(type); | |
468 maxStack = Math.max(maxStack, stack.size()); | |
469 } | |
470 | |
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 } | |
518 | |
519 private Object pop(){ | |
520 return stack.remove(stack.size() - 1); | |
521 } | |
522 | |
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 } | |
531 | |
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 } | |
553 | |
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 } |