1
2
3
4 package joeq.Interpreter;
5
6 import joeq.Class.PrimordialClassLoader;
7 import joeq.Class.jq_Array;
8 import joeq.Class.jq_Class;
9 import joeq.Class.jq_InstanceField;
10 import joeq.Class.jq_InstanceMethod;
11 import joeq.Class.jq_Method;
12 import joeq.Class.jq_Reference;
13 import joeq.Class.jq_StaticField;
14 import joeq.Class.jq_TryCatchBC;
15 import joeq.Class.jq_Type;
16 import joeq.Compiler.BytecodeAnalysis.BytecodeVisitor;
17 import joeq.Runtime.Reflection;
18 import jwutil.util.Assert;
19
20
21
22
23
24 public abstract class BytecodeInterpreter {
25
26 public static
27
28 /*** Creates new Interpreter */
29 public BytecodeInterpreter(VMInterface vm, State istate) {
30 this.vm = vm; this.istate = istate;
31 }
32
33
34 public abstract Object invokeMethod(jq_Method m) throws Throwable;
35 public abstract Object invokeUnsafeMethod(jq_Method m) throws Throwable;
36
37 protected State istate;
38 protected final VMInterface vm;
39
40 public abstract static class State {
41 public abstract void push_I(int v);
42 public abstract void push_L(long v);
43 public abstract void push_F(float v);
44 public abstract void push_D(double v);
45 public abstract void push_A(Object v);
46 public abstract void push(Object v);
47 public abstract int pop_I();
48 public abstract long pop_L();
49 public abstract float pop_F();
50 public abstract double pop_D();
51 public abstract Object pop_A();
52 public abstract Object pop();
53 public abstract void popAll();
54 public abstract Object peek_A(int depth);
55 public abstract void setLocal_I(int i, int v);
56 public abstract void setLocal_L(int i, long v);
57 public abstract void setLocal_F(int i, float v);
58 public abstract void setLocal_D(int i, double v);
59 public abstract void setLocal_A(int i, Object v);
60 public abstract int getLocal_I(int i);
61 public abstract long getLocal_L(int i);
62 public abstract float getLocal_F(int i);
63 public abstract double getLocal_D(int i);
64 public abstract Object getLocal_A(int i);
65 public abstract void return_I(int v);
66 public abstract void return_L(long v);
67 public abstract void return_F(float v);
68 public abstract void return_D(double v);
69 public abstract void return_A(Object v);
70 public abstract void return_V();
71 public abstract int getReturnVal_I();
72 public abstract long getReturnVal_L();
73 public abstract float getReturnVal_F();
74 public abstract double getReturnVal_D();
75 public abstract Object getReturnVal_A();
76 }
77
78 public abstract static class VMInterface {
79 public abstract Object new_obj(jq_Type t);
80 public abstract Object new_array(jq_Type t, int length);
81 public abstract Object checkcast(Object o, jq_Type t);
82 public abstract boolean instance_of(Object o, jq_Type t);
83 public abstract int arraylength(Object o);
84 public abstract void monitorenter(Object o, MethodInterpreter v);
85 public abstract void monitorexit(Object o);
86 public abstract Object multinewarray(int[] dims, jq_Type t);
87 }
88
89 public static class WrappedException extends RuntimeException {
90 /***
91 * Version ID for serialization.
92 */
93 private static final long serialVersionUID = 3977582476543866419L;
94 Throwable t;
95 WrappedException(Throwable t) { this.t = t; }
96 public String toString() { return "WrappedException: "+t; }
97 }
98
99 class MethodInterpreter extends BytecodeVisitor {
100
101 MethodInterpreter(jq_Method method) {
102 super(method);
103 i_end = -1;
104 String s = method.getDeclaringClass().getName().toString();
105 int i = s.lastIndexOf('.');
106 name = s.substring(i+1)+"/"+method.getName();
107 TRACE = ALWAYS_TRACE;
108 out = System.err;
109 }
110
111 final String name;
112 public String toString() {
113 return name;
114 }
115
116
117 boolean getTraceFlag() { return TRACE; }
118 java.io.PrintStream getTraceOut() { return out; }
119
120 public void forwardTraversal() throws VerifyError, WrappedException {
121 if (this.TRACE) this.out.println(this+": Starting traversal.");
122 for (;;) {
123 i_start = i_end+1;
124 if (i_start >= bcs.length) break;
125 try {
126 super.visitBytecode();
127 } catch (WrappedException ix) {
128 if (this.TRACE) this.out.println(this+": Exception thrown! "+ix.t);
129 handleException(ix.t);
130 } catch (Throwable x) {
131 if (this.TRACE) this.out.println(this+": RuntimeException/Error thrown! "+x);
132 handleException(x);
133 }
134 }
135 if (this.TRACE) this.out.println(this+": Finished traversal.");
136 }
137
138 public void continueForwardTraversal() throws VerifyError, WrappedException, ReflectiveInterpreter.MonitorExit {
139 for (;;) {
140 i_start = i_end+1;
141 if (i_start >= bcs.length) break;
142 try {
143 super.visitBytecode();
144 } catch (ReflectiveInterpreter.MonitorExit x) {
145 throw x;
146 } catch (WrappedException ix) {
147 if (this.TRACE) this.out.println(this+": Exception thrown! "+ix.t);
148 handleException(ix.t);
149 } catch (Throwable x) {
150 if (this.TRACE) this.out.println(this+": RuntimeException/Error thrown! "+x);
151 handleException(x);
152 }
153 }
154 }
155
156 public void visitBytecode() throws WrappedException {
157 try {
158 super.visitBytecode();
159 } catch (WrappedException ix) {
160 if (this.TRACE) this.out.println(this+": Exception thrown! "+ix.t);
161 handleException(ix.t);
162 } catch (Throwable x) {
163 if (this.TRACE) this.out.println(this+": RuntimeException/Error thrown! "+x);
164 handleException(x);
165 }
166 }
167
168 private void handleException(Throwable x) throws WrappedException {
169 jq_Class t = (jq_Class)jq_Reference.getTypeOf(x);
170 t.prepare();
171 jq_TryCatchBC[] tc = method.getExceptionTable();
172 for (int i=0; i<tc.length; ++i) {
173 if (tc[i].catches(i_start, t)) {
174 istate.popAll(); istate.push_A(x);
175 branchTo(tc[i].getHandlerPC());
176 if (this.TRACE) this.out.println(this+": Branching to exception handler "+tc[i]);
177 return;
178 }
179 }
180 if (this.TRACE) this.out.println(this+": Uncaught exception, exiting method.");
181 throw new WrappedException(x);
182 }
183
184 protected void branchTo(int target) {
185 i_end = target-1;
186 }
187
188 public void visitNOP() {
189 super.visitNOP();
190 }
191 public void visitACONST(Object s) {
192 super.visitACONST(s);
193 istate.push_A(s);
194 }
195 public void visitICONST(int c) {
196 super.visitICONST(c);
197 istate.push_I(c);
198 }
199 public void visitLCONST(long c) {
200 super.visitLCONST(c);
201 istate.push_L(c);
202 }
203 public void visitFCONST(float c) {
204 super.visitFCONST(c);
205 istate.push_F(c);
206 }
207 public void visitDCONST(double c) {
208 super.visitDCONST(c);
209 istate.push_D(c);
210 }
211 public void visitILOAD(int i) {
212 super.visitILOAD(i);
213 istate.push_I(istate.getLocal_I(i));
214 }
215 public void visitLLOAD(int i) {
216 super.visitLLOAD(i);
217 istate.push_L(istate.getLocal_L(i));
218 }
219 public void visitFLOAD(int i) {
220 super.visitFLOAD(i);
221 istate.push_F(istate.getLocal_F(i));
222 }
223 public void visitDLOAD(int i) {
224 super.visitDLOAD(i);
225 istate.push_D(istate.getLocal_D(i));
226 }
227 public void visitALOAD(int i) {
228 super.visitALOAD(i);
229 istate.push_A(istate.getLocal_A(i));
230 }
231 public void visitISTORE(int i) {
232 super.visitISTORE(i);
233 istate.setLocal_I(i, istate.pop_I());
234 }
235 public void visitLSTORE(int i) {
236 super.visitLSTORE(i);
237 istate.setLocal_L(i, istate.pop_L());
238 }
239 public void visitFSTORE(int i) {
240 super.visitFSTORE(i);
241 istate.setLocal_F(i, istate.pop_F());
242 }
243 public void visitDSTORE(int i) {
244 super.visitDSTORE(i);
245 istate.setLocal_D(i, istate.pop_D());
246 }
247 public void visitASTORE(int i) {
248 super.visitASTORE(i);
249 istate.setLocal_A(i, istate.pop_A());
250 }
251 public void visitIALOAD() {
252 super.visitIALOAD();
253 int index = istate.pop_I();
254 int[] array = (int[])istate.pop_A();
255 istate.push_I(array[index]);
256 }
257 public void visitLALOAD() {
258 super.visitLALOAD();
259 int index = istate.pop_I();
260 long[] array = (long[])istate.pop_A();
261 istate.push_L(array[index]);
262 }
263 public void visitFALOAD() {
264 super.visitFALOAD();
265 int index = istate.pop_I();
266 float[] array = (float[])istate.pop_A();
267 istate.push_F(array[index]);
268 }
269 public void visitDALOAD() {
270 super.visitDALOAD();
271 int index = istate.pop_I();
272 double[] array = (double[])istate.pop_A();
273 istate.push_D(array[index]);
274 }
275 public void visitAALOAD() {
276 super.visitAALOAD();
277 int index = istate.pop_I();
278 Object[] array = (Object[])istate.pop_A();
279 istate.push_A(array[index]);
280 }
281 public void visitBALOAD() {
282 super.visitBALOAD();
283 int index = istate.pop_I();
284 Object array = (Object)istate.pop_A();
285 int val;
286 try {
287 if (array.getClass() == Class.forName("[Z")) val = ((boolean[])array)[index]?1:0;
288 else val = ((byte[])array)[index];
289 } catch (ClassNotFoundException x) { Assert.UNREACHABLE(); return; }
290 istate.push_I(val);
291 }
292 public void visitCALOAD() {
293 super.visitCALOAD();
294 int index = istate.pop_I();
295 char[] array = (char[])istate.pop_A();
296 istate.push_I(array[index]);
297 }
298 public void visitSALOAD() {
299 super.visitSALOAD();
300 int index = istate.pop_I();
301 short[] array = (short[])istate.pop_A();
302 istate.push_I(array[index]);
303 }
304 public void visitIASTORE() {
305 super.visitIASTORE();
306 int val = istate.pop_I();
307 int index = istate.pop_I();
308 int[] array = (int[])istate.pop_A();
309 array[index] = val;
310 }
311 public void visitLASTORE() {
312 super.visitLASTORE();
313 long val = istate.pop_L();
314 int index = istate.pop_I();
315 long[] array = (long[])istate.pop_A();
316 array[index] = val;
317 }
318 public void visitFASTORE() {
319 super.visitFASTORE();
320 float val = istate.pop_F();
321 int index = istate.pop_I();
322 float[] array = (float[])istate.pop_A();
323 array[index] = val;
324 }
325 public void visitDASTORE() {
326 super.visitDASTORE();
327 double val = istate.pop_D();
328 int index = istate.pop_I();
329 double[] array = (double[])istate.pop_A();
330 array[index] = val;
331 }
332 public void visitAASTORE() {
333 super.visitAASTORE();
334 Object val = istate.pop_A();
335 int index = istate.pop_I();
336 Object[] array = (Object[])istate.pop_A();
337 array[index] = val;
338 }
339 public void visitBASTORE() {
340 super.visitBASTORE();
341 int val = istate.pop_I();
342 int index = istate.pop_I();
343 Object array = (Object)istate.pop_A();
344 try {
345 if (array.getClass() == Class.forName("[Z")) ((boolean[])array)[index] = val!=0;
346 else ((byte[])array)[index] = (byte)val;
347 } catch (ClassNotFoundException x) { Assert.UNREACHABLE(); }
348 }
349 public void visitCASTORE() {
350 super.visitCASTORE();
351 int val = istate.pop_I();
352 int index = istate.pop_I();
353 char[] array = (char[])istate.pop_A();
354 array[index] = (char)val;
355 }
356 public void visitSASTORE() {
357 super.visitSASTORE();
358 int val = istate.pop_I();
359 int index = istate.pop_I();
360 short[] array = (short[])istate.pop_A();
361 array[index] = (short)val;
362 }
363 public void visitPOP() {
364 super.visitPOP();
365 istate.pop();
366 }
367 public void visitPOP2() {
368 super.visitPOP2();
369 istate.pop();
370 istate.pop();
371 }
372 public void visitDUP() {
373 super.visitDUP();
374 Object o = istate.pop();
375 istate.push(o);
376 istate.push(o);
377 }
378 public void visitDUP_x1() {
379 super.visitDUP_x1();
380 Object o1 = istate.pop();
381 Object o2 = istate.pop();
382 istate.push(o1);
383 istate.push(o2);
384 istate.push(o1);
385 }
386 public void visitDUP_x2() {
387 super.visitDUP_x2();
388 Object o1 = istate.pop();
389 Object o2 = istate.pop();
390 Object o3 = istate.pop();
391 istate.push(o1);
392 istate.push(o3);
393 istate.push(o2);
394 istate.push(o1);
395 }
396 public void visitDUP2() {
397 super.visitDUP2();
398 Object o1 = istate.pop();
399 Object o2 = istate.pop();
400 istate.push(o2);
401 istate.push(o1);
402 istate.push(o2);
403 istate.push(o1);
404 }
405 public void visitDUP2_x1() {
406 super.visitDUP2_x1();
407 Object o1 = istate.pop();
408 Object o2 = istate.pop();
409 Object o3 = istate.pop();
410 istate.push(o2);
411 istate.push(o1);
412 istate.push(o3);
413 istate.push(o2);
414 istate.push(o1);
415 }
416 public void visitDUP2_x2() {
417 super.visitDUP2_x2();
418 Object o1 = istate.pop();
419 Object o2 = istate.pop();
420 Object o3 = istate.pop();
421 Object o4 = istate.pop();
422 istate.push(o2);
423 istate.push(o1);
424 istate.push(o4);
425 istate.push(o3);
426 istate.push(o2);
427 istate.push(o1);
428 }
429 public void visitSWAP() {
430 super.visitSWAP();
431 Object o1 = istate.pop();
432 Object o2 = istate.pop();
433 istate.push(o1);
434 istate.push(o2);
435 }
436 public void visitIBINOP(byte op) {
437 super.visitIBINOP(op);
438 int v1 = istate.pop_I();
439 int v2 = istate.pop_I();
440 switch(op) {
441 case BINOP_ADD:
442 istate.push_I(v2+v1);
443 break;
444 case BINOP_SUB:
445 istate.push_I(v2-v1);
446 break;
447 case BINOP_MUL:
448 istate.push_I(v2*v1);
449 break;
450 case BINOP_DIV:
451 istate.push_I(v2/v1);
452 break;
453 case BINOP_REM:
454 istate.push_I(v2%v1);
455 break;
456 case BINOP_AND:
457 istate.push_I(v2&v1);
458 break;
459 case BINOP_OR:
460 istate.push_I(v2|v1);
461 break;
462 case BINOP_XOR:
463 istate.push_I(v2^v1);
464 break;
465 default:
466 Assert.UNREACHABLE();
467 }
468 }
469 public void visitLBINOP(byte op) {
470 super.visitLBINOP(op);
471 long v1 = istate.pop_L();
472 long v2 = istate.pop_L();
473 switch(op) {
474 case BINOP_ADD:
475 istate.push_L(v2+v1);
476 break;
477 case BINOP_SUB:
478 istate.push_L(v2-v1);
479 break;
480 case BINOP_MUL:
481 istate.push_L(v2*v1);
482 break;
483 case BINOP_DIV:
484 istate.push_L(v2/v1);
485 break;
486 case BINOP_REM:
487 istate.push_L(v2%v1);
488 break;
489 case BINOP_AND:
490 istate.push_L(v2&v1);
491 break;
492 case BINOP_OR:
493 istate.push_L(v2|v1);
494 break;
495 case BINOP_XOR:
496 istate.push_L(v2^v1);
497 break;
498 default:
499 Assert.UNREACHABLE();
500 }
501 }
502 public void visitFBINOP(byte op) {
503 super.visitFBINOP(op);
504 float v1 = istate.pop_F();
505 float v2 = istate.pop_F();
506 switch(op) {
507 case BINOP_ADD:
508 istate.push_F(v2+v1);
509 break;
510 case BINOP_SUB:
511 istate.push_F(v2-v1);
512 break;
513 case BINOP_MUL:
514 istate.push_F(v2*v1);
515 break;
516 case BINOP_DIV:
517 istate.push_F(v2/v1);
518 break;
519 case BINOP_REM:
520 istate.push_F(v2%v1);
521 break;
522 default:
523 Assert.UNREACHABLE();
524 }
525 }
526 public void visitDBINOP(byte op) {
527 super.visitDBINOP(op);
528 double v1 = istate.pop_D();
529 double v2 = istate.pop_D();
530 switch(op) {
531 case BINOP_ADD:
532 istate.push_D(v2+v1);
533 break;
534 case BINOP_SUB:
535 istate.push_D(v2-v1);
536 break;
537 case BINOP_MUL:
538 istate.push_D(v2*v1);
539 break;
540 case BINOP_DIV:
541 istate.push_D(v2/v1);
542 break;
543 case BINOP_REM:
544 istate.push_D(v2%v1);
545 break;
546 default:
547 Assert.UNREACHABLE();
548 }
549 }
550 public void visitIUNOP(byte op) {
551 super.visitIUNOP(op);
552 Assert._assert(op == UNOP_NEG);
553 istate.push_I(-istate.pop_I());
554 }
555 public void visitLUNOP(byte op) {
556 super.visitLUNOP(op);
557 Assert._assert(op == UNOP_NEG);
558 istate.push_L(-istate.pop_L());
559 }
560 public void visitFUNOP(byte op) {
561 super.visitFUNOP(op);
562 Assert._assert(op == UNOP_NEG);
563 istate.push_F(-istate.pop_F());
564 }
565 public void visitDUNOP(byte op) {
566 super.visitDUNOP(op);
567 Assert._assert(op == UNOP_NEG);
568 istate.push_D(-istate.pop_D());
569 }
570 public void visitISHIFT(byte op) {
571 super.visitISHIFT(op);
572 int v1 = istate.pop_I();
573 int v2 = istate.pop_I();
574 switch(op) {
575 case SHIFT_LEFT:
576 istate.push_I(v2 << v1);
577 break;
578 case SHIFT_RIGHT:
579 istate.push_I(v2 >> v1);
580 break;
581 case SHIFT_URIGHT:
582 istate.push_I(v2 >>> v1);
583 break;
584 default:
585 Assert.UNREACHABLE();
586 }
587 }
588 public void visitLSHIFT(byte op) {
589 super.visitLSHIFT(op);
590 int v1 = istate.pop_I();
591 long v2 = istate.pop_L();
592 switch(op) {
593 case SHIFT_LEFT:
594 istate.push_L(v2 << v1);
595 break;
596 case SHIFT_RIGHT:
597 istate.push_L(v2 >> v1);
598 break;
599 case SHIFT_URIGHT:
600 istate.push_L(v2 >>> v1);
601 break;
602 default:
603 Assert.UNREACHABLE();
604 }
605 }
606 public void visitIINC(int i, int v) {
607 super.visitIINC(i, v);
608 istate.setLocal_I(i, istate.getLocal_I(i)+v);
609 }
610 public void visitI2L() {
611 super.visitI2L();
612 istate.push_L((long)istate.pop_I());
613 }
614 public void visitI2F() {
615 super.visitI2F();
616 istate.push_F((float)istate.pop_I());
617 }
618 public void visitI2D() {
619 super.visitI2D();
620 istate.push_D((double)istate.pop_I());
621 }
622 public void visitL2I() {
623 super.visitL2I();
624 istate.push_I((int)istate.pop_L());
625 }
626 public void visitL2F() {
627 super.visitL2F();
628 istate.push_F((float)istate.pop_L());
629 }
630 public void visitL2D() {
631 super.visitL2D();
632 istate.push_D((double)istate.pop_L());
633 }
634 public void visitF2I() {
635 super.visitF2I();
636 istate.push_I((int)istate.pop_F());
637 }
638 public void visitF2L() {
639 super.visitF2L();
640 istate.push_L((long)istate.pop_F());
641 }
642 public void visitF2D() {
643 super.visitF2D();
644 istate.push_D((double)istate.pop_F());
645 }
646 public void visitD2I() {
647 super.visitD2I();
648 istate.push_I((int)istate.pop_D());
649 }
650 public void visitD2L() {
651 super.visitD2L();
652 istate.push_L((long)istate.pop_D());
653 }
654 public void visitD2F() {
655 super.visitD2F();
656 istate.push_F((float)istate.pop_D());
657 }
658 public void visitI2B() {
659 super.visitI2B();
660 istate.push_I((byte)istate.pop_I());
661 }
662 public void visitI2C() {
663 super.visitI2C();
664 istate.push_I((char)istate.pop_I());
665 }
666 public void visitI2S() {
667 super.visitI2S();
668 istate.push_I((short)istate.pop_I());
669 }
670 public void visitLCMP2() {
671 super.visitLCMP2();
672 long v1 = istate.pop_L();
673 long v2 = istate.pop_L();
674 istate.push_I((v2>v1)?1:((v2==v1)?0:-1));
675 }
676 public void visitFCMP2(byte op) {
677 super.visitFCMP2(op);
678 float v1 = istate.pop_F();
679 float v2 = istate.pop_F();
680 int val;
681 if (op == CMP_L)
682 val = ((v2>v1)?1:((v2==v1)?0:-1));
683 else
684 val = ((v2<v1)?-1:((v2==v1)?0:1));
685 istate.push_I(val);
686 }
687 public void visitDCMP2(byte op) {
688 super.visitDCMP2(op);
689 double v1 = istate.pop_D();
690 double v2 = istate.pop_D();
691 int val;
692 if (op == CMP_L)
693 val = ((v2>v1)?1:((v2==v1)?0:-1));
694 else
695 val = ((v2<v1)?-1:((v2==v1)?0:1));
696 istate.push_I(val);
697 }
698 public void visitIF(byte op, int target) {
699 super.visitIF(op, target);
700 int v = istate.pop_I();
701 switch(op) {
702 case CMP_EQ: if (v==0) branchTo(target); break;
703 case CMP_NE: if (v!=0) branchTo(target); break;
704 case CMP_LT: if (v<0) branchTo(target); break;
705 case CMP_GE: if (v>=0) branchTo(target); break;
706 case CMP_LE: if (v<=0) branchTo(target); break;
707 case CMP_GT: if (v>0) branchTo(target); break;
708 default: Assert.UNREACHABLE();
709 }
710 }
711 public void visitIFREF(byte op, int target) {
712 super.visitIFREF(op, target);
713 Object v = istate.pop_A();
714 switch(op) {
715 case CMP_EQ: if (v==null) branchTo(target); break;
716 case CMP_NE: if (v!=null) branchTo(target); break;
717 default: Assert.UNREACHABLE();
718 }
719 }
720 public void visitIFCMP(byte op, int target) {
721 super.visitIFCMP(op, target);
722 int v1 = istate.pop_I();
723 int v2 = istate.pop_I();
724 switch(op) {
725 case CMP_EQ: if (v2==v1) branchTo(target); break;
726 case CMP_NE: if (v2!=v1) branchTo(target); break;
727 case CMP_LT: if (v2<v1) branchTo(target); break;
728 case CMP_GE: if (v2>=v1) branchTo(target); break;
729 case CMP_LE: if (v2<=v1) branchTo(target); break;
730 case CMP_GT: if (v2>v1) branchTo(target); break;
731 default: Assert.UNREACHABLE();
732 }
733 }
734 public void visitIFREFCMP(byte op, int target) {
735 super.visitIFREFCMP(op, target);
736 Object v1 = istate.pop_A();
737 Object v2 = istate.pop_A();
738 switch(op) {
739 case CMP_EQ: if (v2==v1) branchTo(target); break;
740 case CMP_NE: if (v2!=v1) branchTo(target); break;
741 default: Assert.UNREACHABLE();
742 }
743 }
744 public void visitGOTO(int target) {
745 super.visitGOTO(target);
746 branchTo(target);
747 }
748 public void visitJSR(int target) {
749 super.visitJSR(target);
750 istate.push_I(i_end+1);
751 branchTo(target);
752 }
753 public void visitRET(int i) {
754 super.visitRET(i);
755 branchTo(istate.getLocal_I(i));
756 }
757 public void visitTABLESWITCH(int default_target, int low, int high, int[] targets) {
758 super.visitTABLESWITCH(default_target, low, high, targets);
759 int v = istate.pop_I();
760 if ((v < low) || (v > high)) branchTo(default_target);
761 else branchTo(targets[v-low]);
762 }
763 public void visitLOOKUPSWITCH(int default_target, int[] values, int[] targets) {
764 super.visitLOOKUPSWITCH(default_target, values, targets);
765 int v = istate.pop_I();
766 for (int i=0; i<values.length; ++i) {
767 if (v == values[i]) {
768 branchTo(targets[i]);
769 return;
770 }
771 }
772 branchTo(default_target);
773 }
774 public void visitIRETURN() {
775 super.visitIRETURN();
776 istate.return_I(istate.pop_I());
777 i_end = bcs.length;
778 }
779 public void visitLRETURN() {
780 super.visitLRETURN();
781 istate.return_L(istate.pop_L());
782 i_end = bcs.length;
783 }
784 public void visitFRETURN() {
785 super.visitFRETURN();
786 istate.return_F(istate.pop_F());
787 i_end = bcs.length;
788 }
789 public void visitDRETURN() {
790 super.visitDRETURN();
791 istate.return_D(istate.pop_D());
792 i_end = bcs.length;
793 }
794 public void visitARETURN() {
795 super.visitARETURN();
796 istate.return_A(istate.pop_A());
797 i_end = bcs.length;
798 }
799 public void visitVRETURN() {
800 super.visitVRETURN();
801 istate.return_V();
802 i_end = bcs.length;
803 }
804 public void visitIGETSTATIC(jq_StaticField f) {
805 super.visitIGETSTATIC(f);
806 f = tryResolve(f);
807 f.getDeclaringClass().cls_initialize();
808 istate.push_I(Reflection.getstatic_I(f));
809 }
810 public void visitLGETSTATIC(jq_StaticField f) {
811 super.visitLGETSTATIC(f);
812 f = tryResolve(f);
813 f.getDeclaringClass().cls_initialize();
814 istate.push_L(Reflection.getstatic_L(f));
815 }
816 public void visitFGETSTATIC(jq_StaticField f) {
817 super.visitFGETSTATIC(f);
818 f = tryResolve(f);
819 f.getDeclaringClass().cls_initialize();
820 istate.push_F(Reflection.getstatic_F(f));
821 }
822 public void visitDGETSTATIC(jq_StaticField f) {
823 super.visitDGETSTATIC(f);
824 f = tryResolve(f);
825 f.getDeclaringClass().cls_initialize();
826 istate.push_D(Reflection.getstatic_D(f));
827 }
828 public void visitAGETSTATIC(jq_StaticField f) {
829 super.visitAGETSTATIC(f);
830 f = tryResolve(f);
831 f.getDeclaringClass().cls_initialize();
832 istate.push_A(Reflection.getstatic_A(f));
833 }
834 public void visitZGETSTATIC(jq_StaticField f) {
835 super.visitZGETSTATIC(f);
836 f = tryResolve(f);
837 f.getDeclaringClass().cls_initialize();
838 istate.push_I(Reflection.getstatic_Z(f)?1:0);
839 }
840 public void visitBGETSTATIC(jq_StaticField f) {
841 super.visitBGETSTATIC(f);
842 f = tryResolve(f);
843 f.getDeclaringClass().cls_initialize();
844 istate.push_I(Reflection.getstatic_B(f));
845 }
846 public void visitCGETSTATIC(jq_StaticField f) {
847 super.visitCGETSTATIC(f);
848 f = tryResolve(f);
849 f.getDeclaringClass().cls_initialize();
850 istate.push_I(Reflection.getstatic_C(f));
851 }
852 public void visitSGETSTATIC(jq_StaticField f) {
853 super.visitSGETSTATIC(f);
854 f = tryResolve(f);
855 f.getDeclaringClass().cls_initialize();
856 istate.push_I(Reflection.getstatic_S(f));
857 }
858 public void visitIPUTSTATIC(jq_StaticField f) {
859 super.visitIPUTSTATIC(f);
860 f = tryResolve(f);
861 f.getDeclaringClass().cls_initialize();
862 Reflection.putstatic_I(f, istate.pop_I());
863 }
864 public void visitLPUTSTATIC(jq_StaticField f) {
865 super.visitLPUTSTATIC(f);
866 f = tryResolve(f);
867 f.getDeclaringClass().cls_initialize();
868 Reflection.putstatic_L(f, istate.pop_L());
869 }
870 public void visitFPUTSTATIC(jq_StaticField f) {
871 super.visitFPUTSTATIC(f);
872 f = tryResolve(f);
873 f.getDeclaringClass().cls_initialize();
874 Reflection.putstatic_F(f, istate.pop_F());
875 }
876 public void visitDPUTSTATIC(jq_StaticField f) {
877 super.visitDPUTSTATIC(f);
878 f = tryResolve(f);
879 f.getDeclaringClass().cls_initialize();
880 Reflection.putstatic_D(f, istate.pop_D());
881 }
882 public void visitAPUTSTATIC(jq_StaticField f) {
883 super.visitAPUTSTATIC(f);
884 f = tryResolve(f);
885 f.getDeclaringClass().cls_initialize();
886 Reflection.putstatic_A(f, istate.pop_A());
887 }
888 public void visitZPUTSTATIC(jq_StaticField f) {
889 super.visitZPUTSTATIC(f);
890 f = tryResolve(f);
891 f.getDeclaringClass().cls_initialize();
892 Reflection.putstatic_Z(f, istate.pop_I()!=0);
893 }
894 public void visitBPUTSTATIC(jq_StaticField f) {
895 super.visitBPUTSTATIC(f);
896 f = tryResolve(f);
897 f.getDeclaringClass().cls_initialize();
898 Reflection.putstatic_B(f, (byte)istate.pop_I());
899 }
900 public void visitCPUTSTATIC(jq_StaticField f) {
901 super.visitCPUTSTATIC(f);
902 f = tryResolve(f);
903 f.getDeclaringClass().cls_initialize();
904 Reflection.putstatic_C(f, (char)istate.pop_I());
905 }
906 public void visitSPUTSTATIC(jq_StaticField f) {
907 super.visitSPUTSTATIC(f);
908 f = tryResolve(f);
909 f.getDeclaringClass().cls_initialize();
910 Reflection.putstatic_S(f, (short)istate.pop_I());
911 }
912 public void visitIGETFIELD(jq_InstanceField f) {
913 super.visitIGETFIELD(f);
914 f = tryResolve(f);
915 istate.push_I(Reflection.getfield_I(istate.pop_A(), f));
916 }
917 public void visitLGETFIELD(jq_InstanceField f) {
918 super.visitLGETFIELD(f);
919 f = tryResolve(f);
920 istate.push_L(Reflection.getfield_L(istate.pop_A(), f));
921 }
922 public void visitFGETFIELD(jq_InstanceField f) {
923 super.visitFGETFIELD(f);
924 f = tryResolve(f);
925 istate.push_F(Reflection.getfield_F(istate.pop_A(), f));
926 }
927 public void visitDGETFIELD(jq_InstanceField f) {
928 super.visitDGETFIELD(f);
929 f = tryResolve(f);
930 istate.push_D(Reflection.getfield_D(istate.pop_A(), f));
931 }
932 public void visitAGETFIELD(jq_InstanceField f) {
933 super.visitAGETFIELD(f);
934 f = tryResolve(f);
935 istate.push_A(Reflection.getfield_A(istate.pop_A(), f));
936 }
937 public void visitBGETFIELD(jq_InstanceField f) {
938 super.visitBGETFIELD(f);
939 f = tryResolve(f);
940 istate.push_I(Reflection.getfield_B(istate.pop_A(), f));
941 }
942 public void visitCGETFIELD(jq_InstanceField f) {
943 super.visitCGETFIELD(f);
944 f = tryResolve(f);
945 istate.push_I(Reflection.getfield_C(istate.pop_A(), f));
946 }
947 public void visitSGETFIELD(jq_InstanceField f) {
948 super.visitSGETFIELD(f);
949 f = tryResolve(f);
950 istate.push_I(Reflection.getfield_S(istate.pop_A(), f));
951 }
952 public void visitZGETFIELD(jq_InstanceField f) {
953 super.visitZGETFIELD(f);
954 f = tryResolve(f);
955 istate.push_I(Reflection.getfield_Z(istate.pop_A(), f)?1:0);
956 }
957 public void visitIPUTFIELD(jq_InstanceField f) {
958 super.visitIPUTFIELD(f);
959 f = tryResolve(f);
960 int v = istate.pop_I();
961 Reflection.putfield_I(istate.pop_A(), f, v);
962 }
963 public void visitLPUTFIELD(jq_InstanceField f) {
964 super.visitLPUTFIELD(f);
965 f = tryResolve(f);
966 long v = istate.pop_L();
967 Reflection.putfield_L(istate.pop_A(), f, v);
968 }
969 public void visitFPUTFIELD(jq_InstanceField f) {
970 super.visitFPUTFIELD(f);
971 f = tryResolve(f);
972 float v = istate.pop_F();
973 Reflection.putfield_F(istate.pop_A(), f, v);
974 }
975 public void visitDPUTFIELD(jq_InstanceField f) {
976 super.visitDPUTFIELD(f);
977 f = tryResolve(f);
978 double v = istate.pop_D();
979 Reflection.putfield_D(istate.pop_A(), f, v);
980 }
981 public void visitAPUTFIELD(jq_InstanceField f) {
982 super.visitAPUTFIELD(f);
983 f = tryResolve(f);
984 Object v = istate.pop_A();
985 Reflection.putfield_A(istate.pop_A(), f, v);
986 }
987 public void visitBPUTFIELD(jq_InstanceField f) {
988 super.visitBPUTFIELD(f);
989 f = tryResolve(f);
990 byte v = (byte)istate.pop_I();
991 Reflection.putfield_B(istate.pop_A(), f, v);
992 }
993 public void visitCPUTFIELD(jq_InstanceField f) {
994 super.visitCPUTFIELD(f);
995 f = tryResolve(f);
996 char v = (char)istate.pop_I();
997 Reflection.putfield_C(istate.pop_A(), f, v);
998 }
999 public void visitSPUTFIELD(jq_InstanceField f) {
1000 super.visitSPUTFIELD(f);
1001 f = tryResolve(f);
1002 short v = (short)istate.pop_I();
1003 Reflection.putfield_S(istate.pop_A(), f, v);
1004 }
1005 public void visitZPUTFIELD(jq_InstanceField f) {
1006 super.visitZPUTFIELD(f);
1007 f = tryResolve(f);
1008 boolean v = istate.pop_I()!=0;
1009 Reflection.putfield_Z(istate.pop_A(), f, v);
1010 }
1011 protected Object INVOKEhelper(byte op, jq_Method f) {
1012 f = (jq_Method) tryResolve(f);
1013 jq_Class k = f.getDeclaringClass();
1014 k.cls_initialize();
1015 jq_Class _class = (jq_Class) PrimordialClassLoader.loader.getOrCreateBSType("Ljoeq/Runtime/Unsafe;");
1016 if (k == _class || k.isAddressType()) {
1017 try {
1018
1019 return invokeUnsafeMethod(f);
1020 } catch (Throwable t) {
1021 if (this.TRACE) this.out.println(this+": "+f+" threw "+t);
1022 throw new WrappedException(t);
1023 }
1024 }
1025 if (op == INVOKE_SPECIAL) {
1026 f = jq_Class.getInvokespecialTarget(clazz, (jq_InstanceMethod)f);
1027 } else if (op != INVOKE_STATIC) {
1028 Object o = istate.peek_A(f.getParamWords()-1);
1029 jq_Reference t = jq_Reference.getTypeOf(o);
1030 t.cls_initialize();
1031 if (op == INVOKE_INTERFACE) {
1032 if (!t.implementsInterface(f.getDeclaringClass()))
1033 throw new IncompatibleClassChangeError();
1034 if (t.isArrayType()) t = PrimordialClassLoader.getJavaLangObject();
1035 } else {
1036 Assert._assert(op == INVOKE_VIRTUAL);
1037 }
1038 jq_Method f2 = f;
1039 f = t.getVirtualMethod(f.getNameAndDesc());
1040 if (this.TRACE) this.out.println(this+": virtual method target "+f);
1041 if (f == null)
1042 throw new AbstractMethodError("no such method "+f2.toString()+" in type "+t);
1043 if (f.isAbstract())
1044 throw new AbstractMethodError("method "+f2.toString()+" on type "+t+" is abstract");
1045 } else {
1046
1047 }
1048 try {
1049 return invokeMethod(f);
1050 } catch (Throwable t) {
1051 if (this.TRACE) this.out.println(this+": "+f+" threw "+t);
1052 throw new WrappedException(t);
1053 }
1054 }
1055 public void visitIINVOKE(byte op, jq_Method f) {
1056 super.visitIINVOKE(op, f);
1057 istate.push_I(((Integer)INVOKEhelper(op, f)).intValue());
1058 }
1059 public void visitLINVOKE(byte op, jq_Method f) {
1060 super.visitLINVOKE(op, f);
1061 istate.push_L(((Long)INVOKEhelper(op, f)).longValue());
1062 }
1063 public void visitFINVOKE(byte op, jq_Method f) {
1064 super.visitFINVOKE(op, f);
1065 istate.push_F(((Float)INVOKEhelper(op, f)).floatValue());
1066 }
1067 public void visitDINVOKE(byte op, jq_Method f) {
1068 super.visitDINVOKE(op, f);
1069 istate.push_D(((Double)INVOKEhelper(op, f)).doubleValue());
1070 }
1071 public void visitAINVOKE(byte op, jq_Method f) {
1072 super.visitAINVOKE(op, f);
1073 istate.push_A(INVOKEhelper(op, f));
1074 }
1075 public void visitVINVOKE(byte op, jq_Method f) {
1076 super.visitVINVOKE(op, f);
1077 INVOKEhelper(op, f);
1078 }
1079 public void visitNEW(jq_Type f) {
1080 super.visitNEW(f);
1081 istate.push_A(vm.new_obj(f));
1082 }
1083 public void visitNEWARRAY(jq_Array f) {
1084 super.visitNEWARRAY(f);
1085 istate.push_A(vm.new_array(f, istate.pop_I()));
1086 }
1087 public void visitCHECKCAST(jq_Type f) {
1088 super.visitCHECKCAST(f);
1089 istate.push_A(vm.checkcast(istate.pop_A(), f));
1090 }
1091 public void visitINSTANCEOF(jq_Type f) {
1092 super.visitINSTANCEOF(f);
1093 istate.push_I(vm.instance_of(istate.pop_A(), f)?1:0);
1094 }
1095 public void visitARRAYLENGTH() {
1096 super.visitARRAYLENGTH();
1097 istate.push_I(vm.arraylength(istate.pop_A()));
1098 }
1099 public void visitATHROW() {
1100 super.visitATHROW();
1101 throw new WrappedException((Throwable)istate.pop_A());
1102 }
1103 public void visitMONITOR(byte op) {
1104 super.visitMONITOR(op);
1105 Object v = istate.pop_A();
1106 if (op == MONITOR_ENTER) vm.monitorenter(v, this);
1107 else vm.monitorexit(v);
1108 }
1109 public void visitMULTINEWARRAY(jq_Type f, char dim) {
1110 super.visitMULTINEWARRAY(f, dim);
1111 int[] dims = new int[dim];
1112
1113 for (int i=0; i<dim; ++i) dims[dim-i-1] = istate.pop_I();
1114 istate.push_A(vm.multinewarray(dims, f));
1115 }
1116 }
1117
1118 }