public inbox for java-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* RFA: Changes to interpreter to avoid non-debugging slowdown
@ 2006-07-28 22:09 Kyle Galloway
  2006-07-31 18:42 ` Tom Tromey
  0 siblings, 1 reply; 16+ messages in thread
From: Kyle Galloway @ 2006-07-28 22:09 UTC (permalink / raw)
  To: java-patches

[-- Attachment #1: Type: text/plain, Size: 407 bytes --]

This patch creates a second version of _Jv_InterpMethod::run() using 
preprocessor directives to allow the debugging info to be collected only 
when the interpreter is passed the debug command line argument.  This 
avoids slowdowns in non-debugging cases by not gathering debug 
information or sending events when not debugging.

Would appreciate if someone would comment/commit this patch.

Thanks,
Kyle



[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 122482 bytes --]

Index: /notnfs/kgallowa/vanilla/libjava/ChangeLog
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/ChangeLog	(revision 115801)
+++ /notnfs/kgallowa/vanilla/libjava/ChangeLog	(working copy)
@@ -1,3 +1,25 @@
+2006-07-28  Kyle Galloway  <kgallowa@redhat.com>
+
+	* /include/java-interp.h (_Jv_InterpMethod::run): Changed to function pointer.
+	(_Jv_InterpMethod::run_no_debug): Renamed from run.
+	(_Jv_InterpMethod::run_debug): New method.
+	(_Jv_InterpMethod::getLocalsLength): New method.
+	(_Jv_InterpMethod::setDebug): New Method.
+	(_Jv_InterpFrame): Added localVars and localTypes pointers for variable
+	inspection.
+	* /interpret.cc: Added placeholder for debug variable type info to STORE* 
+	macros.
+	(_Jv_InterpMethod::run): Changed to function pointer and moved body to 
+	interpret-run.cc.
+	(_Jv_InterpMethod::run_no_debug): Renamed from run.
+	(_Jv_InterpMethod::run_debug): New method.
+	(_Jv_CompileMethod): Changed to use run_no_debug.
+	* /interpret-run.cc: New file, holds contents of old _Jv_InterpMethod::run
+	method.
+	* prims.cc (_Jv_RunMain): Disable debug by default.
+	(parse_x_arg): Enable debug on command line argument.
+	*stacktrace.cc (_Unwind_GetRegionStart): Changed to use run function pointer.
+
 2006-07-28  Andrew Haley  <aph@redhat.com>
 
 	* gnu/gcj/runtime/natSharedLibLoader.cc (init): Don't set
Index: /notnfs/kgallowa/vanilla/libjava/include/java-interp.h
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/include/java-interp.h	(revision 115793)
+++ /notnfs/kgallowa/vanilla/libjava/include/java-interp.h	(working copy)
@@ -177,8 +177,12 @@
   static void run_class (ffi_cif*, void*, ffi_raw*, void*);
   static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*);
 
-  static void run (void*, ffi_raw *, _Jv_InterpMethod *);
-
+  static void run_no_debug (void *, ffi_raw *, _Jv_InterpMethod *);
+  static void run_debug (void *, ffi_raw *, _Jv_InterpMethod *);
+  
+  //function pointer to distinguish between normal(no_debug) and debug mode
+  static void (*run) (void *, ffi_raw *, _Jv_InterpMethod *);
+  
   // Returns source file line number for given PC value, or -1 if line
   // number info is unavailable.
   int get_source_line(pc_t mpc);
@@ -183,6 +187,8 @@
   // number info is unavailable.
   int get_source_line(pc_t mpc);
 
+ public:
+
 #ifdef DIRECT_THREADED
   // Convenience function for indexing bytecode PC/insn slots in
   // line tables for JDWP
@@ -188,9 +194,18 @@
   // line tables for JDWP
   jlong insn_index (pc_t pc);
 #endif
-
- public:
-
+  
+  //used to get local variable list size info for JVMTI
+  jint getLocalsLength ()
+  {
+    return (jint) max_locals;
+  }
+  
+  //switch debug mode on or off
+  static void setDebug(bool debug)
+  {
+  	run = (debug) ? run_debug : run_no_debug;
+  }
   /* Get the line table for this method.
    * start  is the lowest index in the method
    * end    is the  highest index in the method
@@ -291,6 +306,10 @@
   java::lang::Thread *thread;
   _Jv_InterpFrame *next;
   pc_t pc;
+  
+  //For JVMTI/JDWP variable inspection
+  _Jv_word *localVars;
+  char *localTypes;
 
   _Jv_InterpFrame (_Jv_InterpMethod *s, java::lang::Thread *thr)
   {
Index: /notnfs/kgallowa/vanilla/libjava/interpret-run.cc
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/interpret-run.cc	(revision 0)
+++ /notnfs/kgallowa/vanilla/libjava/interpret-run.cc	(revision 0)
@@ -0,0 +1,2500 @@
+  using namespace java::lang::reflect;
+
+  // FRAME_DESC registers this particular invocation as the top-most
+  // interpreter frame.  This lets the stack tracing code (for
+  // Throwable) print information about the method being interpreted
+  // rather than about the interpreter itself.  FRAME_DESC has a
+  // destructor so it cleans up automatically when the interpreter
+  // returns.
+  java::lang::Thread *thread = java::lang::Thread::currentThread();
+  _Jv_InterpFrame frame_desc (meth, thread);
+
+  _Jv_word stack[meth->max_stack];
+  _Jv_word *sp = stack;
+
+  _Jv_word locals[meth->max_locals];
+  
+#ifdef DEBUG
+  char localsType[meth->max_locals];
+  frame_desc.localVars = locals;
+  frame_desc.localTypes = localsType;
+#endif
+
+#define INSN_LABEL(op) &&insn_##op
+
+  static const void *const insn_target[] = 
+  {
+    INSN_LABEL(nop),
+    INSN_LABEL(aconst_null),
+    INSN_LABEL(iconst_m1),
+    INSN_LABEL(iconst_0),
+    INSN_LABEL(iconst_1),
+    INSN_LABEL(iconst_2),
+    INSN_LABEL(iconst_3),
+    INSN_LABEL(iconst_4),
+    INSN_LABEL(iconst_5),
+    INSN_LABEL(lconst_0),
+    INSN_LABEL(lconst_1),
+    INSN_LABEL(fconst_0),
+    INSN_LABEL(fconst_1),
+    INSN_LABEL(fconst_2),
+    INSN_LABEL(dconst_0),
+    INSN_LABEL(dconst_1),
+    INSN_LABEL(bipush),
+    INSN_LABEL(sipush),
+    INSN_LABEL(ldc),
+    INSN_LABEL(ldc_w),
+    INSN_LABEL(ldc2_w),
+    INSN_LABEL(iload),
+    INSN_LABEL(lload),
+    INSN_LABEL(fload),
+    INSN_LABEL(dload),
+    INSN_LABEL(aload),
+    INSN_LABEL(iload_0),
+    INSN_LABEL(iload_1),
+    INSN_LABEL(iload_2),
+    INSN_LABEL(iload_3),
+    INSN_LABEL(lload_0),
+    INSN_LABEL(lload_1),
+    INSN_LABEL(lload_2),
+    INSN_LABEL(lload_3),
+    INSN_LABEL(fload_0),
+    INSN_LABEL(fload_1),
+    INSN_LABEL(fload_2),
+    INSN_LABEL(fload_3),
+    INSN_LABEL(dload_0),
+    INSN_LABEL(dload_1),
+    INSN_LABEL(dload_2),
+    INSN_LABEL(dload_3),
+    INSN_LABEL(aload_0),
+    INSN_LABEL(aload_1),
+    INSN_LABEL(aload_2),
+    INSN_LABEL(aload_3),
+    INSN_LABEL(iaload),
+    INSN_LABEL(laload),
+    INSN_LABEL(faload),
+    INSN_LABEL(daload),
+    INSN_LABEL(aaload),
+    INSN_LABEL(baload),
+    INSN_LABEL(caload),
+    INSN_LABEL(saload),
+    INSN_LABEL(istore),
+    INSN_LABEL(lstore),
+    INSN_LABEL(fstore),
+    INSN_LABEL(dstore),
+    INSN_LABEL(astore),
+    INSN_LABEL(istore_0),
+    INSN_LABEL(istore_1),
+    INSN_LABEL(istore_2),
+    INSN_LABEL(istore_3),
+    INSN_LABEL(lstore_0),
+    INSN_LABEL(lstore_1),
+    INSN_LABEL(lstore_2),
+    INSN_LABEL(lstore_3),
+    INSN_LABEL(fstore_0),
+    INSN_LABEL(fstore_1),
+    INSN_LABEL(fstore_2),
+    INSN_LABEL(fstore_3),
+    INSN_LABEL(dstore_0),
+    INSN_LABEL(dstore_1),
+    INSN_LABEL(dstore_2),
+    INSN_LABEL(dstore_3),
+    INSN_LABEL(astore_0),
+    INSN_LABEL(astore_1),
+    INSN_LABEL(astore_2),
+    INSN_LABEL(astore_3),
+    INSN_LABEL(iastore),
+    INSN_LABEL(lastore),
+    INSN_LABEL(fastore),
+    INSN_LABEL(dastore),
+    INSN_LABEL(aastore),
+    INSN_LABEL(bastore),
+    INSN_LABEL(castore),
+    INSN_LABEL(sastore),
+    INSN_LABEL(pop),
+    INSN_LABEL(pop2),
+    INSN_LABEL(dup),
+    INSN_LABEL(dup_x1),
+    INSN_LABEL(dup_x2),
+    INSN_LABEL(dup2),
+    INSN_LABEL(dup2_x1),
+    INSN_LABEL(dup2_x2),
+    INSN_LABEL(swap),
+    INSN_LABEL(iadd),
+    INSN_LABEL(ladd),
+    INSN_LABEL(fadd),
+    INSN_LABEL(dadd),
+    INSN_LABEL(isub),
+    INSN_LABEL(lsub),
+    INSN_LABEL(fsub),
+    INSN_LABEL(dsub),
+    INSN_LABEL(imul),
+    INSN_LABEL(lmul),
+    INSN_LABEL(fmul),
+    INSN_LABEL(dmul),
+    INSN_LABEL(idiv),
+    INSN_LABEL(ldiv),
+    INSN_LABEL(fdiv),
+    INSN_LABEL(ddiv),
+    INSN_LABEL(irem),
+    INSN_LABEL(lrem),
+    INSN_LABEL(frem),
+    INSN_LABEL(drem),
+    INSN_LABEL(ineg),
+    INSN_LABEL(lneg),
+    INSN_LABEL(fneg),
+    INSN_LABEL(dneg),
+    INSN_LABEL(ishl),
+    INSN_LABEL(lshl),
+    INSN_LABEL(ishr),
+    INSN_LABEL(lshr),
+    INSN_LABEL(iushr),
+    INSN_LABEL(lushr),
+    INSN_LABEL(iand),
+    INSN_LABEL(land),
+    INSN_LABEL(ior),
+    INSN_LABEL(lor),
+    INSN_LABEL(ixor),
+    INSN_LABEL(lxor),
+    INSN_LABEL(iinc),
+    INSN_LABEL(i2l),
+    INSN_LABEL(i2f),
+    INSN_LABEL(i2d),
+    INSN_LABEL(l2i),
+    INSN_LABEL(l2f),
+    INSN_LABEL(l2d),
+    INSN_LABEL(f2i),
+    INSN_LABEL(f2l),
+    INSN_LABEL(f2d),
+    INSN_LABEL(d2i),
+    INSN_LABEL(d2l),
+    INSN_LABEL(d2f),
+    INSN_LABEL(i2b),
+    INSN_LABEL(i2c),
+    INSN_LABEL(i2s),
+    INSN_LABEL(lcmp),
+    INSN_LABEL(fcmpl),
+    INSN_LABEL(fcmpg),
+    INSN_LABEL(dcmpl),
+    INSN_LABEL(dcmpg),
+    INSN_LABEL(ifeq),
+    INSN_LABEL(ifne),
+    INSN_LABEL(iflt),
+    INSN_LABEL(ifge),
+    INSN_LABEL(ifgt),
+    INSN_LABEL(ifle),
+    INSN_LABEL(if_icmpeq),
+    INSN_LABEL(if_icmpne),
+    INSN_LABEL(if_icmplt),
+    INSN_LABEL(if_icmpge),
+    INSN_LABEL(if_icmpgt),
+    INSN_LABEL(if_icmple),
+    INSN_LABEL(if_acmpeq),
+    INSN_LABEL(if_acmpne),
+    INSN_LABEL(goto), 
+    INSN_LABEL(jsr),
+    INSN_LABEL(ret),
+    INSN_LABEL(tableswitch),
+    INSN_LABEL(lookupswitch),
+    INSN_LABEL(ireturn),
+    INSN_LABEL(lreturn),
+    INSN_LABEL(freturn),
+    INSN_LABEL(dreturn),
+    INSN_LABEL(areturn),
+    INSN_LABEL(return),
+    INSN_LABEL(getstatic),
+    INSN_LABEL(putstatic),
+    INSN_LABEL(getfield),
+    INSN_LABEL(putfield),
+    INSN_LABEL(invokevirtual),
+    INSN_LABEL(invokespecial),
+    INSN_LABEL(invokestatic),
+    INSN_LABEL(invokeinterface),
+    0, /* Unused.  */
+    INSN_LABEL(new),
+    INSN_LABEL(newarray),
+    INSN_LABEL(anewarray),
+    INSN_LABEL(arraylength),
+    INSN_LABEL(athrow),
+    INSN_LABEL(checkcast),
+    INSN_LABEL(instanceof),
+    INSN_LABEL(monitorenter),
+    INSN_LABEL(monitorexit),
+#ifdef DIRECT_THREADED
+    0, // wide
+#else
+    INSN_LABEL(wide),
+#endif
+    INSN_LABEL(multianewarray),
+    INSN_LABEL(ifnull),
+    INSN_LABEL(ifnonnull),
+    INSN_LABEL(goto_w),
+    INSN_LABEL(jsr_w),
+#ifdef DIRECT_THREADED
+    INSN_LABEL (ldc_class)
+#else
+    0
+#endif
+  };
+
+  pc_t pc;
+
+#ifdef DIRECT_THREADED
+
+#define NEXT_INSN goto *((pc++)->insn)
+#define INTVAL() ((pc++)->int_val)
+#define AVAL() ((pc++)->datum)
+
+#define GET1S() INTVAL ()
+#define GET2S() INTVAL ()
+#define GET1U() INTVAL ()
+#define GET2U() INTVAL ()
+#define AVAL1U() AVAL ()
+#define AVAL2U() AVAL ()
+#define AVAL2UP() AVAL ()
+#define SKIP_GOTO ++pc
+#define GOTO_VAL() (insn_slot *) pc->datum
+#define PCVAL(unionval) unionval.p
+#define AMPAMP(label) &&label
+
+  // Compile if we must. NOTE: Double-check locking.
+  if (meth->prepared == NULL)
+    {
+      _Jv_MutexLock (&compile_mutex);
+      if (meth->prepared == NULL)
+	meth->compile (insn_target);
+      _Jv_MutexUnlock (&compile_mutex);
+    }
+
+  // If we're only compiling, stop here
+  if (args == NULL)
+    return;
+
+  pc = (insn_slot *) meth->prepared;
+
+#else
+
+#define NEXT_INSN goto *(insn_target[*pc++])
+
+#define GET1S() get1s (pc++)
+#define GET2S() (pc += 2, get2s (pc- 2))
+#define GET1U() get1u (pc++)
+#define GET2U() (pc += 2, get2u (pc - 2))
+  // Note that these could be more efficient when not handling 'ldc
+  // class'.
+#define AVAL1U()						\
+  ({ int index = get1u (pc++);					\
+      resolve_pool_entry (meth->defining_class, index).o; })
+#define AVAL2U()						\
+  ({ int index = get2u (pc); pc += 2;				\
+      resolve_pool_entry (meth->defining_class, index).o; })
+  // Note that we don't need to resolve the pool entry here as class
+  // constants are never wide.
+#define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
+#define SKIP_GOTO pc += 2
+#define GOTO_VAL() pc - 1 + get2s (pc)
+#define PCVAL(unionval) unionval.i
+#define AMPAMP(label) NULL
+
+  pc = bytecode ();
+
+#endif /* DIRECT_THREADED */
+
+#define TAKE_GOTO pc = GOTO_VAL ()
+
+  /* Go straight at it!  the ffi raw format matches the internal
+     stack representation exactly.  At least, that's the idea.
+  */
+  memcpy ((void*) locals, (void*) args, meth->args_raw_size);
+
+  _Jv_word *pool_data = meth->defining_class->constants.data;
+
+  /* These three are temporaries for common code used by several
+     instructions.  */
+  void (*fun)();
+  _Jv_ResolvedMethod* rmeth;
+  int tmpval;
+
+  try
+    {
+      // We keep nop around.  It is used if we're interpreting the
+      // bytecodes and not doing direct threading.
+    insn_nop:
+      NEXT_INSN;
+
+      /* The first few instructions here are ordered according to their
+	 frequency, in the hope that this will improve code locality a
+	 little.  */
+
+    insn_aload_0:		// 0x2a
+      LOADA (0);
+      NEXT_INSN;
+
+    insn_iload:		// 0x15
+      LOADI (GET1U ());
+      NEXT_INSN;
+
+    insn_iload_1:		// 0x1b
+      LOADI (1);
+      NEXT_INSN;
+
+    insn_invokevirtual:	// 0xb6
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	/* _Jv_Linker::resolve_pool_entry returns immediately if the
+	 * value already is resolved.  If we want to clutter up the
+	 * code here to gain a little performance, then we can check
+	 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
+	 * directly.  For now, I don't think it is worth it.  */
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	if (rmeth->method->accflags & Modifier::FINAL)
+	  {
+	    // We can't rely on NULLCHECK working if the method is final.
+	    if (! sp[0].o)
+	      throw_null_pointer_exception ();
+
+	    // Final methods might not appear in the vtable.
+	    fun = (void (*)()) rmeth->method->ncode;
+	  }
+	else
+	  {
+	    NULLCHECK (sp[0].o);
+	    jobject rcv = sp[0].o;
+	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
+	    fun = (void (*)()) table->get_method (rmeth->method->index);
+	  }
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokevirtual_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokevirtual_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+
+	if (rmeth->method->accflags & Modifier::FINAL)
+	  {
+	    // We can't rely on NULLCHECK working if the method is final.
+	    if (! sp[0].o)
+	      throw_null_pointer_exception ();
+
+	    // Final methods might not appear in the vtable.
+	    fun = (void (*)()) rmeth->method->ncode;
+	  }
+	else
+	  {
+	    jobject rcv = sp[0].o;
+	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
+	    fun = (void (*)()) table->get_method (rmeth->method->index);
+	  }
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    perform_invoke:
+      {
+	/* here goes the magic again... */
+	ffi_cif *cif = &rmeth->cif;
+	ffi_raw *raw = (ffi_raw*) sp;
+
+	_Jv_value rvalue;
+
+#if FFI_NATIVE_RAW_API
+	/* We assume that this is only implemented if it's correct	*/
+	/* to use it here.  On a 64 bit machine, it never is.		*/
+	ffi_raw_call (cif, fun, (void*)&rvalue, raw);
+#else
+	ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
+#endif
+
+	int rtype = cif->rtype->type;
+
+	/* the likelyhood of object, int, or void return is very high,
+	 * so those are checked before the switch */
+	if (rtype == FFI_TYPE_POINTER)
+	  {
+	    PUSHA (rvalue.object_value);
+	  }
+	else if (rtype == FFI_TYPE_SINT32)
+	  {
+	    PUSHI (rvalue.int_value);
+	  }
+	else if (rtype == FFI_TYPE_VOID)
+	  {
+	    /* skip */
+	  }
+	else
+	  {
+	    switch (rtype)
+	      {
+	      case FFI_TYPE_SINT8:
+		PUSHI ((jbyte)(rvalue.int_value & 0xff));
+		break;
+
+	      case FFI_TYPE_SINT16:
+		PUSHI ((jshort)(rvalue.int_value & 0xffff));
+		break;
+
+	      case FFI_TYPE_UINT16:
+		PUSHI (rvalue.int_value & 0xffff);
+		break;
+
+	      case FFI_TYPE_FLOAT:
+	        PUSHF (rvalue.float_value);
+		break;
+
+	      case FFI_TYPE_DOUBLE:
+	        PUSHD (rvalue.double_value);
+		break;
+
+	      case FFI_TYPE_SINT64:
+	        PUSHL (rvalue.long_value);
+		break;
+
+	      default:
+		throw_internal_error ("unknown return type in invokeXXX");
+	      }
+	  }
+      }
+      NEXT_INSN;
+
+    insn_aconst_null:
+      PUSHA (NULL);
+      NEXT_INSN;
+
+    insn_iconst_m1:
+      PUSHI (-1);
+      NEXT_INSN;
+
+    insn_iconst_0:
+      PUSHI (0);
+      NEXT_INSN;
+
+    insn_iconst_1:
+      PUSHI (1);
+      NEXT_INSN;
+
+    insn_iconst_2:
+      PUSHI (2);
+      NEXT_INSN;
+
+    insn_iconst_3:
+      PUSHI (3);
+      NEXT_INSN;
+
+    insn_iconst_4:
+      PUSHI (4);
+      NEXT_INSN;
+
+    insn_iconst_5:
+      PUSHI (5);
+      NEXT_INSN;
+
+    insn_lconst_0:
+      PUSHL (0);
+      NEXT_INSN;
+
+    insn_lconst_1:
+      PUSHL (1);
+      NEXT_INSN;
+
+    insn_fconst_0:
+      PUSHF (0);
+      NEXT_INSN;
+
+    insn_fconst_1:
+      PUSHF (1);
+      NEXT_INSN;
+
+    insn_fconst_2:
+      PUSHF (2);
+      NEXT_INSN;
+
+    insn_dconst_0:
+      PUSHD (0);
+      NEXT_INSN;
+
+    insn_dconst_1:
+      PUSHD (1);
+      NEXT_INSN;
+
+    insn_bipush:
+      // For direct threaded, bipush and sipush are the same.
+#ifndef DIRECT_THREADED
+      PUSHI (GET1S ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_sipush:
+      PUSHI (GET2S ());
+      NEXT_INSN;
+
+    insn_ldc:
+      // For direct threaded, ldc and ldc_w are the same.
+#ifndef DIRECT_THREADED
+      PUSHA ((jobject) AVAL1U ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_ldc_w:
+      PUSHA ((jobject) AVAL2U ());
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+      // For direct threaded we have a separate 'ldc class' operation.
+    insn_ldc_class:
+      {
+	SAVE_PC();
+	// We could rewrite the instruction at this point.
+	int index = INTVAL ();
+	jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						     index)).o;
+	PUSHA (k);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_ldc2_w:
+      {
+	void *where = AVAL2UP ();
+	memcpy (sp, where, 2*sizeof (_Jv_word));
+	sp += 2;
+      }
+      NEXT_INSN;
+
+    insn_lload:
+      LOADL (GET1U ());
+      NEXT_INSN;
+
+    insn_fload:
+      LOADF (GET1U ());
+      NEXT_INSN;
+
+    insn_dload:
+      LOADD (GET1U ());
+      NEXT_INSN;
+
+    insn_aload:
+      LOADA (GET1U ());
+      NEXT_INSN;
+
+    insn_iload_0:
+      LOADI (0);
+      NEXT_INSN;
+
+    insn_iload_2:
+      LOADI (2);
+      NEXT_INSN;
+
+    insn_iload_3:
+      LOADI (3);
+      NEXT_INSN;
+
+    insn_lload_0:
+      LOADL (0);
+      NEXT_INSN;
+
+    insn_lload_1:
+      LOADL (1);
+      NEXT_INSN;
+
+    insn_lload_2:
+      LOADL (2);
+      NEXT_INSN;
+
+    insn_lload_3:
+      LOADL (3);
+      NEXT_INSN;
+
+    insn_fload_0:
+      LOADF (0);
+      NEXT_INSN;
+
+    insn_fload_1:
+      LOADF (1);
+      NEXT_INSN;
+
+    insn_fload_2:
+      LOADF (2);
+      NEXT_INSN;
+
+    insn_fload_3:
+      LOADF (3);
+      NEXT_INSN;
+
+    insn_dload_0:
+      LOADD (0);
+      NEXT_INSN;
+
+    insn_dload_1:
+      LOADD (1);
+      NEXT_INSN;
+
+    insn_dload_2:
+      LOADD (2);
+      NEXT_INSN;
+
+    insn_dload_3:
+      LOADD (3);
+      NEXT_INSN;
+
+    insn_aload_1:
+      LOADA(1);
+      NEXT_INSN;
+
+    insn_aload_2:
+      LOADA(2);
+      NEXT_INSN;
+
+    insn_aload_3:
+      LOADA(3);
+      NEXT_INSN;
+
+    insn_iaload:
+      {
+	jint index = POPI();
+	jintArray arr = (jintArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_laload:
+      {
+	jint index = POPI();
+	jlongArray arr = (jlongArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHL( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_faload:
+      {
+	jint index = POPI();
+	jfloatArray arr = (jfloatArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHF( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_daload:
+      {
+	jint index = POPI();
+	jdoubleArray arr = (jdoubleArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHD( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_aaload:
+      {
+	jint index = POPI();
+	jobjectArray arr = (jobjectArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHA( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_baload:
+      {
+	jint index = POPI();
+	jbyteArray arr = (jbyteArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_caload:
+      {
+	jint index = POPI();
+	jcharArray arr = (jcharArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_saload:
+      {
+	jint index = POPI();
+	jshortArray arr = (jshortArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_istore:
+      STOREI (GET1U ());
+      NEXT_INSN;
+
+    insn_lstore:
+      STOREL (GET1U ());
+      NEXT_INSN;
+
+    insn_fstore:
+      STOREF (GET1U ());
+      NEXT_INSN;
+
+    insn_dstore:
+      STORED (GET1U ());
+      NEXT_INSN;
+
+    insn_astore:
+      STOREA (GET1U ());
+      NEXT_INSN;
+
+    insn_istore_0:
+      STOREI (0);
+      NEXT_INSN;
+
+    insn_istore_1:
+      STOREI (1);
+      NEXT_INSN;
+
+    insn_istore_2:
+      STOREI (2);
+      NEXT_INSN;
+
+    insn_istore_3:
+      STOREI (3);
+      NEXT_INSN;
+
+    insn_lstore_0:
+      STOREL (0);
+      NEXT_INSN;
+
+    insn_lstore_1:
+      STOREL (1);
+      NEXT_INSN;
+
+    insn_lstore_2:
+      STOREL (2);
+      NEXT_INSN;
+
+    insn_lstore_3:
+      STOREL (3);
+      NEXT_INSN;
+
+    insn_fstore_0:
+      STOREF (0);
+      NEXT_INSN;
+
+    insn_fstore_1:
+      STOREF (1);
+      NEXT_INSN;
+
+    insn_fstore_2:
+      STOREF (2);
+      NEXT_INSN;
+
+    insn_fstore_3:
+      STOREF (3);
+      NEXT_INSN;
+
+    insn_dstore_0:
+      STORED (0);
+      NEXT_INSN;
+
+    insn_dstore_1:
+      STORED (1);
+      NEXT_INSN;
+
+    insn_dstore_2:
+      STORED (2);
+      NEXT_INSN;
+
+    insn_dstore_3:
+      STORED (3);
+      NEXT_INSN;
+
+    insn_astore_0:
+      STOREA(0);
+      NEXT_INSN;
+
+    insn_astore_1:
+      STOREA(1);
+      NEXT_INSN;
+
+    insn_astore_2:
+      STOREA(2);
+      NEXT_INSN;
+
+    insn_astore_3:
+      STOREA(3);
+      NEXT_INSN;
+
+    insn_iastore:
+      {
+	jint value = POPI();
+	jint index  = POPI();
+	jintArray arr = (jintArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_lastore:
+      {
+	jlong value = POPL();
+	jint index  = POPI();
+	jlongArray arr = (jlongArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_fastore:
+      {
+	jfloat value = POPF();
+	jint index  = POPI();
+	jfloatArray arr = (jfloatArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_dastore:
+      {
+	jdouble value = POPD();
+	jint index  = POPI();
+	jdoubleArray arr = (jdoubleArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_aastore:
+      {
+	jobject value = POPA();
+	jint index  = POPI();
+	jobjectArray arr = (jobjectArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	_Jv_CheckArrayStore (arr, value);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_bastore:
+      {
+	jbyte value = (jbyte) POPI();
+	jint index  = POPI();
+	jbyteArray arr = (jbyteArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_castore:
+      {
+	jchar value = (jchar) POPI();
+	jint index  = POPI();
+	jcharArray arr = (jcharArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_sastore:
+      {
+	jshort value = (jshort) POPI();
+	jint index  = POPI();
+	jshortArray arr = (jshortArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_pop:
+      sp -= 1;
+      NEXT_INSN;
+
+    insn_pop2:
+      sp -= 2;
+      NEXT_INSN;
+
+    insn_dup:
+      sp[0] = sp[-1];
+      sp += 1;
+      NEXT_INSN;
+
+    insn_dup_x1:
+      dupx (sp, 1, 1); sp+=1;
+      NEXT_INSN;
+
+    insn_dup_x2:
+      dupx (sp, 1, 2); sp+=1;
+      NEXT_INSN;
+
+    insn_dup2:
+      sp[0] = sp[-2];
+      sp[1] = sp[-1];
+      sp += 2;
+      NEXT_INSN;
+
+    insn_dup2_x1:
+      dupx (sp, 2, 1); sp+=2;
+      NEXT_INSN;
+
+    insn_dup2_x2:
+      dupx (sp, 2, 2); sp+=2;
+      NEXT_INSN;
+
+    insn_swap:
+      {
+	jobject tmp1 = POPA();
+	jobject tmp2 = POPA();
+	PUSHA (tmp1);
+	PUSHA (tmp2);
+      }
+      NEXT_INSN;
+
+    insn_iadd:
+      BINOPI(+);
+      NEXT_INSN;
+
+    insn_ladd:
+      BINOPL(+);
+      NEXT_INSN;
+
+    insn_fadd:
+      BINOPF(+);
+      NEXT_INSN;
+
+    insn_dadd:
+      BINOPD(+);
+      NEXT_INSN;
+
+    insn_isub:
+      BINOPI(-);
+      NEXT_INSN;
+
+    insn_lsub:
+      BINOPL(-);
+      NEXT_INSN;
+
+    insn_fsub:
+      BINOPF(-);
+      NEXT_INSN;
+
+    insn_dsub:
+      BINOPD(-);
+      NEXT_INSN;
+
+    insn_imul:
+      BINOPI(*);
+      NEXT_INSN;
+
+    insn_lmul:
+      BINOPL(*);
+      NEXT_INSN;
+
+    insn_fmul:
+      BINOPF(*);
+      NEXT_INSN;
+
+    insn_dmul:
+      BINOPD(*);
+      NEXT_INSN;
+
+    insn_idiv:
+      {
+	SAVE_PC();
+	jint value2 = POPI();
+	jint value1 = POPI();
+	jint res = _Jv_divI (value1, value2);
+	PUSHI (res);
+      }
+      NEXT_INSN;
+
+    insn_ldiv:
+      {
+	SAVE_PC();
+	jlong value2 = POPL();
+	jlong value1 = POPL();
+	jlong res = _Jv_divJ (value1, value2);
+	PUSHL (res);
+      }
+      NEXT_INSN;
+
+    insn_fdiv:
+      {
+	jfloat value2 = POPF();
+	jfloat value1 = POPF();
+	jfloat res = value1 / value2;
+	PUSHF (res);
+      }
+      NEXT_INSN;
+
+    insn_ddiv:
+      {
+	jdouble value2 = POPD();
+	jdouble value1 = POPD();
+	jdouble res = value1 / value2;
+	PUSHD (res);
+      }
+      NEXT_INSN;
+
+    insn_irem:
+      {
+	SAVE_PC();
+	jint value2 = POPI();
+	jint value1 =  POPI();
+	jint res = _Jv_remI (value1, value2);
+	PUSHI (res);
+      }
+      NEXT_INSN;
+
+    insn_lrem:
+      {
+	SAVE_PC();
+	jlong value2 = POPL();
+	jlong value1 = POPL();
+	jlong res = _Jv_remJ (value1, value2);
+	PUSHL (res);
+      }
+      NEXT_INSN;
+
+    insn_frem:
+      {
+	jfloat value2 = POPF();
+	jfloat value1 = POPF();
+	jfloat res    = __ieee754_fmod (value1, value2);
+	PUSHF (res);
+      }
+      NEXT_INSN;
+
+    insn_drem:
+      {
+	jdouble value2 = POPD();
+	jdouble value1 = POPD();
+	jdouble res    = __ieee754_fmod (value1, value2);
+	PUSHD (res);
+      }
+      NEXT_INSN;
+
+    insn_ineg:
+      {
+	jint value = POPI();
+	PUSHI (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_lneg:
+      {
+	jlong value = POPL();
+	PUSHL (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_fneg:
+      {
+	jfloat value = POPF();
+	PUSHF (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_dneg:
+      {
+	jdouble value = POPD();
+	PUSHD (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_ishl:
+      {
+	jint shift = (POPI() & 0x1f);
+	jint value = POPI();
+	PUSHI (value << shift);
+      }
+      NEXT_INSN;
+
+    insn_lshl:
+      {
+	jint shift = (POPI() & 0x3f);
+	jlong value = POPL();
+	PUSHL (value << shift);
+      }
+      NEXT_INSN;
+
+    insn_ishr:
+      {
+	jint shift = (POPI() & 0x1f);
+	jint value = POPI();
+	PUSHI (value >> shift);
+      }
+      NEXT_INSN;
+
+    insn_lshr:
+      {
+	jint shift = (POPI() & 0x3f);
+	jlong value = POPL();
+	PUSHL (value >> shift);
+      }
+      NEXT_INSN;
+
+    insn_iushr:
+      {
+	jint shift = (POPI() & 0x1f);
+	_Jv_uint value = (_Jv_uint) POPI();
+	PUSHI ((jint) (value >> shift));
+      }
+      NEXT_INSN;
+
+    insn_lushr:
+      {
+	jint shift = (POPI() & 0x3f);
+	_Jv_ulong value = (_Jv_ulong) POPL();
+	PUSHL ((jlong) (value >> shift));
+      }
+      NEXT_INSN;
+
+    insn_iand:
+      BINOPI (&);
+      NEXT_INSN;
+
+    insn_land:
+      BINOPL (&);
+      NEXT_INSN;
+
+    insn_ior:
+      BINOPI (|);
+      NEXT_INSN;
+
+    insn_lor:
+      BINOPL (|);
+      NEXT_INSN;
+
+    insn_ixor:
+      BINOPI (^);
+      NEXT_INSN;
+
+    insn_lxor:
+      BINOPL (^);
+      NEXT_INSN;
+
+    insn_iinc:
+      {
+	jint index  = GET1U ();
+	jint amount = GET1S ();
+	locals[index].i += amount;
+      }
+      NEXT_INSN;
+
+    insn_i2l:
+      {jlong value = POPI(); PUSHL (value);}
+      NEXT_INSN;
+
+    insn_i2f:
+      {jfloat value = POPI(); PUSHF (value);}
+      NEXT_INSN;
+
+    insn_i2d:
+      {jdouble value = POPI(); PUSHD (value);}
+      NEXT_INSN;
+
+    insn_l2i:
+      {jint value = POPL(); PUSHI (value);}
+      NEXT_INSN;
+
+    insn_l2f:
+      {jfloat value = POPL(); PUSHF (value);}
+      NEXT_INSN;
+
+    insn_l2d:
+      {jdouble value = POPL(); PUSHD (value);}
+      NEXT_INSN;
+
+    insn_f2i:
+      {
+	using namespace java::lang;
+	jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
+	PUSHI(value);
+      }
+      NEXT_INSN;
+
+    insn_f2l:
+      {
+	using namespace java::lang;
+	jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
+	PUSHL(value);
+      }
+      NEXT_INSN;
+
+    insn_f2d:
+      { jdouble value = POPF (); PUSHD(value); }
+      NEXT_INSN;
+
+    insn_d2i:
+      {
+	using namespace java::lang;
+	jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
+	PUSHI(value);
+      }
+      NEXT_INSN;
+
+    insn_d2l:
+      {
+	using namespace java::lang;
+	jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
+	PUSHL(value);
+      }
+      NEXT_INSN;
+
+    insn_d2f:
+      { jfloat value = POPD (); PUSHF(value); }
+      NEXT_INSN;
+
+    insn_i2b:
+      { jbyte value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_i2c:
+      { jchar value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_i2s:
+      { jshort value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_lcmp:
+      {
+	jlong value2 = POPL ();
+	jlong value1 = POPL ();
+	if (value1 > value2)
+	  { PUSHI (1); }
+	else if (value1 == value2)
+	  { PUSHI (0); }
+	else
+	  { PUSHI (-1); }
+      }
+      NEXT_INSN;
+
+    insn_fcmpl:
+      tmpval = -1;
+      goto fcmp;
+
+    insn_fcmpg:
+      tmpval = 1;
+
+    fcmp:
+      {
+	jfloat value2 = POPF ();
+	jfloat value1 = POPF ();
+	if (value1 > value2)
+	  PUSHI (1);
+	else if (value1 == value2)
+	  PUSHI (0);
+	else if (value1 < value2)
+	  PUSHI (-1);
+	else
+	  PUSHI (tmpval);
+      }
+      NEXT_INSN;
+
+    insn_dcmpl:
+      tmpval = -1;
+      goto dcmp;
+
+    insn_dcmpg:
+      tmpval = 1;
+
+    dcmp:
+      {
+	jdouble value2 = POPD ();
+	jdouble value1 = POPD ();
+	if (value1 > value2)
+	  PUSHI (1);
+	else if (value1 == value2)
+	  PUSHI (0);
+	else if (value1 < value2)
+	  PUSHI (-1);
+	else
+	  PUSHI (tmpval);
+      }
+      NEXT_INSN;
+
+    insn_ifeq:
+      {
+	if (POPI() == 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifne:
+      {
+	if (POPI() != 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_iflt:
+      {
+	if (POPI() < 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifge:
+      {
+	if (POPI() >= 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifgt:
+      {
+	if (POPI() > 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifle:
+      {
+	if (POPI() <= 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpeq:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 == value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpne:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 != value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmplt:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 < value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpge:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 >= value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpgt:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 > value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmple:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 <= value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_acmpeq:
+      {
+	jobject value2 = POPA();
+	jobject value1 = POPA();
+	if (value1 == value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_acmpne:
+      {
+	jobject value2 = POPA();
+	jobject value1 = POPA();
+	if (value1 != value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_goto_w:
+#ifndef DIRECT_THREADED
+      // For direct threaded, goto and goto_w are the same.
+      pc = pc - 1 + get4 (pc);
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_goto:
+      TAKE_GOTO;
+      NEXT_INSN;
+
+    insn_jsr_w:
+#ifndef DIRECT_THREADED
+      // For direct threaded, jsr and jsr_w are the same.
+      {
+	pc_t next = pc - 1 + get4 (pc);
+	pc += 4;
+	PUSHA ((jobject) pc);
+	pc = next;
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_jsr:
+      {
+	pc_t next = GOTO_VAL();
+	SKIP_GOTO;
+	PUSHA ((jobject) pc);
+	pc = next;
+      }
+      NEXT_INSN;
+
+    insn_ret:
+      {
+	jint index = GET1U ();
+	pc = (pc_t) PEEKA (index);
+      }
+      NEXT_INSN;
+
+    insn_tableswitch:
+      {
+#ifdef DIRECT_THREADED
+	void *def = (pc++)->datum;
+
+	int index = POPI();
+
+	jint low = INTVAL ();
+	jint high = INTVAL ();
+
+	if (index < low || index > high)
+	  pc = (insn_slot *) def;
+	else
+	  pc = (insn_slot *) ((pc + index - low)->datum);
+#else
+	pc_t base_pc = pc - 1;
+	int index = POPI ();
+
+	pc_t base = (pc_t) bytecode ();
+	while ((pc - base) % 4 != 0)
+	  ++pc;
+
+	jint def = get4 (pc);
+	jint low = get4 (pc + 4);
+	jint high = get4 (pc + 8);
+	if (index < low || index > high)
+	  pc = base_pc + def;
+	else
+	  pc = base_pc + get4 (pc + 4 * (index - low + 3));
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+    insn_lookupswitch:
+      {
+#ifdef DIRECT_THREADED
+	void *def = (pc++)->insn;
+
+	int index = POPI();
+
+	jint npairs = INTVAL ();
+
+	int max = npairs - 1;
+	int min = 0;
+
+	// Simple binary search...
+	while (min < max)
+	  {
+	    int half = (min + max) / 2;
+	    int match = pc[2 * half].int_val;
+
+	    if (index == match)
+	      {
+		// Found it.
+		pc = (insn_slot *) pc[2 * half + 1].datum;
+		NEXT_INSN;
+	      }
+	    else if (index < match)
+	      // We can use HALF - 1 here because we check again on
+	      // loop exit.
+	      max = half - 1;
+	    else
+	      // We can use HALF + 1 here because we check again on
+	      // loop exit.
+	      min = half + 1;
+	  }
+	if (index == pc[2 * min].int_val)
+	  pc = (insn_slot *) pc[2 * min + 1].datum;
+	else
+	  pc = (insn_slot *) def;
+#else
+	unsigned char *base_pc = pc-1;
+	int index = POPI();
+
+	unsigned char* base = bytecode ();
+	while ((pc-base) % 4 != 0)
+	  ++pc;
+
+	jint def     = get4 (pc);
+	jint npairs  = get4 (pc+4);
+
+	int max = npairs-1;
+	int min = 0;
+
+	// Simple binary search...
+	while (min < max)
+	  {
+	    int half = (min+max)/2;
+	    int match = get4 (pc+ 4*(2 + 2*half));
+
+	    if (index == match)
+	      min = max = half;
+	    else if (index < match)
+	      // We can use HALF - 1 here because we check again on
+	      // loop exit.
+	      max = half - 1;
+	    else
+	      // We can use HALF + 1 here because we check again on
+	      // loop exit.
+	      min = half + 1;
+	  }
+
+	if (index == get4 (pc+ 4*(2 + 2*min)))
+	  pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
+	else
+	  pc = base_pc + def;    
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+    insn_areturn:
+      *(jobject *) retp = POPA ();
+      return;
+
+    insn_lreturn:
+      *(jlong *) retp = POPL ();
+      return;
+
+    insn_freturn:
+      *(jfloat *) retp = POPF ();
+      return;
+
+    insn_dreturn:
+      *(jdouble *) retp = POPD ();
+      return;
+
+    insn_ireturn:
+      *(jint *) retp = POPI ();
+      return;
+
+    insn_return:
+      return;
+
+    insn_getstatic:
+      {
+	jint fieldref_index = GET2U ();
+        SAVE_PC(); // Constant pool resolution could throw.
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	if ((field->flags & Modifier::STATIC) == 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field no longer static"));
+
+	jclass type = field->type;
+
+	// We rewrite the instruction once we discover what it refers
+	// to.
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes)
+	      {
+	      case 1:
+		PUSHI (*field->u.byte_addr);
+		newinsn = AMPAMP (getstatic_resolved_1);
+		break;
+
+	      case 2:
+		if (type == JvPrimClass (char))
+		  {
+		    PUSHI (*field->u.char_addr);
+		    newinsn = AMPAMP (getstatic_resolved_char);
+		  }
+		else
+		  {
+		    PUSHI (*field->u.short_addr);
+		    newinsn = AMPAMP (getstatic_resolved_short);
+		  }
+		break;
+
+	      case 4:
+	        PUSHI(*field->u.int_addr);
+		newinsn = AMPAMP (getstatic_resolved_4);
+		break;
+
+	      case 8:
+	        PUSHL(*field->u.long_addr);
+		newinsn = AMPAMP (getstatic_resolved_8);
+		break;
+	      }
+	  }
+	else
+	  {
+	    PUSHA(*field->u.object_addr);
+	    newinsn = AMPAMP (getstatic_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].datum = field->u.addr;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    getstatic_resolved_1:
+      PUSHI (*(jbyte *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_char:
+      PUSHI (*(jchar *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_short:
+      PUSHI (*(jshort *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_4:
+      PUSHI (*(jint *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_8:
+      PUSHL (*(jlong *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_obj:
+      PUSHA (*(jobject *) AVAL ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_getfield:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	if ((field->flags & Modifier::STATIC) != 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field is static"));
+
+	jclass type = field->type;
+	jint field_offset = field->u.boffset;
+
+	jobject obj   = POPA();
+	NULLCHECK(obj);
+
+	void *newinsn = NULL;
+	_Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes)
+	      {
+	      case 1:
+	        PUSHI (val->byte_value);
+		newinsn = AMPAMP (getfield_resolved_1);
+		break;
+
+	      case 2:
+		if (type == JvPrimClass (char))
+		  {
+		    PUSHI (val->char_value);
+		    newinsn = AMPAMP (getfield_resolved_char);
+		  }
+		else
+		  {
+		    PUSHI (val->short_value);
+		    newinsn = AMPAMP (getfield_resolved_short);
+		  }
+		break;
+
+	      case 4:
+		PUSHI (val->int_value);
+		newinsn = AMPAMP (getfield_resolved_4);
+		break;
+
+	      case 8:
+	        PUSHL (val->long_value);
+		newinsn = AMPAMP (getfield_resolved_8);
+		break;
+	      }
+	  }
+	else
+	  {
+	    PUSHA (val->object_value);
+	    newinsn = AMPAMP (getfield_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].int_val = field_offset;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    getfield_resolved_1:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jbyte *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_char:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jchar *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_short:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jshort *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_4:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jint *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_8:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHL (*(jlong *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_obj:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHA (*(jobject *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_putstatic:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	jclass type = field->type;
+
+	// ResolvePoolEntry cannot check this
+	if ((field->flags & Modifier::STATIC) == 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field no longer static"));
+
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes) 
+	      {
+	      case 1:
+		{
+		  jint value = POPI();
+		  *field->u.byte_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_1);
+		  break;
+		}
+
+	      case 2:
+		{
+		  jint value = POPI();
+		  *field->u.char_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_2);
+		  break;
+		}
+
+	      case 4:
+		{
+		  jint value = POPI();
+		  *field->u.int_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_4);
+		  break;
+		}
+
+	      case 8:
+		{
+		  jlong value = POPL();
+		  *field->u.long_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_8);
+		  break;
+		}
+	      }
+	  }
+	else
+	  {
+	    jobject value = POPA();
+	    *field->u.object_addr = value;
+	    newinsn = AMPAMP (putstatic_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].datum = field->u.addr;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    putstatic_resolved_1:
+      *(jbyte *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_2:
+      *(jchar *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_4:
+      *(jint *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_8:
+      *(jlong *) AVAL () = POPL ();
+      NEXT_INSN;
+
+    putstatic_resolved_obj:
+      *(jobject *) AVAL () = POPA ();
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_putfield:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	jclass type = field->type;
+
+	if ((field->flags & Modifier::STATIC) != 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field is static"));
+
+	jint field_offset = field->u.boffset;
+
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes) 
+	      {
+	      case 1:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jbyte*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_1);
+		  break;
+		}
+
+	      case 2:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jchar*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_2);
+		  break;
+		}
+
+	      case 4:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jint*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_4);
+		  break;
+		}
+
+	      case 8:
+		{
+		  jlong   value = POPL();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jlong*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_8);
+		  break;
+		}
+	      }
+	  }
+	else
+	  {
+	    jobject value = POPA();
+	    jobject obj   = POPA();
+	    NULLCHECK(obj);
+	    *(jobject*) ((char*)obj + field_offset) = value;
+	    newinsn = AMPAMP (putfield_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].int_val = field_offset;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    putfield_resolved_1:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jbyte *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_2:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jchar *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_4:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jint *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_8:
+      {
+	jlong val = POPL ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jlong *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_obj:
+      {
+	jobject val = POPA ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jobject *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_invokespecial:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	// We don't use NULLCHECK here because we can't rely on that
+	// working for <init>.  So instead we do an explicit test.
+	if (! sp[0].o)
+	  {
+	    SAVE_PC();
+	    throw_null_pointer_exception ();
+	  }
+
+	fun = (void (*)()) rmeth->method->ncode;
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokespecial_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokespecial_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	// We don't use NULLCHECK here because we can't rely on that
+	// working for <init>.  So instead we do an explicit test.
+	if (! sp[0].o)
+	  {
+	    throw_null_pointer_exception ();
+	  }
+	fun = (void (*)()) rmeth->method->ncode;
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_invokestatic:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	fun = (void (*)()) rmeth->method->ncode;
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokestatic_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokestatic_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	fun = (void (*)()) rmeth->method->ncode;
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_invokeinterface:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	jobject rcv = sp[0].o;
+
+	NULLCHECK (rcv);
+
+	fun = (void (*)())
+	  _Jv_LookupInterfaceMethod (rcv->getClass (),
+				     rmeth->method->name,
+				     rmeth->method->signature);
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokeinterface_resolved;
+	pc[-1].datum = rmeth;
+#else
+	// Skip dummy bytes.
+	pc += 2;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokeinterface_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	jobject rcv = sp[0].o;
+	NULLCHECK (rcv);
+	fun = (void (*)())
+	  _Jv_LookupInterfaceMethod (rcv->getClass (),
+				     rmeth->method->name,
+				     rmeth->method->signature);
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_new:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+							  index)).clazz;
+	/* VM spec, section 3.11.5 */
+	if ((klass->getModifiers() & Modifier::ABSTRACT)
+	    || klass->isInterface())
+	  throw new java::lang::InstantiationException;
+	jobject res = _Jv_AllocObject (klass);
+	PUSHA (res);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&new_resolved;
+	pc[-1].datum = klass;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    new_resolved:
+      {
+	jclass klass = (jclass) AVAL ();
+	jobject res = _Jv_AllocObject (klass);
+	PUSHA (res);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_newarray:
+      {
+	int atype = GET1U ();
+	int size  = POPI();
+	jobject result = _Jv_NewArray (atype, size);
+	PUSHA (result);
+      }
+      NEXT_INSN;
+
+    insn_anewarray:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+							  index)).clazz;
+	int size  = POPI();
+	jobject result = _Jv_NewObjectArray (size, klass, 0);
+	PUSHA (result);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&anewarray_resolved;
+	pc[-1].datum = klass;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    anewarray_resolved:
+      {
+	jclass klass = (jclass) AVAL ();
+	int size = POPI ();
+	jobject result = _Jv_NewObjectArray (size, klass, 0);
+	PUSHA (result);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_arraylength:
+      {
+	__JArray *arr = (__JArray*)POPA();
+	NULLARRAYCHECK (arr);
+	PUSHI (arr->length);
+      }
+      NEXT_INSN;
+
+    insn_athrow:
+      {
+	jobject value = POPA();
+	throw static_cast<jthrowable>(value);
+      }
+      NEXT_INSN;
+
+    insn_checkcast:
+      {
+        SAVE_PC();
+	jobject value = POPA();
+	jint index = GET2U ();
+	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						       index)).clazz;
+
+	value = (jobject) _Jv_CheckCast (to, value);
+
+	PUSHA (value);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&checkcast_resolved;
+	pc[-1].datum = to;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    checkcast_resolved:
+      {
+        SAVE_PC();
+	jobject value = POPA ();
+	jclass to = (jclass) AVAL ();
+	value = (jobject) _Jv_CheckCast (to, value);
+	PUSHA (value);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_instanceof:
+      {
+        SAVE_PC();
+	jobject value = POPA();
+	jint index = GET2U ();
+	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						       index)).clazz;
+	PUSHI (to->isInstance (value));
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&instanceof_resolved;
+	pc[-1].datum = to;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    instanceof_resolved:
+      {
+	jobject value = POPA ();
+	jclass to = (jclass) AVAL ();
+	PUSHI (to->isInstance (value));
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_monitorenter:
+      {
+	jobject value = POPA();
+	NULLCHECK(value);
+	_Jv_MonitorEnter (value);
+      }
+      NEXT_INSN;
+
+    insn_monitorexit:
+      {
+	jobject value = POPA();
+	NULLCHECK(value);
+	_Jv_MonitorExit (value);
+      }
+      NEXT_INSN;
+
+    insn_ifnull:
+      {
+	jobject val = POPA();
+	if (val == NULL)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifnonnull:
+      {
+	jobject val = POPA();
+	if (val != NULL)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_multianewarray:
+      {
+	SAVE_PC();
+	int kind_index = GET2U ();
+	int dim        = GET1U ();
+
+	jclass type    
+	  = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+					       kind_index)).clazz;
+	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
+
+	for (int i = dim - 1; i >= 0; i--)
+	  {
+	    sizes[i] = POPI ();
+	  }
+
+	jobject res    = _Jv_NewMultiArray (type,dim, sizes);
+
+	PUSHA (res);
+      }
+      NEXT_INSN;
+
+#ifndef DIRECT_THREADED
+    insn_wide:
+      {
+	jint the_mod_op = get1u (pc++);
+	jint wide       = get2u (pc); pc += 2;
+
+	switch (the_mod_op)
+	  {
+	  case op_istore:
+	    STOREI (wide);
+	    NEXT_INSN;
+
+	  case op_fstore:
+	    STOREF (wide);
+	    NEXT_INSN;
+
+	  case op_astore:
+	    STOREA (wide);
+	    NEXT_INSN;
+
+	  case op_lload:
+	    LOADL (wide);
+	    NEXT_INSN;
+
+	  case op_dload:
+	    LOADD (wide);
+	    NEXT_INSN;
+
+	  case op_iload:
+	    LOADI (wide);
+	    NEXT_INSN;
+
+	  case op_fload:
+	    LOADF (wide);
+	    NEXT_INSN;
+
+	  case op_aload:
+	    LOADA (wide);
+	    NEXT_INSN;
+
+	  case op_lstore:
+	    STOREL (wide);
+	    NEXT_INSN;
+
+	  case op_dstore:
+	    STORED (wide);
+	    NEXT_INSN;
+
+	  case op_ret:
+	    pc = (unsigned char*) PEEKA (wide);
+	    NEXT_INSN;
+
+	  case op_iinc:
+	    {
+	      jint amount = get2s (pc); pc += 2;
+	      jint value = PEEKI (wide);
+	      POKEI (wide, value+amount);
+	    }
+	    NEXT_INSN;
+
+	  default:
+	    throw_internal_error ("illegal bytecode modified by wide");
+	  }
+
+      }
+#endif /* DIRECT_THREADED */
+    }
+  catch (java::lang::Throwable *ex)
+    {
+#ifdef DIRECT_THREADED
+      void *logical_pc = (void *) ((insn_slot *) pc - 1);
+#else
+      int logical_pc = pc - 1 - bytecode ();
+#endif
+      _Jv_InterpException *exc = meth->exceptions ();
+      jclass exc_class = ex->getClass ();
+
+      for (int i = 0; i < meth->exc_count; i++)
+	{
+	  if (PCVAL (exc[i].start_pc) <= logical_pc
+	      && logical_pc < PCVAL (exc[i].end_pc))
+	    {
+#ifdef DIRECT_THREADED
+	      jclass handler = (jclass) exc[i].handler_type.p;
+#else
+	      jclass handler = NULL;
+	      if (exc[i].handler_type.i != 0)
+		handler = (_Jv_Linker::resolve_pool_entry (defining_class,
+							     exc[i].handler_type.i)).clazz;
+#endif /* DIRECT_THREADED */
+
+	      if (handler == NULL || handler->isAssignableFrom (exc_class))
+		{
+#ifdef DIRECT_THREADED
+		  pc = (insn_slot *) exc[i].handler_pc.p;
+#else
+		  pc = bytecode () + exc[i].handler_pc.i;
+#endif /* DIRECT_THREADED */
+		  sp = stack;
+		  sp++->o = ex; // Push exception.
+		  NEXT_INSN;
+		}
+	    }
+	}
+
+      // No handler, so re-throw.
+      throw ex;
+    }
Index: /notnfs/kgallowa/vanilla/libjava/interpret.cc
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/interpret.cc	(revision 115793)
+++ /notnfs/kgallowa/vanilla/libjava/interpret.cc	(working copy)
@@ -152,18 +152,36 @@
 # define LOADD(I)  LOADL(I)
 #endif
 
-#define STOREA(I) locals[I].o = (--sp)->o
-#define STOREI(I) locals[I].i = (--sp)->i
-#define STOREF(I) locals[I].f = (--sp)->f
+#define STOREA(I) 		\
+DEBUG_LOCALS_INSN(I,o)	\
+locals[I].o = (--sp)->o
+#define STOREI(I) 		\
+DEBUG_LOCALS_INSN (I,i)	\
+locals[I].i = (--sp)->i
+#define STOREF(I)  		\
+DEBUG_LOCALS_INSN (I,f)	\
+locals[I].f = (--sp)->f
 #if SIZEOF_VOID_P == 8
-# define STOREL(I) (sp -= 2, locals[I].l = sp->l)
-# define STORED(I) (sp -= 2, locals[I].d = sp->d)
+# define STOREL(I)  			\
+DEBUG_LOCALS_INSN (I,l)			\
+(sp -= 2, locals[I].l = sp->l)
+# define STORED(I) 				\
+DEBUG_LOCALS_INSN (I,d)			\
+(sp -= 2, locals[I].d = sp->d)
+
 #else
-# define STOREL(I) do { jint __idx = (I); \
-    		       locals[__idx+1].ia[0] = (--sp)->ia[0]; \
-    		       locals[__idx].ia[0] = (--sp)->ia[0]; \
-		   } while (0)
-# define STORED(I) STOREL(I)
+# define STOREL(I)		\
+DEBUG_LOCALS_INSN(I,m)	\
+do { jint __idx = (I); 	\
+     locals[__idx+1].ia[0] = (--sp)->ia[0]; \
+     locals[__idx].ia[0] = (--sp)->ia[0]; 	\
+   } while (0)
+# define STORED(I)		\
+DEBUG_LOCALS_INSN(I,e)	\
+do { jint __idx = (I); 	\
+     locals[__idx+1].ia[0] = (--sp)->ia[0]; \
+     locals[__idx].ia[0] = (--sp)->ia[0]; 	\
+   } while (0)
 #endif
 
 #define PEEKI(I)  (locals+(I))->i
@@ -169,7 +187,9 @@
 #define PEEKI(I)  (locals+(I))->i
 #define PEEKA(I)  (locals+(I))->o
 
-#define POKEI(I,V)  ((locals+(I))->i = (V))
+#define POKEI(I,V)  	\
+DEBUG_LOCALS_INSN(I,i)	\
+((locals+(I))->i = (V))
 
 
 #define BINOPI(OP) { \
@@ -247,6 +267,8 @@
     }									      \
   while (0)
 
+void (*_Jv_InterpMethod::run) (void *, ffi_raw *, _Jv_InterpMethod *) = NULL;
+
 void
 _Jv_InterpMethod::run_normal (ffi_cif *,
 			      void* ret,
@@ -803,2773 +825,305 @@
 /* Run the given method.
    When args is NULL, don't run anything -- just compile it. */
 void
-_Jv_InterpMethod::run (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
+_Jv_InterpMethod::run_no_debug (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
 {
-  using namespace java::lang::reflect;
+#undef DEBUG
+#undef DEBUG_LOCALS_INSN
+#define DEBUG_LOCALS_INSN(s,t) {}
 
-  // FRAME_DESC registers this particular invocation as the top-most
-  // interpreter frame.  This lets the stack tracing code (for
-  // Throwable) print information about the method being interpreted
-  // rather than about the interpreter itself.  FRAME_DESC has a
-  // destructor so it cleans up automatically when the interpreter
-  // returns.
-  java::lang::Thread *thread = java::lang::Thread::currentThread();
-  _Jv_InterpFrame frame_desc (meth, thread);
+#include "interpret-run.cc"
+}
 
-  _Jv_word stack[meth->max_stack];
-  _Jv_word *sp = stack;
+void
+_Jv_InterpMethod::run_debug (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
+{
+/* Used to keep track of local variable type
+ * 
+ * Possible Types:
+ * o object
+ * i integer
+ * f float
+ * l long (one slot)
+ * m long (two slots)
+ * d double (one slot)
+ * e double (two slots)
+ */
+#define DEBUG
+#undef DEBUG_LOCALS_INSN
+#define DEBUG_LOCALS_INSN(s,t) { localsType[s] = 't'; }
 
-  _Jv_word locals[meth->max_locals];
+#include "interpret-run.cc"
+}
 
-#define INSN_LABEL(op) &&insn_##op
+static void
+throw_internal_error (const char *msg)
+{
+  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
+}
 
-  static const void *const insn_target[] = 
-  {
-    INSN_LABEL(nop),
-    INSN_LABEL(aconst_null),
-    INSN_LABEL(iconst_m1),
-    INSN_LABEL(iconst_0),
-    INSN_LABEL(iconst_1),
-    INSN_LABEL(iconst_2),
-    INSN_LABEL(iconst_3),
-    INSN_LABEL(iconst_4),
-    INSN_LABEL(iconst_5),
-    INSN_LABEL(lconst_0),
-    INSN_LABEL(lconst_1),
-    INSN_LABEL(fconst_0),
-    INSN_LABEL(fconst_1),
-    INSN_LABEL(fconst_2),
-    INSN_LABEL(dconst_0),
-    INSN_LABEL(dconst_1),
-    INSN_LABEL(bipush),
-    INSN_LABEL(sipush),
-    INSN_LABEL(ldc),
-    INSN_LABEL(ldc_w),
-    INSN_LABEL(ldc2_w),
-    INSN_LABEL(iload),
-    INSN_LABEL(lload),
-    INSN_LABEL(fload),
-    INSN_LABEL(dload),
-    INSN_LABEL(aload),
-    INSN_LABEL(iload_0),
-    INSN_LABEL(iload_1),
-    INSN_LABEL(iload_2),
-    INSN_LABEL(iload_3),
-    INSN_LABEL(lload_0),
-    INSN_LABEL(lload_1),
-    INSN_LABEL(lload_2),
-    INSN_LABEL(lload_3),
-    INSN_LABEL(fload_0),
-    INSN_LABEL(fload_1),
-    INSN_LABEL(fload_2),
-    INSN_LABEL(fload_3),
-    INSN_LABEL(dload_0),
-    INSN_LABEL(dload_1),
-    INSN_LABEL(dload_2),
-    INSN_LABEL(dload_3),
-    INSN_LABEL(aload_0),
-    INSN_LABEL(aload_1),
-    INSN_LABEL(aload_2),
-    INSN_LABEL(aload_3),
-    INSN_LABEL(iaload),
-    INSN_LABEL(laload),
-    INSN_LABEL(faload),
-    INSN_LABEL(daload),
-    INSN_LABEL(aaload),
-    INSN_LABEL(baload),
-    INSN_LABEL(caload),
-    INSN_LABEL(saload),
-    INSN_LABEL(istore),
-    INSN_LABEL(lstore),
-    INSN_LABEL(fstore),
-    INSN_LABEL(dstore),
-    INSN_LABEL(astore),
-    INSN_LABEL(istore_0),
-    INSN_LABEL(istore_1),
-    INSN_LABEL(istore_2),
-    INSN_LABEL(istore_3),
-    INSN_LABEL(lstore_0),
-    INSN_LABEL(lstore_1),
-    INSN_LABEL(lstore_2),
-    INSN_LABEL(lstore_3),
-    INSN_LABEL(fstore_0),
-    INSN_LABEL(fstore_1),
-    INSN_LABEL(fstore_2),
-    INSN_LABEL(fstore_3),
-    INSN_LABEL(dstore_0),
-    INSN_LABEL(dstore_1),
-    INSN_LABEL(dstore_2),
-    INSN_LABEL(dstore_3),
-    INSN_LABEL(astore_0),
-    INSN_LABEL(astore_1),
-    INSN_LABEL(astore_2),
-    INSN_LABEL(astore_3),
-    INSN_LABEL(iastore),
-    INSN_LABEL(lastore),
-    INSN_LABEL(fastore),
-    INSN_LABEL(dastore),
-    INSN_LABEL(aastore),
-    INSN_LABEL(bastore),
-    INSN_LABEL(castore),
-    INSN_LABEL(sastore),
-    INSN_LABEL(pop),
-    INSN_LABEL(pop2),
-    INSN_LABEL(dup),
-    INSN_LABEL(dup_x1),
-    INSN_LABEL(dup_x2),
-    INSN_LABEL(dup2),
-    INSN_LABEL(dup2_x1),
-    INSN_LABEL(dup2_x2),
-    INSN_LABEL(swap),
-    INSN_LABEL(iadd),
-    INSN_LABEL(ladd),
-    INSN_LABEL(fadd),
-    INSN_LABEL(dadd),
-    INSN_LABEL(isub),
-    INSN_LABEL(lsub),
-    INSN_LABEL(fsub),
-    INSN_LABEL(dsub),
-    INSN_LABEL(imul),
-    INSN_LABEL(lmul),
-    INSN_LABEL(fmul),
-    INSN_LABEL(dmul),
-    INSN_LABEL(idiv),
-    INSN_LABEL(ldiv),
-    INSN_LABEL(fdiv),
-    INSN_LABEL(ddiv),
-    INSN_LABEL(irem),
-    INSN_LABEL(lrem),
-    INSN_LABEL(frem),
-    INSN_LABEL(drem),
-    INSN_LABEL(ineg),
-    INSN_LABEL(lneg),
-    INSN_LABEL(fneg),
-    INSN_LABEL(dneg),
-    INSN_LABEL(ishl),
-    INSN_LABEL(lshl),
-    INSN_LABEL(ishr),
-    INSN_LABEL(lshr),
-    INSN_LABEL(iushr),
-    INSN_LABEL(lushr),
-    INSN_LABEL(iand),
-    INSN_LABEL(land),
-    INSN_LABEL(ior),
-    INSN_LABEL(lor),
-    INSN_LABEL(ixor),
-    INSN_LABEL(lxor),
-    INSN_LABEL(iinc),
-    INSN_LABEL(i2l),
-    INSN_LABEL(i2f),
-    INSN_LABEL(i2d),
-    INSN_LABEL(l2i),
-    INSN_LABEL(l2f),
-    INSN_LABEL(l2d),
-    INSN_LABEL(f2i),
-    INSN_LABEL(f2l),
-    INSN_LABEL(f2d),
-    INSN_LABEL(d2i),
-    INSN_LABEL(d2l),
-    INSN_LABEL(d2f),
-    INSN_LABEL(i2b),
-    INSN_LABEL(i2c),
-    INSN_LABEL(i2s),
-    INSN_LABEL(lcmp),
-    INSN_LABEL(fcmpl),
-    INSN_LABEL(fcmpg),
-    INSN_LABEL(dcmpl),
-    INSN_LABEL(dcmpg),
-    INSN_LABEL(ifeq),
-    INSN_LABEL(ifne),
-    INSN_LABEL(iflt),
-    INSN_LABEL(ifge),
-    INSN_LABEL(ifgt),
-    INSN_LABEL(ifle),
-    INSN_LABEL(if_icmpeq),
-    INSN_LABEL(if_icmpne),
-    INSN_LABEL(if_icmplt),
-    INSN_LABEL(if_icmpge),
-    INSN_LABEL(if_icmpgt),
-    INSN_LABEL(if_icmple),
-    INSN_LABEL(if_acmpeq),
-    INSN_LABEL(if_acmpne),
-    INSN_LABEL(goto), 
-    INSN_LABEL(jsr),
-    INSN_LABEL(ret),
-    INSN_LABEL(tableswitch),
-    INSN_LABEL(lookupswitch),
-    INSN_LABEL(ireturn),
-    INSN_LABEL(lreturn),
-    INSN_LABEL(freturn),
-    INSN_LABEL(dreturn),
-    INSN_LABEL(areturn),
-    INSN_LABEL(return),
-    INSN_LABEL(getstatic),
-    INSN_LABEL(putstatic),
-    INSN_LABEL(getfield),
-    INSN_LABEL(putfield),
-    INSN_LABEL(invokevirtual),
-    INSN_LABEL(invokespecial),
-    INSN_LABEL(invokestatic),
-    INSN_LABEL(invokeinterface),
-    0, /* Unused.  */
-    INSN_LABEL(new),
-    INSN_LABEL(newarray),
-    INSN_LABEL(anewarray),
-    INSN_LABEL(arraylength),
-    INSN_LABEL(athrow),
-    INSN_LABEL(checkcast),
-    INSN_LABEL(instanceof),
-    INSN_LABEL(monitorenter),
-    INSN_LABEL(monitorexit),
-#ifdef DIRECT_THREADED
-    0, // wide
-#else
-    INSN_LABEL(wide),
-#endif
-    INSN_LABEL(multianewarray),
-    INSN_LABEL(ifnull),
-    INSN_LABEL(ifnonnull),
-    INSN_LABEL(goto_w),
-    INSN_LABEL(jsr_w),
-#ifdef DIRECT_THREADED
-    INSN_LABEL (ldc_class)
-#else
-    0
-#endif
-  };
+static void 
+throw_incompatible_class_change_error (jstring msg)
+{
+  throw new java::lang::IncompatibleClassChangeError (msg);
+}
 
-  pc_t pc;
+static void 
+throw_null_pointer_exception ()
+{
+  throw new java::lang::NullPointerException;
+}
 
-#ifdef DIRECT_THREADED
+/* Look up source code line number for given bytecode (or direct threaded
+   interpreter) PC. */
+int
+_Jv_InterpMethod::get_source_line(pc_t mpc)
+{
+  int line = line_table_len > 0 ? line_table[0].line : -1;
+  for (int i = 1; i < line_table_len; i++)
+    if (line_table[i].pc > mpc)
+      break;
+    else
+      line = line_table[i].line;
 
-#define NEXT_INSN goto *((pc++)->insn)
-#define INTVAL() ((pc++)->int_val)
-#define AVAL() ((pc++)->datum)
+  return line;
+}
 
-#define GET1S() INTVAL ()
-#define GET2S() INTVAL ()
-#define GET1U() INTVAL ()
-#define GET2U() INTVAL ()
-#define AVAL1U() AVAL ()
-#define AVAL2U() AVAL ()
-#define AVAL2UP() AVAL ()
-#define SKIP_GOTO ++pc
-#define GOTO_VAL() (insn_slot *) pc->datum
-#define PCVAL(unionval) unionval.p
-#define AMPAMP(label) &&label
+/** Do static initialization for fields with a constant initializer */
+void
+_Jv_InitField (jobject obj, jclass klass, int index)
+{
+  using namespace java::lang::reflect;
 
-  // Compile if we must. NOTE: Double-check locking.
-  if (meth->prepared == NULL)
-    {
-      _Jv_MutexLock (&compile_mutex);
-      if (meth->prepared == NULL)
-	meth->compile (insn_target);
-      _Jv_MutexUnlock (&compile_mutex);
-    }
+  if (obj != 0 && klass == 0)
+    klass = obj->getClass ();
 
-  // If we're only compiling, stop here
-  if (args == NULL)
+  if (!_Jv_IsInterpretedClass (klass))
     return;
 
-  pc = (insn_slot *) meth->prepared;
-
-#else
+  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
 
-#define NEXT_INSN goto *(insn_target[*pc++])
+  _Jv_Field * field = (&klass->fields[0]) + index;
 
-#define GET1S() get1s (pc++)
-#define GET2S() (pc += 2, get2s (pc- 2))
-#define GET1U() get1u (pc++)
-#define GET2U() (pc += 2, get2u (pc - 2))
-  // Note that these could be more efficient when not handling 'ldc
-  // class'.
-#define AVAL1U()						\
-  ({ int index = get1u (pc++);					\
-      resolve_pool_entry (meth->defining_class, index).o; })
-#define AVAL2U()						\
-  ({ int index = get2u (pc); pc += 2;				\
-      resolve_pool_entry (meth->defining_class, index).o; })
-  // Note that we don't need to resolve the pool entry here as class
-  // constants are never wide.
-#define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
-#define SKIP_GOTO pc += 2
-#define GOTO_VAL() pc - 1 + get2s (pc)
-#define PCVAL(unionval) unionval.i
-#define AMPAMP(label) NULL
+  if (index > klass->field_count)
+    throw_internal_error ("field out of range");
 
-  pc = bytecode ();
+  int init = iclass->field_initializers[index];
+  if (init == 0)
+    return;
 
-#endif /* DIRECT_THREADED */
+  _Jv_Constants *pool = &klass->constants;
+  int tag = pool->tags[init];
 
-#define TAKE_GOTO pc = GOTO_VAL ()
+  if (! field->isResolved ())
+    throw_internal_error ("initializing unresolved field");
 
-  /* Go straight at it!  the ffi raw format matches the internal
-     stack representation exactly.  At least, that's the idea.
-  */
-  memcpy ((void*) locals, (void*) args, meth->args_raw_size);
+  if (obj==0 && ((field->flags & Modifier::STATIC) == 0))
+    throw_internal_error ("initializing non-static field with no object");
 
-  _Jv_word *pool_data = meth->defining_class->constants.data;
+  void *addr = 0;
 
-  /* These three are temporaries for common code used by several
-     instructions.  */
-  void (*fun)();
-  _Jv_ResolvedMethod* rmeth;
-  int tmpval;
+  if ((field->flags & Modifier::STATIC) != 0)
+    addr = (void*) field->u.addr;
+  else
+    addr = (void*) (((char*)obj) + field->u.boffset);
 
-  try
+  switch (tag)
     {
-      // We keep nop around.  It is used if we're interpreting the
-      // bytecodes and not doing direct threading.
-    insn_nop:
-      NEXT_INSN;
-
-      /* The first few instructions here are ordered according to their
-	 frequency, in the hope that this will improve code locality a
-	 little.  */
-
-    insn_aload_0:		// 0x2a
-      LOADA (0);
-      NEXT_INSN;
+    case JV_CONSTANT_String:
+      {
+	jstring str;
+	str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
+	pool->data[init].string = str;
+	pool->tags[init] = JV_CONSTANT_ResolvedString;
+      }
+      /* fall through */
 
-    insn_iload:		// 0x15
-      LOADI (GET1U ());
-      NEXT_INSN;
+    case JV_CONSTANT_ResolvedString:
+      if (! (field->type == &java::lang::String::class$
+ 	     || field->type == &java::lang::Class::class$))
+	throw_class_format_error ("string initialiser to non-string field");
 
-    insn_iload_1:		// 0x1b
-      LOADI (1);
-      NEXT_INSN;
+      *(jstring*)addr = pool->data[init].string;
+      break;
 
-    insn_invokevirtual:	// 0xb6
+    case JV_CONSTANT_Integer:
       {
-	SAVE_PC();
-	int index = GET2U ();
+	int value = pool->data[init].i;
 
-	/* _Jv_Linker::resolve_pool_entry returns immediately if the
-	 * value already is resolved.  If we want to clutter up the
-	 * code here to gain a little performance, then we can check
-	 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
-	 * directly.  For now, I don't think it is worth it.  */
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
+	if (field->type == JvPrimClass (boolean))
+	  *(jboolean*)addr = (jboolean)value;
+	
+	else if (field->type == JvPrimClass (byte))
+	  *(jbyte*)addr = (jbyte)value;
+	
+	else if (field->type == JvPrimClass (char))
+	  *(jchar*)addr = (jchar)value;
 
-	if (rmeth->method->accflags & Modifier::FINAL)
-	  {
-	    // We can't rely on NULLCHECK working if the method is final.
-	    if (! sp[0].o)
-	      throw_null_pointer_exception ();
+	else if (field->type == JvPrimClass (short))
+	  *(jshort*)addr = (jshort)value;
+	
+	else if (field->type == JvPrimClass (int))
+	  *(jint*)addr = (jint)value;
 
-	    // Final methods might not appear in the vtable.
-	    fun = (void (*)()) rmeth->method->ncode;
-	  }
 	else
-	  {
-	    NULLCHECK (sp[0].o);
-	    jobject rcv = sp[0].o;
-	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
-	    fun = (void (*)()) table->get_method (rmeth->method->index);
-	  }
+	  throw_class_format_error ("erroneous field initializer");
+      }  
+      break;
 
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokevirtual_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
+    case JV_CONSTANT_Long:
+      if (field->type != JvPrimClass (long))
+	throw_class_format_error ("erroneous field initializer");
 
-#ifdef DIRECT_THREADED
-    invokevirtual_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
+      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
+      break;
 
-	if (rmeth->method->accflags & Modifier::FINAL)
-	  {
-	    // We can't rely on NULLCHECK working if the method is final.
-	    if (! sp[0].o)
-	      throw_null_pointer_exception ();
+    case JV_CONSTANT_Float:
+      if (field->type != JvPrimClass (float))
+	throw_class_format_error ("erroneous field initializer");
 
-	    // Final methods might not appear in the vtable.
-	    fun = (void (*)()) rmeth->method->ncode;
-	  }
-	else
-	  {
-	    jobject rcv = sp[0].o;
-	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
-	    fun = (void (*)()) table->get_method (rmeth->method->index);
-	  }
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
+      *(jfloat*)addr = pool->data[init].f;
+      break;
 
-    perform_invoke:
-      {
-	/* here goes the magic again... */
-	ffi_cif *cif = &rmeth->cif;
-	ffi_raw *raw = (ffi_raw*) sp;
+    case JV_CONSTANT_Double:
+      if (field->type != JvPrimClass (double))
+	throw_class_format_error ("erroneous field initializer");
 
-	_Jv_value rvalue;
+      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
+      break;
 
-#if FFI_NATIVE_RAW_API
-	/* We assume that this is only implemented if it's correct	*/
-	/* to use it here.  On a 64 bit machine, it never is.		*/
-	ffi_raw_call (cif, fun, (void*)&rvalue, raw);
-#else
-	ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
-#endif
+    default:
+      throw_class_format_error ("erroneous field initializer");
+    }
+}
 
-	int rtype = cif->rtype->type;
+inline static unsigned char*
+skip_one_type (unsigned char* ptr)
+{
+  int ch = *ptr++;
 
-	/* the likelyhood of object, int, or void return is very high,
-	 * so those are checked before the switch */
-	if (rtype == FFI_TYPE_POINTER)
-	  {
-	    PUSHA (rvalue.object_value);
-	  }
-	else if (rtype == FFI_TYPE_SINT32)
-	  {
-	    PUSHI (rvalue.int_value);
-	  }
-	else if (rtype == FFI_TYPE_VOID)
-	  {
-	    /* skip */
-	  }
-	else
-	  {
-	    switch (rtype)
-	      {
-	      case FFI_TYPE_SINT8:
-		PUSHI ((jbyte)(rvalue.int_value & 0xff));
-		break;
+  while (ch == '[')
+    { 
+      ch = *ptr++;
+    }
+  
+  if (ch == 'L')
+    {
+      do { ch = *ptr++; } while (ch != ';');
+    }
 
-	      case FFI_TYPE_SINT16:
-		PUSHI ((jshort)(rvalue.int_value & 0xffff));
-		break;
+  return ptr;
+}
 
-	      case FFI_TYPE_UINT16:
-		PUSHI (rvalue.int_value & 0xffff);
-		break;
+static ffi_type*
+get_ffi_type_from_signature (unsigned char* ptr)
+{
+  switch (*ptr) 
+    {
+    case 'L':
+    case '[':
+      return &ffi_type_pointer;
+      break;
 
-	      case FFI_TYPE_FLOAT:
-	        PUSHF (rvalue.float_value);
-		break;
+    case 'Z':
+      // On some platforms a bool is a byte, on others an int.
+      if (sizeof (jboolean) == sizeof (jbyte))
+	return &ffi_type_sint8;
+      else
+	{
+	  JvAssert (sizeof (jbyte) == sizeof (jint));
+	  return &ffi_type_sint32;
+	}
+      break;
 
-	      case FFI_TYPE_DOUBLE:
-	        PUSHD (rvalue.double_value);
-		break;
+    case 'B':
+      return &ffi_type_sint8;
+      break;
+      
+    case 'C':
+      return &ffi_type_uint16;
+      break;
+	  
+    case 'S': 
+      return &ffi_type_sint16;
+      break;
+	  
+    case 'I':
+      return &ffi_type_sint32;
+      break;
+	  
+    case 'J':
+      return &ffi_type_sint64;
+      break;
+	  
+    case 'F':
+      return &ffi_type_float;
+      break;
+	  
+    case 'D':
+      return &ffi_type_double;
+      break;
 
-	      case FFI_TYPE_SINT64:
-	        PUSHL (rvalue.long_value);
-		break;
+    case 'V':
+      return &ffi_type_void;
+      break;
+    }
 
-	      default:
-		throw_internal_error ("unknown return type in invokeXXX");
-	      }
-	  }
-      }
-      NEXT_INSN;
+  throw_internal_error ("unknown type in signature");
+}
 
-    insn_aconst_null:
-      PUSHA (NULL);
-      NEXT_INSN;
+/* this function yields the number of actual arguments, that is, if the
+ * function is non-static, then one is added to the number of elements
+ * found in the signature */
 
-    insn_iconst_m1:
-      PUSHI (-1);
-      NEXT_INSN;
+int 
+_Jv_count_arguments (_Jv_Utf8Const *signature,
+		     jboolean staticp)
+{
+  unsigned char *ptr = (unsigned char*) signature->chars();
+  int arg_count = staticp ? 0 : 1;
 
-    insn_iconst_0:
-      PUSHI (0);
-      NEXT_INSN;
+  /* first, count number of arguments */
 
-    insn_iconst_1:
-      PUSHI (1);
-      NEXT_INSN;
+  // skip '('
+  ptr++;
 
-    insn_iconst_2:
-      PUSHI (2);
-      NEXT_INSN;
+  // count args
+  while (*ptr != ')')
+    {
+      ptr = skip_one_type (ptr);
+      arg_count += 1;
+    }
 
-    insn_iconst_3:
-      PUSHI (3);
-      NEXT_INSN;
+  return arg_count;
+}
 
-    insn_iconst_4:
-      PUSHI (4);
-      NEXT_INSN;
+/* This beast will build a cif, given the signature.  Memory for
+ * the cif itself and for the argument types must be allocated by the
+ * caller.
+ */
 
-    insn_iconst_5:
-      PUSHI (5);
-      NEXT_INSN;
+static int 
+init_cif (_Jv_Utf8Const* signature,
+	  int arg_count,
+	  jboolean staticp,
+	  ffi_cif *cif,
+	  ffi_type **arg_types,
+	  ffi_type **rtype_p)
+{
+  unsigned char *ptr = (unsigned char*) signature->chars();
 
-    insn_lconst_0:
-      PUSHL (0);
-      NEXT_INSN;
+  int arg_index = 0;		// arg number
+  int item_count = 0;		// stack-item count
 
-    insn_lconst_1:
-      PUSHL (1);
-      NEXT_INSN;
+  // setup receiver
+  if (!staticp)
+    {
+      arg_types[arg_index++] = &ffi_type_pointer;
+      item_count += 1;
+    }
 
-    insn_fconst_0:
-      PUSHF (0);
-      NEXT_INSN;
-
-    insn_fconst_1:
-      PUSHF (1);
-      NEXT_INSN;
-
-    insn_fconst_2:
-      PUSHF (2);
-      NEXT_INSN;
-
-    insn_dconst_0:
-      PUSHD (0);
-      NEXT_INSN;
-
-    insn_dconst_1:
-      PUSHD (1);
-      NEXT_INSN;
-
-    insn_bipush:
-      // For direct threaded, bipush and sipush are the same.
-#ifndef DIRECT_THREADED
-      PUSHI (GET1S ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_sipush:
-      PUSHI (GET2S ());
-      NEXT_INSN;
-
-    insn_ldc:
-      // For direct threaded, ldc and ldc_w are the same.
-#ifndef DIRECT_THREADED
-      PUSHA ((jobject) AVAL1U ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_ldc_w:
-      PUSHA ((jobject) AVAL2U ());
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-      // For direct threaded we have a separate 'ldc class' operation.
-    insn_ldc_class:
-      {
-	SAVE_PC();
-	// We could rewrite the instruction at this point.
-	int index = INTVAL ();
-	jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						     index)).o;
-	PUSHA (k);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_ldc2_w:
-      {
-	void *where = AVAL2UP ();
-	memcpy (sp, where, 2*sizeof (_Jv_word));
-	sp += 2;
-      }
-      NEXT_INSN;
-
-    insn_lload:
-      LOADL (GET1U ());
-      NEXT_INSN;
-
-    insn_fload:
-      LOADF (GET1U ());
-      NEXT_INSN;
-
-    insn_dload:
-      LOADD (GET1U ());
-      NEXT_INSN;
-
-    insn_aload:
-      LOADA (GET1U ());
-      NEXT_INSN;
-
-    insn_iload_0:
-      LOADI (0);
-      NEXT_INSN;
-
-    insn_iload_2:
-      LOADI (2);
-      NEXT_INSN;
-
-    insn_iload_3:
-      LOADI (3);
-      NEXT_INSN;
-
-    insn_lload_0:
-      LOADL (0);
-      NEXT_INSN;
-
-    insn_lload_1:
-      LOADL (1);
-      NEXT_INSN;
-
-    insn_lload_2:
-      LOADL (2);
-      NEXT_INSN;
-
-    insn_lload_3:
-      LOADL (3);
-      NEXT_INSN;
-
-    insn_fload_0:
-      LOADF (0);
-      NEXT_INSN;
-
-    insn_fload_1:
-      LOADF (1);
-      NEXT_INSN;
-
-    insn_fload_2:
-      LOADF (2);
-      NEXT_INSN;
-
-    insn_fload_3:
-      LOADF (3);
-      NEXT_INSN;
-
-    insn_dload_0:
-      LOADD (0);
-      NEXT_INSN;
-
-    insn_dload_1:
-      LOADD (1);
-      NEXT_INSN;
-
-    insn_dload_2:
-      LOADD (2);
-      NEXT_INSN;
-
-    insn_dload_3:
-      LOADD (3);
-      NEXT_INSN;
-
-    insn_aload_1:
-      LOADA(1);
-      NEXT_INSN;
-
-    insn_aload_2:
-      LOADA(2);
-      NEXT_INSN;
-
-    insn_aload_3:
-      LOADA(3);
-      NEXT_INSN;
-
-    insn_iaload:
-      {
-	jint index = POPI();
-	jintArray arr = (jintArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_laload:
-      {
-	jint index = POPI();
-	jlongArray arr = (jlongArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHL( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_faload:
-      {
-	jint index = POPI();
-	jfloatArray arr = (jfloatArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHF( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_daload:
-      {
-	jint index = POPI();
-	jdoubleArray arr = (jdoubleArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHD( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_aaload:
-      {
-	jint index = POPI();
-	jobjectArray arr = (jobjectArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHA( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_baload:
-      {
-	jint index = POPI();
-	jbyteArray arr = (jbyteArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_caload:
-      {
-	jint index = POPI();
-	jcharArray arr = (jcharArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_saload:
-      {
-	jint index = POPI();
-	jshortArray arr = (jshortArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_istore:
-      STOREI (GET1U ());
-      NEXT_INSN;
-
-    insn_lstore:
-      STOREL (GET1U ());
-      NEXT_INSN;
-
-    insn_fstore:
-      STOREF (GET1U ());
-      NEXT_INSN;
-
-    insn_dstore:
-      STORED (GET1U ());
-      NEXT_INSN;
-
-    insn_astore:
-      STOREA (GET1U ());
-      NEXT_INSN;
-
-    insn_istore_0:
-      STOREI (0);
-      NEXT_INSN;
-
-    insn_istore_1:
-      STOREI (1);
-      NEXT_INSN;
-
-    insn_istore_2:
-      STOREI (2);
-      NEXT_INSN;
-
-    insn_istore_3:
-      STOREI (3);
-      NEXT_INSN;
-
-    insn_lstore_0:
-      STOREL (0);
-      NEXT_INSN;
-
-    insn_lstore_1:
-      STOREL (1);
-      NEXT_INSN;
-
-    insn_lstore_2:
-      STOREL (2);
-      NEXT_INSN;
-
-    insn_lstore_3:
-      STOREL (3);
-      NEXT_INSN;
-
-    insn_fstore_0:
-      STOREF (0);
-      NEXT_INSN;
-
-    insn_fstore_1:
-      STOREF (1);
-      NEXT_INSN;
-
-    insn_fstore_2:
-      STOREF (2);
-      NEXT_INSN;
-
-    insn_fstore_3:
-      STOREF (3);
-      NEXT_INSN;
-
-    insn_dstore_0:
-      STORED (0);
-      NEXT_INSN;
-
-    insn_dstore_1:
-      STORED (1);
-      NEXT_INSN;
-
-    insn_dstore_2:
-      STORED (2);
-      NEXT_INSN;
-
-    insn_dstore_3:
-      STORED (3);
-      NEXT_INSN;
-
-    insn_astore_0:
-      STOREA(0);
-      NEXT_INSN;
-
-    insn_astore_1:
-      STOREA(1);
-      NEXT_INSN;
-
-    insn_astore_2:
-      STOREA(2);
-      NEXT_INSN;
-
-    insn_astore_3:
-      STOREA(3);
-      NEXT_INSN;
-
-    insn_iastore:
-      {
-	jint value = POPI();
-	jint index  = POPI();
-	jintArray arr = (jintArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_lastore:
-      {
-	jlong value = POPL();
-	jint index  = POPI();
-	jlongArray arr = (jlongArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_fastore:
-      {
-	jfloat value = POPF();
-	jint index  = POPI();
-	jfloatArray arr = (jfloatArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_dastore:
-      {
-	jdouble value = POPD();
-	jint index  = POPI();
-	jdoubleArray arr = (jdoubleArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_aastore:
-      {
-	jobject value = POPA();
-	jint index  = POPI();
-	jobjectArray arr = (jobjectArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	_Jv_CheckArrayStore (arr, value);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_bastore:
-      {
-	jbyte value = (jbyte) POPI();
-	jint index  = POPI();
-	jbyteArray arr = (jbyteArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_castore:
-      {
-	jchar value = (jchar) POPI();
-	jint index  = POPI();
-	jcharArray arr = (jcharArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_sastore:
-      {
-	jshort value = (jshort) POPI();
-	jint index  = POPI();
-	jshortArray arr = (jshortArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_pop:
-      sp -= 1;
-      NEXT_INSN;
-
-    insn_pop2:
-      sp -= 2;
-      NEXT_INSN;
-
-    insn_dup:
-      sp[0] = sp[-1];
-      sp += 1;
-      NEXT_INSN;
-
-    insn_dup_x1:
-      dupx (sp, 1, 1); sp+=1;
-      NEXT_INSN;
-
-    insn_dup_x2:
-      dupx (sp, 1, 2); sp+=1;
-      NEXT_INSN;
-
-    insn_dup2:
-      sp[0] = sp[-2];
-      sp[1] = sp[-1];
-      sp += 2;
-      NEXT_INSN;
-
-    insn_dup2_x1:
-      dupx (sp, 2, 1); sp+=2;
-      NEXT_INSN;
-
-    insn_dup2_x2:
-      dupx (sp, 2, 2); sp+=2;
-      NEXT_INSN;
-
-    insn_swap:
-      {
-	jobject tmp1 = POPA();
-	jobject tmp2 = POPA();
-	PUSHA (tmp1);
-	PUSHA (tmp2);
-      }
-      NEXT_INSN;
-
-    insn_iadd:
-      BINOPI(+);
-      NEXT_INSN;
-
-    insn_ladd:
-      BINOPL(+);
-      NEXT_INSN;
-
-    insn_fadd:
-      BINOPF(+);
-      NEXT_INSN;
-
-    insn_dadd:
-      BINOPD(+);
-      NEXT_INSN;
-
-    insn_isub:
-      BINOPI(-);
-      NEXT_INSN;
-
-    insn_lsub:
-      BINOPL(-);
-      NEXT_INSN;
-
-    insn_fsub:
-      BINOPF(-);
-      NEXT_INSN;
-
-    insn_dsub:
-      BINOPD(-);
-      NEXT_INSN;
-
-    insn_imul:
-      BINOPI(*);
-      NEXT_INSN;
-
-    insn_lmul:
-      BINOPL(*);
-      NEXT_INSN;
-
-    insn_fmul:
-      BINOPF(*);
-      NEXT_INSN;
-
-    insn_dmul:
-      BINOPD(*);
-      NEXT_INSN;
-
-    insn_idiv:
-      {
-	SAVE_PC();
-	jint value2 = POPI();
-	jint value1 = POPI();
-	jint res = _Jv_divI (value1, value2);
-	PUSHI (res);
-      }
-      NEXT_INSN;
-
-    insn_ldiv:
-      {
-	SAVE_PC();
-	jlong value2 = POPL();
-	jlong value1 = POPL();
-	jlong res = _Jv_divJ (value1, value2);
-	PUSHL (res);
-      }
-      NEXT_INSN;
-
-    insn_fdiv:
-      {
-	jfloat value2 = POPF();
-	jfloat value1 = POPF();
-	jfloat res = value1 / value2;
-	PUSHF (res);
-      }
-      NEXT_INSN;
-
-    insn_ddiv:
-      {
-	jdouble value2 = POPD();
-	jdouble value1 = POPD();
-	jdouble res = value1 / value2;
-	PUSHD (res);
-      }
-      NEXT_INSN;
-
-    insn_irem:
-      {
-	SAVE_PC();
-	jint value2 = POPI();
-	jint value1 =  POPI();
-	jint res = _Jv_remI (value1, value2);
-	PUSHI (res);
-      }
-      NEXT_INSN;
-
-    insn_lrem:
-      {
-	SAVE_PC();
-	jlong value2 = POPL();
-	jlong value1 = POPL();
-	jlong res = _Jv_remJ (value1, value2);
-	PUSHL (res);
-      }
-      NEXT_INSN;
-
-    insn_frem:
-      {
-	jfloat value2 = POPF();
-	jfloat value1 = POPF();
-	jfloat res    = __ieee754_fmod (value1, value2);
-	PUSHF (res);
-      }
-      NEXT_INSN;
-
-    insn_drem:
-      {
-	jdouble value2 = POPD();
-	jdouble value1 = POPD();
-	jdouble res    = __ieee754_fmod (value1, value2);
-	PUSHD (res);
-      }
-      NEXT_INSN;
-
-    insn_ineg:
-      {
-	jint value = POPI();
-	PUSHI (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_lneg:
-      {
-	jlong value = POPL();
-	PUSHL (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_fneg:
-      {
-	jfloat value = POPF();
-	PUSHF (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_dneg:
-      {
-	jdouble value = POPD();
-	PUSHD (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_ishl:
-      {
-	jint shift = (POPI() & 0x1f);
-	jint value = POPI();
-	PUSHI (value << shift);
-      }
-      NEXT_INSN;
-
-    insn_lshl:
-      {
-	jint shift = (POPI() & 0x3f);
-	jlong value = POPL();
-	PUSHL (value << shift);
-      }
-      NEXT_INSN;
-
-    insn_ishr:
-      {
-	jint shift = (POPI() & 0x1f);
-	jint value = POPI();
-	PUSHI (value >> shift);
-      }
-      NEXT_INSN;
-
-    insn_lshr:
-      {
-	jint shift = (POPI() & 0x3f);
-	jlong value = POPL();
-	PUSHL (value >> shift);
-      }
-      NEXT_INSN;
-
-    insn_iushr:
-      {
-	jint shift = (POPI() & 0x1f);
-	_Jv_uint value = (_Jv_uint) POPI();
-	PUSHI ((jint) (value >> shift));
-      }
-      NEXT_INSN;
-
-    insn_lushr:
-      {
-	jint shift = (POPI() & 0x3f);
-	_Jv_ulong value = (_Jv_ulong) POPL();
-	PUSHL ((jlong) (value >> shift));
-      }
-      NEXT_INSN;
-
-    insn_iand:
-      BINOPI (&);
-      NEXT_INSN;
-
-    insn_land:
-      BINOPL (&);
-      NEXT_INSN;
-
-    insn_ior:
-      BINOPI (|);
-      NEXT_INSN;
-
-    insn_lor:
-      BINOPL (|);
-      NEXT_INSN;
-
-    insn_ixor:
-      BINOPI (^);
-      NEXT_INSN;
-
-    insn_lxor:
-      BINOPL (^);
-      NEXT_INSN;
-
-    insn_iinc:
-      {
-	jint index  = GET1U ();
-	jint amount = GET1S ();
-	locals[index].i += amount;
-      }
-      NEXT_INSN;
-
-    insn_i2l:
-      {jlong value = POPI(); PUSHL (value);}
-      NEXT_INSN;
-
-    insn_i2f:
-      {jfloat value = POPI(); PUSHF (value);}
-      NEXT_INSN;
-
-    insn_i2d:
-      {jdouble value = POPI(); PUSHD (value);}
-      NEXT_INSN;
-
-    insn_l2i:
-      {jint value = POPL(); PUSHI (value);}
-      NEXT_INSN;
-
-    insn_l2f:
-      {jfloat value = POPL(); PUSHF (value);}
-      NEXT_INSN;
-
-    insn_l2d:
-      {jdouble value = POPL(); PUSHD (value);}
-      NEXT_INSN;
-
-    insn_f2i:
-      {
-	using namespace java::lang;
-	jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
-	PUSHI(value);
-      }
-      NEXT_INSN;
-
-    insn_f2l:
-      {
-	using namespace java::lang;
-	jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
-	PUSHL(value);
-      }
-      NEXT_INSN;
-
-    insn_f2d:
-      { jdouble value = POPF (); PUSHD(value); }
-      NEXT_INSN;
-
-    insn_d2i:
-      {
-	using namespace java::lang;
-	jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
-	PUSHI(value);
-      }
-      NEXT_INSN;
-
-    insn_d2l:
-      {
-	using namespace java::lang;
-	jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
-	PUSHL(value);
-      }
-      NEXT_INSN;
-
-    insn_d2f:
-      { jfloat value = POPD (); PUSHF(value); }
-      NEXT_INSN;
-
-    insn_i2b:
-      { jbyte value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_i2c:
-      { jchar value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_i2s:
-      { jshort value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_lcmp:
-      {
-	jlong value2 = POPL ();
-	jlong value1 = POPL ();
-	if (value1 > value2)
-	  { PUSHI (1); }
-	else if (value1 == value2)
-	  { PUSHI (0); }
-	else
-	  { PUSHI (-1); }
-      }
-      NEXT_INSN;
-
-    insn_fcmpl:
-      tmpval = -1;
-      goto fcmp;
-
-    insn_fcmpg:
-      tmpval = 1;
-
-    fcmp:
-      {
-	jfloat value2 = POPF ();
-	jfloat value1 = POPF ();
-	if (value1 > value2)
-	  PUSHI (1);
-	else if (value1 == value2)
-	  PUSHI (0);
-	else if (value1 < value2)
-	  PUSHI (-1);
-	else
-	  PUSHI (tmpval);
-      }
-      NEXT_INSN;
-
-    insn_dcmpl:
-      tmpval = -1;
-      goto dcmp;
-
-    insn_dcmpg:
-      tmpval = 1;
-
-    dcmp:
-      {
-	jdouble value2 = POPD ();
-	jdouble value1 = POPD ();
-	if (value1 > value2)
-	  PUSHI (1);
-	else if (value1 == value2)
-	  PUSHI (0);
-	else if (value1 < value2)
-	  PUSHI (-1);
-	else
-	  PUSHI (tmpval);
-      }
-      NEXT_INSN;
-
-    insn_ifeq:
-      {
-	if (POPI() == 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifne:
-      {
-	if (POPI() != 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_iflt:
-      {
-	if (POPI() < 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifge:
-      {
-	if (POPI() >= 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifgt:
-      {
-	if (POPI() > 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifle:
-      {
-	if (POPI() <= 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpeq:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 == value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpne:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 != value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmplt:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 < value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpge:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 >= value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpgt:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 > value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmple:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 <= value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_acmpeq:
-      {
-	jobject value2 = POPA();
-	jobject value1 = POPA();
-	if (value1 == value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_acmpne:
-      {
-	jobject value2 = POPA();
-	jobject value1 = POPA();
-	if (value1 != value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_goto_w:
-#ifndef DIRECT_THREADED
-      // For direct threaded, goto and goto_w are the same.
-      pc = pc - 1 + get4 (pc);
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_goto:
-      TAKE_GOTO;
-      NEXT_INSN;
-
-    insn_jsr_w:
-#ifndef DIRECT_THREADED
-      // For direct threaded, jsr and jsr_w are the same.
-      {
-	pc_t next = pc - 1 + get4 (pc);
-	pc += 4;
-	PUSHA ((jobject) pc);
-	pc = next;
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_jsr:
-      {
-	pc_t next = GOTO_VAL();
-	SKIP_GOTO;
-	PUSHA ((jobject) pc);
-	pc = next;
-      }
-      NEXT_INSN;
-
-    insn_ret:
-      {
-	jint index = GET1U ();
-	pc = (pc_t) PEEKA (index);
-      }
-      NEXT_INSN;
-
-    insn_tableswitch:
-      {
-#ifdef DIRECT_THREADED
-	void *def = (pc++)->datum;
-
-	int index = POPI();
-
-	jint low = INTVAL ();
-	jint high = INTVAL ();
-
-	if (index < low || index > high)
-	  pc = (insn_slot *) def;
-	else
-	  pc = (insn_slot *) ((pc + index - low)->datum);
-#else
-	pc_t base_pc = pc - 1;
-	int index = POPI ();
-
-	pc_t base = (pc_t) bytecode ();
-	while ((pc - base) % 4 != 0)
-	  ++pc;
-
-	jint def = get4 (pc);
-	jint low = get4 (pc + 4);
-	jint high = get4 (pc + 8);
-	if (index < low || index > high)
-	  pc = base_pc + def;
-	else
-	  pc = base_pc + get4 (pc + 4 * (index - low + 3));
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-    insn_lookupswitch:
-      {
-#ifdef DIRECT_THREADED
-	void *def = (pc++)->insn;
-
-	int index = POPI();
-
-	jint npairs = INTVAL ();
-
-	int max = npairs - 1;
-	int min = 0;
-
-	// Simple binary search...
-	while (min < max)
-	  {
-	    int half = (min + max) / 2;
-	    int match = pc[2 * half].int_val;
-
-	    if (index == match)
-	      {
-		// Found it.
-		pc = (insn_slot *) pc[2 * half + 1].datum;
-		NEXT_INSN;
-	      }
-	    else if (index < match)
-	      // We can use HALF - 1 here because we check again on
-	      // loop exit.
-	      max = half - 1;
-	    else
-	      // We can use HALF + 1 here because we check again on
-	      // loop exit.
-	      min = half + 1;
-	  }
-	if (index == pc[2 * min].int_val)
-	  pc = (insn_slot *) pc[2 * min + 1].datum;
-	else
-	  pc = (insn_slot *) def;
-#else
-	unsigned char *base_pc = pc-1;
-	int index = POPI();
-
-	unsigned char* base = bytecode ();
-	while ((pc-base) % 4 != 0)
-	  ++pc;
-
-	jint def     = get4 (pc);
-	jint npairs  = get4 (pc+4);
-
-	int max = npairs-1;
-	int min = 0;
-
-	// Simple binary search...
-	while (min < max)
-	  {
-	    int half = (min+max)/2;
-	    int match = get4 (pc+ 4*(2 + 2*half));
-
-	    if (index == match)
-	      min = max = half;
-	    else if (index < match)
-	      // We can use HALF - 1 here because we check again on
-	      // loop exit.
-	      max = half - 1;
-	    else
-	      // We can use HALF + 1 here because we check again on
-	      // loop exit.
-	      min = half + 1;
-	  }
-
-	if (index == get4 (pc+ 4*(2 + 2*min)))
-	  pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
-	else
-	  pc = base_pc + def;    
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-    insn_areturn:
-      *(jobject *) retp = POPA ();
-      return;
-
-    insn_lreturn:
-      *(jlong *) retp = POPL ();
-      return;
-
-    insn_freturn:
-      *(jfloat *) retp = POPF ();
-      return;
-
-    insn_dreturn:
-      *(jdouble *) retp = POPD ();
-      return;
-
-    insn_ireturn:
-      *(jint *) retp = POPI ();
-      return;
-
-    insn_return:
-      return;
-
-    insn_getstatic:
-      {
-	jint fieldref_index = GET2U ();
-        SAVE_PC(); // Constant pool resolution could throw.
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	if ((field->flags & Modifier::STATIC) == 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field no longer static"));
-
-	jclass type = field->type;
-
-	// We rewrite the instruction once we discover what it refers
-	// to.
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes)
-	      {
-	      case 1:
-		PUSHI (*field->u.byte_addr);
-		newinsn = AMPAMP (getstatic_resolved_1);
-		break;
-
-	      case 2:
-		if (type == JvPrimClass (char))
-		  {
-		    PUSHI (*field->u.char_addr);
-		    newinsn = AMPAMP (getstatic_resolved_char);
-		  }
-		else
-		  {
-		    PUSHI (*field->u.short_addr);
-		    newinsn = AMPAMP (getstatic_resolved_short);
-		  }
-		break;
-
-	      case 4:
-	        PUSHI(*field->u.int_addr);
-		newinsn = AMPAMP (getstatic_resolved_4);
-		break;
-
-	      case 8:
-	        PUSHL(*field->u.long_addr);
-		newinsn = AMPAMP (getstatic_resolved_8);
-		break;
-	      }
-	  }
-	else
-	  {
-	    PUSHA(*field->u.object_addr);
-	    newinsn = AMPAMP (getstatic_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].datum = field->u.addr;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    getstatic_resolved_1:
-      PUSHI (*(jbyte *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_char:
-      PUSHI (*(jchar *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_short:
-      PUSHI (*(jshort *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_4:
-      PUSHI (*(jint *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_8:
-      PUSHL (*(jlong *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_obj:
-      PUSHA (*(jobject *) AVAL ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_getfield:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	if ((field->flags & Modifier::STATIC) != 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field is static"));
-
-	jclass type = field->type;
-	jint field_offset = field->u.boffset;
-
-	jobject obj   = POPA();
-	NULLCHECK(obj);
-
-	void *newinsn = NULL;
-	_Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes)
-	      {
-	      case 1:
-	        PUSHI (val->byte_value);
-		newinsn = AMPAMP (getfield_resolved_1);
-		break;
-
-	      case 2:
-		if (type == JvPrimClass (char))
-		  {
-		    PUSHI (val->char_value);
-		    newinsn = AMPAMP (getfield_resolved_char);
-		  }
-		else
-		  {
-		    PUSHI (val->short_value);
-		    newinsn = AMPAMP (getfield_resolved_short);
-		  }
-		break;
-
-	      case 4:
-		PUSHI (val->int_value);
-		newinsn = AMPAMP (getfield_resolved_4);
-		break;
-
-	      case 8:
-	        PUSHL (val->long_value);
-		newinsn = AMPAMP (getfield_resolved_8);
-		break;
-	      }
-	  }
-	else
-	  {
-	    PUSHA (val->object_value);
-	    newinsn = AMPAMP (getfield_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].int_val = field_offset;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    getfield_resolved_1:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jbyte *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_char:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jchar *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_short:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jshort *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_4:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jint *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_8:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHL (*(jlong *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_obj:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHA (*(jobject *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_putstatic:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	jclass type = field->type;
-
-	// ResolvePoolEntry cannot check this
-	if ((field->flags & Modifier::STATIC) == 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field no longer static"));
-
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes) 
-	      {
-	      case 1:
-		{
-		  jint value = POPI();
-		  *field->u.byte_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_1);
-		  break;
-		}
-
-	      case 2:
-		{
-		  jint value = POPI();
-		  *field->u.char_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_2);
-		  break;
-		}
-
-	      case 4:
-		{
-		  jint value = POPI();
-		  *field->u.int_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_4);
-		  break;
-		}
-
-	      case 8:
-		{
-		  jlong value = POPL();
-		  *field->u.long_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_8);
-		  break;
-		}
-	      }
-	  }
-	else
-	  {
-	    jobject value = POPA();
-	    *field->u.object_addr = value;
-	    newinsn = AMPAMP (putstatic_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].datum = field->u.addr;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    putstatic_resolved_1:
-      *(jbyte *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_2:
-      *(jchar *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_4:
-      *(jint *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_8:
-      *(jlong *) AVAL () = POPL ();
-      NEXT_INSN;
-
-    putstatic_resolved_obj:
-      *(jobject *) AVAL () = POPA ();
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_putfield:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	jclass type = field->type;
-
-	if ((field->flags & Modifier::STATIC) != 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field is static"));
-
-	jint field_offset = field->u.boffset;
-
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes) 
-	      {
-	      case 1:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jbyte*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_1);
-		  break;
-		}
-
-	      case 2:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jchar*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_2);
-		  break;
-		}
-
-	      case 4:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jint*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_4);
-		  break;
-		}
-
-	      case 8:
-		{
-		  jlong   value = POPL();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jlong*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_8);
-		  break;
-		}
-	      }
-	  }
-	else
-	  {
-	    jobject value = POPA();
-	    jobject obj   = POPA();
-	    NULLCHECK(obj);
-	    *(jobject*) ((char*)obj + field_offset) = value;
-	    newinsn = AMPAMP (putfield_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].int_val = field_offset;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    putfield_resolved_1:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jbyte *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_2:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jchar *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_4:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jint *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_8:
-      {
-	jlong val = POPL ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jlong *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_obj:
-      {
-	jobject val = POPA ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jobject *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_invokespecial:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	// We don't use NULLCHECK here because we can't rely on that
-	// working for <init>.  So instead we do an explicit test.
-	if (! sp[0].o)
-	  {
-	    SAVE_PC();
-	    throw_null_pointer_exception ();
-	  }
-
-	fun = (void (*)()) rmeth->method->ncode;
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokespecial_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokespecial_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	// We don't use NULLCHECK here because we can't rely on that
-	// working for <init>.  So instead we do an explicit test.
-	if (! sp[0].o)
-	  {
-	    throw_null_pointer_exception ();
-	  }
-	fun = (void (*)()) rmeth->method->ncode;
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_invokestatic:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	fun = (void (*)()) rmeth->method->ncode;
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokestatic_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokestatic_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	fun = (void (*)()) rmeth->method->ncode;
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_invokeinterface:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	jobject rcv = sp[0].o;
-
-	NULLCHECK (rcv);
-
-	fun = (void (*)())
-	  _Jv_LookupInterfaceMethod (rcv->getClass (),
-				     rmeth->method->name,
-				     rmeth->method->signature);
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokeinterface_resolved;
-	pc[-1].datum = rmeth;
-#else
-	// Skip dummy bytes.
-	pc += 2;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokeinterface_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	jobject rcv = sp[0].o;
-	NULLCHECK (rcv);
-	fun = (void (*)())
-	  _Jv_LookupInterfaceMethod (rcv->getClass (),
-				     rmeth->method->name,
-				     rmeth->method->signature);
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_new:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-							  index)).clazz;
-	/* VM spec, section 3.11.5 */
-	if ((klass->getModifiers() & Modifier::ABSTRACT)
-	    || klass->isInterface())
-	  throw new java::lang::InstantiationException;
-	jobject res = _Jv_AllocObject (klass);
-	PUSHA (res);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&new_resolved;
-	pc[-1].datum = klass;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    new_resolved:
-      {
-	jclass klass = (jclass) AVAL ();
-	jobject res = _Jv_AllocObject (klass);
-	PUSHA (res);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_newarray:
-      {
-	int atype = GET1U ();
-	int size  = POPI();
-	jobject result = _Jv_NewArray (atype, size);
-	PUSHA (result);
-      }
-      NEXT_INSN;
-
-    insn_anewarray:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-							  index)).clazz;
-	int size  = POPI();
-	jobject result = _Jv_NewObjectArray (size, klass, 0);
-	PUSHA (result);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&anewarray_resolved;
-	pc[-1].datum = klass;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    anewarray_resolved:
-      {
-	jclass klass = (jclass) AVAL ();
-	int size = POPI ();
-	jobject result = _Jv_NewObjectArray (size, klass, 0);
-	PUSHA (result);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_arraylength:
-      {
-	__JArray *arr = (__JArray*)POPA();
-	NULLARRAYCHECK (arr);
-	PUSHI (arr->length);
-      }
-      NEXT_INSN;
-
-    insn_athrow:
-      {
-	jobject value = POPA();
-	throw static_cast<jthrowable>(value);
-      }
-      NEXT_INSN;
-
-    insn_checkcast:
-      {
-        SAVE_PC();
-	jobject value = POPA();
-	jint index = GET2U ();
-	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						       index)).clazz;
-
-	value = (jobject) _Jv_CheckCast (to, value);
-
-	PUSHA (value);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&checkcast_resolved;
-	pc[-1].datum = to;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    checkcast_resolved:
-      {
-        SAVE_PC();
-	jobject value = POPA ();
-	jclass to = (jclass) AVAL ();
-	value = (jobject) _Jv_CheckCast (to, value);
-	PUSHA (value);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_instanceof:
-      {
-        SAVE_PC();
-	jobject value = POPA();
-	jint index = GET2U ();
-	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						       index)).clazz;
-	PUSHI (to->isInstance (value));
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&instanceof_resolved;
-	pc[-1].datum = to;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    instanceof_resolved:
-      {
-	jobject value = POPA ();
-	jclass to = (jclass) AVAL ();
-	PUSHI (to->isInstance (value));
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_monitorenter:
-      {
-	jobject value = POPA();
-	NULLCHECK(value);
-	_Jv_MonitorEnter (value);
-      }
-      NEXT_INSN;
-
-    insn_monitorexit:
-      {
-	jobject value = POPA();
-	NULLCHECK(value);
-	_Jv_MonitorExit (value);
-      }
-      NEXT_INSN;
-
-    insn_ifnull:
-      {
-	jobject val = POPA();
-	if (val == NULL)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifnonnull:
-      {
-	jobject val = POPA();
-	if (val != NULL)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_multianewarray:
-      {
-	SAVE_PC();
-	int kind_index = GET2U ();
-	int dim        = GET1U ();
-
-	jclass type    
-	  = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-					       kind_index)).clazz;
-	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
-
-	for (int i = dim - 1; i >= 0; i--)
-	  {
-	    sizes[i] = POPI ();
-	  }
-
-	jobject res    = _Jv_NewMultiArray (type,dim, sizes);
-
-	PUSHA (res);
-      }
-      NEXT_INSN;
-
-#ifndef DIRECT_THREADED
-    insn_wide:
-      {
-	jint the_mod_op = get1u (pc++);
-	jint wide       = get2u (pc); pc += 2;
-
-	switch (the_mod_op)
-	  {
-	  case op_istore:
-	    STOREI (wide);
-	    NEXT_INSN;
-
-	  case op_fstore:
-	    STOREF (wide);
-	    NEXT_INSN;
-
-	  case op_astore:
-	    STOREA (wide);
-	    NEXT_INSN;
-
-	  case op_lload:
-	    LOADL (wide);
-	    NEXT_INSN;
-
-	  case op_dload:
-	    LOADD (wide);
-	    NEXT_INSN;
-
-	  case op_iload:
-	    LOADI (wide);
-	    NEXT_INSN;
-
-	  case op_fload:
-	    LOADF (wide);
-	    NEXT_INSN;
-
-	  case op_aload:
-	    LOADA (wide);
-	    NEXT_INSN;
-
-	  case op_lstore:
-	    STOREL (wide);
-	    NEXT_INSN;
-
-	  case op_dstore:
-	    STORED (wide);
-	    NEXT_INSN;
-
-	  case op_ret:
-	    pc = (unsigned char*) PEEKA (wide);
-	    NEXT_INSN;
-
-	  case op_iinc:
-	    {
-	      jint amount = get2s (pc); pc += 2;
-	      jint value = PEEKI (wide);
-	      POKEI (wide, value+amount);
-	    }
-	    NEXT_INSN;
-
-	  default:
-	    throw_internal_error ("illegal bytecode modified by wide");
-	  }
-
-      }
-#endif /* DIRECT_THREADED */
-    }
-  catch (java::lang::Throwable *ex)
-    {
-#ifdef DIRECT_THREADED
-      void *logical_pc = (void *) ((insn_slot *) pc - 1);
-#else
-      int logical_pc = pc - 1 - bytecode ();
-#endif
-      _Jv_InterpException *exc = meth->exceptions ();
-      jclass exc_class = ex->getClass ();
-
-      for (int i = 0; i < meth->exc_count; i++)
-	{
-	  if (PCVAL (exc[i].start_pc) <= logical_pc
-	      && logical_pc < PCVAL (exc[i].end_pc))
-	    {
-#ifdef DIRECT_THREADED
-	      jclass handler = (jclass) exc[i].handler_type.p;
-#else
-	      jclass handler = NULL;
-	      if (exc[i].handler_type.i != 0)
-		handler = (_Jv_Linker::resolve_pool_entry (defining_class,
-							     exc[i].handler_type.i)).clazz;
-#endif /* DIRECT_THREADED */
-
-	      if (handler == NULL || handler->isAssignableFrom (exc_class))
-		{
-#ifdef DIRECT_THREADED
-		  pc = (insn_slot *) exc[i].handler_pc.p;
-#else
-		  pc = bytecode () + exc[i].handler_pc.i;
-#endif /* DIRECT_THREADED */
-		  sp = stack;
-		  sp++->o = ex; // Push exception.
-		  NEXT_INSN;
-		}
-	    }
-	}
-
-      // No handler, so re-throw.
-      throw ex;
-    }
-}
-
-static void
-throw_internal_error (const char *msg)
-{
-  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
-}
-
-static void 
-throw_incompatible_class_change_error (jstring msg)
-{
-  throw new java::lang::IncompatibleClassChangeError (msg);
-}
-
-static void 
-throw_null_pointer_exception ()
-{
-  throw new java::lang::NullPointerException;
-}
-
-/* Look up source code line number for given bytecode (or direct threaded
-   interpreter) PC. */
-int
-_Jv_InterpMethod::get_source_line(pc_t mpc)
-{
-  int line = line_table_len > 0 ? line_table[0].line : -1;
-  for (int i = 1; i < line_table_len; i++)
-    if (line_table[i].pc > mpc)
-      break;
-    else
-      line = line_table[i].line;
-
-  return line;
-}
-
-/** Do static initialization for fields with a constant initializer */
-void
-_Jv_InitField (jobject obj, jclass klass, int index)
-{
-  using namespace java::lang::reflect;
-
-  if (obj != 0 && klass == 0)
-    klass = obj->getClass ();
-
-  if (!_Jv_IsInterpretedClass (klass))
-    return;
-
-  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
-
-  _Jv_Field * field = (&klass->fields[0]) + index;
-
-  if (index > klass->field_count)
-    throw_internal_error ("field out of range");
-
-  int init = iclass->field_initializers[index];
-  if (init == 0)
-    return;
-
-  _Jv_Constants *pool = &klass->constants;
-  int tag = pool->tags[init];
-
-  if (! field->isResolved ())
-    throw_internal_error ("initializing unresolved field");
-
-  if (obj==0 && ((field->flags & Modifier::STATIC) == 0))
-    throw_internal_error ("initializing non-static field with no object");
-
-  void *addr = 0;
-
-  if ((field->flags & Modifier::STATIC) != 0)
-    addr = (void*) field->u.addr;
-  else
-    addr = (void*) (((char*)obj) + field->u.boffset);
-
-  switch (tag)
-    {
-    case JV_CONSTANT_String:
-      {
-	jstring str;
-	str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
-	pool->data[init].string = str;
-	pool->tags[init] = JV_CONSTANT_ResolvedString;
-      }
-      /* fall through */
-
-    case JV_CONSTANT_ResolvedString:
-      if (! (field->type == &java::lang::String::class$
- 	     || field->type == &java::lang::Class::class$))
-	throw_class_format_error ("string initialiser to non-string field");
-
-      *(jstring*)addr = pool->data[init].string;
-      break;
-
-    case JV_CONSTANT_Integer:
-      {
-	int value = pool->data[init].i;
-
-	if (field->type == JvPrimClass (boolean))
-	  *(jboolean*)addr = (jboolean)value;
-	
-	else if (field->type == JvPrimClass (byte))
-	  *(jbyte*)addr = (jbyte)value;
-	
-	else if (field->type == JvPrimClass (char))
-	  *(jchar*)addr = (jchar)value;
-
-	else if (field->type == JvPrimClass (short))
-	  *(jshort*)addr = (jshort)value;
-	
-	else if (field->type == JvPrimClass (int))
-	  *(jint*)addr = (jint)value;
-
-	else
-	  throw_class_format_error ("erroneous field initializer");
-      }  
-      break;
-
-    case JV_CONSTANT_Long:
-      if (field->type != JvPrimClass (long))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
-      break;
-
-    case JV_CONSTANT_Float:
-      if (field->type != JvPrimClass (float))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jfloat*)addr = pool->data[init].f;
-      break;
-
-    case JV_CONSTANT_Double:
-      if (field->type != JvPrimClass (double))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
-      break;
-
-    default:
-      throw_class_format_error ("erroneous field initializer");
-    }
-}
-
-inline static unsigned char*
-skip_one_type (unsigned char* ptr)
-{
-  int ch = *ptr++;
-
-  while (ch == '[')
-    { 
-      ch = *ptr++;
-    }
-  
-  if (ch == 'L')
-    {
-      do { ch = *ptr++; } while (ch != ';');
-    }
-
-  return ptr;
-}
-
-static ffi_type*
-get_ffi_type_from_signature (unsigned char* ptr)
-{
-  switch (*ptr) 
-    {
-    case 'L':
-    case '[':
-      return &ffi_type_pointer;
-      break;
-
-    case 'Z':
-      // On some platforms a bool is a byte, on others an int.
-      if (sizeof (jboolean) == sizeof (jbyte))
-	return &ffi_type_sint8;
-      else
-	{
-	  JvAssert (sizeof (jbyte) == sizeof (jint));
-	  return &ffi_type_sint32;
-	}
-      break;
-
-    case 'B':
-      return &ffi_type_sint8;
-      break;
-      
-    case 'C':
-      return &ffi_type_uint16;
-      break;
-	  
-    case 'S': 
-      return &ffi_type_sint16;
-      break;
-	  
-    case 'I':
-      return &ffi_type_sint32;
-      break;
-	  
-    case 'J':
-      return &ffi_type_sint64;
-      break;
-	  
-    case 'F':
-      return &ffi_type_float;
-      break;
-	  
-    case 'D':
-      return &ffi_type_double;
-      break;
-
-    case 'V':
-      return &ffi_type_void;
-      break;
-    }
-
-  throw_internal_error ("unknown type in signature");
-}
-
-/* this function yields the number of actual arguments, that is, if the
- * function is non-static, then one is added to the number of elements
- * found in the signature */
-
-int 
-_Jv_count_arguments (_Jv_Utf8Const *signature,
-		     jboolean staticp)
-{
-  unsigned char *ptr = (unsigned char*) signature->chars();
-  int arg_count = staticp ? 0 : 1;
-
-  /* first, count number of arguments */
-
-  // skip '('
-  ptr++;
-
-  // count args
-  while (*ptr != ')')
-    {
-      ptr = skip_one_type (ptr);
-      arg_count += 1;
-    }
-
-  return arg_count;
-}
-
-/* This beast will build a cif, given the signature.  Memory for
- * the cif itself and for the argument types must be allocated by the
- * caller.
- */
-
-static int 
-init_cif (_Jv_Utf8Const* signature,
-	  int arg_count,
-	  jboolean staticp,
-	  ffi_cif *cif,
-	  ffi_type **arg_types,
-	  ffi_type **rtype_p)
-{
-  unsigned char *ptr = (unsigned char*) signature->chars();
-
-  int arg_index = 0;		// arg number
-  int item_count = 0;		// stack-item count
-
-  // setup receiver
-  if (!staticp)
-    {
-      arg_types[arg_index++] = &ffi_type_pointer;
-      item_count += 1;
-    }
-
-  // skip '('
-  ptr++;
+  // skip '('
+  ptr++;
 
   // assign arg types
   while (*ptr != ')')
@@ -3969,7 +1523,7 @@
 _Jv_CompileMethod (_Jv_InterpMethod* method)
 {
   if (method->prepared == NULL)
-    _Jv_InterpMethod::run (NULL, NULL, method);
+    _Jv_InterpMethod::run_no_debug (NULL, NULL, method);
 }
 #endif // DIRECT_THREADED
Index: /notnfs/kgallowa/vanilla/libjava/prims.cc
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/prims.cc	(revision 115793)
+++ /notnfs/kgallowa/vanilla/libjava/prims.cc	(working copy)
@@ -1138,6 +1138,8 @@
     }
   else if (! strcmp (option_string, "debug"))
     {
+      //use debug mode interpreter
+      _Jv_InterpMethod::setDebug(true);
       // FIXME: add JDWP/JVMDI support
     }
   else if (! strncmp (option_string, "bootclasspath:", 14))
@@ -1489,6 +1491,7 @@
 _Jv_RunMain (JvVMInitArgs *vm_args, jclass klass, const char *name, int argc,
              const char **argv, bool is_jar)
 {
+  _Jv_InterpMethod::setDebug(false);
 #ifndef DISABLE_MAIN_ARGS
   _Jv_SetArgs (argc, argv);
 #endif
Index: /notnfs/kgallowa/vanilla/libjava/stacktrace.cc
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/stacktrace.cc	(revision 115793)
+++ /notnfs/kgallowa/vanilla/libjava/stacktrace.cc	(working copy)
@@ -111,7 +111,7 @@
   // correspondance between call frames in the interpreted stack and occurances
   // of _Jv_InterpMethod::run() on the native stack.
 #ifdef INTERPRETER
-  void *interp_run = (void *) &_Jv_InterpMethod::run;
+  void *interp_run = (void *) _Jv_InterpMethod::run;
   if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
     {
       state->frames[pos].type = frame_interpreter;

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-07-28 22:09 RFA: Changes to interpreter to avoid non-debugging slowdown Kyle Galloway
@ 2006-07-31 18:42 ` Tom Tromey
  2006-08-01 13:37   ` Kyle Galloway
  0 siblings, 1 reply; 16+ messages in thread
From: Tom Tromey @ 2006-07-31 18:42 UTC (permalink / raw)
  To: Kyle Galloway; +Cc: java-patches

>>>>> "Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:

Kyle> This patch creates a second version of _Jv_InterpMethod::run() using 
Kyle> preprocessor directives to allow the debugging info to be collected only 
Kyle> when the interpreter is passed the debug command line argument.  This 
Kyle> avoids slowdowns in non-debugging cases by not gathering debug 
Kyle> information or sending events when not debugging.

When posting put a bit more rationale in for a big change like this.

We talked about it offline and the idea is, we need to track the types
of stack and local variable slots while interpreting if the debugging
code is enabled.  However, we don't want to do this unconditionally as
it adds overhead to interpretation.

One idea was to keep the verifier-generated information around, but
this looked costly due to increased memory use and also because we'd
still have to do some work in the interpreter (the verifier only keeps
type states at branch targets).

So, having a second debug-only interpreter seemed more suitable.

This is looking pretty good.  Some problems below.

Kyle> +  //switch debug mode on or off
Kyle> +  static void setDebug(bool debug)
Kyle> +  {
Kyle> +  	run = (debug) ? run_debug : run_no_debug;
Kyle> +  }

Do we really need this as a method on _Jv_InterpMethod?
I was assuming that "debug mode" would be a global choice.
But... you tell me, I don't know how this part is supposed to work.

Kyle> Index: /notnfs/kgallowa/vanilla/libjava/interpret-run.cc
Kyle> ===================================================================
Kyle> --- /notnfs/kgallowa/vanilla/libjava/interpret-run.cc	(revision 0)
Kyle> +++ /notnfs/kgallowa/vanilla/libjava/interpret-run.cc	(revision 0)
Kyle> @@ -0,0 +1,2500 @@
Kyle> +  using namespace java::lang::reflect;

This file needs a copyright header.
Also there ought to be a comment after the copyright header explaining
that this file shouldn't be compiled but instead is only included by
interpret.cc.

Kyle> Index: /notnfs/kgallowa/vanilla/libjava/interpret.cc
Kyle> +#define STOREA(I) 		\
Kyle> +DEBUG_LOCALS_INSN(I,o)	\

It is our style to put a space after the ',' here.

Kyle> +void (*_Jv_InterpMethod::run) (void *, ffi_raw *, _Jv_InterpMethod *) = NULL;

If debug mode is a global then I don't think we need this.  We can
simply have multiple run_normal, etc, methods, and choose the ones we
like when preparing the ffi closures.  That lets us avoid putting an
extra indirect dispatch into every call to an interpreted method.

Kyle> +/* Used to keep track of local variable type
Kyle> + * 
Kyle> + * Possible Types:
Kyle> + * o object
Kyle> + * i integer
Kyle> + * f float
Kyle> + * l long (one slot)
Kyle> + * m long (two slots)
Kyle> + * d double (one slot)
Kyle> + * e double (two slots)
Kyle> + */

I think we don't really need the 'm' and 'e' types -- on a given
platform, we will always either do one or the other.  This knowledge
might as well be available to other parts of libgcj.

Kyle> +#define DEBUG
Kyle> +#undef DEBUG_LOCALS_INSN
Kyle> +#define DEBUG_LOCALS_INSN(s,t) { localsType[s] = 't'; }

This won't do what you think it does.  You'll always see a literal 't'
in the result.

Instead you either want to just pass in character constants (best, if
possible) or do something like:

  localsType[s] = (# t)[0];

Tom

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-07-31 18:42 ` Tom Tromey
@ 2006-08-01 13:37   ` Kyle Galloway
  2006-08-01 15:09     ` Tom Tromey
  0 siblings, 1 reply; 16+ messages in thread
From: Kyle Galloway @ 2006-08-01 13:37 UTC (permalink / raw)
  To: tromey, java-patches

[-- Attachment #1: Type: text/plain, Size: 4642 bytes --]

Tom Tromey wrote:
>>>>>> "Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:
>>>>>>             
>
> Kyle> This patch creates a second version of _Jv_InterpMethod::run() using 
> Kyle> preprocessor directives to allow the debugging info to be collected only 
> Kyle> when the interpreter is passed the debug command line argument.  This 
> Kyle> avoids slowdowns in non-debugging cases by not gathering debug 
> Kyle> information or sending events when not debugging.
>
> When posting put a bit more rationale in for a big change like this.
>
> We talked about it offline and the idea is, we need to track the types
> of stack and local variable slots while interpreting if the debugging
> code is enabled.  However, we don't want to do this unconditionally as
> it adds overhead to interpretation.
>
> One idea was to keep the verifier-generated information around, but
> this looked costly due to increased memory use and also because we'd
> still have to do some work in the interpreter (the verifier only keeps
> type states at branch targets).
>
> So, having a second debug-only interpreter seemed more suitable.
>
> This is looking pretty good.  Some problems below.
>
> Kyle> +  //switch debug mode on or off
> Kyle> +  static void setDebug(bool debug)
> Kyle> +  {
> Kyle> +  	run = (debug) ? run_debug : run_no_debug;
> Kyle> +  }
>
> Do we really need this as a method on _Jv_InterpMethod?
> I was assuming that "debug mode" would be a global choice.
> But... you tell me, I don't know how this part is supposed to work.
>   
I've changed this now so that debug mode is set globally, and cannot be 
changed without restarting the interpreter.
> Kyle> Index: /notnfs/kgallowa/vanilla/libjava/interpret-run.cc
> Kyle> ===================================================================
> Kyle> --- /notnfs/kgallowa/vanilla/libjava/interpret-run.cc	(revision 0)
> Kyle> +++ /notnfs/kgallowa/vanilla/libjava/interpret-run.cc	(revision 0)
> Kyle> @@ -0,0 +1,2500 @@
> Kyle> +  using namespace java::lang::reflect;
>
> This file needs a copyright header.
> Also there ought to be a comment after the copyright header explaining
> that this file shouldn't be compiled but instead is only included by
> interpret.cc.
>   
Added.
> Kyle> Index: /notnfs/kgallowa/vanilla/libjava/interpret.cc
> Kyle> +#define STOREA(I) 		\
> Kyle> +DEBUG_LOCALS_INSN(I,o)	\
>
> It is our style to put a space after the ',' here.
>   
I've fixed this everywhere I saw it.
> Kyle> +void (*_Jv_InterpMethod::run) (void *, ffi_raw *, _Jv_InterpMethod *) = NULL;
>
> If debug mode is a global then I don't think we need this.  We can
> simply have multiple run_normal, etc, methods, and choose the ones we
> like when preparing the ffi closures.  That lets us avoid putting an
> extra indirect dispatch into every call to an interpreted method.
>   
This has been chnaged so that either a debug or normal version of the 4 
run_* functions are called when preparing the closure.  The function 
pointer has been removed.
> Kyle> +/* Used to keep track of local variable type
> Kyle> + * 
> Kyle> + * Possible Types:
> Kyle> + * o object
> Kyle> + * i integer
> Kyle> + * f float
> Kyle> + * l long (one slot)
> Kyle> + * m long (two slots)
> Kyle> + * d double (one slot)
> Kyle> + * e double (two slots)
> Kyle> + */
>
> I think we don't really need the 'm' and 'e' types -- on a given
> platform, we will always either do one or the other.  This knowledge
> might as well be available to other parts of libgcj.
>   
I got rid of these.
> Kyle> +#define DEBUG
> Kyle> +#undef DEBUG_LOCALS_INSN
> Kyle> +#define DEBUG_LOCALS_INSN(s,t) { localsType[s] = 't'; }
>
> This won't do what you think it does.  You'll always see a literal 't'
> in the result.
>   
I've switched to passing character constants and changed the instruction 
appropriately.

I also stripped out some changes that aren't really part of the split 
itself (they are more a beginning to debugging, I will submit in another 
patch once this change is accepted) and updated the changelog and 
included the fixed patch:

2006-07-28  Kyle Galloway  <kgallowa@redhat.com>

    * /include/java-interp.h (_Jv_InterpMethod::run_debug): New method.
    * /interpret.cc: Added placeholder for debug variable type info to 
STORE*
    macros.
    (_Jv_InterpMethod::run_debug): New method.
    (_Jv_InterpMethod::run_sync_object_debug): New method.
    (_Jv_InterpMethod::run_sync_class_debug): New method.
    (_Jv_InterpMethod::run_normal_debug): New method.
    (_Jv_InterpMethod::run_class_debug): New method.
    * /interpret-run.cc: New file, holds contents of old 
_Jv_InterpMethod::run
    method.



[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 119074 bytes --]

Index: /notnfs/kgallowa/vanilla/libjava/include/java-interp.h
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/include/java-interp.h	(revision 115793)
+++ /notnfs/kgallowa/vanilla/libjava/include/java-interp.h	(working copy)
@@ -176,9 +176,17 @@
   static void run_synch_object (ffi_cif*, void*, ffi_raw*, void*);
   static void run_class (ffi_cif*, void*, ffi_raw*, void*);
   static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*);
+  
+  static void run_normal_debug (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_synch_object_debug (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_class_debug (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_synch_class_debug (ffi_cif*, void*, ffi_raw*, void*);
 
-  static void run (void*, ffi_raw *, _Jv_InterpMethod *);
+  static void run (void *, ffi_raw *, _Jv_InterpMethod *);
+  static void run_debug (void *, ffi_raw *, _Jv_InterpMethod *);
+  
 
+  
   // Returns source file line number for given PC value, or -1 if line
   // number info is unavailable.
   int get_source_line(pc_t mpc);
Index: /notnfs/kgallowa/vanilla/libjava/interpret-run.cc
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/interpret-run.cc	(revision 0)
+++ /notnfs/kgallowa/vanilla/libjava/interpret-run.cc	(revision 0)
@@ -0,0 +1,2508 @@
+// interpret-run.cc - Code to interpret bytecode
+
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+/* This file is meant only to be included in interpret.cc, it should not be
+ * compiled directly.	*/
+
+  using namespace java::lang::reflect;
+
+  // FRAME_DESC registers this particular invocation as the top-most
+  // interpreter frame.  This lets the stack tracing code (for
+  // Throwable) print information about the method being interpreted
+  // rather than about the interpreter itself.  FRAME_DESC has a
+  // destructor so it cleans up automatically when the interpreter
+  // returns.
+  java::lang::Thread *thread = java::lang::Thread::currentThread();
+  _Jv_InterpFrame frame_desc (meth, thread);
+
+  _Jv_word stack[meth->max_stack];
+  _Jv_word *sp = stack;
+
+  _Jv_word locals[meth->max_locals];
+
+#define INSN_LABEL(op) &&insn_##op
+
+  static const void *const insn_target[] = 
+  {
+    INSN_LABEL(nop),
+    INSN_LABEL(aconst_null),
+    INSN_LABEL(iconst_m1),
+    INSN_LABEL(iconst_0),
+    INSN_LABEL(iconst_1),
+    INSN_LABEL(iconst_2),
+    INSN_LABEL(iconst_3),
+    INSN_LABEL(iconst_4),
+    INSN_LABEL(iconst_5),
+    INSN_LABEL(lconst_0),
+    INSN_LABEL(lconst_1),
+    INSN_LABEL(fconst_0),
+    INSN_LABEL(fconst_1),
+    INSN_LABEL(fconst_2),
+    INSN_LABEL(dconst_0),
+    INSN_LABEL(dconst_1),
+    INSN_LABEL(bipush),
+    INSN_LABEL(sipush),
+    INSN_LABEL(ldc),
+    INSN_LABEL(ldc_w),
+    INSN_LABEL(ldc2_w),
+    INSN_LABEL(iload),
+    INSN_LABEL(lload),
+    INSN_LABEL(fload),
+    INSN_LABEL(dload),
+    INSN_LABEL(aload),
+    INSN_LABEL(iload_0),
+    INSN_LABEL(iload_1),
+    INSN_LABEL(iload_2),
+    INSN_LABEL(iload_3),
+    INSN_LABEL(lload_0),
+    INSN_LABEL(lload_1),
+    INSN_LABEL(lload_2),
+    INSN_LABEL(lload_3),
+    INSN_LABEL(fload_0),
+    INSN_LABEL(fload_1),
+    INSN_LABEL(fload_2),
+    INSN_LABEL(fload_3),
+    INSN_LABEL(dload_0),
+    INSN_LABEL(dload_1),
+    INSN_LABEL(dload_2),
+    INSN_LABEL(dload_3),
+    INSN_LABEL(aload_0),
+    INSN_LABEL(aload_1),
+    INSN_LABEL(aload_2),
+    INSN_LABEL(aload_3),
+    INSN_LABEL(iaload),
+    INSN_LABEL(laload),
+    INSN_LABEL(faload),
+    INSN_LABEL(daload),
+    INSN_LABEL(aaload),
+    INSN_LABEL(baload),
+    INSN_LABEL(caload),
+    INSN_LABEL(saload),
+    INSN_LABEL(istore),
+    INSN_LABEL(lstore),
+    INSN_LABEL(fstore),
+    INSN_LABEL(dstore),
+    INSN_LABEL(astore),
+    INSN_LABEL(istore_0),
+    INSN_LABEL(istore_1),
+    INSN_LABEL(istore_2),
+    INSN_LABEL(istore_3),
+    INSN_LABEL(lstore_0),
+    INSN_LABEL(lstore_1),
+    INSN_LABEL(lstore_2),
+    INSN_LABEL(lstore_3),
+    INSN_LABEL(fstore_0),
+    INSN_LABEL(fstore_1),
+    INSN_LABEL(fstore_2),
+    INSN_LABEL(fstore_3),
+    INSN_LABEL(dstore_0),
+    INSN_LABEL(dstore_1),
+    INSN_LABEL(dstore_2),
+    INSN_LABEL(dstore_3),
+    INSN_LABEL(astore_0),
+    INSN_LABEL(astore_1),
+    INSN_LABEL(astore_2),
+    INSN_LABEL(astore_3),
+    INSN_LABEL(iastore),
+    INSN_LABEL(lastore),
+    INSN_LABEL(fastore),
+    INSN_LABEL(dastore),
+    INSN_LABEL(aastore),
+    INSN_LABEL(bastore),
+    INSN_LABEL(castore),
+    INSN_LABEL(sastore),
+    INSN_LABEL(pop),
+    INSN_LABEL(pop2),
+    INSN_LABEL(dup),
+    INSN_LABEL(dup_x1),
+    INSN_LABEL(dup_x2),
+    INSN_LABEL(dup2),
+    INSN_LABEL(dup2_x1),
+    INSN_LABEL(dup2_x2),
+    INSN_LABEL(swap),
+    INSN_LABEL(iadd),
+    INSN_LABEL(ladd),
+    INSN_LABEL(fadd),
+    INSN_LABEL(dadd),
+    INSN_LABEL(isub),
+    INSN_LABEL(lsub),
+    INSN_LABEL(fsub),
+    INSN_LABEL(dsub),
+    INSN_LABEL(imul),
+    INSN_LABEL(lmul),
+    INSN_LABEL(fmul),
+    INSN_LABEL(dmul),
+    INSN_LABEL(idiv),
+    INSN_LABEL(ldiv),
+    INSN_LABEL(fdiv),
+    INSN_LABEL(ddiv),
+    INSN_LABEL(irem),
+    INSN_LABEL(lrem),
+    INSN_LABEL(frem),
+    INSN_LABEL(drem),
+    INSN_LABEL(ineg),
+    INSN_LABEL(lneg),
+    INSN_LABEL(fneg),
+    INSN_LABEL(dneg),
+    INSN_LABEL(ishl),
+    INSN_LABEL(lshl),
+    INSN_LABEL(ishr),
+    INSN_LABEL(lshr),
+    INSN_LABEL(iushr),
+    INSN_LABEL(lushr),
+    INSN_LABEL(iand),
+    INSN_LABEL(land),
+    INSN_LABEL(ior),
+    INSN_LABEL(lor),
+    INSN_LABEL(ixor),
+    INSN_LABEL(lxor),
+    INSN_LABEL(iinc),
+    INSN_LABEL(i2l),
+    INSN_LABEL(i2f),
+    INSN_LABEL(i2d),
+    INSN_LABEL(l2i),
+    INSN_LABEL(l2f),
+    INSN_LABEL(l2d),
+    INSN_LABEL(f2i),
+    INSN_LABEL(f2l),
+    INSN_LABEL(f2d),
+    INSN_LABEL(d2i),
+    INSN_LABEL(d2l),
+    INSN_LABEL(d2f),
+    INSN_LABEL(i2b),
+    INSN_LABEL(i2c),
+    INSN_LABEL(i2s),
+    INSN_LABEL(lcmp),
+    INSN_LABEL(fcmpl),
+    INSN_LABEL(fcmpg),
+    INSN_LABEL(dcmpl),
+    INSN_LABEL(dcmpg),
+    INSN_LABEL(ifeq),
+    INSN_LABEL(ifne),
+    INSN_LABEL(iflt),
+    INSN_LABEL(ifge),
+    INSN_LABEL(ifgt),
+    INSN_LABEL(ifle),
+    INSN_LABEL(if_icmpeq),
+    INSN_LABEL(if_icmpne),
+    INSN_LABEL(if_icmplt),
+    INSN_LABEL(if_icmpge),
+    INSN_LABEL(if_icmpgt),
+    INSN_LABEL(if_icmple),
+    INSN_LABEL(if_acmpeq),
+    INSN_LABEL(if_acmpne),
+    INSN_LABEL(goto), 
+    INSN_LABEL(jsr),
+    INSN_LABEL(ret),
+    INSN_LABEL(tableswitch),
+    INSN_LABEL(lookupswitch),
+    INSN_LABEL(ireturn),
+    INSN_LABEL(lreturn),
+    INSN_LABEL(freturn),
+    INSN_LABEL(dreturn),
+    INSN_LABEL(areturn),
+    INSN_LABEL(return),
+    INSN_LABEL(getstatic),
+    INSN_LABEL(putstatic),
+    INSN_LABEL(getfield),
+    INSN_LABEL(putfield),
+    INSN_LABEL(invokevirtual),
+    INSN_LABEL(invokespecial),
+    INSN_LABEL(invokestatic),
+    INSN_LABEL(invokeinterface),
+    0, /* Unused.  */
+    INSN_LABEL(new),
+    INSN_LABEL(newarray),
+    INSN_LABEL(anewarray),
+    INSN_LABEL(arraylength),
+    INSN_LABEL(athrow),
+    INSN_LABEL(checkcast),
+    INSN_LABEL(instanceof),
+    INSN_LABEL(monitorenter),
+    INSN_LABEL(monitorexit),
+#ifdef DIRECT_THREADED
+    0, // wide
+#else
+    INSN_LABEL(wide),
+#endif
+    INSN_LABEL(multianewarray),
+    INSN_LABEL(ifnull),
+    INSN_LABEL(ifnonnull),
+    INSN_LABEL(goto_w),
+    INSN_LABEL(jsr_w),
+#ifdef DIRECT_THREADED
+    INSN_LABEL (ldc_class)
+#else
+    0
+#endif
+  };
+
+  pc_t pc;
+
+#ifdef DIRECT_THREADED
+
+#define NEXT_INSN goto *((pc++)->insn)
+#define INTVAL() ((pc++)->int_val)
+#define AVAL() ((pc++)->datum)
+
+#define GET1S() INTVAL ()
+#define GET2S() INTVAL ()
+#define GET1U() INTVAL ()
+#define GET2U() INTVAL ()
+#define AVAL1U() AVAL ()
+#define AVAL2U() AVAL ()
+#define AVAL2UP() AVAL ()
+#define SKIP_GOTO ++pc
+#define GOTO_VAL() (insn_slot *) pc->datum
+#define PCVAL(unionval) unionval.p
+#define AMPAMP(label) &&label
+
+  // Compile if we must. NOTE: Double-check locking.
+  if (meth->prepared == NULL)
+    {
+      _Jv_MutexLock (&compile_mutex);
+      if (meth->prepared == NULL)
+	meth->compile (insn_target);
+      _Jv_MutexUnlock (&compile_mutex);
+    }
+
+  // If we're only compiling, stop here
+  if (args == NULL)
+    return;
+
+  pc = (insn_slot *) meth->prepared;
+
+#else
+
+#define NEXT_INSN goto *(insn_target[*pc++])
+
+#define GET1S() get1s (pc++)
+#define GET2S() (pc += 2, get2s (pc- 2))
+#define GET1U() get1u (pc++)
+#define GET2U() (pc += 2, get2u (pc - 2))
+  // Note that these could be more efficient when not handling 'ldc
+  // class'.
+#define AVAL1U()						\
+  ({ int index = get1u (pc++);					\
+      resolve_pool_entry (meth->defining_class, index).o; })
+#define AVAL2U()						\
+  ({ int index = get2u (pc); pc += 2;				\
+      resolve_pool_entry (meth->defining_class, index).o; })
+  // Note that we don't need to resolve the pool entry here as class
+  // constants are never wide.
+#define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
+#define SKIP_GOTO pc += 2
+#define GOTO_VAL() pc - 1 + get2s (pc)
+#define PCVAL(unionval) unionval.i
+#define AMPAMP(label) NULL
+
+  pc = bytecode ();
+
+#endif /* DIRECT_THREADED */
+
+#define TAKE_GOTO pc = GOTO_VAL ()
+
+  /* Go straight at it!  the ffi raw format matches the internal
+     stack representation exactly.  At least, that's the idea.
+  */
+  memcpy ((void*) locals, (void*) args, meth->args_raw_size);
+
+  _Jv_word *pool_data = meth->defining_class->constants.data;
+
+  /* These three are temporaries for common code used by several
+     instructions.  */
+  void (*fun)();
+  _Jv_ResolvedMethod* rmeth;
+  int tmpval;
+
+  try
+    {
+      // We keep nop around.  It is used if we're interpreting the
+      // bytecodes and not doing direct threading.
+    insn_nop:
+      NEXT_INSN;
+
+      /* The first few instructions here are ordered according to their
+	 frequency, in the hope that this will improve code locality a
+	 little.  */
+
+    insn_aload_0:		// 0x2a
+      LOADA (0);
+      NEXT_INSN;
+
+    insn_iload:		// 0x15
+      LOADI (GET1U ());
+      NEXT_INSN;
+
+    insn_iload_1:		// 0x1b
+      LOADI (1);
+      NEXT_INSN;
+
+    insn_invokevirtual:	// 0xb6
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	/* _Jv_Linker::resolve_pool_entry returns immediately if the
+	 * value already is resolved.  If we want to clutter up the
+	 * code here to gain a little performance, then we can check
+	 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
+	 * directly.  For now, I don't think it is worth it.  */
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	if (rmeth->method->accflags & Modifier::FINAL)
+	  {
+	    // We can't rely on NULLCHECK working if the method is final.
+	    if (! sp[0].o)
+	      throw_null_pointer_exception ();
+
+	    // Final methods might not appear in the vtable.
+	    fun = (void (*)()) rmeth->method->ncode;
+	  }
+	else
+	  {
+	    NULLCHECK (sp[0].o);
+	    jobject rcv = sp[0].o;
+	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
+	    fun = (void (*)()) table->get_method (rmeth->method->index);
+	  }
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokevirtual_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokevirtual_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+
+	if (rmeth->method->accflags & Modifier::FINAL)
+	  {
+	    // We can't rely on NULLCHECK working if the method is final.
+	    if (! sp[0].o)
+	      throw_null_pointer_exception ();
+
+	    // Final methods might not appear in the vtable.
+	    fun = (void (*)()) rmeth->method->ncode;
+	  }
+	else
+	  {
+	    jobject rcv = sp[0].o;
+	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
+	    fun = (void (*)()) table->get_method (rmeth->method->index);
+	  }
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    perform_invoke:
+      {
+	/* here goes the magic again... */
+	ffi_cif *cif = &rmeth->cif;
+	ffi_raw *raw = (ffi_raw*) sp;
+
+	_Jv_value rvalue;
+
+#if FFI_NATIVE_RAW_API
+	/* We assume that this is only implemented if it's correct	*/
+	/* to use it here.  On a 64 bit machine, it never is.		*/
+	ffi_raw_call (cif, fun, (void*)&rvalue, raw);
+#else
+	ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
+#endif
+
+	int rtype = cif->rtype->type;
+
+	/* the likelyhood of object, int, or void return is very high,
+	 * so those are checked before the switch */
+	if (rtype == FFI_TYPE_POINTER)
+	  {
+	    PUSHA (rvalue.object_value);
+	  }
+	else if (rtype == FFI_TYPE_SINT32)
+	  {
+	    PUSHI (rvalue.int_value);
+	  }
+	else if (rtype == FFI_TYPE_VOID)
+	  {
+	    /* skip */
+	  }
+	else
+	  {
+	    switch (rtype)
+	      {
+	      case FFI_TYPE_SINT8:
+		PUSHI ((jbyte)(rvalue.int_value & 0xff));
+		break;
+
+	      case FFI_TYPE_SINT16:
+		PUSHI ((jshort)(rvalue.int_value & 0xffff));
+		break;
+
+	      case FFI_TYPE_UINT16:
+		PUSHI (rvalue.int_value & 0xffff);
+		break;
+
+	      case FFI_TYPE_FLOAT:
+	        PUSHF (rvalue.float_value);
+		break;
+
+	      case FFI_TYPE_DOUBLE:
+	        PUSHD (rvalue.double_value);
+		break;
+
+	      case FFI_TYPE_SINT64:
+	        PUSHL (rvalue.long_value);
+		break;
+
+	      default:
+		throw_internal_error ("unknown return type in invokeXXX");
+	      }
+	  }
+      }
+      NEXT_INSN;
+
+    insn_aconst_null:
+      PUSHA (NULL);
+      NEXT_INSN;
+
+    insn_iconst_m1:
+      PUSHI (-1);
+      NEXT_INSN;
+
+    insn_iconst_0:
+      PUSHI (0);
+      NEXT_INSN;
+
+    insn_iconst_1:
+      PUSHI (1);
+      NEXT_INSN;
+
+    insn_iconst_2:
+      PUSHI (2);
+      NEXT_INSN;
+
+    insn_iconst_3:
+      PUSHI (3);
+      NEXT_INSN;
+
+    insn_iconst_4:
+      PUSHI (4);
+      NEXT_INSN;
+
+    insn_iconst_5:
+      PUSHI (5);
+      NEXT_INSN;
+
+    insn_lconst_0:
+      PUSHL (0);
+      NEXT_INSN;
+
+    insn_lconst_1:
+      PUSHL (1);
+      NEXT_INSN;
+
+    insn_fconst_0:
+      PUSHF (0);
+      NEXT_INSN;
+
+    insn_fconst_1:
+      PUSHF (1);
+      NEXT_INSN;
+
+    insn_fconst_2:
+      PUSHF (2);
+      NEXT_INSN;
+
+    insn_dconst_0:
+      PUSHD (0);
+      NEXT_INSN;
+
+    insn_dconst_1:
+      PUSHD (1);
+      NEXT_INSN;
+
+    insn_bipush:
+      // For direct threaded, bipush and sipush are the same.
+#ifndef DIRECT_THREADED
+      PUSHI (GET1S ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_sipush:
+      PUSHI (GET2S ());
+      NEXT_INSN;
+
+    insn_ldc:
+      // For direct threaded, ldc and ldc_w are the same.
+#ifndef DIRECT_THREADED
+      PUSHA ((jobject) AVAL1U ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_ldc_w:
+      PUSHA ((jobject) AVAL2U ());
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+      // For direct threaded we have a separate 'ldc class' operation.
+    insn_ldc_class:
+      {
+	SAVE_PC();
+	// We could rewrite the instruction at this point.
+	int index = INTVAL ();
+	jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						     index)).o;
+	PUSHA (k);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_ldc2_w:
+      {
+	void *where = AVAL2UP ();
+	memcpy (sp, where, 2*sizeof (_Jv_word));
+	sp += 2;
+      }
+      NEXT_INSN;
+
+    insn_lload:
+      LOADL (GET1U ());
+      NEXT_INSN;
+
+    insn_fload:
+      LOADF (GET1U ());
+      NEXT_INSN;
+
+    insn_dload:
+      LOADD (GET1U ());
+      NEXT_INSN;
+
+    insn_aload:
+      LOADA (GET1U ());
+      NEXT_INSN;
+
+    insn_iload_0:
+      LOADI (0);
+      NEXT_INSN;
+
+    insn_iload_2:
+      LOADI (2);
+      NEXT_INSN;
+
+    insn_iload_3:
+      LOADI (3);
+      NEXT_INSN;
+
+    insn_lload_0:
+      LOADL (0);
+      NEXT_INSN;
+
+    insn_lload_1:
+      LOADL (1);
+      NEXT_INSN;
+
+    insn_lload_2:
+      LOADL (2);
+      NEXT_INSN;
+
+    insn_lload_3:
+      LOADL (3);
+      NEXT_INSN;
+
+    insn_fload_0:
+      LOADF (0);
+      NEXT_INSN;
+
+    insn_fload_1:
+      LOADF (1);
+      NEXT_INSN;
+
+    insn_fload_2:
+      LOADF (2);
+      NEXT_INSN;
+
+    insn_fload_3:
+      LOADF (3);
+      NEXT_INSN;
+
+    insn_dload_0:
+      LOADD (0);
+      NEXT_INSN;
+
+    insn_dload_1:
+      LOADD (1);
+      NEXT_INSN;
+
+    insn_dload_2:
+      LOADD (2);
+      NEXT_INSN;
+
+    insn_dload_3:
+      LOADD (3);
+      NEXT_INSN;
+
+    insn_aload_1:
+      LOADA(1);
+      NEXT_INSN;
+
+    insn_aload_2:
+      LOADA(2);
+      NEXT_INSN;
+
+    insn_aload_3:
+      LOADA(3);
+      NEXT_INSN;
+
+    insn_iaload:
+      {
+	jint index = POPI();
+	jintArray arr = (jintArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_laload:
+      {
+	jint index = POPI();
+	jlongArray arr = (jlongArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHL( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_faload:
+      {
+	jint index = POPI();
+	jfloatArray arr = (jfloatArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHF( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_daload:
+      {
+	jint index = POPI();
+	jdoubleArray arr = (jdoubleArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHD( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_aaload:
+      {
+	jint index = POPI();
+	jobjectArray arr = (jobjectArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHA( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_baload:
+      {
+	jint index = POPI();
+	jbyteArray arr = (jbyteArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_caload:
+      {
+	jint index = POPI();
+	jcharArray arr = (jcharArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_saload:
+      {
+	jint index = POPI();
+	jshortArray arr = (jshortArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_istore:
+      STOREI (GET1U ());
+      NEXT_INSN;
+
+    insn_lstore:
+      STOREL (GET1U ());
+      NEXT_INSN;
+
+    insn_fstore:
+      STOREF (GET1U ());
+      NEXT_INSN;
+
+    insn_dstore:
+      STORED (GET1U ());
+      NEXT_INSN;
+
+    insn_astore:
+      STOREA (GET1U ());
+      NEXT_INSN;
+
+    insn_istore_0:
+      STOREI (0);
+      NEXT_INSN;
+
+    insn_istore_1:
+      STOREI (1);
+      NEXT_INSN;
+
+    insn_istore_2:
+      STOREI (2);
+      NEXT_INSN;
+
+    insn_istore_3:
+      STOREI (3);
+      NEXT_INSN;
+
+    insn_lstore_0:
+      STOREL (0);
+      NEXT_INSN;
+
+    insn_lstore_1:
+      STOREL (1);
+      NEXT_INSN;
+
+    insn_lstore_2:
+      STOREL (2);
+      NEXT_INSN;
+
+    insn_lstore_3:
+      STOREL (3);
+      NEXT_INSN;
+
+    insn_fstore_0:
+      STOREF (0);
+      NEXT_INSN;
+
+    insn_fstore_1:
+      STOREF (1);
+      NEXT_INSN;
+
+    insn_fstore_2:
+      STOREF (2);
+      NEXT_INSN;
+
+    insn_fstore_3:
+      STOREF (3);
+      NEXT_INSN;
+
+    insn_dstore_0:
+      STORED (0);
+      NEXT_INSN;
+
+    insn_dstore_1:
+      STORED (1);
+      NEXT_INSN;
+
+    insn_dstore_2:
+      STORED (2);
+      NEXT_INSN;
+
+    insn_dstore_3:
+      STORED (3);
+      NEXT_INSN;
+
+    insn_astore_0:
+      STOREA(0);
+      NEXT_INSN;
+
+    insn_astore_1:
+      STOREA(1);
+      NEXT_INSN;
+
+    insn_astore_2:
+      STOREA(2);
+      NEXT_INSN;
+
+    insn_astore_3:
+      STOREA(3);
+      NEXT_INSN;
+
+    insn_iastore:
+      {
+	jint value = POPI();
+	jint index  = POPI();
+	jintArray arr = (jintArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_lastore:
+      {
+	jlong value = POPL();
+	jint index  = POPI();
+	jlongArray arr = (jlongArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_fastore:
+      {
+	jfloat value = POPF();
+	jint index  = POPI();
+	jfloatArray arr = (jfloatArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_dastore:
+      {
+	jdouble value = POPD();
+	jint index  = POPI();
+	jdoubleArray arr = (jdoubleArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_aastore:
+      {
+	jobject value = POPA();
+	jint index  = POPI();
+	jobjectArray arr = (jobjectArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	_Jv_CheckArrayStore (arr, value);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_bastore:
+      {
+	jbyte value = (jbyte) POPI();
+	jint index  = POPI();
+	jbyteArray arr = (jbyteArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_castore:
+      {
+	jchar value = (jchar) POPI();
+	jint index  = POPI();
+	jcharArray arr = (jcharArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_sastore:
+      {
+	jshort value = (jshort) POPI();
+	jint index  = POPI();
+	jshortArray arr = (jshortArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_pop:
+      sp -= 1;
+      NEXT_INSN;
+
+    insn_pop2:
+      sp -= 2;
+      NEXT_INSN;
+
+    insn_dup:
+      sp[0] = sp[-1];
+      sp += 1;
+      NEXT_INSN;
+
+    insn_dup_x1:
+      dupx (sp, 1, 1); sp+=1;
+      NEXT_INSN;
+
+    insn_dup_x2:
+      dupx (sp, 1, 2); sp+=1;
+      NEXT_INSN;
+
+    insn_dup2:
+      sp[0] = sp[-2];
+      sp[1] = sp[-1];
+      sp += 2;
+      NEXT_INSN;
+
+    insn_dup2_x1:
+      dupx (sp, 2, 1); sp+=2;
+      NEXT_INSN;
+
+    insn_dup2_x2:
+      dupx (sp, 2, 2); sp+=2;
+      NEXT_INSN;
+
+    insn_swap:
+      {
+	jobject tmp1 = POPA();
+	jobject tmp2 = POPA();
+	PUSHA (tmp1);
+	PUSHA (tmp2);
+      }
+      NEXT_INSN;
+
+    insn_iadd:
+      BINOPI(+);
+      NEXT_INSN;
+
+    insn_ladd:
+      BINOPL(+);
+      NEXT_INSN;
+
+    insn_fadd:
+      BINOPF(+);
+      NEXT_INSN;
+
+    insn_dadd:
+      BINOPD(+);
+      NEXT_INSN;
+
+    insn_isub:
+      BINOPI(-);
+      NEXT_INSN;
+
+    insn_lsub:
+      BINOPL(-);
+      NEXT_INSN;
+
+    insn_fsub:
+      BINOPF(-);
+      NEXT_INSN;
+
+    insn_dsub:
+      BINOPD(-);
+      NEXT_INSN;
+
+    insn_imul:
+      BINOPI(*);
+      NEXT_INSN;
+
+    insn_lmul:
+      BINOPL(*);
+      NEXT_INSN;
+
+    insn_fmul:
+      BINOPF(*);
+      NEXT_INSN;
+
+    insn_dmul:
+      BINOPD(*);
+      NEXT_INSN;
+
+    insn_idiv:
+      {
+	SAVE_PC();
+	jint value2 = POPI();
+	jint value1 = POPI();
+	jint res = _Jv_divI (value1, value2);
+	PUSHI (res);
+      }
+      NEXT_INSN;
+
+    insn_ldiv:
+      {
+	SAVE_PC();
+	jlong value2 = POPL();
+	jlong value1 = POPL();
+	jlong res = _Jv_divJ (value1, value2);
+	PUSHL (res);
+      }
+      NEXT_INSN;
+
+    insn_fdiv:
+      {
+	jfloat value2 = POPF();
+	jfloat value1 = POPF();
+	jfloat res = value1 / value2;
+	PUSHF (res);
+      }
+      NEXT_INSN;
+
+    insn_ddiv:
+      {
+	jdouble value2 = POPD();
+	jdouble value1 = POPD();
+	jdouble res = value1 / value2;
+	PUSHD (res);
+      }
+      NEXT_INSN;
+
+    insn_irem:
+      {
+	SAVE_PC();
+	jint value2 = POPI();
+	jint value1 =  POPI();
+	jint res = _Jv_remI (value1, value2);
+	PUSHI (res);
+      }
+      NEXT_INSN;
+
+    insn_lrem:
+      {
+	SAVE_PC();
+	jlong value2 = POPL();
+	jlong value1 = POPL();
+	jlong res = _Jv_remJ (value1, value2);
+	PUSHL (res);
+      }
+      NEXT_INSN;
+
+    insn_frem:
+      {
+	jfloat value2 = POPF();
+	jfloat value1 = POPF();
+	jfloat res    = __ieee754_fmod (value1, value2);
+	PUSHF (res);
+      }
+      NEXT_INSN;
+
+    insn_drem:
+      {
+	jdouble value2 = POPD();
+	jdouble value1 = POPD();
+	jdouble res    = __ieee754_fmod (value1, value2);
+	PUSHD (res);
+      }
+      NEXT_INSN;
+
+    insn_ineg:
+      {
+	jint value = POPI();
+	PUSHI (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_lneg:
+      {
+	jlong value = POPL();
+	PUSHL (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_fneg:
+      {
+	jfloat value = POPF();
+	PUSHF (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_dneg:
+      {
+	jdouble value = POPD();
+	PUSHD (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_ishl:
+      {
+	jint shift = (POPI() & 0x1f);
+	jint value = POPI();
+	PUSHI (value << shift);
+      }
+      NEXT_INSN;
+
+    insn_lshl:
+      {
+	jint shift = (POPI() & 0x3f);
+	jlong value = POPL();
+	PUSHL (value << shift);
+      }
+      NEXT_INSN;
+
+    insn_ishr:
+      {
+	jint shift = (POPI() & 0x1f);
+	jint value = POPI();
+	PUSHI (value >> shift);
+      }
+      NEXT_INSN;
+
+    insn_lshr:
+      {
+	jint shift = (POPI() & 0x3f);
+	jlong value = POPL();
+	PUSHL (value >> shift);
+      }
+      NEXT_INSN;
+
+    insn_iushr:
+      {
+	jint shift = (POPI() & 0x1f);
+	_Jv_uint value = (_Jv_uint) POPI();
+	PUSHI ((jint) (value >> shift));
+      }
+      NEXT_INSN;
+
+    insn_lushr:
+      {
+	jint shift = (POPI() & 0x3f);
+	_Jv_ulong value = (_Jv_ulong) POPL();
+	PUSHL ((jlong) (value >> shift));
+      }
+      NEXT_INSN;
+
+    insn_iand:
+      BINOPI (&);
+      NEXT_INSN;
+
+    insn_land:
+      BINOPL (&);
+      NEXT_INSN;
+
+    insn_ior:
+      BINOPI (|);
+      NEXT_INSN;
+
+    insn_lor:
+      BINOPL (|);
+      NEXT_INSN;
+
+    insn_ixor:
+      BINOPI (^);
+      NEXT_INSN;
+
+    insn_lxor:
+      BINOPL (^);
+      NEXT_INSN;
+
+    insn_iinc:
+      {
+	jint index  = GET1U ();
+	jint amount = GET1S ();
+	locals[index].i += amount;
+      }
+      NEXT_INSN;
+
+    insn_i2l:
+      {jlong value = POPI(); PUSHL (value);}
+      NEXT_INSN;
+
+    insn_i2f:
+      {jfloat value = POPI(); PUSHF (value);}
+      NEXT_INSN;
+
+    insn_i2d:
+      {jdouble value = POPI(); PUSHD (value);}
+      NEXT_INSN;
+
+    insn_l2i:
+      {jint value = POPL(); PUSHI (value);}
+      NEXT_INSN;
+
+    insn_l2f:
+      {jfloat value = POPL(); PUSHF (value);}
+      NEXT_INSN;
+
+    insn_l2d:
+      {jdouble value = POPL(); PUSHD (value);}
+      NEXT_INSN;
+
+    insn_f2i:
+      {
+	using namespace java::lang;
+	jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
+	PUSHI(value);
+      }
+      NEXT_INSN;
+
+    insn_f2l:
+      {
+	using namespace java::lang;
+	jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
+	PUSHL(value);
+      }
+      NEXT_INSN;
+
+    insn_f2d:
+      { jdouble value = POPF (); PUSHD(value); }
+      NEXT_INSN;
+
+    insn_d2i:
+      {
+	using namespace java::lang;
+	jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
+	PUSHI(value);
+      }
+      NEXT_INSN;
+
+    insn_d2l:
+      {
+	using namespace java::lang;
+	jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
+	PUSHL(value);
+      }
+      NEXT_INSN;
+
+    insn_d2f:
+      { jfloat value = POPD (); PUSHF(value); }
+      NEXT_INSN;
+
+    insn_i2b:
+      { jbyte value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_i2c:
+      { jchar value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_i2s:
+      { jshort value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_lcmp:
+      {
+	jlong value2 = POPL ();
+	jlong value1 = POPL ();
+	if (value1 > value2)
+	  { PUSHI (1); }
+	else if (value1 == value2)
+	  { PUSHI (0); }
+	else
+	  { PUSHI (-1); }
+      }
+      NEXT_INSN;
+
+    insn_fcmpl:
+      tmpval = -1;
+      goto fcmp;
+
+    insn_fcmpg:
+      tmpval = 1;
+
+    fcmp:
+      {
+	jfloat value2 = POPF ();
+	jfloat value1 = POPF ();
+	if (value1 > value2)
+	  PUSHI (1);
+	else if (value1 == value2)
+	  PUSHI (0);
+	else if (value1 < value2)
+	  PUSHI (-1);
+	else
+	  PUSHI (tmpval);
+      }
+      NEXT_INSN;
+
+    insn_dcmpl:
+      tmpval = -1;
+      goto dcmp;
+
+    insn_dcmpg:
+      tmpval = 1;
+
+    dcmp:
+      {
+	jdouble value2 = POPD ();
+	jdouble value1 = POPD ();
+	if (value1 > value2)
+	  PUSHI (1);
+	else if (value1 == value2)
+	  PUSHI (0);
+	else if (value1 < value2)
+	  PUSHI (-1);
+	else
+	  PUSHI (tmpval);
+      }
+      NEXT_INSN;
+
+    insn_ifeq:
+      {
+	if (POPI() == 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifne:
+      {
+	if (POPI() != 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_iflt:
+      {
+	if (POPI() < 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifge:
+      {
+	if (POPI() >= 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifgt:
+      {
+	if (POPI() > 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifle:
+      {
+	if (POPI() <= 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpeq:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 == value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpne:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 != value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmplt:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 < value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpge:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 >= value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpgt:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 > value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmple:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 <= value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_acmpeq:
+      {
+	jobject value2 = POPA();
+	jobject value1 = POPA();
+	if (value1 == value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_acmpne:
+      {
+	jobject value2 = POPA();
+	jobject value1 = POPA();
+	if (value1 != value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_goto_w:
+#ifndef DIRECT_THREADED
+      // For direct threaded, goto and goto_w are the same.
+      pc = pc - 1 + get4 (pc);
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_goto:
+      TAKE_GOTO;
+      NEXT_INSN;
+
+    insn_jsr_w:
+#ifndef DIRECT_THREADED
+      // For direct threaded, jsr and jsr_w are the same.
+      {
+	pc_t next = pc - 1 + get4 (pc);
+	pc += 4;
+	PUSHA ((jobject) pc);
+	pc = next;
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_jsr:
+      {
+	pc_t next = GOTO_VAL();
+	SKIP_GOTO;
+	PUSHA ((jobject) pc);
+	pc = next;
+      }
+      NEXT_INSN;
+
+    insn_ret:
+      {
+	jint index = GET1U ();
+	pc = (pc_t) PEEKA (index);
+      }
+      NEXT_INSN;
+
+    insn_tableswitch:
+      {
+#ifdef DIRECT_THREADED
+	void *def = (pc++)->datum;
+
+	int index = POPI();
+
+	jint low = INTVAL ();
+	jint high = INTVAL ();
+
+	if (index < low || index > high)
+	  pc = (insn_slot *) def;
+	else
+	  pc = (insn_slot *) ((pc + index - low)->datum);
+#else
+	pc_t base_pc = pc - 1;
+	int index = POPI ();
+
+	pc_t base = (pc_t) bytecode ();
+	while ((pc - base) % 4 != 0)
+	  ++pc;
+
+	jint def = get4 (pc);
+	jint low = get4 (pc + 4);
+	jint high = get4 (pc + 8);
+	if (index < low || index > high)
+	  pc = base_pc + def;
+	else
+	  pc = base_pc + get4 (pc + 4 * (index - low + 3));
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+    insn_lookupswitch:
+      {
+#ifdef DIRECT_THREADED
+	void *def = (pc++)->insn;
+
+	int index = POPI();
+
+	jint npairs = INTVAL ();
+
+	int max = npairs - 1;
+	int min = 0;
+
+	// Simple binary search...
+	while (min < max)
+	  {
+	    int half = (min + max) / 2;
+	    int match = pc[2 * half].int_val;
+
+	    if (index == match)
+	      {
+		// Found it.
+		pc = (insn_slot *) pc[2 * half + 1].datum;
+		NEXT_INSN;
+	      }
+	    else if (index < match)
+	      // We can use HALF - 1 here because we check again on
+	      // loop exit.
+	      max = half - 1;
+	    else
+	      // We can use HALF + 1 here because we check again on
+	      // loop exit.
+	      min = half + 1;
+	  }
+	if (index == pc[2 * min].int_val)
+	  pc = (insn_slot *) pc[2 * min + 1].datum;
+	else
+	  pc = (insn_slot *) def;
+#else
+	unsigned char *base_pc = pc-1;
+	int index = POPI();
+
+	unsigned char* base = bytecode ();
+	while ((pc-base) % 4 != 0)
+	  ++pc;
+
+	jint def     = get4 (pc);
+	jint npairs  = get4 (pc+4);
+
+	int max = npairs-1;
+	int min = 0;
+
+	// Simple binary search...
+	while (min < max)
+	  {
+	    int half = (min+max)/2;
+	    int match = get4 (pc+ 4*(2 + 2*half));
+
+	    if (index == match)
+	      min = max = half;
+	    else if (index < match)
+	      // We can use HALF - 1 here because we check again on
+	      // loop exit.
+	      max = half - 1;
+	    else
+	      // We can use HALF + 1 here because we check again on
+	      // loop exit.
+	      min = half + 1;
+	  }
+
+	if (index == get4 (pc+ 4*(2 + 2*min)))
+	  pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
+	else
+	  pc = base_pc + def;    
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+    insn_areturn:
+      *(jobject *) retp = POPA ();
+      return;
+
+    insn_lreturn:
+      *(jlong *) retp = POPL ();
+      return;
+
+    insn_freturn:
+      *(jfloat *) retp = POPF ();
+      return;
+
+    insn_dreturn:
+      *(jdouble *) retp = POPD ();
+      return;
+
+    insn_ireturn:
+      *(jint *) retp = POPI ();
+      return;
+
+    insn_return:
+      return;
+
+    insn_getstatic:
+      {
+	jint fieldref_index = GET2U ();
+        SAVE_PC(); // Constant pool resolution could throw.
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	if ((field->flags & Modifier::STATIC) == 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field no longer static"));
+
+	jclass type = field->type;
+
+	// We rewrite the instruction once we discover what it refers
+	// to.
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes)
+	      {
+	      case 1:
+		PUSHI (*field->u.byte_addr);
+		newinsn = AMPAMP (getstatic_resolved_1);
+		break;
+
+	      case 2:
+		if (type == JvPrimClass (char))
+		  {
+		    PUSHI (*field->u.char_addr);
+		    newinsn = AMPAMP (getstatic_resolved_char);
+		  }
+		else
+		  {
+		    PUSHI (*field->u.short_addr);
+		    newinsn = AMPAMP (getstatic_resolved_short);
+		  }
+		break;
+
+	      case 4:
+	        PUSHI(*field->u.int_addr);
+		newinsn = AMPAMP (getstatic_resolved_4);
+		break;
+
+	      case 8:
+	        PUSHL(*field->u.long_addr);
+		newinsn = AMPAMP (getstatic_resolved_8);
+		break;
+	      }
+	  }
+	else
+	  {
+	    PUSHA(*field->u.object_addr);
+	    newinsn = AMPAMP (getstatic_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].datum = field->u.addr;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    getstatic_resolved_1:
+      PUSHI (*(jbyte *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_char:
+      PUSHI (*(jchar *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_short:
+      PUSHI (*(jshort *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_4:
+      PUSHI (*(jint *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_8:
+      PUSHL (*(jlong *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_obj:
+      PUSHA (*(jobject *) AVAL ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_getfield:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	if ((field->flags & Modifier::STATIC) != 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field is static"));
+
+	jclass type = field->type;
+	jint field_offset = field->u.boffset;
+
+	jobject obj   = POPA();
+	NULLCHECK(obj);
+
+	void *newinsn = NULL;
+	_Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes)
+	      {
+	      case 1:
+	        PUSHI (val->byte_value);
+		newinsn = AMPAMP (getfield_resolved_1);
+		break;
+
+	      case 2:
+		if (type == JvPrimClass (char))
+		  {
+		    PUSHI (val->char_value);
+		    newinsn = AMPAMP (getfield_resolved_char);
+		  }
+		else
+		  {
+		    PUSHI (val->short_value);
+		    newinsn = AMPAMP (getfield_resolved_short);
+		  }
+		break;
+
+	      case 4:
+		PUSHI (val->int_value);
+		newinsn = AMPAMP (getfield_resolved_4);
+		break;
+
+	      case 8:
+	        PUSHL (val->long_value);
+		newinsn = AMPAMP (getfield_resolved_8);
+		break;
+	      }
+	  }
+	else
+	  {
+	    PUSHA (val->object_value);
+	    newinsn = AMPAMP (getfield_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].int_val = field_offset;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    getfield_resolved_1:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jbyte *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_char:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jchar *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_short:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jshort *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_4:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jint *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_8:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHL (*(jlong *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_obj:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHA (*(jobject *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_putstatic:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	jclass type = field->type;
+
+	// ResolvePoolEntry cannot check this
+	if ((field->flags & Modifier::STATIC) == 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field no longer static"));
+
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes) 
+	      {
+	      case 1:
+		{
+		  jint value = POPI();
+		  *field->u.byte_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_1);
+		  break;
+		}
+
+	      case 2:
+		{
+		  jint value = POPI();
+		  *field->u.char_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_2);
+		  break;
+		}
+
+	      case 4:
+		{
+		  jint value = POPI();
+		  *field->u.int_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_4);
+		  break;
+		}
+
+	      case 8:
+		{
+		  jlong value = POPL();
+		  *field->u.long_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_8);
+		  break;
+		}
+	      }
+	  }
+	else
+	  {
+	    jobject value = POPA();
+	    *field->u.object_addr = value;
+	    newinsn = AMPAMP (putstatic_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].datum = field->u.addr;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    putstatic_resolved_1:
+      *(jbyte *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_2:
+      *(jchar *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_4:
+      *(jint *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_8:
+      *(jlong *) AVAL () = POPL ();
+      NEXT_INSN;
+
+    putstatic_resolved_obj:
+      *(jobject *) AVAL () = POPA ();
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_putfield:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	jclass type = field->type;
+
+	if ((field->flags & Modifier::STATIC) != 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field is static"));
+
+	jint field_offset = field->u.boffset;
+
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes) 
+	      {
+	      case 1:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jbyte*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_1);
+		  break;
+		}
+
+	      case 2:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jchar*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_2);
+		  break;
+		}
+
+	      case 4:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jint*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_4);
+		  break;
+		}
+
+	      case 8:
+		{
+		  jlong   value = POPL();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jlong*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_8);
+		  break;
+		}
+	      }
+	  }
+	else
+	  {
+	    jobject value = POPA();
+	    jobject obj   = POPA();
+	    NULLCHECK(obj);
+	    *(jobject*) ((char*)obj + field_offset) = value;
+	    newinsn = AMPAMP (putfield_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].int_val = field_offset;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    putfield_resolved_1:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jbyte *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_2:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jchar *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_4:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jint *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_8:
+      {
+	jlong val = POPL ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jlong *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_obj:
+      {
+	jobject val = POPA ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jobject *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_invokespecial:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	// We don't use NULLCHECK here because we can't rely on that
+	// working for <init>.  So instead we do an explicit test.
+	if (! sp[0].o)
+	  {
+	    SAVE_PC();
+	    throw_null_pointer_exception ();
+	  }
+
+	fun = (void (*)()) rmeth->method->ncode;
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokespecial_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokespecial_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	// We don't use NULLCHECK here because we can't rely on that
+	// working for <init>.  So instead we do an explicit test.
+	if (! sp[0].o)
+	  {
+	    throw_null_pointer_exception ();
+	  }
+	fun = (void (*)()) rmeth->method->ncode;
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_invokestatic:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	fun = (void (*)()) rmeth->method->ncode;
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokestatic_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokestatic_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	fun = (void (*)()) rmeth->method->ncode;
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_invokeinterface:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	jobject rcv = sp[0].o;
+
+	NULLCHECK (rcv);
+
+	fun = (void (*)())
+	  _Jv_LookupInterfaceMethod (rcv->getClass (),
+				     rmeth->method->name,
+				     rmeth->method->signature);
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokeinterface_resolved;
+	pc[-1].datum = rmeth;
+#else
+	// Skip dummy bytes.
+	pc += 2;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokeinterface_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	jobject rcv = sp[0].o;
+	NULLCHECK (rcv);
+	fun = (void (*)())
+	  _Jv_LookupInterfaceMethod (rcv->getClass (),
+				     rmeth->method->name,
+				     rmeth->method->signature);
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_new:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+							  index)).clazz;
+	/* VM spec, section 3.11.5 */
+	if ((klass->getModifiers() & Modifier::ABSTRACT)
+	    || klass->isInterface())
+	  throw new java::lang::InstantiationException;
+	jobject res = _Jv_AllocObject (klass);
+	PUSHA (res);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&new_resolved;
+	pc[-1].datum = klass;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    new_resolved:
+      {
+	jclass klass = (jclass) AVAL ();
+	jobject res = _Jv_AllocObject (klass);
+	PUSHA (res);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_newarray:
+      {
+	int atype = GET1U ();
+	int size  = POPI();
+	jobject result = _Jv_NewArray (atype, size);
+	PUSHA (result);
+      }
+      NEXT_INSN;
+
+    insn_anewarray:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+							  index)).clazz;
+	int size  = POPI();
+	jobject result = _Jv_NewObjectArray (size, klass, 0);
+	PUSHA (result);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&anewarray_resolved;
+	pc[-1].datum = klass;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    anewarray_resolved:
+      {
+	jclass klass = (jclass) AVAL ();
+	int size = POPI ();
+	jobject result = _Jv_NewObjectArray (size, klass, 0);
+	PUSHA (result);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_arraylength:
+      {
+	__JArray *arr = (__JArray*)POPA();
+	NULLARRAYCHECK (arr);
+	PUSHI (arr->length);
+      }
+      NEXT_INSN;
+
+    insn_athrow:
+      {
+	jobject value = POPA();
+	throw static_cast<jthrowable>(value);
+      }
+      NEXT_INSN;
+
+    insn_checkcast:
+      {
+        SAVE_PC();
+	jobject value = POPA();
+	jint index = GET2U ();
+	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						       index)).clazz;
+
+	value = (jobject) _Jv_CheckCast (to, value);
+
+	PUSHA (value);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&checkcast_resolved;
+	pc[-1].datum = to;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    checkcast_resolved:
+      {
+        SAVE_PC();
+	jobject value = POPA ();
+	jclass to = (jclass) AVAL ();
+	value = (jobject) _Jv_CheckCast (to, value);
+	PUSHA (value);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_instanceof:
+      {
+        SAVE_PC();
+	jobject value = POPA();
+	jint index = GET2U ();
+	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						       index)).clazz;
+	PUSHI (to->isInstance (value));
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&instanceof_resolved;
+	pc[-1].datum = to;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    instanceof_resolved:
+      {
+	jobject value = POPA ();
+	jclass to = (jclass) AVAL ();
+	PUSHI (to->isInstance (value));
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_monitorenter:
+      {
+	jobject value = POPA();
+	NULLCHECK(value);
+	_Jv_MonitorEnter (value);
+      }
+      NEXT_INSN;
+
+    insn_monitorexit:
+      {
+	jobject value = POPA();
+	NULLCHECK(value);
+	_Jv_MonitorExit (value);
+      }
+      NEXT_INSN;
+
+    insn_ifnull:
+      {
+	jobject val = POPA();
+	if (val == NULL)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifnonnull:
+      {
+	jobject val = POPA();
+	if (val != NULL)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_multianewarray:
+      {
+	SAVE_PC();
+	int kind_index = GET2U ();
+	int dim        = GET1U ();
+
+	jclass type    
+	  = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+					       kind_index)).clazz;
+	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
+
+	for (int i = dim - 1; i >= 0; i--)
+	  {
+	    sizes[i] = POPI ();
+	  }
+
+	jobject res    = _Jv_NewMultiArray (type,dim, sizes);
+
+	PUSHA (res);
+      }
+      NEXT_INSN;
+
+#ifndef DIRECT_THREADED
+    insn_wide:
+      {
+	jint the_mod_op = get1u (pc++);
+	jint wide       = get2u (pc); pc += 2;
+
+	switch (the_mod_op)
+	  {
+	  case op_istore:
+	    STOREI (wide);
+	    NEXT_INSN;
+
+	  case op_fstore:
+	    STOREF (wide);
+	    NEXT_INSN;
+
+	  case op_astore:
+	    STOREA (wide);
+	    NEXT_INSN;
+
+	  case op_lload:
+	    LOADL (wide);
+	    NEXT_INSN;
+
+	  case op_dload:
+	    LOADD (wide);
+	    NEXT_INSN;
+
+	  case op_iload:
+	    LOADI (wide);
+	    NEXT_INSN;
+
+	  case op_fload:
+	    LOADF (wide);
+	    NEXT_INSN;
+
+	  case op_aload:
+	    LOADA (wide);
+	    NEXT_INSN;
+
+	  case op_lstore:
+	    STOREL (wide);
+	    NEXT_INSN;
+
+	  case op_dstore:
+	    STORED (wide);
+	    NEXT_INSN;
+
+	  case op_ret:
+	    pc = (unsigned char*) PEEKA (wide);
+	    NEXT_INSN;
+
+	  case op_iinc:
+	    {
+	      jint amount = get2s (pc); pc += 2;
+	      jint value = PEEKI (wide);
+	      POKEI (wide, value+amount);
+	    }
+	    NEXT_INSN;
+
+	  default:
+	    throw_internal_error ("illegal bytecode modified by wide");
+	  }
+
+      }
+#endif /* DIRECT_THREADED */
+    }
+  catch (java::lang::Throwable *ex)
+    {
+#ifdef DIRECT_THREADED
+      void *logical_pc = (void *) ((insn_slot *) pc - 1);
+#else
+      int logical_pc = pc - 1 - bytecode ();
+#endif
+      _Jv_InterpException *exc = meth->exceptions ();
+      jclass exc_class = ex->getClass ();
+
+      for (int i = 0; i < meth->exc_count; i++)
+	{
+	  if (PCVAL (exc[i].start_pc) <= logical_pc
+	      && logical_pc < PCVAL (exc[i].end_pc))
+	    {
+#ifdef DIRECT_THREADED
+	      jclass handler = (jclass) exc[i].handler_type.p;
+#else
+	      jclass handler = NULL;
+	      if (exc[i].handler_type.i != 0)
+		handler = (_Jv_Linker::resolve_pool_entry (defining_class,
+							     exc[i].handler_type.i)).clazz;
+#endif /* DIRECT_THREADED */
+
+	      if (handler == NULL || handler->isAssignableFrom (exc_class))
+		{
+
+#ifdef DIRECT_THREADED
+		  pc = (insn_slot *) exc[i].handler_pc.p;
+#else
+		  pc = bytecode () + exc[i].handler_pc.i;
+#endif /* DIRECT_THREADED */
+		  sp = stack;
+		  sp++->o = ex; // Push exception.
+		  NEXT_INSN;
+		}
+	    }
+	}
+
+      // No handler, so re-throw.
+      throw ex;
+    }
Index: /notnfs/kgallowa/vanilla/libjava/interpret.cc
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/interpret.cc	(revision 115793)
+++ /notnfs/kgallowa/vanilla/libjava/interpret.cc	(working copy)
@@ -37,6 +37,8 @@
 #include <execution.h>
 #include <java/lang/reflect/Modifier.h>
 
+#include <gnu/classpath/jdwp/Jdwp.h>
+
 #ifdef INTERPRETER
 
 // Execution engine for interpreted code.
@@ -152,18 +154,36 @@
 # define LOADD(I)  LOADL(I)
 #endif
 
-#define STOREA(I) locals[I].o = (--sp)->o
-#define STOREI(I) locals[I].i = (--sp)->i
-#define STOREF(I) locals[I].f = (--sp)->f
+#define STOREA(I) 		\
+DEBUG_LOCALS_INSN(I, 'o')	\
+locals[I].o = (--sp)->o
+#define STOREI(I) 		\
+DEBUG_LOCALS_INSN (I, 'i')	\
+locals[I].i = (--sp)->i
+#define STOREF(I)  		\
+DEBUG_LOCALS_INSN (I, 'f')	\
+locals[I].f = (--sp)->f
 #if SIZEOF_VOID_P == 8
-# define STOREL(I) (sp -= 2, locals[I].l = sp->l)
-# define STORED(I) (sp -= 2, locals[I].d = sp->d)
+# define STOREL(I)  			\
+DEBUG_LOCALS_INSN (I, 'l')			\
+(sp -= 2, locals[I].l = sp->l)
+# define STORED(I) 				\
+DEBUG_LOCALS_INSN (I, 'd')			\
+(sp -= 2, locals[I].d = sp->d)
+
 #else
-# define STOREL(I) do { jint __idx = (I); \
-    		       locals[__idx+1].ia[0] = (--sp)->ia[0]; \
-    		       locals[__idx].ia[0] = (--sp)->ia[0]; \
-		   } while (0)
-# define STORED(I) STOREL(I)
+# define STOREL(I)		\
+DEBUG_LOCALS_INSN(I, 'l')	\
+do { jint __idx = (I); 	\
+     locals[__idx+1].ia[0] = (--sp)->ia[0]; \
+     locals[__idx].ia[0] = (--sp)->ia[0]; 	\
+   } while (0)
+# define STORED(I)		\
+DEBUG_LOCALS_INSN(I, 'd')	\
+do { jint __idx = (I); 	\
+     locals[__idx+1].ia[0] = (--sp)->ia[0]; \
+     locals[__idx].ia[0] = (--sp)->ia[0]; 	\
+   } while (0)
 #endif
 
 #define PEEKI(I)  (locals+(I))->i
@@ -169,7 +189,9 @@
 #define PEEKI(I)  (locals+(I))->i
 #define PEEKA(I)  (locals+(I))->o
 
-#define POKEI(I,V)  ((locals+(I))->i = (V))
+#define POKEI(I,V)  	\
+DEBUG_LOCALS_INSN(I,i)	\
+((locals+(I))->i = (V))
 
 
 #define BINOPI(OP) { \
@@ -258,6 +280,16 @@
 }
 
 void
+_Jv_InterpMethod::run_normal_debug (ffi_cif *,
+			      void* ret,
+			      ffi_raw * args,
+			      void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+  run_debug (ret, args, _this);
+}
+
+void
 _Jv_InterpMethod::run_synch_object (ffi_cif *,
 				    void* ret,
 				    ffi_raw * args,
@@ -272,6 +304,20 @@
 }
 
 void
+_Jv_InterpMethod::run_synch_object_debug (ffi_cif *,
+				    void* ret,
+				    ffi_raw * args,
+				    void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+
+  jobject rcv = (jobject) args[0].ptr;
+  JvSynchronize mutex (rcv);
+
+  run_debug (ret, args, _this);
+}
+
+void
 _Jv_InterpMethod::run_class (ffi_cif *,
 			     void* ret,
 			     ffi_raw * args,
@@ -283,6 +329,17 @@
 }
 
 void
+_Jv_InterpMethod::run_class_debug (ffi_cif *,
+			     void* ret,
+			     ffi_raw * args,
+			     void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+  _Jv_InitClass (_this->defining_class);
+  run_debug (ret, args, _this);
+}
+
+void
 _Jv_InterpMethod::run_synch_class (ffi_cif *,
 				   void* ret,
 				   ffi_raw * args,
@@ -297,6 +354,21 @@
   run (ret, args, _this);
 }
 
+void
+_Jv_InterpMethod::run_synch_class_debug (ffi_cif *,
+				   void* ret,
+				   ffi_raw * args,
+				   void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+
+  jclass sync = _this->defining_class;
+  _Jv_InitClass (sync);
+  JvSynchronize mutex (sync);
+
+  run_debug (ret, args, _this);
+}
+
 #ifdef DIRECT_THREADED
 // "Compile" a method by turning it from bytecode to direct-threaded
 // code.
@@ -805,2709 +877,239 @@
 void
 _Jv_InterpMethod::run (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
 {
-  using namespace java::lang::reflect;
+#undef DEBUG
+#undef DEBUG_LOCALS_INSN
+#define DEBUG_LOCALS_INSN(s, t) {}
 
-  // FRAME_DESC registers this particular invocation as the top-most
-  // interpreter frame.  This lets the stack tracing code (for
-  // Throwable) print information about the method being interpreted
-  // rather than about the interpreter itself.  FRAME_DESC has a
-  // destructor so it cleans up automatically when the interpreter
-  // returns.
-  java::lang::Thread *thread = java::lang::Thread::currentThread();
-  _Jv_InterpFrame frame_desc (meth, thread);
+#include "interpret-run.cc"
+}
 
-  _Jv_word stack[meth->max_stack];
-  _Jv_word *sp = stack;
+void
+_Jv_InterpMethod::run_debug (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
+{
+/* Used to keep track of local variable type
+ * 
+ * Possible Types:
+ * o object
+ * i integer
+ * f float
+ * l long 
+ * d double 
+ */
+#define DEBUG
+#undef DEBUG_LOCALS_INSN
+#define DEBUG_LOCALS_INSN(s, t) { }
 
-  _Jv_word locals[meth->max_locals];
+#include "interpret-run.cc"
+}
 
-#define INSN_LABEL(op) &&insn_##op
+static void
+throw_internal_error (const char *msg)
+{
+  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
+}
 
-  static const void *const insn_target[] = 
-  {
-    INSN_LABEL(nop),
-    INSN_LABEL(aconst_null),
-    INSN_LABEL(iconst_m1),
-    INSN_LABEL(iconst_0),
-    INSN_LABEL(iconst_1),
-    INSN_LABEL(iconst_2),
-    INSN_LABEL(iconst_3),
-    INSN_LABEL(iconst_4),
-    INSN_LABEL(iconst_5),
-    INSN_LABEL(lconst_0),
-    INSN_LABEL(lconst_1),
-    INSN_LABEL(fconst_0),
-    INSN_LABEL(fconst_1),
-    INSN_LABEL(fconst_2),
-    INSN_LABEL(dconst_0),
-    INSN_LABEL(dconst_1),
-    INSN_LABEL(bipush),
-    INSN_LABEL(sipush),
-    INSN_LABEL(ldc),
-    INSN_LABEL(ldc_w),
-    INSN_LABEL(ldc2_w),
-    INSN_LABEL(iload),
-    INSN_LABEL(lload),
-    INSN_LABEL(fload),
-    INSN_LABEL(dload),
-    INSN_LABEL(aload),
-    INSN_LABEL(iload_0),
-    INSN_LABEL(iload_1),
-    INSN_LABEL(iload_2),
-    INSN_LABEL(iload_3),
-    INSN_LABEL(lload_0),
-    INSN_LABEL(lload_1),
-    INSN_LABEL(lload_2),
-    INSN_LABEL(lload_3),
-    INSN_LABEL(fload_0),
-    INSN_LABEL(fload_1),
-    INSN_LABEL(fload_2),
-    INSN_LABEL(fload_3),
-    INSN_LABEL(dload_0),
-    INSN_LABEL(dload_1),
-    INSN_LABEL(dload_2),
-    INSN_LABEL(dload_3),
-    INSN_LABEL(aload_0),
-    INSN_LABEL(aload_1),
-    INSN_LABEL(aload_2),
-    INSN_LABEL(aload_3),
-    INSN_LABEL(iaload),
-    INSN_LABEL(laload),
-    INSN_LABEL(faload),
-    INSN_LABEL(daload),
-    INSN_LABEL(aaload),
-    INSN_LABEL(baload),
-    INSN_LABEL(caload),
-    INSN_LABEL(saload),
-    INSN_LABEL(istore),
-    INSN_LABEL(lstore),
-    INSN_LABEL(fstore),
-    INSN_LABEL(dstore),
-    INSN_LABEL(astore),
-    INSN_LABEL(istore_0),
-    INSN_LABEL(istore_1),
-    INSN_LABEL(istore_2),
-    INSN_LABEL(istore_3),
-    INSN_LABEL(lstore_0),
-    INSN_LABEL(lstore_1),
-    INSN_LABEL(lstore_2),
-    INSN_LABEL(lstore_3),
-    INSN_LABEL(fstore_0),
-    INSN_LABEL(fstore_1),
-    INSN_LABEL(fstore_2),
-    INSN_LABEL(fstore_3),
-    INSN_LABEL(dstore_0),
-    INSN_LABEL(dstore_1),
-    INSN_LABEL(dstore_2),
-    INSN_LABEL(dstore_3),
-    INSN_LABEL(astore_0),
-    INSN_LABEL(astore_1),
-    INSN_LABEL(astore_2),
-    INSN_LABEL(astore_3),
-    INSN_LABEL(iastore),
-    INSN_LABEL(lastore),
-    INSN_LABEL(fastore),
-    INSN_LABEL(dastore),
-    INSN_LABEL(aastore),
-    INSN_LABEL(bastore),
-    INSN_LABEL(castore),
-    INSN_LABEL(sastore),
-    INSN_LABEL(pop),
-    INSN_LABEL(pop2),
-    INSN_LABEL(dup),
-    INSN_LABEL(dup_x1),
-    INSN_LABEL(dup_x2),
-    INSN_LABEL(dup2),
-    INSN_LABEL(dup2_x1),
-    INSN_LABEL(dup2_x2),
-    INSN_LABEL(swap),
-    INSN_LABEL(iadd),
-    INSN_LABEL(ladd),
-    INSN_LABEL(fadd),
-    INSN_LABEL(dadd),
-    INSN_LABEL(isub),
-    INSN_LABEL(lsub),
-    INSN_LABEL(fsub),
-    INSN_LABEL(dsub),
-    INSN_LABEL(imul),
-    INSN_LABEL(lmul),
-    INSN_LABEL(fmul),
-    INSN_LABEL(dmul),
-    INSN_LABEL(idiv),
-    INSN_LABEL(ldiv),
-    INSN_LABEL(fdiv),
-    INSN_LABEL(ddiv),
-    INSN_LABEL(irem),
-    INSN_LABEL(lrem),
-    INSN_LABEL(frem),
-    INSN_LABEL(drem),
-    INSN_LABEL(ineg),
-    INSN_LABEL(lneg),
-    INSN_LABEL(fneg),
-    INSN_LABEL(dneg),
-    INSN_LABEL(ishl),
-    INSN_LABEL(lshl),
-    INSN_LABEL(ishr),
-    INSN_LABEL(lshr),
-    INSN_LABEL(iushr),
-    INSN_LABEL(lushr),
-    INSN_LABEL(iand),
-    INSN_LABEL(land),
-    INSN_LABEL(ior),
-    INSN_LABEL(lor),
-    INSN_LABEL(ixor),
-    INSN_LABEL(lxor),
-    INSN_LABEL(iinc),
-    INSN_LABEL(i2l),
-    INSN_LABEL(i2f),
-    INSN_LABEL(i2d),
-    INSN_LABEL(l2i),
-    INSN_LABEL(l2f),
-    INSN_LABEL(l2d),
-    INSN_LABEL(f2i),
-    INSN_LABEL(f2l),
-    INSN_LABEL(f2d),
-    INSN_LABEL(d2i),
-    INSN_LABEL(d2l),
-    INSN_LABEL(d2f),
-    INSN_LABEL(i2b),
-    INSN_LABEL(i2c),
-    INSN_LABEL(i2s),
-    INSN_LABEL(lcmp),
-    INSN_LABEL(fcmpl),
-    INSN_LABEL(fcmpg),
-    INSN_LABEL(dcmpl),
-    INSN_LABEL(dcmpg),
-    INSN_LABEL(ifeq),
-    INSN_LABEL(ifne),
-    INSN_LABEL(iflt),
-    INSN_LABEL(ifge),
-    INSN_LABEL(ifgt),
-    INSN_LABEL(ifle),
-    INSN_LABEL(if_icmpeq),
-    INSN_LABEL(if_icmpne),
-    INSN_LABEL(if_icmplt),
-    INSN_LABEL(if_icmpge),
-    INSN_LABEL(if_icmpgt),
-    INSN_LABEL(if_icmple),
-    INSN_LABEL(if_acmpeq),
-    INSN_LABEL(if_acmpne),
-    INSN_LABEL(goto), 
-    INSN_LABEL(jsr),
-    INSN_LABEL(ret),
-    INSN_LABEL(tableswitch),
-    INSN_LABEL(lookupswitch),
-    INSN_LABEL(ireturn),
-    INSN_LABEL(lreturn),
-    INSN_LABEL(freturn),
-    INSN_LABEL(dreturn),
-    INSN_LABEL(areturn),
-    INSN_LABEL(return),
-    INSN_LABEL(getstatic),
-    INSN_LABEL(putstatic),
-    INSN_LABEL(getfield),
-    INSN_LABEL(putfield),
-    INSN_LABEL(invokevirtual),
-    INSN_LABEL(invokespecial),
-    INSN_LABEL(invokestatic),
-    INSN_LABEL(invokeinterface),
-    0, /* Unused.  */
-    INSN_LABEL(new),
-    INSN_LABEL(newarray),
-    INSN_LABEL(anewarray),
-    INSN_LABEL(arraylength),
-    INSN_LABEL(athrow),
-    INSN_LABEL(checkcast),
-    INSN_LABEL(instanceof),
-    INSN_LABEL(monitorenter),
-    INSN_LABEL(monitorexit),
-#ifdef DIRECT_THREADED
-    0, // wide
-#else
-    INSN_LABEL(wide),
-#endif
-    INSN_LABEL(multianewarray),
-    INSN_LABEL(ifnull),
-    INSN_LABEL(ifnonnull),
-    INSN_LABEL(goto_w),
-    INSN_LABEL(jsr_w),
-#ifdef DIRECT_THREADED
-    INSN_LABEL (ldc_class)
-#else
-    0
-#endif
-  };
+static void 
+throw_incompatible_class_change_error (jstring msg)
+{
+  throw new java::lang::IncompatibleClassChangeError (msg);
+}
 
-  pc_t pc;
+static void 
+throw_null_pointer_exception ()
+{
+  throw new java::lang::NullPointerException;
+}
 
-#ifdef DIRECT_THREADED
+/* Look up source code line number for given bytecode (or direct threaded
+   interpreter) PC. */
+int
+_Jv_InterpMethod::get_source_line(pc_t mpc)
+{
+  int line = line_table_len > 0 ? line_table[0].line : -1;
+  for (int i = 1; i < line_table_len; i++)
+    if (line_table[i].pc > mpc)
+      break;
+    else
+      line = line_table[i].line;
 
-#define NEXT_INSN goto *((pc++)->insn)
-#define INTVAL() ((pc++)->int_val)
-#define AVAL() ((pc++)->datum)
+  return line;
+}
 
-#define GET1S() INTVAL ()
-#define GET2S() INTVAL ()
-#define GET1U() INTVAL ()
-#define GET2U() INTVAL ()
-#define AVAL1U() AVAL ()
-#define AVAL2U() AVAL ()
-#define AVAL2UP() AVAL ()
-#define SKIP_GOTO ++pc
-#define GOTO_VAL() (insn_slot *) pc->datum
-#define PCVAL(unionval) unionval.p
-#define AMPAMP(label) &&label
+/** Do static initialization for fields with a constant initializer */
+void
+_Jv_InitField (jobject obj, jclass klass, int index)
+{
+  using namespace java::lang::reflect;
 
-  // Compile if we must. NOTE: Double-check locking.
-  if (meth->prepared == NULL)
-    {
-      _Jv_MutexLock (&compile_mutex);
-      if (meth->prepared == NULL)
-	meth->compile (insn_target);
-      _Jv_MutexUnlock (&compile_mutex);
-    }
+  if (obj != 0 && klass == 0)
+    klass = obj->getClass ();
 
-  // If we're only compiling, stop here
-  if (args == NULL)
+  if (!_Jv_IsInterpretedClass (klass))
     return;
 
-  pc = (insn_slot *) meth->prepared;
-
-#else
+  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
 
-#define NEXT_INSN goto *(insn_target[*pc++])
+  _Jv_Field * field = (&klass->fields[0]) + index;
 
-#define GET1S() get1s (pc++)
-#define GET2S() (pc += 2, get2s (pc- 2))
-#define GET1U() get1u (pc++)
-#define GET2U() (pc += 2, get2u (pc - 2))
-  // Note that these could be more efficient when not handling 'ldc
-  // class'.
-#define AVAL1U()						\
-  ({ int index = get1u (pc++);					\
-      resolve_pool_entry (meth->defining_class, index).o; })
-#define AVAL2U()						\
-  ({ int index = get2u (pc); pc += 2;				\
-      resolve_pool_entry (meth->defining_class, index).o; })
-  // Note that we don't need to resolve the pool entry here as class
-  // constants are never wide.
-#define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
-#define SKIP_GOTO pc += 2
-#define GOTO_VAL() pc - 1 + get2s (pc)
-#define PCVAL(unionval) unionval.i
-#define AMPAMP(label) NULL
+  if (index > klass->field_count)
+    throw_internal_error ("field out of range");
 
-  pc = bytecode ();
+  int init = iclass->field_initializers[index];
+  if (init == 0)
+    return;
 
-#endif /* DIRECT_THREADED */
+  _Jv_Constants *pool = &klass->constants;
+  int tag = pool->tags[init];
 
-#define TAKE_GOTO pc = GOTO_VAL ()
+  if (! field->isResolved ())
+    throw_internal_error ("initializing unresolved field");
 
-  /* Go straight at it!  the ffi raw format matches the internal
-     stack representation exactly.  At least, that's the idea.
-  */
-  memcpy ((void*) locals, (void*) args, meth->args_raw_size);
+  if (obj==0 && ((field->flags & Modifier::STATIC) == 0))
+    throw_internal_error ("initializing non-static field with no object");
 
-  _Jv_word *pool_data = meth->defining_class->constants.data;
+  void *addr = 0;
 
-  /* These three are temporaries for common code used by several
-     instructions.  */
-  void (*fun)();
-  _Jv_ResolvedMethod* rmeth;
-  int tmpval;
+  if ((field->flags & Modifier::STATIC) != 0)
+    addr = (void*) field->u.addr;
+  else
+    addr = (void*) (((char*)obj) + field->u.boffset);
 
-  try
+  switch (tag)
     {
-      // We keep nop around.  It is used if we're interpreting the
-      // bytecodes and not doing direct threading.
-    insn_nop:
-      NEXT_INSN;
-
-      /* The first few instructions here are ordered according to their
-	 frequency, in the hope that this will improve code locality a
-	 little.  */
-
-    insn_aload_0:		// 0x2a
-      LOADA (0);
-      NEXT_INSN;
-
-    insn_iload:		// 0x15
-      LOADI (GET1U ());
-      NEXT_INSN;
-
-    insn_iload_1:		// 0x1b
-      LOADI (1);
-      NEXT_INSN;
-
-    insn_invokevirtual:	// 0xb6
+    case JV_CONSTANT_String:
       {
-	SAVE_PC();
-	int index = GET2U ();
-
-	/* _Jv_Linker::resolve_pool_entry returns immediately if the
-	 * value already is resolved.  If we want to clutter up the
-	 * code here to gain a little performance, then we can check
-	 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
-	 * directly.  For now, I don't think it is worth it.  */
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	if (rmeth->method->accflags & Modifier::FINAL)
-	  {
-	    // We can't rely on NULLCHECK working if the method is final.
-	    if (! sp[0].o)
-	      throw_null_pointer_exception ();
-
-	    // Final methods might not appear in the vtable.
-	    fun = (void (*)()) rmeth->method->ncode;
-	  }
-	else
-	  {
-	    NULLCHECK (sp[0].o);
-	    jobject rcv = sp[0].o;
-	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
-	    fun = (void (*)()) table->get_method (rmeth->method->index);
-	  }
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokevirtual_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
+	jstring str;
+	str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
+	pool->data[init].string = str;
+	pool->tags[init] = JV_CONSTANT_ResolvedString;
       }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokevirtual_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
+      /* fall through */
 
-	if (rmeth->method->accflags & Modifier::FINAL)
-	  {
-	    // We can't rely on NULLCHECK working if the method is final.
-	    if (! sp[0].o)
-	      throw_null_pointer_exception ();
+    case JV_CONSTANT_ResolvedString:
+      if (! (field->type == &java::lang::String::class$
+ 	     || field->type == &java::lang::Class::class$))
+	throw_class_format_error ("string initialiser to non-string field");
 
-	    // Final methods might not appear in the vtable.
-	    fun = (void (*)()) rmeth->method->ncode;
-	  }
-	else
-	  {
-	    jobject rcv = sp[0].o;
-	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
-	    fun = (void (*)()) table->get_method (rmeth->method->index);
-	  }
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
+      *(jstring*)addr = pool->data[init].string;
+      break;
 
-    perform_invoke:
+    case JV_CONSTANT_Integer:
       {
-	/* here goes the magic again... */
-	ffi_cif *cif = &rmeth->cif;
-	ffi_raw *raw = (ffi_raw*) sp;
-
-	_Jv_value rvalue;
+	int value = pool->data[init].i;
 
-#if FFI_NATIVE_RAW_API
-	/* We assume that this is only implemented if it's correct	*/
-	/* to use it here.  On a 64 bit machine, it never is.		*/
-	ffi_raw_call (cif, fun, (void*)&rvalue, raw);
-#else
-	ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
-#endif
+	if (field->type == JvPrimClass (boolean))
+	  *(jboolean*)addr = (jboolean)value;
+	
+	else if (field->type == JvPrimClass (byte))
+	  *(jbyte*)addr = (jbyte)value;
+	
+	else if (field->type == JvPrimClass (char))
+	  *(jchar*)addr = (jchar)value;
 
-	int rtype = cif->rtype->type;
+	else if (field->type == JvPrimClass (short))
+	  *(jshort*)addr = (jshort)value;
+	
+	else if (field->type == JvPrimClass (int))
+	  *(jint*)addr = (jint)value;
 
-	/* the likelyhood of object, int, or void return is very high,
-	 * so those are checked before the switch */
-	if (rtype == FFI_TYPE_POINTER)
-	  {
-	    PUSHA (rvalue.object_value);
-	  }
-	else if (rtype == FFI_TYPE_SINT32)
-	  {
-	    PUSHI (rvalue.int_value);
-	  }
-	else if (rtype == FFI_TYPE_VOID)
-	  {
-	    /* skip */
-	  }
 	else
-	  {
-	    switch (rtype)
-	      {
-	      case FFI_TYPE_SINT8:
-		PUSHI ((jbyte)(rvalue.int_value & 0xff));
-		break;
-
-	      case FFI_TYPE_SINT16:
-		PUSHI ((jshort)(rvalue.int_value & 0xffff));
-		break;
-
-	      case FFI_TYPE_UINT16:
-		PUSHI (rvalue.int_value & 0xffff);
-		break;
+	  throw_class_format_error ("erroneous field initializer");
+      }  
+      break;
 
-	      case FFI_TYPE_FLOAT:
-	        PUSHF (rvalue.float_value);
-		break;
+    case JV_CONSTANT_Long:
+      if (field->type != JvPrimClass (long))
+	throw_class_format_error ("erroneous field initializer");
 
-	      case FFI_TYPE_DOUBLE:
-	        PUSHD (rvalue.double_value);
-		break;
+      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
+      break;
 
-	      case FFI_TYPE_SINT64:
-	        PUSHL (rvalue.long_value);
-		break;
+    case JV_CONSTANT_Float:
+      if (field->type != JvPrimClass (float))
+	throw_class_format_error ("erroneous field initializer");
 
-	      default:
-		throw_internal_error ("unknown return type in invokeXXX");
-	      }
-	  }
-      }
-      NEXT_INSN;
+      *(jfloat*)addr = pool->data[init].f;
+      break;
 
-    insn_aconst_null:
-      PUSHA (NULL);
-      NEXT_INSN;
+    case JV_CONSTANT_Double:
+      if (field->type != JvPrimClass (double))
+	throw_class_format_error ("erroneous field initializer");
 
-    insn_iconst_m1:
-      PUSHI (-1);
-      NEXT_INSN;
+      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
+      break;
 
-    insn_iconst_0:
-      PUSHI (0);
-      NEXT_INSN;
+    default:
+      throw_class_format_error ("erroneous field initializer");
+    }
+}
 
-    insn_iconst_1:
-      PUSHI (1);
-      NEXT_INSN;
+inline static unsigned char*
+skip_one_type (unsigned char* ptr)
+{
+  int ch = *ptr++;
 
-    insn_iconst_2:
-      PUSHI (2);
-      NEXT_INSN;
+  while (ch == '[')
+    { 
+      ch = *ptr++;
+    }
+  
+  if (ch == 'L')
+    {
+      do { ch = *ptr++; } while (ch != ';');
+    }
 
-    insn_iconst_3:
-      PUSHI (3);
-      NEXT_INSN;
+  return ptr;
+}
 
-    insn_iconst_4:
-      PUSHI (4);
-      NEXT_INSN;
+static ffi_type*
+get_ffi_type_from_signature (unsigned char* ptr)
+{
+  switch (*ptr) 
+    {
+    case 'L':
+    case '[':
+      return &ffi_type_pointer;
+      break;
 
-    insn_iconst_5:
-      PUSHI (5);
-      NEXT_INSN;
+    case 'Z':
+      // On some platforms a bool is a byte, on others an int.
+      if (sizeof (jboolean) == sizeof (jbyte))
+	return &ffi_type_sint8;
+      else
+	{
+	  JvAssert (sizeof (jbyte) == sizeof (jint));
+	  return &ffi_type_sint32;
+	}
+      break;
 
-    insn_lconst_0:
-      PUSHL (0);
-      NEXT_INSN;
-
-    insn_lconst_1:
-      PUSHL (1);
-      NEXT_INSN;
-
-    insn_fconst_0:
-      PUSHF (0);
-      NEXT_INSN;
-
-    insn_fconst_1:
-      PUSHF (1);
-      NEXT_INSN;
-
-    insn_fconst_2:
-      PUSHF (2);
-      NEXT_INSN;
-
-    insn_dconst_0:
-      PUSHD (0);
-      NEXT_INSN;
-
-    insn_dconst_1:
-      PUSHD (1);
-      NEXT_INSN;
-
-    insn_bipush:
-      // For direct threaded, bipush and sipush are the same.
-#ifndef DIRECT_THREADED
-      PUSHI (GET1S ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_sipush:
-      PUSHI (GET2S ());
-      NEXT_INSN;
-
-    insn_ldc:
-      // For direct threaded, ldc and ldc_w are the same.
-#ifndef DIRECT_THREADED
-      PUSHA ((jobject) AVAL1U ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_ldc_w:
-      PUSHA ((jobject) AVAL2U ());
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-      // For direct threaded we have a separate 'ldc class' operation.
-    insn_ldc_class:
-      {
-	SAVE_PC();
-	// We could rewrite the instruction at this point.
-	int index = INTVAL ();
-	jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						     index)).o;
-	PUSHA (k);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_ldc2_w:
-      {
-	void *where = AVAL2UP ();
-	memcpy (sp, where, 2*sizeof (_Jv_word));
-	sp += 2;
-      }
-      NEXT_INSN;
-
-    insn_lload:
-      LOADL (GET1U ());
-      NEXT_INSN;
-
-    insn_fload:
-      LOADF (GET1U ());
-      NEXT_INSN;
-
-    insn_dload:
-      LOADD (GET1U ());
-      NEXT_INSN;
-
-    insn_aload:
-      LOADA (GET1U ());
-      NEXT_INSN;
-
-    insn_iload_0:
-      LOADI (0);
-      NEXT_INSN;
-
-    insn_iload_2:
-      LOADI (2);
-      NEXT_INSN;
-
-    insn_iload_3:
-      LOADI (3);
-      NEXT_INSN;
-
-    insn_lload_0:
-      LOADL (0);
-      NEXT_INSN;
-
-    insn_lload_1:
-      LOADL (1);
-      NEXT_INSN;
-
-    insn_lload_2:
-      LOADL (2);
-      NEXT_INSN;
-
-    insn_lload_3:
-      LOADL (3);
-      NEXT_INSN;
-
-    insn_fload_0:
-      LOADF (0);
-      NEXT_INSN;
-
-    insn_fload_1:
-      LOADF (1);
-      NEXT_INSN;
-
-    insn_fload_2:
-      LOADF (2);
-      NEXT_INSN;
-
-    insn_fload_3:
-      LOADF (3);
-      NEXT_INSN;
-
-    insn_dload_0:
-      LOADD (0);
-      NEXT_INSN;
-
-    insn_dload_1:
-      LOADD (1);
-      NEXT_INSN;
-
-    insn_dload_2:
-      LOADD (2);
-      NEXT_INSN;
-
-    insn_dload_3:
-      LOADD (3);
-      NEXT_INSN;
-
-    insn_aload_1:
-      LOADA(1);
-      NEXT_INSN;
-
-    insn_aload_2:
-      LOADA(2);
-      NEXT_INSN;
-
-    insn_aload_3:
-      LOADA(3);
-      NEXT_INSN;
-
-    insn_iaload:
-      {
-	jint index = POPI();
-	jintArray arr = (jintArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_laload:
-      {
-	jint index = POPI();
-	jlongArray arr = (jlongArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHL( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_faload:
-      {
-	jint index = POPI();
-	jfloatArray arr = (jfloatArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHF( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_daload:
-      {
-	jint index = POPI();
-	jdoubleArray arr = (jdoubleArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHD( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_aaload:
-      {
-	jint index = POPI();
-	jobjectArray arr = (jobjectArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHA( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_baload:
-      {
-	jint index = POPI();
-	jbyteArray arr = (jbyteArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_caload:
-      {
-	jint index = POPI();
-	jcharArray arr = (jcharArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_saload:
-      {
-	jint index = POPI();
-	jshortArray arr = (jshortArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_istore:
-      STOREI (GET1U ());
-      NEXT_INSN;
-
-    insn_lstore:
-      STOREL (GET1U ());
-      NEXT_INSN;
-
-    insn_fstore:
-      STOREF (GET1U ());
-      NEXT_INSN;
-
-    insn_dstore:
-      STORED (GET1U ());
-      NEXT_INSN;
-
-    insn_astore:
-      STOREA (GET1U ());
-      NEXT_INSN;
-
-    insn_istore_0:
-      STOREI (0);
-      NEXT_INSN;
-
-    insn_istore_1:
-      STOREI (1);
-      NEXT_INSN;
-
-    insn_istore_2:
-      STOREI (2);
-      NEXT_INSN;
-
-    insn_istore_3:
-      STOREI (3);
-      NEXT_INSN;
-
-    insn_lstore_0:
-      STOREL (0);
-      NEXT_INSN;
-
-    insn_lstore_1:
-      STOREL (1);
-      NEXT_INSN;
-
-    insn_lstore_2:
-      STOREL (2);
-      NEXT_INSN;
-
-    insn_lstore_3:
-      STOREL (3);
-      NEXT_INSN;
-
-    insn_fstore_0:
-      STOREF (0);
-      NEXT_INSN;
-
-    insn_fstore_1:
-      STOREF (1);
-      NEXT_INSN;
-
-    insn_fstore_2:
-      STOREF (2);
-      NEXT_INSN;
-
-    insn_fstore_3:
-      STOREF (3);
-      NEXT_INSN;
-
-    insn_dstore_0:
-      STORED (0);
-      NEXT_INSN;
-
-    insn_dstore_1:
-      STORED (1);
-      NEXT_INSN;
-
-    insn_dstore_2:
-      STORED (2);
-      NEXT_INSN;
-
-    insn_dstore_3:
-      STORED (3);
-      NEXT_INSN;
-
-    insn_astore_0:
-      STOREA(0);
-      NEXT_INSN;
-
-    insn_astore_1:
-      STOREA(1);
-      NEXT_INSN;
-
-    insn_astore_2:
-      STOREA(2);
-      NEXT_INSN;
-
-    insn_astore_3:
-      STOREA(3);
-      NEXT_INSN;
-
-    insn_iastore:
-      {
-	jint value = POPI();
-	jint index  = POPI();
-	jintArray arr = (jintArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_lastore:
-      {
-	jlong value = POPL();
-	jint index  = POPI();
-	jlongArray arr = (jlongArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_fastore:
-      {
-	jfloat value = POPF();
-	jint index  = POPI();
-	jfloatArray arr = (jfloatArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_dastore:
-      {
-	jdouble value = POPD();
-	jint index  = POPI();
-	jdoubleArray arr = (jdoubleArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_aastore:
-      {
-	jobject value = POPA();
-	jint index  = POPI();
-	jobjectArray arr = (jobjectArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	_Jv_CheckArrayStore (arr, value);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_bastore:
-      {
-	jbyte value = (jbyte) POPI();
-	jint index  = POPI();
-	jbyteArray arr = (jbyteArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_castore:
-      {
-	jchar value = (jchar) POPI();
-	jint index  = POPI();
-	jcharArray arr = (jcharArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_sastore:
-      {
-	jshort value = (jshort) POPI();
-	jint index  = POPI();
-	jshortArray arr = (jshortArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_pop:
-      sp -= 1;
-      NEXT_INSN;
-
-    insn_pop2:
-      sp -= 2;
-      NEXT_INSN;
-
-    insn_dup:
-      sp[0] = sp[-1];
-      sp += 1;
-      NEXT_INSN;
-
-    insn_dup_x1:
-      dupx (sp, 1, 1); sp+=1;
-      NEXT_INSN;
-
-    insn_dup_x2:
-      dupx (sp, 1, 2); sp+=1;
-      NEXT_INSN;
-
-    insn_dup2:
-      sp[0] = sp[-2];
-      sp[1] = sp[-1];
-      sp += 2;
-      NEXT_INSN;
-
-    insn_dup2_x1:
-      dupx (sp, 2, 1); sp+=2;
-      NEXT_INSN;
-
-    insn_dup2_x2:
-      dupx (sp, 2, 2); sp+=2;
-      NEXT_INSN;
-
-    insn_swap:
-      {
-	jobject tmp1 = POPA();
-	jobject tmp2 = POPA();
-	PUSHA (tmp1);
-	PUSHA (tmp2);
-      }
-      NEXT_INSN;
-
-    insn_iadd:
-      BINOPI(+);
-      NEXT_INSN;
-
-    insn_ladd:
-      BINOPL(+);
-      NEXT_INSN;
-
-    insn_fadd:
-      BINOPF(+);
-      NEXT_INSN;
-
-    insn_dadd:
-      BINOPD(+);
-      NEXT_INSN;
-
-    insn_isub:
-      BINOPI(-);
-      NEXT_INSN;
-
-    insn_lsub:
-      BINOPL(-);
-      NEXT_INSN;
-
-    insn_fsub:
-      BINOPF(-);
-      NEXT_INSN;
-
-    insn_dsub:
-      BINOPD(-);
-      NEXT_INSN;
-
-    insn_imul:
-      BINOPI(*);
-      NEXT_INSN;
-
-    insn_lmul:
-      BINOPL(*);
-      NEXT_INSN;
-
-    insn_fmul:
-      BINOPF(*);
-      NEXT_INSN;
-
-    insn_dmul:
-      BINOPD(*);
-      NEXT_INSN;
-
-    insn_idiv:
-      {
-	SAVE_PC();
-	jint value2 = POPI();
-	jint value1 = POPI();
-	jint res = _Jv_divI (value1, value2);
-	PUSHI (res);
-      }
-      NEXT_INSN;
-
-    insn_ldiv:
-      {
-	SAVE_PC();
-	jlong value2 = POPL();
-	jlong value1 = POPL();
-	jlong res = _Jv_divJ (value1, value2);
-	PUSHL (res);
-      }
-      NEXT_INSN;
-
-    insn_fdiv:
-      {
-	jfloat value2 = POPF();
-	jfloat value1 = POPF();
-	jfloat res = value1 / value2;
-	PUSHF (res);
-      }
-      NEXT_INSN;
-
-    insn_ddiv:
-      {
-	jdouble value2 = POPD();
-	jdouble value1 = POPD();
-	jdouble res = value1 / value2;
-	PUSHD (res);
-      }
-      NEXT_INSN;
-
-    insn_irem:
-      {
-	SAVE_PC();
-	jint value2 = POPI();
-	jint value1 =  POPI();
-	jint res = _Jv_remI (value1, value2);
-	PUSHI (res);
-      }
-      NEXT_INSN;
-
-    insn_lrem:
-      {
-	SAVE_PC();
-	jlong value2 = POPL();
-	jlong value1 = POPL();
-	jlong res = _Jv_remJ (value1, value2);
-	PUSHL (res);
-      }
-      NEXT_INSN;
-
-    insn_frem:
-      {
-	jfloat value2 = POPF();
-	jfloat value1 = POPF();
-	jfloat res    = __ieee754_fmod (value1, value2);
-	PUSHF (res);
-      }
-      NEXT_INSN;
-
-    insn_drem:
-      {
-	jdouble value2 = POPD();
-	jdouble value1 = POPD();
-	jdouble res    = __ieee754_fmod (value1, value2);
-	PUSHD (res);
-      }
-      NEXT_INSN;
-
-    insn_ineg:
-      {
-	jint value = POPI();
-	PUSHI (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_lneg:
-      {
-	jlong value = POPL();
-	PUSHL (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_fneg:
-      {
-	jfloat value = POPF();
-	PUSHF (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_dneg:
-      {
-	jdouble value = POPD();
-	PUSHD (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_ishl:
-      {
-	jint shift = (POPI() & 0x1f);
-	jint value = POPI();
-	PUSHI (value << shift);
-      }
-      NEXT_INSN;
-
-    insn_lshl:
-      {
-	jint shift = (POPI() & 0x3f);
-	jlong value = POPL();
-	PUSHL (value << shift);
-      }
-      NEXT_INSN;
-
-    insn_ishr:
-      {
-	jint shift = (POPI() & 0x1f);
-	jint value = POPI();
-	PUSHI (value >> shift);
-      }
-      NEXT_INSN;
-
-    insn_lshr:
-      {
-	jint shift = (POPI() & 0x3f);
-	jlong value = POPL();
-	PUSHL (value >> shift);
-      }
-      NEXT_INSN;
-
-    insn_iushr:
-      {
-	jint shift = (POPI() & 0x1f);
-	_Jv_uint value = (_Jv_uint) POPI();
-	PUSHI ((jint) (value >> shift));
-      }
-      NEXT_INSN;
-
-    insn_lushr:
-      {
-	jint shift = (POPI() & 0x3f);
-	_Jv_ulong value = (_Jv_ulong) POPL();
-	PUSHL ((jlong) (value >> shift));
-      }
-      NEXT_INSN;
-
-    insn_iand:
-      BINOPI (&);
-      NEXT_INSN;
-
-    insn_land:
-      BINOPL (&);
-      NEXT_INSN;
-
-    insn_ior:
-      BINOPI (|);
-      NEXT_INSN;
-
-    insn_lor:
-      BINOPL (|);
-      NEXT_INSN;
-
-    insn_ixor:
-      BINOPI (^);
-      NEXT_INSN;
-
-    insn_lxor:
-      BINOPL (^);
-      NEXT_INSN;
-
-    insn_iinc:
-      {
-	jint index  = GET1U ();
-	jint amount = GET1S ();
-	locals[index].i += amount;
-      }
-      NEXT_INSN;
-
-    insn_i2l:
-      {jlong value = POPI(); PUSHL (value);}
-      NEXT_INSN;
-
-    insn_i2f:
-      {jfloat value = POPI(); PUSHF (value);}
-      NEXT_INSN;
-
-    insn_i2d:
-      {jdouble value = POPI(); PUSHD (value);}
-      NEXT_INSN;
-
-    insn_l2i:
-      {jint value = POPL(); PUSHI (value);}
-      NEXT_INSN;
-
-    insn_l2f:
-      {jfloat value = POPL(); PUSHF (value);}
-      NEXT_INSN;
-
-    insn_l2d:
-      {jdouble value = POPL(); PUSHD (value);}
-      NEXT_INSN;
-
-    insn_f2i:
-      {
-	using namespace java::lang;
-	jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
-	PUSHI(value);
-      }
-      NEXT_INSN;
-
-    insn_f2l:
-      {
-	using namespace java::lang;
-	jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
-	PUSHL(value);
-      }
-      NEXT_INSN;
-
-    insn_f2d:
-      { jdouble value = POPF (); PUSHD(value); }
-      NEXT_INSN;
-
-    insn_d2i:
-      {
-	using namespace java::lang;
-	jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
-	PUSHI(value);
-      }
-      NEXT_INSN;
-
-    insn_d2l:
-      {
-	using namespace java::lang;
-	jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
-	PUSHL(value);
-      }
-      NEXT_INSN;
-
-    insn_d2f:
-      { jfloat value = POPD (); PUSHF(value); }
-      NEXT_INSN;
-
-    insn_i2b:
-      { jbyte value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_i2c:
-      { jchar value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_i2s:
-      { jshort value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_lcmp:
-      {
-	jlong value2 = POPL ();
-	jlong value1 = POPL ();
-	if (value1 > value2)
-	  { PUSHI (1); }
-	else if (value1 == value2)
-	  { PUSHI (0); }
-	else
-	  { PUSHI (-1); }
-      }
-      NEXT_INSN;
-
-    insn_fcmpl:
-      tmpval = -1;
-      goto fcmp;
-
-    insn_fcmpg:
-      tmpval = 1;
-
-    fcmp:
-      {
-	jfloat value2 = POPF ();
-	jfloat value1 = POPF ();
-	if (value1 > value2)
-	  PUSHI (1);
-	else if (value1 == value2)
-	  PUSHI (0);
-	else if (value1 < value2)
-	  PUSHI (-1);
-	else
-	  PUSHI (tmpval);
-      }
-      NEXT_INSN;
-
-    insn_dcmpl:
-      tmpval = -1;
-      goto dcmp;
-
-    insn_dcmpg:
-      tmpval = 1;
-
-    dcmp:
-      {
-	jdouble value2 = POPD ();
-	jdouble value1 = POPD ();
-	if (value1 > value2)
-	  PUSHI (1);
-	else if (value1 == value2)
-	  PUSHI (0);
-	else if (value1 < value2)
-	  PUSHI (-1);
-	else
-	  PUSHI (tmpval);
-      }
-      NEXT_INSN;
-
-    insn_ifeq:
-      {
-	if (POPI() == 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifne:
-      {
-	if (POPI() != 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_iflt:
-      {
-	if (POPI() < 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifge:
-      {
-	if (POPI() >= 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifgt:
-      {
-	if (POPI() > 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifle:
-      {
-	if (POPI() <= 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpeq:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 == value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpne:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 != value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmplt:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 < value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpge:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 >= value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpgt:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 > value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmple:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 <= value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_acmpeq:
-      {
-	jobject value2 = POPA();
-	jobject value1 = POPA();
-	if (value1 == value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_acmpne:
-      {
-	jobject value2 = POPA();
-	jobject value1 = POPA();
-	if (value1 != value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_goto_w:
-#ifndef DIRECT_THREADED
-      // For direct threaded, goto and goto_w are the same.
-      pc = pc - 1 + get4 (pc);
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_goto:
-      TAKE_GOTO;
-      NEXT_INSN;
-
-    insn_jsr_w:
-#ifndef DIRECT_THREADED
-      // For direct threaded, jsr and jsr_w are the same.
-      {
-	pc_t next = pc - 1 + get4 (pc);
-	pc += 4;
-	PUSHA ((jobject) pc);
-	pc = next;
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_jsr:
-      {
-	pc_t next = GOTO_VAL();
-	SKIP_GOTO;
-	PUSHA ((jobject) pc);
-	pc = next;
-      }
-      NEXT_INSN;
-
-    insn_ret:
-      {
-	jint index = GET1U ();
-	pc = (pc_t) PEEKA (index);
-      }
-      NEXT_INSN;
-
-    insn_tableswitch:
-      {
-#ifdef DIRECT_THREADED
-	void *def = (pc++)->datum;
-
-	int index = POPI();
-
-	jint low = INTVAL ();
-	jint high = INTVAL ();
-
-	if (index < low || index > high)
-	  pc = (insn_slot *) def;
-	else
-	  pc = (insn_slot *) ((pc + index - low)->datum);
-#else
-	pc_t base_pc = pc - 1;
-	int index = POPI ();
-
-	pc_t base = (pc_t) bytecode ();
-	while ((pc - base) % 4 != 0)
-	  ++pc;
-
-	jint def = get4 (pc);
-	jint low = get4 (pc + 4);
-	jint high = get4 (pc + 8);
-	if (index < low || index > high)
-	  pc = base_pc + def;
-	else
-	  pc = base_pc + get4 (pc + 4 * (index - low + 3));
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-    insn_lookupswitch:
-      {
-#ifdef DIRECT_THREADED
-	void *def = (pc++)->insn;
-
-	int index = POPI();
-
-	jint npairs = INTVAL ();
-
-	int max = npairs - 1;
-	int min = 0;
-
-	// Simple binary search...
-	while (min < max)
-	  {
-	    int half = (min + max) / 2;
-	    int match = pc[2 * half].int_val;
-
-	    if (index == match)
-	      {
-		// Found it.
-		pc = (insn_slot *) pc[2 * half + 1].datum;
-		NEXT_INSN;
-	      }
-	    else if (index < match)
-	      // We can use HALF - 1 here because we check again on
-	      // loop exit.
-	      max = half - 1;
-	    else
-	      // We can use HALF + 1 here because we check again on
-	      // loop exit.
-	      min = half + 1;
-	  }
-	if (index == pc[2 * min].int_val)
-	  pc = (insn_slot *) pc[2 * min + 1].datum;
-	else
-	  pc = (insn_slot *) def;
-#else
-	unsigned char *base_pc = pc-1;
-	int index = POPI();
-
-	unsigned char* base = bytecode ();
-	while ((pc-base) % 4 != 0)
-	  ++pc;
-
-	jint def     = get4 (pc);
-	jint npairs  = get4 (pc+4);
-
-	int max = npairs-1;
-	int min = 0;
-
-	// Simple binary search...
-	while (min < max)
-	  {
-	    int half = (min+max)/2;
-	    int match = get4 (pc+ 4*(2 + 2*half));
-
-	    if (index == match)
-	      min = max = half;
-	    else if (index < match)
-	      // We can use HALF - 1 here because we check again on
-	      // loop exit.
-	      max = half - 1;
-	    else
-	      // We can use HALF + 1 here because we check again on
-	      // loop exit.
-	      min = half + 1;
-	  }
-
-	if (index == get4 (pc+ 4*(2 + 2*min)))
-	  pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
-	else
-	  pc = base_pc + def;    
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-    insn_areturn:
-      *(jobject *) retp = POPA ();
-      return;
-
-    insn_lreturn:
-      *(jlong *) retp = POPL ();
-      return;
-
-    insn_freturn:
-      *(jfloat *) retp = POPF ();
-      return;
-
-    insn_dreturn:
-      *(jdouble *) retp = POPD ();
-      return;
-
-    insn_ireturn:
-      *(jint *) retp = POPI ();
-      return;
-
-    insn_return:
-      return;
-
-    insn_getstatic:
-      {
-	jint fieldref_index = GET2U ();
-        SAVE_PC(); // Constant pool resolution could throw.
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	if ((field->flags & Modifier::STATIC) == 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field no longer static"));
-
-	jclass type = field->type;
-
-	// We rewrite the instruction once we discover what it refers
-	// to.
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes)
-	      {
-	      case 1:
-		PUSHI (*field->u.byte_addr);
-		newinsn = AMPAMP (getstatic_resolved_1);
-		break;
-
-	      case 2:
-		if (type == JvPrimClass (char))
-		  {
-		    PUSHI (*field->u.char_addr);
-		    newinsn = AMPAMP (getstatic_resolved_char);
-		  }
-		else
-		  {
-		    PUSHI (*field->u.short_addr);
-		    newinsn = AMPAMP (getstatic_resolved_short);
-		  }
-		break;
-
-	      case 4:
-	        PUSHI(*field->u.int_addr);
-		newinsn = AMPAMP (getstatic_resolved_4);
-		break;
-
-	      case 8:
-	        PUSHL(*field->u.long_addr);
-		newinsn = AMPAMP (getstatic_resolved_8);
-		break;
-	      }
-	  }
-	else
-	  {
-	    PUSHA(*field->u.object_addr);
-	    newinsn = AMPAMP (getstatic_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].datum = field->u.addr;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    getstatic_resolved_1:
-      PUSHI (*(jbyte *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_char:
-      PUSHI (*(jchar *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_short:
-      PUSHI (*(jshort *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_4:
-      PUSHI (*(jint *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_8:
-      PUSHL (*(jlong *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_obj:
-      PUSHA (*(jobject *) AVAL ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_getfield:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	if ((field->flags & Modifier::STATIC) != 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field is static"));
-
-	jclass type = field->type;
-	jint field_offset = field->u.boffset;
-
-	jobject obj   = POPA();
-	NULLCHECK(obj);
-
-	void *newinsn = NULL;
-	_Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes)
-	      {
-	      case 1:
-	        PUSHI (val->byte_value);
-		newinsn = AMPAMP (getfield_resolved_1);
-		break;
-
-	      case 2:
-		if (type == JvPrimClass (char))
-		  {
-		    PUSHI (val->char_value);
-		    newinsn = AMPAMP (getfield_resolved_char);
-		  }
-		else
-		  {
-		    PUSHI (val->short_value);
-		    newinsn = AMPAMP (getfield_resolved_short);
-		  }
-		break;
-
-	      case 4:
-		PUSHI (val->int_value);
-		newinsn = AMPAMP (getfield_resolved_4);
-		break;
-
-	      case 8:
-	        PUSHL (val->long_value);
-		newinsn = AMPAMP (getfield_resolved_8);
-		break;
-	      }
-	  }
-	else
-	  {
-	    PUSHA (val->object_value);
-	    newinsn = AMPAMP (getfield_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].int_val = field_offset;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    getfield_resolved_1:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jbyte *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_char:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jchar *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_short:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jshort *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_4:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jint *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_8:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHL (*(jlong *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_obj:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHA (*(jobject *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_putstatic:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	jclass type = field->type;
-
-	// ResolvePoolEntry cannot check this
-	if ((field->flags & Modifier::STATIC) == 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field no longer static"));
-
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes) 
-	      {
-	      case 1:
-		{
-		  jint value = POPI();
-		  *field->u.byte_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_1);
-		  break;
-		}
-
-	      case 2:
-		{
-		  jint value = POPI();
-		  *field->u.char_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_2);
-		  break;
-		}
-
-	      case 4:
-		{
-		  jint value = POPI();
-		  *field->u.int_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_4);
-		  break;
-		}
-
-	      case 8:
-		{
-		  jlong value = POPL();
-		  *field->u.long_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_8);
-		  break;
-		}
-	      }
-	  }
-	else
-	  {
-	    jobject value = POPA();
-	    *field->u.object_addr = value;
-	    newinsn = AMPAMP (putstatic_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].datum = field->u.addr;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    putstatic_resolved_1:
-      *(jbyte *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_2:
-      *(jchar *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_4:
-      *(jint *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_8:
-      *(jlong *) AVAL () = POPL ();
-      NEXT_INSN;
-
-    putstatic_resolved_obj:
-      *(jobject *) AVAL () = POPA ();
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_putfield:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	jclass type = field->type;
-
-	if ((field->flags & Modifier::STATIC) != 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field is static"));
-
-	jint field_offset = field->u.boffset;
-
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes) 
-	      {
-	      case 1:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jbyte*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_1);
-		  break;
-		}
-
-	      case 2:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jchar*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_2);
-		  break;
-		}
-
-	      case 4:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jint*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_4);
-		  break;
-		}
-
-	      case 8:
-		{
-		  jlong   value = POPL();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jlong*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_8);
-		  break;
-		}
-	      }
-	  }
-	else
-	  {
-	    jobject value = POPA();
-	    jobject obj   = POPA();
-	    NULLCHECK(obj);
-	    *(jobject*) ((char*)obj + field_offset) = value;
-	    newinsn = AMPAMP (putfield_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].int_val = field_offset;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    putfield_resolved_1:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jbyte *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_2:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jchar *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_4:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jint *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_8:
-      {
-	jlong val = POPL ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jlong *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_obj:
-      {
-	jobject val = POPA ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jobject *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_invokespecial:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	// We don't use NULLCHECK here because we can't rely on that
-	// working for <init>.  So instead we do an explicit test.
-	if (! sp[0].o)
-	  {
-	    SAVE_PC();
-	    throw_null_pointer_exception ();
-	  }
-
-	fun = (void (*)()) rmeth->method->ncode;
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokespecial_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokespecial_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	// We don't use NULLCHECK here because we can't rely on that
-	// working for <init>.  So instead we do an explicit test.
-	if (! sp[0].o)
-	  {
-	    throw_null_pointer_exception ();
-	  }
-	fun = (void (*)()) rmeth->method->ncode;
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_invokestatic:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	fun = (void (*)()) rmeth->method->ncode;
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokestatic_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokestatic_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	fun = (void (*)()) rmeth->method->ncode;
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_invokeinterface:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	jobject rcv = sp[0].o;
-
-	NULLCHECK (rcv);
-
-	fun = (void (*)())
-	  _Jv_LookupInterfaceMethod (rcv->getClass (),
-				     rmeth->method->name,
-				     rmeth->method->signature);
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokeinterface_resolved;
-	pc[-1].datum = rmeth;
-#else
-	// Skip dummy bytes.
-	pc += 2;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokeinterface_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	jobject rcv = sp[0].o;
-	NULLCHECK (rcv);
-	fun = (void (*)())
-	  _Jv_LookupInterfaceMethod (rcv->getClass (),
-				     rmeth->method->name,
-				     rmeth->method->signature);
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_new:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-							  index)).clazz;
-	/* VM spec, section 3.11.5 */
-	if ((klass->getModifiers() & Modifier::ABSTRACT)
-	    || klass->isInterface())
-	  throw new java::lang::InstantiationException;
-	jobject res = _Jv_AllocObject (klass);
-	PUSHA (res);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&new_resolved;
-	pc[-1].datum = klass;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    new_resolved:
-      {
-	jclass klass = (jclass) AVAL ();
-	jobject res = _Jv_AllocObject (klass);
-	PUSHA (res);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_newarray:
-      {
-	int atype = GET1U ();
-	int size  = POPI();
-	jobject result = _Jv_NewArray (atype, size);
-	PUSHA (result);
-      }
-      NEXT_INSN;
-
-    insn_anewarray:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-							  index)).clazz;
-	int size  = POPI();
-	jobject result = _Jv_NewObjectArray (size, klass, 0);
-	PUSHA (result);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&anewarray_resolved;
-	pc[-1].datum = klass;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    anewarray_resolved:
-      {
-	jclass klass = (jclass) AVAL ();
-	int size = POPI ();
-	jobject result = _Jv_NewObjectArray (size, klass, 0);
-	PUSHA (result);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_arraylength:
-      {
-	__JArray *arr = (__JArray*)POPA();
-	NULLARRAYCHECK (arr);
-	PUSHI (arr->length);
-      }
-      NEXT_INSN;
-
-    insn_athrow:
-      {
-	jobject value = POPA();
-	throw static_cast<jthrowable>(value);
-      }
-      NEXT_INSN;
-
-    insn_checkcast:
-      {
-        SAVE_PC();
-	jobject value = POPA();
-	jint index = GET2U ();
-	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						       index)).clazz;
-
-	value = (jobject) _Jv_CheckCast (to, value);
-
-	PUSHA (value);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&checkcast_resolved;
-	pc[-1].datum = to;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    checkcast_resolved:
-      {
-        SAVE_PC();
-	jobject value = POPA ();
-	jclass to = (jclass) AVAL ();
-	value = (jobject) _Jv_CheckCast (to, value);
-	PUSHA (value);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_instanceof:
-      {
-        SAVE_PC();
-	jobject value = POPA();
-	jint index = GET2U ();
-	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						       index)).clazz;
-	PUSHI (to->isInstance (value));
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&instanceof_resolved;
-	pc[-1].datum = to;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    instanceof_resolved:
-      {
-	jobject value = POPA ();
-	jclass to = (jclass) AVAL ();
-	PUSHI (to->isInstance (value));
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_monitorenter:
-      {
-	jobject value = POPA();
-	NULLCHECK(value);
-	_Jv_MonitorEnter (value);
-      }
-      NEXT_INSN;
-
-    insn_monitorexit:
-      {
-	jobject value = POPA();
-	NULLCHECK(value);
-	_Jv_MonitorExit (value);
-      }
-      NEXT_INSN;
-
-    insn_ifnull:
-      {
-	jobject val = POPA();
-	if (val == NULL)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifnonnull:
-      {
-	jobject val = POPA();
-	if (val != NULL)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_multianewarray:
-      {
-	SAVE_PC();
-	int kind_index = GET2U ();
-	int dim        = GET1U ();
-
-	jclass type    
-	  = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-					       kind_index)).clazz;
-	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
-
-	for (int i = dim - 1; i >= 0; i--)
-	  {
-	    sizes[i] = POPI ();
-	  }
-
-	jobject res    = _Jv_NewMultiArray (type,dim, sizes);
-
-	PUSHA (res);
-      }
-      NEXT_INSN;
-
-#ifndef DIRECT_THREADED
-    insn_wide:
-      {
-	jint the_mod_op = get1u (pc++);
-	jint wide       = get2u (pc); pc += 2;
-
-	switch (the_mod_op)
-	  {
-	  case op_istore:
-	    STOREI (wide);
-	    NEXT_INSN;
-
-	  case op_fstore:
-	    STOREF (wide);
-	    NEXT_INSN;
-
-	  case op_astore:
-	    STOREA (wide);
-	    NEXT_INSN;
-
-	  case op_lload:
-	    LOADL (wide);
-	    NEXT_INSN;
-
-	  case op_dload:
-	    LOADD (wide);
-	    NEXT_INSN;
-
-	  case op_iload:
-	    LOADI (wide);
-	    NEXT_INSN;
-
-	  case op_fload:
-	    LOADF (wide);
-	    NEXT_INSN;
-
-	  case op_aload:
-	    LOADA (wide);
-	    NEXT_INSN;
-
-	  case op_lstore:
-	    STOREL (wide);
-	    NEXT_INSN;
-
-	  case op_dstore:
-	    STORED (wide);
-	    NEXT_INSN;
-
-	  case op_ret:
-	    pc = (unsigned char*) PEEKA (wide);
-	    NEXT_INSN;
-
-	  case op_iinc:
-	    {
-	      jint amount = get2s (pc); pc += 2;
-	      jint value = PEEKI (wide);
-	      POKEI (wide, value+amount);
-	    }
-	    NEXT_INSN;
-
-	  default:
-	    throw_internal_error ("illegal bytecode modified by wide");
-	  }
-
-      }
-#endif /* DIRECT_THREADED */
-    }
-  catch (java::lang::Throwable *ex)
-    {
-#ifdef DIRECT_THREADED
-      void *logical_pc = (void *) ((insn_slot *) pc - 1);
-#else
-      int logical_pc = pc - 1 - bytecode ();
-#endif
-      _Jv_InterpException *exc = meth->exceptions ();
-      jclass exc_class = ex->getClass ();
-
-      for (int i = 0; i < meth->exc_count; i++)
-	{
-	  if (PCVAL (exc[i].start_pc) <= logical_pc
-	      && logical_pc < PCVAL (exc[i].end_pc))
-	    {
-#ifdef DIRECT_THREADED
-	      jclass handler = (jclass) exc[i].handler_type.p;
-#else
-	      jclass handler = NULL;
-	      if (exc[i].handler_type.i != 0)
-		handler = (_Jv_Linker::resolve_pool_entry (defining_class,
-							     exc[i].handler_type.i)).clazz;
-#endif /* DIRECT_THREADED */
-
-	      if (handler == NULL || handler->isAssignableFrom (exc_class))
-		{
-#ifdef DIRECT_THREADED
-		  pc = (insn_slot *) exc[i].handler_pc.p;
-#else
-		  pc = bytecode () + exc[i].handler_pc.i;
-#endif /* DIRECT_THREADED */
-		  sp = stack;
-		  sp++->o = ex; // Push exception.
-		  NEXT_INSN;
-		}
-	    }
-	}
-
-      // No handler, so re-throw.
-      throw ex;
-    }
-}
-
-static void
-throw_internal_error (const char *msg)
-{
-  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
-}
-
-static void 
-throw_incompatible_class_change_error (jstring msg)
-{
-  throw new java::lang::IncompatibleClassChangeError (msg);
-}
-
-static void 
-throw_null_pointer_exception ()
-{
-  throw new java::lang::NullPointerException;
-}
-
-/* Look up source code line number for given bytecode (or direct threaded
-   interpreter) PC. */
-int
-_Jv_InterpMethod::get_source_line(pc_t mpc)
-{
-  int line = line_table_len > 0 ? line_table[0].line : -1;
-  for (int i = 1; i < line_table_len; i++)
-    if (line_table[i].pc > mpc)
-      break;
-    else
-      line = line_table[i].line;
-
-  return line;
-}
-
-/** Do static initialization for fields with a constant initializer */
-void
-_Jv_InitField (jobject obj, jclass klass, int index)
-{
-  using namespace java::lang::reflect;
-
-  if (obj != 0 && klass == 0)
-    klass = obj->getClass ();
-
-  if (!_Jv_IsInterpretedClass (klass))
-    return;
-
-  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
-
-  _Jv_Field * field = (&klass->fields[0]) + index;
-
-  if (index > klass->field_count)
-    throw_internal_error ("field out of range");
-
-  int init = iclass->field_initializers[index];
-  if (init == 0)
-    return;
-
-  _Jv_Constants *pool = &klass->constants;
-  int tag = pool->tags[init];
-
-  if (! field->isResolved ())
-    throw_internal_error ("initializing unresolved field");
-
-  if (obj==0 && ((field->flags & Modifier::STATIC) == 0))
-    throw_internal_error ("initializing non-static field with no object");
-
-  void *addr = 0;
-
-  if ((field->flags & Modifier::STATIC) != 0)
-    addr = (void*) field->u.addr;
-  else
-    addr = (void*) (((char*)obj) + field->u.boffset);
-
-  switch (tag)
-    {
-    case JV_CONSTANT_String:
-      {
-	jstring str;
-	str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
-	pool->data[init].string = str;
-	pool->tags[init] = JV_CONSTANT_ResolvedString;
-      }
-      /* fall through */
-
-    case JV_CONSTANT_ResolvedString:
-      if (! (field->type == &java::lang::String::class$
- 	     || field->type == &java::lang::Class::class$))
-	throw_class_format_error ("string initialiser to non-string field");
-
-      *(jstring*)addr = pool->data[init].string;
-      break;
-
-    case JV_CONSTANT_Integer:
-      {
-	int value = pool->data[init].i;
-
-	if (field->type == JvPrimClass (boolean))
-	  *(jboolean*)addr = (jboolean)value;
-	
-	else if (field->type == JvPrimClass (byte))
-	  *(jbyte*)addr = (jbyte)value;
-	
-	else if (field->type == JvPrimClass (char))
-	  *(jchar*)addr = (jchar)value;
-
-	else if (field->type == JvPrimClass (short))
-	  *(jshort*)addr = (jshort)value;
-	
-	else if (field->type == JvPrimClass (int))
-	  *(jint*)addr = (jint)value;
-
-	else
-	  throw_class_format_error ("erroneous field initializer");
-      }  
-      break;
-
-    case JV_CONSTANT_Long:
-      if (field->type != JvPrimClass (long))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
-      break;
-
-    case JV_CONSTANT_Float:
-      if (field->type != JvPrimClass (float))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jfloat*)addr = pool->data[init].f;
-      break;
-
-    case JV_CONSTANT_Double:
-      if (field->type != JvPrimClass (double))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
-      break;
-
-    default:
-      throw_class_format_error ("erroneous field initializer");
-    }
-}
-
-inline static unsigned char*
-skip_one_type (unsigned char* ptr)
-{
-  int ch = *ptr++;
-
-  while (ch == '[')
-    { 
-      ch = *ptr++;
-    }
-  
-  if (ch == 'L')
-    {
-      do { ch = *ptr++; } while (ch != ';');
-    }
-
-  return ptr;
-}
-
-static ffi_type*
-get_ffi_type_from_signature (unsigned char* ptr)
-{
-  switch (*ptr) 
-    {
-    case 'L':
-    case '[':
-      return &ffi_type_pointer;
-      break;
-
-    case 'Z':
-      // On some platforms a bool is a byte, on others an int.
-      if (sizeof (jboolean) == sizeof (jbyte))
-	return &ffi_type_sint8;
-      else
-	{
-	  JvAssert (sizeof (jbyte) == sizeof (jint));
-	  return &ffi_type_sint32;
-	}
-      break;
-
-    case 'B':
-      return &ffi_type_sint8;
-      break;
-      
-    case 'C':
-      return &ffi_type_uint16;
-      break;
-	  
-    case 'S': 
-      return &ffi_type_sint16;
-      break;
-	  
-    case 'I':
-      return &ffi_type_sint32;
-      break;
-	  
-    case 'J':
-      return &ffi_type_sint64;
-      break;
-	  
-    case 'F':
-      return &ffi_type_float;
-      break;
-	  
-    case 'D':
-      return &ffi_type_double;
-      break;
+    case 'B':
+      return &ffi_type_sint8;
+      break;
+      
+    case 'C':
+      return &ffi_type_uint16;
+      break;
+	  
+    case 'S': 
+      return &ffi_type_sint16;
+      break;
+	  
+    case 'I':
+      return &ffi_type_sint32;
+      break;
+	  
+    case 'J':
+      return &ffi_type_sint64;
+      break;
+	  
+    case 'F':
+      return &ffi_type_float;
+      break;
+	  
+    case 'D':
+      return &ffi_type_double;
+      break;
 
     case 'V':
       return &ffi_type_void;
@@ -3654,9 +1256,19 @@
   if ((self->accflags & Modifier::SYNCHRONIZED) != 0)
     {
       if (staticp)
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
+        {
+        if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		  fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class_debug;
+		else
+		  fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
+        }
       else
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object; 
+        {
+	      if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object_debug;
+		  else
+		  	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object;
+        } 
     }
   else
     {
@@ -3661,9 +1273,19 @@
   else
     {
       if (staticp)
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
+        {
+	      if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class_debug;
+		  else
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
+        }
       else
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+        {
+	      if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal_debug;
+		  else
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+        }
     }
 
   FFI_PREP_RAW_CLOSURE (&closure->closure,

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-01 13:37   ` Kyle Galloway
@ 2006-08-01 15:09     ` Tom Tromey
  2006-08-01 16:05       ` Keith Seitz
  0 siblings, 1 reply; 16+ messages in thread
From: Tom Tromey @ 2006-08-01 15:09 UTC (permalink / raw)
  To: Kyle Galloway; +Cc: tromey, java-patches

>>>>> "Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:

Tom> We talked about it offline and the idea is, we need to track the types
Tom> of stack and local variable slots while interpreting if the debugging
Tom> code is enabled.  However, we don't want to do this unconditionally as
Tom> it adds overhead to interpretation.

So, I looked at JVMTI a little more.  It seems that we only need to
know the types of locals, is that correct?

I'm wondering now if it is worthwhile to make an entire second
interpreter just for this.  Perhaps an extra store in the various
'store' instructions is not too much overhead.

Are there other reasons we may want a special debug-only interpreter?
I thought Keith said there were, but I don't recall why exactly...


That said, your updated patch is looking pretty good to me.
One more addition I didn't think of yesterday: you have to update
stacktrace.cc to account for the new interpreter.

Tom

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-01 15:09     ` Tom Tromey
@ 2006-08-01 16:05       ` Keith Seitz
  2006-08-01 16:10         ` Tom Tromey
  0 siblings, 1 reply; 16+ messages in thread
From: Keith Seitz @ 2006-08-01 16:05 UTC (permalink / raw)
  To: tromey; +Cc: Kyle Galloway, java-patches

Tom Tromey wrote:

> So, I looked at JVMTI a little more.  It seems that we only need to
> know the types of locals, is that correct?

Yeah, that's all that I can see/remember...

> Are there other reasons we may want a special debug-only interpreter?
> I thought Keith said there were, but I don't recall why exactly...

Yes, there is. While breakpointing won't interfere with the speed of the 
interpreter, I expect stepping support will be a much larger impact. I 
was planning on separating this into a debug interpreter to minimize the 
impact on the non-debug case.

Keith

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-01 16:05       ` Keith Seitz
@ 2006-08-01 16:10         ` Tom Tromey
  2006-08-01 17:01           ` Kyle Galloway
  0 siblings, 1 reply; 16+ messages in thread
From: Tom Tromey @ 2006-08-01 16:10 UTC (permalink / raw)
  To: Keith Seitz; +Cc: tromey, Kyle Galloway, java-patches

>>>>> "Keith" == Keith Seitz <keiths@redhat.com> writes:

Keith> Yes, there is. While breakpointing won't interfere with the
Keith> speed of the interpreter, I expect stepping support will be a
Keith> much larger impact. I was planning on separating this into a
Keith> debug interpreter to minimize the impact on the non-debug case.

Ok, great.  Let's go with this plan then.
Thanks.

Tom

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-01 16:10         ` Tom Tromey
@ 2006-08-01 17:01           ` Kyle Galloway
  2006-08-01 22:56             ` Tom Tromey
  0 siblings, 1 reply; 16+ messages in thread
From: Kyle Galloway @ 2006-08-01 17:01 UTC (permalink / raw)
  To: tromey; +Cc: Keith Seitz, java-patches

Tom Tromey wrote:
>>>>>> "Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:
>>>>>>             
>
> Tom> We talked about it offline and the idea is, we need to track the types
> Tom> of stack and local variable slots while interpreting if the debugging
> Tom> code is enabled.  However, we don't want to do this unconditionally as
> Tom> it adds overhead to interpretation.
>
> So, I looked at JVMTI a little more.  It seems that we only need to
> know the types of locals, is that correct?
>
> I'm wondering now if it is worthwhile to make an entire second
> interpreter just for this.  Perhaps an extra store in the various
> 'store' instructions is not too much overhead.
>   
There are other reasons for this as well, in addition to what Keith 
said.  If we want the full suite of event notifications, we need to add 
code to check for them so it could mean a slew of conditional checks to 
see if we are debugging.  If we instead can just #ifdef this code into 
the debugging version, it will mean we don't have to do conditional 
checks in either case since we will know at the invocation of run() or 
run_debug() whether we should report debug info or not.
> That said, your updated patch is looking pretty good to me.
> One more addition I didn't think of yesterday: you have to update
> stacktrace.cc to account for the new interpreter.
>   
Small oversight on my part, I've fixed it.  I had also forgot about the 
change in ncode() in the changelog.  New changelog and new patch attached.

2006-07-28  Kyle Galloway  <kgallowa@redhat.com>

   * /include/java-interp.h (_Jv_InterpMethod::run_debug): New method.
   * /interpret.cc: Added placeholder for debug variable type info to STORE*
   macros.
   (_Jv_InterpMethod::run_debug): New method.
   (_Jv_InterpMethod::run_sync_object_debug): New method.
   (_Jv_InterpMethod::run_sync_class_debug): New method.
   (_Jv_InterpMethod::run_normal_debug): New method.
   (_Jv_InterpMethod::run_class_debug): New method.
   (_Jv_InterpMethod::ncode ()): Changed to select either debug or normal
   versions of these functions.
   * /interpret-run.cc: New file, holds contents of old 
_Jv_InterpMethod::run
   method.
   * /stacktrace.cc (_Jv_StackTrace::UnwindTraceFn): Changed to select
   appropriate function for debug or normal mode.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-01 17:01           ` Kyle Galloway
@ 2006-08-01 22:56             ` Tom Tromey
  2006-08-02 14:27               ` Kyle Galloway
  2006-08-02 15:05               ` Kyle Galloway
  0 siblings, 2 replies; 16+ messages in thread
From: Tom Tromey @ 2006-08-01 22:56 UTC (permalink / raw)
  To: Kyle Galloway; +Cc: tromey, Keith Seitz, java-patches

>>>>> "Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:

Kyle> There are other reasons for this as well, in addition to what Keith 
Kyle> said.  If we want the full suite of event notifications, we need to add 
Kyle> code to check for them so it could mean a slew of conditional checks to 
Kyle> see if we are debugging.  If we instead can just #ifdef this code into 
Kyle> the debugging version, it will mean we don't have to do conditional 
Kyle> checks in either case

Sounds good.

Kyle> Small oversight on my part, I've fixed it.  I had also forgot
Kyle> about the change in ncode() in the changelog.  New changelog and
Kyle> new patch attached.

The patch wasn't there... the changelog entry looks good though.

Kyle>    * /include/java-interp.h (_Jv_InterpMethod::run_debug): New method.

One nit: we don't put a '/' before the file name.

Tom

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-01 22:56             ` Tom Tromey
@ 2006-08-02 14:27               ` Kyle Galloway
  2006-08-02 15:05               ` Kyle Galloway
  1 sibling, 0 replies; 16+ messages in thread
From: Kyle Galloway @ 2006-08-02 14:27 UTC (permalink / raw)
  To: java-patches

[-- Attachment #1: Type: text/plain, Size: 1763 bytes --]

Tom Tromey wrote:
>>>>>> "Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:
>>>>>>             
>
> Kyle> There are other reasons for this as well, in addition to what Keith 
> Kyle> said.  If we want the full suite of event notifications, we need to add 
> Kyle> code to check for them so it could mean a slew of conditional checks to 
> Kyle> see if we are debugging.  If we instead can just #ifdef this code into 
> Kyle> the debugging version, it will mean we don't have to do conditional 
> Kyle> checks in either case
>
> Sounds good.
>
> Kyle> Small oversight on my part, I've fixed it.  I had also forgot
> Kyle> about the change in ncode() in the changelog.  New changelog and
> Kyle> new patch attached.
>
> The patch wasn't there... the changelog entry looks good though.
>
> Kyle>    * /include/java-interp.h (_Jv_InterpMethod::run_debug): New method.
>
> One nit: we don't put a '/' before the file name.
>   
Woops.....I've attached the patch and changed the changelog:

2006-07-28  Kyle Galloway  <kgallowa@redhat.com>

  * include/java-interp.h (_Jv_InterpMethod::run_debug): New method.
  * interpret.cc: Added placeholder for debug variable type info to STORE*
  macros.
  (_Jv_InterpMethod::run_debug): New method.
  (_Jv_InterpMethod::run_sync_object_debug): New method.
  (_Jv_InterpMethod::run_sync_class_debug): New method.
  (_Jv_InterpMethod::run_normal_debug): New method.
  (_Jv_InterpMethod::run_class_debug): New method.
  (_Jv_InterpMethod::ncode ()): Changed to select either debug or normal
  versions of these functions.
  * interpret-run.cc: New file, holds contents of old _Jv_InterpMethod::run
  method.
  * stacktrace.cc (_Jv_StackTrace::UnwindTraceFn): Changed to select
  appropriate function for debug or normal mode.



[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 120222 bytes --]

Index: include/java-interp.h
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/include/java-interp.h	(revision 115852)
+++ /notnfs/kgallowa/vanilla/libjava/include/java-interp.h	(working copy)
@@ -176,9 +176,17 @@
   static void run_synch_object (ffi_cif*, void*, ffi_raw*, void*);
   static void run_class (ffi_cif*, void*, ffi_raw*, void*);
   static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*);
+  
+  static void run_normal_debug (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_synch_object_debug (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_class_debug (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_synch_class_debug (ffi_cif*, void*, ffi_raw*, void*);
 
-  static void run (void*, ffi_raw *, _Jv_InterpMethod *);
+  static void run (void *, ffi_raw *, _Jv_InterpMethod *);
+  static void run_debug (void *, ffi_raw *, _Jv_InterpMethod *);
+  
 
+  
   // Returns source file line number for given PC value, or -1 if line
   // number info is unavailable.
   int get_source_line(pc_t mpc);
@@ -183,6 +191,8 @@
   // number info is unavailable.
   int get_source_line(pc_t mpc);
 
+
+
 #ifdef DIRECT_THREADED
   // Convenience function for indexing bytecode PC/insn slots in
   // line tables for JDWP
@@ -188,9 +198,9 @@
   // line tables for JDWP
   jlong insn_index (pc_t pc);
 #endif
-
- public:
-
+  
+   public:
+   
   /* Get the line table for this method.
    * start  is the lowest index in the method
    * end    is the  highest index in the method
Index: interpret-run.cc
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/interpret-run.cc	(revision 0)
+++ /notnfs/kgallowa/vanilla/libjava/interpret-run.cc	(revision 0)
@@ -0,0 +1,2508 @@
+// interpret-run.cc - Code to interpret bytecode
+
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+/* This file is meant only to be included in interpret.cc, it should not be
+ * compiled directly.	*/
+
+  using namespace java::lang::reflect;
+
+  // FRAME_DESC registers this particular invocation as the top-most
+  // interpreter frame.  This lets the stack tracing code (for
+  // Throwable) print information about the method being interpreted
+  // rather than about the interpreter itself.  FRAME_DESC has a
+  // destructor so it cleans up automatically when the interpreter
+  // returns.
+  java::lang::Thread *thread = java::lang::Thread::currentThread();
+  _Jv_InterpFrame frame_desc (meth, thread);
+
+  _Jv_word stack[meth->max_stack];
+  _Jv_word *sp = stack;
+
+  _Jv_word locals[meth->max_locals];
+
+#define INSN_LABEL(op) &&insn_##op
+
+  static const void *const insn_target[] = 
+  {
+    INSN_LABEL(nop),
+    INSN_LABEL(aconst_null),
+    INSN_LABEL(iconst_m1),
+    INSN_LABEL(iconst_0),
+    INSN_LABEL(iconst_1),
+    INSN_LABEL(iconst_2),
+    INSN_LABEL(iconst_3),
+    INSN_LABEL(iconst_4),
+    INSN_LABEL(iconst_5),
+    INSN_LABEL(lconst_0),
+    INSN_LABEL(lconst_1),
+    INSN_LABEL(fconst_0),
+    INSN_LABEL(fconst_1),
+    INSN_LABEL(fconst_2),
+    INSN_LABEL(dconst_0),
+    INSN_LABEL(dconst_1),
+    INSN_LABEL(bipush),
+    INSN_LABEL(sipush),
+    INSN_LABEL(ldc),
+    INSN_LABEL(ldc_w),
+    INSN_LABEL(ldc2_w),
+    INSN_LABEL(iload),
+    INSN_LABEL(lload),
+    INSN_LABEL(fload),
+    INSN_LABEL(dload),
+    INSN_LABEL(aload),
+    INSN_LABEL(iload_0),
+    INSN_LABEL(iload_1),
+    INSN_LABEL(iload_2),
+    INSN_LABEL(iload_3),
+    INSN_LABEL(lload_0),
+    INSN_LABEL(lload_1),
+    INSN_LABEL(lload_2),
+    INSN_LABEL(lload_3),
+    INSN_LABEL(fload_0),
+    INSN_LABEL(fload_1),
+    INSN_LABEL(fload_2),
+    INSN_LABEL(fload_3),
+    INSN_LABEL(dload_0),
+    INSN_LABEL(dload_1),
+    INSN_LABEL(dload_2),
+    INSN_LABEL(dload_3),
+    INSN_LABEL(aload_0),
+    INSN_LABEL(aload_1),
+    INSN_LABEL(aload_2),
+    INSN_LABEL(aload_3),
+    INSN_LABEL(iaload),
+    INSN_LABEL(laload),
+    INSN_LABEL(faload),
+    INSN_LABEL(daload),
+    INSN_LABEL(aaload),
+    INSN_LABEL(baload),
+    INSN_LABEL(caload),
+    INSN_LABEL(saload),
+    INSN_LABEL(istore),
+    INSN_LABEL(lstore),
+    INSN_LABEL(fstore),
+    INSN_LABEL(dstore),
+    INSN_LABEL(astore),
+    INSN_LABEL(istore_0),
+    INSN_LABEL(istore_1),
+    INSN_LABEL(istore_2),
+    INSN_LABEL(istore_3),
+    INSN_LABEL(lstore_0),
+    INSN_LABEL(lstore_1),
+    INSN_LABEL(lstore_2),
+    INSN_LABEL(lstore_3),
+    INSN_LABEL(fstore_0),
+    INSN_LABEL(fstore_1),
+    INSN_LABEL(fstore_2),
+    INSN_LABEL(fstore_3),
+    INSN_LABEL(dstore_0),
+    INSN_LABEL(dstore_1),
+    INSN_LABEL(dstore_2),
+    INSN_LABEL(dstore_3),
+    INSN_LABEL(astore_0),
+    INSN_LABEL(astore_1),
+    INSN_LABEL(astore_2),
+    INSN_LABEL(astore_3),
+    INSN_LABEL(iastore),
+    INSN_LABEL(lastore),
+    INSN_LABEL(fastore),
+    INSN_LABEL(dastore),
+    INSN_LABEL(aastore),
+    INSN_LABEL(bastore),
+    INSN_LABEL(castore),
+    INSN_LABEL(sastore),
+    INSN_LABEL(pop),
+    INSN_LABEL(pop2),
+    INSN_LABEL(dup),
+    INSN_LABEL(dup_x1),
+    INSN_LABEL(dup_x2),
+    INSN_LABEL(dup2),
+    INSN_LABEL(dup2_x1),
+    INSN_LABEL(dup2_x2),
+    INSN_LABEL(swap),
+    INSN_LABEL(iadd),
+    INSN_LABEL(ladd),
+    INSN_LABEL(fadd),
+    INSN_LABEL(dadd),
+    INSN_LABEL(isub),
+    INSN_LABEL(lsub),
+    INSN_LABEL(fsub),
+    INSN_LABEL(dsub),
+    INSN_LABEL(imul),
+    INSN_LABEL(lmul),
+    INSN_LABEL(fmul),
+    INSN_LABEL(dmul),
+    INSN_LABEL(idiv),
+    INSN_LABEL(ldiv),
+    INSN_LABEL(fdiv),
+    INSN_LABEL(ddiv),
+    INSN_LABEL(irem),
+    INSN_LABEL(lrem),
+    INSN_LABEL(frem),
+    INSN_LABEL(drem),
+    INSN_LABEL(ineg),
+    INSN_LABEL(lneg),
+    INSN_LABEL(fneg),
+    INSN_LABEL(dneg),
+    INSN_LABEL(ishl),
+    INSN_LABEL(lshl),
+    INSN_LABEL(ishr),
+    INSN_LABEL(lshr),
+    INSN_LABEL(iushr),
+    INSN_LABEL(lushr),
+    INSN_LABEL(iand),
+    INSN_LABEL(land),
+    INSN_LABEL(ior),
+    INSN_LABEL(lor),
+    INSN_LABEL(ixor),
+    INSN_LABEL(lxor),
+    INSN_LABEL(iinc),
+    INSN_LABEL(i2l),
+    INSN_LABEL(i2f),
+    INSN_LABEL(i2d),
+    INSN_LABEL(l2i),
+    INSN_LABEL(l2f),
+    INSN_LABEL(l2d),
+    INSN_LABEL(f2i),
+    INSN_LABEL(f2l),
+    INSN_LABEL(f2d),
+    INSN_LABEL(d2i),
+    INSN_LABEL(d2l),
+    INSN_LABEL(d2f),
+    INSN_LABEL(i2b),
+    INSN_LABEL(i2c),
+    INSN_LABEL(i2s),
+    INSN_LABEL(lcmp),
+    INSN_LABEL(fcmpl),
+    INSN_LABEL(fcmpg),
+    INSN_LABEL(dcmpl),
+    INSN_LABEL(dcmpg),
+    INSN_LABEL(ifeq),
+    INSN_LABEL(ifne),
+    INSN_LABEL(iflt),
+    INSN_LABEL(ifge),
+    INSN_LABEL(ifgt),
+    INSN_LABEL(ifle),
+    INSN_LABEL(if_icmpeq),
+    INSN_LABEL(if_icmpne),
+    INSN_LABEL(if_icmplt),
+    INSN_LABEL(if_icmpge),
+    INSN_LABEL(if_icmpgt),
+    INSN_LABEL(if_icmple),
+    INSN_LABEL(if_acmpeq),
+    INSN_LABEL(if_acmpne),
+    INSN_LABEL(goto), 
+    INSN_LABEL(jsr),
+    INSN_LABEL(ret),
+    INSN_LABEL(tableswitch),
+    INSN_LABEL(lookupswitch),
+    INSN_LABEL(ireturn),
+    INSN_LABEL(lreturn),
+    INSN_LABEL(freturn),
+    INSN_LABEL(dreturn),
+    INSN_LABEL(areturn),
+    INSN_LABEL(return),
+    INSN_LABEL(getstatic),
+    INSN_LABEL(putstatic),
+    INSN_LABEL(getfield),
+    INSN_LABEL(putfield),
+    INSN_LABEL(invokevirtual),
+    INSN_LABEL(invokespecial),
+    INSN_LABEL(invokestatic),
+    INSN_LABEL(invokeinterface),
+    0, /* Unused.  */
+    INSN_LABEL(new),
+    INSN_LABEL(newarray),
+    INSN_LABEL(anewarray),
+    INSN_LABEL(arraylength),
+    INSN_LABEL(athrow),
+    INSN_LABEL(checkcast),
+    INSN_LABEL(instanceof),
+    INSN_LABEL(monitorenter),
+    INSN_LABEL(monitorexit),
+#ifdef DIRECT_THREADED
+    0, // wide
+#else
+    INSN_LABEL(wide),
+#endif
+    INSN_LABEL(multianewarray),
+    INSN_LABEL(ifnull),
+    INSN_LABEL(ifnonnull),
+    INSN_LABEL(goto_w),
+    INSN_LABEL(jsr_w),
+#ifdef DIRECT_THREADED
+    INSN_LABEL (ldc_class)
+#else
+    0
+#endif
+  };
+
+  pc_t pc;
+
+#ifdef DIRECT_THREADED
+
+#define NEXT_INSN goto *((pc++)->insn)
+#define INTVAL() ((pc++)->int_val)
+#define AVAL() ((pc++)->datum)
+
+#define GET1S() INTVAL ()
+#define GET2S() INTVAL ()
+#define GET1U() INTVAL ()
+#define GET2U() INTVAL ()
+#define AVAL1U() AVAL ()
+#define AVAL2U() AVAL ()
+#define AVAL2UP() AVAL ()
+#define SKIP_GOTO ++pc
+#define GOTO_VAL() (insn_slot *) pc->datum
+#define PCVAL(unionval) unionval.p
+#define AMPAMP(label) &&label
+
+  // Compile if we must. NOTE: Double-check locking.
+  if (meth->prepared == NULL)
+    {
+      _Jv_MutexLock (&compile_mutex);
+      if (meth->prepared == NULL)
+	meth->compile (insn_target);
+      _Jv_MutexUnlock (&compile_mutex);
+    }
+
+  // If we're only compiling, stop here
+  if (args == NULL)
+    return;
+
+  pc = (insn_slot *) meth->prepared;
+
+#else
+
+#define NEXT_INSN goto *(insn_target[*pc++])
+
+#define GET1S() get1s (pc++)
+#define GET2S() (pc += 2, get2s (pc- 2))
+#define GET1U() get1u (pc++)
+#define GET2U() (pc += 2, get2u (pc - 2))
+  // Note that these could be more efficient when not handling 'ldc
+  // class'.
+#define AVAL1U()						\
+  ({ int index = get1u (pc++);					\
+      resolve_pool_entry (meth->defining_class, index).o; })
+#define AVAL2U()						\
+  ({ int index = get2u (pc); pc += 2;				\
+      resolve_pool_entry (meth->defining_class, index).o; })
+  // Note that we don't need to resolve the pool entry here as class
+  // constants are never wide.
+#define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
+#define SKIP_GOTO pc += 2
+#define GOTO_VAL() pc - 1 + get2s (pc)
+#define PCVAL(unionval) unionval.i
+#define AMPAMP(label) NULL
+
+  pc = bytecode ();
+
+#endif /* DIRECT_THREADED */
+
+#define TAKE_GOTO pc = GOTO_VAL ()
+
+  /* Go straight at it!  the ffi raw format matches the internal
+     stack representation exactly.  At least, that's the idea.
+  */
+  memcpy ((void*) locals, (void*) args, meth->args_raw_size);
+
+  _Jv_word *pool_data = meth->defining_class->constants.data;
+
+  /* These three are temporaries for common code used by several
+     instructions.  */
+  void (*fun)();
+  _Jv_ResolvedMethod* rmeth;
+  int tmpval;
+
+  try
+    {
+      // We keep nop around.  It is used if we're interpreting the
+      // bytecodes and not doing direct threading.
+    insn_nop:
+      NEXT_INSN;
+
+      /* The first few instructions here are ordered according to their
+	 frequency, in the hope that this will improve code locality a
+	 little.  */
+
+    insn_aload_0:		// 0x2a
+      LOADA (0);
+      NEXT_INSN;
+
+    insn_iload:		// 0x15
+      LOADI (GET1U ());
+      NEXT_INSN;
+
+    insn_iload_1:		// 0x1b
+      LOADI (1);
+      NEXT_INSN;
+
+    insn_invokevirtual:	// 0xb6
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	/* _Jv_Linker::resolve_pool_entry returns immediately if the
+	 * value already is resolved.  If we want to clutter up the
+	 * code here to gain a little performance, then we can check
+	 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
+	 * directly.  For now, I don't think it is worth it.  */
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	if (rmeth->method->accflags & Modifier::FINAL)
+	  {
+	    // We can't rely on NULLCHECK working if the method is final.
+	    if (! sp[0].o)
+	      throw_null_pointer_exception ();
+
+	    // Final methods might not appear in the vtable.
+	    fun = (void (*)()) rmeth->method->ncode;
+	  }
+	else
+	  {
+	    NULLCHECK (sp[0].o);
+	    jobject rcv = sp[0].o;
+	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
+	    fun = (void (*)()) table->get_method (rmeth->method->index);
+	  }
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokevirtual_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokevirtual_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+
+	if (rmeth->method->accflags & Modifier::FINAL)
+	  {
+	    // We can't rely on NULLCHECK working if the method is final.
+	    if (! sp[0].o)
+	      throw_null_pointer_exception ();
+
+	    // Final methods might not appear in the vtable.
+	    fun = (void (*)()) rmeth->method->ncode;
+	  }
+	else
+	  {
+	    jobject rcv = sp[0].o;
+	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
+	    fun = (void (*)()) table->get_method (rmeth->method->index);
+	  }
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    perform_invoke:
+      {
+	/* here goes the magic again... */
+	ffi_cif *cif = &rmeth->cif;
+	ffi_raw *raw = (ffi_raw*) sp;
+
+	_Jv_value rvalue;
+
+#if FFI_NATIVE_RAW_API
+	/* We assume that this is only implemented if it's correct	*/
+	/* to use it here.  On a 64 bit machine, it never is.		*/
+	ffi_raw_call (cif, fun, (void*)&rvalue, raw);
+#else
+	ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
+#endif
+
+	int rtype = cif->rtype->type;
+
+	/* the likelyhood of object, int, or void return is very high,
+	 * so those are checked before the switch */
+	if (rtype == FFI_TYPE_POINTER)
+	  {
+	    PUSHA (rvalue.object_value);
+	  }
+	else if (rtype == FFI_TYPE_SINT32)
+	  {
+	    PUSHI (rvalue.int_value);
+	  }
+	else if (rtype == FFI_TYPE_VOID)
+	  {
+	    /* skip */
+	  }
+	else
+	  {
+	    switch (rtype)
+	      {
+	      case FFI_TYPE_SINT8:
+		PUSHI ((jbyte)(rvalue.int_value & 0xff));
+		break;
+
+	      case FFI_TYPE_SINT16:
+		PUSHI ((jshort)(rvalue.int_value & 0xffff));
+		break;
+
+	      case FFI_TYPE_UINT16:
+		PUSHI (rvalue.int_value & 0xffff);
+		break;
+
+	      case FFI_TYPE_FLOAT:
+	        PUSHF (rvalue.float_value);
+		break;
+
+	      case FFI_TYPE_DOUBLE:
+	        PUSHD (rvalue.double_value);
+		break;
+
+	      case FFI_TYPE_SINT64:
+	        PUSHL (rvalue.long_value);
+		break;
+
+	      default:
+		throw_internal_error ("unknown return type in invokeXXX");
+	      }
+	  }
+      }
+      NEXT_INSN;
+
+    insn_aconst_null:
+      PUSHA (NULL);
+      NEXT_INSN;
+
+    insn_iconst_m1:
+      PUSHI (-1);
+      NEXT_INSN;
+
+    insn_iconst_0:
+      PUSHI (0);
+      NEXT_INSN;
+
+    insn_iconst_1:
+      PUSHI (1);
+      NEXT_INSN;
+
+    insn_iconst_2:
+      PUSHI (2);
+      NEXT_INSN;
+
+    insn_iconst_3:
+      PUSHI (3);
+      NEXT_INSN;
+
+    insn_iconst_4:
+      PUSHI (4);
+      NEXT_INSN;
+
+    insn_iconst_5:
+      PUSHI (5);
+      NEXT_INSN;
+
+    insn_lconst_0:
+      PUSHL (0);
+      NEXT_INSN;
+
+    insn_lconst_1:
+      PUSHL (1);
+      NEXT_INSN;
+
+    insn_fconst_0:
+      PUSHF (0);
+      NEXT_INSN;
+
+    insn_fconst_1:
+      PUSHF (1);
+      NEXT_INSN;
+
+    insn_fconst_2:
+      PUSHF (2);
+      NEXT_INSN;
+
+    insn_dconst_0:
+      PUSHD (0);
+      NEXT_INSN;
+
+    insn_dconst_1:
+      PUSHD (1);
+      NEXT_INSN;
+
+    insn_bipush:
+      // For direct threaded, bipush and sipush are the same.
+#ifndef DIRECT_THREADED
+      PUSHI (GET1S ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_sipush:
+      PUSHI (GET2S ());
+      NEXT_INSN;
+
+    insn_ldc:
+      // For direct threaded, ldc and ldc_w are the same.
+#ifndef DIRECT_THREADED
+      PUSHA ((jobject) AVAL1U ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_ldc_w:
+      PUSHA ((jobject) AVAL2U ());
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+      // For direct threaded we have a separate 'ldc class' operation.
+    insn_ldc_class:
+      {
+	SAVE_PC();
+	// We could rewrite the instruction at this point.
+	int index = INTVAL ();
+	jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						     index)).o;
+	PUSHA (k);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_ldc2_w:
+      {
+	void *where = AVAL2UP ();
+	memcpy (sp, where, 2*sizeof (_Jv_word));
+	sp += 2;
+      }
+      NEXT_INSN;
+
+    insn_lload:
+      LOADL (GET1U ());
+      NEXT_INSN;
+
+    insn_fload:
+      LOADF (GET1U ());
+      NEXT_INSN;
+
+    insn_dload:
+      LOADD (GET1U ());
+      NEXT_INSN;
+
+    insn_aload:
+      LOADA (GET1U ());
+      NEXT_INSN;
+
+    insn_iload_0:
+      LOADI (0);
+      NEXT_INSN;
+
+    insn_iload_2:
+      LOADI (2);
+      NEXT_INSN;
+
+    insn_iload_3:
+      LOADI (3);
+      NEXT_INSN;
+
+    insn_lload_0:
+      LOADL (0);
+      NEXT_INSN;
+
+    insn_lload_1:
+      LOADL (1);
+      NEXT_INSN;
+
+    insn_lload_2:
+      LOADL (2);
+      NEXT_INSN;
+
+    insn_lload_3:
+      LOADL (3);
+      NEXT_INSN;
+
+    insn_fload_0:
+      LOADF (0);
+      NEXT_INSN;
+
+    insn_fload_1:
+      LOADF (1);
+      NEXT_INSN;
+
+    insn_fload_2:
+      LOADF (2);
+      NEXT_INSN;
+
+    insn_fload_3:
+      LOADF (3);
+      NEXT_INSN;
+
+    insn_dload_0:
+      LOADD (0);
+      NEXT_INSN;
+
+    insn_dload_1:
+      LOADD (1);
+      NEXT_INSN;
+
+    insn_dload_2:
+      LOADD (2);
+      NEXT_INSN;
+
+    insn_dload_3:
+      LOADD (3);
+      NEXT_INSN;
+
+    insn_aload_1:
+      LOADA(1);
+      NEXT_INSN;
+
+    insn_aload_2:
+      LOADA(2);
+      NEXT_INSN;
+
+    insn_aload_3:
+      LOADA(3);
+      NEXT_INSN;
+
+    insn_iaload:
+      {
+	jint index = POPI();
+	jintArray arr = (jintArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_laload:
+      {
+	jint index = POPI();
+	jlongArray arr = (jlongArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHL( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_faload:
+      {
+	jint index = POPI();
+	jfloatArray arr = (jfloatArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHF( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_daload:
+      {
+	jint index = POPI();
+	jdoubleArray arr = (jdoubleArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHD( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_aaload:
+      {
+	jint index = POPI();
+	jobjectArray arr = (jobjectArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHA( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_baload:
+      {
+	jint index = POPI();
+	jbyteArray arr = (jbyteArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_caload:
+      {
+	jint index = POPI();
+	jcharArray arr = (jcharArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_saload:
+      {
+	jint index = POPI();
+	jshortArray arr = (jshortArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_istore:
+      STOREI (GET1U ());
+      NEXT_INSN;
+
+    insn_lstore:
+      STOREL (GET1U ());
+      NEXT_INSN;
+
+    insn_fstore:
+      STOREF (GET1U ());
+      NEXT_INSN;
+
+    insn_dstore:
+      STORED (GET1U ());
+      NEXT_INSN;
+
+    insn_astore:
+      STOREA (GET1U ());
+      NEXT_INSN;
+
+    insn_istore_0:
+      STOREI (0);
+      NEXT_INSN;
+
+    insn_istore_1:
+      STOREI (1);
+      NEXT_INSN;
+
+    insn_istore_2:
+      STOREI (2);
+      NEXT_INSN;
+
+    insn_istore_3:
+      STOREI (3);
+      NEXT_INSN;
+
+    insn_lstore_0:
+      STOREL (0);
+      NEXT_INSN;
+
+    insn_lstore_1:
+      STOREL (1);
+      NEXT_INSN;
+
+    insn_lstore_2:
+      STOREL (2);
+      NEXT_INSN;
+
+    insn_lstore_3:
+      STOREL (3);
+      NEXT_INSN;
+
+    insn_fstore_0:
+      STOREF (0);
+      NEXT_INSN;
+
+    insn_fstore_1:
+      STOREF (1);
+      NEXT_INSN;
+
+    insn_fstore_2:
+      STOREF (2);
+      NEXT_INSN;
+
+    insn_fstore_3:
+      STOREF (3);
+      NEXT_INSN;
+
+    insn_dstore_0:
+      STORED (0);
+      NEXT_INSN;
+
+    insn_dstore_1:
+      STORED (1);
+      NEXT_INSN;
+
+    insn_dstore_2:
+      STORED (2);
+      NEXT_INSN;
+
+    insn_dstore_3:
+      STORED (3);
+      NEXT_INSN;
+
+    insn_astore_0:
+      STOREA(0);
+      NEXT_INSN;
+
+    insn_astore_1:
+      STOREA(1);
+      NEXT_INSN;
+
+    insn_astore_2:
+      STOREA(2);
+      NEXT_INSN;
+
+    insn_astore_3:
+      STOREA(3);
+      NEXT_INSN;
+
+    insn_iastore:
+      {
+	jint value = POPI();
+	jint index  = POPI();
+	jintArray arr = (jintArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_lastore:
+      {
+	jlong value = POPL();
+	jint index  = POPI();
+	jlongArray arr = (jlongArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_fastore:
+      {
+	jfloat value = POPF();
+	jint index  = POPI();
+	jfloatArray arr = (jfloatArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_dastore:
+      {
+	jdouble value = POPD();
+	jint index  = POPI();
+	jdoubleArray arr = (jdoubleArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_aastore:
+      {
+	jobject value = POPA();
+	jint index  = POPI();
+	jobjectArray arr = (jobjectArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	_Jv_CheckArrayStore (arr, value);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_bastore:
+      {
+	jbyte value = (jbyte) POPI();
+	jint index  = POPI();
+	jbyteArray arr = (jbyteArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_castore:
+      {
+	jchar value = (jchar) POPI();
+	jint index  = POPI();
+	jcharArray arr = (jcharArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_sastore:
+      {
+	jshort value = (jshort) POPI();
+	jint index  = POPI();
+	jshortArray arr = (jshortArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_pop:
+      sp -= 1;
+      NEXT_INSN;
+
+    insn_pop2:
+      sp -= 2;
+      NEXT_INSN;
+
+    insn_dup:
+      sp[0] = sp[-1];
+      sp += 1;
+      NEXT_INSN;
+
+    insn_dup_x1:
+      dupx (sp, 1, 1); sp+=1;
+      NEXT_INSN;
+
+    insn_dup_x2:
+      dupx (sp, 1, 2); sp+=1;
+      NEXT_INSN;
+
+    insn_dup2:
+      sp[0] = sp[-2];
+      sp[1] = sp[-1];
+      sp += 2;
+      NEXT_INSN;
+
+    insn_dup2_x1:
+      dupx (sp, 2, 1); sp+=2;
+      NEXT_INSN;
+
+    insn_dup2_x2:
+      dupx (sp, 2, 2); sp+=2;
+      NEXT_INSN;
+
+    insn_swap:
+      {
+	jobject tmp1 = POPA();
+	jobject tmp2 = POPA();
+	PUSHA (tmp1);
+	PUSHA (tmp2);
+      }
+      NEXT_INSN;
+
+    insn_iadd:
+      BINOPI(+);
+      NEXT_INSN;
+
+    insn_ladd:
+      BINOPL(+);
+      NEXT_INSN;
+
+    insn_fadd:
+      BINOPF(+);
+      NEXT_INSN;
+
+    insn_dadd:
+      BINOPD(+);
+      NEXT_INSN;
+
+    insn_isub:
+      BINOPI(-);
+      NEXT_INSN;
+
+    insn_lsub:
+      BINOPL(-);
+      NEXT_INSN;
+
+    insn_fsub:
+      BINOPF(-);
+      NEXT_INSN;
+
+    insn_dsub:
+      BINOPD(-);
+      NEXT_INSN;
+
+    insn_imul:
+      BINOPI(*);
+      NEXT_INSN;
+
+    insn_lmul:
+      BINOPL(*);
+      NEXT_INSN;
+
+    insn_fmul:
+      BINOPF(*);
+      NEXT_INSN;
+
+    insn_dmul:
+      BINOPD(*);
+      NEXT_INSN;
+
+    insn_idiv:
+      {
+	SAVE_PC();
+	jint value2 = POPI();
+	jint value1 = POPI();
+	jint res = _Jv_divI (value1, value2);
+	PUSHI (res);
+      }
+      NEXT_INSN;
+
+    insn_ldiv:
+      {
+	SAVE_PC();
+	jlong value2 = POPL();
+	jlong value1 = POPL();
+	jlong res = _Jv_divJ (value1, value2);
+	PUSHL (res);
+      }
+      NEXT_INSN;
+
+    insn_fdiv:
+      {
+	jfloat value2 = POPF();
+	jfloat value1 = POPF();
+	jfloat res = value1 / value2;
+	PUSHF (res);
+      }
+      NEXT_INSN;
+
+    insn_ddiv:
+      {
+	jdouble value2 = POPD();
+	jdouble value1 = POPD();
+	jdouble res = value1 / value2;
+	PUSHD (res);
+      }
+      NEXT_INSN;
+
+    insn_irem:
+      {
+	SAVE_PC();
+	jint value2 = POPI();
+	jint value1 =  POPI();
+	jint res = _Jv_remI (value1, value2);
+	PUSHI (res);
+      }
+      NEXT_INSN;
+
+    insn_lrem:
+      {
+	SAVE_PC();
+	jlong value2 = POPL();
+	jlong value1 = POPL();
+	jlong res = _Jv_remJ (value1, value2);
+	PUSHL (res);
+      }
+      NEXT_INSN;
+
+    insn_frem:
+      {
+	jfloat value2 = POPF();
+	jfloat value1 = POPF();
+	jfloat res    = __ieee754_fmod (value1, value2);
+	PUSHF (res);
+      }
+      NEXT_INSN;
+
+    insn_drem:
+      {
+	jdouble value2 = POPD();
+	jdouble value1 = POPD();
+	jdouble res    = __ieee754_fmod (value1, value2);
+	PUSHD (res);
+      }
+      NEXT_INSN;
+
+    insn_ineg:
+      {
+	jint value = POPI();
+	PUSHI (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_lneg:
+      {
+	jlong value = POPL();
+	PUSHL (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_fneg:
+      {
+	jfloat value = POPF();
+	PUSHF (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_dneg:
+      {
+	jdouble value = POPD();
+	PUSHD (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_ishl:
+      {
+	jint shift = (POPI() & 0x1f);
+	jint value = POPI();
+	PUSHI (value << shift);
+      }
+      NEXT_INSN;
+
+    insn_lshl:
+      {
+	jint shift = (POPI() & 0x3f);
+	jlong value = POPL();
+	PUSHL (value << shift);
+      }
+      NEXT_INSN;
+
+    insn_ishr:
+      {
+	jint shift = (POPI() & 0x1f);
+	jint value = POPI();
+	PUSHI (value >> shift);
+      }
+      NEXT_INSN;
+
+    insn_lshr:
+      {
+	jint shift = (POPI() & 0x3f);
+	jlong value = POPL();
+	PUSHL (value >> shift);
+      }
+      NEXT_INSN;
+
+    insn_iushr:
+      {
+	jint shift = (POPI() & 0x1f);
+	_Jv_uint value = (_Jv_uint) POPI();
+	PUSHI ((jint) (value >> shift));
+      }
+      NEXT_INSN;
+
+    insn_lushr:
+      {
+	jint shift = (POPI() & 0x3f);
+	_Jv_ulong value = (_Jv_ulong) POPL();
+	PUSHL ((jlong) (value >> shift));
+      }
+      NEXT_INSN;
+
+    insn_iand:
+      BINOPI (&);
+      NEXT_INSN;
+
+    insn_land:
+      BINOPL (&);
+      NEXT_INSN;
+
+    insn_ior:
+      BINOPI (|);
+      NEXT_INSN;
+
+    insn_lor:
+      BINOPL (|);
+      NEXT_INSN;
+
+    insn_ixor:
+      BINOPI (^);
+      NEXT_INSN;
+
+    insn_lxor:
+      BINOPL (^);
+      NEXT_INSN;
+
+    insn_iinc:
+      {
+	jint index  = GET1U ();
+	jint amount = GET1S ();
+	locals[index].i += amount;
+      }
+      NEXT_INSN;
+
+    insn_i2l:
+      {jlong value = POPI(); PUSHL (value);}
+      NEXT_INSN;
+
+    insn_i2f:
+      {jfloat value = POPI(); PUSHF (value);}
+      NEXT_INSN;
+
+    insn_i2d:
+      {jdouble value = POPI(); PUSHD (value);}
+      NEXT_INSN;
+
+    insn_l2i:
+      {jint value = POPL(); PUSHI (value);}
+      NEXT_INSN;
+
+    insn_l2f:
+      {jfloat value = POPL(); PUSHF (value);}
+      NEXT_INSN;
+
+    insn_l2d:
+      {jdouble value = POPL(); PUSHD (value);}
+      NEXT_INSN;
+
+    insn_f2i:
+      {
+	using namespace java::lang;
+	jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
+	PUSHI(value);
+      }
+      NEXT_INSN;
+
+    insn_f2l:
+      {
+	using namespace java::lang;
+	jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
+	PUSHL(value);
+      }
+      NEXT_INSN;
+
+    insn_f2d:
+      { jdouble value = POPF (); PUSHD(value); }
+      NEXT_INSN;
+
+    insn_d2i:
+      {
+	using namespace java::lang;
+	jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
+	PUSHI(value);
+      }
+      NEXT_INSN;
+
+    insn_d2l:
+      {
+	using namespace java::lang;
+	jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
+	PUSHL(value);
+      }
+      NEXT_INSN;
+
+    insn_d2f:
+      { jfloat value = POPD (); PUSHF(value); }
+      NEXT_INSN;
+
+    insn_i2b:
+      { jbyte value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_i2c:
+      { jchar value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_i2s:
+      { jshort value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_lcmp:
+      {
+	jlong value2 = POPL ();
+	jlong value1 = POPL ();
+	if (value1 > value2)
+	  { PUSHI (1); }
+	else if (value1 == value2)
+	  { PUSHI (0); }
+	else
+	  { PUSHI (-1); }
+      }
+      NEXT_INSN;
+
+    insn_fcmpl:
+      tmpval = -1;
+      goto fcmp;
+
+    insn_fcmpg:
+      tmpval = 1;
+
+    fcmp:
+      {
+	jfloat value2 = POPF ();
+	jfloat value1 = POPF ();
+	if (value1 > value2)
+	  PUSHI (1);
+	else if (value1 == value2)
+	  PUSHI (0);
+	else if (value1 < value2)
+	  PUSHI (-1);
+	else
+	  PUSHI (tmpval);
+      }
+      NEXT_INSN;
+
+    insn_dcmpl:
+      tmpval = -1;
+      goto dcmp;
+
+    insn_dcmpg:
+      tmpval = 1;
+
+    dcmp:
+      {
+	jdouble value2 = POPD ();
+	jdouble value1 = POPD ();
+	if (value1 > value2)
+	  PUSHI (1);
+	else if (value1 == value2)
+	  PUSHI (0);
+	else if (value1 < value2)
+	  PUSHI (-1);
+	else
+	  PUSHI (tmpval);
+      }
+      NEXT_INSN;
+
+    insn_ifeq:
+      {
+	if (POPI() == 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifne:
+      {
+	if (POPI() != 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_iflt:
+      {
+	if (POPI() < 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifge:
+      {
+	if (POPI() >= 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifgt:
+      {
+	if (POPI() > 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifle:
+      {
+	if (POPI() <= 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpeq:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 == value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpne:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 != value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmplt:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 < value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpge:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 >= value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpgt:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 > value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmple:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 <= value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_acmpeq:
+      {
+	jobject value2 = POPA();
+	jobject value1 = POPA();
+	if (value1 == value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_acmpne:
+      {
+	jobject value2 = POPA();
+	jobject value1 = POPA();
+	if (value1 != value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_goto_w:
+#ifndef DIRECT_THREADED
+      // For direct threaded, goto and goto_w are the same.
+      pc = pc - 1 + get4 (pc);
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_goto:
+      TAKE_GOTO;
+      NEXT_INSN;
+
+    insn_jsr_w:
+#ifndef DIRECT_THREADED
+      // For direct threaded, jsr and jsr_w are the same.
+      {
+	pc_t next = pc - 1 + get4 (pc);
+	pc += 4;
+	PUSHA ((jobject) pc);
+	pc = next;
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_jsr:
+      {
+	pc_t next = GOTO_VAL();
+	SKIP_GOTO;
+	PUSHA ((jobject) pc);
+	pc = next;
+      }
+      NEXT_INSN;
+
+    insn_ret:
+      {
+	jint index = GET1U ();
+	pc = (pc_t) PEEKA (index);
+      }
+      NEXT_INSN;
+
+    insn_tableswitch:
+      {
+#ifdef DIRECT_THREADED
+	void *def = (pc++)->datum;
+
+	int index = POPI();
+
+	jint low = INTVAL ();
+	jint high = INTVAL ();
+
+	if (index < low || index > high)
+	  pc = (insn_slot *) def;
+	else
+	  pc = (insn_slot *) ((pc + index - low)->datum);
+#else
+	pc_t base_pc = pc - 1;
+	int index = POPI ();
+
+	pc_t base = (pc_t) bytecode ();
+	while ((pc - base) % 4 != 0)
+	  ++pc;
+
+	jint def = get4 (pc);
+	jint low = get4 (pc + 4);
+	jint high = get4 (pc + 8);
+	if (index < low || index > high)
+	  pc = base_pc + def;
+	else
+	  pc = base_pc + get4 (pc + 4 * (index - low + 3));
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+    insn_lookupswitch:
+      {
+#ifdef DIRECT_THREADED
+	void *def = (pc++)->insn;
+
+	int index = POPI();
+
+	jint npairs = INTVAL ();
+
+	int max = npairs - 1;
+	int min = 0;
+
+	// Simple binary search...
+	while (min < max)
+	  {
+	    int half = (min + max) / 2;
+	    int match = pc[2 * half].int_val;
+
+	    if (index == match)
+	      {
+		// Found it.
+		pc = (insn_slot *) pc[2 * half + 1].datum;
+		NEXT_INSN;
+	      }
+	    else if (index < match)
+	      // We can use HALF - 1 here because we check again on
+	      // loop exit.
+	      max = half - 1;
+	    else
+	      // We can use HALF + 1 here because we check again on
+	      // loop exit.
+	      min = half + 1;
+	  }
+	if (index == pc[2 * min].int_val)
+	  pc = (insn_slot *) pc[2 * min + 1].datum;
+	else
+	  pc = (insn_slot *) def;
+#else
+	unsigned char *base_pc = pc-1;
+	int index = POPI();
+
+	unsigned char* base = bytecode ();
+	while ((pc-base) % 4 != 0)
+	  ++pc;
+
+	jint def     = get4 (pc);
+	jint npairs  = get4 (pc+4);
+
+	int max = npairs-1;
+	int min = 0;
+
+	// Simple binary search...
+	while (min < max)
+	  {
+	    int half = (min+max)/2;
+	    int match = get4 (pc+ 4*(2 + 2*half));
+
+	    if (index == match)
+	      min = max = half;
+	    else if (index < match)
+	      // We can use HALF - 1 here because we check again on
+	      // loop exit.
+	      max = half - 1;
+	    else
+	      // We can use HALF + 1 here because we check again on
+	      // loop exit.
+	      min = half + 1;
+	  }
+
+	if (index == get4 (pc+ 4*(2 + 2*min)))
+	  pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
+	else
+	  pc = base_pc + def;    
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+    insn_areturn:
+      *(jobject *) retp = POPA ();
+      return;
+
+    insn_lreturn:
+      *(jlong *) retp = POPL ();
+      return;
+
+    insn_freturn:
+      *(jfloat *) retp = POPF ();
+      return;
+
+    insn_dreturn:
+      *(jdouble *) retp = POPD ();
+      return;
+
+    insn_ireturn:
+      *(jint *) retp = POPI ();
+      return;
+
+    insn_return:
+      return;
+
+    insn_getstatic:
+      {
+	jint fieldref_index = GET2U ();
+        SAVE_PC(); // Constant pool resolution could throw.
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	if ((field->flags & Modifier::STATIC) == 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field no longer static"));
+
+	jclass type = field->type;
+
+	// We rewrite the instruction once we discover what it refers
+	// to.
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes)
+	      {
+	      case 1:
+		PUSHI (*field->u.byte_addr);
+		newinsn = AMPAMP (getstatic_resolved_1);
+		break;
+
+	      case 2:
+		if (type == JvPrimClass (char))
+		  {
+		    PUSHI (*field->u.char_addr);
+		    newinsn = AMPAMP (getstatic_resolved_char);
+		  }
+		else
+		  {
+		    PUSHI (*field->u.short_addr);
+		    newinsn = AMPAMP (getstatic_resolved_short);
+		  }
+		break;
+
+	      case 4:
+	        PUSHI(*field->u.int_addr);
+		newinsn = AMPAMP (getstatic_resolved_4);
+		break;
+
+	      case 8:
+	        PUSHL(*field->u.long_addr);
+		newinsn = AMPAMP (getstatic_resolved_8);
+		break;
+	      }
+	  }
+	else
+	  {
+	    PUSHA(*field->u.object_addr);
+	    newinsn = AMPAMP (getstatic_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].datum = field->u.addr;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    getstatic_resolved_1:
+      PUSHI (*(jbyte *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_char:
+      PUSHI (*(jchar *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_short:
+      PUSHI (*(jshort *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_4:
+      PUSHI (*(jint *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_8:
+      PUSHL (*(jlong *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_obj:
+      PUSHA (*(jobject *) AVAL ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_getfield:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	if ((field->flags & Modifier::STATIC) != 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field is static"));
+
+	jclass type = field->type;
+	jint field_offset = field->u.boffset;
+
+	jobject obj   = POPA();
+	NULLCHECK(obj);
+
+	void *newinsn = NULL;
+	_Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes)
+	      {
+	      case 1:
+	        PUSHI (val->byte_value);
+		newinsn = AMPAMP (getfield_resolved_1);
+		break;
+
+	      case 2:
+		if (type == JvPrimClass (char))
+		  {
+		    PUSHI (val->char_value);
+		    newinsn = AMPAMP (getfield_resolved_char);
+		  }
+		else
+		  {
+		    PUSHI (val->short_value);
+		    newinsn = AMPAMP (getfield_resolved_short);
+		  }
+		break;
+
+	      case 4:
+		PUSHI (val->int_value);
+		newinsn = AMPAMP (getfield_resolved_4);
+		break;
+
+	      case 8:
+	        PUSHL (val->long_value);
+		newinsn = AMPAMP (getfield_resolved_8);
+		break;
+	      }
+	  }
+	else
+	  {
+	    PUSHA (val->object_value);
+	    newinsn = AMPAMP (getfield_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].int_val = field_offset;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    getfield_resolved_1:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jbyte *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_char:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jchar *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_short:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jshort *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_4:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jint *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_8:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHL (*(jlong *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_obj:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHA (*(jobject *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_putstatic:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	jclass type = field->type;
+
+	// ResolvePoolEntry cannot check this
+	if ((field->flags & Modifier::STATIC) == 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field no longer static"));
+
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes) 
+	      {
+	      case 1:
+		{
+		  jint value = POPI();
+		  *field->u.byte_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_1);
+		  break;
+		}
+
+	      case 2:
+		{
+		  jint value = POPI();
+		  *field->u.char_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_2);
+		  break;
+		}
+
+	      case 4:
+		{
+		  jint value = POPI();
+		  *field->u.int_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_4);
+		  break;
+		}
+
+	      case 8:
+		{
+		  jlong value = POPL();
+		  *field->u.long_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_8);
+		  break;
+		}
+	      }
+	  }
+	else
+	  {
+	    jobject value = POPA();
+	    *field->u.object_addr = value;
+	    newinsn = AMPAMP (putstatic_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].datum = field->u.addr;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    putstatic_resolved_1:
+      *(jbyte *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_2:
+      *(jchar *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_4:
+      *(jint *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_8:
+      *(jlong *) AVAL () = POPL ();
+      NEXT_INSN;
+
+    putstatic_resolved_obj:
+      *(jobject *) AVAL () = POPA ();
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_putfield:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	jclass type = field->type;
+
+	if ((field->flags & Modifier::STATIC) != 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field is static"));
+
+	jint field_offset = field->u.boffset;
+
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes) 
+	      {
+	      case 1:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jbyte*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_1);
+		  break;
+		}
+
+	      case 2:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jchar*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_2);
+		  break;
+		}
+
+	      case 4:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jint*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_4);
+		  break;
+		}
+
+	      case 8:
+		{
+		  jlong   value = POPL();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jlong*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_8);
+		  break;
+		}
+	      }
+	  }
+	else
+	  {
+	    jobject value = POPA();
+	    jobject obj   = POPA();
+	    NULLCHECK(obj);
+	    *(jobject*) ((char*)obj + field_offset) = value;
+	    newinsn = AMPAMP (putfield_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].int_val = field_offset;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    putfield_resolved_1:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jbyte *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_2:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jchar *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_4:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jint *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_8:
+      {
+	jlong val = POPL ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jlong *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_obj:
+      {
+	jobject val = POPA ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jobject *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_invokespecial:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	// We don't use NULLCHECK here because we can't rely on that
+	// working for <init>.  So instead we do an explicit test.
+	if (! sp[0].o)
+	  {
+	    SAVE_PC();
+	    throw_null_pointer_exception ();
+	  }
+
+	fun = (void (*)()) rmeth->method->ncode;
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokespecial_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokespecial_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	// We don't use NULLCHECK here because we can't rely on that
+	// working for <init>.  So instead we do an explicit test.
+	if (! sp[0].o)
+	  {
+	    throw_null_pointer_exception ();
+	  }
+	fun = (void (*)()) rmeth->method->ncode;
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_invokestatic:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	fun = (void (*)()) rmeth->method->ncode;
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokestatic_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokestatic_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	fun = (void (*)()) rmeth->method->ncode;
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_invokeinterface:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	jobject rcv = sp[0].o;
+
+	NULLCHECK (rcv);
+
+	fun = (void (*)())
+	  _Jv_LookupInterfaceMethod (rcv->getClass (),
+				     rmeth->method->name,
+				     rmeth->method->signature);
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokeinterface_resolved;
+	pc[-1].datum = rmeth;
+#else
+	// Skip dummy bytes.
+	pc += 2;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokeinterface_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	jobject rcv = sp[0].o;
+	NULLCHECK (rcv);
+	fun = (void (*)())
+	  _Jv_LookupInterfaceMethod (rcv->getClass (),
+				     rmeth->method->name,
+				     rmeth->method->signature);
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_new:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+							  index)).clazz;
+	/* VM spec, section 3.11.5 */
+	if ((klass->getModifiers() & Modifier::ABSTRACT)
+	    || klass->isInterface())
+	  throw new java::lang::InstantiationException;
+	jobject res = _Jv_AllocObject (klass);
+	PUSHA (res);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&new_resolved;
+	pc[-1].datum = klass;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    new_resolved:
+      {
+	jclass klass = (jclass) AVAL ();
+	jobject res = _Jv_AllocObject (klass);
+	PUSHA (res);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_newarray:
+      {
+	int atype = GET1U ();
+	int size  = POPI();
+	jobject result = _Jv_NewArray (atype, size);
+	PUSHA (result);
+      }
+      NEXT_INSN;
+
+    insn_anewarray:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+							  index)).clazz;
+	int size  = POPI();
+	jobject result = _Jv_NewObjectArray (size, klass, 0);
+	PUSHA (result);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&anewarray_resolved;
+	pc[-1].datum = klass;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    anewarray_resolved:
+      {
+	jclass klass = (jclass) AVAL ();
+	int size = POPI ();
+	jobject result = _Jv_NewObjectArray (size, klass, 0);
+	PUSHA (result);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_arraylength:
+      {
+	__JArray *arr = (__JArray*)POPA();
+	NULLARRAYCHECK (arr);
+	PUSHI (arr->length);
+      }
+      NEXT_INSN;
+
+    insn_athrow:
+      {
+	jobject value = POPA();
+	throw static_cast<jthrowable>(value);
+      }
+      NEXT_INSN;
+
+    insn_checkcast:
+      {
+        SAVE_PC();
+	jobject value = POPA();
+	jint index = GET2U ();
+	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						       index)).clazz;
+
+	value = (jobject) _Jv_CheckCast (to, value);
+
+	PUSHA (value);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&checkcast_resolved;
+	pc[-1].datum = to;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    checkcast_resolved:
+      {
+        SAVE_PC();
+	jobject value = POPA ();
+	jclass to = (jclass) AVAL ();
+	value = (jobject) _Jv_CheckCast (to, value);
+	PUSHA (value);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_instanceof:
+      {
+        SAVE_PC();
+	jobject value = POPA();
+	jint index = GET2U ();
+	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						       index)).clazz;
+	PUSHI (to->isInstance (value));
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&instanceof_resolved;
+	pc[-1].datum = to;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    instanceof_resolved:
+      {
+	jobject value = POPA ();
+	jclass to = (jclass) AVAL ();
+	PUSHI (to->isInstance (value));
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_monitorenter:
+      {
+	jobject value = POPA();
+	NULLCHECK(value);
+	_Jv_MonitorEnter (value);
+      }
+      NEXT_INSN;
+
+    insn_monitorexit:
+      {
+	jobject value = POPA();
+	NULLCHECK(value);
+	_Jv_MonitorExit (value);
+      }
+      NEXT_INSN;
+
+    insn_ifnull:
+      {
+	jobject val = POPA();
+	if (val == NULL)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifnonnull:
+      {
+	jobject val = POPA();
+	if (val != NULL)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_multianewarray:
+      {
+	SAVE_PC();
+	int kind_index = GET2U ();
+	int dim        = GET1U ();
+
+	jclass type    
+	  = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+					       kind_index)).clazz;
+	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
+
+	for (int i = dim - 1; i >= 0; i--)
+	  {
+	    sizes[i] = POPI ();
+	  }
+
+	jobject res    = _Jv_NewMultiArray (type,dim, sizes);
+
+	PUSHA (res);
+      }
+      NEXT_INSN;
+
+#ifndef DIRECT_THREADED
+    insn_wide:
+      {
+	jint the_mod_op = get1u (pc++);
+	jint wide       = get2u (pc); pc += 2;
+
+	switch (the_mod_op)
+	  {
+	  case op_istore:
+	    STOREI (wide);
+	    NEXT_INSN;
+
+	  case op_fstore:
+	    STOREF (wide);
+	    NEXT_INSN;
+
+	  case op_astore:
+	    STOREA (wide);
+	    NEXT_INSN;
+
+	  case op_lload:
+	    LOADL (wide);
+	    NEXT_INSN;
+
+	  case op_dload:
+	    LOADD (wide);
+	    NEXT_INSN;
+
+	  case op_iload:
+	    LOADI (wide);
+	    NEXT_INSN;
+
+	  case op_fload:
+	    LOADF (wide);
+	    NEXT_INSN;
+
+	  case op_aload:
+	    LOADA (wide);
+	    NEXT_INSN;
+
+	  case op_lstore:
+	    STOREL (wide);
+	    NEXT_INSN;
+
+	  case op_dstore:
+	    STORED (wide);
+	    NEXT_INSN;
+
+	  case op_ret:
+	    pc = (unsigned char*) PEEKA (wide);
+	    NEXT_INSN;
+
+	  case op_iinc:
+	    {
+	      jint amount = get2s (pc); pc += 2;
+	      jint value = PEEKI (wide);
+	      POKEI (wide, value+amount);
+	    }
+	    NEXT_INSN;
+
+	  default:
+	    throw_internal_error ("illegal bytecode modified by wide");
+	  }
+
+      }
+#endif /* DIRECT_THREADED */
+    }
+  catch (java::lang::Throwable *ex)
+    {
+#ifdef DIRECT_THREADED
+      void *logical_pc = (void *) ((insn_slot *) pc - 1);
+#else
+      int logical_pc = pc - 1 - bytecode ();
+#endif
+      _Jv_InterpException *exc = meth->exceptions ();
+      jclass exc_class = ex->getClass ();
+
+      for (int i = 0; i < meth->exc_count; i++)
+	{
+	  if (PCVAL (exc[i].start_pc) <= logical_pc
+	      && logical_pc < PCVAL (exc[i].end_pc))
+	    {
+#ifdef DIRECT_THREADED
+	      jclass handler = (jclass) exc[i].handler_type.p;
+#else
+	      jclass handler = NULL;
+	      if (exc[i].handler_type.i != 0)
+		handler = (_Jv_Linker::resolve_pool_entry (defining_class,
+							     exc[i].handler_type.i)).clazz;
+#endif /* DIRECT_THREADED */
+
+	      if (handler == NULL || handler->isAssignableFrom (exc_class))
+		{
+
+#ifdef DIRECT_THREADED
+		  pc = (insn_slot *) exc[i].handler_pc.p;
+#else
+		  pc = bytecode () + exc[i].handler_pc.i;
+#endif /* DIRECT_THREADED */
+		  sp = stack;
+		  sp++->o = ex; // Push exception.
+		  NEXT_INSN;
+		}
+	    }
+	}
+
+      // No handler, so re-throw.
+      throw ex;
+    }
Index: interpret.cc
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/interpret.cc	(revision 115852)
+++ /notnfs/kgallowa/vanilla/libjava/interpret.cc	(working copy)
@@ -37,6 +37,8 @@
 #include <execution.h>
 #include <java/lang/reflect/Modifier.h>
 
+#include <gnu/classpath/jdwp/Jdwp.h>
+
 #ifdef INTERPRETER
 
 // Execution engine for interpreted code.
@@ -152,18 +154,36 @@
 # define LOADD(I)  LOADL(I)
 #endif
 
-#define STOREA(I) locals[I].o = (--sp)->o
-#define STOREI(I) locals[I].i = (--sp)->i
-#define STOREF(I) locals[I].f = (--sp)->f
+#define STOREA(I) 		\
+DEBUG_LOCALS_INSN(I, 'o')	\
+locals[I].o = (--sp)->o
+#define STOREI(I) 		\
+DEBUG_LOCALS_INSN (I, 'i')	\
+locals[I].i = (--sp)->i
+#define STOREF(I)  		\
+DEBUG_LOCALS_INSN (I, 'f')	\
+locals[I].f = (--sp)->f
 #if SIZEOF_VOID_P == 8
-# define STOREL(I) (sp -= 2, locals[I].l = sp->l)
-# define STORED(I) (sp -= 2, locals[I].d = sp->d)
+# define STOREL(I)  			\
+DEBUG_LOCALS_INSN (I, 'l')			\
+(sp -= 2, locals[I].l = sp->l)
+# define STORED(I) 				\
+DEBUG_LOCALS_INSN (I, 'd')			\
+(sp -= 2, locals[I].d = sp->d)
+
 #else
-# define STOREL(I) do { jint __idx = (I); \
-    		       locals[__idx+1].ia[0] = (--sp)->ia[0]; \
-    		       locals[__idx].ia[0] = (--sp)->ia[0]; \
-		   } while (0)
-# define STORED(I) STOREL(I)
+# define STOREL(I)		\
+DEBUG_LOCALS_INSN(I, 'l')	\
+do { jint __idx = (I); 	\
+     locals[__idx+1].ia[0] = (--sp)->ia[0]; \
+     locals[__idx].ia[0] = (--sp)->ia[0]; 	\
+   } while (0)
+# define STORED(I)		\
+DEBUG_LOCALS_INSN(I, 'd')	\
+do { jint __idx = (I); 	\
+     locals[__idx+1].ia[0] = (--sp)->ia[0]; \
+     locals[__idx].ia[0] = (--sp)->ia[0]; 	\
+   } while (0)
 #endif
 
 #define PEEKI(I)  (locals+(I))->i
@@ -169,7 +189,9 @@
 #define PEEKI(I)  (locals+(I))->i
 #define PEEKA(I)  (locals+(I))->o
 
-#define POKEI(I,V)  ((locals+(I))->i = (V))
+#define POKEI(I,V)  	\
+DEBUG_LOCALS_INSN(I,i)	\
+((locals+(I))->i = (V))
 
 
 #define BINOPI(OP) { \
@@ -258,6 +280,16 @@
 }
 
 void
+_Jv_InterpMethod::run_normal_debug (ffi_cif *,
+			      void* ret,
+			      ffi_raw * args,
+			      void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+  run_debug (ret, args, _this);
+}
+
+void
 _Jv_InterpMethod::run_synch_object (ffi_cif *,
 				    void* ret,
 				    ffi_raw * args,
@@ -272,6 +304,20 @@
 }
 
 void
+_Jv_InterpMethod::run_synch_object_debug (ffi_cif *,
+				    void* ret,
+				    ffi_raw * args,
+				    void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+
+  jobject rcv = (jobject) args[0].ptr;
+  JvSynchronize mutex (rcv);
+
+  run_debug (ret, args, _this);
+}
+
+void
 _Jv_InterpMethod::run_class (ffi_cif *,
 			     void* ret,
 			     ffi_raw * args,
@@ -283,6 +329,17 @@
 }
 
 void
+_Jv_InterpMethod::run_class_debug (ffi_cif *,
+			     void* ret,
+			     ffi_raw * args,
+			     void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+  _Jv_InitClass (_this->defining_class);
+  run_debug (ret, args, _this);
+}
+
+void
 _Jv_InterpMethod::run_synch_class (ffi_cif *,
 				   void* ret,
 				   ffi_raw * args,
@@ -297,6 +354,21 @@
   run (ret, args, _this);
 }
 
+void
+_Jv_InterpMethod::run_synch_class_debug (ffi_cif *,
+				   void* ret,
+				   ffi_raw * args,
+				   void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+
+  jclass sync = _this->defining_class;
+  _Jv_InitClass (sync);
+  JvSynchronize mutex (sync);
+
+  run_debug (ret, args, _this);
+}
+
 #ifdef DIRECT_THREADED
 // "Compile" a method by turning it from bytecode to direct-threaded
 // code.
@@ -805,2709 +877,239 @@
 void
 _Jv_InterpMethod::run (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
 {
-  using namespace java::lang::reflect;
+#undef DEBUG
+#undef DEBUG_LOCALS_INSN
+#define DEBUG_LOCALS_INSN(s, t) {}
 
-  // FRAME_DESC registers this particular invocation as the top-most
-  // interpreter frame.  This lets the stack tracing code (for
-  // Throwable) print information about the method being interpreted
-  // rather than about the interpreter itself.  FRAME_DESC has a
-  // destructor so it cleans up automatically when the interpreter
-  // returns.
-  java::lang::Thread *thread = java::lang::Thread::currentThread();
-  _Jv_InterpFrame frame_desc (meth, thread);
+#include "interpret-run.cc"
+}
 
-  _Jv_word stack[meth->max_stack];
-  _Jv_word *sp = stack;
+void
+_Jv_InterpMethod::run_debug (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
+{
+/* Used to keep track of local variable type
+ * 
+ * Possible Types:
+ * o object
+ * i integer
+ * f float
+ * l long 
+ * d double 
+ */
+#define DEBUG
+#undef DEBUG_LOCALS_INSN
+#define DEBUG_LOCALS_INSN(s, t) {}
 
-  _Jv_word locals[meth->max_locals];
+#include "interpret-run.cc"
+}
 
-#define INSN_LABEL(op) &&insn_##op
+static void
+throw_internal_error (const char *msg)
+{
+  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
+}
 
-  static const void *const insn_target[] = 
-  {
-    INSN_LABEL(nop),
-    INSN_LABEL(aconst_null),
-    INSN_LABEL(iconst_m1),
-    INSN_LABEL(iconst_0),
-    INSN_LABEL(iconst_1),
-    INSN_LABEL(iconst_2),
-    INSN_LABEL(iconst_3),
-    INSN_LABEL(iconst_4),
-    INSN_LABEL(iconst_5),
-    INSN_LABEL(lconst_0),
-    INSN_LABEL(lconst_1),
-    INSN_LABEL(fconst_0),
-    INSN_LABEL(fconst_1),
-    INSN_LABEL(fconst_2),
-    INSN_LABEL(dconst_0),
-    INSN_LABEL(dconst_1),
-    INSN_LABEL(bipush),
-    INSN_LABEL(sipush),
-    INSN_LABEL(ldc),
-    INSN_LABEL(ldc_w),
-    INSN_LABEL(ldc2_w),
-    INSN_LABEL(iload),
-    INSN_LABEL(lload),
-    INSN_LABEL(fload),
-    INSN_LABEL(dload),
-    INSN_LABEL(aload),
-    INSN_LABEL(iload_0),
-    INSN_LABEL(iload_1),
-    INSN_LABEL(iload_2),
-    INSN_LABEL(iload_3),
-    INSN_LABEL(lload_0),
-    INSN_LABEL(lload_1),
-    INSN_LABEL(lload_2),
-    INSN_LABEL(lload_3),
-    INSN_LABEL(fload_0),
-    INSN_LABEL(fload_1),
-    INSN_LABEL(fload_2),
-    INSN_LABEL(fload_3),
-    INSN_LABEL(dload_0),
-    INSN_LABEL(dload_1),
-    INSN_LABEL(dload_2),
-    INSN_LABEL(dload_3),
-    INSN_LABEL(aload_0),
-    INSN_LABEL(aload_1),
-    INSN_LABEL(aload_2),
-    INSN_LABEL(aload_3),
-    INSN_LABEL(iaload),
-    INSN_LABEL(laload),
-    INSN_LABEL(faload),
-    INSN_LABEL(daload),
-    INSN_LABEL(aaload),
-    INSN_LABEL(baload),
-    INSN_LABEL(caload),
-    INSN_LABEL(saload),
-    INSN_LABEL(istore),
-    INSN_LABEL(lstore),
-    INSN_LABEL(fstore),
-    INSN_LABEL(dstore),
-    INSN_LABEL(astore),
-    INSN_LABEL(istore_0),
-    INSN_LABEL(istore_1),
-    INSN_LABEL(istore_2),
-    INSN_LABEL(istore_3),
-    INSN_LABEL(lstore_0),
-    INSN_LABEL(lstore_1),
-    INSN_LABEL(lstore_2),
-    INSN_LABEL(lstore_3),
-    INSN_LABEL(fstore_0),
-    INSN_LABEL(fstore_1),
-    INSN_LABEL(fstore_2),
-    INSN_LABEL(fstore_3),
-    INSN_LABEL(dstore_0),
-    INSN_LABEL(dstore_1),
-    INSN_LABEL(dstore_2),
-    INSN_LABEL(dstore_3),
-    INSN_LABEL(astore_0),
-    INSN_LABEL(astore_1),
-    INSN_LABEL(astore_2),
-    INSN_LABEL(astore_3),
-    INSN_LABEL(iastore),
-    INSN_LABEL(lastore),
-    INSN_LABEL(fastore),
-    INSN_LABEL(dastore),
-    INSN_LABEL(aastore),
-    INSN_LABEL(bastore),
-    INSN_LABEL(castore),
-    INSN_LABEL(sastore),
-    INSN_LABEL(pop),
-    INSN_LABEL(pop2),
-    INSN_LABEL(dup),
-    INSN_LABEL(dup_x1),
-    INSN_LABEL(dup_x2),
-    INSN_LABEL(dup2),
-    INSN_LABEL(dup2_x1),
-    INSN_LABEL(dup2_x2),
-    INSN_LABEL(swap),
-    INSN_LABEL(iadd),
-    INSN_LABEL(ladd),
-    INSN_LABEL(fadd),
-    INSN_LABEL(dadd),
-    INSN_LABEL(isub),
-    INSN_LABEL(lsub),
-    INSN_LABEL(fsub),
-    INSN_LABEL(dsub),
-    INSN_LABEL(imul),
-    INSN_LABEL(lmul),
-    INSN_LABEL(fmul),
-    INSN_LABEL(dmul),
-    INSN_LABEL(idiv),
-    INSN_LABEL(ldiv),
-    INSN_LABEL(fdiv),
-    INSN_LABEL(ddiv),
-    INSN_LABEL(irem),
-    INSN_LABEL(lrem),
-    INSN_LABEL(frem),
-    INSN_LABEL(drem),
-    INSN_LABEL(ineg),
-    INSN_LABEL(lneg),
-    INSN_LABEL(fneg),
-    INSN_LABEL(dneg),
-    INSN_LABEL(ishl),
-    INSN_LABEL(lshl),
-    INSN_LABEL(ishr),
-    INSN_LABEL(lshr),
-    INSN_LABEL(iushr),
-    INSN_LABEL(lushr),
-    INSN_LABEL(iand),
-    INSN_LABEL(land),
-    INSN_LABEL(ior),
-    INSN_LABEL(lor),
-    INSN_LABEL(ixor),
-    INSN_LABEL(lxor),
-    INSN_LABEL(iinc),
-    INSN_LABEL(i2l),
-    INSN_LABEL(i2f),
-    INSN_LABEL(i2d),
-    INSN_LABEL(l2i),
-    INSN_LABEL(l2f),
-    INSN_LABEL(l2d),
-    INSN_LABEL(f2i),
-    INSN_LABEL(f2l),
-    INSN_LABEL(f2d),
-    INSN_LABEL(d2i),
-    INSN_LABEL(d2l),
-    INSN_LABEL(d2f),
-    INSN_LABEL(i2b),
-    INSN_LABEL(i2c),
-    INSN_LABEL(i2s),
-    INSN_LABEL(lcmp),
-    INSN_LABEL(fcmpl),
-    INSN_LABEL(fcmpg),
-    INSN_LABEL(dcmpl),
-    INSN_LABEL(dcmpg),
-    INSN_LABEL(ifeq),
-    INSN_LABEL(ifne),
-    INSN_LABEL(iflt),
-    INSN_LABEL(ifge),
-    INSN_LABEL(ifgt),
-    INSN_LABEL(ifle),
-    INSN_LABEL(if_icmpeq),
-    INSN_LABEL(if_icmpne),
-    INSN_LABEL(if_icmplt),
-    INSN_LABEL(if_icmpge),
-    INSN_LABEL(if_icmpgt),
-    INSN_LABEL(if_icmple),
-    INSN_LABEL(if_acmpeq),
-    INSN_LABEL(if_acmpne),
-    INSN_LABEL(goto), 
-    INSN_LABEL(jsr),
-    INSN_LABEL(ret),
-    INSN_LABEL(tableswitch),
-    INSN_LABEL(lookupswitch),
-    INSN_LABEL(ireturn),
-    INSN_LABEL(lreturn),
-    INSN_LABEL(freturn),
-    INSN_LABEL(dreturn),
-    INSN_LABEL(areturn),
-    INSN_LABEL(return),
-    INSN_LABEL(getstatic),
-    INSN_LABEL(putstatic),
-    INSN_LABEL(getfield),
-    INSN_LABEL(putfield),
-    INSN_LABEL(invokevirtual),
-    INSN_LABEL(invokespecial),
-    INSN_LABEL(invokestatic),
-    INSN_LABEL(invokeinterface),
-    0, /* Unused.  */
-    INSN_LABEL(new),
-    INSN_LABEL(newarray),
-    INSN_LABEL(anewarray),
-    INSN_LABEL(arraylength),
-    INSN_LABEL(athrow),
-    INSN_LABEL(checkcast),
-    INSN_LABEL(instanceof),
-    INSN_LABEL(monitorenter),
-    INSN_LABEL(monitorexit),
-#ifdef DIRECT_THREADED
-    0, // wide
-#else
-    INSN_LABEL(wide),
-#endif
-    INSN_LABEL(multianewarray),
-    INSN_LABEL(ifnull),
-    INSN_LABEL(ifnonnull),
-    INSN_LABEL(goto_w),
-    INSN_LABEL(jsr_w),
-#ifdef DIRECT_THREADED
-    INSN_LABEL (ldc_class)
-#else
-    0
-#endif
-  };
+static void 
+throw_incompatible_class_change_error (jstring msg)
+{
+  throw new java::lang::IncompatibleClassChangeError (msg);
+}
 
-  pc_t pc;
+static void 
+throw_null_pointer_exception ()
+{
+  throw new java::lang::NullPointerException;
+}
 
-#ifdef DIRECT_THREADED
+/* Look up source code line number for given bytecode (or direct threaded
+   interpreter) PC. */
+int
+_Jv_InterpMethod::get_source_line(pc_t mpc)
+{
+  int line = line_table_len > 0 ? line_table[0].line : -1;
+  for (int i = 1; i < line_table_len; i++)
+    if (line_table[i].pc > mpc)
+      break;
+    else
+      line = line_table[i].line;
 
-#define NEXT_INSN goto *((pc++)->insn)
-#define INTVAL() ((pc++)->int_val)
-#define AVAL() ((pc++)->datum)
+  return line;
+}
 
-#define GET1S() INTVAL ()
-#define GET2S() INTVAL ()
-#define GET1U() INTVAL ()
-#define GET2U() INTVAL ()
-#define AVAL1U() AVAL ()
-#define AVAL2U() AVAL ()
-#define AVAL2UP() AVAL ()
-#define SKIP_GOTO ++pc
-#define GOTO_VAL() (insn_slot *) pc->datum
-#define PCVAL(unionval) unionval.p
-#define AMPAMP(label) &&label
+/** Do static initialization for fields with a constant initializer */
+void
+_Jv_InitField (jobject obj, jclass klass, int index)
+{
+  using namespace java::lang::reflect;
 
-  // Compile if we must. NOTE: Double-check locking.
-  if (meth->prepared == NULL)
-    {
-      _Jv_MutexLock (&compile_mutex);
-      if (meth->prepared == NULL)
-	meth->compile (insn_target);
-      _Jv_MutexUnlock (&compile_mutex);
-    }
+  if (obj != 0 && klass == 0)
+    klass = obj->getClass ();
 
-  // If we're only compiling, stop here
-  if (args == NULL)
+  if (!_Jv_IsInterpretedClass (klass))
     return;
 
-  pc = (insn_slot *) meth->prepared;
-
-#else
+  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
 
-#define NEXT_INSN goto *(insn_target[*pc++])
+  _Jv_Field * field = (&klass->fields[0]) + index;
 
-#define GET1S() get1s (pc++)
-#define GET2S() (pc += 2, get2s (pc- 2))
-#define GET1U() get1u (pc++)
-#define GET2U() (pc += 2, get2u (pc - 2))
-  // Note that these could be more efficient when not handling 'ldc
-  // class'.
-#define AVAL1U()						\
-  ({ int index = get1u (pc++);					\
-      resolve_pool_entry (meth->defining_class, index).o; })
-#define AVAL2U()						\
-  ({ int index = get2u (pc); pc += 2;				\
-      resolve_pool_entry (meth->defining_class, index).o; })
-  // Note that we don't need to resolve the pool entry here as class
-  // constants are never wide.
-#define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
-#define SKIP_GOTO pc += 2
-#define GOTO_VAL() pc - 1 + get2s (pc)
-#define PCVAL(unionval) unionval.i
-#define AMPAMP(label) NULL
+  if (index > klass->field_count)
+    throw_internal_error ("field out of range");
 
-  pc = bytecode ();
+  int init = iclass->field_initializers[index];
+  if (init == 0)
+    return;
 
-#endif /* DIRECT_THREADED */
+  _Jv_Constants *pool = &klass->constants;
+  int tag = pool->tags[init];
 
-#define TAKE_GOTO pc = GOTO_VAL ()
+  if (! field->isResolved ())
+    throw_internal_error ("initializing unresolved field");
 
-  /* Go straight at it!  the ffi raw format matches the internal
-     stack representation exactly.  At least, that's the idea.
-  */
-  memcpy ((void*) locals, (void*) args, meth->args_raw_size);
+  if (obj==0 && ((field->flags & Modifier::STATIC) == 0))
+    throw_internal_error ("initializing non-static field with no object");
 
-  _Jv_word *pool_data = meth->defining_class->constants.data;
+  void *addr = 0;
 
-  /* These three are temporaries for common code used by several
-     instructions.  */
-  void (*fun)();
-  _Jv_ResolvedMethod* rmeth;
-  int tmpval;
+  if ((field->flags & Modifier::STATIC) != 0)
+    addr = (void*) field->u.addr;
+  else
+    addr = (void*) (((char*)obj) + field->u.boffset);
 
-  try
+  switch (tag)
     {
-      // We keep nop around.  It is used if we're interpreting the
-      // bytecodes and not doing direct threading.
-    insn_nop:
-      NEXT_INSN;
-
-      /* The first few instructions here are ordered according to their
-	 frequency, in the hope that this will improve code locality a
-	 little.  */
-
-    insn_aload_0:		// 0x2a
-      LOADA (0);
-      NEXT_INSN;
-
-    insn_iload:		// 0x15
-      LOADI (GET1U ());
-      NEXT_INSN;
-
-    insn_iload_1:		// 0x1b
-      LOADI (1);
-      NEXT_INSN;
-
-    insn_invokevirtual:	// 0xb6
+    case JV_CONSTANT_String:
       {
-	SAVE_PC();
-	int index = GET2U ();
-
-	/* _Jv_Linker::resolve_pool_entry returns immediately if the
-	 * value already is resolved.  If we want to clutter up the
-	 * code here to gain a little performance, then we can check
-	 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
-	 * directly.  For now, I don't think it is worth it.  */
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	if (rmeth->method->accflags & Modifier::FINAL)
-	  {
-	    // We can't rely on NULLCHECK working if the method is final.
-	    if (! sp[0].o)
-	      throw_null_pointer_exception ();
-
-	    // Final methods might not appear in the vtable.
-	    fun = (void (*)()) rmeth->method->ncode;
-	  }
-	else
-	  {
-	    NULLCHECK (sp[0].o);
-	    jobject rcv = sp[0].o;
-	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
-	    fun = (void (*)()) table->get_method (rmeth->method->index);
-	  }
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokevirtual_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
+	jstring str;
+	str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
+	pool->data[init].string = str;
+	pool->tags[init] = JV_CONSTANT_ResolvedString;
       }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokevirtual_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
+      /* fall through */
 
-	if (rmeth->method->accflags & Modifier::FINAL)
-	  {
-	    // We can't rely on NULLCHECK working if the method is final.
-	    if (! sp[0].o)
-	      throw_null_pointer_exception ();
+    case JV_CONSTANT_ResolvedString:
+      if (! (field->type == &java::lang::String::class$
+ 	     || field->type == &java::lang::Class::class$))
+	throw_class_format_error ("string initialiser to non-string field");
 
-	    // Final methods might not appear in the vtable.
-	    fun = (void (*)()) rmeth->method->ncode;
-	  }
-	else
-	  {
-	    jobject rcv = sp[0].o;
-	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
-	    fun = (void (*)()) table->get_method (rmeth->method->index);
-	  }
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
+      *(jstring*)addr = pool->data[init].string;
+      break;
 
-    perform_invoke:
+    case JV_CONSTANT_Integer:
       {
-	/* here goes the magic again... */
-	ffi_cif *cif = &rmeth->cif;
-	ffi_raw *raw = (ffi_raw*) sp;
-
-	_Jv_value rvalue;
+	int value = pool->data[init].i;
 
-#if FFI_NATIVE_RAW_API
-	/* We assume that this is only implemented if it's correct	*/
-	/* to use it here.  On a 64 bit machine, it never is.		*/
-	ffi_raw_call (cif, fun, (void*)&rvalue, raw);
-#else
-	ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
-#endif
+	if (field->type == JvPrimClass (boolean))
+	  *(jboolean*)addr = (jboolean)value;
+	
+	else if (field->type == JvPrimClass (byte))
+	  *(jbyte*)addr = (jbyte)value;
+	
+	else if (field->type == JvPrimClass (char))
+	  *(jchar*)addr = (jchar)value;
 
-	int rtype = cif->rtype->type;
+	else if (field->type == JvPrimClass (short))
+	  *(jshort*)addr = (jshort)value;
+	
+	else if (field->type == JvPrimClass (int))
+	  *(jint*)addr = (jint)value;
 
-	/* the likelyhood of object, int, or void return is very high,
-	 * so those are checked before the switch */
-	if (rtype == FFI_TYPE_POINTER)
-	  {
-	    PUSHA (rvalue.object_value);
-	  }
-	else if (rtype == FFI_TYPE_SINT32)
-	  {
-	    PUSHI (rvalue.int_value);
-	  }
-	else if (rtype == FFI_TYPE_VOID)
-	  {
-	    /* skip */
-	  }
 	else
-	  {
-	    switch (rtype)
-	      {
-	      case FFI_TYPE_SINT8:
-		PUSHI ((jbyte)(rvalue.int_value & 0xff));
-		break;
-
-	      case FFI_TYPE_SINT16:
-		PUSHI ((jshort)(rvalue.int_value & 0xffff));
-		break;
-
-	      case FFI_TYPE_UINT16:
-		PUSHI (rvalue.int_value & 0xffff);
-		break;
+	  throw_class_format_error ("erroneous field initializer");
+      }  
+      break;
 
-	      case FFI_TYPE_FLOAT:
-	        PUSHF (rvalue.float_value);
-		break;
+    case JV_CONSTANT_Long:
+      if (field->type != JvPrimClass (long))
+	throw_class_format_error ("erroneous field initializer");
 
-	      case FFI_TYPE_DOUBLE:
-	        PUSHD (rvalue.double_value);
-		break;
+      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
+      break;
 
-	      case FFI_TYPE_SINT64:
-	        PUSHL (rvalue.long_value);
-		break;
+    case JV_CONSTANT_Float:
+      if (field->type != JvPrimClass (float))
+	throw_class_format_error ("erroneous field initializer");
 
-	      default:
-		throw_internal_error ("unknown return type in invokeXXX");
-	      }
-	  }
-      }
-      NEXT_INSN;
+      *(jfloat*)addr = pool->data[init].f;
+      break;
 
-    insn_aconst_null:
-      PUSHA (NULL);
-      NEXT_INSN;
+    case JV_CONSTANT_Double:
+      if (field->type != JvPrimClass (double))
+	throw_class_format_error ("erroneous field initializer");
 
-    insn_iconst_m1:
-      PUSHI (-1);
-      NEXT_INSN;
+      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
+      break;
 
-    insn_iconst_0:
-      PUSHI (0);
-      NEXT_INSN;
+    default:
+      throw_class_format_error ("erroneous field initializer");
+    }
+}
 
-    insn_iconst_1:
-      PUSHI (1);
-      NEXT_INSN;
+inline static unsigned char*
+skip_one_type (unsigned char* ptr)
+{
+  int ch = *ptr++;
 
-    insn_iconst_2:
-      PUSHI (2);
-      NEXT_INSN;
+  while (ch == '[')
+    { 
+      ch = *ptr++;
+    }
+  
+  if (ch == 'L')
+    {
+      do { ch = *ptr++; } while (ch != ';');
+    }
 
-    insn_iconst_3:
-      PUSHI (3);
-      NEXT_INSN;
+  return ptr;
+}
 
-    insn_iconst_4:
-      PUSHI (4);
-      NEXT_INSN;
+static ffi_type*
+get_ffi_type_from_signature (unsigned char* ptr)
+{
+  switch (*ptr) 
+    {
+    case 'L':
+    case '[':
+      return &ffi_type_pointer;
+      break;
 
-    insn_iconst_5:
-      PUSHI (5);
-      NEXT_INSN;
+    case 'Z':
+      // On some platforms a bool is a byte, on others an int.
+      if (sizeof (jboolean) == sizeof (jbyte))
+	return &ffi_type_sint8;
+      else
+	{
+	  JvAssert (sizeof (jbyte) == sizeof (jint));
+	  return &ffi_type_sint32;
+	}
+      break;
 
-    insn_lconst_0:
-      PUSHL (0);
-      NEXT_INSN;
-
-    insn_lconst_1:
-      PUSHL (1);
-      NEXT_INSN;
-
-    insn_fconst_0:
-      PUSHF (0);
-      NEXT_INSN;
-
-    insn_fconst_1:
-      PUSHF (1);
-      NEXT_INSN;
-
-    insn_fconst_2:
-      PUSHF (2);
-      NEXT_INSN;
-
-    insn_dconst_0:
-      PUSHD (0);
-      NEXT_INSN;
-
-    insn_dconst_1:
-      PUSHD (1);
-      NEXT_INSN;
-
-    insn_bipush:
-      // For direct threaded, bipush and sipush are the same.
-#ifndef DIRECT_THREADED
-      PUSHI (GET1S ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_sipush:
-      PUSHI (GET2S ());
-      NEXT_INSN;
-
-    insn_ldc:
-      // For direct threaded, ldc and ldc_w are the same.
-#ifndef DIRECT_THREADED
-      PUSHA ((jobject) AVAL1U ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_ldc_w:
-      PUSHA ((jobject) AVAL2U ());
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-      // For direct threaded we have a separate 'ldc class' operation.
-    insn_ldc_class:
-      {
-	SAVE_PC();
-	// We could rewrite the instruction at this point.
-	int index = INTVAL ();
-	jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						     index)).o;
-	PUSHA (k);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_ldc2_w:
-      {
-	void *where = AVAL2UP ();
-	memcpy (sp, where, 2*sizeof (_Jv_word));
-	sp += 2;
-      }
-      NEXT_INSN;
-
-    insn_lload:
-      LOADL (GET1U ());
-      NEXT_INSN;
-
-    insn_fload:
-      LOADF (GET1U ());
-      NEXT_INSN;
-
-    insn_dload:
-      LOADD (GET1U ());
-      NEXT_INSN;
-
-    insn_aload:
-      LOADA (GET1U ());
-      NEXT_INSN;
-
-    insn_iload_0:
-      LOADI (0);
-      NEXT_INSN;
-
-    insn_iload_2:
-      LOADI (2);
-      NEXT_INSN;
-
-    insn_iload_3:
-      LOADI (3);
-      NEXT_INSN;
-
-    insn_lload_0:
-      LOADL (0);
-      NEXT_INSN;
-
-    insn_lload_1:
-      LOADL (1);
-      NEXT_INSN;
-
-    insn_lload_2:
-      LOADL (2);
-      NEXT_INSN;
-
-    insn_lload_3:
-      LOADL (3);
-      NEXT_INSN;
-
-    insn_fload_0:
-      LOADF (0);
-      NEXT_INSN;
-
-    insn_fload_1:
-      LOADF (1);
-      NEXT_INSN;
-
-    insn_fload_2:
-      LOADF (2);
-      NEXT_INSN;
-
-    insn_fload_3:
-      LOADF (3);
-      NEXT_INSN;
-
-    insn_dload_0:
-      LOADD (0);
-      NEXT_INSN;
-
-    insn_dload_1:
-      LOADD (1);
-      NEXT_INSN;
-
-    insn_dload_2:
-      LOADD (2);
-      NEXT_INSN;
-
-    insn_dload_3:
-      LOADD (3);
-      NEXT_INSN;
-
-    insn_aload_1:
-      LOADA(1);
-      NEXT_INSN;
-
-    insn_aload_2:
-      LOADA(2);
-      NEXT_INSN;
-
-    insn_aload_3:
-      LOADA(3);
-      NEXT_INSN;
-
-    insn_iaload:
-      {
-	jint index = POPI();
-	jintArray arr = (jintArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_laload:
-      {
-	jint index = POPI();
-	jlongArray arr = (jlongArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHL( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_faload:
-      {
-	jint index = POPI();
-	jfloatArray arr = (jfloatArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHF( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_daload:
-      {
-	jint index = POPI();
-	jdoubleArray arr = (jdoubleArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHD( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_aaload:
-      {
-	jint index = POPI();
-	jobjectArray arr = (jobjectArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHA( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_baload:
-      {
-	jint index = POPI();
-	jbyteArray arr = (jbyteArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_caload:
-      {
-	jint index = POPI();
-	jcharArray arr = (jcharArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_saload:
-      {
-	jint index = POPI();
-	jshortArray arr = (jshortArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_istore:
-      STOREI (GET1U ());
-      NEXT_INSN;
-
-    insn_lstore:
-      STOREL (GET1U ());
-      NEXT_INSN;
-
-    insn_fstore:
-      STOREF (GET1U ());
-      NEXT_INSN;
-
-    insn_dstore:
-      STORED (GET1U ());
-      NEXT_INSN;
-
-    insn_astore:
-      STOREA (GET1U ());
-      NEXT_INSN;
-
-    insn_istore_0:
-      STOREI (0);
-      NEXT_INSN;
-
-    insn_istore_1:
-      STOREI (1);
-      NEXT_INSN;
-
-    insn_istore_2:
-      STOREI (2);
-      NEXT_INSN;
-
-    insn_istore_3:
-      STOREI (3);
-      NEXT_INSN;
-
-    insn_lstore_0:
-      STOREL (0);
-      NEXT_INSN;
-
-    insn_lstore_1:
-      STOREL (1);
-      NEXT_INSN;
-
-    insn_lstore_2:
-      STOREL (2);
-      NEXT_INSN;
-
-    insn_lstore_3:
-      STOREL (3);
-      NEXT_INSN;
-
-    insn_fstore_0:
-      STOREF (0);
-      NEXT_INSN;
-
-    insn_fstore_1:
-      STOREF (1);
-      NEXT_INSN;
-
-    insn_fstore_2:
-      STOREF (2);
-      NEXT_INSN;
-
-    insn_fstore_3:
-      STOREF (3);
-      NEXT_INSN;
-
-    insn_dstore_0:
-      STORED (0);
-      NEXT_INSN;
-
-    insn_dstore_1:
-      STORED (1);
-      NEXT_INSN;
-
-    insn_dstore_2:
-      STORED (2);
-      NEXT_INSN;
-
-    insn_dstore_3:
-      STORED (3);
-      NEXT_INSN;
-
-    insn_astore_0:
-      STOREA(0);
-      NEXT_INSN;
-
-    insn_astore_1:
-      STOREA(1);
-      NEXT_INSN;
-
-    insn_astore_2:
-      STOREA(2);
-      NEXT_INSN;
-
-    insn_astore_3:
-      STOREA(3);
-      NEXT_INSN;
-
-    insn_iastore:
-      {
-	jint value = POPI();
-	jint index  = POPI();
-	jintArray arr = (jintArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_lastore:
-      {
-	jlong value = POPL();
-	jint index  = POPI();
-	jlongArray arr = (jlongArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_fastore:
-      {
-	jfloat value = POPF();
-	jint index  = POPI();
-	jfloatArray arr = (jfloatArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_dastore:
-      {
-	jdouble value = POPD();
-	jint index  = POPI();
-	jdoubleArray arr = (jdoubleArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_aastore:
-      {
-	jobject value = POPA();
-	jint index  = POPI();
-	jobjectArray arr = (jobjectArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	_Jv_CheckArrayStore (arr, value);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_bastore:
-      {
-	jbyte value = (jbyte) POPI();
-	jint index  = POPI();
-	jbyteArray arr = (jbyteArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_castore:
-      {
-	jchar value = (jchar) POPI();
-	jint index  = POPI();
-	jcharArray arr = (jcharArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_sastore:
-      {
-	jshort value = (jshort) POPI();
-	jint index  = POPI();
-	jshortArray arr = (jshortArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_pop:
-      sp -= 1;
-      NEXT_INSN;
-
-    insn_pop2:
-      sp -= 2;
-      NEXT_INSN;
-
-    insn_dup:
-      sp[0] = sp[-1];
-      sp += 1;
-      NEXT_INSN;
-
-    insn_dup_x1:
-      dupx (sp, 1, 1); sp+=1;
-      NEXT_INSN;
-
-    insn_dup_x2:
-      dupx (sp, 1, 2); sp+=1;
-      NEXT_INSN;
-
-    insn_dup2:
-      sp[0] = sp[-2];
-      sp[1] = sp[-1];
-      sp += 2;
-      NEXT_INSN;
-
-    insn_dup2_x1:
-      dupx (sp, 2, 1); sp+=2;
-      NEXT_INSN;
-
-    insn_dup2_x2:
-      dupx (sp, 2, 2); sp+=2;
-      NEXT_INSN;
-
-    insn_swap:
-      {
-	jobject tmp1 = POPA();
-	jobject tmp2 = POPA();
-	PUSHA (tmp1);
-	PUSHA (tmp2);
-      }
-      NEXT_INSN;
-
-    insn_iadd:
-      BINOPI(+);
-      NEXT_INSN;
-
-    insn_ladd:
-      BINOPL(+);
-      NEXT_INSN;
-
-    insn_fadd:
-      BINOPF(+);
-      NEXT_INSN;
-
-    insn_dadd:
-      BINOPD(+);
-      NEXT_INSN;
-
-    insn_isub:
-      BINOPI(-);
-      NEXT_INSN;
-
-    insn_lsub:
-      BINOPL(-);
-      NEXT_INSN;
-
-    insn_fsub:
-      BINOPF(-);
-      NEXT_INSN;
-
-    insn_dsub:
-      BINOPD(-);
-      NEXT_INSN;
-
-    insn_imul:
-      BINOPI(*);
-      NEXT_INSN;
-
-    insn_lmul:
-      BINOPL(*);
-      NEXT_INSN;
-
-    insn_fmul:
-      BINOPF(*);
-      NEXT_INSN;
-
-    insn_dmul:
-      BINOPD(*);
-      NEXT_INSN;
-
-    insn_idiv:
-      {
-	SAVE_PC();
-	jint value2 = POPI();
-	jint value1 = POPI();
-	jint res = _Jv_divI (value1, value2);
-	PUSHI (res);
-      }
-      NEXT_INSN;
-
-    insn_ldiv:
-      {
-	SAVE_PC();
-	jlong value2 = POPL();
-	jlong value1 = POPL();
-	jlong res = _Jv_divJ (value1, value2);
-	PUSHL (res);
-      }
-      NEXT_INSN;
-
-    insn_fdiv:
-      {
-	jfloat value2 = POPF();
-	jfloat value1 = POPF();
-	jfloat res = value1 / value2;
-	PUSHF (res);
-      }
-      NEXT_INSN;
-
-    insn_ddiv:
-      {
-	jdouble value2 = POPD();
-	jdouble value1 = POPD();
-	jdouble res = value1 / value2;
-	PUSHD (res);
-      }
-      NEXT_INSN;
-
-    insn_irem:
-      {
-	SAVE_PC();
-	jint value2 = POPI();
-	jint value1 =  POPI();
-	jint res = _Jv_remI (value1, value2);
-	PUSHI (res);
-      }
-      NEXT_INSN;
-
-    insn_lrem:
-      {
-	SAVE_PC();
-	jlong value2 = POPL();
-	jlong value1 = POPL();
-	jlong res = _Jv_remJ (value1, value2);
-	PUSHL (res);
-      }
-      NEXT_INSN;
-
-    insn_frem:
-      {
-	jfloat value2 = POPF();
-	jfloat value1 = POPF();
-	jfloat res    = __ieee754_fmod (value1, value2);
-	PUSHF (res);
-      }
-      NEXT_INSN;
-
-    insn_drem:
-      {
-	jdouble value2 = POPD();
-	jdouble value1 = POPD();
-	jdouble res    = __ieee754_fmod (value1, value2);
-	PUSHD (res);
-      }
-      NEXT_INSN;
-
-    insn_ineg:
-      {
-	jint value = POPI();
-	PUSHI (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_lneg:
-      {
-	jlong value = POPL();
-	PUSHL (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_fneg:
-      {
-	jfloat value = POPF();
-	PUSHF (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_dneg:
-      {
-	jdouble value = POPD();
-	PUSHD (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_ishl:
-      {
-	jint shift = (POPI() & 0x1f);
-	jint value = POPI();
-	PUSHI (value << shift);
-      }
-      NEXT_INSN;
-
-    insn_lshl:
-      {
-	jint shift = (POPI() & 0x3f);
-	jlong value = POPL();
-	PUSHL (value << shift);
-      }
-      NEXT_INSN;
-
-    insn_ishr:
-      {
-	jint shift = (POPI() & 0x1f);
-	jint value = POPI();
-	PUSHI (value >> shift);
-      }
-      NEXT_INSN;
-
-    insn_lshr:
-      {
-	jint shift = (POPI() & 0x3f);
-	jlong value = POPL();
-	PUSHL (value >> shift);
-      }
-      NEXT_INSN;
-
-    insn_iushr:
-      {
-	jint shift = (POPI() & 0x1f);
-	_Jv_uint value = (_Jv_uint) POPI();
-	PUSHI ((jint) (value >> shift));
-      }
-      NEXT_INSN;
-
-    insn_lushr:
-      {
-	jint shift = (POPI() & 0x3f);
-	_Jv_ulong value = (_Jv_ulong) POPL();
-	PUSHL ((jlong) (value >> shift));
-      }
-      NEXT_INSN;
-
-    insn_iand:
-      BINOPI (&);
-      NEXT_INSN;
-
-    insn_land:
-      BINOPL (&);
-      NEXT_INSN;
-
-    insn_ior:
-      BINOPI (|);
-      NEXT_INSN;
-
-    insn_lor:
-      BINOPL (|);
-      NEXT_INSN;
-
-    insn_ixor:
-      BINOPI (^);
-      NEXT_INSN;
-
-    insn_lxor:
-      BINOPL (^);
-      NEXT_INSN;
-
-    insn_iinc:
-      {
-	jint index  = GET1U ();
-	jint amount = GET1S ();
-	locals[index].i += amount;
-      }
-      NEXT_INSN;
-
-    insn_i2l:
-      {jlong value = POPI(); PUSHL (value);}
-      NEXT_INSN;
-
-    insn_i2f:
-      {jfloat value = POPI(); PUSHF (value);}
-      NEXT_INSN;
-
-    insn_i2d:
-      {jdouble value = POPI(); PUSHD (value);}
-      NEXT_INSN;
-
-    insn_l2i:
-      {jint value = POPL(); PUSHI (value);}
-      NEXT_INSN;
-
-    insn_l2f:
-      {jfloat value = POPL(); PUSHF (value);}
-      NEXT_INSN;
-
-    insn_l2d:
-      {jdouble value = POPL(); PUSHD (value);}
-      NEXT_INSN;
-
-    insn_f2i:
-      {
-	using namespace java::lang;
-	jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
-	PUSHI(value);
-      }
-      NEXT_INSN;
-
-    insn_f2l:
-      {
-	using namespace java::lang;
-	jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
-	PUSHL(value);
-      }
-      NEXT_INSN;
-
-    insn_f2d:
-      { jdouble value = POPF (); PUSHD(value); }
-      NEXT_INSN;
-
-    insn_d2i:
-      {
-	using namespace java::lang;
-	jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
-	PUSHI(value);
-      }
-      NEXT_INSN;
-
-    insn_d2l:
-      {
-	using namespace java::lang;
-	jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
-	PUSHL(value);
-      }
-      NEXT_INSN;
-
-    insn_d2f:
-      { jfloat value = POPD (); PUSHF(value); }
-      NEXT_INSN;
-
-    insn_i2b:
-      { jbyte value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_i2c:
-      { jchar value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_i2s:
-      { jshort value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_lcmp:
-      {
-	jlong value2 = POPL ();
-	jlong value1 = POPL ();
-	if (value1 > value2)
-	  { PUSHI (1); }
-	else if (value1 == value2)
-	  { PUSHI (0); }
-	else
-	  { PUSHI (-1); }
-      }
-      NEXT_INSN;
-
-    insn_fcmpl:
-      tmpval = -1;
-      goto fcmp;
-
-    insn_fcmpg:
-      tmpval = 1;
-
-    fcmp:
-      {
-	jfloat value2 = POPF ();
-	jfloat value1 = POPF ();
-	if (value1 > value2)
-	  PUSHI (1);
-	else if (value1 == value2)
-	  PUSHI (0);
-	else if (value1 < value2)
-	  PUSHI (-1);
-	else
-	  PUSHI (tmpval);
-      }
-      NEXT_INSN;
-
-    insn_dcmpl:
-      tmpval = -1;
-      goto dcmp;
-
-    insn_dcmpg:
-      tmpval = 1;
-
-    dcmp:
-      {
-	jdouble value2 = POPD ();
-	jdouble value1 = POPD ();
-	if (value1 > value2)
-	  PUSHI (1);
-	else if (value1 == value2)
-	  PUSHI (0);
-	else if (value1 < value2)
-	  PUSHI (-1);
-	else
-	  PUSHI (tmpval);
-      }
-      NEXT_INSN;
-
-    insn_ifeq:
-      {
-	if (POPI() == 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifne:
-      {
-	if (POPI() != 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_iflt:
-      {
-	if (POPI() < 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifge:
-      {
-	if (POPI() >= 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifgt:
-      {
-	if (POPI() > 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifle:
-      {
-	if (POPI() <= 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpeq:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 == value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpne:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 != value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmplt:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 < value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpge:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 >= value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpgt:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 > value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmple:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 <= value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_acmpeq:
-      {
-	jobject value2 = POPA();
-	jobject value1 = POPA();
-	if (value1 == value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_acmpne:
-      {
-	jobject value2 = POPA();
-	jobject value1 = POPA();
-	if (value1 != value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_goto_w:
-#ifndef DIRECT_THREADED
-      // For direct threaded, goto and goto_w are the same.
-      pc = pc - 1 + get4 (pc);
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_goto:
-      TAKE_GOTO;
-      NEXT_INSN;
-
-    insn_jsr_w:
-#ifndef DIRECT_THREADED
-      // For direct threaded, jsr and jsr_w are the same.
-      {
-	pc_t next = pc - 1 + get4 (pc);
-	pc += 4;
-	PUSHA ((jobject) pc);
-	pc = next;
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_jsr:
-      {
-	pc_t next = GOTO_VAL();
-	SKIP_GOTO;
-	PUSHA ((jobject) pc);
-	pc = next;
-      }
-      NEXT_INSN;
-
-    insn_ret:
-      {
-	jint index = GET1U ();
-	pc = (pc_t) PEEKA (index);
-      }
-      NEXT_INSN;
-
-    insn_tableswitch:
-      {
-#ifdef DIRECT_THREADED
-	void *def = (pc++)->datum;
-
-	int index = POPI();
-
-	jint low = INTVAL ();
-	jint high = INTVAL ();
-
-	if (index < low || index > high)
-	  pc = (insn_slot *) def;
-	else
-	  pc = (insn_slot *) ((pc + index - low)->datum);
-#else
-	pc_t base_pc = pc - 1;
-	int index = POPI ();
-
-	pc_t base = (pc_t) bytecode ();
-	while ((pc - base) % 4 != 0)
-	  ++pc;
-
-	jint def = get4 (pc);
-	jint low = get4 (pc + 4);
-	jint high = get4 (pc + 8);
-	if (index < low || index > high)
-	  pc = base_pc + def;
-	else
-	  pc = base_pc + get4 (pc + 4 * (index - low + 3));
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-    insn_lookupswitch:
-      {
-#ifdef DIRECT_THREADED
-	void *def = (pc++)->insn;
-
-	int index = POPI();
-
-	jint npairs = INTVAL ();
-
-	int max = npairs - 1;
-	int min = 0;
-
-	// Simple binary search...
-	while (min < max)
-	  {
-	    int half = (min + max) / 2;
-	    int match = pc[2 * half].int_val;
-
-	    if (index == match)
-	      {
-		// Found it.
-		pc = (insn_slot *) pc[2 * half + 1].datum;
-		NEXT_INSN;
-	      }
-	    else if (index < match)
-	      // We can use HALF - 1 here because we check again on
-	      // loop exit.
-	      max = half - 1;
-	    else
-	      // We can use HALF + 1 here because we check again on
-	      // loop exit.
-	      min = half + 1;
-	  }
-	if (index == pc[2 * min].int_val)
-	  pc = (insn_slot *) pc[2 * min + 1].datum;
-	else
-	  pc = (insn_slot *) def;
-#else
-	unsigned char *base_pc = pc-1;
-	int index = POPI();
-
-	unsigned char* base = bytecode ();
-	while ((pc-base) % 4 != 0)
-	  ++pc;
-
-	jint def     = get4 (pc);
-	jint npairs  = get4 (pc+4);
-
-	int max = npairs-1;
-	int min = 0;
-
-	// Simple binary search...
-	while (min < max)
-	  {
-	    int half = (min+max)/2;
-	    int match = get4 (pc+ 4*(2 + 2*half));
-
-	    if (index == match)
-	      min = max = half;
-	    else if (index < match)
-	      // We can use HALF - 1 here because we check again on
-	      // loop exit.
-	      max = half - 1;
-	    else
-	      // We can use HALF + 1 here because we check again on
-	      // loop exit.
-	      min = half + 1;
-	  }
-
-	if (index == get4 (pc+ 4*(2 + 2*min)))
-	  pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
-	else
-	  pc = base_pc + def;    
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-    insn_areturn:
-      *(jobject *) retp = POPA ();
-      return;
-
-    insn_lreturn:
-      *(jlong *) retp = POPL ();
-      return;
-
-    insn_freturn:
-      *(jfloat *) retp = POPF ();
-      return;
-
-    insn_dreturn:
-      *(jdouble *) retp = POPD ();
-      return;
-
-    insn_ireturn:
-      *(jint *) retp = POPI ();
-      return;
-
-    insn_return:
-      return;
-
-    insn_getstatic:
-      {
-	jint fieldref_index = GET2U ();
-        SAVE_PC(); // Constant pool resolution could throw.
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	if ((field->flags & Modifier::STATIC) == 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field no longer static"));
-
-	jclass type = field->type;
-
-	// We rewrite the instruction once we discover what it refers
-	// to.
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes)
-	      {
-	      case 1:
-		PUSHI (*field->u.byte_addr);
-		newinsn = AMPAMP (getstatic_resolved_1);
-		break;
-
-	      case 2:
-		if (type == JvPrimClass (char))
-		  {
-		    PUSHI (*field->u.char_addr);
-		    newinsn = AMPAMP (getstatic_resolved_char);
-		  }
-		else
-		  {
-		    PUSHI (*field->u.short_addr);
-		    newinsn = AMPAMP (getstatic_resolved_short);
-		  }
-		break;
-
-	      case 4:
-	        PUSHI(*field->u.int_addr);
-		newinsn = AMPAMP (getstatic_resolved_4);
-		break;
-
-	      case 8:
-	        PUSHL(*field->u.long_addr);
-		newinsn = AMPAMP (getstatic_resolved_8);
-		break;
-	      }
-	  }
-	else
-	  {
-	    PUSHA(*field->u.object_addr);
-	    newinsn = AMPAMP (getstatic_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].datum = field->u.addr;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    getstatic_resolved_1:
-      PUSHI (*(jbyte *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_char:
-      PUSHI (*(jchar *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_short:
-      PUSHI (*(jshort *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_4:
-      PUSHI (*(jint *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_8:
-      PUSHL (*(jlong *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_obj:
-      PUSHA (*(jobject *) AVAL ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_getfield:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	if ((field->flags & Modifier::STATIC) != 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field is static"));
-
-	jclass type = field->type;
-	jint field_offset = field->u.boffset;
-
-	jobject obj   = POPA();
-	NULLCHECK(obj);
-
-	void *newinsn = NULL;
-	_Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes)
-	      {
-	      case 1:
-	        PUSHI (val->byte_value);
-		newinsn = AMPAMP (getfield_resolved_1);
-		break;
-
-	      case 2:
-		if (type == JvPrimClass (char))
-		  {
-		    PUSHI (val->char_value);
-		    newinsn = AMPAMP (getfield_resolved_char);
-		  }
-		else
-		  {
-		    PUSHI (val->short_value);
-		    newinsn = AMPAMP (getfield_resolved_short);
-		  }
-		break;
-
-	      case 4:
-		PUSHI (val->int_value);
-		newinsn = AMPAMP (getfield_resolved_4);
-		break;
-
-	      case 8:
-	        PUSHL (val->long_value);
-		newinsn = AMPAMP (getfield_resolved_8);
-		break;
-	      }
-	  }
-	else
-	  {
-	    PUSHA (val->object_value);
-	    newinsn = AMPAMP (getfield_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].int_val = field_offset;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    getfield_resolved_1:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jbyte *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_char:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jchar *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_short:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jshort *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_4:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jint *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_8:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHL (*(jlong *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_obj:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHA (*(jobject *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_putstatic:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	jclass type = field->type;
-
-	// ResolvePoolEntry cannot check this
-	if ((field->flags & Modifier::STATIC) == 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field no longer static"));
-
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes) 
-	      {
-	      case 1:
-		{
-		  jint value = POPI();
-		  *field->u.byte_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_1);
-		  break;
-		}
-
-	      case 2:
-		{
-		  jint value = POPI();
-		  *field->u.char_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_2);
-		  break;
-		}
-
-	      case 4:
-		{
-		  jint value = POPI();
-		  *field->u.int_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_4);
-		  break;
-		}
-
-	      case 8:
-		{
-		  jlong value = POPL();
-		  *field->u.long_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_8);
-		  break;
-		}
-	      }
-	  }
-	else
-	  {
-	    jobject value = POPA();
-	    *field->u.object_addr = value;
-	    newinsn = AMPAMP (putstatic_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].datum = field->u.addr;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    putstatic_resolved_1:
-      *(jbyte *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_2:
-      *(jchar *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_4:
-      *(jint *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_8:
-      *(jlong *) AVAL () = POPL ();
-      NEXT_INSN;
-
-    putstatic_resolved_obj:
-      *(jobject *) AVAL () = POPA ();
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_putfield:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	jclass type = field->type;
-
-	if ((field->flags & Modifier::STATIC) != 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field is static"));
-
-	jint field_offset = field->u.boffset;
-
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes) 
-	      {
-	      case 1:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jbyte*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_1);
-		  break;
-		}
-
-	      case 2:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jchar*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_2);
-		  break;
-		}
-
-	      case 4:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jint*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_4);
-		  break;
-		}
-
-	      case 8:
-		{
-		  jlong   value = POPL();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jlong*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_8);
-		  break;
-		}
-	      }
-	  }
-	else
-	  {
-	    jobject value = POPA();
-	    jobject obj   = POPA();
-	    NULLCHECK(obj);
-	    *(jobject*) ((char*)obj + field_offset) = value;
-	    newinsn = AMPAMP (putfield_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].int_val = field_offset;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    putfield_resolved_1:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jbyte *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_2:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jchar *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_4:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jint *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_8:
-      {
-	jlong val = POPL ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jlong *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_obj:
-      {
-	jobject val = POPA ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jobject *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_invokespecial:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	// We don't use NULLCHECK here because we can't rely on that
-	// working for <init>.  So instead we do an explicit test.
-	if (! sp[0].o)
-	  {
-	    SAVE_PC();
-	    throw_null_pointer_exception ();
-	  }
-
-	fun = (void (*)()) rmeth->method->ncode;
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokespecial_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokespecial_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	// We don't use NULLCHECK here because we can't rely on that
-	// working for <init>.  So instead we do an explicit test.
-	if (! sp[0].o)
-	  {
-	    throw_null_pointer_exception ();
-	  }
-	fun = (void (*)()) rmeth->method->ncode;
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_invokestatic:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	fun = (void (*)()) rmeth->method->ncode;
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokestatic_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokestatic_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	fun = (void (*)()) rmeth->method->ncode;
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_invokeinterface:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	jobject rcv = sp[0].o;
-
-	NULLCHECK (rcv);
-
-	fun = (void (*)())
-	  _Jv_LookupInterfaceMethod (rcv->getClass (),
-				     rmeth->method->name,
-				     rmeth->method->signature);
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokeinterface_resolved;
-	pc[-1].datum = rmeth;
-#else
-	// Skip dummy bytes.
-	pc += 2;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokeinterface_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	jobject rcv = sp[0].o;
-	NULLCHECK (rcv);
-	fun = (void (*)())
-	  _Jv_LookupInterfaceMethod (rcv->getClass (),
-				     rmeth->method->name,
-				     rmeth->method->signature);
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_new:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-							  index)).clazz;
-	/* VM spec, section 3.11.5 */
-	if ((klass->getModifiers() & Modifier::ABSTRACT)
-	    || klass->isInterface())
-	  throw new java::lang::InstantiationException;
-	jobject res = _Jv_AllocObject (klass);
-	PUSHA (res);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&new_resolved;
-	pc[-1].datum = klass;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    new_resolved:
-      {
-	jclass klass = (jclass) AVAL ();
-	jobject res = _Jv_AllocObject (klass);
-	PUSHA (res);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_newarray:
-      {
-	int atype = GET1U ();
-	int size  = POPI();
-	jobject result = _Jv_NewArray (atype, size);
-	PUSHA (result);
-      }
-      NEXT_INSN;
-
-    insn_anewarray:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-							  index)).clazz;
-	int size  = POPI();
-	jobject result = _Jv_NewObjectArray (size, klass, 0);
-	PUSHA (result);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&anewarray_resolved;
-	pc[-1].datum = klass;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    anewarray_resolved:
-      {
-	jclass klass = (jclass) AVAL ();
-	int size = POPI ();
-	jobject result = _Jv_NewObjectArray (size, klass, 0);
-	PUSHA (result);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_arraylength:
-      {
-	__JArray *arr = (__JArray*)POPA();
-	NULLARRAYCHECK (arr);
-	PUSHI (arr->length);
-      }
-      NEXT_INSN;
-
-    insn_athrow:
-      {
-	jobject value = POPA();
-	throw static_cast<jthrowable>(value);
-      }
-      NEXT_INSN;
-
-    insn_checkcast:
-      {
-        SAVE_PC();
-	jobject value = POPA();
-	jint index = GET2U ();
-	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						       index)).clazz;
-
-	value = (jobject) _Jv_CheckCast (to, value);
-
-	PUSHA (value);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&checkcast_resolved;
-	pc[-1].datum = to;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    checkcast_resolved:
-      {
-        SAVE_PC();
-	jobject value = POPA ();
-	jclass to = (jclass) AVAL ();
-	value = (jobject) _Jv_CheckCast (to, value);
-	PUSHA (value);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_instanceof:
-      {
-        SAVE_PC();
-	jobject value = POPA();
-	jint index = GET2U ();
-	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						       index)).clazz;
-	PUSHI (to->isInstance (value));
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&instanceof_resolved;
-	pc[-1].datum = to;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    instanceof_resolved:
-      {
-	jobject value = POPA ();
-	jclass to = (jclass) AVAL ();
-	PUSHI (to->isInstance (value));
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_monitorenter:
-      {
-	jobject value = POPA();
-	NULLCHECK(value);
-	_Jv_MonitorEnter (value);
-      }
-      NEXT_INSN;
-
-    insn_monitorexit:
-      {
-	jobject value = POPA();
-	NULLCHECK(value);
-	_Jv_MonitorExit (value);
-      }
-      NEXT_INSN;
-
-    insn_ifnull:
-      {
-	jobject val = POPA();
-	if (val == NULL)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifnonnull:
-      {
-	jobject val = POPA();
-	if (val != NULL)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_multianewarray:
-      {
-	SAVE_PC();
-	int kind_index = GET2U ();
-	int dim        = GET1U ();
-
-	jclass type    
-	  = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-					       kind_index)).clazz;
-	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
-
-	for (int i = dim - 1; i >= 0; i--)
-	  {
-	    sizes[i] = POPI ();
-	  }
-
-	jobject res    = _Jv_NewMultiArray (type,dim, sizes);
-
-	PUSHA (res);
-      }
-      NEXT_INSN;
-
-#ifndef DIRECT_THREADED
-    insn_wide:
-      {
-	jint the_mod_op = get1u (pc++);
-	jint wide       = get2u (pc); pc += 2;
-
-	switch (the_mod_op)
-	  {
-	  case op_istore:
-	    STOREI (wide);
-	    NEXT_INSN;
-
-	  case op_fstore:
-	    STOREF (wide);
-	    NEXT_INSN;
-
-	  case op_astore:
-	    STOREA (wide);
-	    NEXT_INSN;
-
-	  case op_lload:
-	    LOADL (wide);
-	    NEXT_INSN;
-
-	  case op_dload:
-	    LOADD (wide);
-	    NEXT_INSN;
-
-	  case op_iload:
-	    LOADI (wide);
-	    NEXT_INSN;
-
-	  case op_fload:
-	    LOADF (wide);
-	    NEXT_INSN;
-
-	  case op_aload:
-	    LOADA (wide);
-	    NEXT_INSN;
-
-	  case op_lstore:
-	    STOREL (wide);
-	    NEXT_INSN;
-
-	  case op_dstore:
-	    STORED (wide);
-	    NEXT_INSN;
-
-	  case op_ret:
-	    pc = (unsigned char*) PEEKA (wide);
-	    NEXT_INSN;
-
-	  case op_iinc:
-	    {
-	      jint amount = get2s (pc); pc += 2;
-	      jint value = PEEKI (wide);
-	      POKEI (wide, value+amount);
-	    }
-	    NEXT_INSN;
-
-	  default:
-	    throw_internal_error ("illegal bytecode modified by wide");
-	  }
-
-      }
-#endif /* DIRECT_THREADED */
-    }
-  catch (java::lang::Throwable *ex)
-    {
-#ifdef DIRECT_THREADED
-      void *logical_pc = (void *) ((insn_slot *) pc - 1);
-#else
-      int logical_pc = pc - 1 - bytecode ();
-#endif
-      _Jv_InterpException *exc = meth->exceptions ();
-      jclass exc_class = ex->getClass ();
-
-      for (int i = 0; i < meth->exc_count; i++)
-	{
-	  if (PCVAL (exc[i].start_pc) <= logical_pc
-	      && logical_pc < PCVAL (exc[i].end_pc))
-	    {
-#ifdef DIRECT_THREADED
-	      jclass handler = (jclass) exc[i].handler_type.p;
-#else
-	      jclass handler = NULL;
-	      if (exc[i].handler_type.i != 0)
-		handler = (_Jv_Linker::resolve_pool_entry (defining_class,
-							     exc[i].handler_type.i)).clazz;
-#endif /* DIRECT_THREADED */
-
-	      if (handler == NULL || handler->isAssignableFrom (exc_class))
-		{
-#ifdef DIRECT_THREADED
-		  pc = (insn_slot *) exc[i].handler_pc.p;
-#else
-		  pc = bytecode () + exc[i].handler_pc.i;
-#endif /* DIRECT_THREADED */
-		  sp = stack;
-		  sp++->o = ex; // Push exception.
-		  NEXT_INSN;
-		}
-	    }
-	}
-
-      // No handler, so re-throw.
-      throw ex;
-    }
-}
-
-static void
-throw_internal_error (const char *msg)
-{
-  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
-}
-
-static void 
-throw_incompatible_class_change_error (jstring msg)
-{
-  throw new java::lang::IncompatibleClassChangeError (msg);
-}
-
-static void 
-throw_null_pointer_exception ()
-{
-  throw new java::lang::NullPointerException;
-}
-
-/* Look up source code line number for given bytecode (or direct threaded
-   interpreter) PC. */
-int
-_Jv_InterpMethod::get_source_line(pc_t mpc)
-{
-  int line = line_table_len > 0 ? line_table[0].line : -1;
-  for (int i = 1; i < line_table_len; i++)
-    if (line_table[i].pc > mpc)
-      break;
-    else
-      line = line_table[i].line;
-
-  return line;
-}
-
-/** Do static initialization for fields with a constant initializer */
-void
-_Jv_InitField (jobject obj, jclass klass, int index)
-{
-  using namespace java::lang::reflect;
-
-  if (obj != 0 && klass == 0)
-    klass = obj->getClass ();
-
-  if (!_Jv_IsInterpretedClass (klass))
-    return;
-
-  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
-
-  _Jv_Field * field = (&klass->fields[0]) + index;
-
-  if (index > klass->field_count)
-    throw_internal_error ("field out of range");
-
-  int init = iclass->field_initializers[index];
-  if (init == 0)
-    return;
-
-  _Jv_Constants *pool = &klass->constants;
-  int tag = pool->tags[init];
-
-  if (! field->isResolved ())
-    throw_internal_error ("initializing unresolved field");
-
-  if (obj==0 && ((field->flags & Modifier::STATIC) == 0))
-    throw_internal_error ("initializing non-static field with no object");
-
-  void *addr = 0;
-
-  if ((field->flags & Modifier::STATIC) != 0)
-    addr = (void*) field->u.addr;
-  else
-    addr = (void*) (((char*)obj) + field->u.boffset);
-
-  switch (tag)
-    {
-    case JV_CONSTANT_String:
-      {
-	jstring str;
-	str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
-	pool->data[init].string = str;
-	pool->tags[init] = JV_CONSTANT_ResolvedString;
-      }
-      /* fall through */
-
-    case JV_CONSTANT_ResolvedString:
-      if (! (field->type == &java::lang::String::class$
- 	     || field->type == &java::lang::Class::class$))
-	throw_class_format_error ("string initialiser to non-string field");
-
-      *(jstring*)addr = pool->data[init].string;
-      break;
-
-    case JV_CONSTANT_Integer:
-      {
-	int value = pool->data[init].i;
-
-	if (field->type == JvPrimClass (boolean))
-	  *(jboolean*)addr = (jboolean)value;
-	
-	else if (field->type == JvPrimClass (byte))
-	  *(jbyte*)addr = (jbyte)value;
-	
-	else if (field->type == JvPrimClass (char))
-	  *(jchar*)addr = (jchar)value;
-
-	else if (field->type == JvPrimClass (short))
-	  *(jshort*)addr = (jshort)value;
-	
-	else if (field->type == JvPrimClass (int))
-	  *(jint*)addr = (jint)value;
-
-	else
-	  throw_class_format_error ("erroneous field initializer");
-      }  
-      break;
-
-    case JV_CONSTANT_Long:
-      if (field->type != JvPrimClass (long))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
-      break;
-
-    case JV_CONSTANT_Float:
-      if (field->type != JvPrimClass (float))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jfloat*)addr = pool->data[init].f;
-      break;
-
-    case JV_CONSTANT_Double:
-      if (field->type != JvPrimClass (double))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
-      break;
-
-    default:
-      throw_class_format_error ("erroneous field initializer");
-    }
-}
-
-inline static unsigned char*
-skip_one_type (unsigned char* ptr)
-{
-  int ch = *ptr++;
-
-  while (ch == '[')
-    { 
-      ch = *ptr++;
-    }
-  
-  if (ch == 'L')
-    {
-      do { ch = *ptr++; } while (ch != ';');
-    }
-
-  return ptr;
-}
-
-static ffi_type*
-get_ffi_type_from_signature (unsigned char* ptr)
-{
-  switch (*ptr) 
-    {
-    case 'L':
-    case '[':
-      return &ffi_type_pointer;
-      break;
-
-    case 'Z':
-      // On some platforms a bool is a byte, on others an int.
-      if (sizeof (jboolean) == sizeof (jbyte))
-	return &ffi_type_sint8;
-      else
-	{
-	  JvAssert (sizeof (jbyte) == sizeof (jint));
-	  return &ffi_type_sint32;
-	}
-      break;
-
-    case 'B':
-      return &ffi_type_sint8;
-      break;
-      
-    case 'C':
-      return &ffi_type_uint16;
-      break;
-	  
-    case 'S': 
-      return &ffi_type_sint16;
-      break;
-	  
-    case 'I':
-      return &ffi_type_sint32;
-      break;
-	  
-    case 'J':
-      return &ffi_type_sint64;
-      break;
-	  
-    case 'F':
-      return &ffi_type_float;
-      break;
-	  
-    case 'D':
-      return &ffi_type_double;
-      break;
+    case 'B':
+      return &ffi_type_sint8;
+      break;
+      
+    case 'C':
+      return &ffi_type_uint16;
+      break;
+	  
+    case 'S': 
+      return &ffi_type_sint16;
+      break;
+	  
+    case 'I':
+      return &ffi_type_sint32;
+      break;
+	  
+    case 'J':
+      return &ffi_type_sint64;
+      break;
+	  
+    case 'F':
+      return &ffi_type_float;
+      break;
+	  
+    case 'D':
+      return &ffi_type_double;
+      break;
 
     case 'V':
       return &ffi_type_void;
@@ -3654,9 +1256,19 @@
   if ((self->accflags & Modifier::SYNCHRONIZED) != 0)
     {
       if (staticp)
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
+        {
+        if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		  fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class_debug;
+		else
+		  fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
+        }
       else
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object; 
+        {
+	      if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object_debug;
+		  else
+		  	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object;
+        } 
     }
   else
     {
@@ -3661,9 +1273,19 @@
   else
     {
       if (staticp)
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
+        {
+	      if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class_debug;
+		  else
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
+        }
       else
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+        {
+	      if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal_debug;
+		  else
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+        }
     }
 
   FFI_PREP_RAW_CLOSURE (&closure->closure,
Index: stacktrace.cc
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/stacktrace.cc	(revision 115852)
+++ /notnfs/kgallowa/vanilla/libjava/stacktrace.cc	(working copy)
@@ -111,7 +111,13 @@
   // correspondance between call frames in the interpreted stack and occurances
   // of _Jv_InterpMethod::run() on the native stack.
 #ifdef INTERPRETER
-  void *interp_run = (void *) &_Jv_InterpMethod::run;
+  void *interp_run = NULL;
+  
+  if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+  	interp_run = (void *) &_Jv_InterpMethod::run_debug;
+  else
+    interp_run = (void *) &_Jv_InterpMethod::run;
+  	
   if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
     {
       state->frames[pos].type = frame_interpreter;


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-01 22:56             ` Tom Tromey
  2006-08-02 14:27               ` Kyle Galloway
@ 2006-08-02 15:05               ` Kyle Galloway
  2006-08-02 22:56                 ` Tom Tromey
  1 sibling, 1 reply; 16+ messages in thread
From: Kyle Galloway @ 2006-08-02 15:05 UTC (permalink / raw)
  To: java-patches

[-- Attachment #1: Type: text/plain, Size: 976 bytes --]

I noticed a small error in my last patch.  I accidentally whacked out an
include in stacktrace.cc which will cause some problems.  The new patch
is included in this file.

Changelog (same as before):

2006-07-28  Kyle Galloway  <kgallowa@redhat.com>

  * include/java-interp.h (_Jv_InterpMethod::run_debug): New method.
  * interpret.cc: Added placeholder for debug variable type info to STORE*
  macros.
  (_Jv_InterpMethod::run_debug): New method.
  (_Jv_InterpMethod::run_sync_object_debug): New method.
  (_Jv_InterpMethod::run_sync_class_debug): New method.
  (_Jv_InterpMethod::run_normal_debug): New method.
  (_Jv_InterpMethod::run_class_debug): New method.
  (_Jv_InterpMethod::ncode ()): Changed to select either debug or normal
  versions of these functions.
  * interpret-run.cc: New file, holds contents of old 	
_Jv_InterpMethod::run
  method.
  * stacktrace.cc (_Jv_StackTrace::UnwindTraceFn): Changed to select
  appropriate function for debug or normal mode.

[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 120457 bytes --]

Index: include/java-interp.h
===================================================================
--- /home/kgallowa/work/gcc/libjava/include/java-interp.h	(revision 115873)
+++ /home/kgallowa/work/gcc/libjava/include/java-interp.h	(working copy)
@@ -176,9 +176,17 @@
   static void run_synch_object (ffi_cif*, void*, ffi_raw*, void*);
   static void run_class (ffi_cif*, void*, ffi_raw*, void*);
   static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*);
+  
+  static void run_normal_debug (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_synch_object_debug (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_class_debug (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_synch_class_debug (ffi_cif*, void*, ffi_raw*, void*);
 
-  static void run (void*, ffi_raw *, _Jv_InterpMethod *);
+  static void run (void *, ffi_raw *, _Jv_InterpMethod *);
+  static void run_debug (void *, ffi_raw *, _Jv_InterpMethod *);
+  
 
+  
   // Returns source file line number for given PC value, or -1 if line
   // number info is unavailable.
   int get_source_line(pc_t mpc);
@@ -183,6 +191,8 @@
   // number info is unavailable.
   int get_source_line(pc_t mpc);
 
+
+
 #ifdef DIRECT_THREADED
   // Convenience function for indexing bytecode PC/insn slots in
   // line tables for JDWP
@@ -188,9 +198,9 @@
   // line tables for JDWP
   jlong insn_index (pc_t pc);
 #endif
-
- public:
-
+  
+   public:
+   
   /* Get the line table for this method.
    * start  is the lowest index in the method
    * end    is the  highest index in the method
Index: interpret-run.cc
===================================================================
--- /home/kgallowa/work/gcc/libjava/interpret-run.cc	(revision 0)
+++ /home/kgallowa/work/gcc/libjava/interpret-run.cc	(revision 0)
@@ -0,0 +1,2508 @@
+// interpret-run.cc - Code to interpret bytecode
+
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+/* This file is meant only to be included in interpret.cc, it should not be
+ * compiled directly.	*/
+
+  using namespace java::lang::reflect;
+
+  // FRAME_DESC registers this particular invocation as the top-most
+  // interpreter frame.  This lets the stack tracing code (for
+  // Throwable) print information about the method being interpreted
+  // rather than about the interpreter itself.  FRAME_DESC has a
+  // destructor so it cleans up automatically when the interpreter
+  // returns.
+  java::lang::Thread *thread = java::lang::Thread::currentThread();
+  _Jv_InterpFrame frame_desc (meth, thread);
+
+  _Jv_word stack[meth->max_stack];
+  _Jv_word *sp = stack;
+
+  _Jv_word locals[meth->max_locals];
+
+#define INSN_LABEL(op) &&insn_##op
+
+  static const void *const insn_target[] = 
+  {
+    INSN_LABEL(nop),
+    INSN_LABEL(aconst_null),
+    INSN_LABEL(iconst_m1),
+    INSN_LABEL(iconst_0),
+    INSN_LABEL(iconst_1),
+    INSN_LABEL(iconst_2),
+    INSN_LABEL(iconst_3),
+    INSN_LABEL(iconst_4),
+    INSN_LABEL(iconst_5),
+    INSN_LABEL(lconst_0),
+    INSN_LABEL(lconst_1),
+    INSN_LABEL(fconst_0),
+    INSN_LABEL(fconst_1),
+    INSN_LABEL(fconst_2),
+    INSN_LABEL(dconst_0),
+    INSN_LABEL(dconst_1),
+    INSN_LABEL(bipush),
+    INSN_LABEL(sipush),
+    INSN_LABEL(ldc),
+    INSN_LABEL(ldc_w),
+    INSN_LABEL(ldc2_w),
+    INSN_LABEL(iload),
+    INSN_LABEL(lload),
+    INSN_LABEL(fload),
+    INSN_LABEL(dload),
+    INSN_LABEL(aload),
+    INSN_LABEL(iload_0),
+    INSN_LABEL(iload_1),
+    INSN_LABEL(iload_2),
+    INSN_LABEL(iload_3),
+    INSN_LABEL(lload_0),
+    INSN_LABEL(lload_1),
+    INSN_LABEL(lload_2),
+    INSN_LABEL(lload_3),
+    INSN_LABEL(fload_0),
+    INSN_LABEL(fload_1),
+    INSN_LABEL(fload_2),
+    INSN_LABEL(fload_3),
+    INSN_LABEL(dload_0),
+    INSN_LABEL(dload_1),
+    INSN_LABEL(dload_2),
+    INSN_LABEL(dload_3),
+    INSN_LABEL(aload_0),
+    INSN_LABEL(aload_1),
+    INSN_LABEL(aload_2),
+    INSN_LABEL(aload_3),
+    INSN_LABEL(iaload),
+    INSN_LABEL(laload),
+    INSN_LABEL(faload),
+    INSN_LABEL(daload),
+    INSN_LABEL(aaload),
+    INSN_LABEL(baload),
+    INSN_LABEL(caload),
+    INSN_LABEL(saload),
+    INSN_LABEL(istore),
+    INSN_LABEL(lstore),
+    INSN_LABEL(fstore),
+    INSN_LABEL(dstore),
+    INSN_LABEL(astore),
+    INSN_LABEL(istore_0),
+    INSN_LABEL(istore_1),
+    INSN_LABEL(istore_2),
+    INSN_LABEL(istore_3),
+    INSN_LABEL(lstore_0),
+    INSN_LABEL(lstore_1),
+    INSN_LABEL(lstore_2),
+    INSN_LABEL(lstore_3),
+    INSN_LABEL(fstore_0),
+    INSN_LABEL(fstore_1),
+    INSN_LABEL(fstore_2),
+    INSN_LABEL(fstore_3),
+    INSN_LABEL(dstore_0),
+    INSN_LABEL(dstore_1),
+    INSN_LABEL(dstore_2),
+    INSN_LABEL(dstore_3),
+    INSN_LABEL(astore_0),
+    INSN_LABEL(astore_1),
+    INSN_LABEL(astore_2),
+    INSN_LABEL(astore_3),
+    INSN_LABEL(iastore),
+    INSN_LABEL(lastore),
+    INSN_LABEL(fastore),
+    INSN_LABEL(dastore),
+    INSN_LABEL(aastore),
+    INSN_LABEL(bastore),
+    INSN_LABEL(castore),
+    INSN_LABEL(sastore),
+    INSN_LABEL(pop),
+    INSN_LABEL(pop2),
+    INSN_LABEL(dup),
+    INSN_LABEL(dup_x1),
+    INSN_LABEL(dup_x2),
+    INSN_LABEL(dup2),
+    INSN_LABEL(dup2_x1),
+    INSN_LABEL(dup2_x2),
+    INSN_LABEL(swap),
+    INSN_LABEL(iadd),
+    INSN_LABEL(ladd),
+    INSN_LABEL(fadd),
+    INSN_LABEL(dadd),
+    INSN_LABEL(isub),
+    INSN_LABEL(lsub),
+    INSN_LABEL(fsub),
+    INSN_LABEL(dsub),
+    INSN_LABEL(imul),
+    INSN_LABEL(lmul),
+    INSN_LABEL(fmul),
+    INSN_LABEL(dmul),
+    INSN_LABEL(idiv),
+    INSN_LABEL(ldiv),
+    INSN_LABEL(fdiv),
+    INSN_LABEL(ddiv),
+    INSN_LABEL(irem),
+    INSN_LABEL(lrem),
+    INSN_LABEL(frem),
+    INSN_LABEL(drem),
+    INSN_LABEL(ineg),
+    INSN_LABEL(lneg),
+    INSN_LABEL(fneg),
+    INSN_LABEL(dneg),
+    INSN_LABEL(ishl),
+    INSN_LABEL(lshl),
+    INSN_LABEL(ishr),
+    INSN_LABEL(lshr),
+    INSN_LABEL(iushr),
+    INSN_LABEL(lushr),
+    INSN_LABEL(iand),
+    INSN_LABEL(land),
+    INSN_LABEL(ior),
+    INSN_LABEL(lor),
+    INSN_LABEL(ixor),
+    INSN_LABEL(lxor),
+    INSN_LABEL(iinc),
+    INSN_LABEL(i2l),
+    INSN_LABEL(i2f),
+    INSN_LABEL(i2d),
+    INSN_LABEL(l2i),
+    INSN_LABEL(l2f),
+    INSN_LABEL(l2d),
+    INSN_LABEL(f2i),
+    INSN_LABEL(f2l),
+    INSN_LABEL(f2d),
+    INSN_LABEL(d2i),
+    INSN_LABEL(d2l),
+    INSN_LABEL(d2f),
+    INSN_LABEL(i2b),
+    INSN_LABEL(i2c),
+    INSN_LABEL(i2s),
+    INSN_LABEL(lcmp),
+    INSN_LABEL(fcmpl),
+    INSN_LABEL(fcmpg),
+    INSN_LABEL(dcmpl),
+    INSN_LABEL(dcmpg),
+    INSN_LABEL(ifeq),
+    INSN_LABEL(ifne),
+    INSN_LABEL(iflt),
+    INSN_LABEL(ifge),
+    INSN_LABEL(ifgt),
+    INSN_LABEL(ifle),
+    INSN_LABEL(if_icmpeq),
+    INSN_LABEL(if_icmpne),
+    INSN_LABEL(if_icmplt),
+    INSN_LABEL(if_icmpge),
+    INSN_LABEL(if_icmpgt),
+    INSN_LABEL(if_icmple),
+    INSN_LABEL(if_acmpeq),
+    INSN_LABEL(if_acmpne),
+    INSN_LABEL(goto), 
+    INSN_LABEL(jsr),
+    INSN_LABEL(ret),
+    INSN_LABEL(tableswitch),
+    INSN_LABEL(lookupswitch),
+    INSN_LABEL(ireturn),
+    INSN_LABEL(lreturn),
+    INSN_LABEL(freturn),
+    INSN_LABEL(dreturn),
+    INSN_LABEL(areturn),
+    INSN_LABEL(return),
+    INSN_LABEL(getstatic),
+    INSN_LABEL(putstatic),
+    INSN_LABEL(getfield),
+    INSN_LABEL(putfield),
+    INSN_LABEL(invokevirtual),
+    INSN_LABEL(invokespecial),
+    INSN_LABEL(invokestatic),
+    INSN_LABEL(invokeinterface),
+    0, /* Unused.  */
+    INSN_LABEL(new),
+    INSN_LABEL(newarray),
+    INSN_LABEL(anewarray),
+    INSN_LABEL(arraylength),
+    INSN_LABEL(athrow),
+    INSN_LABEL(checkcast),
+    INSN_LABEL(instanceof),
+    INSN_LABEL(monitorenter),
+    INSN_LABEL(monitorexit),
+#ifdef DIRECT_THREADED
+    0, // wide
+#else
+    INSN_LABEL(wide),
+#endif
+    INSN_LABEL(multianewarray),
+    INSN_LABEL(ifnull),
+    INSN_LABEL(ifnonnull),
+    INSN_LABEL(goto_w),
+    INSN_LABEL(jsr_w),
+#ifdef DIRECT_THREADED
+    INSN_LABEL (ldc_class)
+#else
+    0
+#endif
+  };
+
+  pc_t pc;
+
+#ifdef DIRECT_THREADED
+
+#define NEXT_INSN goto *((pc++)->insn)
+#define INTVAL() ((pc++)->int_val)
+#define AVAL() ((pc++)->datum)
+
+#define GET1S() INTVAL ()
+#define GET2S() INTVAL ()
+#define GET1U() INTVAL ()
+#define GET2U() INTVAL ()
+#define AVAL1U() AVAL ()
+#define AVAL2U() AVAL ()
+#define AVAL2UP() AVAL ()
+#define SKIP_GOTO ++pc
+#define GOTO_VAL() (insn_slot *) pc->datum
+#define PCVAL(unionval) unionval.p
+#define AMPAMP(label) &&label
+
+  // Compile if we must. NOTE: Double-check locking.
+  if (meth->prepared == NULL)
+    {
+      _Jv_MutexLock (&compile_mutex);
+      if (meth->prepared == NULL)
+	meth->compile (insn_target);
+      _Jv_MutexUnlock (&compile_mutex);
+    }
+
+  // If we're only compiling, stop here
+  if (args == NULL)
+    return;
+
+  pc = (insn_slot *) meth->prepared;
+
+#else
+
+#define NEXT_INSN goto *(insn_target[*pc++])
+
+#define GET1S() get1s (pc++)
+#define GET2S() (pc += 2, get2s (pc- 2))
+#define GET1U() get1u (pc++)
+#define GET2U() (pc += 2, get2u (pc - 2))
+  // Note that these could be more efficient when not handling 'ldc
+  // class'.
+#define AVAL1U()						\
+  ({ int index = get1u (pc++);					\
+      resolve_pool_entry (meth->defining_class, index).o; })
+#define AVAL2U()						\
+  ({ int index = get2u (pc); pc += 2;				\
+      resolve_pool_entry (meth->defining_class, index).o; })
+  // Note that we don't need to resolve the pool entry here as class
+  // constants are never wide.
+#define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
+#define SKIP_GOTO pc += 2
+#define GOTO_VAL() pc - 1 + get2s (pc)
+#define PCVAL(unionval) unionval.i
+#define AMPAMP(label) NULL
+
+  pc = bytecode ();
+
+#endif /* DIRECT_THREADED */
+
+#define TAKE_GOTO pc = GOTO_VAL ()
+
+  /* Go straight at it!  the ffi raw format matches the internal
+     stack representation exactly.  At least, that's the idea.
+  */
+  memcpy ((void*) locals, (void*) args, meth->args_raw_size);
+
+  _Jv_word *pool_data = meth->defining_class->constants.data;
+
+  /* These three are temporaries for common code used by several
+     instructions.  */
+  void (*fun)();
+  _Jv_ResolvedMethod* rmeth;
+  int tmpval;
+
+  try
+    {
+      // We keep nop around.  It is used if we're interpreting the
+      // bytecodes and not doing direct threading.
+    insn_nop:
+      NEXT_INSN;
+
+      /* The first few instructions here are ordered according to their
+	 frequency, in the hope that this will improve code locality a
+	 little.  */
+
+    insn_aload_0:		// 0x2a
+      LOADA (0);
+      NEXT_INSN;
+
+    insn_iload:		// 0x15
+      LOADI (GET1U ());
+      NEXT_INSN;
+
+    insn_iload_1:		// 0x1b
+      LOADI (1);
+      NEXT_INSN;
+
+    insn_invokevirtual:	// 0xb6
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	/* _Jv_Linker::resolve_pool_entry returns immediately if the
+	 * value already is resolved.  If we want to clutter up the
+	 * code here to gain a little performance, then we can check
+	 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
+	 * directly.  For now, I don't think it is worth it.  */
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	if (rmeth->method->accflags & Modifier::FINAL)
+	  {
+	    // We can't rely on NULLCHECK working if the method is final.
+	    if (! sp[0].o)
+	      throw_null_pointer_exception ();
+
+	    // Final methods might not appear in the vtable.
+	    fun = (void (*)()) rmeth->method->ncode;
+	  }
+	else
+	  {
+	    NULLCHECK (sp[0].o);
+	    jobject rcv = sp[0].o;
+	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
+	    fun = (void (*)()) table->get_method (rmeth->method->index);
+	  }
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokevirtual_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokevirtual_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+
+	if (rmeth->method->accflags & Modifier::FINAL)
+	  {
+	    // We can't rely on NULLCHECK working if the method is final.
+	    if (! sp[0].o)
+	      throw_null_pointer_exception ();
+
+	    // Final methods might not appear in the vtable.
+	    fun = (void (*)()) rmeth->method->ncode;
+	  }
+	else
+	  {
+	    jobject rcv = sp[0].o;
+	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
+	    fun = (void (*)()) table->get_method (rmeth->method->index);
+	  }
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    perform_invoke:
+      {
+	/* here goes the magic again... */
+	ffi_cif *cif = &rmeth->cif;
+	ffi_raw *raw = (ffi_raw*) sp;
+
+	_Jv_value rvalue;
+
+#if FFI_NATIVE_RAW_API
+	/* We assume that this is only implemented if it's correct	*/
+	/* to use it here.  On a 64 bit machine, it never is.		*/
+	ffi_raw_call (cif, fun, (void*)&rvalue, raw);
+#else
+	ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
+#endif
+
+	int rtype = cif->rtype->type;
+
+	/* the likelyhood of object, int, or void return is very high,
+	 * so those are checked before the switch */
+	if (rtype == FFI_TYPE_POINTER)
+	  {
+	    PUSHA (rvalue.object_value);
+	  }
+	else if (rtype == FFI_TYPE_SINT32)
+	  {
+	    PUSHI (rvalue.int_value);
+	  }
+	else if (rtype == FFI_TYPE_VOID)
+	  {
+	    /* skip */
+	  }
+	else
+	  {
+	    switch (rtype)
+	      {
+	      case FFI_TYPE_SINT8:
+		PUSHI ((jbyte)(rvalue.int_value & 0xff));
+		break;
+
+	      case FFI_TYPE_SINT16:
+		PUSHI ((jshort)(rvalue.int_value & 0xffff));
+		break;
+
+	      case FFI_TYPE_UINT16:
+		PUSHI (rvalue.int_value & 0xffff);
+		break;
+
+	      case FFI_TYPE_FLOAT:
+	        PUSHF (rvalue.float_value);
+		break;
+
+	      case FFI_TYPE_DOUBLE:
+	        PUSHD (rvalue.double_value);
+		break;
+
+	      case FFI_TYPE_SINT64:
+	        PUSHL (rvalue.long_value);
+		break;
+
+	      default:
+		throw_internal_error ("unknown return type in invokeXXX");
+	      }
+	  }
+      }
+      NEXT_INSN;
+
+    insn_aconst_null:
+      PUSHA (NULL);
+      NEXT_INSN;
+
+    insn_iconst_m1:
+      PUSHI (-1);
+      NEXT_INSN;
+
+    insn_iconst_0:
+      PUSHI (0);
+      NEXT_INSN;
+
+    insn_iconst_1:
+      PUSHI (1);
+      NEXT_INSN;
+
+    insn_iconst_2:
+      PUSHI (2);
+      NEXT_INSN;
+
+    insn_iconst_3:
+      PUSHI (3);
+      NEXT_INSN;
+
+    insn_iconst_4:
+      PUSHI (4);
+      NEXT_INSN;
+
+    insn_iconst_5:
+      PUSHI (5);
+      NEXT_INSN;
+
+    insn_lconst_0:
+      PUSHL (0);
+      NEXT_INSN;
+
+    insn_lconst_1:
+      PUSHL (1);
+      NEXT_INSN;
+
+    insn_fconst_0:
+      PUSHF (0);
+      NEXT_INSN;
+
+    insn_fconst_1:
+      PUSHF (1);
+      NEXT_INSN;
+
+    insn_fconst_2:
+      PUSHF (2);
+      NEXT_INSN;
+
+    insn_dconst_0:
+      PUSHD (0);
+      NEXT_INSN;
+
+    insn_dconst_1:
+      PUSHD (1);
+      NEXT_INSN;
+
+    insn_bipush:
+      // For direct threaded, bipush and sipush are the same.
+#ifndef DIRECT_THREADED
+      PUSHI (GET1S ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_sipush:
+      PUSHI (GET2S ());
+      NEXT_INSN;
+
+    insn_ldc:
+      // For direct threaded, ldc and ldc_w are the same.
+#ifndef DIRECT_THREADED
+      PUSHA ((jobject) AVAL1U ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_ldc_w:
+      PUSHA ((jobject) AVAL2U ());
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+      // For direct threaded we have a separate 'ldc class' operation.
+    insn_ldc_class:
+      {
+	SAVE_PC();
+	// We could rewrite the instruction at this point.
+	int index = INTVAL ();
+	jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						     index)).o;
+	PUSHA (k);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_ldc2_w:
+      {
+	void *where = AVAL2UP ();
+	memcpy (sp, where, 2*sizeof (_Jv_word));
+	sp += 2;
+      }
+      NEXT_INSN;
+
+    insn_lload:
+      LOADL (GET1U ());
+      NEXT_INSN;
+
+    insn_fload:
+      LOADF (GET1U ());
+      NEXT_INSN;
+
+    insn_dload:
+      LOADD (GET1U ());
+      NEXT_INSN;
+
+    insn_aload:
+      LOADA (GET1U ());
+      NEXT_INSN;
+
+    insn_iload_0:
+      LOADI (0);
+      NEXT_INSN;
+
+    insn_iload_2:
+      LOADI (2);
+      NEXT_INSN;
+
+    insn_iload_3:
+      LOADI (3);
+      NEXT_INSN;
+
+    insn_lload_0:
+      LOADL (0);
+      NEXT_INSN;
+
+    insn_lload_1:
+      LOADL (1);
+      NEXT_INSN;
+
+    insn_lload_2:
+      LOADL (2);
+      NEXT_INSN;
+
+    insn_lload_3:
+      LOADL (3);
+      NEXT_INSN;
+
+    insn_fload_0:
+      LOADF (0);
+      NEXT_INSN;
+
+    insn_fload_1:
+      LOADF (1);
+      NEXT_INSN;
+
+    insn_fload_2:
+      LOADF (2);
+      NEXT_INSN;
+
+    insn_fload_3:
+      LOADF (3);
+      NEXT_INSN;
+
+    insn_dload_0:
+      LOADD (0);
+      NEXT_INSN;
+
+    insn_dload_1:
+      LOADD (1);
+      NEXT_INSN;
+
+    insn_dload_2:
+      LOADD (2);
+      NEXT_INSN;
+
+    insn_dload_3:
+      LOADD (3);
+      NEXT_INSN;
+
+    insn_aload_1:
+      LOADA(1);
+      NEXT_INSN;
+
+    insn_aload_2:
+      LOADA(2);
+      NEXT_INSN;
+
+    insn_aload_3:
+      LOADA(3);
+      NEXT_INSN;
+
+    insn_iaload:
+      {
+	jint index = POPI();
+	jintArray arr = (jintArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_laload:
+      {
+	jint index = POPI();
+	jlongArray arr = (jlongArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHL( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_faload:
+      {
+	jint index = POPI();
+	jfloatArray arr = (jfloatArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHF( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_daload:
+      {
+	jint index = POPI();
+	jdoubleArray arr = (jdoubleArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHD( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_aaload:
+      {
+	jint index = POPI();
+	jobjectArray arr = (jobjectArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHA( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_baload:
+      {
+	jint index = POPI();
+	jbyteArray arr = (jbyteArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_caload:
+      {
+	jint index = POPI();
+	jcharArray arr = (jcharArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_saload:
+      {
+	jint index = POPI();
+	jshortArray arr = (jshortArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_istore:
+      STOREI (GET1U ());
+      NEXT_INSN;
+
+    insn_lstore:
+      STOREL (GET1U ());
+      NEXT_INSN;
+
+    insn_fstore:
+      STOREF (GET1U ());
+      NEXT_INSN;
+
+    insn_dstore:
+      STORED (GET1U ());
+      NEXT_INSN;
+
+    insn_astore:
+      STOREA (GET1U ());
+      NEXT_INSN;
+
+    insn_istore_0:
+      STOREI (0);
+      NEXT_INSN;
+
+    insn_istore_1:
+      STOREI (1);
+      NEXT_INSN;
+
+    insn_istore_2:
+      STOREI (2);
+      NEXT_INSN;
+
+    insn_istore_3:
+      STOREI (3);
+      NEXT_INSN;
+
+    insn_lstore_0:
+      STOREL (0);
+      NEXT_INSN;
+
+    insn_lstore_1:
+      STOREL (1);
+      NEXT_INSN;
+
+    insn_lstore_2:
+      STOREL (2);
+      NEXT_INSN;
+
+    insn_lstore_3:
+      STOREL (3);
+      NEXT_INSN;
+
+    insn_fstore_0:
+      STOREF (0);
+      NEXT_INSN;
+
+    insn_fstore_1:
+      STOREF (1);
+      NEXT_INSN;
+
+    insn_fstore_2:
+      STOREF (2);
+      NEXT_INSN;
+
+    insn_fstore_3:
+      STOREF (3);
+      NEXT_INSN;
+
+    insn_dstore_0:
+      STORED (0);
+      NEXT_INSN;
+
+    insn_dstore_1:
+      STORED (1);
+      NEXT_INSN;
+
+    insn_dstore_2:
+      STORED (2);
+      NEXT_INSN;
+
+    insn_dstore_3:
+      STORED (3);
+      NEXT_INSN;
+
+    insn_astore_0:
+      STOREA(0);
+      NEXT_INSN;
+
+    insn_astore_1:
+      STOREA(1);
+      NEXT_INSN;
+
+    insn_astore_2:
+      STOREA(2);
+      NEXT_INSN;
+
+    insn_astore_3:
+      STOREA(3);
+      NEXT_INSN;
+
+    insn_iastore:
+      {
+	jint value = POPI();
+	jint index  = POPI();
+	jintArray arr = (jintArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_lastore:
+      {
+	jlong value = POPL();
+	jint index  = POPI();
+	jlongArray arr = (jlongArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_fastore:
+      {
+	jfloat value = POPF();
+	jint index  = POPI();
+	jfloatArray arr = (jfloatArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_dastore:
+      {
+	jdouble value = POPD();
+	jint index  = POPI();
+	jdoubleArray arr = (jdoubleArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_aastore:
+      {
+	jobject value = POPA();
+	jint index  = POPI();
+	jobjectArray arr = (jobjectArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	_Jv_CheckArrayStore (arr, value);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_bastore:
+      {
+	jbyte value = (jbyte) POPI();
+	jint index  = POPI();
+	jbyteArray arr = (jbyteArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_castore:
+      {
+	jchar value = (jchar) POPI();
+	jint index  = POPI();
+	jcharArray arr = (jcharArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_sastore:
+      {
+	jshort value = (jshort) POPI();
+	jint index  = POPI();
+	jshortArray arr = (jshortArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_pop:
+      sp -= 1;
+      NEXT_INSN;
+
+    insn_pop2:
+      sp -= 2;
+      NEXT_INSN;
+
+    insn_dup:
+      sp[0] = sp[-1];
+      sp += 1;
+      NEXT_INSN;
+
+    insn_dup_x1:
+      dupx (sp, 1, 1); sp+=1;
+      NEXT_INSN;
+
+    insn_dup_x2:
+      dupx (sp, 1, 2); sp+=1;
+      NEXT_INSN;
+
+    insn_dup2:
+      sp[0] = sp[-2];
+      sp[1] = sp[-1];
+      sp += 2;
+      NEXT_INSN;
+
+    insn_dup2_x1:
+      dupx (sp, 2, 1); sp+=2;
+      NEXT_INSN;
+
+    insn_dup2_x2:
+      dupx (sp, 2, 2); sp+=2;
+      NEXT_INSN;
+
+    insn_swap:
+      {
+	jobject tmp1 = POPA();
+	jobject tmp2 = POPA();
+	PUSHA (tmp1);
+	PUSHA (tmp2);
+      }
+      NEXT_INSN;
+
+    insn_iadd:
+      BINOPI(+);
+      NEXT_INSN;
+
+    insn_ladd:
+      BINOPL(+);
+      NEXT_INSN;
+
+    insn_fadd:
+      BINOPF(+);
+      NEXT_INSN;
+
+    insn_dadd:
+      BINOPD(+);
+      NEXT_INSN;
+
+    insn_isub:
+      BINOPI(-);
+      NEXT_INSN;
+
+    insn_lsub:
+      BINOPL(-);
+      NEXT_INSN;
+
+    insn_fsub:
+      BINOPF(-);
+      NEXT_INSN;
+
+    insn_dsub:
+      BINOPD(-);
+      NEXT_INSN;
+
+    insn_imul:
+      BINOPI(*);
+      NEXT_INSN;
+
+    insn_lmul:
+      BINOPL(*);
+      NEXT_INSN;
+
+    insn_fmul:
+      BINOPF(*);
+      NEXT_INSN;
+
+    insn_dmul:
+      BINOPD(*);
+      NEXT_INSN;
+
+    insn_idiv:
+      {
+	SAVE_PC();
+	jint value2 = POPI();
+	jint value1 = POPI();
+	jint res = _Jv_divI (value1, value2);
+	PUSHI (res);
+      }
+      NEXT_INSN;
+
+    insn_ldiv:
+      {
+	SAVE_PC();
+	jlong value2 = POPL();
+	jlong value1 = POPL();
+	jlong res = _Jv_divJ (value1, value2);
+	PUSHL (res);
+      }
+      NEXT_INSN;
+
+    insn_fdiv:
+      {
+	jfloat value2 = POPF();
+	jfloat value1 = POPF();
+	jfloat res = value1 / value2;
+	PUSHF (res);
+      }
+      NEXT_INSN;
+
+    insn_ddiv:
+      {
+	jdouble value2 = POPD();
+	jdouble value1 = POPD();
+	jdouble res = value1 / value2;
+	PUSHD (res);
+      }
+      NEXT_INSN;
+
+    insn_irem:
+      {
+	SAVE_PC();
+	jint value2 = POPI();
+	jint value1 =  POPI();
+	jint res = _Jv_remI (value1, value2);
+	PUSHI (res);
+      }
+      NEXT_INSN;
+
+    insn_lrem:
+      {
+	SAVE_PC();
+	jlong value2 = POPL();
+	jlong value1 = POPL();
+	jlong res = _Jv_remJ (value1, value2);
+	PUSHL (res);
+      }
+      NEXT_INSN;
+
+    insn_frem:
+      {
+	jfloat value2 = POPF();
+	jfloat value1 = POPF();
+	jfloat res    = __ieee754_fmod (value1, value2);
+	PUSHF (res);
+      }
+      NEXT_INSN;
+
+    insn_drem:
+      {
+	jdouble value2 = POPD();
+	jdouble value1 = POPD();
+	jdouble res    = __ieee754_fmod (value1, value2);
+	PUSHD (res);
+      }
+      NEXT_INSN;
+
+    insn_ineg:
+      {
+	jint value = POPI();
+	PUSHI (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_lneg:
+      {
+	jlong value = POPL();
+	PUSHL (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_fneg:
+      {
+	jfloat value = POPF();
+	PUSHF (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_dneg:
+      {
+	jdouble value = POPD();
+	PUSHD (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_ishl:
+      {
+	jint shift = (POPI() & 0x1f);
+	jint value = POPI();
+	PUSHI (value << shift);
+      }
+      NEXT_INSN;
+
+    insn_lshl:
+      {
+	jint shift = (POPI() & 0x3f);
+	jlong value = POPL();
+	PUSHL (value << shift);
+      }
+      NEXT_INSN;
+
+    insn_ishr:
+      {
+	jint shift = (POPI() & 0x1f);
+	jint value = POPI();
+	PUSHI (value >> shift);
+      }
+      NEXT_INSN;
+
+    insn_lshr:
+      {
+	jint shift = (POPI() & 0x3f);
+	jlong value = POPL();
+	PUSHL (value >> shift);
+      }
+      NEXT_INSN;
+
+    insn_iushr:
+      {
+	jint shift = (POPI() & 0x1f);
+	_Jv_uint value = (_Jv_uint) POPI();
+	PUSHI ((jint) (value >> shift));
+      }
+      NEXT_INSN;
+
+    insn_lushr:
+      {
+	jint shift = (POPI() & 0x3f);
+	_Jv_ulong value = (_Jv_ulong) POPL();
+	PUSHL ((jlong) (value >> shift));
+      }
+      NEXT_INSN;
+
+    insn_iand:
+      BINOPI (&);
+      NEXT_INSN;
+
+    insn_land:
+      BINOPL (&);
+      NEXT_INSN;
+
+    insn_ior:
+      BINOPI (|);
+      NEXT_INSN;
+
+    insn_lor:
+      BINOPL (|);
+      NEXT_INSN;
+
+    insn_ixor:
+      BINOPI (^);
+      NEXT_INSN;
+
+    insn_lxor:
+      BINOPL (^);
+      NEXT_INSN;
+
+    insn_iinc:
+      {
+	jint index  = GET1U ();
+	jint amount = GET1S ();
+	locals[index].i += amount;
+      }
+      NEXT_INSN;
+
+    insn_i2l:
+      {jlong value = POPI(); PUSHL (value);}
+      NEXT_INSN;
+
+    insn_i2f:
+      {jfloat value = POPI(); PUSHF (value);}
+      NEXT_INSN;
+
+    insn_i2d:
+      {jdouble value = POPI(); PUSHD (value);}
+      NEXT_INSN;
+
+    insn_l2i:
+      {jint value = POPL(); PUSHI (value);}
+      NEXT_INSN;
+
+    insn_l2f:
+      {jfloat value = POPL(); PUSHF (value);}
+      NEXT_INSN;
+
+    insn_l2d:
+      {jdouble value = POPL(); PUSHD (value);}
+      NEXT_INSN;
+
+    insn_f2i:
+      {
+	using namespace java::lang;
+	jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
+	PUSHI(value);
+      }
+      NEXT_INSN;
+
+    insn_f2l:
+      {
+	using namespace java::lang;
+	jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
+	PUSHL(value);
+      }
+      NEXT_INSN;
+
+    insn_f2d:
+      { jdouble value = POPF (); PUSHD(value); }
+      NEXT_INSN;
+
+    insn_d2i:
+      {
+	using namespace java::lang;
+	jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
+	PUSHI(value);
+      }
+      NEXT_INSN;
+
+    insn_d2l:
+      {
+	using namespace java::lang;
+	jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
+	PUSHL(value);
+      }
+      NEXT_INSN;
+
+    insn_d2f:
+      { jfloat value = POPD (); PUSHF(value); }
+      NEXT_INSN;
+
+    insn_i2b:
+      { jbyte value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_i2c:
+      { jchar value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_i2s:
+      { jshort value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_lcmp:
+      {
+	jlong value2 = POPL ();
+	jlong value1 = POPL ();
+	if (value1 > value2)
+	  { PUSHI (1); }
+	else if (value1 == value2)
+	  { PUSHI (0); }
+	else
+	  { PUSHI (-1); }
+      }
+      NEXT_INSN;
+
+    insn_fcmpl:
+      tmpval = -1;
+      goto fcmp;
+
+    insn_fcmpg:
+      tmpval = 1;
+
+    fcmp:
+      {
+	jfloat value2 = POPF ();
+	jfloat value1 = POPF ();
+	if (value1 > value2)
+	  PUSHI (1);
+	else if (value1 == value2)
+	  PUSHI (0);
+	else if (value1 < value2)
+	  PUSHI (-1);
+	else
+	  PUSHI (tmpval);
+      }
+      NEXT_INSN;
+
+    insn_dcmpl:
+      tmpval = -1;
+      goto dcmp;
+
+    insn_dcmpg:
+      tmpval = 1;
+
+    dcmp:
+      {
+	jdouble value2 = POPD ();
+	jdouble value1 = POPD ();
+	if (value1 > value2)
+	  PUSHI (1);
+	else if (value1 == value2)
+	  PUSHI (0);
+	else if (value1 < value2)
+	  PUSHI (-1);
+	else
+	  PUSHI (tmpval);
+      }
+      NEXT_INSN;
+
+    insn_ifeq:
+      {
+	if (POPI() == 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifne:
+      {
+	if (POPI() != 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_iflt:
+      {
+	if (POPI() < 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifge:
+      {
+	if (POPI() >= 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifgt:
+      {
+	if (POPI() > 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifle:
+      {
+	if (POPI() <= 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpeq:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 == value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpne:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 != value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmplt:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 < value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpge:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 >= value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpgt:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 > value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmple:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 <= value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_acmpeq:
+      {
+	jobject value2 = POPA();
+	jobject value1 = POPA();
+	if (value1 == value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_acmpne:
+      {
+	jobject value2 = POPA();
+	jobject value1 = POPA();
+	if (value1 != value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_goto_w:
+#ifndef DIRECT_THREADED
+      // For direct threaded, goto and goto_w are the same.
+      pc = pc - 1 + get4 (pc);
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_goto:
+      TAKE_GOTO;
+      NEXT_INSN;
+
+    insn_jsr_w:
+#ifndef DIRECT_THREADED
+      // For direct threaded, jsr and jsr_w are the same.
+      {
+	pc_t next = pc - 1 + get4 (pc);
+	pc += 4;
+	PUSHA ((jobject) pc);
+	pc = next;
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_jsr:
+      {
+	pc_t next = GOTO_VAL();
+	SKIP_GOTO;
+	PUSHA ((jobject) pc);
+	pc = next;
+      }
+      NEXT_INSN;
+
+    insn_ret:
+      {
+	jint index = GET1U ();
+	pc = (pc_t) PEEKA (index);
+      }
+      NEXT_INSN;
+
+    insn_tableswitch:
+      {
+#ifdef DIRECT_THREADED
+	void *def = (pc++)->datum;
+
+	int index = POPI();
+
+	jint low = INTVAL ();
+	jint high = INTVAL ();
+
+	if (index < low || index > high)
+	  pc = (insn_slot *) def;
+	else
+	  pc = (insn_slot *) ((pc + index - low)->datum);
+#else
+	pc_t base_pc = pc - 1;
+	int index = POPI ();
+
+	pc_t base = (pc_t) bytecode ();
+	while ((pc - base) % 4 != 0)
+	  ++pc;
+
+	jint def = get4 (pc);
+	jint low = get4 (pc + 4);
+	jint high = get4 (pc + 8);
+	if (index < low || index > high)
+	  pc = base_pc + def;
+	else
+	  pc = base_pc + get4 (pc + 4 * (index - low + 3));
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+    insn_lookupswitch:
+      {
+#ifdef DIRECT_THREADED
+	void *def = (pc++)->insn;
+
+	int index = POPI();
+
+	jint npairs = INTVAL ();
+
+	int max = npairs - 1;
+	int min = 0;
+
+	// Simple binary search...
+	while (min < max)
+	  {
+	    int half = (min + max) / 2;
+	    int match = pc[2 * half].int_val;
+
+	    if (index == match)
+	      {
+		// Found it.
+		pc = (insn_slot *) pc[2 * half + 1].datum;
+		NEXT_INSN;
+	      }
+	    else if (index < match)
+	      // We can use HALF - 1 here because we check again on
+	      // loop exit.
+	      max = half - 1;
+	    else
+	      // We can use HALF + 1 here because we check again on
+	      // loop exit.
+	      min = half + 1;
+	  }
+	if (index == pc[2 * min].int_val)
+	  pc = (insn_slot *) pc[2 * min + 1].datum;
+	else
+	  pc = (insn_slot *) def;
+#else
+	unsigned char *base_pc = pc-1;
+	int index = POPI();
+
+	unsigned char* base = bytecode ();
+	while ((pc-base) % 4 != 0)
+	  ++pc;
+
+	jint def     = get4 (pc);
+	jint npairs  = get4 (pc+4);
+
+	int max = npairs-1;
+	int min = 0;
+
+	// Simple binary search...
+	while (min < max)
+	  {
+	    int half = (min+max)/2;
+	    int match = get4 (pc+ 4*(2 + 2*half));
+
+	    if (index == match)
+	      min = max = half;
+	    else if (index < match)
+	      // We can use HALF - 1 here because we check again on
+	      // loop exit.
+	      max = half - 1;
+	    else
+	      // We can use HALF + 1 here because we check again on
+	      // loop exit.
+	      min = half + 1;
+	  }
+
+	if (index == get4 (pc+ 4*(2 + 2*min)))
+	  pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
+	else
+	  pc = base_pc + def;    
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+    insn_areturn:
+      *(jobject *) retp = POPA ();
+      return;
+
+    insn_lreturn:
+      *(jlong *) retp = POPL ();
+      return;
+
+    insn_freturn:
+      *(jfloat *) retp = POPF ();
+      return;
+
+    insn_dreturn:
+      *(jdouble *) retp = POPD ();
+      return;
+
+    insn_ireturn:
+      *(jint *) retp = POPI ();
+      return;
+
+    insn_return:
+      return;
+
+    insn_getstatic:
+      {
+	jint fieldref_index = GET2U ();
+        SAVE_PC(); // Constant pool resolution could throw.
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	if ((field->flags & Modifier::STATIC) == 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field no longer static"));
+
+	jclass type = field->type;
+
+	// We rewrite the instruction once we discover what it refers
+	// to.
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes)
+	      {
+	      case 1:
+		PUSHI (*field->u.byte_addr);
+		newinsn = AMPAMP (getstatic_resolved_1);
+		break;
+
+	      case 2:
+		if (type == JvPrimClass (char))
+		  {
+		    PUSHI (*field->u.char_addr);
+		    newinsn = AMPAMP (getstatic_resolved_char);
+		  }
+		else
+		  {
+		    PUSHI (*field->u.short_addr);
+		    newinsn = AMPAMP (getstatic_resolved_short);
+		  }
+		break;
+
+	      case 4:
+	        PUSHI(*field->u.int_addr);
+		newinsn = AMPAMP (getstatic_resolved_4);
+		break;
+
+	      case 8:
+	        PUSHL(*field->u.long_addr);
+		newinsn = AMPAMP (getstatic_resolved_8);
+		break;
+	      }
+	  }
+	else
+	  {
+	    PUSHA(*field->u.object_addr);
+	    newinsn = AMPAMP (getstatic_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].datum = field->u.addr;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    getstatic_resolved_1:
+      PUSHI (*(jbyte *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_char:
+      PUSHI (*(jchar *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_short:
+      PUSHI (*(jshort *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_4:
+      PUSHI (*(jint *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_8:
+      PUSHL (*(jlong *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_obj:
+      PUSHA (*(jobject *) AVAL ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_getfield:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	if ((field->flags & Modifier::STATIC) != 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field is static"));
+
+	jclass type = field->type;
+	jint field_offset = field->u.boffset;
+
+	jobject obj   = POPA();
+	NULLCHECK(obj);
+
+	void *newinsn = NULL;
+	_Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes)
+	      {
+	      case 1:
+	        PUSHI (val->byte_value);
+		newinsn = AMPAMP (getfield_resolved_1);
+		break;
+
+	      case 2:
+		if (type == JvPrimClass (char))
+		  {
+		    PUSHI (val->char_value);
+		    newinsn = AMPAMP (getfield_resolved_char);
+		  }
+		else
+		  {
+		    PUSHI (val->short_value);
+		    newinsn = AMPAMP (getfield_resolved_short);
+		  }
+		break;
+
+	      case 4:
+		PUSHI (val->int_value);
+		newinsn = AMPAMP (getfield_resolved_4);
+		break;
+
+	      case 8:
+	        PUSHL (val->long_value);
+		newinsn = AMPAMP (getfield_resolved_8);
+		break;
+	      }
+	  }
+	else
+	  {
+	    PUSHA (val->object_value);
+	    newinsn = AMPAMP (getfield_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].int_val = field_offset;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    getfield_resolved_1:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jbyte *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_char:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jchar *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_short:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jshort *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_4:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jint *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_8:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHL (*(jlong *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_obj:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHA (*(jobject *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_putstatic:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	jclass type = field->type;
+
+	// ResolvePoolEntry cannot check this
+	if ((field->flags & Modifier::STATIC) == 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field no longer static"));
+
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes) 
+	      {
+	      case 1:
+		{
+		  jint value = POPI();
+		  *field->u.byte_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_1);
+		  break;
+		}
+
+	      case 2:
+		{
+		  jint value = POPI();
+		  *field->u.char_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_2);
+		  break;
+		}
+
+	      case 4:
+		{
+		  jint value = POPI();
+		  *field->u.int_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_4);
+		  break;
+		}
+
+	      case 8:
+		{
+		  jlong value = POPL();
+		  *field->u.long_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_8);
+		  break;
+		}
+	      }
+	  }
+	else
+	  {
+	    jobject value = POPA();
+	    *field->u.object_addr = value;
+	    newinsn = AMPAMP (putstatic_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].datum = field->u.addr;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    putstatic_resolved_1:
+      *(jbyte *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_2:
+      *(jchar *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_4:
+      *(jint *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_8:
+      *(jlong *) AVAL () = POPL ();
+      NEXT_INSN;
+
+    putstatic_resolved_obj:
+      *(jobject *) AVAL () = POPA ();
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_putfield:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	jclass type = field->type;
+
+	if ((field->flags & Modifier::STATIC) != 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field is static"));
+
+	jint field_offset = field->u.boffset;
+
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes) 
+	      {
+	      case 1:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jbyte*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_1);
+		  break;
+		}
+
+	      case 2:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jchar*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_2);
+		  break;
+		}
+
+	      case 4:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jint*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_4);
+		  break;
+		}
+
+	      case 8:
+		{
+		  jlong   value = POPL();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jlong*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_8);
+		  break;
+		}
+	      }
+	  }
+	else
+	  {
+	    jobject value = POPA();
+	    jobject obj   = POPA();
+	    NULLCHECK(obj);
+	    *(jobject*) ((char*)obj + field_offset) = value;
+	    newinsn = AMPAMP (putfield_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].int_val = field_offset;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    putfield_resolved_1:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jbyte *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_2:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jchar *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_4:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jint *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_8:
+      {
+	jlong val = POPL ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jlong *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_obj:
+      {
+	jobject val = POPA ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jobject *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_invokespecial:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	// We don't use NULLCHECK here because we can't rely on that
+	// working for <init>.  So instead we do an explicit test.
+	if (! sp[0].o)
+	  {
+	    SAVE_PC();
+	    throw_null_pointer_exception ();
+	  }
+
+	fun = (void (*)()) rmeth->method->ncode;
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokespecial_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokespecial_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	// We don't use NULLCHECK here because we can't rely on that
+	// working for <init>.  So instead we do an explicit test.
+	if (! sp[0].o)
+	  {
+	    throw_null_pointer_exception ();
+	  }
+	fun = (void (*)()) rmeth->method->ncode;
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_invokestatic:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	fun = (void (*)()) rmeth->method->ncode;
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokestatic_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokestatic_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	fun = (void (*)()) rmeth->method->ncode;
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_invokeinterface:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	jobject rcv = sp[0].o;
+
+	NULLCHECK (rcv);
+
+	fun = (void (*)())
+	  _Jv_LookupInterfaceMethod (rcv->getClass (),
+				     rmeth->method->name,
+				     rmeth->method->signature);
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokeinterface_resolved;
+	pc[-1].datum = rmeth;
+#else
+	// Skip dummy bytes.
+	pc += 2;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokeinterface_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	jobject rcv = sp[0].o;
+	NULLCHECK (rcv);
+	fun = (void (*)())
+	  _Jv_LookupInterfaceMethod (rcv->getClass (),
+				     rmeth->method->name,
+				     rmeth->method->signature);
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_new:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+							  index)).clazz;
+	/* VM spec, section 3.11.5 */
+	if ((klass->getModifiers() & Modifier::ABSTRACT)
+	    || klass->isInterface())
+	  throw new java::lang::InstantiationException;
+	jobject res = _Jv_AllocObject (klass);
+	PUSHA (res);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&new_resolved;
+	pc[-1].datum = klass;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    new_resolved:
+      {
+	jclass klass = (jclass) AVAL ();
+	jobject res = _Jv_AllocObject (klass);
+	PUSHA (res);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_newarray:
+      {
+	int atype = GET1U ();
+	int size  = POPI();
+	jobject result = _Jv_NewArray (atype, size);
+	PUSHA (result);
+      }
+      NEXT_INSN;
+
+    insn_anewarray:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+							  index)).clazz;
+	int size  = POPI();
+	jobject result = _Jv_NewObjectArray (size, klass, 0);
+	PUSHA (result);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&anewarray_resolved;
+	pc[-1].datum = klass;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    anewarray_resolved:
+      {
+	jclass klass = (jclass) AVAL ();
+	int size = POPI ();
+	jobject result = _Jv_NewObjectArray (size, klass, 0);
+	PUSHA (result);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_arraylength:
+      {
+	__JArray *arr = (__JArray*)POPA();
+	NULLARRAYCHECK (arr);
+	PUSHI (arr->length);
+      }
+      NEXT_INSN;
+
+    insn_athrow:
+      {
+	jobject value = POPA();
+	throw static_cast<jthrowable>(value);
+      }
+      NEXT_INSN;
+
+    insn_checkcast:
+      {
+        SAVE_PC();
+	jobject value = POPA();
+	jint index = GET2U ();
+	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						       index)).clazz;
+
+	value = (jobject) _Jv_CheckCast (to, value);
+
+	PUSHA (value);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&checkcast_resolved;
+	pc[-1].datum = to;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    checkcast_resolved:
+      {
+        SAVE_PC();
+	jobject value = POPA ();
+	jclass to = (jclass) AVAL ();
+	value = (jobject) _Jv_CheckCast (to, value);
+	PUSHA (value);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_instanceof:
+      {
+        SAVE_PC();
+	jobject value = POPA();
+	jint index = GET2U ();
+	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						       index)).clazz;
+	PUSHI (to->isInstance (value));
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&instanceof_resolved;
+	pc[-1].datum = to;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    instanceof_resolved:
+      {
+	jobject value = POPA ();
+	jclass to = (jclass) AVAL ();
+	PUSHI (to->isInstance (value));
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_monitorenter:
+      {
+	jobject value = POPA();
+	NULLCHECK(value);
+	_Jv_MonitorEnter (value);
+      }
+      NEXT_INSN;
+
+    insn_monitorexit:
+      {
+	jobject value = POPA();
+	NULLCHECK(value);
+	_Jv_MonitorExit (value);
+      }
+      NEXT_INSN;
+
+    insn_ifnull:
+      {
+	jobject val = POPA();
+	if (val == NULL)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifnonnull:
+      {
+	jobject val = POPA();
+	if (val != NULL)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_multianewarray:
+      {
+	SAVE_PC();
+	int kind_index = GET2U ();
+	int dim        = GET1U ();
+
+	jclass type    
+	  = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+					       kind_index)).clazz;
+	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
+
+	for (int i = dim - 1; i >= 0; i--)
+	  {
+	    sizes[i] = POPI ();
+	  }
+
+	jobject res    = _Jv_NewMultiArray (type,dim, sizes);
+
+	PUSHA (res);
+      }
+      NEXT_INSN;
+
+#ifndef DIRECT_THREADED
+    insn_wide:
+      {
+	jint the_mod_op = get1u (pc++);
+	jint wide       = get2u (pc); pc += 2;
+
+	switch (the_mod_op)
+	  {
+	  case op_istore:
+	    STOREI (wide);
+	    NEXT_INSN;
+
+	  case op_fstore:
+	    STOREF (wide);
+	    NEXT_INSN;
+
+	  case op_astore:
+	    STOREA (wide);
+	    NEXT_INSN;
+
+	  case op_lload:
+	    LOADL (wide);
+	    NEXT_INSN;
+
+	  case op_dload:
+	    LOADD (wide);
+	    NEXT_INSN;
+
+	  case op_iload:
+	    LOADI (wide);
+	    NEXT_INSN;
+
+	  case op_fload:
+	    LOADF (wide);
+	    NEXT_INSN;
+
+	  case op_aload:
+	    LOADA (wide);
+	    NEXT_INSN;
+
+	  case op_lstore:
+	    STOREL (wide);
+	    NEXT_INSN;
+
+	  case op_dstore:
+	    STORED (wide);
+	    NEXT_INSN;
+
+	  case op_ret:
+	    pc = (unsigned char*) PEEKA (wide);
+	    NEXT_INSN;
+
+	  case op_iinc:
+	    {
+	      jint amount = get2s (pc); pc += 2;
+	      jint value = PEEKI (wide);
+	      POKEI (wide, value+amount);
+	    }
+	    NEXT_INSN;
+
+	  default:
+	    throw_internal_error ("illegal bytecode modified by wide");
+	  }
+
+      }
+#endif /* DIRECT_THREADED */
+    }
+  catch (java::lang::Throwable *ex)
+    {
+#ifdef DIRECT_THREADED
+      void *logical_pc = (void *) ((insn_slot *) pc - 1);
+#else
+      int logical_pc = pc - 1 - bytecode ();
+#endif
+      _Jv_InterpException *exc = meth->exceptions ();
+      jclass exc_class = ex->getClass ();
+
+      for (int i = 0; i < meth->exc_count; i++)
+	{
+	  if (PCVAL (exc[i].start_pc) <= logical_pc
+	      && logical_pc < PCVAL (exc[i].end_pc))
+	    {
+#ifdef DIRECT_THREADED
+	      jclass handler = (jclass) exc[i].handler_type.p;
+#else
+	      jclass handler = NULL;
+	      if (exc[i].handler_type.i != 0)
+		handler = (_Jv_Linker::resolve_pool_entry (defining_class,
+							     exc[i].handler_type.i)).clazz;
+#endif /* DIRECT_THREADED */
+
+	      if (handler == NULL || handler->isAssignableFrom (exc_class))
+		{
+
+#ifdef DIRECT_THREADED
+		  pc = (insn_slot *) exc[i].handler_pc.p;
+#else
+		  pc = bytecode () + exc[i].handler_pc.i;
+#endif /* DIRECT_THREADED */
+		  sp = stack;
+		  sp++->o = ex; // Push exception.
+		  NEXT_INSN;
+		}
+	    }
+	}
+
+      // No handler, so re-throw.
+      throw ex;
+    }
Index: interpret.cc
===================================================================
--- /home/kgallowa/work/gcc/libjava/interpret.cc	(revision 115873)
+++ /home/kgallowa/work/gcc/libjava/interpret.cc	(working copy)
@@ -37,6 +37,8 @@
 #include <execution.h>
 #include <java/lang/reflect/Modifier.h>
 
+#include <gnu/classpath/jdwp/Jdwp.h>
+
 #ifdef INTERPRETER
 
 // Execution engine for interpreted code.
@@ -152,18 +154,36 @@
 # define LOADD(I)  LOADL(I)
 #endif
 
-#define STOREA(I) locals[I].o = (--sp)->o
-#define STOREI(I) locals[I].i = (--sp)->i
-#define STOREF(I) locals[I].f = (--sp)->f
+#define STOREA(I) 		\
+DEBUG_LOCALS_INSN(I, 'o')	\
+locals[I].o = (--sp)->o
+#define STOREI(I) 		\
+DEBUG_LOCALS_INSN (I, 'i')	\
+locals[I].i = (--sp)->i
+#define STOREF(I)  		\
+DEBUG_LOCALS_INSN (I, 'f')	\
+locals[I].f = (--sp)->f
 #if SIZEOF_VOID_P == 8
-# define STOREL(I) (sp -= 2, locals[I].l = sp->l)
-# define STORED(I) (sp -= 2, locals[I].d = sp->d)
+# define STOREL(I)  			\
+DEBUG_LOCALS_INSN (I, 'l')			\
+(sp -= 2, locals[I].l = sp->l)
+# define STORED(I) 				\
+DEBUG_LOCALS_INSN (I, 'd')			\
+(sp -= 2, locals[I].d = sp->d)
+
 #else
-# define STOREL(I) do { jint __idx = (I); \
-    		       locals[__idx+1].ia[0] = (--sp)->ia[0]; \
-    		       locals[__idx].ia[0] = (--sp)->ia[0]; \
-		   } while (0)
-# define STORED(I) STOREL(I)
+# define STOREL(I)		\
+DEBUG_LOCALS_INSN(I, 'l')	\
+do { jint __idx = (I); 	\
+     locals[__idx+1].ia[0] = (--sp)->ia[0]; \
+     locals[__idx].ia[0] = (--sp)->ia[0]; 	\
+   } while (0)
+# define STORED(I)		\
+DEBUG_LOCALS_INSN(I, 'd')	\
+do { jint __idx = (I); 	\
+     locals[__idx+1].ia[0] = (--sp)->ia[0]; \
+     locals[__idx].ia[0] = (--sp)->ia[0]; 	\
+   } while (0)
 #endif
 
 #define PEEKI(I)  (locals+(I))->i
@@ -169,7 +189,9 @@
 #define PEEKI(I)  (locals+(I))->i
 #define PEEKA(I)  (locals+(I))->o
 
-#define POKEI(I,V)  ((locals+(I))->i = (V))
+#define POKEI(I,V)  	\
+DEBUG_LOCALS_INSN(I,i)	\
+((locals+(I))->i = (V))
 
 
 #define BINOPI(OP) { \
@@ -258,6 +280,16 @@
 }
 
 void
+_Jv_InterpMethod::run_normal_debug (ffi_cif *,
+			      void* ret,
+			      ffi_raw * args,
+			      void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+  run_debug (ret, args, _this);
+}
+
+void
 _Jv_InterpMethod::run_synch_object (ffi_cif *,
 				    void* ret,
 				    ffi_raw * args,
@@ -272,6 +304,20 @@
 }
 
 void
+_Jv_InterpMethod::run_synch_object_debug (ffi_cif *,
+				    void* ret,
+				    ffi_raw * args,
+				    void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+
+  jobject rcv = (jobject) args[0].ptr;
+  JvSynchronize mutex (rcv);
+
+  run_debug (ret, args, _this);
+}
+
+void
 _Jv_InterpMethod::run_class (ffi_cif *,
 			     void* ret,
 			     ffi_raw * args,
@@ -283,6 +329,17 @@
 }
 
 void
+_Jv_InterpMethod::run_class_debug (ffi_cif *,
+			     void* ret,
+			     ffi_raw * args,
+			     void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+  _Jv_InitClass (_this->defining_class);
+  run_debug (ret, args, _this);
+}
+
+void
 _Jv_InterpMethod::run_synch_class (ffi_cif *,
 				   void* ret,
 				   ffi_raw * args,
@@ -297,6 +354,21 @@
   run (ret, args, _this);
 }
 
+void
+_Jv_InterpMethod::run_synch_class_debug (ffi_cif *,
+				   void* ret,
+				   ffi_raw * args,
+				   void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+
+  jclass sync = _this->defining_class;
+  _Jv_InitClass (sync);
+  JvSynchronize mutex (sync);
+
+  run_debug (ret, args, _this);
+}
+
 #ifdef DIRECT_THREADED
 // "Compile" a method by turning it from bytecode to direct-threaded
 // code.
@@ -805,2709 +877,239 @@
 void
 _Jv_InterpMethod::run (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
 {
-  using namespace java::lang::reflect;
+#undef DEBUG
+#undef DEBUG_LOCALS_INSN
+#define DEBUG_LOCALS_INSN(s, t) {}
 
-  // FRAME_DESC registers this particular invocation as the top-most
-  // interpreter frame.  This lets the stack tracing code (for
-  // Throwable) print information about the method being interpreted
-  // rather than about the interpreter itself.  FRAME_DESC has a
-  // destructor so it cleans up automatically when the interpreter
-  // returns.
-  java::lang::Thread *thread = java::lang::Thread::currentThread();
-  _Jv_InterpFrame frame_desc (meth, thread);
+#include "interpret-run.cc"
+}
 
-  _Jv_word stack[meth->max_stack];
-  _Jv_word *sp = stack;
+void
+_Jv_InterpMethod::run_debug (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
+{
+/* Used to keep track of local variable type
+ * 
+ * Possible Types:
+ * o object
+ * i integer
+ * f float
+ * l long 
+ * d double 
+ */
+#define DEBUG
+#undef DEBUG_LOCALS_INSN
+#define DEBUG_LOCALS_INSN(s, t) {}
 
-  _Jv_word locals[meth->max_locals];
+#include "interpret-run.cc"
+}
 
-#define INSN_LABEL(op) &&insn_##op
+static void
+throw_internal_error (const char *msg)
+{
+  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
+}
 
-  static const void *const insn_target[] = 
-  {
-    INSN_LABEL(nop),
-    INSN_LABEL(aconst_null),
-    INSN_LABEL(iconst_m1),
-    INSN_LABEL(iconst_0),
-    INSN_LABEL(iconst_1),
-    INSN_LABEL(iconst_2),
-    INSN_LABEL(iconst_3),
-    INSN_LABEL(iconst_4),
-    INSN_LABEL(iconst_5),
-    INSN_LABEL(lconst_0),
-    INSN_LABEL(lconst_1),
-    INSN_LABEL(fconst_0),
-    INSN_LABEL(fconst_1),
-    INSN_LABEL(fconst_2),
-    INSN_LABEL(dconst_0),
-    INSN_LABEL(dconst_1),
-    INSN_LABEL(bipush),
-    INSN_LABEL(sipush),
-    INSN_LABEL(ldc),
-    INSN_LABEL(ldc_w),
-    INSN_LABEL(ldc2_w),
-    INSN_LABEL(iload),
-    INSN_LABEL(lload),
-    INSN_LABEL(fload),
-    INSN_LABEL(dload),
-    INSN_LABEL(aload),
-    INSN_LABEL(iload_0),
-    INSN_LABEL(iload_1),
-    INSN_LABEL(iload_2),
-    INSN_LABEL(iload_3),
-    INSN_LABEL(lload_0),
-    INSN_LABEL(lload_1),
-    INSN_LABEL(lload_2),
-    INSN_LABEL(lload_3),
-    INSN_LABEL(fload_0),
-    INSN_LABEL(fload_1),
-    INSN_LABEL(fload_2),
-    INSN_LABEL(fload_3),
-    INSN_LABEL(dload_0),
-    INSN_LABEL(dload_1),
-    INSN_LABEL(dload_2),
-    INSN_LABEL(dload_3),
-    INSN_LABEL(aload_0),
-    INSN_LABEL(aload_1),
-    INSN_LABEL(aload_2),
-    INSN_LABEL(aload_3),
-    INSN_LABEL(iaload),
-    INSN_LABEL(laload),
-    INSN_LABEL(faload),
-    INSN_LABEL(daload),
-    INSN_LABEL(aaload),
-    INSN_LABEL(baload),
-    INSN_LABEL(caload),
-    INSN_LABEL(saload),
-    INSN_LABEL(istore),
-    INSN_LABEL(lstore),
-    INSN_LABEL(fstore),
-    INSN_LABEL(dstore),
-    INSN_LABEL(astore),
-    INSN_LABEL(istore_0),
-    INSN_LABEL(istore_1),
-    INSN_LABEL(istore_2),
-    INSN_LABEL(istore_3),
-    INSN_LABEL(lstore_0),
-    INSN_LABEL(lstore_1),
-    INSN_LABEL(lstore_2),
-    INSN_LABEL(lstore_3),
-    INSN_LABEL(fstore_0),
-    INSN_LABEL(fstore_1),
-    INSN_LABEL(fstore_2),
-    INSN_LABEL(fstore_3),
-    INSN_LABEL(dstore_0),
-    INSN_LABEL(dstore_1),
-    INSN_LABEL(dstore_2),
-    INSN_LABEL(dstore_3),
-    INSN_LABEL(astore_0),
-    INSN_LABEL(astore_1),
-    INSN_LABEL(astore_2),
-    INSN_LABEL(astore_3),
-    INSN_LABEL(iastore),
-    INSN_LABEL(lastore),
-    INSN_LABEL(fastore),
-    INSN_LABEL(dastore),
-    INSN_LABEL(aastore),
-    INSN_LABEL(bastore),
-    INSN_LABEL(castore),
-    INSN_LABEL(sastore),
-    INSN_LABEL(pop),
-    INSN_LABEL(pop2),
-    INSN_LABEL(dup),
-    INSN_LABEL(dup_x1),
-    INSN_LABEL(dup_x2),
-    INSN_LABEL(dup2),
-    INSN_LABEL(dup2_x1),
-    INSN_LABEL(dup2_x2),
-    INSN_LABEL(swap),
-    INSN_LABEL(iadd),
-    INSN_LABEL(ladd),
-    INSN_LABEL(fadd),
-    INSN_LABEL(dadd),
-    INSN_LABEL(isub),
-    INSN_LABEL(lsub),
-    INSN_LABEL(fsub),
-    INSN_LABEL(dsub),
-    INSN_LABEL(imul),
-    INSN_LABEL(lmul),
-    INSN_LABEL(fmul),
-    INSN_LABEL(dmul),
-    INSN_LABEL(idiv),
-    INSN_LABEL(ldiv),
-    INSN_LABEL(fdiv),
-    INSN_LABEL(ddiv),
-    INSN_LABEL(irem),
-    INSN_LABEL(lrem),
-    INSN_LABEL(frem),
-    INSN_LABEL(drem),
-    INSN_LABEL(ineg),
-    INSN_LABEL(lneg),
-    INSN_LABEL(fneg),
-    INSN_LABEL(dneg),
-    INSN_LABEL(ishl),
-    INSN_LABEL(lshl),
-    INSN_LABEL(ishr),
-    INSN_LABEL(lshr),
-    INSN_LABEL(iushr),
-    INSN_LABEL(lushr),
-    INSN_LABEL(iand),
-    INSN_LABEL(land),
-    INSN_LABEL(ior),
-    INSN_LABEL(lor),
-    INSN_LABEL(ixor),
-    INSN_LABEL(lxor),
-    INSN_LABEL(iinc),
-    INSN_LABEL(i2l),
-    INSN_LABEL(i2f),
-    INSN_LABEL(i2d),
-    INSN_LABEL(l2i),
-    INSN_LABEL(l2f),
-    INSN_LABEL(l2d),
-    INSN_LABEL(f2i),
-    INSN_LABEL(f2l),
-    INSN_LABEL(f2d),
-    INSN_LABEL(d2i),
-    INSN_LABEL(d2l),
-    INSN_LABEL(d2f),
-    INSN_LABEL(i2b),
-    INSN_LABEL(i2c),
-    INSN_LABEL(i2s),
-    INSN_LABEL(lcmp),
-    INSN_LABEL(fcmpl),
-    INSN_LABEL(fcmpg),
-    INSN_LABEL(dcmpl),
-    INSN_LABEL(dcmpg),
-    INSN_LABEL(ifeq),
-    INSN_LABEL(ifne),
-    INSN_LABEL(iflt),
-    INSN_LABEL(ifge),
-    INSN_LABEL(ifgt),
-    INSN_LABEL(ifle),
-    INSN_LABEL(if_icmpeq),
-    INSN_LABEL(if_icmpne),
-    INSN_LABEL(if_icmplt),
-    INSN_LABEL(if_icmpge),
-    INSN_LABEL(if_icmpgt),
-    INSN_LABEL(if_icmple),
-    INSN_LABEL(if_acmpeq),
-    INSN_LABEL(if_acmpne),
-    INSN_LABEL(goto), 
-    INSN_LABEL(jsr),
-    INSN_LABEL(ret),
-    INSN_LABEL(tableswitch),
-    INSN_LABEL(lookupswitch),
-    INSN_LABEL(ireturn),
-    INSN_LABEL(lreturn),
-    INSN_LABEL(freturn),
-    INSN_LABEL(dreturn),
-    INSN_LABEL(areturn),
-    INSN_LABEL(return),
-    INSN_LABEL(getstatic),
-    INSN_LABEL(putstatic),
-    INSN_LABEL(getfield),
-    INSN_LABEL(putfield),
-    INSN_LABEL(invokevirtual),
-    INSN_LABEL(invokespecial),
-    INSN_LABEL(invokestatic),
-    INSN_LABEL(invokeinterface),
-    0, /* Unused.  */
-    INSN_LABEL(new),
-    INSN_LABEL(newarray),
-    INSN_LABEL(anewarray),
-    INSN_LABEL(arraylength),
-    INSN_LABEL(athrow),
-    INSN_LABEL(checkcast),
-    INSN_LABEL(instanceof),
-    INSN_LABEL(monitorenter),
-    INSN_LABEL(monitorexit),
-#ifdef DIRECT_THREADED
-    0, // wide
-#else
-    INSN_LABEL(wide),
-#endif
-    INSN_LABEL(multianewarray),
-    INSN_LABEL(ifnull),
-    INSN_LABEL(ifnonnull),
-    INSN_LABEL(goto_w),
-    INSN_LABEL(jsr_w),
-#ifdef DIRECT_THREADED
-    INSN_LABEL (ldc_class)
-#else
-    0
-#endif
-  };
+static void 
+throw_incompatible_class_change_error (jstring msg)
+{
+  throw new java::lang::IncompatibleClassChangeError (msg);
+}
 
-  pc_t pc;
+static void 
+throw_null_pointer_exception ()
+{
+  throw new java::lang::NullPointerException;
+}
 
-#ifdef DIRECT_THREADED
+/* Look up source code line number for given bytecode (or direct threaded
+   interpreter) PC. */
+int
+_Jv_InterpMethod::get_source_line(pc_t mpc)
+{
+  int line = line_table_len > 0 ? line_table[0].line : -1;
+  for (int i = 1; i < line_table_len; i++)
+    if (line_table[i].pc > mpc)
+      break;
+    else
+      line = line_table[i].line;
 
-#define NEXT_INSN goto *((pc++)->insn)
-#define INTVAL() ((pc++)->int_val)
-#define AVAL() ((pc++)->datum)
+  return line;
+}
 
-#define GET1S() INTVAL ()
-#define GET2S() INTVAL ()
-#define GET1U() INTVAL ()
-#define GET2U() INTVAL ()
-#define AVAL1U() AVAL ()
-#define AVAL2U() AVAL ()
-#define AVAL2UP() AVAL ()
-#define SKIP_GOTO ++pc
-#define GOTO_VAL() (insn_slot *) pc->datum
-#define PCVAL(unionval) unionval.p
-#define AMPAMP(label) &&label
+/** Do static initialization for fields with a constant initializer */
+void
+_Jv_InitField (jobject obj, jclass klass, int index)
+{
+  using namespace java::lang::reflect;
 
-  // Compile if we must. NOTE: Double-check locking.
-  if (meth->prepared == NULL)
-    {
-      _Jv_MutexLock (&compile_mutex);
-      if (meth->prepared == NULL)
-	meth->compile (insn_target);
-      _Jv_MutexUnlock (&compile_mutex);
-    }
+  if (obj != 0 && klass == 0)
+    klass = obj->getClass ();
 
-  // If we're only compiling, stop here
-  if (args == NULL)
+  if (!_Jv_IsInterpretedClass (klass))
     return;
 
-  pc = (insn_slot *) meth->prepared;
-
-#else
+  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
 
-#define NEXT_INSN goto *(insn_target[*pc++])
+  _Jv_Field * field = (&klass->fields[0]) + index;
 
-#define GET1S() get1s (pc++)
-#define GET2S() (pc += 2, get2s (pc- 2))
-#define GET1U() get1u (pc++)
-#define GET2U() (pc += 2, get2u (pc - 2))
-  // Note that these could be more efficient when not handling 'ldc
-  // class'.
-#define AVAL1U()						\
-  ({ int index = get1u (pc++);					\
-      resolve_pool_entry (meth->defining_class, index).o; })
-#define AVAL2U()						\
-  ({ int index = get2u (pc); pc += 2;				\
-      resolve_pool_entry (meth->defining_class, index).o; })
-  // Note that we don't need to resolve the pool entry here as class
-  // constants are never wide.
-#define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
-#define SKIP_GOTO pc += 2
-#define GOTO_VAL() pc - 1 + get2s (pc)
-#define PCVAL(unionval) unionval.i
-#define AMPAMP(label) NULL
+  if (index > klass->field_count)
+    throw_internal_error ("field out of range");
 
-  pc = bytecode ();
+  int init = iclass->field_initializers[index];
+  if (init == 0)
+    return;
 
-#endif /* DIRECT_THREADED */
+  _Jv_Constants *pool = &klass->constants;
+  int tag = pool->tags[init];
 
-#define TAKE_GOTO pc = GOTO_VAL ()
+  if (! field->isResolved ())
+    throw_internal_error ("initializing unresolved field");
 
-  /* Go straight at it!  the ffi raw format matches the internal
-     stack representation exactly.  At least, that's the idea.
-  */
-  memcpy ((void*) locals, (void*) args, meth->args_raw_size);
+  if (obj==0 && ((field->flags & Modifier::STATIC) == 0))
+    throw_internal_error ("initializing non-static field with no object");
 
-  _Jv_word *pool_data = meth->defining_class->constants.data;
+  void *addr = 0;
 
-  /* These three are temporaries for common code used by several
-     instructions.  */
-  void (*fun)();
-  _Jv_ResolvedMethod* rmeth;
-  int tmpval;
+  if ((field->flags & Modifier::STATIC) != 0)
+    addr = (void*) field->u.addr;
+  else
+    addr = (void*) (((char*)obj) + field->u.boffset);
 
-  try
+  switch (tag)
     {
-      // We keep nop around.  It is used if we're interpreting the
-      // bytecodes and not doing direct threading.
-    insn_nop:
-      NEXT_INSN;
-
-      /* The first few instructions here are ordered according to their
-	 frequency, in the hope that this will improve code locality a
-	 little.  */
-
-    insn_aload_0:		// 0x2a
-      LOADA (0);
-      NEXT_INSN;
-
-    insn_iload:		// 0x15
-      LOADI (GET1U ());
-      NEXT_INSN;
-
-    insn_iload_1:		// 0x1b
-      LOADI (1);
-      NEXT_INSN;
-
-    insn_invokevirtual:	// 0xb6
+    case JV_CONSTANT_String:
       {
-	SAVE_PC();
-	int index = GET2U ();
-
-	/* _Jv_Linker::resolve_pool_entry returns immediately if the
-	 * value already is resolved.  If we want to clutter up the
-	 * code here to gain a little performance, then we can check
-	 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
-	 * directly.  For now, I don't think it is worth it.  */
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	if (rmeth->method->accflags & Modifier::FINAL)
-	  {
-	    // We can't rely on NULLCHECK working if the method is final.
-	    if (! sp[0].o)
-	      throw_null_pointer_exception ();
-
-	    // Final methods might not appear in the vtable.
-	    fun = (void (*)()) rmeth->method->ncode;
-	  }
-	else
-	  {
-	    NULLCHECK (sp[0].o);
-	    jobject rcv = sp[0].o;
-	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
-	    fun = (void (*)()) table->get_method (rmeth->method->index);
-	  }
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokevirtual_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
+	jstring str;
+	str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
+	pool->data[init].string = str;
+	pool->tags[init] = JV_CONSTANT_ResolvedString;
       }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokevirtual_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
+      /* fall through */
 
-	if (rmeth->method->accflags & Modifier::FINAL)
-	  {
-	    // We can't rely on NULLCHECK working if the method is final.
-	    if (! sp[0].o)
-	      throw_null_pointer_exception ();
+    case JV_CONSTANT_ResolvedString:
+      if (! (field->type == &java::lang::String::class$
+ 	     || field->type == &java::lang::Class::class$))
+	throw_class_format_error ("string initialiser to non-string field");
 
-	    // Final methods might not appear in the vtable.
-	    fun = (void (*)()) rmeth->method->ncode;
-	  }
-	else
-	  {
-	    jobject rcv = sp[0].o;
-	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
-	    fun = (void (*)()) table->get_method (rmeth->method->index);
-	  }
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
+      *(jstring*)addr = pool->data[init].string;
+      break;
 
-    perform_invoke:
+    case JV_CONSTANT_Integer:
       {
-	/* here goes the magic again... */
-	ffi_cif *cif = &rmeth->cif;
-	ffi_raw *raw = (ffi_raw*) sp;
-
-	_Jv_value rvalue;
+	int value = pool->data[init].i;
 
-#if FFI_NATIVE_RAW_API
-	/* We assume that this is only implemented if it's correct	*/
-	/* to use it here.  On a 64 bit machine, it never is.		*/
-	ffi_raw_call (cif, fun, (void*)&rvalue, raw);
-#else
-	ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
-#endif
+	if (field->type == JvPrimClass (boolean))
+	  *(jboolean*)addr = (jboolean)value;
+	
+	else if (field->type == JvPrimClass (byte))
+	  *(jbyte*)addr = (jbyte)value;
+	
+	else if (field->type == JvPrimClass (char))
+	  *(jchar*)addr = (jchar)value;
 
-	int rtype = cif->rtype->type;
+	else if (field->type == JvPrimClass (short))
+	  *(jshort*)addr = (jshort)value;
+	
+	else if (field->type == JvPrimClass (int))
+	  *(jint*)addr = (jint)value;
 
-	/* the likelyhood of object, int, or void return is very high,
-	 * so those are checked before the switch */
-	if (rtype == FFI_TYPE_POINTER)
-	  {
-	    PUSHA (rvalue.object_value);
-	  }
-	else if (rtype == FFI_TYPE_SINT32)
-	  {
-	    PUSHI (rvalue.int_value);
-	  }
-	else if (rtype == FFI_TYPE_VOID)
-	  {
-	    /* skip */
-	  }
 	else
-	  {
-	    switch (rtype)
-	      {
-	      case FFI_TYPE_SINT8:
-		PUSHI ((jbyte)(rvalue.int_value & 0xff));
-		break;
-
-	      case FFI_TYPE_SINT16:
-		PUSHI ((jshort)(rvalue.int_value & 0xffff));
-		break;
-
-	      case FFI_TYPE_UINT16:
-		PUSHI (rvalue.int_value & 0xffff);
-		break;
+	  throw_class_format_error ("erroneous field initializer");
+      }  
+      break;
 
-	      case FFI_TYPE_FLOAT:
-	        PUSHF (rvalue.float_value);
-		break;
+    case JV_CONSTANT_Long:
+      if (field->type != JvPrimClass (long))
+	throw_class_format_error ("erroneous field initializer");
 
-	      case FFI_TYPE_DOUBLE:
-	        PUSHD (rvalue.double_value);
-		break;
+      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
+      break;
 
-	      case FFI_TYPE_SINT64:
-	        PUSHL (rvalue.long_value);
-		break;
+    case JV_CONSTANT_Float:
+      if (field->type != JvPrimClass (float))
+	throw_class_format_error ("erroneous field initializer");
 
-	      default:
-		throw_internal_error ("unknown return type in invokeXXX");
-	      }
-	  }
-      }
-      NEXT_INSN;
+      *(jfloat*)addr = pool->data[init].f;
+      break;
 
-    insn_aconst_null:
-      PUSHA (NULL);
-      NEXT_INSN;
+    case JV_CONSTANT_Double:
+      if (field->type != JvPrimClass (double))
+	throw_class_format_error ("erroneous field initializer");
 
-    insn_iconst_m1:
-      PUSHI (-1);
-      NEXT_INSN;
+      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
+      break;
 
-    insn_iconst_0:
-      PUSHI (0);
-      NEXT_INSN;
+    default:
+      throw_class_format_error ("erroneous field initializer");
+    }
+}
 
-    insn_iconst_1:
-      PUSHI (1);
-      NEXT_INSN;
+inline static unsigned char*
+skip_one_type (unsigned char* ptr)
+{
+  int ch = *ptr++;
 
-    insn_iconst_2:
-      PUSHI (2);
-      NEXT_INSN;
+  while (ch == '[')
+    { 
+      ch = *ptr++;
+    }
+  
+  if (ch == 'L')
+    {
+      do { ch = *ptr++; } while (ch != ';');
+    }
 
-    insn_iconst_3:
-      PUSHI (3);
-      NEXT_INSN;
+  return ptr;
+}
 
-    insn_iconst_4:
-      PUSHI (4);
-      NEXT_INSN;
+static ffi_type*
+get_ffi_type_from_signature (unsigned char* ptr)
+{
+  switch (*ptr) 
+    {
+    case 'L':
+    case '[':
+      return &ffi_type_pointer;
+      break;
 
-    insn_iconst_5:
-      PUSHI (5);
-      NEXT_INSN;
+    case 'Z':
+      // On some platforms a bool is a byte, on others an int.
+      if (sizeof (jboolean) == sizeof (jbyte))
+	return &ffi_type_sint8;
+      else
+	{
+	  JvAssert (sizeof (jbyte) == sizeof (jint));
+	  return &ffi_type_sint32;
+	}
+      break;
 
-    insn_lconst_0:
-      PUSHL (0);
-      NEXT_INSN;
-
-    insn_lconst_1:
-      PUSHL (1);
-      NEXT_INSN;
-
-    insn_fconst_0:
-      PUSHF (0);
-      NEXT_INSN;
-
-    insn_fconst_1:
-      PUSHF (1);
-      NEXT_INSN;
-
-    insn_fconst_2:
-      PUSHF (2);
-      NEXT_INSN;
-
-    insn_dconst_0:
-      PUSHD (0);
-      NEXT_INSN;
-
-    insn_dconst_1:
-      PUSHD (1);
-      NEXT_INSN;
-
-    insn_bipush:
-      // For direct threaded, bipush and sipush are the same.
-#ifndef DIRECT_THREADED
-      PUSHI (GET1S ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_sipush:
-      PUSHI (GET2S ());
-      NEXT_INSN;
-
-    insn_ldc:
-      // For direct threaded, ldc and ldc_w are the same.
-#ifndef DIRECT_THREADED
-      PUSHA ((jobject) AVAL1U ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_ldc_w:
-      PUSHA ((jobject) AVAL2U ());
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-      // For direct threaded we have a separate 'ldc class' operation.
-    insn_ldc_class:
-      {
-	SAVE_PC();
-	// We could rewrite the instruction at this point.
-	int index = INTVAL ();
-	jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						     index)).o;
-	PUSHA (k);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_ldc2_w:
-      {
-	void *where = AVAL2UP ();
-	memcpy (sp, where, 2*sizeof (_Jv_word));
-	sp += 2;
-      }
-      NEXT_INSN;
-
-    insn_lload:
-      LOADL (GET1U ());
-      NEXT_INSN;
-
-    insn_fload:
-      LOADF (GET1U ());
-      NEXT_INSN;
-
-    insn_dload:
-      LOADD (GET1U ());
-      NEXT_INSN;
-
-    insn_aload:
-      LOADA (GET1U ());
-      NEXT_INSN;
-
-    insn_iload_0:
-      LOADI (0);
-      NEXT_INSN;
-
-    insn_iload_2:
-      LOADI (2);
-      NEXT_INSN;
-
-    insn_iload_3:
-      LOADI (3);
-      NEXT_INSN;
-
-    insn_lload_0:
-      LOADL (0);
-      NEXT_INSN;
-
-    insn_lload_1:
-      LOADL (1);
-      NEXT_INSN;
-
-    insn_lload_2:
-      LOADL (2);
-      NEXT_INSN;
-
-    insn_lload_3:
-      LOADL (3);
-      NEXT_INSN;
-
-    insn_fload_0:
-      LOADF (0);
-      NEXT_INSN;
-
-    insn_fload_1:
-      LOADF (1);
-      NEXT_INSN;
-
-    insn_fload_2:
-      LOADF (2);
-      NEXT_INSN;
-
-    insn_fload_3:
-      LOADF (3);
-      NEXT_INSN;
-
-    insn_dload_0:
-      LOADD (0);
-      NEXT_INSN;
-
-    insn_dload_1:
-      LOADD (1);
-      NEXT_INSN;
-
-    insn_dload_2:
-      LOADD (2);
-      NEXT_INSN;
-
-    insn_dload_3:
-      LOADD (3);
-      NEXT_INSN;
-
-    insn_aload_1:
-      LOADA(1);
-      NEXT_INSN;
-
-    insn_aload_2:
-      LOADA(2);
-      NEXT_INSN;
-
-    insn_aload_3:
-      LOADA(3);
-      NEXT_INSN;
-
-    insn_iaload:
-      {
-	jint index = POPI();
-	jintArray arr = (jintArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_laload:
-      {
-	jint index = POPI();
-	jlongArray arr = (jlongArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHL( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_faload:
-      {
-	jint index = POPI();
-	jfloatArray arr = (jfloatArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHF( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_daload:
-      {
-	jint index = POPI();
-	jdoubleArray arr = (jdoubleArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHD( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_aaload:
-      {
-	jint index = POPI();
-	jobjectArray arr = (jobjectArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHA( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_baload:
-      {
-	jint index = POPI();
-	jbyteArray arr = (jbyteArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_caload:
-      {
-	jint index = POPI();
-	jcharArray arr = (jcharArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_saload:
-      {
-	jint index = POPI();
-	jshortArray arr = (jshortArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_istore:
-      STOREI (GET1U ());
-      NEXT_INSN;
-
-    insn_lstore:
-      STOREL (GET1U ());
-      NEXT_INSN;
-
-    insn_fstore:
-      STOREF (GET1U ());
-      NEXT_INSN;
-
-    insn_dstore:
-      STORED (GET1U ());
-      NEXT_INSN;
-
-    insn_astore:
-      STOREA (GET1U ());
-      NEXT_INSN;
-
-    insn_istore_0:
-      STOREI (0);
-      NEXT_INSN;
-
-    insn_istore_1:
-      STOREI (1);
-      NEXT_INSN;
-
-    insn_istore_2:
-      STOREI (2);
-      NEXT_INSN;
-
-    insn_istore_3:
-      STOREI (3);
-      NEXT_INSN;
-
-    insn_lstore_0:
-      STOREL (0);
-      NEXT_INSN;
-
-    insn_lstore_1:
-      STOREL (1);
-      NEXT_INSN;
-
-    insn_lstore_2:
-      STOREL (2);
-      NEXT_INSN;
-
-    insn_lstore_3:
-      STOREL (3);
-      NEXT_INSN;
-
-    insn_fstore_0:
-      STOREF (0);
-      NEXT_INSN;
-
-    insn_fstore_1:
-      STOREF (1);
-      NEXT_INSN;
-
-    insn_fstore_2:
-      STOREF (2);
-      NEXT_INSN;
-
-    insn_fstore_3:
-      STOREF (3);
-      NEXT_INSN;
-
-    insn_dstore_0:
-      STORED (0);
-      NEXT_INSN;
-
-    insn_dstore_1:
-      STORED (1);
-      NEXT_INSN;
-
-    insn_dstore_2:
-      STORED (2);
-      NEXT_INSN;
-
-    insn_dstore_3:
-      STORED (3);
-      NEXT_INSN;
-
-    insn_astore_0:
-      STOREA(0);
-      NEXT_INSN;
-
-    insn_astore_1:
-      STOREA(1);
-      NEXT_INSN;
-
-    insn_astore_2:
-      STOREA(2);
-      NEXT_INSN;
-
-    insn_astore_3:
-      STOREA(3);
-      NEXT_INSN;
-
-    insn_iastore:
-      {
-	jint value = POPI();
-	jint index  = POPI();
-	jintArray arr = (jintArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_lastore:
-      {
-	jlong value = POPL();
-	jint index  = POPI();
-	jlongArray arr = (jlongArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_fastore:
-      {
-	jfloat value = POPF();
-	jint index  = POPI();
-	jfloatArray arr = (jfloatArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_dastore:
-      {
-	jdouble value = POPD();
-	jint index  = POPI();
-	jdoubleArray arr = (jdoubleArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_aastore:
-      {
-	jobject value = POPA();
-	jint index  = POPI();
-	jobjectArray arr = (jobjectArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	_Jv_CheckArrayStore (arr, value);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_bastore:
-      {
-	jbyte value = (jbyte) POPI();
-	jint index  = POPI();
-	jbyteArray arr = (jbyteArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_castore:
-      {
-	jchar value = (jchar) POPI();
-	jint index  = POPI();
-	jcharArray arr = (jcharArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_sastore:
-      {
-	jshort value = (jshort) POPI();
-	jint index  = POPI();
-	jshortArray arr = (jshortArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_pop:
-      sp -= 1;
-      NEXT_INSN;
-
-    insn_pop2:
-      sp -= 2;
-      NEXT_INSN;
-
-    insn_dup:
-      sp[0] = sp[-1];
-      sp += 1;
-      NEXT_INSN;
-
-    insn_dup_x1:
-      dupx (sp, 1, 1); sp+=1;
-      NEXT_INSN;
-
-    insn_dup_x2:
-      dupx (sp, 1, 2); sp+=1;
-      NEXT_INSN;
-
-    insn_dup2:
-      sp[0] = sp[-2];
-      sp[1] = sp[-1];
-      sp += 2;
-      NEXT_INSN;
-
-    insn_dup2_x1:
-      dupx (sp, 2, 1); sp+=2;
-      NEXT_INSN;
-
-    insn_dup2_x2:
-      dupx (sp, 2, 2); sp+=2;
-      NEXT_INSN;
-
-    insn_swap:
-      {
-	jobject tmp1 = POPA();
-	jobject tmp2 = POPA();
-	PUSHA (tmp1);
-	PUSHA (tmp2);
-      }
-      NEXT_INSN;
-
-    insn_iadd:
-      BINOPI(+);
-      NEXT_INSN;
-
-    insn_ladd:
-      BINOPL(+);
-      NEXT_INSN;
-
-    insn_fadd:
-      BINOPF(+);
-      NEXT_INSN;
-
-    insn_dadd:
-      BINOPD(+);
-      NEXT_INSN;
-
-    insn_isub:
-      BINOPI(-);
-      NEXT_INSN;
-
-    insn_lsub:
-      BINOPL(-);
-      NEXT_INSN;
-
-    insn_fsub:
-      BINOPF(-);
-      NEXT_INSN;
-
-    insn_dsub:
-      BINOPD(-);
-      NEXT_INSN;
-
-    insn_imul:
-      BINOPI(*);
-      NEXT_INSN;
-
-    insn_lmul:
-      BINOPL(*);
-      NEXT_INSN;
-
-    insn_fmul:
-      BINOPF(*);
-      NEXT_INSN;
-
-    insn_dmul:
-      BINOPD(*);
-      NEXT_INSN;
-
-    insn_idiv:
-      {
-	SAVE_PC();
-	jint value2 = POPI();
-	jint value1 = POPI();
-	jint res = _Jv_divI (value1, value2);
-	PUSHI (res);
-      }
-      NEXT_INSN;
-
-    insn_ldiv:
-      {
-	SAVE_PC();
-	jlong value2 = POPL();
-	jlong value1 = POPL();
-	jlong res = _Jv_divJ (value1, value2);
-	PUSHL (res);
-      }
-      NEXT_INSN;
-
-    insn_fdiv:
-      {
-	jfloat value2 = POPF();
-	jfloat value1 = POPF();
-	jfloat res = value1 / value2;
-	PUSHF (res);
-      }
-      NEXT_INSN;
-
-    insn_ddiv:
-      {
-	jdouble value2 = POPD();
-	jdouble value1 = POPD();
-	jdouble res = value1 / value2;
-	PUSHD (res);
-      }
-      NEXT_INSN;
-
-    insn_irem:
-      {
-	SAVE_PC();
-	jint value2 = POPI();
-	jint value1 =  POPI();
-	jint res = _Jv_remI (value1, value2);
-	PUSHI (res);
-      }
-      NEXT_INSN;
-
-    insn_lrem:
-      {
-	SAVE_PC();
-	jlong value2 = POPL();
-	jlong value1 = POPL();
-	jlong res = _Jv_remJ (value1, value2);
-	PUSHL (res);
-      }
-      NEXT_INSN;
-
-    insn_frem:
-      {
-	jfloat value2 = POPF();
-	jfloat value1 = POPF();
-	jfloat res    = __ieee754_fmod (value1, value2);
-	PUSHF (res);
-      }
-      NEXT_INSN;
-
-    insn_drem:
-      {
-	jdouble value2 = POPD();
-	jdouble value1 = POPD();
-	jdouble res    = __ieee754_fmod (value1, value2);
-	PUSHD (res);
-      }
-      NEXT_INSN;
-
-    insn_ineg:
-      {
-	jint value = POPI();
-	PUSHI (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_lneg:
-      {
-	jlong value = POPL();
-	PUSHL (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_fneg:
-      {
-	jfloat value = POPF();
-	PUSHF (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_dneg:
-      {
-	jdouble value = POPD();
-	PUSHD (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_ishl:
-      {
-	jint shift = (POPI() & 0x1f);
-	jint value = POPI();
-	PUSHI (value << shift);
-      }
-      NEXT_INSN;
-
-    insn_lshl:
-      {
-	jint shift = (POPI() & 0x3f);
-	jlong value = POPL();
-	PUSHL (value << shift);
-      }
-      NEXT_INSN;
-
-    insn_ishr:
-      {
-	jint shift = (POPI() & 0x1f);
-	jint value = POPI();
-	PUSHI (value >> shift);
-      }
-      NEXT_INSN;
-
-    insn_lshr:
-      {
-	jint shift = (POPI() & 0x3f);
-	jlong value = POPL();
-	PUSHL (value >> shift);
-      }
-      NEXT_INSN;
-
-    insn_iushr:
-      {
-	jint shift = (POPI() & 0x1f);
-	_Jv_uint value = (_Jv_uint) POPI();
-	PUSHI ((jint) (value >> shift));
-      }
-      NEXT_INSN;
-
-    insn_lushr:
-      {
-	jint shift = (POPI() & 0x3f);
-	_Jv_ulong value = (_Jv_ulong) POPL();
-	PUSHL ((jlong) (value >> shift));
-      }
-      NEXT_INSN;
-
-    insn_iand:
-      BINOPI (&);
-      NEXT_INSN;
-
-    insn_land:
-      BINOPL (&);
-      NEXT_INSN;
-
-    insn_ior:
-      BINOPI (|);
-      NEXT_INSN;
-
-    insn_lor:
-      BINOPL (|);
-      NEXT_INSN;
-
-    insn_ixor:
-      BINOPI (^);
-      NEXT_INSN;
-
-    insn_lxor:
-      BINOPL (^);
-      NEXT_INSN;
-
-    insn_iinc:
-      {
-	jint index  = GET1U ();
-	jint amount = GET1S ();
-	locals[index].i += amount;
-      }
-      NEXT_INSN;
-
-    insn_i2l:
-      {jlong value = POPI(); PUSHL (value);}
-      NEXT_INSN;
-
-    insn_i2f:
-      {jfloat value = POPI(); PUSHF (value);}
-      NEXT_INSN;
-
-    insn_i2d:
-      {jdouble value = POPI(); PUSHD (value);}
-      NEXT_INSN;
-
-    insn_l2i:
-      {jint value = POPL(); PUSHI (value);}
-      NEXT_INSN;
-
-    insn_l2f:
-      {jfloat value = POPL(); PUSHF (value);}
-      NEXT_INSN;
-
-    insn_l2d:
-      {jdouble value = POPL(); PUSHD (value);}
-      NEXT_INSN;
-
-    insn_f2i:
-      {
-	using namespace java::lang;
-	jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
-	PUSHI(value);
-      }
-      NEXT_INSN;
-
-    insn_f2l:
-      {
-	using namespace java::lang;
-	jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
-	PUSHL(value);
-      }
-      NEXT_INSN;
-
-    insn_f2d:
-      { jdouble value = POPF (); PUSHD(value); }
-      NEXT_INSN;
-
-    insn_d2i:
-      {
-	using namespace java::lang;
-	jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
-	PUSHI(value);
-      }
-      NEXT_INSN;
-
-    insn_d2l:
-      {
-	using namespace java::lang;
-	jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
-	PUSHL(value);
-      }
-      NEXT_INSN;
-
-    insn_d2f:
-      { jfloat value = POPD (); PUSHF(value); }
-      NEXT_INSN;
-
-    insn_i2b:
-      { jbyte value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_i2c:
-      { jchar value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_i2s:
-      { jshort value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_lcmp:
-      {
-	jlong value2 = POPL ();
-	jlong value1 = POPL ();
-	if (value1 > value2)
-	  { PUSHI (1); }
-	else if (value1 == value2)
-	  { PUSHI (0); }
-	else
-	  { PUSHI (-1); }
-      }
-      NEXT_INSN;
-
-    insn_fcmpl:
-      tmpval = -1;
-      goto fcmp;
-
-    insn_fcmpg:
-      tmpval = 1;
-
-    fcmp:
-      {
-	jfloat value2 = POPF ();
-	jfloat value1 = POPF ();
-	if (value1 > value2)
-	  PUSHI (1);
-	else if (value1 == value2)
-	  PUSHI (0);
-	else if (value1 < value2)
-	  PUSHI (-1);
-	else
-	  PUSHI (tmpval);
-      }
-      NEXT_INSN;
-
-    insn_dcmpl:
-      tmpval = -1;
-      goto dcmp;
-
-    insn_dcmpg:
-      tmpval = 1;
-
-    dcmp:
-      {
-	jdouble value2 = POPD ();
-	jdouble value1 = POPD ();
-	if (value1 > value2)
-	  PUSHI (1);
-	else if (value1 == value2)
-	  PUSHI (0);
-	else if (value1 < value2)
-	  PUSHI (-1);
-	else
-	  PUSHI (tmpval);
-      }
-      NEXT_INSN;
-
-    insn_ifeq:
-      {
-	if (POPI() == 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifne:
-      {
-	if (POPI() != 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_iflt:
-      {
-	if (POPI() < 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifge:
-      {
-	if (POPI() >= 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifgt:
-      {
-	if (POPI() > 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifle:
-      {
-	if (POPI() <= 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpeq:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 == value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpne:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 != value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmplt:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 < value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpge:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 >= value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpgt:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 > value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmple:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 <= value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_acmpeq:
-      {
-	jobject value2 = POPA();
-	jobject value1 = POPA();
-	if (value1 == value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_acmpne:
-      {
-	jobject value2 = POPA();
-	jobject value1 = POPA();
-	if (value1 != value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_goto_w:
-#ifndef DIRECT_THREADED
-      // For direct threaded, goto and goto_w are the same.
-      pc = pc - 1 + get4 (pc);
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_goto:
-      TAKE_GOTO;
-      NEXT_INSN;
-
-    insn_jsr_w:
-#ifndef DIRECT_THREADED
-      // For direct threaded, jsr and jsr_w are the same.
-      {
-	pc_t next = pc - 1 + get4 (pc);
-	pc += 4;
-	PUSHA ((jobject) pc);
-	pc = next;
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_jsr:
-      {
-	pc_t next = GOTO_VAL();
-	SKIP_GOTO;
-	PUSHA ((jobject) pc);
-	pc = next;
-      }
-      NEXT_INSN;
-
-    insn_ret:
-      {
-	jint index = GET1U ();
-	pc = (pc_t) PEEKA (index);
-      }
-      NEXT_INSN;
-
-    insn_tableswitch:
-      {
-#ifdef DIRECT_THREADED
-	void *def = (pc++)->datum;
-
-	int index = POPI();
-
-	jint low = INTVAL ();
-	jint high = INTVAL ();
-
-	if (index < low || index > high)
-	  pc = (insn_slot *) def;
-	else
-	  pc = (insn_slot *) ((pc + index - low)->datum);
-#else
-	pc_t base_pc = pc - 1;
-	int index = POPI ();
-
-	pc_t base = (pc_t) bytecode ();
-	while ((pc - base) % 4 != 0)
-	  ++pc;
-
-	jint def = get4 (pc);
-	jint low = get4 (pc + 4);
-	jint high = get4 (pc + 8);
-	if (index < low || index > high)
-	  pc = base_pc + def;
-	else
-	  pc = base_pc + get4 (pc + 4 * (index - low + 3));
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-    insn_lookupswitch:
-      {
-#ifdef DIRECT_THREADED
-	void *def = (pc++)->insn;
-
-	int index = POPI();
-
-	jint npairs = INTVAL ();
-
-	int max = npairs - 1;
-	int min = 0;
-
-	// Simple binary search...
-	while (min < max)
-	  {
-	    int half = (min + max) / 2;
-	    int match = pc[2 * half].int_val;
-
-	    if (index == match)
-	      {
-		// Found it.
-		pc = (insn_slot *) pc[2 * half + 1].datum;
-		NEXT_INSN;
-	      }
-	    else if (index < match)
-	      // We can use HALF - 1 here because we check again on
-	      // loop exit.
-	      max = half - 1;
-	    else
-	      // We can use HALF + 1 here because we check again on
-	      // loop exit.
-	      min = half + 1;
-	  }
-	if (index == pc[2 * min].int_val)
-	  pc = (insn_slot *) pc[2 * min + 1].datum;
-	else
-	  pc = (insn_slot *) def;
-#else
-	unsigned char *base_pc = pc-1;
-	int index = POPI();
-
-	unsigned char* base = bytecode ();
-	while ((pc-base) % 4 != 0)
-	  ++pc;
-
-	jint def     = get4 (pc);
-	jint npairs  = get4 (pc+4);
-
-	int max = npairs-1;
-	int min = 0;
-
-	// Simple binary search...
-	while (min < max)
-	  {
-	    int half = (min+max)/2;
-	    int match = get4 (pc+ 4*(2 + 2*half));
-
-	    if (index == match)
-	      min = max = half;
-	    else if (index < match)
-	      // We can use HALF - 1 here because we check again on
-	      // loop exit.
-	      max = half - 1;
-	    else
-	      // We can use HALF + 1 here because we check again on
-	      // loop exit.
-	      min = half + 1;
-	  }
-
-	if (index == get4 (pc+ 4*(2 + 2*min)))
-	  pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
-	else
-	  pc = base_pc + def;    
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-    insn_areturn:
-      *(jobject *) retp = POPA ();
-      return;
-
-    insn_lreturn:
-      *(jlong *) retp = POPL ();
-      return;
-
-    insn_freturn:
-      *(jfloat *) retp = POPF ();
-      return;
-
-    insn_dreturn:
-      *(jdouble *) retp = POPD ();
-      return;
-
-    insn_ireturn:
-      *(jint *) retp = POPI ();
-      return;
-
-    insn_return:
-      return;
-
-    insn_getstatic:
-      {
-	jint fieldref_index = GET2U ();
-        SAVE_PC(); // Constant pool resolution could throw.
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	if ((field->flags & Modifier::STATIC) == 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field no longer static"));
-
-	jclass type = field->type;
-
-	// We rewrite the instruction once we discover what it refers
-	// to.
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes)
-	      {
-	      case 1:
-		PUSHI (*field->u.byte_addr);
-		newinsn = AMPAMP (getstatic_resolved_1);
-		break;
-
-	      case 2:
-		if (type == JvPrimClass (char))
-		  {
-		    PUSHI (*field->u.char_addr);
-		    newinsn = AMPAMP (getstatic_resolved_char);
-		  }
-		else
-		  {
-		    PUSHI (*field->u.short_addr);
-		    newinsn = AMPAMP (getstatic_resolved_short);
-		  }
-		break;
-
-	      case 4:
-	        PUSHI(*field->u.int_addr);
-		newinsn = AMPAMP (getstatic_resolved_4);
-		break;
-
-	      case 8:
-	        PUSHL(*field->u.long_addr);
-		newinsn = AMPAMP (getstatic_resolved_8);
-		break;
-	      }
-	  }
-	else
-	  {
-	    PUSHA(*field->u.object_addr);
-	    newinsn = AMPAMP (getstatic_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].datum = field->u.addr;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    getstatic_resolved_1:
-      PUSHI (*(jbyte *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_char:
-      PUSHI (*(jchar *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_short:
-      PUSHI (*(jshort *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_4:
-      PUSHI (*(jint *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_8:
-      PUSHL (*(jlong *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_obj:
-      PUSHA (*(jobject *) AVAL ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_getfield:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	if ((field->flags & Modifier::STATIC) != 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field is static"));
-
-	jclass type = field->type;
-	jint field_offset = field->u.boffset;
-
-	jobject obj   = POPA();
-	NULLCHECK(obj);
-
-	void *newinsn = NULL;
-	_Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes)
-	      {
-	      case 1:
-	        PUSHI (val->byte_value);
-		newinsn = AMPAMP (getfield_resolved_1);
-		break;
-
-	      case 2:
-		if (type == JvPrimClass (char))
-		  {
-		    PUSHI (val->char_value);
-		    newinsn = AMPAMP (getfield_resolved_char);
-		  }
-		else
-		  {
-		    PUSHI (val->short_value);
-		    newinsn = AMPAMP (getfield_resolved_short);
-		  }
-		break;
-
-	      case 4:
-		PUSHI (val->int_value);
-		newinsn = AMPAMP (getfield_resolved_4);
-		break;
-
-	      case 8:
-	        PUSHL (val->long_value);
-		newinsn = AMPAMP (getfield_resolved_8);
-		break;
-	      }
-	  }
-	else
-	  {
-	    PUSHA (val->object_value);
-	    newinsn = AMPAMP (getfield_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].int_val = field_offset;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    getfield_resolved_1:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jbyte *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_char:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jchar *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_short:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jshort *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_4:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jint *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_8:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHL (*(jlong *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_obj:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHA (*(jobject *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_putstatic:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	jclass type = field->type;
-
-	// ResolvePoolEntry cannot check this
-	if ((field->flags & Modifier::STATIC) == 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field no longer static"));
-
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes) 
-	      {
-	      case 1:
-		{
-		  jint value = POPI();
-		  *field->u.byte_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_1);
-		  break;
-		}
-
-	      case 2:
-		{
-		  jint value = POPI();
-		  *field->u.char_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_2);
-		  break;
-		}
-
-	      case 4:
-		{
-		  jint value = POPI();
-		  *field->u.int_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_4);
-		  break;
-		}
-
-	      case 8:
-		{
-		  jlong value = POPL();
-		  *field->u.long_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_8);
-		  break;
-		}
-	      }
-	  }
-	else
-	  {
-	    jobject value = POPA();
-	    *field->u.object_addr = value;
-	    newinsn = AMPAMP (putstatic_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].datum = field->u.addr;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    putstatic_resolved_1:
-      *(jbyte *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_2:
-      *(jchar *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_4:
-      *(jint *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_8:
-      *(jlong *) AVAL () = POPL ();
-      NEXT_INSN;
-
-    putstatic_resolved_obj:
-      *(jobject *) AVAL () = POPA ();
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_putfield:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	jclass type = field->type;
-
-	if ((field->flags & Modifier::STATIC) != 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field is static"));
-
-	jint field_offset = field->u.boffset;
-
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes) 
-	      {
-	      case 1:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jbyte*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_1);
-		  break;
-		}
-
-	      case 2:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jchar*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_2);
-		  break;
-		}
-
-	      case 4:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jint*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_4);
-		  break;
-		}
-
-	      case 8:
-		{
-		  jlong   value = POPL();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jlong*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_8);
-		  break;
-		}
-	      }
-	  }
-	else
-	  {
-	    jobject value = POPA();
-	    jobject obj   = POPA();
-	    NULLCHECK(obj);
-	    *(jobject*) ((char*)obj + field_offset) = value;
-	    newinsn = AMPAMP (putfield_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].int_val = field_offset;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    putfield_resolved_1:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jbyte *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_2:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jchar *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_4:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jint *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_8:
-      {
-	jlong val = POPL ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jlong *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_obj:
-      {
-	jobject val = POPA ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jobject *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_invokespecial:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	// We don't use NULLCHECK here because we can't rely on that
-	// working for <init>.  So instead we do an explicit test.
-	if (! sp[0].o)
-	  {
-	    SAVE_PC();
-	    throw_null_pointer_exception ();
-	  }
-
-	fun = (void (*)()) rmeth->method->ncode;
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokespecial_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokespecial_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	// We don't use NULLCHECK here because we can't rely on that
-	// working for <init>.  So instead we do an explicit test.
-	if (! sp[0].o)
-	  {
-	    throw_null_pointer_exception ();
-	  }
-	fun = (void (*)()) rmeth->method->ncode;
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_invokestatic:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	fun = (void (*)()) rmeth->method->ncode;
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokestatic_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokestatic_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	fun = (void (*)()) rmeth->method->ncode;
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_invokeinterface:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	jobject rcv = sp[0].o;
-
-	NULLCHECK (rcv);
-
-	fun = (void (*)())
-	  _Jv_LookupInterfaceMethod (rcv->getClass (),
-				     rmeth->method->name,
-				     rmeth->method->signature);
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokeinterface_resolved;
-	pc[-1].datum = rmeth;
-#else
-	// Skip dummy bytes.
-	pc += 2;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokeinterface_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	jobject rcv = sp[0].o;
-	NULLCHECK (rcv);
-	fun = (void (*)())
-	  _Jv_LookupInterfaceMethod (rcv->getClass (),
-				     rmeth->method->name,
-				     rmeth->method->signature);
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_new:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-							  index)).clazz;
-	/* VM spec, section 3.11.5 */
-	if ((klass->getModifiers() & Modifier::ABSTRACT)
-	    || klass->isInterface())
-	  throw new java::lang::InstantiationException;
-	jobject res = _Jv_AllocObject (klass);
-	PUSHA (res);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&new_resolved;
-	pc[-1].datum = klass;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    new_resolved:
-      {
-	jclass klass = (jclass) AVAL ();
-	jobject res = _Jv_AllocObject (klass);
-	PUSHA (res);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_newarray:
-      {
-	int atype = GET1U ();
-	int size  = POPI();
-	jobject result = _Jv_NewArray (atype, size);
-	PUSHA (result);
-      }
-      NEXT_INSN;
-
-    insn_anewarray:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-							  index)).clazz;
-	int size  = POPI();
-	jobject result = _Jv_NewObjectArray (size, klass, 0);
-	PUSHA (result);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&anewarray_resolved;
-	pc[-1].datum = klass;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    anewarray_resolved:
-      {
-	jclass klass = (jclass) AVAL ();
-	int size = POPI ();
-	jobject result = _Jv_NewObjectArray (size, klass, 0);
-	PUSHA (result);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_arraylength:
-      {
-	__JArray *arr = (__JArray*)POPA();
-	NULLARRAYCHECK (arr);
-	PUSHI (arr->length);
-      }
-      NEXT_INSN;
-
-    insn_athrow:
-      {
-	jobject value = POPA();
-	throw static_cast<jthrowable>(value);
-      }
-      NEXT_INSN;
-
-    insn_checkcast:
-      {
-        SAVE_PC();
-	jobject value = POPA();
-	jint index = GET2U ();
-	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						       index)).clazz;
-
-	value = (jobject) _Jv_CheckCast (to, value);
-
-	PUSHA (value);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&checkcast_resolved;
-	pc[-1].datum = to;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    checkcast_resolved:
-      {
-        SAVE_PC();
-	jobject value = POPA ();
-	jclass to = (jclass) AVAL ();
-	value = (jobject) _Jv_CheckCast (to, value);
-	PUSHA (value);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_instanceof:
-      {
-        SAVE_PC();
-	jobject value = POPA();
-	jint index = GET2U ();
-	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						       index)).clazz;
-	PUSHI (to->isInstance (value));
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&instanceof_resolved;
-	pc[-1].datum = to;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    instanceof_resolved:
-      {
-	jobject value = POPA ();
-	jclass to = (jclass) AVAL ();
-	PUSHI (to->isInstance (value));
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_monitorenter:
-      {
-	jobject value = POPA();
-	NULLCHECK(value);
-	_Jv_MonitorEnter (value);
-      }
-      NEXT_INSN;
-
-    insn_monitorexit:
-      {
-	jobject value = POPA();
-	NULLCHECK(value);
-	_Jv_MonitorExit (value);
-      }
-      NEXT_INSN;
-
-    insn_ifnull:
-      {
-	jobject val = POPA();
-	if (val == NULL)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifnonnull:
-      {
-	jobject val = POPA();
-	if (val != NULL)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_multianewarray:
-      {
-	SAVE_PC();
-	int kind_index = GET2U ();
-	int dim        = GET1U ();
-
-	jclass type    
-	  = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-					       kind_index)).clazz;
-	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
-
-	for (int i = dim - 1; i >= 0; i--)
-	  {
-	    sizes[i] = POPI ();
-	  }
-
-	jobject res    = _Jv_NewMultiArray (type,dim, sizes);
-
-	PUSHA (res);
-      }
-      NEXT_INSN;
-
-#ifndef DIRECT_THREADED
-    insn_wide:
-      {
-	jint the_mod_op = get1u (pc++);
-	jint wide       = get2u (pc); pc += 2;
-
-	switch (the_mod_op)
-	  {
-	  case op_istore:
-	    STOREI (wide);
-	    NEXT_INSN;
-
-	  case op_fstore:
-	    STOREF (wide);
-	    NEXT_INSN;
-
-	  case op_astore:
-	    STOREA (wide);
-	    NEXT_INSN;
-
-	  case op_lload:
-	    LOADL (wide);
-	    NEXT_INSN;
-
-	  case op_dload:
-	    LOADD (wide);
-	    NEXT_INSN;
-
-	  case op_iload:
-	    LOADI (wide);
-	    NEXT_INSN;
-
-	  case op_fload:
-	    LOADF (wide);
-	    NEXT_INSN;
-
-	  case op_aload:
-	    LOADA (wide);
-	    NEXT_INSN;
-
-	  case op_lstore:
-	    STOREL (wide);
-	    NEXT_INSN;
-
-	  case op_dstore:
-	    STORED (wide);
-	    NEXT_INSN;
-
-	  case op_ret:
-	    pc = (unsigned char*) PEEKA (wide);
-	    NEXT_INSN;
-
-	  case op_iinc:
-	    {
-	      jint amount = get2s (pc); pc += 2;
-	      jint value = PEEKI (wide);
-	      POKEI (wide, value+amount);
-	    }
-	    NEXT_INSN;
-
-	  default:
-	    throw_internal_error ("illegal bytecode modified by wide");
-	  }
-
-      }
-#endif /* DIRECT_THREADED */
-    }
-  catch (java::lang::Throwable *ex)
-    {
-#ifdef DIRECT_THREADED
-      void *logical_pc = (void *) ((insn_slot *) pc - 1);
-#else
-      int logical_pc = pc - 1 - bytecode ();
-#endif
-      _Jv_InterpException *exc = meth->exceptions ();
-      jclass exc_class = ex->getClass ();
-
-      for (int i = 0; i < meth->exc_count; i++)
-	{
-	  if (PCVAL (exc[i].start_pc) <= logical_pc
-	      && logical_pc < PCVAL (exc[i].end_pc))
-	    {
-#ifdef DIRECT_THREADED
-	      jclass handler = (jclass) exc[i].handler_type.p;
-#else
-	      jclass handler = NULL;
-	      if (exc[i].handler_type.i != 0)
-		handler = (_Jv_Linker::resolve_pool_entry (defining_class,
-							     exc[i].handler_type.i)).clazz;
-#endif /* DIRECT_THREADED */
-
-	      if (handler == NULL || handler->isAssignableFrom (exc_class))
-		{
-#ifdef DIRECT_THREADED
-		  pc = (insn_slot *) exc[i].handler_pc.p;
-#else
-		  pc = bytecode () + exc[i].handler_pc.i;
-#endif /* DIRECT_THREADED */
-		  sp = stack;
-		  sp++->o = ex; // Push exception.
-		  NEXT_INSN;
-		}
-	    }
-	}
-
-      // No handler, so re-throw.
-      throw ex;
-    }
-}
-
-static void
-throw_internal_error (const char *msg)
-{
-  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
-}
-
-static void 
-throw_incompatible_class_change_error (jstring msg)
-{
-  throw new java::lang::IncompatibleClassChangeError (msg);
-}
-
-static void 
-throw_null_pointer_exception ()
-{
-  throw new java::lang::NullPointerException;
-}
-
-/* Look up source code line number for given bytecode (or direct threaded
-   interpreter) PC. */
-int
-_Jv_InterpMethod::get_source_line(pc_t mpc)
-{
-  int line = line_table_len > 0 ? line_table[0].line : -1;
-  for (int i = 1; i < line_table_len; i++)
-    if (line_table[i].pc > mpc)
-      break;
-    else
-      line = line_table[i].line;
-
-  return line;
-}
-
-/** Do static initialization for fields with a constant initializer */
-void
-_Jv_InitField (jobject obj, jclass klass, int index)
-{
-  using namespace java::lang::reflect;
-
-  if (obj != 0 && klass == 0)
-    klass = obj->getClass ();
-
-  if (!_Jv_IsInterpretedClass (klass))
-    return;
-
-  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
-
-  _Jv_Field * field = (&klass->fields[0]) + index;
-
-  if (index > klass->field_count)
-    throw_internal_error ("field out of range");
-
-  int init = iclass->field_initializers[index];
-  if (init == 0)
-    return;
-
-  _Jv_Constants *pool = &klass->constants;
-  int tag = pool->tags[init];
-
-  if (! field->isResolved ())
-    throw_internal_error ("initializing unresolved field");
-
-  if (obj==0 && ((field->flags & Modifier::STATIC) == 0))
-    throw_internal_error ("initializing non-static field with no object");
-
-  void *addr = 0;
-
-  if ((field->flags & Modifier::STATIC) != 0)
-    addr = (void*) field->u.addr;
-  else
-    addr = (void*) (((char*)obj) + field->u.boffset);
-
-  switch (tag)
-    {
-    case JV_CONSTANT_String:
-      {
-	jstring str;
-	str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
-	pool->data[init].string = str;
-	pool->tags[init] = JV_CONSTANT_ResolvedString;
-      }
-      /* fall through */
-
-    case JV_CONSTANT_ResolvedString:
-      if (! (field->type == &java::lang::String::class$
- 	     || field->type == &java::lang::Class::class$))
-	throw_class_format_error ("string initialiser to non-string field");
-
-      *(jstring*)addr = pool->data[init].string;
-      break;
-
-    case JV_CONSTANT_Integer:
-      {
-	int value = pool->data[init].i;
-
-	if (field->type == JvPrimClass (boolean))
-	  *(jboolean*)addr = (jboolean)value;
-	
-	else if (field->type == JvPrimClass (byte))
-	  *(jbyte*)addr = (jbyte)value;
-	
-	else if (field->type == JvPrimClass (char))
-	  *(jchar*)addr = (jchar)value;
-
-	else if (field->type == JvPrimClass (short))
-	  *(jshort*)addr = (jshort)value;
-	
-	else if (field->type == JvPrimClass (int))
-	  *(jint*)addr = (jint)value;
-
-	else
-	  throw_class_format_error ("erroneous field initializer");
-      }  
-      break;
-
-    case JV_CONSTANT_Long:
-      if (field->type != JvPrimClass (long))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
-      break;
-
-    case JV_CONSTANT_Float:
-      if (field->type != JvPrimClass (float))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jfloat*)addr = pool->data[init].f;
-      break;
-
-    case JV_CONSTANT_Double:
-      if (field->type != JvPrimClass (double))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
-      break;
-
-    default:
-      throw_class_format_error ("erroneous field initializer");
-    }
-}
-
-inline static unsigned char*
-skip_one_type (unsigned char* ptr)
-{
-  int ch = *ptr++;
-
-  while (ch == '[')
-    { 
-      ch = *ptr++;
-    }
-  
-  if (ch == 'L')
-    {
-      do { ch = *ptr++; } while (ch != ';');
-    }
-
-  return ptr;
-}
-
-static ffi_type*
-get_ffi_type_from_signature (unsigned char* ptr)
-{
-  switch (*ptr) 
-    {
-    case 'L':
-    case '[':
-      return &ffi_type_pointer;
-      break;
-
-    case 'Z':
-      // On some platforms a bool is a byte, on others an int.
-      if (sizeof (jboolean) == sizeof (jbyte))
-	return &ffi_type_sint8;
-      else
-	{
-	  JvAssert (sizeof (jbyte) == sizeof (jint));
-	  return &ffi_type_sint32;
-	}
-      break;
-
-    case 'B':
-      return &ffi_type_sint8;
-      break;
-      
-    case 'C':
-      return &ffi_type_uint16;
-      break;
-	  
-    case 'S': 
-      return &ffi_type_sint16;
-      break;
-	  
-    case 'I':
-      return &ffi_type_sint32;
-      break;
-	  
-    case 'J':
-      return &ffi_type_sint64;
-      break;
-	  
-    case 'F':
-      return &ffi_type_float;
-      break;
-	  
-    case 'D':
-      return &ffi_type_double;
-      break;
+    case 'B':
+      return &ffi_type_sint8;
+      break;
+      
+    case 'C':
+      return &ffi_type_uint16;
+      break;
+	  
+    case 'S': 
+      return &ffi_type_sint16;
+      break;
+	  
+    case 'I':
+      return &ffi_type_sint32;
+      break;
+	  
+    case 'J':
+      return &ffi_type_sint64;
+      break;
+	  
+    case 'F':
+      return &ffi_type_float;
+      break;
+	  
+    case 'D':
+      return &ffi_type_double;
+      break;
 
     case 'V':
       return &ffi_type_void;
@@ -3654,9 +1256,19 @@
   if ((self->accflags & Modifier::SYNCHRONIZED) != 0)
     {
       if (staticp)
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
+        {
+        if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		  fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class_debug;
+		else
+		  fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
+        }
       else
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object; 
+        {
+	      if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object_debug;
+		  else
+		  	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object;
+        } 
     }
   else
     {
@@ -3661,9 +1273,19 @@
   else
     {
       if (staticp)
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
+        {
+	      if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class_debug;
+		  else
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
+        }
       else
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+        {
+	      if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal_debug;
+		  else
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+        }
     }
 
   FFI_PREP_RAW_CLOSURE (&closure->closure,
Index: stacktrace.cc
===================================================================
--- /home/kgallowa/work/gcc/libjava/stacktrace.cc	(revision 115873)
+++ /home/kgallowa/work/gcc/libjava/stacktrace.cc	(working copy)
@@ -25,6 +25,7 @@
 #include <gnu/java/lang/MainThread.h>
 #include <gnu/gcj/runtime/NameFinder.h>
 #include <gnu/gcj/runtime/StringBuffer.h>
+#include <gnu/classpath/jdwp/Jdwp.h>
 
 #include <sysdep/backtrace.h>
 #include <sysdep/descriptor.h>
@@ -111,7 +112,13 @@
   // correspondance between call frames in the interpreted stack and occurances
   // of _Jv_InterpMethod::run() on the native stack.
 #ifdef INTERPRETER
-  void *interp_run = (void *) &_Jv_InterpMethod::run;
+  void *interp_run = NULL;
+  
+  if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+  	interp_run = (void *) &_Jv_InterpMethod::run_debug;
+  else
+    interp_run = (void *) &_Jv_InterpMethod::run;
+  	
   if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
     {
       state->frames[pos].type = frame_interpreter;

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-02 15:05               ` Kyle Galloway
@ 2006-08-02 22:56                 ` Tom Tromey
  2006-08-03 13:45                   ` Kyle Galloway
  0 siblings, 1 reply; 16+ messages in thread
From: Tom Tromey @ 2006-08-02 22:56 UTC (permalink / raw)
  To: Kyle Galloway; +Cc: java-patches

>>>>> "Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:

Kyle> I noticed a small error in my last patch.  I accidentally whacked out an
Kyle> include in stacktrace.cc which will cause some problems.  The new patch
Kyle> is included in this file.

We're very close :-)

Kyle> +#define STOREA(I) 		\
Kyle> +DEBUG_LOCALS_INSN(I, 'o')	\
Kyle> +locals[I].o = (--sp)->o

It is more normal C style to make these kinds of macros "statement
like", so that users can use them without recalling exactly how they
expand.  So you'd write something like:

#define STOREA(I)              \
  do {                         \
    DEBUG_LOCALS_INSN(I, 'o'); \
    locals[I].o = (--sp)->o;   \
  } while (0)

This approach lets STOREA be used in an 'if' without remembering
whether it needs braces.

Kyle> +#define DEBUG
Kyle> +#undef DEBUG_LOCALS_INSN
Kyle> +#define DEBUG_LOCALS_INSN(s, t) {}
 
Likewise here, DEBUG_LOCALS_INSN could be 'do {} while (0)'.

I notice neither definition of DEBUG_LOCALS_INSN does anything... I
presume that will follow?

Tom

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-02 22:56                 ` Tom Tromey
@ 2006-08-03 13:45                   ` Kyle Galloway
  2006-08-03 17:25                     ` Tom Tromey
  0 siblings, 1 reply; 16+ messages in thread
From: Kyle Galloway @ 2006-08-03 13:45 UTC (permalink / raw)
  To: tromey, java-patches

[-- Attachment #1: Type: text/plain, Size: 1384 bytes --]

Tom Tromey wrote:
>>>>>> "Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:
>>>>>>             
>
> Kyle> I noticed a small error in my last patch.  I accidentally whacked out an
> Kyle> include in stacktrace.cc which will cause some problems.  The new patch
> Kyle> is included in this file.
>
> We're very close :-)
>
> Kyle> +#define STOREA(I) 		\
> Kyle> +DEBUG_LOCALS_INSN(I, 'o')	\
> Kyle> +locals[I].o = (--sp)->o
>
> It is more normal C style to make these kinds of macros "statement
> like", so that users can use them without recalling exactly how they
> expand.  So you'd write something like:
>
> #define STOREA(I)              \
>   do {                         \
>     DEBUG_LOCALS_INSN(I, 'o'); \
>     locals[I].o = (--sp)->o;   \
>   } while (0)
>
> This approach lets STOREA be used in an 'if' without remembering
> whether it needs braces.
>   
Ok, I've changed that now.
> Kyle> +#define DEBUG
> Kyle> +#undef DEBUG_LOCALS_INSN
> Kyle> +#define DEBUG_LOCALS_INSN(s, t) {}
>  
> Likewise here, DEBUG_LOCALS_INSN could be 'do {} while (0)'.
>
> I notice neither definition of DEBUG_LOCALS_INSN does anything... I
> presume that will follow?
>   
I decided to isolate the split from any extra stuff that needs to be 
added by doing it in 2 seperate patches.  Once this one goes in, I will 
submit another to fill in DEBUG_LOCALS_INSN for the debugging case.

Kyle

[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 120685 bytes --]

Index: include/java-interp.h
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/include/java-interp.h	(revision 115852)
+++ /notnfs/kgallowa/vanilla/libjava/include/java-interp.h	(working copy)
@@ -176,9 +176,17 @@
   static void run_synch_object (ffi_cif*, void*, ffi_raw*, void*);
   static void run_class (ffi_cif*, void*, ffi_raw*, void*);
   static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*);
+  
+  static void run_normal_debug (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_synch_object_debug (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_class_debug (ffi_cif*, void*, ffi_raw*, void*);
+  static void run_synch_class_debug (ffi_cif*, void*, ffi_raw*, void*);
 
-  static void run (void*, ffi_raw *, _Jv_InterpMethod *);
+  static void run (void *, ffi_raw *, _Jv_InterpMethod *);
+  static void run_debug (void *, ffi_raw *, _Jv_InterpMethod *);
+  
 
+  
   // Returns source file line number for given PC value, or -1 if line
   // number info is unavailable.
   int get_source_line(pc_t mpc);
@@ -183,6 +191,8 @@
   // number info is unavailable.
   int get_source_line(pc_t mpc);
 
+
+
 #ifdef DIRECT_THREADED
   // Convenience function for indexing bytecode PC/insn slots in
   // line tables for JDWP
@@ -188,9 +198,9 @@
   // line tables for JDWP
   jlong insn_index (pc_t pc);
 #endif
-
- public:
-
+  
+   public:
+   
   /* Get the line table for this method.
    * start  is the lowest index in the method
    * end    is the  highest index in the method
Index: interpret-run.cc
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/interpret-run.cc	(revision 0)
+++ /notnfs/kgallowa/vanilla/libjava/interpret-run.cc	(revision 0)
@@ -0,0 +1,2508 @@
+// interpret-run.cc - Code to interpret bytecode
+
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+/* This file is meant only to be included in interpret.cc, it should not be
+ * compiled directly.	*/
+
+  using namespace java::lang::reflect;
+
+  // FRAME_DESC registers this particular invocation as the top-most
+  // interpreter frame.  This lets the stack tracing code (for
+  // Throwable) print information about the method being interpreted
+  // rather than about the interpreter itself.  FRAME_DESC has a
+  // destructor so it cleans up automatically when the interpreter
+  // returns.
+  java::lang::Thread *thread = java::lang::Thread::currentThread();
+  _Jv_InterpFrame frame_desc (meth, thread);
+
+  _Jv_word stack[meth->max_stack];
+  _Jv_word *sp = stack;
+
+  _Jv_word locals[meth->max_locals];
+
+#define INSN_LABEL(op) &&insn_##op
+
+  static const void *const insn_target[] = 
+  {
+    INSN_LABEL(nop),
+    INSN_LABEL(aconst_null),
+    INSN_LABEL(iconst_m1),
+    INSN_LABEL(iconst_0),
+    INSN_LABEL(iconst_1),
+    INSN_LABEL(iconst_2),
+    INSN_LABEL(iconst_3),
+    INSN_LABEL(iconst_4),
+    INSN_LABEL(iconst_5),
+    INSN_LABEL(lconst_0),
+    INSN_LABEL(lconst_1),
+    INSN_LABEL(fconst_0),
+    INSN_LABEL(fconst_1),
+    INSN_LABEL(fconst_2),
+    INSN_LABEL(dconst_0),
+    INSN_LABEL(dconst_1),
+    INSN_LABEL(bipush),
+    INSN_LABEL(sipush),
+    INSN_LABEL(ldc),
+    INSN_LABEL(ldc_w),
+    INSN_LABEL(ldc2_w),
+    INSN_LABEL(iload),
+    INSN_LABEL(lload),
+    INSN_LABEL(fload),
+    INSN_LABEL(dload),
+    INSN_LABEL(aload),
+    INSN_LABEL(iload_0),
+    INSN_LABEL(iload_1),
+    INSN_LABEL(iload_2),
+    INSN_LABEL(iload_3),
+    INSN_LABEL(lload_0),
+    INSN_LABEL(lload_1),
+    INSN_LABEL(lload_2),
+    INSN_LABEL(lload_3),
+    INSN_LABEL(fload_0),
+    INSN_LABEL(fload_1),
+    INSN_LABEL(fload_2),
+    INSN_LABEL(fload_3),
+    INSN_LABEL(dload_0),
+    INSN_LABEL(dload_1),
+    INSN_LABEL(dload_2),
+    INSN_LABEL(dload_3),
+    INSN_LABEL(aload_0),
+    INSN_LABEL(aload_1),
+    INSN_LABEL(aload_2),
+    INSN_LABEL(aload_3),
+    INSN_LABEL(iaload),
+    INSN_LABEL(laload),
+    INSN_LABEL(faload),
+    INSN_LABEL(daload),
+    INSN_LABEL(aaload),
+    INSN_LABEL(baload),
+    INSN_LABEL(caload),
+    INSN_LABEL(saload),
+    INSN_LABEL(istore),
+    INSN_LABEL(lstore),
+    INSN_LABEL(fstore),
+    INSN_LABEL(dstore),
+    INSN_LABEL(astore),
+    INSN_LABEL(istore_0),
+    INSN_LABEL(istore_1),
+    INSN_LABEL(istore_2),
+    INSN_LABEL(istore_3),
+    INSN_LABEL(lstore_0),
+    INSN_LABEL(lstore_1),
+    INSN_LABEL(lstore_2),
+    INSN_LABEL(lstore_3),
+    INSN_LABEL(fstore_0),
+    INSN_LABEL(fstore_1),
+    INSN_LABEL(fstore_2),
+    INSN_LABEL(fstore_3),
+    INSN_LABEL(dstore_0),
+    INSN_LABEL(dstore_1),
+    INSN_LABEL(dstore_2),
+    INSN_LABEL(dstore_3),
+    INSN_LABEL(astore_0),
+    INSN_LABEL(astore_1),
+    INSN_LABEL(astore_2),
+    INSN_LABEL(astore_3),
+    INSN_LABEL(iastore),
+    INSN_LABEL(lastore),
+    INSN_LABEL(fastore),
+    INSN_LABEL(dastore),
+    INSN_LABEL(aastore),
+    INSN_LABEL(bastore),
+    INSN_LABEL(castore),
+    INSN_LABEL(sastore),
+    INSN_LABEL(pop),
+    INSN_LABEL(pop2),
+    INSN_LABEL(dup),
+    INSN_LABEL(dup_x1),
+    INSN_LABEL(dup_x2),
+    INSN_LABEL(dup2),
+    INSN_LABEL(dup2_x1),
+    INSN_LABEL(dup2_x2),
+    INSN_LABEL(swap),
+    INSN_LABEL(iadd),
+    INSN_LABEL(ladd),
+    INSN_LABEL(fadd),
+    INSN_LABEL(dadd),
+    INSN_LABEL(isub),
+    INSN_LABEL(lsub),
+    INSN_LABEL(fsub),
+    INSN_LABEL(dsub),
+    INSN_LABEL(imul),
+    INSN_LABEL(lmul),
+    INSN_LABEL(fmul),
+    INSN_LABEL(dmul),
+    INSN_LABEL(idiv),
+    INSN_LABEL(ldiv),
+    INSN_LABEL(fdiv),
+    INSN_LABEL(ddiv),
+    INSN_LABEL(irem),
+    INSN_LABEL(lrem),
+    INSN_LABEL(frem),
+    INSN_LABEL(drem),
+    INSN_LABEL(ineg),
+    INSN_LABEL(lneg),
+    INSN_LABEL(fneg),
+    INSN_LABEL(dneg),
+    INSN_LABEL(ishl),
+    INSN_LABEL(lshl),
+    INSN_LABEL(ishr),
+    INSN_LABEL(lshr),
+    INSN_LABEL(iushr),
+    INSN_LABEL(lushr),
+    INSN_LABEL(iand),
+    INSN_LABEL(land),
+    INSN_LABEL(ior),
+    INSN_LABEL(lor),
+    INSN_LABEL(ixor),
+    INSN_LABEL(lxor),
+    INSN_LABEL(iinc),
+    INSN_LABEL(i2l),
+    INSN_LABEL(i2f),
+    INSN_LABEL(i2d),
+    INSN_LABEL(l2i),
+    INSN_LABEL(l2f),
+    INSN_LABEL(l2d),
+    INSN_LABEL(f2i),
+    INSN_LABEL(f2l),
+    INSN_LABEL(f2d),
+    INSN_LABEL(d2i),
+    INSN_LABEL(d2l),
+    INSN_LABEL(d2f),
+    INSN_LABEL(i2b),
+    INSN_LABEL(i2c),
+    INSN_LABEL(i2s),
+    INSN_LABEL(lcmp),
+    INSN_LABEL(fcmpl),
+    INSN_LABEL(fcmpg),
+    INSN_LABEL(dcmpl),
+    INSN_LABEL(dcmpg),
+    INSN_LABEL(ifeq),
+    INSN_LABEL(ifne),
+    INSN_LABEL(iflt),
+    INSN_LABEL(ifge),
+    INSN_LABEL(ifgt),
+    INSN_LABEL(ifle),
+    INSN_LABEL(if_icmpeq),
+    INSN_LABEL(if_icmpne),
+    INSN_LABEL(if_icmplt),
+    INSN_LABEL(if_icmpge),
+    INSN_LABEL(if_icmpgt),
+    INSN_LABEL(if_icmple),
+    INSN_LABEL(if_acmpeq),
+    INSN_LABEL(if_acmpne),
+    INSN_LABEL(goto), 
+    INSN_LABEL(jsr),
+    INSN_LABEL(ret),
+    INSN_LABEL(tableswitch),
+    INSN_LABEL(lookupswitch),
+    INSN_LABEL(ireturn),
+    INSN_LABEL(lreturn),
+    INSN_LABEL(freturn),
+    INSN_LABEL(dreturn),
+    INSN_LABEL(areturn),
+    INSN_LABEL(return),
+    INSN_LABEL(getstatic),
+    INSN_LABEL(putstatic),
+    INSN_LABEL(getfield),
+    INSN_LABEL(putfield),
+    INSN_LABEL(invokevirtual),
+    INSN_LABEL(invokespecial),
+    INSN_LABEL(invokestatic),
+    INSN_LABEL(invokeinterface),
+    0, /* Unused.  */
+    INSN_LABEL(new),
+    INSN_LABEL(newarray),
+    INSN_LABEL(anewarray),
+    INSN_LABEL(arraylength),
+    INSN_LABEL(athrow),
+    INSN_LABEL(checkcast),
+    INSN_LABEL(instanceof),
+    INSN_LABEL(monitorenter),
+    INSN_LABEL(monitorexit),
+#ifdef DIRECT_THREADED
+    0, // wide
+#else
+    INSN_LABEL(wide),
+#endif
+    INSN_LABEL(multianewarray),
+    INSN_LABEL(ifnull),
+    INSN_LABEL(ifnonnull),
+    INSN_LABEL(goto_w),
+    INSN_LABEL(jsr_w),
+#ifdef DIRECT_THREADED
+    INSN_LABEL (ldc_class)
+#else
+    0
+#endif
+  };
+
+  pc_t pc;
+
+#ifdef DIRECT_THREADED
+
+#define NEXT_INSN goto *((pc++)->insn)
+#define INTVAL() ((pc++)->int_val)
+#define AVAL() ((pc++)->datum)
+
+#define GET1S() INTVAL ()
+#define GET2S() INTVAL ()
+#define GET1U() INTVAL ()
+#define GET2U() INTVAL ()
+#define AVAL1U() AVAL ()
+#define AVAL2U() AVAL ()
+#define AVAL2UP() AVAL ()
+#define SKIP_GOTO ++pc
+#define GOTO_VAL() (insn_slot *) pc->datum
+#define PCVAL(unionval) unionval.p
+#define AMPAMP(label) &&label
+
+  // Compile if we must. NOTE: Double-check locking.
+  if (meth->prepared == NULL)
+    {
+      _Jv_MutexLock (&compile_mutex);
+      if (meth->prepared == NULL)
+	meth->compile (insn_target);
+      _Jv_MutexUnlock (&compile_mutex);
+    }
+
+  // If we're only compiling, stop here
+  if (args == NULL)
+    return;
+
+  pc = (insn_slot *) meth->prepared;
+
+#else
+
+#define NEXT_INSN goto *(insn_target[*pc++])
+
+#define GET1S() get1s (pc++)
+#define GET2S() (pc += 2, get2s (pc- 2))
+#define GET1U() get1u (pc++)
+#define GET2U() (pc += 2, get2u (pc - 2))
+  // Note that these could be more efficient when not handling 'ldc
+  // class'.
+#define AVAL1U()						\
+  ({ int index = get1u (pc++);					\
+      resolve_pool_entry (meth->defining_class, index).o; })
+#define AVAL2U()						\
+  ({ int index = get2u (pc); pc += 2;				\
+      resolve_pool_entry (meth->defining_class, index).o; })
+  // Note that we don't need to resolve the pool entry here as class
+  // constants are never wide.
+#define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
+#define SKIP_GOTO pc += 2
+#define GOTO_VAL() pc - 1 + get2s (pc)
+#define PCVAL(unionval) unionval.i
+#define AMPAMP(label) NULL
+
+  pc = bytecode ();
+
+#endif /* DIRECT_THREADED */
+
+#define TAKE_GOTO pc = GOTO_VAL ()
+
+  /* Go straight at it!  the ffi raw format matches the internal
+     stack representation exactly.  At least, that's the idea.
+  */
+  memcpy ((void*) locals, (void*) args, meth->args_raw_size);
+
+  _Jv_word *pool_data = meth->defining_class->constants.data;
+
+  /* These three are temporaries for common code used by several
+     instructions.  */
+  void (*fun)();
+  _Jv_ResolvedMethod* rmeth;
+  int tmpval;
+
+  try
+    {
+      // We keep nop around.  It is used if we're interpreting the
+      // bytecodes and not doing direct threading.
+    insn_nop:
+      NEXT_INSN;
+
+      /* The first few instructions here are ordered according to their
+	 frequency, in the hope that this will improve code locality a
+	 little.  */
+
+    insn_aload_0:		// 0x2a
+      LOADA (0);
+      NEXT_INSN;
+
+    insn_iload:		// 0x15
+      LOADI (GET1U ());
+      NEXT_INSN;
+
+    insn_iload_1:		// 0x1b
+      LOADI (1);
+      NEXT_INSN;
+
+    insn_invokevirtual:	// 0xb6
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	/* _Jv_Linker::resolve_pool_entry returns immediately if the
+	 * value already is resolved.  If we want to clutter up the
+	 * code here to gain a little performance, then we can check
+	 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
+	 * directly.  For now, I don't think it is worth it.  */
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	if (rmeth->method->accflags & Modifier::FINAL)
+	  {
+	    // We can't rely on NULLCHECK working if the method is final.
+	    if (! sp[0].o)
+	      throw_null_pointer_exception ();
+
+	    // Final methods might not appear in the vtable.
+	    fun = (void (*)()) rmeth->method->ncode;
+	  }
+	else
+	  {
+	    NULLCHECK (sp[0].o);
+	    jobject rcv = sp[0].o;
+	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
+	    fun = (void (*)()) table->get_method (rmeth->method->index);
+	  }
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokevirtual_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokevirtual_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+
+	if (rmeth->method->accflags & Modifier::FINAL)
+	  {
+	    // We can't rely on NULLCHECK working if the method is final.
+	    if (! sp[0].o)
+	      throw_null_pointer_exception ();
+
+	    // Final methods might not appear in the vtable.
+	    fun = (void (*)()) rmeth->method->ncode;
+	  }
+	else
+	  {
+	    jobject rcv = sp[0].o;
+	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
+	    fun = (void (*)()) table->get_method (rmeth->method->index);
+	  }
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    perform_invoke:
+      {
+	/* here goes the magic again... */
+	ffi_cif *cif = &rmeth->cif;
+	ffi_raw *raw = (ffi_raw*) sp;
+
+	_Jv_value rvalue;
+
+#if FFI_NATIVE_RAW_API
+	/* We assume that this is only implemented if it's correct	*/
+	/* to use it here.  On a 64 bit machine, it never is.		*/
+	ffi_raw_call (cif, fun, (void*)&rvalue, raw);
+#else
+	ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
+#endif
+
+	int rtype = cif->rtype->type;
+
+	/* the likelyhood of object, int, or void return is very high,
+	 * so those are checked before the switch */
+	if (rtype == FFI_TYPE_POINTER)
+	  {
+	    PUSHA (rvalue.object_value);
+	  }
+	else if (rtype == FFI_TYPE_SINT32)
+	  {
+	    PUSHI (rvalue.int_value);
+	  }
+	else if (rtype == FFI_TYPE_VOID)
+	  {
+	    /* skip */
+	  }
+	else
+	  {
+	    switch (rtype)
+	      {
+	      case FFI_TYPE_SINT8:
+		PUSHI ((jbyte)(rvalue.int_value & 0xff));
+		break;
+
+	      case FFI_TYPE_SINT16:
+		PUSHI ((jshort)(rvalue.int_value & 0xffff));
+		break;
+
+	      case FFI_TYPE_UINT16:
+		PUSHI (rvalue.int_value & 0xffff);
+		break;
+
+	      case FFI_TYPE_FLOAT:
+	        PUSHF (rvalue.float_value);
+		break;
+
+	      case FFI_TYPE_DOUBLE:
+	        PUSHD (rvalue.double_value);
+		break;
+
+	      case FFI_TYPE_SINT64:
+	        PUSHL (rvalue.long_value);
+		break;
+
+	      default:
+		throw_internal_error ("unknown return type in invokeXXX");
+	      }
+	  }
+      }
+      NEXT_INSN;
+
+    insn_aconst_null:
+      PUSHA (NULL);
+      NEXT_INSN;
+
+    insn_iconst_m1:
+      PUSHI (-1);
+      NEXT_INSN;
+
+    insn_iconst_0:
+      PUSHI (0);
+      NEXT_INSN;
+
+    insn_iconst_1:
+      PUSHI (1);
+      NEXT_INSN;
+
+    insn_iconst_2:
+      PUSHI (2);
+      NEXT_INSN;
+
+    insn_iconst_3:
+      PUSHI (3);
+      NEXT_INSN;
+
+    insn_iconst_4:
+      PUSHI (4);
+      NEXT_INSN;
+
+    insn_iconst_5:
+      PUSHI (5);
+      NEXT_INSN;
+
+    insn_lconst_0:
+      PUSHL (0);
+      NEXT_INSN;
+
+    insn_lconst_1:
+      PUSHL (1);
+      NEXT_INSN;
+
+    insn_fconst_0:
+      PUSHF (0);
+      NEXT_INSN;
+
+    insn_fconst_1:
+      PUSHF (1);
+      NEXT_INSN;
+
+    insn_fconst_2:
+      PUSHF (2);
+      NEXT_INSN;
+
+    insn_dconst_0:
+      PUSHD (0);
+      NEXT_INSN;
+
+    insn_dconst_1:
+      PUSHD (1);
+      NEXT_INSN;
+
+    insn_bipush:
+      // For direct threaded, bipush and sipush are the same.
+#ifndef DIRECT_THREADED
+      PUSHI (GET1S ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_sipush:
+      PUSHI (GET2S ());
+      NEXT_INSN;
+
+    insn_ldc:
+      // For direct threaded, ldc and ldc_w are the same.
+#ifndef DIRECT_THREADED
+      PUSHA ((jobject) AVAL1U ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_ldc_w:
+      PUSHA ((jobject) AVAL2U ());
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+      // For direct threaded we have a separate 'ldc class' operation.
+    insn_ldc_class:
+      {
+	SAVE_PC();
+	// We could rewrite the instruction at this point.
+	int index = INTVAL ();
+	jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						     index)).o;
+	PUSHA (k);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_ldc2_w:
+      {
+	void *where = AVAL2UP ();
+	memcpy (sp, where, 2*sizeof (_Jv_word));
+	sp += 2;
+      }
+      NEXT_INSN;
+
+    insn_lload:
+      LOADL (GET1U ());
+      NEXT_INSN;
+
+    insn_fload:
+      LOADF (GET1U ());
+      NEXT_INSN;
+
+    insn_dload:
+      LOADD (GET1U ());
+      NEXT_INSN;
+
+    insn_aload:
+      LOADA (GET1U ());
+      NEXT_INSN;
+
+    insn_iload_0:
+      LOADI (0);
+      NEXT_INSN;
+
+    insn_iload_2:
+      LOADI (2);
+      NEXT_INSN;
+
+    insn_iload_3:
+      LOADI (3);
+      NEXT_INSN;
+
+    insn_lload_0:
+      LOADL (0);
+      NEXT_INSN;
+
+    insn_lload_1:
+      LOADL (1);
+      NEXT_INSN;
+
+    insn_lload_2:
+      LOADL (2);
+      NEXT_INSN;
+
+    insn_lload_3:
+      LOADL (3);
+      NEXT_INSN;
+
+    insn_fload_0:
+      LOADF (0);
+      NEXT_INSN;
+
+    insn_fload_1:
+      LOADF (1);
+      NEXT_INSN;
+
+    insn_fload_2:
+      LOADF (2);
+      NEXT_INSN;
+
+    insn_fload_3:
+      LOADF (3);
+      NEXT_INSN;
+
+    insn_dload_0:
+      LOADD (0);
+      NEXT_INSN;
+
+    insn_dload_1:
+      LOADD (1);
+      NEXT_INSN;
+
+    insn_dload_2:
+      LOADD (2);
+      NEXT_INSN;
+
+    insn_dload_3:
+      LOADD (3);
+      NEXT_INSN;
+
+    insn_aload_1:
+      LOADA(1);
+      NEXT_INSN;
+
+    insn_aload_2:
+      LOADA(2);
+      NEXT_INSN;
+
+    insn_aload_3:
+      LOADA(3);
+      NEXT_INSN;
+
+    insn_iaload:
+      {
+	jint index = POPI();
+	jintArray arr = (jintArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_laload:
+      {
+	jint index = POPI();
+	jlongArray arr = (jlongArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHL( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_faload:
+      {
+	jint index = POPI();
+	jfloatArray arr = (jfloatArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHF( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_daload:
+      {
+	jint index = POPI();
+	jdoubleArray arr = (jdoubleArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHD( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_aaload:
+      {
+	jint index = POPI();
+	jobjectArray arr = (jobjectArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHA( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_baload:
+      {
+	jint index = POPI();
+	jbyteArray arr = (jbyteArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_caload:
+      {
+	jint index = POPI();
+	jcharArray arr = (jcharArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_saload:
+      {
+	jint index = POPI();
+	jshortArray arr = (jshortArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	PUSHI( elements(arr)[index] );
+      }
+      NEXT_INSN;
+
+    insn_istore:
+      STOREI (GET1U ());
+      NEXT_INSN;
+
+    insn_lstore:
+      STOREL (GET1U ());
+      NEXT_INSN;
+
+    insn_fstore:
+      STOREF (GET1U ());
+      NEXT_INSN;
+
+    insn_dstore:
+      STORED (GET1U ());
+      NEXT_INSN;
+
+    insn_astore:
+      STOREA (GET1U ());
+      NEXT_INSN;
+
+    insn_istore_0:
+      STOREI (0);
+      NEXT_INSN;
+
+    insn_istore_1:
+      STOREI (1);
+      NEXT_INSN;
+
+    insn_istore_2:
+      STOREI (2);
+      NEXT_INSN;
+
+    insn_istore_3:
+      STOREI (3);
+      NEXT_INSN;
+
+    insn_lstore_0:
+      STOREL (0);
+      NEXT_INSN;
+
+    insn_lstore_1:
+      STOREL (1);
+      NEXT_INSN;
+
+    insn_lstore_2:
+      STOREL (2);
+      NEXT_INSN;
+
+    insn_lstore_3:
+      STOREL (3);
+      NEXT_INSN;
+
+    insn_fstore_0:
+      STOREF (0);
+      NEXT_INSN;
+
+    insn_fstore_1:
+      STOREF (1);
+      NEXT_INSN;
+
+    insn_fstore_2:
+      STOREF (2);
+      NEXT_INSN;
+
+    insn_fstore_3:
+      STOREF (3);
+      NEXT_INSN;
+
+    insn_dstore_0:
+      STORED (0);
+      NEXT_INSN;
+
+    insn_dstore_1:
+      STORED (1);
+      NEXT_INSN;
+
+    insn_dstore_2:
+      STORED (2);
+      NEXT_INSN;
+
+    insn_dstore_3:
+      STORED (3);
+      NEXT_INSN;
+
+    insn_astore_0:
+      STOREA(0);
+      NEXT_INSN;
+
+    insn_astore_1:
+      STOREA(1);
+      NEXT_INSN;
+
+    insn_astore_2:
+      STOREA(2);
+      NEXT_INSN;
+
+    insn_astore_3:
+      STOREA(3);
+      NEXT_INSN;
+
+    insn_iastore:
+      {
+	jint value = POPI();
+	jint index  = POPI();
+	jintArray arr = (jintArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_lastore:
+      {
+	jlong value = POPL();
+	jint index  = POPI();
+	jlongArray arr = (jlongArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_fastore:
+      {
+	jfloat value = POPF();
+	jint index  = POPI();
+	jfloatArray arr = (jfloatArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_dastore:
+      {
+	jdouble value = POPD();
+	jint index  = POPI();
+	jdoubleArray arr = (jdoubleArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_aastore:
+      {
+	jobject value = POPA();
+	jint index  = POPI();
+	jobjectArray arr = (jobjectArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	_Jv_CheckArrayStore (arr, value);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_bastore:
+      {
+	jbyte value = (jbyte) POPI();
+	jint index  = POPI();
+	jbyteArray arr = (jbyteArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_castore:
+      {
+	jchar value = (jchar) POPI();
+	jint index  = POPI();
+	jcharArray arr = (jcharArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_sastore:
+      {
+	jshort value = (jshort) POPI();
+	jint index  = POPI();
+	jshortArray arr = (jshortArray) POPA();
+	NULLARRAYCHECK (arr);
+	ARRAYBOUNDSCHECK (arr, index);
+	elements(arr)[index] = value;
+      }
+      NEXT_INSN;
+
+    insn_pop:
+      sp -= 1;
+      NEXT_INSN;
+
+    insn_pop2:
+      sp -= 2;
+      NEXT_INSN;
+
+    insn_dup:
+      sp[0] = sp[-1];
+      sp += 1;
+      NEXT_INSN;
+
+    insn_dup_x1:
+      dupx (sp, 1, 1); sp+=1;
+      NEXT_INSN;
+
+    insn_dup_x2:
+      dupx (sp, 1, 2); sp+=1;
+      NEXT_INSN;
+
+    insn_dup2:
+      sp[0] = sp[-2];
+      sp[1] = sp[-1];
+      sp += 2;
+      NEXT_INSN;
+
+    insn_dup2_x1:
+      dupx (sp, 2, 1); sp+=2;
+      NEXT_INSN;
+
+    insn_dup2_x2:
+      dupx (sp, 2, 2); sp+=2;
+      NEXT_INSN;
+
+    insn_swap:
+      {
+	jobject tmp1 = POPA();
+	jobject tmp2 = POPA();
+	PUSHA (tmp1);
+	PUSHA (tmp2);
+      }
+      NEXT_INSN;
+
+    insn_iadd:
+      BINOPI(+);
+      NEXT_INSN;
+
+    insn_ladd:
+      BINOPL(+);
+      NEXT_INSN;
+
+    insn_fadd:
+      BINOPF(+);
+      NEXT_INSN;
+
+    insn_dadd:
+      BINOPD(+);
+      NEXT_INSN;
+
+    insn_isub:
+      BINOPI(-);
+      NEXT_INSN;
+
+    insn_lsub:
+      BINOPL(-);
+      NEXT_INSN;
+
+    insn_fsub:
+      BINOPF(-);
+      NEXT_INSN;
+
+    insn_dsub:
+      BINOPD(-);
+      NEXT_INSN;
+
+    insn_imul:
+      BINOPI(*);
+      NEXT_INSN;
+
+    insn_lmul:
+      BINOPL(*);
+      NEXT_INSN;
+
+    insn_fmul:
+      BINOPF(*);
+      NEXT_INSN;
+
+    insn_dmul:
+      BINOPD(*);
+      NEXT_INSN;
+
+    insn_idiv:
+      {
+	SAVE_PC();
+	jint value2 = POPI();
+	jint value1 = POPI();
+	jint res = _Jv_divI (value1, value2);
+	PUSHI (res);
+      }
+      NEXT_INSN;
+
+    insn_ldiv:
+      {
+	SAVE_PC();
+	jlong value2 = POPL();
+	jlong value1 = POPL();
+	jlong res = _Jv_divJ (value1, value2);
+	PUSHL (res);
+      }
+      NEXT_INSN;
+
+    insn_fdiv:
+      {
+	jfloat value2 = POPF();
+	jfloat value1 = POPF();
+	jfloat res = value1 / value2;
+	PUSHF (res);
+      }
+      NEXT_INSN;
+
+    insn_ddiv:
+      {
+	jdouble value2 = POPD();
+	jdouble value1 = POPD();
+	jdouble res = value1 / value2;
+	PUSHD (res);
+      }
+      NEXT_INSN;
+
+    insn_irem:
+      {
+	SAVE_PC();
+	jint value2 = POPI();
+	jint value1 =  POPI();
+	jint res = _Jv_remI (value1, value2);
+	PUSHI (res);
+      }
+      NEXT_INSN;
+
+    insn_lrem:
+      {
+	SAVE_PC();
+	jlong value2 = POPL();
+	jlong value1 = POPL();
+	jlong res = _Jv_remJ (value1, value2);
+	PUSHL (res);
+      }
+      NEXT_INSN;
+
+    insn_frem:
+      {
+	jfloat value2 = POPF();
+	jfloat value1 = POPF();
+	jfloat res    = __ieee754_fmod (value1, value2);
+	PUSHF (res);
+      }
+      NEXT_INSN;
+
+    insn_drem:
+      {
+	jdouble value2 = POPD();
+	jdouble value1 = POPD();
+	jdouble res    = __ieee754_fmod (value1, value2);
+	PUSHD (res);
+      }
+      NEXT_INSN;
+
+    insn_ineg:
+      {
+	jint value = POPI();
+	PUSHI (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_lneg:
+      {
+	jlong value = POPL();
+	PUSHL (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_fneg:
+      {
+	jfloat value = POPF();
+	PUSHF (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_dneg:
+      {
+	jdouble value = POPD();
+	PUSHD (value * -1);
+      }
+      NEXT_INSN;
+
+    insn_ishl:
+      {
+	jint shift = (POPI() & 0x1f);
+	jint value = POPI();
+	PUSHI (value << shift);
+      }
+      NEXT_INSN;
+
+    insn_lshl:
+      {
+	jint shift = (POPI() & 0x3f);
+	jlong value = POPL();
+	PUSHL (value << shift);
+      }
+      NEXT_INSN;
+
+    insn_ishr:
+      {
+	jint shift = (POPI() & 0x1f);
+	jint value = POPI();
+	PUSHI (value >> shift);
+      }
+      NEXT_INSN;
+
+    insn_lshr:
+      {
+	jint shift = (POPI() & 0x3f);
+	jlong value = POPL();
+	PUSHL (value >> shift);
+      }
+      NEXT_INSN;
+
+    insn_iushr:
+      {
+	jint shift = (POPI() & 0x1f);
+	_Jv_uint value = (_Jv_uint) POPI();
+	PUSHI ((jint) (value >> shift));
+      }
+      NEXT_INSN;
+
+    insn_lushr:
+      {
+	jint shift = (POPI() & 0x3f);
+	_Jv_ulong value = (_Jv_ulong) POPL();
+	PUSHL ((jlong) (value >> shift));
+      }
+      NEXT_INSN;
+
+    insn_iand:
+      BINOPI (&);
+      NEXT_INSN;
+
+    insn_land:
+      BINOPL (&);
+      NEXT_INSN;
+
+    insn_ior:
+      BINOPI (|);
+      NEXT_INSN;
+
+    insn_lor:
+      BINOPL (|);
+      NEXT_INSN;
+
+    insn_ixor:
+      BINOPI (^);
+      NEXT_INSN;
+
+    insn_lxor:
+      BINOPL (^);
+      NEXT_INSN;
+
+    insn_iinc:
+      {
+	jint index  = GET1U ();
+	jint amount = GET1S ();
+	locals[index].i += amount;
+      }
+      NEXT_INSN;
+
+    insn_i2l:
+      {jlong value = POPI(); PUSHL (value);}
+      NEXT_INSN;
+
+    insn_i2f:
+      {jfloat value = POPI(); PUSHF (value);}
+      NEXT_INSN;
+
+    insn_i2d:
+      {jdouble value = POPI(); PUSHD (value);}
+      NEXT_INSN;
+
+    insn_l2i:
+      {jint value = POPL(); PUSHI (value);}
+      NEXT_INSN;
+
+    insn_l2f:
+      {jfloat value = POPL(); PUSHF (value);}
+      NEXT_INSN;
+
+    insn_l2d:
+      {jdouble value = POPL(); PUSHD (value);}
+      NEXT_INSN;
+
+    insn_f2i:
+      {
+	using namespace java::lang;
+	jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
+	PUSHI(value);
+      }
+      NEXT_INSN;
+
+    insn_f2l:
+      {
+	using namespace java::lang;
+	jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
+	PUSHL(value);
+      }
+      NEXT_INSN;
+
+    insn_f2d:
+      { jdouble value = POPF (); PUSHD(value); }
+      NEXT_INSN;
+
+    insn_d2i:
+      {
+	using namespace java::lang;
+	jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
+	PUSHI(value);
+      }
+      NEXT_INSN;
+
+    insn_d2l:
+      {
+	using namespace java::lang;
+	jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
+	PUSHL(value);
+      }
+      NEXT_INSN;
+
+    insn_d2f:
+      { jfloat value = POPD (); PUSHF(value); }
+      NEXT_INSN;
+
+    insn_i2b:
+      { jbyte value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_i2c:
+      { jchar value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_i2s:
+      { jshort value = POPI (); PUSHI(value); }
+      NEXT_INSN;
+
+    insn_lcmp:
+      {
+	jlong value2 = POPL ();
+	jlong value1 = POPL ();
+	if (value1 > value2)
+	  { PUSHI (1); }
+	else if (value1 == value2)
+	  { PUSHI (0); }
+	else
+	  { PUSHI (-1); }
+      }
+      NEXT_INSN;
+
+    insn_fcmpl:
+      tmpval = -1;
+      goto fcmp;
+
+    insn_fcmpg:
+      tmpval = 1;
+
+    fcmp:
+      {
+	jfloat value2 = POPF ();
+	jfloat value1 = POPF ();
+	if (value1 > value2)
+	  PUSHI (1);
+	else if (value1 == value2)
+	  PUSHI (0);
+	else if (value1 < value2)
+	  PUSHI (-1);
+	else
+	  PUSHI (tmpval);
+      }
+      NEXT_INSN;
+
+    insn_dcmpl:
+      tmpval = -1;
+      goto dcmp;
+
+    insn_dcmpg:
+      tmpval = 1;
+
+    dcmp:
+      {
+	jdouble value2 = POPD ();
+	jdouble value1 = POPD ();
+	if (value1 > value2)
+	  PUSHI (1);
+	else if (value1 == value2)
+	  PUSHI (0);
+	else if (value1 < value2)
+	  PUSHI (-1);
+	else
+	  PUSHI (tmpval);
+      }
+      NEXT_INSN;
+
+    insn_ifeq:
+      {
+	if (POPI() == 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifne:
+      {
+	if (POPI() != 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_iflt:
+      {
+	if (POPI() < 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifge:
+      {
+	if (POPI() >= 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifgt:
+      {
+	if (POPI() > 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifle:
+      {
+	if (POPI() <= 0)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpeq:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 == value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpne:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 != value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmplt:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 < value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpge:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 >= value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmpgt:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 > value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_icmple:
+      {
+	jint value2 = POPI();
+	jint value1 = POPI();
+	if (value1 <= value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_acmpeq:
+      {
+	jobject value2 = POPA();
+	jobject value1 = POPA();
+	if (value1 == value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_if_acmpne:
+      {
+	jobject value2 = POPA();
+	jobject value1 = POPA();
+	if (value1 != value2)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_goto_w:
+#ifndef DIRECT_THREADED
+      // For direct threaded, goto and goto_w are the same.
+      pc = pc - 1 + get4 (pc);
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_goto:
+      TAKE_GOTO;
+      NEXT_INSN;
+
+    insn_jsr_w:
+#ifndef DIRECT_THREADED
+      // For direct threaded, jsr and jsr_w are the same.
+      {
+	pc_t next = pc - 1 + get4 (pc);
+	pc += 4;
+	PUSHA ((jobject) pc);
+	pc = next;
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+    insn_jsr:
+      {
+	pc_t next = GOTO_VAL();
+	SKIP_GOTO;
+	PUSHA ((jobject) pc);
+	pc = next;
+      }
+      NEXT_INSN;
+
+    insn_ret:
+      {
+	jint index = GET1U ();
+	pc = (pc_t) PEEKA (index);
+      }
+      NEXT_INSN;
+
+    insn_tableswitch:
+      {
+#ifdef DIRECT_THREADED
+	void *def = (pc++)->datum;
+
+	int index = POPI();
+
+	jint low = INTVAL ();
+	jint high = INTVAL ();
+
+	if (index < low || index > high)
+	  pc = (insn_slot *) def;
+	else
+	  pc = (insn_slot *) ((pc + index - low)->datum);
+#else
+	pc_t base_pc = pc - 1;
+	int index = POPI ();
+
+	pc_t base = (pc_t) bytecode ();
+	while ((pc - base) % 4 != 0)
+	  ++pc;
+
+	jint def = get4 (pc);
+	jint low = get4 (pc + 4);
+	jint high = get4 (pc + 8);
+	if (index < low || index > high)
+	  pc = base_pc + def;
+	else
+	  pc = base_pc + get4 (pc + 4 * (index - low + 3));
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+    insn_lookupswitch:
+      {
+#ifdef DIRECT_THREADED
+	void *def = (pc++)->insn;
+
+	int index = POPI();
+
+	jint npairs = INTVAL ();
+
+	int max = npairs - 1;
+	int min = 0;
+
+	// Simple binary search...
+	while (min < max)
+	  {
+	    int half = (min + max) / 2;
+	    int match = pc[2 * half].int_val;
+
+	    if (index == match)
+	      {
+		// Found it.
+		pc = (insn_slot *) pc[2 * half + 1].datum;
+		NEXT_INSN;
+	      }
+	    else if (index < match)
+	      // We can use HALF - 1 here because we check again on
+	      // loop exit.
+	      max = half - 1;
+	    else
+	      // We can use HALF + 1 here because we check again on
+	      // loop exit.
+	      min = half + 1;
+	  }
+	if (index == pc[2 * min].int_val)
+	  pc = (insn_slot *) pc[2 * min + 1].datum;
+	else
+	  pc = (insn_slot *) def;
+#else
+	unsigned char *base_pc = pc-1;
+	int index = POPI();
+
+	unsigned char* base = bytecode ();
+	while ((pc-base) % 4 != 0)
+	  ++pc;
+
+	jint def     = get4 (pc);
+	jint npairs  = get4 (pc+4);
+
+	int max = npairs-1;
+	int min = 0;
+
+	// Simple binary search...
+	while (min < max)
+	  {
+	    int half = (min+max)/2;
+	    int match = get4 (pc+ 4*(2 + 2*half));
+
+	    if (index == match)
+	      min = max = half;
+	    else if (index < match)
+	      // We can use HALF - 1 here because we check again on
+	      // loop exit.
+	      max = half - 1;
+	    else
+	      // We can use HALF + 1 here because we check again on
+	      // loop exit.
+	      min = half + 1;
+	  }
+
+	if (index == get4 (pc+ 4*(2 + 2*min)))
+	  pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
+	else
+	  pc = base_pc + def;    
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+    insn_areturn:
+      *(jobject *) retp = POPA ();
+      return;
+
+    insn_lreturn:
+      *(jlong *) retp = POPL ();
+      return;
+
+    insn_freturn:
+      *(jfloat *) retp = POPF ();
+      return;
+
+    insn_dreturn:
+      *(jdouble *) retp = POPD ();
+      return;
+
+    insn_ireturn:
+      *(jint *) retp = POPI ();
+      return;
+
+    insn_return:
+      return;
+
+    insn_getstatic:
+      {
+	jint fieldref_index = GET2U ();
+        SAVE_PC(); // Constant pool resolution could throw.
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	if ((field->flags & Modifier::STATIC) == 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field no longer static"));
+
+	jclass type = field->type;
+
+	// We rewrite the instruction once we discover what it refers
+	// to.
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes)
+	      {
+	      case 1:
+		PUSHI (*field->u.byte_addr);
+		newinsn = AMPAMP (getstatic_resolved_1);
+		break;
+
+	      case 2:
+		if (type == JvPrimClass (char))
+		  {
+		    PUSHI (*field->u.char_addr);
+		    newinsn = AMPAMP (getstatic_resolved_char);
+		  }
+		else
+		  {
+		    PUSHI (*field->u.short_addr);
+		    newinsn = AMPAMP (getstatic_resolved_short);
+		  }
+		break;
+
+	      case 4:
+	        PUSHI(*field->u.int_addr);
+		newinsn = AMPAMP (getstatic_resolved_4);
+		break;
+
+	      case 8:
+	        PUSHL(*field->u.long_addr);
+		newinsn = AMPAMP (getstatic_resolved_8);
+		break;
+	      }
+	  }
+	else
+	  {
+	    PUSHA(*field->u.object_addr);
+	    newinsn = AMPAMP (getstatic_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].datum = field->u.addr;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    getstatic_resolved_1:
+      PUSHI (*(jbyte *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_char:
+      PUSHI (*(jchar *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_short:
+      PUSHI (*(jshort *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_4:
+      PUSHI (*(jint *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_8:
+      PUSHL (*(jlong *) AVAL ());
+      NEXT_INSN;
+
+    getstatic_resolved_obj:
+      PUSHA (*(jobject *) AVAL ());
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_getfield:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	if ((field->flags & Modifier::STATIC) != 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field is static"));
+
+	jclass type = field->type;
+	jint field_offset = field->u.boffset;
+
+	jobject obj   = POPA();
+	NULLCHECK(obj);
+
+	void *newinsn = NULL;
+	_Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes)
+	      {
+	      case 1:
+	        PUSHI (val->byte_value);
+		newinsn = AMPAMP (getfield_resolved_1);
+		break;
+
+	      case 2:
+		if (type == JvPrimClass (char))
+		  {
+		    PUSHI (val->char_value);
+		    newinsn = AMPAMP (getfield_resolved_char);
+		  }
+		else
+		  {
+		    PUSHI (val->short_value);
+		    newinsn = AMPAMP (getfield_resolved_short);
+		  }
+		break;
+
+	      case 4:
+		PUSHI (val->int_value);
+		newinsn = AMPAMP (getfield_resolved_4);
+		break;
+
+	      case 8:
+	        PUSHL (val->long_value);
+		newinsn = AMPAMP (getfield_resolved_8);
+		break;
+	      }
+	  }
+	else
+	  {
+	    PUSHA (val->object_value);
+	    newinsn = AMPAMP (getfield_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].int_val = field_offset;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    getfield_resolved_1:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jbyte *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_char:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jchar *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_short:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jshort *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_4:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHI (*(jint *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_8:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHL (*(jlong *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+
+    getfield_resolved_obj:
+      {
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	PUSHA (*(jobject *) (obj + INTVAL ()));
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_putstatic:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	jclass type = field->type;
+
+	// ResolvePoolEntry cannot check this
+	if ((field->flags & Modifier::STATIC) == 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field no longer static"));
+
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes) 
+	      {
+	      case 1:
+		{
+		  jint value = POPI();
+		  *field->u.byte_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_1);
+		  break;
+		}
+
+	      case 2:
+		{
+		  jint value = POPI();
+		  *field->u.char_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_2);
+		  break;
+		}
+
+	      case 4:
+		{
+		  jint value = POPI();
+		  *field->u.int_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_4);
+		  break;
+		}
+
+	      case 8:
+		{
+		  jlong value = POPL();
+		  *field->u.long_addr = value;
+		  newinsn = AMPAMP (putstatic_resolved_8);
+		  break;
+		}
+	      }
+	  }
+	else
+	  {
+	    jobject value = POPA();
+	    *field->u.object_addr = value;
+	    newinsn = AMPAMP (putstatic_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].datum = field->u.addr;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    putstatic_resolved_1:
+      *(jbyte *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_2:
+      *(jchar *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_4:
+      *(jint *) AVAL () = POPI ();
+      NEXT_INSN;
+
+    putstatic_resolved_8:
+      *(jlong *) AVAL () = POPL ();
+      NEXT_INSN;
+
+    putstatic_resolved_obj:
+      *(jobject *) AVAL () = POPA ();
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_putfield:
+      {
+	SAVE_PC();
+	jint fieldref_index = GET2U ();
+	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
+	_Jv_Field *field = pool_data[fieldref_index].field;
+
+	jclass type = field->type;
+
+	if ((field->flags & Modifier::STATIC) != 0)
+	  throw_incompatible_class_change_error 
+	    (JvNewStringLatin1 ("field is static"));
+
+	jint field_offset = field->u.boffset;
+
+	void *newinsn = NULL;
+	if (type->isPrimitive ())
+	  {
+	    switch (type->size_in_bytes) 
+	      {
+	      case 1:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jbyte*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_1);
+		  break;
+		}
+
+	      case 2:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jchar*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_2);
+		  break;
+		}
+
+	      case 4:
+		{
+		  jint    value = POPI();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jint*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_4);
+		  break;
+		}
+
+	      case 8:
+		{
+		  jlong   value = POPL();
+		  jobject obj   = POPA();
+		  NULLCHECK(obj);
+		  *(jlong*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_8);
+		  break;
+		}
+	      }
+	  }
+	else
+	  {
+	    jobject value = POPA();
+	    jobject obj   = POPA();
+	    NULLCHECK(obj);
+	    *(jobject*) ((char*)obj + field_offset) = value;
+	    newinsn = AMPAMP (putfield_resolved_obj);
+	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].int_val = field_offset;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    putfield_resolved_1:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jbyte *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_2:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jchar *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_4:
+      {
+	jint val = POPI ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jint *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_8:
+      {
+	jlong val = POPL ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jlong *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+
+    putfield_resolved_obj:
+      {
+	jobject val = POPA ();
+	char *obj = (char *) POPA ();
+	NULLCHECK (obj);
+	*(jobject *) (obj + INTVAL ()) = val;
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_invokespecial:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	// We don't use NULLCHECK here because we can't rely on that
+	// working for <init>.  So instead we do an explicit test.
+	if (! sp[0].o)
+	  {
+	    SAVE_PC();
+	    throw_null_pointer_exception ();
+	  }
+
+	fun = (void (*)()) rmeth->method->ncode;
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokespecial_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokespecial_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	// We don't use NULLCHECK here because we can't rely on that
+	// working for <init>.  So instead we do an explicit test.
+	if (! sp[0].o)
+	  {
+	    throw_null_pointer_exception ();
+	  }
+	fun = (void (*)()) rmeth->method->ncode;
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_invokestatic:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	fun = (void (*)()) rmeth->method->ncode;
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokestatic_resolved;
+	pc[-1].datum = rmeth;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokestatic_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	fun = (void (*)()) rmeth->method->ncode;
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_invokeinterface:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+
+	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						   index)).rmethod;
+
+	sp -= rmeth->stack_item_count;
+
+	jobject rcv = sp[0].o;
+
+	NULLCHECK (rcv);
+
+	fun = (void (*)())
+	  _Jv_LookupInterfaceMethod (rcv->getClass (),
+				     rmeth->method->name,
+				     rmeth->method->signature);
+
+#ifdef DIRECT_THREADED
+	// Rewrite instruction so that we use a faster pre-resolved
+	// method.
+	pc[-2].insn = &&invokeinterface_resolved;
+	pc[-1].datum = rmeth;
+#else
+	// Skip dummy bytes.
+	pc += 2;
+#endif /* DIRECT_THREADED */
+      }
+      goto perform_invoke;
+
+#ifdef DIRECT_THREADED
+    invokeinterface_resolved:
+      {
+	SAVE_PC();
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	jobject rcv = sp[0].o;
+	NULLCHECK (rcv);
+	fun = (void (*)())
+	  _Jv_LookupInterfaceMethod (rcv->getClass (),
+				     rmeth->method->name,
+				     rmeth->method->signature);
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_new:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+							  index)).clazz;
+	/* VM spec, section 3.11.5 */
+	if ((klass->getModifiers() & Modifier::ABSTRACT)
+	    || klass->isInterface())
+	  throw new java::lang::InstantiationException;
+	jobject res = _Jv_AllocObject (klass);
+	PUSHA (res);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&new_resolved;
+	pc[-1].datum = klass;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    new_resolved:
+      {
+	jclass klass = (jclass) AVAL ();
+	jobject res = _Jv_AllocObject (klass);
+	PUSHA (res);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_newarray:
+      {
+	int atype = GET1U ();
+	int size  = POPI();
+	jobject result = _Jv_NewArray (atype, size);
+	PUSHA (result);
+      }
+      NEXT_INSN;
+
+    insn_anewarray:
+      {
+	SAVE_PC();
+	int index = GET2U ();
+	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+							  index)).clazz;
+	int size  = POPI();
+	jobject result = _Jv_NewObjectArray (size, klass, 0);
+	PUSHA (result);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&anewarray_resolved;
+	pc[-1].datum = klass;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    anewarray_resolved:
+      {
+	jclass klass = (jclass) AVAL ();
+	int size = POPI ();
+	jobject result = _Jv_NewObjectArray (size, klass, 0);
+	PUSHA (result);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_arraylength:
+      {
+	__JArray *arr = (__JArray*)POPA();
+	NULLARRAYCHECK (arr);
+	PUSHI (arr->length);
+      }
+      NEXT_INSN;
+
+    insn_athrow:
+      {
+	jobject value = POPA();
+	throw static_cast<jthrowable>(value);
+      }
+      NEXT_INSN;
+
+    insn_checkcast:
+      {
+        SAVE_PC();
+	jobject value = POPA();
+	jint index = GET2U ();
+	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						       index)).clazz;
+
+	value = (jobject) _Jv_CheckCast (to, value);
+
+	PUSHA (value);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&checkcast_resolved;
+	pc[-1].datum = to;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    checkcast_resolved:
+      {
+        SAVE_PC();
+	jobject value = POPA ();
+	jclass to = (jclass) AVAL ();
+	value = (jobject) _Jv_CheckCast (to, value);
+	PUSHA (value);
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_instanceof:
+      {
+        SAVE_PC();
+	jobject value = POPA();
+	jint index = GET2U ();
+	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+						       index)).clazz;
+	PUSHI (to->isInstance (value));
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&instanceof_resolved;
+	pc[-1].datum = to;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    instanceof_resolved:
+      {
+	jobject value = POPA ();
+	jclass to = (jclass) AVAL ();
+	PUSHI (to->isInstance (value));
+      }
+      NEXT_INSN;
+#endif /* DIRECT_THREADED */
+
+    insn_monitorenter:
+      {
+	jobject value = POPA();
+	NULLCHECK(value);
+	_Jv_MonitorEnter (value);
+      }
+      NEXT_INSN;
+
+    insn_monitorexit:
+      {
+	jobject value = POPA();
+	NULLCHECK(value);
+	_Jv_MonitorExit (value);
+      }
+      NEXT_INSN;
+
+    insn_ifnull:
+      {
+	jobject val = POPA();
+	if (val == NULL)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_ifnonnull:
+      {
+	jobject val = POPA();
+	if (val != NULL)
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
+      }
+      NEXT_INSN;
+
+    insn_multianewarray:
+      {
+	SAVE_PC();
+	int kind_index = GET2U ();
+	int dim        = GET1U ();
+
+	jclass type    
+	  = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
+					       kind_index)).clazz;
+	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
+
+	for (int i = dim - 1; i >= 0; i--)
+	  {
+	    sizes[i] = POPI ();
+	  }
+
+	jobject res    = _Jv_NewMultiArray (type,dim, sizes);
+
+	PUSHA (res);
+      }
+      NEXT_INSN;
+
+#ifndef DIRECT_THREADED
+    insn_wide:
+      {
+	jint the_mod_op = get1u (pc++);
+	jint wide       = get2u (pc); pc += 2;
+
+	switch (the_mod_op)
+	  {
+	  case op_istore:
+	    STOREI (wide);
+	    NEXT_INSN;
+
+	  case op_fstore:
+	    STOREF (wide);
+	    NEXT_INSN;
+
+	  case op_astore:
+	    STOREA (wide);
+	    NEXT_INSN;
+
+	  case op_lload:
+	    LOADL (wide);
+	    NEXT_INSN;
+
+	  case op_dload:
+	    LOADD (wide);
+	    NEXT_INSN;
+
+	  case op_iload:
+	    LOADI (wide);
+	    NEXT_INSN;
+
+	  case op_fload:
+	    LOADF (wide);
+	    NEXT_INSN;
+
+	  case op_aload:
+	    LOADA (wide);
+	    NEXT_INSN;
+
+	  case op_lstore:
+	    STOREL (wide);
+	    NEXT_INSN;
+
+	  case op_dstore:
+	    STORED (wide);
+	    NEXT_INSN;
+
+	  case op_ret:
+	    pc = (unsigned char*) PEEKA (wide);
+	    NEXT_INSN;
+
+	  case op_iinc:
+	    {
+	      jint amount = get2s (pc); pc += 2;
+	      jint value = PEEKI (wide);
+	      POKEI (wide, value+amount);
+	    }
+	    NEXT_INSN;
+
+	  default:
+	    throw_internal_error ("illegal bytecode modified by wide");
+	  }
+
+      }
+#endif /* DIRECT_THREADED */
+    }
+  catch (java::lang::Throwable *ex)
+    {
+#ifdef DIRECT_THREADED
+      void *logical_pc = (void *) ((insn_slot *) pc - 1);
+#else
+      int logical_pc = pc - 1 - bytecode ();
+#endif
+      _Jv_InterpException *exc = meth->exceptions ();
+      jclass exc_class = ex->getClass ();
+
+      for (int i = 0; i < meth->exc_count; i++)
+	{
+	  if (PCVAL (exc[i].start_pc) <= logical_pc
+	      && logical_pc < PCVAL (exc[i].end_pc))
+	    {
+#ifdef DIRECT_THREADED
+	      jclass handler = (jclass) exc[i].handler_type.p;
+#else
+	      jclass handler = NULL;
+	      if (exc[i].handler_type.i != 0)
+		handler = (_Jv_Linker::resolve_pool_entry (defining_class,
+							     exc[i].handler_type.i)).clazz;
+#endif /* DIRECT_THREADED */
+
+	      if (handler == NULL || handler->isAssignableFrom (exc_class))
+		{
+
+#ifdef DIRECT_THREADED
+		  pc = (insn_slot *) exc[i].handler_pc.p;
+#else
+		  pc = bytecode () + exc[i].handler_pc.i;
+#endif /* DIRECT_THREADED */
+		  sp = stack;
+		  sp++->o = ex; // Push exception.
+		  NEXT_INSN;
+		}
+	    }
+	}
+
+      // No handler, so re-throw.
+      throw ex;
+    }
Index: interpret.cc
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/interpret.cc	(revision 115852)
+++ /notnfs/kgallowa/vanilla/libjava/interpret.cc	(working copy)
@@ -37,6 +37,8 @@
 #include <execution.h>
 #include <java/lang/reflect/Modifier.h>
 
+#include <gnu/classpath/jdwp/Jdwp.h>
+
 #ifdef INTERPRETER
 
 // Execution engine for interpreted code.
@@ -152,18 +154,46 @@
 # define LOADD(I)  LOADL(I)
 #endif
 
-#define STOREA(I) locals[I].o = (--sp)->o
-#define STOREI(I) locals[I].i = (--sp)->i
-#define STOREF(I) locals[I].f = (--sp)->f
+#define STOREA(I) 		\
+do {					\
+DEBUG_LOCALS_INSN(I, 'o');		\
+locals[I].o = (--sp)->o;		\
+} while(0)
+#define STOREI(I) 		\
+do {					\
+DEBUG_LOCALS_INSN (I, 'i');		\
+locals[I].i = (--sp)->i;		\
+} while(0)
+#define STOREF(I)  		\
+do {					\
+DEBUG_LOCALS_INSN (I, 'f');		\
+locals[I].f = (--sp)->f;		\
+} while(0)
 #if SIZEOF_VOID_P == 8
-# define STOREL(I) (sp -= 2, locals[I].l = sp->l)
-# define STORED(I) (sp -= 2, locals[I].d = sp->d)
+# define STOREL(I)  			\
+do {							\
+DEBUG_LOCALS_INSN (I, 'l');			\
+(sp -= 2, locals[I].l = sp->l);		\
+} while(0)
+# define STORED(I) 				\
+do {							\
+DEBUG_LOCALS_INSN (I, 'd');			\
+(sp -= 2, locals[I].d = sp->d);		\
+} while(0)
+
 #else
-# define STOREL(I) do { jint __idx = (I); \
-    		       locals[__idx+1].ia[0] = (--sp)->ia[0]; \
-    		       locals[__idx].ia[0] = (--sp)->ia[0]; \
-		   } while (0)
-# define STORED(I) STOREL(I)
+# define STOREL(I)		\
+do { DEBUG_LOCALS_INSN(I, 'l');	\
+	 jint __idx = (I); 	\
+     locals[__idx+1].ia[0] = (--sp)->ia[0]; \
+     locals[__idx].ia[0] = (--sp)->ia[0]; 	\
+   } while (0)
+# define STORED(I)		\
+do { DEBUG_LOCALS_INSN(I, 'd');	\
+	 jint __idx = (I); 	\
+     locals[__idx+1].ia[0] = (--sp)->ia[0]; \
+     locals[__idx].ia[0] = (--sp)->ia[0]; 	\
+   } while (0)
 #endif
 
 #define PEEKI(I)  (locals+(I))->i
@@ -169,7 +199,9 @@
 #define PEEKI(I)  (locals+(I))->i
 #define PEEKA(I)  (locals+(I))->o
 
-#define POKEI(I,V)  ((locals+(I))->i = (V))
+#define POKEI(I,V)  	\
+DEBUG_LOCALS_INSN(I,i)	\
+((locals+(I))->i = (V))
 
 
 #define BINOPI(OP) { \
@@ -258,6 +290,16 @@
 }
 
 void
+_Jv_InterpMethod::run_normal_debug (ffi_cif *,
+			      void* ret,
+			      ffi_raw * args,
+			      void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+  run_debug (ret, args, _this);
+}
+
+void
 _Jv_InterpMethod::run_synch_object (ffi_cif *,
 				    void* ret,
 				    ffi_raw * args,
@@ -272,6 +314,20 @@
 }
 
 void
+_Jv_InterpMethod::run_synch_object_debug (ffi_cif *,
+				    void* ret,
+				    ffi_raw * args,
+				    void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+
+  jobject rcv = (jobject) args[0].ptr;
+  JvSynchronize mutex (rcv);
+
+  run_debug (ret, args, _this);
+}
+
+void
 _Jv_InterpMethod::run_class (ffi_cif *,
 			     void* ret,
 			     ffi_raw * args,
@@ -283,6 +339,17 @@
 }
 
 void
+_Jv_InterpMethod::run_class_debug (ffi_cif *,
+			     void* ret,
+			     ffi_raw * args,
+			     void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+  _Jv_InitClass (_this->defining_class);
+  run_debug (ret, args, _this);
+}
+
+void
 _Jv_InterpMethod::run_synch_class (ffi_cif *,
 				   void* ret,
 				   ffi_raw * args,
@@ -297,6 +364,21 @@
   run (ret, args, _this);
 }
 
+void
+_Jv_InterpMethod::run_synch_class_debug (ffi_cif *,
+				   void* ret,
+				   ffi_raw * args,
+				   void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+
+  jclass sync = _this->defining_class;
+  _Jv_InitClass (sync);
+  JvSynchronize mutex (sync);
+
+  run_debug (ret, args, _this);
+}
+
 #ifdef DIRECT_THREADED
 // "Compile" a method by turning it from bytecode to direct-threaded
 // code.
@@ -805,2709 +887,239 @@
 void
 _Jv_InterpMethod::run (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
 {
-  using namespace java::lang::reflect;
+#undef DEBUG
+#undef DEBUG_LOCALS_INSN
+#define DEBUG_LOCALS_INSN(s, t) do {} while(0)
 
-  // FRAME_DESC registers this particular invocation as the top-most
-  // interpreter frame.  This lets the stack tracing code (for
-  // Throwable) print information about the method being interpreted
-  // rather than about the interpreter itself.  FRAME_DESC has a
-  // destructor so it cleans up automatically when the interpreter
-  // returns.
-  java::lang::Thread *thread = java::lang::Thread::currentThread();
-  _Jv_InterpFrame frame_desc (meth, thread);
+#include "interpret-run.cc"
+}
 
-  _Jv_word stack[meth->max_stack];
-  _Jv_word *sp = stack;
+void
+_Jv_InterpMethod::run_debug (void *retp, ffi_raw *args, _Jv_InterpMethod *meth)
+{
+/* Used to keep track of local variable type
+ * 
+ * Possible Types:
+ * o object
+ * i integer
+ * f float
+ * l long 
+ * d double 
+ */
+#define DEBUG
+#undef DEBUG_LOCALS_INSN
+#define DEBUG_LOCALS_INSN(s, t) do {} while(0)
 
-  _Jv_word locals[meth->max_locals];
+#include "interpret-run.cc"
+}
 
-#define INSN_LABEL(op) &&insn_##op
+static void
+throw_internal_error (const char *msg)
+{
+  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
+}
 
-  static const void *const insn_target[] = 
-  {
-    INSN_LABEL(nop),
-    INSN_LABEL(aconst_null),
-    INSN_LABEL(iconst_m1),
-    INSN_LABEL(iconst_0),
-    INSN_LABEL(iconst_1),
-    INSN_LABEL(iconst_2),
-    INSN_LABEL(iconst_3),
-    INSN_LABEL(iconst_4),
-    INSN_LABEL(iconst_5),
-    INSN_LABEL(lconst_0),
-    INSN_LABEL(lconst_1),
-    INSN_LABEL(fconst_0),
-    INSN_LABEL(fconst_1),
-    INSN_LABEL(fconst_2),
-    INSN_LABEL(dconst_0),
-    INSN_LABEL(dconst_1),
-    INSN_LABEL(bipush),
-    INSN_LABEL(sipush),
-    INSN_LABEL(ldc),
-    INSN_LABEL(ldc_w),
-    INSN_LABEL(ldc2_w),
-    INSN_LABEL(iload),
-    INSN_LABEL(lload),
-    INSN_LABEL(fload),
-    INSN_LABEL(dload),
-    INSN_LABEL(aload),
-    INSN_LABEL(iload_0),
-    INSN_LABEL(iload_1),
-    INSN_LABEL(iload_2),
-    INSN_LABEL(iload_3),
-    INSN_LABEL(lload_0),
-    INSN_LABEL(lload_1),
-    INSN_LABEL(lload_2),
-    INSN_LABEL(lload_3),
-    INSN_LABEL(fload_0),
-    INSN_LABEL(fload_1),
-    INSN_LABEL(fload_2),
-    INSN_LABEL(fload_3),
-    INSN_LABEL(dload_0),
-    INSN_LABEL(dload_1),
-    INSN_LABEL(dload_2),
-    INSN_LABEL(dload_3),
-    INSN_LABEL(aload_0),
-    INSN_LABEL(aload_1),
-    INSN_LABEL(aload_2),
-    INSN_LABEL(aload_3),
-    INSN_LABEL(iaload),
-    INSN_LABEL(laload),
-    INSN_LABEL(faload),
-    INSN_LABEL(daload),
-    INSN_LABEL(aaload),
-    INSN_LABEL(baload),
-    INSN_LABEL(caload),
-    INSN_LABEL(saload),
-    INSN_LABEL(istore),
-    INSN_LABEL(lstore),
-    INSN_LABEL(fstore),
-    INSN_LABEL(dstore),
-    INSN_LABEL(astore),
-    INSN_LABEL(istore_0),
-    INSN_LABEL(istore_1),
-    INSN_LABEL(istore_2),
-    INSN_LABEL(istore_3),
-    INSN_LABEL(lstore_0),
-    INSN_LABEL(lstore_1),
-    INSN_LABEL(lstore_2),
-    INSN_LABEL(lstore_3),
-    INSN_LABEL(fstore_0),
-    INSN_LABEL(fstore_1),
-    INSN_LABEL(fstore_2),
-    INSN_LABEL(fstore_3),
-    INSN_LABEL(dstore_0),
-    INSN_LABEL(dstore_1),
-    INSN_LABEL(dstore_2),
-    INSN_LABEL(dstore_3),
-    INSN_LABEL(astore_0),
-    INSN_LABEL(astore_1),
-    INSN_LABEL(astore_2),
-    INSN_LABEL(astore_3),
-    INSN_LABEL(iastore),
-    INSN_LABEL(lastore),
-    INSN_LABEL(fastore),
-    INSN_LABEL(dastore),
-    INSN_LABEL(aastore),
-    INSN_LABEL(bastore),
-    INSN_LABEL(castore),
-    INSN_LABEL(sastore),
-    INSN_LABEL(pop),
-    INSN_LABEL(pop2),
-    INSN_LABEL(dup),
-    INSN_LABEL(dup_x1),
-    INSN_LABEL(dup_x2),
-    INSN_LABEL(dup2),
-    INSN_LABEL(dup2_x1),
-    INSN_LABEL(dup2_x2),
-    INSN_LABEL(swap),
-    INSN_LABEL(iadd),
-    INSN_LABEL(ladd),
-    INSN_LABEL(fadd),
-    INSN_LABEL(dadd),
-    INSN_LABEL(isub),
-    INSN_LABEL(lsub),
-    INSN_LABEL(fsub),
-    INSN_LABEL(dsub),
-    INSN_LABEL(imul),
-    INSN_LABEL(lmul),
-    INSN_LABEL(fmul),
-    INSN_LABEL(dmul),
-    INSN_LABEL(idiv),
-    INSN_LABEL(ldiv),
-    INSN_LABEL(fdiv),
-    INSN_LABEL(ddiv),
-    INSN_LABEL(irem),
-    INSN_LABEL(lrem),
-    INSN_LABEL(frem),
-    INSN_LABEL(drem),
-    INSN_LABEL(ineg),
-    INSN_LABEL(lneg),
-    INSN_LABEL(fneg),
-    INSN_LABEL(dneg),
-    INSN_LABEL(ishl),
-    INSN_LABEL(lshl),
-    INSN_LABEL(ishr),
-    INSN_LABEL(lshr),
-    INSN_LABEL(iushr),
-    INSN_LABEL(lushr),
-    INSN_LABEL(iand),
-    INSN_LABEL(land),
-    INSN_LABEL(ior),
-    INSN_LABEL(lor),
-    INSN_LABEL(ixor),
-    INSN_LABEL(lxor),
-    INSN_LABEL(iinc),
-    INSN_LABEL(i2l),
-    INSN_LABEL(i2f),
-    INSN_LABEL(i2d),
-    INSN_LABEL(l2i),
-    INSN_LABEL(l2f),
-    INSN_LABEL(l2d),
-    INSN_LABEL(f2i),
-    INSN_LABEL(f2l),
-    INSN_LABEL(f2d),
-    INSN_LABEL(d2i),
-    INSN_LABEL(d2l),
-    INSN_LABEL(d2f),
-    INSN_LABEL(i2b),
-    INSN_LABEL(i2c),
-    INSN_LABEL(i2s),
-    INSN_LABEL(lcmp),
-    INSN_LABEL(fcmpl),
-    INSN_LABEL(fcmpg),
-    INSN_LABEL(dcmpl),
-    INSN_LABEL(dcmpg),
-    INSN_LABEL(ifeq),
-    INSN_LABEL(ifne),
-    INSN_LABEL(iflt),
-    INSN_LABEL(ifge),
-    INSN_LABEL(ifgt),
-    INSN_LABEL(ifle),
-    INSN_LABEL(if_icmpeq),
-    INSN_LABEL(if_icmpne),
-    INSN_LABEL(if_icmplt),
-    INSN_LABEL(if_icmpge),
-    INSN_LABEL(if_icmpgt),
-    INSN_LABEL(if_icmple),
-    INSN_LABEL(if_acmpeq),
-    INSN_LABEL(if_acmpne),
-    INSN_LABEL(goto), 
-    INSN_LABEL(jsr),
-    INSN_LABEL(ret),
-    INSN_LABEL(tableswitch),
-    INSN_LABEL(lookupswitch),
-    INSN_LABEL(ireturn),
-    INSN_LABEL(lreturn),
-    INSN_LABEL(freturn),
-    INSN_LABEL(dreturn),
-    INSN_LABEL(areturn),
-    INSN_LABEL(return),
-    INSN_LABEL(getstatic),
-    INSN_LABEL(putstatic),
-    INSN_LABEL(getfield),
-    INSN_LABEL(putfield),
-    INSN_LABEL(invokevirtual),
-    INSN_LABEL(invokespecial),
-    INSN_LABEL(invokestatic),
-    INSN_LABEL(invokeinterface),
-    0, /* Unused.  */
-    INSN_LABEL(new),
-    INSN_LABEL(newarray),
-    INSN_LABEL(anewarray),
-    INSN_LABEL(arraylength),
-    INSN_LABEL(athrow),
-    INSN_LABEL(checkcast),
-    INSN_LABEL(instanceof),
-    INSN_LABEL(monitorenter),
-    INSN_LABEL(monitorexit),
-#ifdef DIRECT_THREADED
-    0, // wide
-#else
-    INSN_LABEL(wide),
-#endif
-    INSN_LABEL(multianewarray),
-    INSN_LABEL(ifnull),
-    INSN_LABEL(ifnonnull),
-    INSN_LABEL(goto_w),
-    INSN_LABEL(jsr_w),
-#ifdef DIRECT_THREADED
-    INSN_LABEL (ldc_class)
-#else
-    0
-#endif
-  };
+static void 
+throw_incompatible_class_change_error (jstring msg)
+{
+  throw new java::lang::IncompatibleClassChangeError (msg);
+}
 
-  pc_t pc;
+static void 
+throw_null_pointer_exception ()
+{
+  throw new java::lang::NullPointerException;
+}
 
-#ifdef DIRECT_THREADED
+/* Look up source code line number for given bytecode (or direct threaded
+   interpreter) PC. */
+int
+_Jv_InterpMethod::get_source_line(pc_t mpc)
+{
+  int line = line_table_len > 0 ? line_table[0].line : -1;
+  for (int i = 1; i < line_table_len; i++)
+    if (line_table[i].pc > mpc)
+      break;
+    else
+      line = line_table[i].line;
 
-#define NEXT_INSN goto *((pc++)->insn)
-#define INTVAL() ((pc++)->int_val)
-#define AVAL() ((pc++)->datum)
+  return line;
+}
 
-#define GET1S() INTVAL ()
-#define GET2S() INTVAL ()
-#define GET1U() INTVAL ()
-#define GET2U() INTVAL ()
-#define AVAL1U() AVAL ()
-#define AVAL2U() AVAL ()
-#define AVAL2UP() AVAL ()
-#define SKIP_GOTO ++pc
-#define GOTO_VAL() (insn_slot *) pc->datum
-#define PCVAL(unionval) unionval.p
-#define AMPAMP(label) &&label
+/** Do static initialization for fields with a constant initializer */
+void
+_Jv_InitField (jobject obj, jclass klass, int index)
+{
+  using namespace java::lang::reflect;
 
-  // Compile if we must. NOTE: Double-check locking.
-  if (meth->prepared == NULL)
-    {
-      _Jv_MutexLock (&compile_mutex);
-      if (meth->prepared == NULL)
-	meth->compile (insn_target);
-      _Jv_MutexUnlock (&compile_mutex);
-    }
+  if (obj != 0 && klass == 0)
+    klass = obj->getClass ();
 
-  // If we're only compiling, stop here
-  if (args == NULL)
+  if (!_Jv_IsInterpretedClass (klass))
     return;
 
-  pc = (insn_slot *) meth->prepared;
-
-#else
+  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
 
-#define NEXT_INSN goto *(insn_target[*pc++])
+  _Jv_Field * field = (&klass->fields[0]) + index;
 
-#define GET1S() get1s (pc++)
-#define GET2S() (pc += 2, get2s (pc- 2))
-#define GET1U() get1u (pc++)
-#define GET2U() (pc += 2, get2u (pc - 2))
-  // Note that these could be more efficient when not handling 'ldc
-  // class'.
-#define AVAL1U()						\
-  ({ int index = get1u (pc++);					\
-      resolve_pool_entry (meth->defining_class, index).o; })
-#define AVAL2U()						\
-  ({ int index = get2u (pc); pc += 2;				\
-      resolve_pool_entry (meth->defining_class, index).o; })
-  // Note that we don't need to resolve the pool entry here as class
-  // constants are never wide.
-#define AVAL2UP() ({ int index = get2u (pc); pc += 2; &pool_data[index]; })
-#define SKIP_GOTO pc += 2
-#define GOTO_VAL() pc - 1 + get2s (pc)
-#define PCVAL(unionval) unionval.i
-#define AMPAMP(label) NULL
+  if (index > klass->field_count)
+    throw_internal_error ("field out of range");
 
-  pc = bytecode ();
+  int init = iclass->field_initializers[index];
+  if (init == 0)
+    return;
 
-#endif /* DIRECT_THREADED */
+  _Jv_Constants *pool = &klass->constants;
+  int tag = pool->tags[init];
 
-#define TAKE_GOTO pc = GOTO_VAL ()
+  if (! field->isResolved ())
+    throw_internal_error ("initializing unresolved field");
 
-  /* Go straight at it!  the ffi raw format matches the internal
-     stack representation exactly.  At least, that's the idea.
-  */
-  memcpy ((void*) locals, (void*) args, meth->args_raw_size);
+  if (obj==0 && ((field->flags & Modifier::STATIC) == 0))
+    throw_internal_error ("initializing non-static field with no object");
 
-  _Jv_word *pool_data = meth->defining_class->constants.data;
+  void *addr = 0;
 
-  /* These three are temporaries for common code used by several
-     instructions.  */
-  void (*fun)();
-  _Jv_ResolvedMethod* rmeth;
-  int tmpval;
+  if ((field->flags & Modifier::STATIC) != 0)
+    addr = (void*) field->u.addr;
+  else
+    addr = (void*) (((char*)obj) + field->u.boffset);
 
-  try
+  switch (tag)
     {
-      // We keep nop around.  It is used if we're interpreting the
-      // bytecodes and not doing direct threading.
-    insn_nop:
-      NEXT_INSN;
-
-      /* The first few instructions here are ordered according to their
-	 frequency, in the hope that this will improve code locality a
-	 little.  */
-
-    insn_aload_0:		// 0x2a
-      LOADA (0);
-      NEXT_INSN;
-
-    insn_iload:		// 0x15
-      LOADI (GET1U ());
-      NEXT_INSN;
-
-    insn_iload_1:		// 0x1b
-      LOADI (1);
-      NEXT_INSN;
-
-    insn_invokevirtual:	// 0xb6
+    case JV_CONSTANT_String:
       {
-	SAVE_PC();
-	int index = GET2U ();
-
-	/* _Jv_Linker::resolve_pool_entry returns immediately if the
-	 * value already is resolved.  If we want to clutter up the
-	 * code here to gain a little performance, then we can check
-	 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
-	 * directly.  For now, I don't think it is worth it.  */
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	if (rmeth->method->accflags & Modifier::FINAL)
-	  {
-	    // We can't rely on NULLCHECK working if the method is final.
-	    if (! sp[0].o)
-	      throw_null_pointer_exception ();
-
-	    // Final methods might not appear in the vtable.
-	    fun = (void (*)()) rmeth->method->ncode;
-	  }
-	else
-	  {
-	    NULLCHECK (sp[0].o);
-	    jobject rcv = sp[0].o;
-	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
-	    fun = (void (*)()) table->get_method (rmeth->method->index);
-	  }
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokevirtual_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
+	jstring str;
+	str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
+	pool->data[init].string = str;
+	pool->tags[init] = JV_CONSTANT_ResolvedString;
       }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokevirtual_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
+      /* fall through */
 
-	if (rmeth->method->accflags & Modifier::FINAL)
-	  {
-	    // We can't rely on NULLCHECK working if the method is final.
-	    if (! sp[0].o)
-	      throw_null_pointer_exception ();
+    case JV_CONSTANT_ResolvedString:
+      if (! (field->type == &java::lang::String::class$
+ 	     || field->type == &java::lang::Class::class$))
+	throw_class_format_error ("string initialiser to non-string field");
 
-	    // Final methods might not appear in the vtable.
-	    fun = (void (*)()) rmeth->method->ncode;
-	  }
-	else
-	  {
-	    jobject rcv = sp[0].o;
-	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
-	    fun = (void (*)()) table->get_method (rmeth->method->index);
-	  }
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
+      *(jstring*)addr = pool->data[init].string;
+      break;
 
-    perform_invoke:
+    case JV_CONSTANT_Integer:
       {
-	/* here goes the magic again... */
-	ffi_cif *cif = &rmeth->cif;
-	ffi_raw *raw = (ffi_raw*) sp;
-
-	_Jv_value rvalue;
+	int value = pool->data[init].i;
 
-#if FFI_NATIVE_RAW_API
-	/* We assume that this is only implemented if it's correct	*/
-	/* to use it here.  On a 64 bit machine, it never is.		*/
-	ffi_raw_call (cif, fun, (void*)&rvalue, raw);
-#else
-	ffi_java_raw_call (cif, fun, (void*)&rvalue, raw);
-#endif
+	if (field->type == JvPrimClass (boolean))
+	  *(jboolean*)addr = (jboolean)value;
+	
+	else if (field->type == JvPrimClass (byte))
+	  *(jbyte*)addr = (jbyte)value;
+	
+	else if (field->type == JvPrimClass (char))
+	  *(jchar*)addr = (jchar)value;
 
-	int rtype = cif->rtype->type;
+	else if (field->type == JvPrimClass (short))
+	  *(jshort*)addr = (jshort)value;
+	
+	else if (field->type == JvPrimClass (int))
+	  *(jint*)addr = (jint)value;
 
-	/* the likelyhood of object, int, or void return is very high,
-	 * so those are checked before the switch */
-	if (rtype == FFI_TYPE_POINTER)
-	  {
-	    PUSHA (rvalue.object_value);
-	  }
-	else if (rtype == FFI_TYPE_SINT32)
-	  {
-	    PUSHI (rvalue.int_value);
-	  }
-	else if (rtype == FFI_TYPE_VOID)
-	  {
-	    /* skip */
-	  }
 	else
-	  {
-	    switch (rtype)
-	      {
-	      case FFI_TYPE_SINT8:
-		PUSHI ((jbyte)(rvalue.int_value & 0xff));
-		break;
-
-	      case FFI_TYPE_SINT16:
-		PUSHI ((jshort)(rvalue.int_value & 0xffff));
-		break;
-
-	      case FFI_TYPE_UINT16:
-		PUSHI (rvalue.int_value & 0xffff);
-		break;
+	  throw_class_format_error ("erroneous field initializer");
+      }  
+      break;
 
-	      case FFI_TYPE_FLOAT:
-	        PUSHF (rvalue.float_value);
-		break;
+    case JV_CONSTANT_Long:
+      if (field->type != JvPrimClass (long))
+	throw_class_format_error ("erroneous field initializer");
 
-	      case FFI_TYPE_DOUBLE:
-	        PUSHD (rvalue.double_value);
-		break;
+      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
+      break;
 
-	      case FFI_TYPE_SINT64:
-	        PUSHL (rvalue.long_value);
-		break;
+    case JV_CONSTANT_Float:
+      if (field->type != JvPrimClass (float))
+	throw_class_format_error ("erroneous field initializer");
 
-	      default:
-		throw_internal_error ("unknown return type in invokeXXX");
-	      }
-	  }
-      }
-      NEXT_INSN;
+      *(jfloat*)addr = pool->data[init].f;
+      break;
 
-    insn_aconst_null:
-      PUSHA (NULL);
-      NEXT_INSN;
+    case JV_CONSTANT_Double:
+      if (field->type != JvPrimClass (double))
+	throw_class_format_error ("erroneous field initializer");
 
-    insn_iconst_m1:
-      PUSHI (-1);
-      NEXT_INSN;
+      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
+      break;
 
-    insn_iconst_0:
-      PUSHI (0);
-      NEXT_INSN;
+    default:
+      throw_class_format_error ("erroneous field initializer");
+    }
+}
 
-    insn_iconst_1:
-      PUSHI (1);
-      NEXT_INSN;
+inline static unsigned char*
+skip_one_type (unsigned char* ptr)
+{
+  int ch = *ptr++;
 
-    insn_iconst_2:
-      PUSHI (2);
-      NEXT_INSN;
+  while (ch == '[')
+    { 
+      ch = *ptr++;
+    }
+  
+  if (ch == 'L')
+    {
+      do { ch = *ptr++; } while (ch != ';');
+    }
 
-    insn_iconst_3:
-      PUSHI (3);
-      NEXT_INSN;
+  return ptr;
+}
 
-    insn_iconst_4:
-      PUSHI (4);
-      NEXT_INSN;
+static ffi_type*
+get_ffi_type_from_signature (unsigned char* ptr)
+{
+  switch (*ptr) 
+    {
+    case 'L':
+    case '[':
+      return &ffi_type_pointer;
+      break;
 
-    insn_iconst_5:
-      PUSHI (5);
-      NEXT_INSN;
+    case 'Z':
+      // On some platforms a bool is a byte, on others an int.
+      if (sizeof (jboolean) == sizeof (jbyte))
+	return &ffi_type_sint8;
+      else
+	{
+	  JvAssert (sizeof (jbyte) == sizeof (jint));
+	  return &ffi_type_sint32;
+	}
+      break;
 
-    insn_lconst_0:
-      PUSHL (0);
-      NEXT_INSN;
-
-    insn_lconst_1:
-      PUSHL (1);
-      NEXT_INSN;
-
-    insn_fconst_0:
-      PUSHF (0);
-      NEXT_INSN;
-
-    insn_fconst_1:
-      PUSHF (1);
-      NEXT_INSN;
-
-    insn_fconst_2:
-      PUSHF (2);
-      NEXT_INSN;
-
-    insn_dconst_0:
-      PUSHD (0);
-      NEXT_INSN;
-
-    insn_dconst_1:
-      PUSHD (1);
-      NEXT_INSN;
-
-    insn_bipush:
-      // For direct threaded, bipush and sipush are the same.
-#ifndef DIRECT_THREADED
-      PUSHI (GET1S ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_sipush:
-      PUSHI (GET2S ());
-      NEXT_INSN;
-
-    insn_ldc:
-      // For direct threaded, ldc and ldc_w are the same.
-#ifndef DIRECT_THREADED
-      PUSHA ((jobject) AVAL1U ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_ldc_w:
-      PUSHA ((jobject) AVAL2U ());
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-      // For direct threaded we have a separate 'ldc class' operation.
-    insn_ldc_class:
-      {
-	SAVE_PC();
-	// We could rewrite the instruction at this point.
-	int index = INTVAL ();
-	jobject k = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						     index)).o;
-	PUSHA (k);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_ldc2_w:
-      {
-	void *where = AVAL2UP ();
-	memcpy (sp, where, 2*sizeof (_Jv_word));
-	sp += 2;
-      }
-      NEXT_INSN;
-
-    insn_lload:
-      LOADL (GET1U ());
-      NEXT_INSN;
-
-    insn_fload:
-      LOADF (GET1U ());
-      NEXT_INSN;
-
-    insn_dload:
-      LOADD (GET1U ());
-      NEXT_INSN;
-
-    insn_aload:
-      LOADA (GET1U ());
-      NEXT_INSN;
-
-    insn_iload_0:
-      LOADI (0);
-      NEXT_INSN;
-
-    insn_iload_2:
-      LOADI (2);
-      NEXT_INSN;
-
-    insn_iload_3:
-      LOADI (3);
-      NEXT_INSN;
-
-    insn_lload_0:
-      LOADL (0);
-      NEXT_INSN;
-
-    insn_lload_1:
-      LOADL (1);
-      NEXT_INSN;
-
-    insn_lload_2:
-      LOADL (2);
-      NEXT_INSN;
-
-    insn_lload_3:
-      LOADL (3);
-      NEXT_INSN;
-
-    insn_fload_0:
-      LOADF (0);
-      NEXT_INSN;
-
-    insn_fload_1:
-      LOADF (1);
-      NEXT_INSN;
-
-    insn_fload_2:
-      LOADF (2);
-      NEXT_INSN;
-
-    insn_fload_3:
-      LOADF (3);
-      NEXT_INSN;
-
-    insn_dload_0:
-      LOADD (0);
-      NEXT_INSN;
-
-    insn_dload_1:
-      LOADD (1);
-      NEXT_INSN;
-
-    insn_dload_2:
-      LOADD (2);
-      NEXT_INSN;
-
-    insn_dload_3:
-      LOADD (3);
-      NEXT_INSN;
-
-    insn_aload_1:
-      LOADA(1);
-      NEXT_INSN;
-
-    insn_aload_2:
-      LOADA(2);
-      NEXT_INSN;
-
-    insn_aload_3:
-      LOADA(3);
-      NEXT_INSN;
-
-    insn_iaload:
-      {
-	jint index = POPI();
-	jintArray arr = (jintArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_laload:
-      {
-	jint index = POPI();
-	jlongArray arr = (jlongArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHL( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_faload:
-      {
-	jint index = POPI();
-	jfloatArray arr = (jfloatArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHF( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_daload:
-      {
-	jint index = POPI();
-	jdoubleArray arr = (jdoubleArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHD( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_aaload:
-      {
-	jint index = POPI();
-	jobjectArray arr = (jobjectArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHA( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_baload:
-      {
-	jint index = POPI();
-	jbyteArray arr = (jbyteArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_caload:
-      {
-	jint index = POPI();
-	jcharArray arr = (jcharArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_saload:
-      {
-	jint index = POPI();
-	jshortArray arr = (jshortArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	PUSHI( elements(arr)[index] );
-      }
-      NEXT_INSN;
-
-    insn_istore:
-      STOREI (GET1U ());
-      NEXT_INSN;
-
-    insn_lstore:
-      STOREL (GET1U ());
-      NEXT_INSN;
-
-    insn_fstore:
-      STOREF (GET1U ());
-      NEXT_INSN;
-
-    insn_dstore:
-      STORED (GET1U ());
-      NEXT_INSN;
-
-    insn_astore:
-      STOREA (GET1U ());
-      NEXT_INSN;
-
-    insn_istore_0:
-      STOREI (0);
-      NEXT_INSN;
-
-    insn_istore_1:
-      STOREI (1);
-      NEXT_INSN;
-
-    insn_istore_2:
-      STOREI (2);
-      NEXT_INSN;
-
-    insn_istore_3:
-      STOREI (3);
-      NEXT_INSN;
-
-    insn_lstore_0:
-      STOREL (0);
-      NEXT_INSN;
-
-    insn_lstore_1:
-      STOREL (1);
-      NEXT_INSN;
-
-    insn_lstore_2:
-      STOREL (2);
-      NEXT_INSN;
-
-    insn_lstore_3:
-      STOREL (3);
-      NEXT_INSN;
-
-    insn_fstore_0:
-      STOREF (0);
-      NEXT_INSN;
-
-    insn_fstore_1:
-      STOREF (1);
-      NEXT_INSN;
-
-    insn_fstore_2:
-      STOREF (2);
-      NEXT_INSN;
-
-    insn_fstore_3:
-      STOREF (3);
-      NEXT_INSN;
-
-    insn_dstore_0:
-      STORED (0);
-      NEXT_INSN;
-
-    insn_dstore_1:
-      STORED (1);
-      NEXT_INSN;
-
-    insn_dstore_2:
-      STORED (2);
-      NEXT_INSN;
-
-    insn_dstore_3:
-      STORED (3);
-      NEXT_INSN;
-
-    insn_astore_0:
-      STOREA(0);
-      NEXT_INSN;
-
-    insn_astore_1:
-      STOREA(1);
-      NEXT_INSN;
-
-    insn_astore_2:
-      STOREA(2);
-      NEXT_INSN;
-
-    insn_astore_3:
-      STOREA(3);
-      NEXT_INSN;
-
-    insn_iastore:
-      {
-	jint value = POPI();
-	jint index  = POPI();
-	jintArray arr = (jintArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_lastore:
-      {
-	jlong value = POPL();
-	jint index  = POPI();
-	jlongArray arr = (jlongArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_fastore:
-      {
-	jfloat value = POPF();
-	jint index  = POPI();
-	jfloatArray arr = (jfloatArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_dastore:
-      {
-	jdouble value = POPD();
-	jint index  = POPI();
-	jdoubleArray arr = (jdoubleArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_aastore:
-      {
-	jobject value = POPA();
-	jint index  = POPI();
-	jobjectArray arr = (jobjectArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	_Jv_CheckArrayStore (arr, value);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_bastore:
-      {
-	jbyte value = (jbyte) POPI();
-	jint index  = POPI();
-	jbyteArray arr = (jbyteArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_castore:
-      {
-	jchar value = (jchar) POPI();
-	jint index  = POPI();
-	jcharArray arr = (jcharArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_sastore:
-      {
-	jshort value = (jshort) POPI();
-	jint index  = POPI();
-	jshortArray arr = (jshortArray) POPA();
-	NULLARRAYCHECK (arr);
-	ARRAYBOUNDSCHECK (arr, index);
-	elements(arr)[index] = value;
-      }
-      NEXT_INSN;
-
-    insn_pop:
-      sp -= 1;
-      NEXT_INSN;
-
-    insn_pop2:
-      sp -= 2;
-      NEXT_INSN;
-
-    insn_dup:
-      sp[0] = sp[-1];
-      sp += 1;
-      NEXT_INSN;
-
-    insn_dup_x1:
-      dupx (sp, 1, 1); sp+=1;
-      NEXT_INSN;
-
-    insn_dup_x2:
-      dupx (sp, 1, 2); sp+=1;
-      NEXT_INSN;
-
-    insn_dup2:
-      sp[0] = sp[-2];
-      sp[1] = sp[-1];
-      sp += 2;
-      NEXT_INSN;
-
-    insn_dup2_x1:
-      dupx (sp, 2, 1); sp+=2;
-      NEXT_INSN;
-
-    insn_dup2_x2:
-      dupx (sp, 2, 2); sp+=2;
-      NEXT_INSN;
-
-    insn_swap:
-      {
-	jobject tmp1 = POPA();
-	jobject tmp2 = POPA();
-	PUSHA (tmp1);
-	PUSHA (tmp2);
-      }
-      NEXT_INSN;
-
-    insn_iadd:
-      BINOPI(+);
-      NEXT_INSN;
-
-    insn_ladd:
-      BINOPL(+);
-      NEXT_INSN;
-
-    insn_fadd:
-      BINOPF(+);
-      NEXT_INSN;
-
-    insn_dadd:
-      BINOPD(+);
-      NEXT_INSN;
-
-    insn_isub:
-      BINOPI(-);
-      NEXT_INSN;
-
-    insn_lsub:
-      BINOPL(-);
-      NEXT_INSN;
-
-    insn_fsub:
-      BINOPF(-);
-      NEXT_INSN;
-
-    insn_dsub:
-      BINOPD(-);
-      NEXT_INSN;
-
-    insn_imul:
-      BINOPI(*);
-      NEXT_INSN;
-
-    insn_lmul:
-      BINOPL(*);
-      NEXT_INSN;
-
-    insn_fmul:
-      BINOPF(*);
-      NEXT_INSN;
-
-    insn_dmul:
-      BINOPD(*);
-      NEXT_INSN;
-
-    insn_idiv:
-      {
-	SAVE_PC();
-	jint value2 = POPI();
-	jint value1 = POPI();
-	jint res = _Jv_divI (value1, value2);
-	PUSHI (res);
-      }
-      NEXT_INSN;
-
-    insn_ldiv:
-      {
-	SAVE_PC();
-	jlong value2 = POPL();
-	jlong value1 = POPL();
-	jlong res = _Jv_divJ (value1, value2);
-	PUSHL (res);
-      }
-      NEXT_INSN;
-
-    insn_fdiv:
-      {
-	jfloat value2 = POPF();
-	jfloat value1 = POPF();
-	jfloat res = value1 / value2;
-	PUSHF (res);
-      }
-      NEXT_INSN;
-
-    insn_ddiv:
-      {
-	jdouble value2 = POPD();
-	jdouble value1 = POPD();
-	jdouble res = value1 / value2;
-	PUSHD (res);
-      }
-      NEXT_INSN;
-
-    insn_irem:
-      {
-	SAVE_PC();
-	jint value2 = POPI();
-	jint value1 =  POPI();
-	jint res = _Jv_remI (value1, value2);
-	PUSHI (res);
-      }
-      NEXT_INSN;
-
-    insn_lrem:
-      {
-	SAVE_PC();
-	jlong value2 = POPL();
-	jlong value1 = POPL();
-	jlong res = _Jv_remJ (value1, value2);
-	PUSHL (res);
-      }
-      NEXT_INSN;
-
-    insn_frem:
-      {
-	jfloat value2 = POPF();
-	jfloat value1 = POPF();
-	jfloat res    = __ieee754_fmod (value1, value2);
-	PUSHF (res);
-      }
-      NEXT_INSN;
-
-    insn_drem:
-      {
-	jdouble value2 = POPD();
-	jdouble value1 = POPD();
-	jdouble res    = __ieee754_fmod (value1, value2);
-	PUSHD (res);
-      }
-      NEXT_INSN;
-
-    insn_ineg:
-      {
-	jint value = POPI();
-	PUSHI (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_lneg:
-      {
-	jlong value = POPL();
-	PUSHL (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_fneg:
-      {
-	jfloat value = POPF();
-	PUSHF (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_dneg:
-      {
-	jdouble value = POPD();
-	PUSHD (value * -1);
-      }
-      NEXT_INSN;
-
-    insn_ishl:
-      {
-	jint shift = (POPI() & 0x1f);
-	jint value = POPI();
-	PUSHI (value << shift);
-      }
-      NEXT_INSN;
-
-    insn_lshl:
-      {
-	jint shift = (POPI() & 0x3f);
-	jlong value = POPL();
-	PUSHL (value << shift);
-      }
-      NEXT_INSN;
-
-    insn_ishr:
-      {
-	jint shift = (POPI() & 0x1f);
-	jint value = POPI();
-	PUSHI (value >> shift);
-      }
-      NEXT_INSN;
-
-    insn_lshr:
-      {
-	jint shift = (POPI() & 0x3f);
-	jlong value = POPL();
-	PUSHL (value >> shift);
-      }
-      NEXT_INSN;
-
-    insn_iushr:
-      {
-	jint shift = (POPI() & 0x1f);
-	_Jv_uint value = (_Jv_uint) POPI();
-	PUSHI ((jint) (value >> shift));
-      }
-      NEXT_INSN;
-
-    insn_lushr:
-      {
-	jint shift = (POPI() & 0x3f);
-	_Jv_ulong value = (_Jv_ulong) POPL();
-	PUSHL ((jlong) (value >> shift));
-      }
-      NEXT_INSN;
-
-    insn_iand:
-      BINOPI (&);
-      NEXT_INSN;
-
-    insn_land:
-      BINOPL (&);
-      NEXT_INSN;
-
-    insn_ior:
-      BINOPI (|);
-      NEXT_INSN;
-
-    insn_lor:
-      BINOPL (|);
-      NEXT_INSN;
-
-    insn_ixor:
-      BINOPI (^);
-      NEXT_INSN;
-
-    insn_lxor:
-      BINOPL (^);
-      NEXT_INSN;
-
-    insn_iinc:
-      {
-	jint index  = GET1U ();
-	jint amount = GET1S ();
-	locals[index].i += amount;
-      }
-      NEXT_INSN;
-
-    insn_i2l:
-      {jlong value = POPI(); PUSHL (value);}
-      NEXT_INSN;
-
-    insn_i2f:
-      {jfloat value = POPI(); PUSHF (value);}
-      NEXT_INSN;
-
-    insn_i2d:
-      {jdouble value = POPI(); PUSHD (value);}
-      NEXT_INSN;
-
-    insn_l2i:
-      {jint value = POPL(); PUSHI (value);}
-      NEXT_INSN;
-
-    insn_l2f:
-      {jfloat value = POPL(); PUSHF (value);}
-      NEXT_INSN;
-
-    insn_l2d:
-      {jdouble value = POPL(); PUSHD (value);}
-      NEXT_INSN;
-
-    insn_f2i:
-      {
-	using namespace java::lang;
-	jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
-	PUSHI(value);
-      }
-      NEXT_INSN;
-
-    insn_f2l:
-      {
-	using namespace java::lang;
-	jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
-	PUSHL(value);
-      }
-      NEXT_INSN;
-
-    insn_f2d:
-      { jdouble value = POPF (); PUSHD(value); }
-      NEXT_INSN;
-
-    insn_d2i:
-      {
-	using namespace java::lang;
-	jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
-	PUSHI(value);
-      }
-      NEXT_INSN;
-
-    insn_d2l:
-      {
-	using namespace java::lang;
-	jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
-	PUSHL(value);
-      }
-      NEXT_INSN;
-
-    insn_d2f:
-      { jfloat value = POPD (); PUSHF(value); }
-      NEXT_INSN;
-
-    insn_i2b:
-      { jbyte value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_i2c:
-      { jchar value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_i2s:
-      { jshort value = POPI (); PUSHI(value); }
-      NEXT_INSN;
-
-    insn_lcmp:
-      {
-	jlong value2 = POPL ();
-	jlong value1 = POPL ();
-	if (value1 > value2)
-	  { PUSHI (1); }
-	else if (value1 == value2)
-	  { PUSHI (0); }
-	else
-	  { PUSHI (-1); }
-      }
-      NEXT_INSN;
-
-    insn_fcmpl:
-      tmpval = -1;
-      goto fcmp;
-
-    insn_fcmpg:
-      tmpval = 1;
-
-    fcmp:
-      {
-	jfloat value2 = POPF ();
-	jfloat value1 = POPF ();
-	if (value1 > value2)
-	  PUSHI (1);
-	else if (value1 == value2)
-	  PUSHI (0);
-	else if (value1 < value2)
-	  PUSHI (-1);
-	else
-	  PUSHI (tmpval);
-      }
-      NEXT_INSN;
-
-    insn_dcmpl:
-      tmpval = -1;
-      goto dcmp;
-
-    insn_dcmpg:
-      tmpval = 1;
-
-    dcmp:
-      {
-	jdouble value2 = POPD ();
-	jdouble value1 = POPD ();
-	if (value1 > value2)
-	  PUSHI (1);
-	else if (value1 == value2)
-	  PUSHI (0);
-	else if (value1 < value2)
-	  PUSHI (-1);
-	else
-	  PUSHI (tmpval);
-      }
-      NEXT_INSN;
-
-    insn_ifeq:
-      {
-	if (POPI() == 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifne:
-      {
-	if (POPI() != 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_iflt:
-      {
-	if (POPI() < 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifge:
-      {
-	if (POPI() >= 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifgt:
-      {
-	if (POPI() > 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifle:
-      {
-	if (POPI() <= 0)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpeq:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 == value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpne:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 != value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmplt:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 < value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpge:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 >= value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmpgt:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 > value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_icmple:
-      {
-	jint value2 = POPI();
-	jint value1 = POPI();
-	if (value1 <= value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_acmpeq:
-      {
-	jobject value2 = POPA();
-	jobject value1 = POPA();
-	if (value1 == value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_if_acmpne:
-      {
-	jobject value2 = POPA();
-	jobject value1 = POPA();
-	if (value1 != value2)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_goto_w:
-#ifndef DIRECT_THREADED
-      // For direct threaded, goto and goto_w are the same.
-      pc = pc - 1 + get4 (pc);
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_goto:
-      TAKE_GOTO;
-      NEXT_INSN;
-
-    insn_jsr_w:
-#ifndef DIRECT_THREADED
-      // For direct threaded, jsr and jsr_w are the same.
-      {
-	pc_t next = pc - 1 + get4 (pc);
-	pc += 4;
-	PUSHA ((jobject) pc);
-	pc = next;
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-    insn_jsr:
-      {
-	pc_t next = GOTO_VAL();
-	SKIP_GOTO;
-	PUSHA ((jobject) pc);
-	pc = next;
-      }
-      NEXT_INSN;
-
-    insn_ret:
-      {
-	jint index = GET1U ();
-	pc = (pc_t) PEEKA (index);
-      }
-      NEXT_INSN;
-
-    insn_tableswitch:
-      {
-#ifdef DIRECT_THREADED
-	void *def = (pc++)->datum;
-
-	int index = POPI();
-
-	jint low = INTVAL ();
-	jint high = INTVAL ();
-
-	if (index < low || index > high)
-	  pc = (insn_slot *) def;
-	else
-	  pc = (insn_slot *) ((pc + index - low)->datum);
-#else
-	pc_t base_pc = pc - 1;
-	int index = POPI ();
-
-	pc_t base = (pc_t) bytecode ();
-	while ((pc - base) % 4 != 0)
-	  ++pc;
-
-	jint def = get4 (pc);
-	jint low = get4 (pc + 4);
-	jint high = get4 (pc + 8);
-	if (index < low || index > high)
-	  pc = base_pc + def;
-	else
-	  pc = base_pc + get4 (pc + 4 * (index - low + 3));
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-    insn_lookupswitch:
-      {
-#ifdef DIRECT_THREADED
-	void *def = (pc++)->insn;
-
-	int index = POPI();
-
-	jint npairs = INTVAL ();
-
-	int max = npairs - 1;
-	int min = 0;
-
-	// Simple binary search...
-	while (min < max)
-	  {
-	    int half = (min + max) / 2;
-	    int match = pc[2 * half].int_val;
-
-	    if (index == match)
-	      {
-		// Found it.
-		pc = (insn_slot *) pc[2 * half + 1].datum;
-		NEXT_INSN;
-	      }
-	    else if (index < match)
-	      // We can use HALF - 1 here because we check again on
-	      // loop exit.
-	      max = half - 1;
-	    else
-	      // We can use HALF + 1 here because we check again on
-	      // loop exit.
-	      min = half + 1;
-	  }
-	if (index == pc[2 * min].int_val)
-	  pc = (insn_slot *) pc[2 * min + 1].datum;
-	else
-	  pc = (insn_slot *) def;
-#else
-	unsigned char *base_pc = pc-1;
-	int index = POPI();
-
-	unsigned char* base = bytecode ();
-	while ((pc-base) % 4 != 0)
-	  ++pc;
-
-	jint def     = get4 (pc);
-	jint npairs  = get4 (pc+4);
-
-	int max = npairs-1;
-	int min = 0;
-
-	// Simple binary search...
-	while (min < max)
-	  {
-	    int half = (min+max)/2;
-	    int match = get4 (pc+ 4*(2 + 2*half));
-
-	    if (index == match)
-	      min = max = half;
-	    else if (index < match)
-	      // We can use HALF - 1 here because we check again on
-	      // loop exit.
-	      max = half - 1;
-	    else
-	      // We can use HALF + 1 here because we check again on
-	      // loop exit.
-	      min = half + 1;
-	  }
-
-	if (index == get4 (pc+ 4*(2 + 2*min)))
-	  pc = base_pc + get4 (pc+ 4*(2 + 2*min + 1));
-	else
-	  pc = base_pc + def;    
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-    insn_areturn:
-      *(jobject *) retp = POPA ();
-      return;
-
-    insn_lreturn:
-      *(jlong *) retp = POPL ();
-      return;
-
-    insn_freturn:
-      *(jfloat *) retp = POPF ();
-      return;
-
-    insn_dreturn:
-      *(jdouble *) retp = POPD ();
-      return;
-
-    insn_ireturn:
-      *(jint *) retp = POPI ();
-      return;
-
-    insn_return:
-      return;
-
-    insn_getstatic:
-      {
-	jint fieldref_index = GET2U ();
-        SAVE_PC(); // Constant pool resolution could throw.
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	if ((field->flags & Modifier::STATIC) == 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field no longer static"));
-
-	jclass type = field->type;
-
-	// We rewrite the instruction once we discover what it refers
-	// to.
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes)
-	      {
-	      case 1:
-		PUSHI (*field->u.byte_addr);
-		newinsn = AMPAMP (getstatic_resolved_1);
-		break;
-
-	      case 2:
-		if (type == JvPrimClass (char))
-		  {
-		    PUSHI (*field->u.char_addr);
-		    newinsn = AMPAMP (getstatic_resolved_char);
-		  }
-		else
-		  {
-		    PUSHI (*field->u.short_addr);
-		    newinsn = AMPAMP (getstatic_resolved_short);
-		  }
-		break;
-
-	      case 4:
-	        PUSHI(*field->u.int_addr);
-		newinsn = AMPAMP (getstatic_resolved_4);
-		break;
-
-	      case 8:
-	        PUSHL(*field->u.long_addr);
-		newinsn = AMPAMP (getstatic_resolved_8);
-		break;
-	      }
-	  }
-	else
-	  {
-	    PUSHA(*field->u.object_addr);
-	    newinsn = AMPAMP (getstatic_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].datum = field->u.addr;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    getstatic_resolved_1:
-      PUSHI (*(jbyte *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_char:
-      PUSHI (*(jchar *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_short:
-      PUSHI (*(jshort *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_4:
-      PUSHI (*(jint *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_8:
-      PUSHL (*(jlong *) AVAL ());
-      NEXT_INSN;
-
-    getstatic_resolved_obj:
-      PUSHA (*(jobject *) AVAL ());
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_getfield:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	if ((field->flags & Modifier::STATIC) != 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field is static"));
-
-	jclass type = field->type;
-	jint field_offset = field->u.boffset;
-
-	jobject obj   = POPA();
-	NULLCHECK(obj);
-
-	void *newinsn = NULL;
-	_Jv_value *val = (_Jv_value *) ((char *)obj + field_offset);
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes)
-	      {
-	      case 1:
-	        PUSHI (val->byte_value);
-		newinsn = AMPAMP (getfield_resolved_1);
-		break;
-
-	      case 2:
-		if (type == JvPrimClass (char))
-		  {
-		    PUSHI (val->char_value);
-		    newinsn = AMPAMP (getfield_resolved_char);
-		  }
-		else
-		  {
-		    PUSHI (val->short_value);
-		    newinsn = AMPAMP (getfield_resolved_short);
-		  }
-		break;
-
-	      case 4:
-		PUSHI (val->int_value);
-		newinsn = AMPAMP (getfield_resolved_4);
-		break;
-
-	      case 8:
-	        PUSHL (val->long_value);
-		newinsn = AMPAMP (getfield_resolved_8);
-		break;
-	      }
-	  }
-	else
-	  {
-	    PUSHA (val->object_value);
-	    newinsn = AMPAMP (getfield_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].int_val = field_offset;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    getfield_resolved_1:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jbyte *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_char:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jchar *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_short:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jshort *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_4:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHI (*(jint *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_8:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHL (*(jlong *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-
-    getfield_resolved_obj:
-      {
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	PUSHA (*(jobject *) (obj + INTVAL ()));
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_putstatic:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	jclass type = field->type;
-
-	// ResolvePoolEntry cannot check this
-	if ((field->flags & Modifier::STATIC) == 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field no longer static"));
-
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes) 
-	      {
-	      case 1:
-		{
-		  jint value = POPI();
-		  *field->u.byte_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_1);
-		  break;
-		}
-
-	      case 2:
-		{
-		  jint value = POPI();
-		  *field->u.char_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_2);
-		  break;
-		}
-
-	      case 4:
-		{
-		  jint value = POPI();
-		  *field->u.int_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_4);
-		  break;
-		}
-
-	      case 8:
-		{
-		  jlong value = POPL();
-		  *field->u.long_addr = value;
-		  newinsn = AMPAMP (putstatic_resolved_8);
-		  break;
-		}
-	      }
-	  }
-	else
-	  {
-	    jobject value = POPA();
-	    *field->u.object_addr = value;
-	    newinsn = AMPAMP (putstatic_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].datum = field->u.addr;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    putstatic_resolved_1:
-      *(jbyte *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_2:
-      *(jchar *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_4:
-      *(jint *) AVAL () = POPI ();
-      NEXT_INSN;
-
-    putstatic_resolved_8:
-      *(jlong *) AVAL () = POPL ();
-      NEXT_INSN;
-
-    putstatic_resolved_obj:
-      *(jobject *) AVAL () = POPA ();
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_putfield:
-      {
-	SAVE_PC();
-	jint fieldref_index = GET2U ();
-	_Jv_Linker::resolve_pool_entry (meth->defining_class, fieldref_index);
-	_Jv_Field *field = pool_data[fieldref_index].field;
-
-	jclass type = field->type;
-
-	if ((field->flags & Modifier::STATIC) != 0)
-	  throw_incompatible_class_change_error 
-	    (JvNewStringLatin1 ("field is static"));
-
-	jint field_offset = field->u.boffset;
-
-	void *newinsn = NULL;
-	if (type->isPrimitive ())
-	  {
-	    switch (type->size_in_bytes) 
-	      {
-	      case 1:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jbyte*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_1);
-		  break;
-		}
-
-	      case 2:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jchar*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_2);
-		  break;
-		}
-
-	      case 4:
-		{
-		  jint    value = POPI();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jint*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_4);
-		  break;
-		}
-
-	      case 8:
-		{
-		  jlong   value = POPL();
-		  jobject obj   = POPA();
-		  NULLCHECK(obj);
-		  *(jlong*) ((char*)obj + field_offset) = value;
-		  newinsn = AMPAMP (putfield_resolved_8);
-		  break;
-		}
-	      }
-	  }
-	else
-	  {
-	    jobject value = POPA();
-	    jobject obj   = POPA();
-	    NULLCHECK(obj);
-	    *(jobject*) ((char*)obj + field_offset) = value;
-	    newinsn = AMPAMP (putfield_resolved_obj);
-	  }
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = newinsn;
-	pc[-1].int_val = field_offset;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    putfield_resolved_1:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jbyte *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_2:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jchar *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_4:
-      {
-	jint val = POPI ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jint *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_8:
-      {
-	jlong val = POPL ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jlong *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-
-    putfield_resolved_obj:
-      {
-	jobject val = POPA ();
-	char *obj = (char *) POPA ();
-	NULLCHECK (obj);
-	*(jobject *) (obj + INTVAL ()) = val;
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_invokespecial:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	// We don't use NULLCHECK here because we can't rely on that
-	// working for <init>.  So instead we do an explicit test.
-	if (! sp[0].o)
-	  {
-	    SAVE_PC();
-	    throw_null_pointer_exception ();
-	  }
-
-	fun = (void (*)()) rmeth->method->ncode;
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokespecial_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokespecial_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	// We don't use NULLCHECK here because we can't rely on that
-	// working for <init>.  So instead we do an explicit test.
-	if (! sp[0].o)
-	  {
-	    throw_null_pointer_exception ();
-	  }
-	fun = (void (*)()) rmeth->method->ncode;
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_invokestatic:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	fun = (void (*)()) rmeth->method->ncode;
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokestatic_resolved;
-	pc[-1].datum = rmeth;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokestatic_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	fun = (void (*)()) rmeth->method->ncode;
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_invokeinterface:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-
-	rmeth = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						   index)).rmethod;
-
-	sp -= rmeth->stack_item_count;
-
-	jobject rcv = sp[0].o;
-
-	NULLCHECK (rcv);
-
-	fun = (void (*)())
-	  _Jv_LookupInterfaceMethod (rcv->getClass (),
-				     rmeth->method->name,
-				     rmeth->method->signature);
-
-#ifdef DIRECT_THREADED
-	// Rewrite instruction so that we use a faster pre-resolved
-	// method.
-	pc[-2].insn = &&invokeinterface_resolved;
-	pc[-1].datum = rmeth;
-#else
-	// Skip dummy bytes.
-	pc += 2;
-#endif /* DIRECT_THREADED */
-      }
-      goto perform_invoke;
-
-#ifdef DIRECT_THREADED
-    invokeinterface_resolved:
-      {
-	SAVE_PC();
-	rmeth = (_Jv_ResolvedMethod *) AVAL ();
-	sp -= rmeth->stack_item_count;
-	jobject rcv = sp[0].o;
-	NULLCHECK (rcv);
-	fun = (void (*)())
-	  _Jv_LookupInterfaceMethod (rcv->getClass (),
-				     rmeth->method->name,
-				     rmeth->method->signature);
-      }
-      goto perform_invoke;
-#endif /* DIRECT_THREADED */
-
-    insn_new:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-							  index)).clazz;
-	/* VM spec, section 3.11.5 */
-	if ((klass->getModifiers() & Modifier::ABSTRACT)
-	    || klass->isInterface())
-	  throw new java::lang::InstantiationException;
-	jobject res = _Jv_AllocObject (klass);
-	PUSHA (res);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&new_resolved;
-	pc[-1].datum = klass;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    new_resolved:
-      {
-	jclass klass = (jclass) AVAL ();
-	jobject res = _Jv_AllocObject (klass);
-	PUSHA (res);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_newarray:
-      {
-	int atype = GET1U ();
-	int size  = POPI();
-	jobject result = _Jv_NewArray (atype, size);
-	PUSHA (result);
-      }
-      NEXT_INSN;
-
-    insn_anewarray:
-      {
-	SAVE_PC();
-	int index = GET2U ();
-	jclass klass = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-							  index)).clazz;
-	int size  = POPI();
-	jobject result = _Jv_NewObjectArray (size, klass, 0);
-	PUSHA (result);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&anewarray_resolved;
-	pc[-1].datum = klass;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    anewarray_resolved:
-      {
-	jclass klass = (jclass) AVAL ();
-	int size = POPI ();
-	jobject result = _Jv_NewObjectArray (size, klass, 0);
-	PUSHA (result);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_arraylength:
-      {
-	__JArray *arr = (__JArray*)POPA();
-	NULLARRAYCHECK (arr);
-	PUSHI (arr->length);
-      }
-      NEXT_INSN;
-
-    insn_athrow:
-      {
-	jobject value = POPA();
-	throw static_cast<jthrowable>(value);
-      }
-      NEXT_INSN;
-
-    insn_checkcast:
-      {
-        SAVE_PC();
-	jobject value = POPA();
-	jint index = GET2U ();
-	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						       index)).clazz;
-
-	value = (jobject) _Jv_CheckCast (to, value);
-
-	PUSHA (value);
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&checkcast_resolved;
-	pc[-1].datum = to;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    checkcast_resolved:
-      {
-        SAVE_PC();
-	jobject value = POPA ();
-	jclass to = (jclass) AVAL ();
-	value = (jobject) _Jv_CheckCast (to, value);
-	PUSHA (value);
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_instanceof:
-      {
-        SAVE_PC();
-	jobject value = POPA();
-	jint index = GET2U ();
-	jclass to = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-						       index)).clazz;
-	PUSHI (to->isInstance (value));
-
-#ifdef DIRECT_THREADED
-	pc[-2].insn = &&instanceof_resolved;
-	pc[-1].datum = to;
-#endif /* DIRECT_THREADED */
-      }
-      NEXT_INSN;
-
-#ifdef DIRECT_THREADED
-    instanceof_resolved:
-      {
-	jobject value = POPA ();
-	jclass to = (jclass) AVAL ();
-	PUSHI (to->isInstance (value));
-      }
-      NEXT_INSN;
-#endif /* DIRECT_THREADED */
-
-    insn_monitorenter:
-      {
-	jobject value = POPA();
-	NULLCHECK(value);
-	_Jv_MonitorEnter (value);
-      }
-      NEXT_INSN;
-
-    insn_monitorexit:
-      {
-	jobject value = POPA();
-	NULLCHECK(value);
-	_Jv_MonitorExit (value);
-      }
-      NEXT_INSN;
-
-    insn_ifnull:
-      {
-	jobject val = POPA();
-	if (val == NULL)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_ifnonnull:
-      {
-	jobject val = POPA();
-	if (val != NULL)
-	  TAKE_GOTO;
-	else
-	  SKIP_GOTO;
-      }
-      NEXT_INSN;
-
-    insn_multianewarray:
-      {
-	SAVE_PC();
-	int kind_index = GET2U ();
-	int dim        = GET1U ();
-
-	jclass type    
-	  = (_Jv_Linker::resolve_pool_entry (meth->defining_class,
-					       kind_index)).clazz;
-	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
-
-	for (int i = dim - 1; i >= 0; i--)
-	  {
-	    sizes[i] = POPI ();
-	  }
-
-	jobject res    = _Jv_NewMultiArray (type,dim, sizes);
-
-	PUSHA (res);
-      }
-      NEXT_INSN;
-
-#ifndef DIRECT_THREADED
-    insn_wide:
-      {
-	jint the_mod_op = get1u (pc++);
-	jint wide       = get2u (pc); pc += 2;
-
-	switch (the_mod_op)
-	  {
-	  case op_istore:
-	    STOREI (wide);
-	    NEXT_INSN;
-
-	  case op_fstore:
-	    STOREF (wide);
-	    NEXT_INSN;
-
-	  case op_astore:
-	    STOREA (wide);
-	    NEXT_INSN;
-
-	  case op_lload:
-	    LOADL (wide);
-	    NEXT_INSN;
-
-	  case op_dload:
-	    LOADD (wide);
-	    NEXT_INSN;
-
-	  case op_iload:
-	    LOADI (wide);
-	    NEXT_INSN;
-
-	  case op_fload:
-	    LOADF (wide);
-	    NEXT_INSN;
-
-	  case op_aload:
-	    LOADA (wide);
-	    NEXT_INSN;
-
-	  case op_lstore:
-	    STOREL (wide);
-	    NEXT_INSN;
-
-	  case op_dstore:
-	    STORED (wide);
-	    NEXT_INSN;
-
-	  case op_ret:
-	    pc = (unsigned char*) PEEKA (wide);
-	    NEXT_INSN;
-
-	  case op_iinc:
-	    {
-	      jint amount = get2s (pc); pc += 2;
-	      jint value = PEEKI (wide);
-	      POKEI (wide, value+amount);
-	    }
-	    NEXT_INSN;
-
-	  default:
-	    throw_internal_error ("illegal bytecode modified by wide");
-	  }
-
-      }
-#endif /* DIRECT_THREADED */
-    }
-  catch (java::lang::Throwable *ex)
-    {
-#ifdef DIRECT_THREADED
-      void *logical_pc = (void *) ((insn_slot *) pc - 1);
-#else
-      int logical_pc = pc - 1 - bytecode ();
-#endif
-      _Jv_InterpException *exc = meth->exceptions ();
-      jclass exc_class = ex->getClass ();
-
-      for (int i = 0; i < meth->exc_count; i++)
-	{
-	  if (PCVAL (exc[i].start_pc) <= logical_pc
-	      && logical_pc < PCVAL (exc[i].end_pc))
-	    {
-#ifdef DIRECT_THREADED
-	      jclass handler = (jclass) exc[i].handler_type.p;
-#else
-	      jclass handler = NULL;
-	      if (exc[i].handler_type.i != 0)
-		handler = (_Jv_Linker::resolve_pool_entry (defining_class,
-							     exc[i].handler_type.i)).clazz;
-#endif /* DIRECT_THREADED */
-
-	      if (handler == NULL || handler->isAssignableFrom (exc_class))
-		{
-#ifdef DIRECT_THREADED
-		  pc = (insn_slot *) exc[i].handler_pc.p;
-#else
-		  pc = bytecode () + exc[i].handler_pc.i;
-#endif /* DIRECT_THREADED */
-		  sp = stack;
-		  sp++->o = ex; // Push exception.
-		  NEXT_INSN;
-		}
-	    }
-	}
-
-      // No handler, so re-throw.
-      throw ex;
-    }
-}
-
-static void
-throw_internal_error (const char *msg)
-{
-  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
-}
-
-static void 
-throw_incompatible_class_change_error (jstring msg)
-{
-  throw new java::lang::IncompatibleClassChangeError (msg);
-}
-
-static void 
-throw_null_pointer_exception ()
-{
-  throw new java::lang::NullPointerException;
-}
-
-/* Look up source code line number for given bytecode (or direct threaded
-   interpreter) PC. */
-int
-_Jv_InterpMethod::get_source_line(pc_t mpc)
-{
-  int line = line_table_len > 0 ? line_table[0].line : -1;
-  for (int i = 1; i < line_table_len; i++)
-    if (line_table[i].pc > mpc)
-      break;
-    else
-      line = line_table[i].line;
-
-  return line;
-}
-
-/** Do static initialization for fields with a constant initializer */
-void
-_Jv_InitField (jobject obj, jclass klass, int index)
-{
-  using namespace java::lang::reflect;
-
-  if (obj != 0 && klass == 0)
-    klass = obj->getClass ();
-
-  if (!_Jv_IsInterpretedClass (klass))
-    return;
-
-  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
-
-  _Jv_Field * field = (&klass->fields[0]) + index;
-
-  if (index > klass->field_count)
-    throw_internal_error ("field out of range");
-
-  int init = iclass->field_initializers[index];
-  if (init == 0)
-    return;
-
-  _Jv_Constants *pool = &klass->constants;
-  int tag = pool->tags[init];
-
-  if (! field->isResolved ())
-    throw_internal_error ("initializing unresolved field");
-
-  if (obj==0 && ((field->flags & Modifier::STATIC) == 0))
-    throw_internal_error ("initializing non-static field with no object");
-
-  void *addr = 0;
-
-  if ((field->flags & Modifier::STATIC) != 0)
-    addr = (void*) field->u.addr;
-  else
-    addr = (void*) (((char*)obj) + field->u.boffset);
-
-  switch (tag)
-    {
-    case JV_CONSTANT_String:
-      {
-	jstring str;
-	str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
-	pool->data[init].string = str;
-	pool->tags[init] = JV_CONSTANT_ResolvedString;
-      }
-      /* fall through */
-
-    case JV_CONSTANT_ResolvedString:
-      if (! (field->type == &java::lang::String::class$
- 	     || field->type == &java::lang::Class::class$))
-	throw_class_format_error ("string initialiser to non-string field");
-
-      *(jstring*)addr = pool->data[init].string;
-      break;
-
-    case JV_CONSTANT_Integer:
-      {
-	int value = pool->data[init].i;
-
-	if (field->type == JvPrimClass (boolean))
-	  *(jboolean*)addr = (jboolean)value;
-	
-	else if (field->type == JvPrimClass (byte))
-	  *(jbyte*)addr = (jbyte)value;
-	
-	else if (field->type == JvPrimClass (char))
-	  *(jchar*)addr = (jchar)value;
-
-	else if (field->type == JvPrimClass (short))
-	  *(jshort*)addr = (jshort)value;
-	
-	else if (field->type == JvPrimClass (int))
-	  *(jint*)addr = (jint)value;
-
-	else
-	  throw_class_format_error ("erroneous field initializer");
-      }  
-      break;
-
-    case JV_CONSTANT_Long:
-      if (field->type != JvPrimClass (long))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
-      break;
-
-    case JV_CONSTANT_Float:
-      if (field->type != JvPrimClass (float))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jfloat*)addr = pool->data[init].f;
-      break;
-
-    case JV_CONSTANT_Double:
-      if (field->type != JvPrimClass (double))
-	throw_class_format_error ("erroneous field initializer");
-
-      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
-      break;
-
-    default:
-      throw_class_format_error ("erroneous field initializer");
-    }
-}
-
-inline static unsigned char*
-skip_one_type (unsigned char* ptr)
-{
-  int ch = *ptr++;
-
-  while (ch == '[')
-    { 
-      ch = *ptr++;
-    }
-  
-  if (ch == 'L')
-    {
-      do { ch = *ptr++; } while (ch != ';');
-    }
-
-  return ptr;
-}
-
-static ffi_type*
-get_ffi_type_from_signature (unsigned char* ptr)
-{
-  switch (*ptr) 
-    {
-    case 'L':
-    case '[':
-      return &ffi_type_pointer;
-      break;
-
-    case 'Z':
-      // On some platforms a bool is a byte, on others an int.
-      if (sizeof (jboolean) == sizeof (jbyte))
-	return &ffi_type_sint8;
-      else
-	{
-	  JvAssert (sizeof (jbyte) == sizeof (jint));
-	  return &ffi_type_sint32;
-	}
-      break;
-
-    case 'B':
-      return &ffi_type_sint8;
-      break;
-      
-    case 'C':
-      return &ffi_type_uint16;
-      break;
-	  
-    case 'S': 
-      return &ffi_type_sint16;
-      break;
-	  
-    case 'I':
-      return &ffi_type_sint32;
-      break;
-	  
-    case 'J':
-      return &ffi_type_sint64;
-      break;
-	  
-    case 'F':
-      return &ffi_type_float;
-      break;
-	  
-    case 'D':
-      return &ffi_type_double;
-      break;
+    case 'B':
+      return &ffi_type_sint8;
+      break;
+      
+    case 'C':
+      return &ffi_type_uint16;
+      break;
+	  
+    case 'S': 
+      return &ffi_type_sint16;
+      break;
+	  
+    case 'I':
+      return &ffi_type_sint32;
+      break;
+	  
+    case 'J':
+      return &ffi_type_sint64;
+      break;
+	  
+    case 'F':
+      return &ffi_type_float;
+      break;
+	  
+    case 'D':
+      return &ffi_type_double;
+      break;
 
     case 'V':
       return &ffi_type_void;
@@ -3654,9 +1266,19 @@
   if ((self->accflags & Modifier::SYNCHRONIZED) != 0)
     {
       if (staticp)
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
+        {
+        if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		  fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class_debug;
+		else
+		  fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
+        }
       else
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object; 
+        {
+	      if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object_debug;
+		  else
+		  	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object;
+        } 
     }
   else
     {
@@ -3661,9 +1283,19 @@
   else
     {
       if (staticp)
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
+        {
+	      if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class_debug;
+		  else
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
+        }
       else
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+        {
+	      if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal_debug;
+		  else
+		    fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+        }
     }
 
   FFI_PREP_RAW_CLOSURE (&closure->closure,
Index: stacktrace.cc
===================================================================
--- /notnfs/kgallowa/vanilla/libjava/stacktrace.cc	(revision 115852)
+++ /notnfs/kgallowa/vanilla/libjava/stacktrace.cc	(working copy)
@@ -22,6 +22,7 @@
 #include <java/lang/Long.h>
 #include <java/util/ArrayList.h>
 #include <java/util/IdentityHashMap.h>
+#include <gnu/classpath/jdwp/Jdwp.h>
 #include <gnu/java/lang/MainThread.h>
 #include <gnu/gcj/runtime/NameFinder.h>
 #include <gnu/gcj/runtime/StringBuffer.h>
@@ -111,7 +112,13 @@
   // correspondance between call frames in the interpreted stack and occurances
   // of _Jv_InterpMethod::run() on the native stack.
 #ifdef INTERPRETER
-  void *interp_run = (void *) &_Jv_InterpMethod::run;
+  void *interp_run = NULL;
+  
+  if (::gnu::classpath::jdwp::Jdwp::isDebugging)
+  	interp_run = (void *) &_Jv_InterpMethod::run_debug;
+  else
+    interp_run = (void *) &_Jv_InterpMethod::run;
+  	
   if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
     {
       state->frames[pos].type = frame_interpreter;

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-03 13:45                   ` Kyle Galloway
@ 2006-08-03 17:25                     ` Tom Tromey
  2006-08-15 20:40                       ` Kyle Galloway
  0 siblings, 1 reply; 16+ messages in thread
From: Tom Tromey @ 2006-08-03 17:25 UTC (permalink / raw)
  To: Kyle Galloway; +Cc: java-patches

>>>>> "Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:

Kyle> I decided to isolate the split from any extra stuff that needs to be
Kyle> added by doing it in 2 seperate patches.  Once this one goes in, I
Kyle> will submit another to fill in DEBUG_LOCALS_INSN for the debugging
Kyle> case.

Great.

This patch is ok, please commit... if you don't have write access,
let's set that up -- send me email.

Tom

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-03 17:25                     ` Tom Tromey
@ 2006-08-15 20:40                       ` Kyle Galloway
  2006-08-15 20:44                         ` Tom Tromey
  0 siblings, 1 reply; 16+ messages in thread
From: Kyle Galloway @ 2006-08-15 20:40 UTC (permalink / raw)
  To: java-patches

Tom Tromey wrote:
>>>>>> "Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:
>>>>>>             
>
> Kyle> I decided to isolate the split from any extra stuff that needs to be
> Kyle> added by doing it in 2 seperate patches.  Once this one goes in, I
> Kyle> will submit another to fill in DEBUG_LOCALS_INSN for the debugging
> Kyle> case.
>
> Great.
>
> This patch is ok, please commit... if you don't have write access,
> let's set that up -- send me email.
>
> Tom
>   
Comitted.

2006-08-15  Kyle Galloway  <kgallowa@redhat.com>

  * include/java-interp.h (_Jv_InterpMethod::run_debug): New method.
  * interpret.cc: Added placeholder for debug variable type info to STORE*
  macros.
  (_Jv_InterpMethod::run_debug): New method.
  (_Jv_InterpMethod::run_sync_object_debug): New method.
  (_Jv_InterpMethod::run_sync_class_debug): New method.
  (_Jv_InterpMethod::run_normal_debug): New method.
  (_Jv_InterpMethod::run_class_debug): New method.
  (_Jv_InterpMethod::ncode ()): Changed to select either debug or normal
  versions of these functions.
  * interpret-run.cc: New file, holds contents of old 	
  _Jv_InterpMethod::run
  method.
  * stacktrace.cc (_Jv_StackTrace::UnwindTraceFn): Changed to select
  appropriate function for debug or normal mode.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-15 20:40                       ` Kyle Galloway
@ 2006-08-15 20:44                         ` Tom Tromey
  2006-08-15 21:06                           ` Kyle Galloway
  0 siblings, 1 reply; 16+ messages in thread
From: Tom Tromey @ 2006-08-15 20:44 UTC (permalink / raw)
  To: Kyle Galloway; +Cc: java-patches

>>>>> "Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:

Kyle> Comitted.

Thanks.  You forgot to check in the ChangeLog entry though.

Tom

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: RFA: Changes to interpreter to avoid non-debugging slowdown
  2006-08-15 20:44                         ` Tom Tromey
@ 2006-08-15 21:06                           ` Kyle Galloway
  0 siblings, 0 replies; 16+ messages in thread
From: Kyle Galloway @ 2006-08-15 21:06 UTC (permalink / raw)
  To: java-patches

Tom Tromey wrote:
>>>>>> "Kyle" == Kyle Galloway <kgallowa@redhat.com> writes:
>>>>>>             
>
> Kyle> Comitted.
>
> Thanks.  You forgot to check in the ChangeLog entry though.
>
> Tom
>   
Sure did...fixed.

Kyle

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2006-08-15 21:06 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-07-28 22:09 RFA: Changes to interpreter to avoid non-debugging slowdown Kyle Galloway
2006-07-31 18:42 ` Tom Tromey
2006-08-01 13:37   ` Kyle Galloway
2006-08-01 15:09     ` Tom Tromey
2006-08-01 16:05       ` Keith Seitz
2006-08-01 16:10         ` Tom Tromey
2006-08-01 17:01           ` Kyle Galloway
2006-08-01 22:56             ` Tom Tromey
2006-08-02 14:27               ` Kyle Galloway
2006-08-02 15:05               ` Kyle Galloway
2006-08-02 22:56                 ` Tom Tromey
2006-08-03 13:45                   ` Kyle Galloway
2006-08-03 17:25                     ` Tom Tromey
2006-08-15 20:40                       ` Kyle Galloway
2006-08-15 20:44                         ` Tom Tromey
2006-08-15 21:06                           ` Kyle Galloway

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).