View Javadoc

1   // BytecodeInterpreter.java, created Fri Aug 16 16:04:04 2002 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
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   * @author  John Whaley <jwhaley@alum.mit.edu>
22   * @version $Id: BytecodeInterpreter.java 2250 2005-04-29 07:41:11Z joewhaley $
23   */
24  public abstract class BytecodeInterpreter {
25  
26      public static /*final*/ boolean ALWAYS_TRACE = System.getProperty("interpreter.trace") != null;
27      
28      /*** Creates new Interpreter */
29      public BytecodeInterpreter(VMInterface vm, State istate) {
30          this.vm = vm; this.istate = istate;
31      }
32  
33      // create an Interpreter.State and call invokeMethod(m, istate)
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         // Workaround for javac bug -> cannot access protected members of inner classes.
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                     // redirect call
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                 // static call
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             //for (int i=0; i<dim; ++i) f = ((jq_Array)f).getElementType();
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 }