View Javadoc

1   // DirectInterpreter.java, created Mon Feb  5 23:23:21 2001 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 java.util.Arrays;
7   import java.util.HashSet;
8   import java.util.Iterator;
9   import java.util.Set;
10  import joeq.Allocator.ObjectLayout;
11  import joeq.Class.PrimordialClassLoader;
12  import joeq.Class.jq_Array;
13  import joeq.Class.jq_Class;
14  import joeq.Class.jq_InstanceField;
15  import joeq.Class.jq_Method;
16  import joeq.Class.jq_Primitive;
17  import joeq.Class.jq_Reference;
18  import joeq.Class.jq_StaticField;
19  import joeq.Class.jq_StaticMethod;
20  import joeq.Class.jq_Type;
21  import joeq.Main.TraceFlags;
22  import joeq.Main.jq;
23  import joeq.Memory.Address;
24  import joeq.Memory.HeapAddress;
25  import joeq.Memory.StackAddress;
26  import joeq.Runtime.Monitor;
27  import joeq.Runtime.Reflection;
28  import joeq.Runtime.SystemInterface;
29  import joeq.Runtime.TypeCheck;
30  import joeq.Runtime.Unsafe;
31  import joeq.UTF.Utf8;
32  import jwutil.collections.Filter;
33  import jwutil.util.Assert;
34  import jwutil.util.Convert;
35  
36  /***
37   * DirectInterpreter
38   * 
39   * @author  John Whaley <jwhaley@alum.mit.edu>
40   * @version $Id: DirectInterpreter.java 1985 2004-10-08 08:43:02Z joewhaley $
41   */
42  public class DirectInterpreter extends BytecodeInterpreter {
43  
44      /*** Creates new DirectInterpreter */
45      public DirectInterpreter(State initialState) {
46          super(new DirectVMInterface(), initialState);
47      }
48  
49      public static final Set bad_classes;
50      public static final Set bad_methods;
51      public static final Filter interpret_filter;
52      static {
53          bad_classes = new HashSet();
54          bad_classes.add(SystemInterface._class);
55          bad_classes.add(Reflection._class);
56          bad_classes.add(PrimordialClassLoader.loader.getOrCreateBSType("Ljoeq/Runtime/ExceptionDeliverer;"));
57          bad_methods = new HashSet();
58          bad_methods.add(joeq.Runtime.Arrays._multinewarray);
59          interpret_filter = new Filter() {
60              public boolean isElement(Object o) {
61                  jq_Method m = (jq_Method)o;
62                  if (m.getBytecode() == null) return false;
63                  if (bad_classes.contains(m.getDeclaringClass())) return false;
64                  if (bad_methods.contains(m)) return false;
65                  return true;
66              }
67          };
68      }
69  
70      public Object invokeMethod(jq_Method m) throws Throwable {
71          //Debug.writeln("Enter: "+m);
72          jq_Class k = m.getDeclaringClass();
73          k.cls_initialize();
74          if (!interpret_filter.isElement(m)) {
75              //Debug.writeln("Native call: "+m);
76              Object result = invokeMethod(m, null);
77              //Debug.writeln("Result: "+result);
78              return result;
79          }
80          int localsize = m.getMaxLocals() * HeapAddress.size();
81          int stacksize = m.getMaxStack() * HeapAddress.size();
82          StackAddress newframe = StackAddress.alloca(localsize+stacksize);
83          DirectState callee = new DirectState((StackAddress) newframe.offset(localsize+stacksize), (StackAddress) newframe.offset(stacksize), m.getMaxLocals());
84          Object result = this.invokeMethod(m, callee);
85          //Debug.writeln("Leave: "+m);
86          return result;
87      }
88      
89      // callee == null -> call compiled version
90      public Object invokeMethod(jq_Method m, State callee) throws Throwable {
91          //Runtime.SystemInterface.debugwriteln("Invoking method "+m);
92          jq_Class k = m.getDeclaringClass();
93          Assert._assert(k.isClsInitialized());
94          Assert._assert(m.getBytecode() != null);
95          jq_Type[] paramTypes = m.getParamTypes();
96          Object[] params = new Object[paramTypes.length];
97          for (int i=paramTypes.length-1; i>=0; --i) {
98              jq_Type t = paramTypes[i];
99              if (t.isPrimitiveType()) {
100                 if (t == jq_Primitive.LONG) {
101                     params[i] = new Long(istate.pop_L());
102                 } else if (t == jq_Primitive.FLOAT) {
103                     params[i] = new Float(istate.pop_F());
104                 } else if (t == jq_Primitive.DOUBLE) {
105                     params[i] = new Double(istate.pop_D());
106                 } else {
107                     params[i] = new Integer(istate.pop_I());
108                 }
109             } else {
110                 params[i] = istate.pop_A();
111             }
112             //System.out.println("Param "+i+": "+params[i]);
113         }
114         for (int i=0, j=0; i<paramTypes.length; ++i, ++j) {
115             jq_Type t = paramTypes[i];
116             if (t.isPrimitiveType()) {
117                 if (t == jq_Primitive.LONG) {
118                     long v = ((Long)params[i]).longValue();
119                     if (callee == null) {
120                         Unsafe.pushArg((int)(v>>32)); // hi
121                         Unsafe.pushArg((int)v);       // lo
122                     } else callee.setLocal_L(j, v);
123                     ++j;
124                 } else if (t == jq_Primitive.FLOAT) {
125                     float v = ((Float)params[i]).floatValue();
126                     if (callee == null) {
127                         Unsafe.pushArg(Float.floatToRawIntBits(v));
128                     } else callee.setLocal_F(j, v);
129                 } else if (t == jq_Primitive.DOUBLE) {
130                     long v = Double.doubleToRawLongBits(((Double)params[i]).doubleValue());
131                     if (callee == null) {
132                         Unsafe.pushArg((int)(v>>32)); // hi
133                         Unsafe.pushArg((int)v);       // lo
134                     } else callee.setLocal_D(j, Double.longBitsToDouble(v));
135                     ++j;
136                 } else {
137                     int v = ((Integer)params[i]).intValue();
138                     if (callee == null) {
139                         Unsafe.pushArg(v);
140                     } else callee.setLocal_I(j, v);
141                 }
142             } else {
143                 Object v = params[i];
144                 if (callee == null) {
145                     Unsafe.pushArgA(HeapAddress.addressOf(v));
146                 } else callee.setLocal_A(j, v);
147             }
148         }
149         if (callee == null) {
150             jq_Type returnType = m.getReturnType();
151             if (returnType.isReferenceType()) {
152                 Address result = Unsafe.invokeA(m.getDefaultCompiledVersion().getEntrypoint());
153                 if (returnType.isAddressType()) return result;
154                 return ((HeapAddress) result).asObject();
155             }
156             long result = Unsafe.invoke(m.getDefaultCompiledVersion().getEntrypoint());
157             if (returnType == jq_Primitive.VOID)
158                 return null;
159             else if (returnType == jq_Primitive.LONG)
160                 return new Long(result);
161             else if (returnType == jq_Primitive.FLOAT)
162                 return new Float(Float.intBitsToFloat((int)(result)));
163             else if (returnType == jq_Primitive.DOUBLE)
164                 return new Double(Double.longBitsToDouble(result));
165             else
166                 return new Integer((int)(result));
167         } else {
168             State oldState = this.istate;
169             this.istate = callee;
170             MethodInterpreter mi = new MethodInterpreter(m);
171             Object synchobj = null;
172             try {
173                 if (m.isSynchronized()) {
174                     if (!m.isStatic()) {
175                         if (mi.getTraceFlag()) mi.getTraceOut().println("synchronized instance method, locking 'this' object");
176                         vm.monitorenter(synchobj = istate.getLocal_A(0), mi);
177                     } else {
178                         if (mi.getTraceFlag()) mi.getTraceOut().println("synchronized static method, locking class object");
179                         vm.monitorenter(synchobj = Reflection.getJDKType(m.getDeclaringClass()), mi);
180                     }
181                 }
182                 mi.forwardTraversal();
183                 this.istate = oldState;
184                 if (m.isSynchronized()) {
185                     if (mi.getTraceFlag()) mi.getTraceOut().println("exiting synchronized method, unlocking object");
186                     vm.monitorexit(synchobj);
187                 }
188                 jq_Type returnType = m.getReturnType();
189                 Object retval;
190                 if (returnType.isReferenceType()) {
191                     retval = callee.getReturnVal_A();
192                 } else if (returnType == jq_Primitive.VOID) {
193                     retval = null;
194                 } else if (returnType == jq_Primitive.LONG) {
195                     retval = new Long(callee.getReturnVal_L());
196                 } else if (returnType == jq_Primitive.FLOAT) {
197                     retval = new Float(callee.getReturnVal_F());
198                 } else if (returnType == jq_Primitive.DOUBLE) {
199                     retval = new Double(callee.getReturnVal_D());
200                 } else {
201                     retval = new Integer(callee.getReturnVal_I());
202                 }
203                 if (mi.getTraceFlag())
204                     mi.getTraceOut().println("Return value: "+retval);
205                 return retval;
206             } catch (WrappedException ix) {
207                 this.istate = oldState;
208                 if (m.isSynchronized()) {
209                     if (mi.getTraceFlag()) mi.getTraceOut().println("exiting synchronized method, unlocking object");
210                     vm.monitorexit(synchobj);
211                 }
212                 throw ix.t;
213             }
214         }
215     }
216 
217     public Object invokeUnsafeMethod(jq_Method f) throws Throwable {
218         if (f == Unsafe._intBitsToFloat) {
219             return new Float(istate.pop_F());
220         } else if (f == Unsafe._floatToIntBits) {
221             return new Integer(istate.pop_I());
222         } else if (f == Unsafe._doubleToLongBits) {
223             return new Long(istate.pop_L());
224         } else if (f == Unsafe._longBitsToDouble) {
225             return new Double(istate.pop_D());
226         } else if (f == Unsafe._getThreadBlock) {
227             return Unsafe.getThreadBlock();
228         } else if (f.getName() == Utf8.get("to32BitValue")) {
229             return new Integer(((Address) istate.pop()).to32BitValue());
230         } else if (f.getName() == Utf8.get("addressOf")) {
231             return HeapAddress.addressOf(istate.pop_A());
232         } else if (f.getName() == Utf8.get("asObject")) {
233             return ((HeapAddress)istate.pop()).asObject();
234         } else if (f.getName() == Utf8.get("offset")) {
235             int i = istate.pop_I();
236             return ((Address)istate.pop()).offset(i);
237         } else if (f.getName() == Utf8.get("asReferenceType")) {
238             return (jq_Reference) ((HeapAddress)istate.pop()).asObject();
239         } else if (f.getName() == Utf8.get("peek")) {
240             return ((Address)istate.pop()).peek();
241         } else if (f.getName() == Utf8.get("peek1")) {
242             return new Integer(((Address)istate.pop()).peek1());
243         } else if (f.getName() == Utf8.get("peek2")) {
244             return new Integer(((Address)istate.pop()).peek2());
245         } else if (f.getName() == Utf8.get("peek4")) {
246             return new Integer(((Address)istate.pop()).peek4());
247         } else if (f.getName() == Utf8.get("peek8")) {
248             return new Long(((Address)istate.pop()).peek8());
249         } else if (f.getName() == Utf8.get("poke")) {
250             Address v = (Address) istate.pop();
251             Address a = (Address) istate.pop();
252             a.poke(v);
253             return null;
254         } else if (f.getName() == Utf8.get("poke1")) {
255             byte v = (byte) istate.pop_I();
256             Address a = (Address) istate.pop();
257             a.poke1(v);
258             return null;
259         } else if (f.getName() == Utf8.get("poke2")) {
260             short v = (short) istate.pop_I();
261             Address a = (Address) istate.pop();
262             a.poke2(v);
263             return null;
264         } else if (f.getName() == Utf8.get("poke4")) {
265             int v = istate.pop_I();
266             Address a = (Address) istate.pop();
267             a.poke4(v);
268             return null;
269         } else if (f.getName() == Utf8.get("poke8")) {
270             long v = istate.pop_L();
271             Address a = (Address) istate.pop();
272             a.poke8(v);
273             return null;
274         } else {
275             System.err.println(f.toString());
276             Assert.UNREACHABLE();
277             return null;
278         }
279     }
280         
281     public static class DirectState extends BytecodeInterpreter.State {
282         final StackAddress fp;
283         final int nlocals;
284         StackAddress sp;
285         int loResult, hiResult;
286         
287         public DirectState(StackAddress fp, StackAddress sp, int nlocals) {
288             this.fp = fp; this.sp = sp;
289             this.nlocals = nlocals;
290         }
291 
292         public void fillInParameters(jq_Type[] paramTypes, Object[] incomingArgs) {
293             for (int i=0, j=0; i<paramTypes.length; ++i, ++j) {
294                 jq_Type t = paramTypes[i];
295                 if (t.isReferenceType()) {
296                     push_A(incomingArgs[j]);
297                 } else if (t.isIntLike()) {
298                     push_I(Convert.unwrapToInt(incomingArgs[j]));
299                 } else if (t == jq_Primitive.FLOAT) {
300                     push_F(Convert.unwrapToFloat(incomingArgs[j]));
301                 } else if (t == jq_Primitive.LONG) {
302                     push_L(Convert.unwrapToLong(incomingArgs[j]));
303                     ++j;
304                 } else if (t == jq_Primitive.DOUBLE) {
305                     push_D(Convert.unwrapToDouble(incomingArgs[j]));
306                     ++j;
307                 } else {
308                     Assert.UNREACHABLE();
309                 }
310             }
311         }
312         
313         public void push_I(int v) {
314             sp = (StackAddress) sp.offset(-HeapAddress.size());
315             sp.poke4(v);
316         }
317         public void push_L(long v) {
318             push_I((int)(v>>32)); push_I((int)v); // hi, lo
319         }
320         public void push_F(float v) {
321             push_I(Float.floatToRawIntBits(v));
322         }
323         public void push_D(double v) {
324             push_L(Double.doubleToRawLongBits(v));
325         }
326         public void push_A(Object v) {
327             push_R(HeapAddress.addressOf(v));
328         }
329         public void push_R(Address v) {
330             sp = (StackAddress) sp.offset(-HeapAddress.size());
331             sp.poke(v);
332         }
333         public void push(Object v) {
334             push_A(v);
335         }
336         public int pop_I() {
337             int v = sp.peek4();
338             sp = (StackAddress) sp.offset(HeapAddress.size());
339             return v;
340         }
341         public long pop_L() {
342             int lo=pop_I(); int hi=pop_I();
343             return Convert.twoIntsToLong(lo, hi); // lo, hi
344         }
345         public float pop_F() {
346             return Float.intBitsToFloat(pop_I());
347         }
348         public double pop_D() {
349             return Double.longBitsToDouble(pop_L());
350         }
351         public Object pop_A() {
352             return ((HeapAddress) pop_R()).asObject();
353         }
354         public Address pop_R() {
355             Address v = sp.peek();
356             sp = (StackAddress) sp.offset(HeapAddress.size());
357             return v;
358         }
359         public Object pop() {
360             return pop_A();
361         }
362         public void popAll() {
363             sp = (StackAddress) fp.offset(-(nlocals * HeapAddress.size()));
364         }
365         public Object peek_A(int depth) {
366             HeapAddress v = (HeapAddress) sp.offset(depth * HeapAddress.size()).peek();
367             return v.asObject();
368         }
369         public void setLocal_I(int i, int v) {
370             fp.offset(-(i * HeapAddress.size())).poke4(v);
371         }
372         public void setLocal_L(int i, long v) {
373             setLocal_I(i, (int)(v>>32)); setLocal_I(i+1, (int)v); // hi, lo
374         }
375         public void setLocal_F(int i, float v) {
376             setLocal_I(i, Float.floatToRawIntBits(v));
377         }
378         public void setLocal_D(int i, double v) {
379             setLocal_L(i, Double.doubleToRawLongBits(v));
380         }
381         public void setLocal_A(int i, Object v) {
382             setLocal_R(i, HeapAddress.addressOf(v));
383         }
384         public void setLocal_R(int i, Address v) {
385             fp.offset(-(i * HeapAddress.size())).poke(v);
386         }
387         public int getLocal_I(int i) {
388             return fp.offset(-(i * HeapAddress.size())).peek4();
389         }
390         public long getLocal_L(int i) {
391             int lo=getLocal_I(i+1); int hi=getLocal_I(i); // lo, hi
392             return Convert.twoIntsToLong(lo, hi);
393         }
394         public float getLocal_F(int i) {
395             return Float.intBitsToFloat(getLocal_I(i));
396         }
397         public double getLocal_D(int i) {
398             return Double.longBitsToDouble(getLocal_L(i));
399         }
400         public Object getLocal_A(int i) {
401             return ((HeapAddress) getLocal_R(i)).asObject();
402         }
403         public Address getLocal_R(int i) {
404             return fp.offset(-(i * HeapAddress.size())).peek();
405         }
406         public void return_I(int v) {
407             loResult = v;
408         }
409         public void return_L(long v) {
410             loResult = (int)(v>>32); hiResult = (int)v;
411         }
412         public void return_F(float v) {
413             loResult = Float.floatToRawIntBits(v);
414         }
415         public void return_D(double v) {
416             return_L(Double.doubleToRawLongBits(v));
417         }
418         public void return_A(Object v) {
419             loResult = HeapAddress.addressOf(v).to32BitValue();
420         }
421         public void return_V() {}
422         public int getReturnVal_I() {
423             return loResult;
424         }
425         public long getReturnVal_L() {
426             return Convert.twoIntsToLong(loResult, hiResult);
427         }
428         public float getReturnVal_F() {
429             return Float.intBitsToFloat(loResult);
430         }
431         public double getReturnVal_D() {
432             return Double.longBitsToDouble(getReturnVal_L());
433         }
434         public Object getReturnVal_A() {
435             return ((HeapAddress) getReturnVal_R()).asObject();
436         }
437         public Address getReturnVal_R() {
438             return HeapAddress.address32(loResult);
439         }
440     }
441     
442     public static class DirectVMInterface extends BytecodeInterpreter.VMInterface {
443         public int getstatic_I(jq_StaticField f) { return f.getAddress().peek4(); }
444         public long getstatic_L(jq_StaticField f) { return f.getAddress().peek8(); }
445         public float getstatic_F(jq_StaticField f) { return Float.intBitsToFloat(getstatic_I(f)); }
446         public double getstatic_D(jq_StaticField f) { return Double.longBitsToDouble(getstatic_L(f)); }
447         public Object getstatic_A(jq_StaticField f) { return ((HeapAddress) f.getAddress().peek()).asObject(); }
448         public byte getstatic_B(jq_StaticField f) { return (byte)f.getAddress().peek4(); }
449         public char getstatic_C(jq_StaticField f) { return (char)f.getAddress().peek4(); }
450         public short getstatic_S(jq_StaticField f) { return (short)f.getAddress().peek4(); }
451         public boolean getstatic_Z(jq_StaticField f) { return f.getAddress().peek4()!=0; }
452         public void putstatic_I(jq_StaticField f, int v) { f.getDeclaringClass().setStaticData(f, v); }
453         public void putstatic_L(jq_StaticField f, long v) { f.getDeclaringClass().setStaticData(f, v); }
454         public void putstatic_F(jq_StaticField f, float v) { f.getDeclaringClass().setStaticData(f, v); }
455         public void putstatic_D(jq_StaticField f, double v) { f.getDeclaringClass().setStaticData(f, v); }
456         public void putstatic_A(jq_StaticField f, Object v) { f.getDeclaringClass().setStaticData(f, v); }
457         public void putstatic_Z(jq_StaticField f, boolean v) { f.getDeclaringClass().setStaticData(f, v?1:0); }
458         public void putstatic_B(jq_StaticField f, byte v) { f.getDeclaringClass().setStaticData(f, v); }
459         public void putstatic_C(jq_StaticField f, char v) { f.getDeclaringClass().setStaticData(f, v); }
460         public void putstatic_S(jq_StaticField f, short v) { f.getDeclaringClass().setStaticData(f, v); }
461         public int getfield_I(Object o, jq_InstanceField f) { return HeapAddress.addressOf(o).offset(f.getOffset()).peek4(); }
462         public long getfield_L(Object o, jq_InstanceField f) { return HeapAddress.addressOf(o).offset(f.getOffset()).peek8(); }
463         public float getfield_F(Object o, jq_InstanceField f) { return Float.intBitsToFloat(getfield_I(o, f)); }
464         public double getfield_D(Object o, jq_InstanceField f) { return Double.longBitsToDouble(getfield_L(o, f)); }
465         public Object getfield_A(Object o, jq_InstanceField f) { return ((HeapAddress)HeapAddress.addressOf(o).offset(f.getOffset()).peek()).asObject(); }
466         public byte getfield_B(Object o, jq_InstanceField f) { return HeapAddress.addressOf(o).offset(f.getOffset()).peek1(); }
467         public char getfield_C(Object o, jq_InstanceField f) { return (char)HeapAddress.addressOf(o).offset(f.getOffset()).peek4(); }
468         public short getfield_S(Object o, jq_InstanceField f) { return (short)HeapAddress.addressOf(o).offset(f.getOffset()).peek2(); }
469         public boolean getfield_Z(Object o, jq_InstanceField f) { return HeapAddress.addressOf(o).offset(f.getOffset()).peek1() != (byte)0; }
470         public void putfield_I(Object o, jq_InstanceField f, int v) { HeapAddress.addressOf(o).offset(f.getOffset()).poke4(v); }
471         public void putfield_L(Object o, jq_InstanceField f, long v) { HeapAddress.addressOf(o).offset(f.getOffset()).poke8(v); }
472         public void putfield_F(Object o, jq_InstanceField f, float v) { putfield_I(o, f, Float.floatToRawIntBits(v)); }
473         public void putfield_D(Object o, jq_InstanceField f, double v) { putfield_L(o, f, Double.doubleToRawLongBits(v)); }
474         public void putfield_A(Object o, jq_InstanceField f, Object v) { HeapAddress.addressOf(o).offset(f.getOffset()).poke(HeapAddress.addressOf(v)); }
475         public void putfield_B(Object o, jq_InstanceField f, byte v) { HeapAddress.addressOf(o).offset(f.getOffset()).poke1(v); }
476         public void putfield_C(Object o, jq_InstanceField f, char v) { HeapAddress.addressOf(o).offset(f.getOffset()).poke2((short)((v<<16)>>16)); }
477         public void putfield_S(Object o, jq_InstanceField f, short v) { HeapAddress.addressOf(o).offset(f.getOffset()).poke2(v); }
478         public void putfield_Z(Object o, jq_InstanceField f, boolean v) { HeapAddress.addressOf(o).offset(f.getOffset()).poke1(v?(byte)1:(byte)0); }
479         public Object new_obj(jq_Type t) { return ((jq_Class)t).newInstance(); }
480         public Object new_array(jq_Type t, int length) { return ((jq_Array)t).newInstance(length); }
481         public Object checkcast(Object o, jq_Type t) {
482             if (t.isAddressType()) return o;
483             return TypeCheck.checkcast(o, t);
484         }
485         public boolean instance_of(Object o, jq_Type t) { return TypeCheck.instance_of(o, t); }
486         public int arraylength(Object o) { return HeapAddress.addressOf(o).offset(ObjectLayout.ARRAY_LENGTH_OFFSET).peek4(); }
487         public void monitorenter(Object o, MethodInterpreter v) { Monitor.monitorenter(o); }
488         public void monitorexit(Object o) { Monitor.monitorexit(o); }
489         public Object multinewarray(int[] dims, jq_Type t) { return joeq.Runtime.Arrays.multinewarray_helper(dims, 0, (jq_Array)t); }
490         public jq_Reference getJQTypeOf(Object o) { return jq_Reference.getTypeOf(o); }
491     }
492 
493     // Invoke reflective interpreter from command line.
494     public static void main(String[] s_args) throws Throwable {
495         String s = s_args[0];
496         int dotloc = s.lastIndexOf('.');
497         String rootMethodClassName = s.substring(0, dotloc);
498         String rootMethodName = s.substring(dotloc+1);
499         
500         Assert._assert(jq.RunningNative);
501         
502         jq_Class c = (jq_Class)PrimordialClassLoader.loader.getOrCreateBSType("L"+rootMethodClassName.replace('.','/')+";");
503         c.cls_initialize();
504 
505         jq_StaticMethod rootm = null;
506         Utf8 rootm_name = Utf8.get(rootMethodName);
507         for(Iterator it = Arrays.asList(c.getDeclaredStaticMethods()).iterator();
508             it.hasNext(); ) {
509             jq_StaticMethod m = (jq_StaticMethod)it.next();
510             if (m.getName() == rootm_name) {
511                 rootm = m;
512                 break;
513             }
514         }
515         if (rootm == null)
516             Assert.UNREACHABLE("root method not found: "+rootMethodClassName+"."+rootMethodName);
517         Object[] args = new Object[rootm.getParamWords()];
518         jq_Type[] paramTypes = rootm.getParamTypes();
519         for (int i=0, j=0; i<paramTypes.length; ++i) {
520             j = TraceFlags.parseArg(args, i, paramTypes[i], s_args, j);
521         }
522         StackAddress newframe = StackAddress.alloca(args.length * HeapAddress.size());
523         StackAddress fp = (StackAddress) newframe.offset(args.length * HeapAddress.size());
524         StackAddress sp = fp;
525         DirectState initialState = new DirectState(fp, sp, 0);
526         initialState.fillInParameters(paramTypes, args);
527         Object retval = new DirectInterpreter(initialState).invokeMethod(rootm);
528         System.out.println("Return value: "+retval);
529     }
530     
531 }