Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: Interpreter/BytecodeInterpreter.java


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