This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: FYI: direct threaded interpreter


I'm checking this in.

This changes the bytecode interpreter to be direct threaded.  This
gives us a nice performance boost.

This version of the patch can be compiled in two different ways by
tweaking a #define in interpret.cc.  In one mode we revert to a pure
interpreter, and by default we use direct threading.  The latter is
faster but uses a bit more memory; the former is slower but perhaps
more appropriate for severely constrained environments.

I haven't added any configury support for disabling the direct
threading.

This version of the patch runs the test suite with no regressions.  I
tested it both ways, on x86 Red Hat Linux 7.3.

Tom


Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>
	* verify.cc (branch_prepass): Updated for change to exception
	handler type.
	(verify_instructions_0): Likewise.
	* defineclass.cc (handleCodeAttribute): Initialize `prepared'.
	(handleExceptionTableEntry): Updated for change to exception
	handler type.
	* java/lang/Class.h (Class): Removed _Jv_InterpMethodInvocation.
	* include/java-interp.h (_Jv_InterpMethodInvocation): Removed.
	(union _Jv_InterpPC): New.
	(class _Jv_InterpException): Changed types to _Jv_InterpPC.
	(class _Jv_InterpMethod): Added new `prepared' field.
	(class _Jv_InterpMethod): Added `compile' method.  Removed
	`continue1' and `find_exception'.  Changed arguments to `run'.
	* interpret.cc (union insn_slot): New.
	(find_exception): Removed.
	(run_normal): Removed most logic.
	(run_synch_object): Likewise; also, use JvSynchronize.
	(run_synch_class): Likewise.
	(run): Removed.
	(continue1): Renamed as `run'.  Compile bytecode if required.
	Add new code to allow refinement of direct-threaded code at
	runtime.  Handle exceptions.
	(SAVE_PC): Removed.
	(compile): New method.
	(SET_ONE, SET_INSN, SET_INT, SET_DATUM): New defines.
	(NULLARRAYCHECK): Don't use SAVE_PC.
	(pc_t): New typedef.
	(TAKE_GOTO, GET1S, GET1U, GET2U, AVAL1U, AVAL2U, AVAL2UP,
	SKIP_GOTO, GOTO_VAL, PCVAL, AMPAMP): New macros.

Index: defineclass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/defineclass.cc,v
retrieving revision 1.28
diff -u -r1.28 defineclass.cc
--- defineclass.cc 20 Jun 2002 15:10:49 -0000 1.28
+++ defineclass.cc 24 Jun 2002 20:35:41 -0000
@@ -1258,6 +1258,7 @@
   method->exc_count      = exc_table_length;
   method->defining_class = def;
   method->self           = &def->methods[method_index];
+  method->prepared       = NULL;
 
   // grab the byte code!
   memcpy ((void*) method->bytecode (),
@@ -1267,7 +1268,7 @@
   def->interpreted_methods[method_index] = method;
 }
 
-void _Jv_ClassReader::handleExceptionTableEntry 
+void _Jv_ClassReader::handleExceptionTableEntry
   (int method_index, int exc_index, 
    int start_pc, int end_pc, int handler_pc, int catch_type)
 {
@@ -1275,10 +1276,10 @@
     (def->interpreted_methods[method_index]);
   _Jv_InterpException *exc = method->exceptions ();
 
-  exc[exc_index].start_pc     = start_pc;
-  exc[exc_index].end_pc       = end_pc;
-  exc[exc_index].handler_pc   = handler_pc;
-  exc[exc_index].handler_type = catch_type;
+  exc[exc_index].start_pc.i     = start_pc;
+  exc[exc_index].end_pc.i       = end_pc;
+  exc[exc_index].handler_pc.i   = handler_pc;
+  exc[exc_index].handler_type.i = catch_type;
 }
 
 void _Jv_ClassReader::handleMethodsEnd ()
Index: interpret.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/interpret.cc,v
retrieving revision 1.32
diff -u -r1.32 interpret.cc
--- interpret.cc 26 Apr 2002 22:39:29 -0000 1.32
+++ interpret.cc 24 Jun 2002 20:35:42 -0000
@@ -1,6 +1,6 @@
 // interpret.cc - Code for the interpreter
 
-/* Copyright (C) 1999, 2000, 2001 , 2002 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation
 
    This file is part of libgcj.
 
@@ -12,6 +12,11 @@
 
 #include <config.h>
 
+// Define this to get the direct-threaded interpreter.  If undefined,
+// we revert to a basic bytecode interpreter.  The former is faster
+// but uses more memory.
+#define DIRECT_THREADED
+
 #pragma implementation "java-interp.h"
 
 #include <jvm.h>
@@ -51,6 +56,26 @@
 
 extern "C" double __ieee754_fmod (double,double);
 
+// This represents a single slot in the "compiled" form of the
+// bytecode.
+union insn_slot
+{
+  // Address of code.
+  void *insn;
+  // An integer value used by an instruction.
+  jint int_val;
+  // A pointer value used by an instruction.
+  void *datum;
+};
+
+// The type of the PC depends on whether we're doing direct threading
+// or a more ordinary bytecode interpreter.
+#ifdef DIRECT_THREADED
+typedef insn_slot *pc_t;
+#else
+typedef unsigned char *pc_t;
+#endif
+
 static inline void dupx (_Jv_word *sp, int n, int x)
 {
   // first "slide" n+x elements n to the right
@@ -199,12 +224,12 @@
 
 #ifdef HANDLE_SEGV
 #define NULLCHECK(X) 
-#define NULLARRAYCHECK(X) do { SAVE_PC; } while (0)
+#define NULLARRAYCHECK(X)
 #else
 #define NULLCHECK(X) \
   do { if ((X)==NULL) throw_null_pointer_exception (); } while (0)
 #define NULLARRAYCHECK(X) \
-  do { if ((X)==NULL) { SAVE_PC; throw_null_pointer_exception (); } } while (0)
+  do { if ((X)==NULL) { throw_null_pointer_exception (); } } while (0)
 #endif
 
 #define ARRAYBOUNDSCHECK(array, index)					      \
@@ -215,230 +240,534 @@
     }									      \
   while (0)
 
-// this method starts the actual running of the method.  It is inlined
-// in three different variants in the static methods run_normal,
-// run_sync_object and run_sync_class (see below).  Those static methods
-// are installed directly in the stub for this method (by
-// _Jv_InterpMethod::ncode, in resolve.cc).
-
-inline jobject
-_Jv_InterpMethod::run (ffi_cif* cif,
-		       void *retp,
-		       ffi_raw *args,
-		       _Jv_InterpMethodInvocation *inv)
+void _Jv_InterpMethod::run_normal (ffi_cif *,
+				   void* ret,
+				   ffi_raw * args,
+				   void* __this)
 {
-  inv->running  = this;
-  inv->pc       = bytecode ();
-  inv->sp       = inv->stack_base ();
-  _Jv_word *locals = inv->local_base ();
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+  _this->run (ret, args);
+}
 
-  /* 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, args_raw_size);
+void _Jv_InterpMethod::run_synch_object (ffi_cif *,
+					 void* ret,
+					 ffi_raw * args,
+					 void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
 
- next_segment:
+  jobject rcv = (jobject) args[0].ptr;
+  JvSynchronize mutex (rcv);
 
-  jobject ex = NULL;
+  _this->run (ret, args);
+}
 
-  try
-    {
-      continue1 (inv);
-    }
-  catch (java::lang::Throwable *ex2)
-    {
-      ex = ex2;
-    }
+void _Jv_InterpMethod::run_synch_class (ffi_cif *,
+					void* ret,
+					ffi_raw * args,
+					void* __this)
+{
+  _Jv_InterpMethod *_this = (_Jv_InterpMethod *) __this;
+
+  jclass sync = _this->defining_class;
+  JvSynchronize mutex (sync);
+
+  _this->run (ret, args);
+}
+
+#ifdef DIRECT_THREADED
+// "Compile" a method by turning it from bytecode to direct-threaded
+// code.
+void
+_Jv_InterpMethod::compile (const void * const *insn_targets)
+{
+  insn_slot *insns = NULL;
+  int next = 0;
+  unsigned char *codestart = bytecode ();
+  unsigned char *end = codestart + code_length;
+  _Jv_word *pool_data = defining_class->constants.data;
+
+#define SET_ONE(Field, Value)						      \
+  do									      \
+    {									      \
+      if (first_pass)							      \
+	++next;								      \
+      else								      \
+	insns[next++].Field = Value;					      \
+    }									      \
+  while (0)
 
-  if (ex == 0)			// no exception...
+#define SET_INSN(Value) SET_ONE (insn, (void *) Value)
+#define SET_INT(Value) SET_ONE (int_val, Value)
+#define SET_DATUM(Value) SET_ONE (datum, Value)
+
+  // Map from bytecode PC to slot in INSNS.
+  int *pc_mapping = (int *) __builtin_alloca (sizeof (int) * code_length);
+  for (int i = 0; i < code_length; ++i)
+    pc_mapping[i] = -1;
+
+  for (int i = 0; i < 2; ++i)
     {
-      /* define sp locally, so the POP? macros will pick it up */
-      _Jv_word *sp = inv->sp;
-      int rtype = cif->rtype->type;
+      jboolean first_pass = i == 0;
 
-      if (rtype == FFI_TYPE_POINTER)
-	{
-	  jobject r = POPA();
-	  *(jobject*) retp = r;
-	  return 0;
-	}
-      else if (rtype == FFI_TYPE_SINT32)
+      if (! first_pass)
 	{
-	  jint r = POPI();
-	  *(jint*)retp = r;
-	  return 0;
+	  insns = (insn_slot *) _Jv_Malloc (sizeof (insn_slot) * next);
+	  next = 0;
 	}
-      else if (rtype == FFI_TYPE_VOID)
-	{
-	  return 0;
-	}
-      else switch (rtype)
+
+      unsigned char *pc = codestart;
+      while (pc < end)
 	{
-	case FFI_TYPE_FLOAT:
-	  {
-	    jfloat r = POPF();
-	    *(jfloat*)retp = r;
-	    return 0;
-	  }
-      
-	case FFI_TYPE_DOUBLE:
-	  {
-	    jdouble r = POPD();
-	    *(jdouble*)retp = r;
-	    return 0;
-	  }
+	  int base_pc_val = pc - codestart;
+	  if (first_pass)
+	    pc_mapping[base_pc_val] = next;
+
+	  java_opcode opcode = (java_opcode) *pc++;
+	  // Just elide NOPs.
+	  if (opcode == op_nop)
+	    continue;
+	  SET_INSN (insn_targets[opcode]);
 
-	case FFI_TYPE_UINT8:
-	case FFI_TYPE_UINT16:
-	case FFI_TYPE_UINT32:
-	case FFI_TYPE_SINT8:
-	case FFI_TYPE_SINT16:
-	  {
-	    jint r = POPI();
-	    *(jint*)retp = r;
-	    return 0;
-	  }
-      
-	case FFI_TYPE_SINT64:
-	  {
-	    jlong r = POPL();
-	    *(jlong*)retp = r;
-	    return 0;
-	  }
-	
-	default:
-	  throw_internal_error ("unknown return type");
-	}
-    }
+	  switch (opcode)
+	    {
+	    case op_nop:
+	    case op_aconst_null:
+	    case op_iconst_m1:
+	    case op_iconst_0:
+	    case op_iconst_1:
+	    case op_iconst_2:
+	    case op_iconst_3:
+	    case op_iconst_4:
+	    case op_iconst_5:
+	    case op_lconst_0:
+	    case op_lconst_1:
+	    case op_fconst_0:
+	    case op_fconst_1:
+	    case op_fconst_2:
+	    case op_dconst_0:
+	    case op_dconst_1:
+	    case op_iload_0:
+	    case op_iload_1:
+	    case op_iload_2:
+	    case op_iload_3:
+	    case op_lload_0:
+	    case op_lload_1:
+	    case op_lload_2:
+	    case op_lload_3:
+	    case op_fload_0:
+	    case op_fload_1:
+	    case op_fload_2:
+	    case op_fload_3:
+	    case op_dload_0:
+	    case op_dload_1:
+	    case op_dload_2:
+	    case op_dload_3:
+	    case op_aload_0:
+	    case op_aload_1:
+	    case op_aload_2:
+	    case op_aload_3:
+	    case op_iaload:
+	    case op_laload:
+	    case op_faload:
+	    case op_daload:
+	    case op_aaload:
+	    case op_baload:
+	    case op_caload:
+	    case op_saload:
+	    case op_istore_0:
+	    case op_istore_1:
+	    case op_istore_2:
+	    case op_istore_3:
+	    case op_lstore_0:
+	    case op_lstore_1:
+	    case op_lstore_2:
+	    case op_lstore_3:
+	    case op_fstore_0:
+	    case op_fstore_1:
+	    case op_fstore_2:
+	    case op_fstore_3:
+	    case op_dstore_0:
+	    case op_dstore_1:
+	    case op_dstore_2:
+	    case op_dstore_3:
+	    case op_astore_0:
+	    case op_astore_1:
+	    case op_astore_2:
+	    case op_astore_3:
+	    case op_iastore:
+	    case op_lastore:
+	    case op_fastore:
+	    case op_dastore:
+	    case op_aastore:
+	    case op_bastore:
+	    case op_castore:
+	    case op_sastore:
+	    case op_pop:
+	    case op_pop2:
+	    case op_dup:
+	    case op_dup_x1:
+	    case op_dup_x2:
+	    case op_dup2:
+	    case op_dup2_x1:
+	    case op_dup2_x2:
+	    case op_swap:
+	    case op_iadd:
+	    case op_isub:
+	    case op_imul:
+	    case op_idiv:
+	    case op_irem:
+	    case op_ishl:
+	    case op_ishr:
+	    case op_iushr:
+	    case op_iand:
+	    case op_ior:
+	    case op_ixor:
+	    case op_ladd:
+	    case op_lsub:
+	    case op_lmul:
+	    case op_ldiv:
+	    case op_lrem:
+	    case op_lshl:
+	    case op_lshr:
+	    case op_lushr:
+	    case op_land:
+	    case op_lor:
+	    case op_lxor:
+	    case op_fadd:
+	    case op_fsub:
+	    case op_fmul:
+	    case op_fdiv:
+	    case op_frem:
+	    case op_dadd:
+	    case op_dsub:
+	    case op_dmul:
+	    case op_ddiv:
+	    case op_drem:
+	    case op_ineg:
+	    case op_i2b:
+	    case op_i2c:
+	    case op_i2s:
+	    case op_lneg:
+	    case op_fneg:
+	    case op_dneg:
+	    case op_i2l:
+	    case op_i2f:
+	    case op_i2d:
+	    case op_l2i:
+	    case op_l2f:
+	    case op_l2d:
+	    case op_f2i:
+	    case op_f2l:
+	    case op_f2d:
+	    case op_d2i:
+	    case op_d2l:
+	    case op_d2f:
+	    case op_lcmp:
+	    case op_fcmpl:
+	    case op_fcmpg:
+	    case op_dcmpl:
+	    case op_dcmpg:
+	    case op_monitorenter:
+	    case op_monitorexit:
+	    case op_ireturn:
+	    case op_lreturn:
+	    case op_freturn:
+	    case op_dreturn:
+	    case op_areturn:
+	    case op_return:
+	    case op_athrow:
+	    case op_arraylength:
+	      // No argument, nothing else to do.
+	      break;
+
+	    case op_bipush:
+	      SET_INT (get1s (pc));
+	      ++pc;
+	      break;
 
-  /** handle an exception */
-  if ( find_exception (ex, inv) )
-    goto next_segment;
+	    case op_ldc:
+	      {
+		int index = get1u (pc);
+		++pc;
+		SET_DATUM (pool_data[index].o);
+	      }
+	      break;
 
-  return ex;
-}
+	    case op_ret:
+	    case op_iload:
+	    case op_lload:
+	    case op_fload:
+	    case op_dload:
+	    case op_aload:
+	    case op_istore:
+	    case op_lstore:
+	    case op_fstore:
+	    case op_dstore:
+	    case op_astore:
+	    case op_newarray:
+	      SET_INT (get1u (pc));
+	      ++pc;
+	      break;
+
+	    case op_iinc:
+	      SET_INT (get1u (pc));
+	      SET_INT (get1s (pc + 1));
+	      pc += 2;
+	      break;
 
-#define SAVE_PC   inv->pc = pc
+	    case op_ldc_w:
+	      {
+		int index = get2u (pc);
+		pc += 2;
+		SET_DATUM (pool_data[index].o);
+	      }
+	      break;
 
-bool _Jv_InterpMethod::find_exception (jobject ex,
-				       _Jv_InterpMethodInvocation *inv)
-{
-  // We subtract one because the PC was incremented before it was
-  // saved.
-  int logical_pc = inv->pc - 1 - bytecode ();
-  _Jv_InterpException *exc = exceptions ();
-  jclass exc_class = ex->getClass ();
+	    case op_ldc2_w:
+	      {
+		int index = get2u (pc);
+		pc += 2;
+		SET_DATUM (&pool_data[index]);
+	      }
+	      break;
 
-  for (int i = 0; i < exc_count; i++)
-    {
-      if (exc[i].start_pc <= logical_pc && logical_pc < exc[i].end_pc)
-	{	
-	  jclass handler;
-
-	  if (exc[i].handler_type != 0)
-	    handler = (_Jv_ResolvePoolEntry (defining_class, 
-					     exc[i].handler_type)).clazz;
-	  else
-	    handler = NULL;
-	  
-	  if (handler==NULL || handler->isAssignableFrom (exc_class))
-	    {
-	      inv->pc = bytecode () + exc[i].handler_pc;
-	      inv->sp = inv->stack_base (); // reset stack
-	      (inv->sp++)->o = ex; // push exception
-	      return true;
-	    }
-	}
-    }
-  return false;
-}
+	    case op_sipush:
+	      SET_INT (get2s (pc));
+	      pc += 2;
+	      break;
+
+	    case op_new:
+	    case op_getstatic:
+	    case op_getfield:
+	    case op_putfield:
+	    case op_putstatic:
+	    case op_anewarray:
+	    case op_instanceof:
+	    case op_checkcast:
+	    case op_invokespecial:
+	    case op_invokestatic:
+	    case op_invokevirtual:
+	      SET_INT (get2u (pc));
+	      pc += 2;
+	      break;
+
+	    case op_multianewarray:
+	      SET_INT (get2u (pc));
+	      SET_INT (get1u (pc + 2));
+	      pc += 3;
+	      break;
+
+	    case op_jsr:
+	    case op_ifeq:
+	    case op_ifne:
+	    case op_iflt:
+	    case op_ifge:
+	    case op_ifgt:
+	    case op_ifle:
+	    case op_if_icmpeq:
+	    case op_if_icmpne:
+	    case op_if_icmplt:
+	    case op_if_icmpge:
+	    case op_if_icmpgt:
+	    case op_if_icmple:
+	    case op_if_acmpeq:
+	    case op_if_acmpne:
+	    case op_ifnull:
+	    case op_ifnonnull:
+	    case op_goto:
+	      {
+		int offset = get2s (pc);
+		pc += 2;
 
-void _Jv_InterpMethod::run_normal (ffi_cif* cif,
-				   void* ret,
-				   ffi_raw * args,
-				   void* __this)
-{
-  _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
+		int new_pc = base_pc_val + offset;
 
-  // we do the alloca of the method invocation here, to allow the method
-  // "run" ro be inlined.  Otherwise gcc will ignore the inline directive.
-  int storage_size = _this->max_stack+_this->max_locals;
-  _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 
-    __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
-		      + storage_size * sizeof (_Jv_word));
+		bool orig_was_goto = opcode == op_goto;
 
-  jobject ex = _this->run (cif, ret, args, inv);
-  if (ex != 0) throw static_cast<jthrowable>(ex);
-}
+		// Thread jumps.  We limit the loop count; this lets
+		// us avoid infinite loops if the bytecode contains
+		// such.  `10' is arbitrary.
+		int count = 10;
+		while (codestart[new_pc] == op_goto && count-- > 0)
+		  new_pc += get2s (&codestart[new_pc + 1]);
+
+		// If the jump takes us to a `return' instruction and
+		// the original branch was an unconditional goto, then
+		// we hoist the return.
+		opcode = (java_opcode) codestart[new_pc];
+		if (orig_was_goto
+		    && (opcode == op_ireturn || opcode == op_lreturn
+			|| opcode == op_freturn || opcode == op_dreturn
+			|| opcode == op_areturn || opcode == op_return))
+		  {
+		    --next;
+		    SET_INSN (insn_targets[opcode]);
+		  }
+		else
+		  SET_DATUM (&insns[pc_mapping[new_pc]]);
+	      }
+	      break;
 
-void _Jv_InterpMethod::run_synch_object (ffi_cif* cif,
-					 void* ret,
-					 ffi_raw * args,
-					 void* __this)
-{
-  _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
-  jobject rcv = (jobject)args[0].ptr;
+	    case op_tableswitch:
+	      {
+		while ((pc - codestart) % 4 != 0)
+		  ++pc;
 
-  int storage_size = _this->max_stack+_this->max_locals;
-  _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 
-    __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
-		      + storage_size * sizeof (_Jv_word));
-
-  _Jv_MonitorEnter (rcv);
-  jobject ex = _this->run (cif, ret, args, inv);
-  _Jv_MonitorExit (rcv);
+		jint def = get4 (pc);
+		SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
+		pc += 4;
+
+		int low = get4 (pc);
+		SET_INT (low);
+		pc += 4;
+		int high = get4 (pc);
+		SET_INT (high);
+		pc += 4;
+
+		for (int i = low; i <= high; ++i)
+		  {
+		    SET_DATUM (&insns[pc_mapping[base_pc_val + get4 (pc)]]);
+		    pc += 4;
+		  }
+	      }
+	      break;
 
-  if (ex != 0) throw static_cast<jthrowable>(ex);
-}
+	    case op_lookupswitch:
+	      {
+		while ((pc - codestart) % 4 != 0)
+		  ++pc;
 
-void _Jv_InterpMethod::run_synch_class (ffi_cif* cif,
-					void* ret,
-					ffi_raw * args,
-					void* __this)
-{
-  _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this;
-  jclass  sync = _this->defining_class;
+		jint def = get4 (pc);
+		SET_DATUM (&insns[pc_mapping[base_pc_val + def]]);
+		pc += 4;
+
+		jint npairs = get4 (pc);
+		pc += 4;
+		SET_INT (npairs);
+
+		while (npairs-- > 0)
+		  {
+		    jint match = get4 (pc);
+		    jint offset = get4 (pc + 4);
+		    SET_INT (match);
+		    SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
+		    pc += 8;
+		  }
+	      }
+	      break;
 
-  int storage_size = _this->max_stack+_this->max_locals;
-  _Jv_InterpMethodInvocation* inv = (_Jv_InterpMethodInvocation*) 
-    __builtin_alloca (sizeof (_Jv_InterpMethodInvocation)
-		      + storage_size * sizeof (_Jv_word));
-
-  _Jv_MonitorEnter (sync);
-  jobject ex = _this->run (cif, ret, args, inv);
-  _Jv_MonitorExit (sync);
+	    case op_invokeinterface:
+	      {
+		jint index = get2u (pc);
+		pc += 2;
+		// We ignore the next two bytes.
+		pc += 2;
+		SET_INT (index);
+	      }
+	      break;
 
-  if (ex != 0) throw static_cast<jthrowable>(ex);
-}
+	    case op_wide:
+	      {
+		opcode = (java_opcode) get1u (pc);
+		pc += 1;
+		jint val = get2u (pc);
+		pc += 2;
+
+		// We implement narrow and wide instructions using the
+		// same code in the interpreter.  So we rewrite the
+		// instruction slot here.
+		if (! first_pass)
+		  insns[next - 1].insn = (void *) insn_targets[opcode];
+		SET_INT (val);
+
+		if (opcode == op_iinc)
+		  {
+		    SET_INT (get2s (pc));
+		    pc += 2;
+		  }
+	      }
+	      break;
 
-/*
-  This proceeds execution, as designated in "inv".  If an exception
-  happens, then it is simply thrown, and handled in Java.  Thus, the pc
-  needs to be stored in the inv->pc at all times, so we can figure
-  out which handler (if any) to invoke.
-
-  One design issue, which I have not completely considered, is if it
-  should be possible to have interpreted classes linked in!  Seldom used
-  (or non-critical) classes could reasonably be interpreted.  
-*/
+	    case op_jsr_w:
+	    case op_goto_w:
+	      {
+		jint offset = get4 (pc);
+		pc += 4;
+		SET_DATUM (&insns[pc_mapping[base_pc_val + offset]]);
+	      }
+	      break;
 
+	    // Some "can't happen" cases that we include for
+	    // error-checking purposes.
+	    case op_putfield_1:
+	    case op_putfield_2:
+	    case op_putfield_4:
+	    case op_putfield_8:
+	    case op_putfield_a:
+	    case op_putstatic_1:
+	    case op_putstatic_2:
+	    case op_putstatic_4:
+	    case op_putstatic_8:
+	    case op_putstatic_a:
+	    case op_getfield_1:
+	    case op_getfield_2s:
+	    case op_getfield_2u:
+	    case op_getfield_4:
+	    case op_getfield_8:
+	    case op_getfield_a:
+	    case op_getstatic_1:
+	    case op_getstatic_2s:
+	    case op_getstatic_2u:
+	    case op_getstatic_4:
+	    case op_getstatic_8:
+	    case op_getstatic_a:
+	    default:
+	      // Fail somehow.
+	      break;
+	    }
+	}
+    }
 
-void _Jv_InterpMethod::continue1 (_Jv_InterpMethodInvocation *inv)
+  // Now update exceptions.
+  _Jv_InterpException *exc = exceptions ();
+  for (int i = 0; i < exc_count; ++i)
+    {
+      exc[i].start_pc.p = &insns[pc_mapping[exc[i].start_pc.i]];
+      exc[i].end_pc.p = &insns[pc_mapping[exc[i].end_pc.i]];
+      exc[i].handler_pc.p = &insns[pc_mapping[exc[i].handler_pc.i]];
+      jclass handler = (_Jv_ResolvePoolEntry (defining_class,
+					      exc[i].handler_type.i)).clazz;
+      exc[i].handler_type.p = handler;
+    }
+
+  prepared = insns;
+}
+#endif /* DIRECT_THREADED */
+
+void
+_Jv_InterpMethod::run (void *retp, ffi_raw *args)
 {
   using namespace java::lang::reflect;
 
-  _Jv_word      *sp     = inv->sp;
-  unsigned char *pc     = inv->pc;
-  _Jv_word               *locals = inv->local_base ();
+  _Jv_word stack[max_stack];
+  _Jv_word *sp = stack;
 
-  _Jv_word *pool_data   = defining_class->constants.data;
-  
-  /* these two are used in the invokeXXX instructions */
+  _Jv_word locals[max_locals];
+
+  /* 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, args_raw_size);
+
+  _Jv_word *pool_data = defining_class->constants.data;
+
+  /* These three are temporaries for common code used by several
+     instructions.  */
   void (*fun)();
   _Jv_ResolvedMethod* rmeth;
+  int tmpval;
 
 #define INSN_LABEL(op) &&insn_##op
-#define GOTO_INSN(op) goto *(insn_target[op])
 
   static const void *const insn_target[] = 
   {
@@ -638,62 +967,92 @@
     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),
+    0
   };
 
-  /* If the macro INLINE_SWITCH is not defined, then the main loop
-     operates as one big (normal) switch statement.  If it is defined,
-     then the case selection is performed `inline' in the end of the
-     code for each case.  The latter saves a native branch instruction
-     for each java-instruction, but expands the code size somewhat.
+  pc_t pc;
 
-     NOTE: On i386 defining INLINE_SWITCH improves over all
-     performance approximately seven percent, but it may be different
-     for other machines.  At some point, this may be made into a proper
-     configuration parameter.  */
+#ifdef DIRECT_THREADED
 
-#define INLINE_SWITCH 
+#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.
+  if (prepared == NULL)
+    compile (insn_target);
+  pc = (insn_slot *) prepared;
 
-#ifdef  INLINE_SWITCH
+#else
 
-#define NEXT_INSN do { GOTO_INSN(*pc++); } while (0)
+#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))
+#define AVAL1U() ({ int index = get1u (pc++); pool_data[index].o; })
+#define AVAL2U() ({ int index = get2u (pc); pc += 2; pool_data[index].o; })
+#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
 
-  NEXT_INSN;
-#else
+  pc = bytecode ();
 
-#define NEXT_INSN goto next_insn
+#endif /* DIRECT_THREADED */
 
- next_insn:
-  GOTO_INSN (*pc++);
+#define TAKE_GOTO pc = GOTO_VAL ()
 
-#endif
+  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.  */
+      /* 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);
+    insn_aload_0:		// 0x2a
+      LOADA (0);
       NEXT_INSN;
 
-     insn_iload:		// 0x15
-      LOADI (get1u (pc++));
+    insn_iload:		// 0x15
+      LOADI (GET1U ());
       NEXT_INSN;
 
-     insn_iload_1:		// 0x1b
+    insn_iload_1:		// 0x1b
       LOADI (1);
       NEXT_INSN;
 
-     insn_invokevirtual:	// 0xb6
-      SAVE_PC;
+    insn_invokevirtual:	// 0xb6
       {
-	int index = get2u (pc); pc += 2;
+	int index = GET2U ();
 
 	/* _Jv_ResolvePoolEntry returns immediately if the value already
 	 * is resolved.  If we want to clutter up the code here to gain
@@ -719,13 +1078,47 @@
 	else
 	  {
 	    jobject rcv = sp[0].o;
-	    _Jv_VTable *table = *(_Jv_VTable**)rcv;
-	    fun = (void (*)()) table->get_method(rmeth->vtable_index);
+	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
+	    fun = (void (*)()) table->get_method (rmeth->vtable_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:
+      {
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	// We don't use NULLCHECK here because we can't rely on that
+	// working if the method is final.  So instead we do an
+	// explicit test.
+	if (! sp[0].o)
+	  throw new java::lang::NullPointerException;
+
+	if (rmeth->vtable_index == -1)
+	  {
+	    // final methods do not appear in the vtable,
+	    // if it does not appear in the superclass.
+	    fun = (void (*)()) rmeth->method->ncode;
+	  }
+	else
+	  {
+	    jobject rcv = sp[0].o;
+	    _Jv_VTable *table = *(_Jv_VTable**) rcv;
+	    fun = (void (*)()) table->get_method (rmeth->vtable_index);
 	  }
       }
       goto perform_invoke;
+#endif /* DIRECT_THREADED */
 
-     perform_invoke:
+    perform_invoke:
       {
 	/* here goes the magic again... */
 	ffi_cif *cif = &rmeth->cif;
@@ -757,231 +1150,227 @@
 	  {
 	    /* skip */
 	  }
-	else switch (rtype) 
+	else
 	  {
-	  case FFI_TYPE_SINT8:
-	    {
-	      jbyte value = (*(jint*)&rvalue) & 0xff;
-	      PUSHI (value);
-	    }
-	    break;
-
-	  case FFI_TYPE_SINT16:
-	    {
-	      jshort value = (*(jint*)&rvalue) & 0xffff;
-	      PUSHI (value);
-	    }
-	    break;
+	    switch (rtype)
+	      {
+	      case FFI_TYPE_SINT8:
+		{
+		  jbyte value = (*(jint*)&rvalue) & 0xff;
+		  PUSHI (value);
+		}
+		break;
 
-	  case FFI_TYPE_UINT16:
-	    {
-	      jint value = (*(jint*)&rvalue) & 0xffff;
-	      PUSHI (value);
-	    }
-	    break;
+	      case FFI_TYPE_SINT16:
+		{
+		  jshort value = (*(jint*)&rvalue) & 0xffff;
+		  PUSHI (value);
+		}
+		break;
 
-	  case FFI_TYPE_FLOAT:
-	    PUSHF (*(jfloat*)&rvalue);
-	    break;
-
-	  case FFI_TYPE_DOUBLE:
-	    PUSHD (rvalue);
-	    break;
-
-	  case FFI_TYPE_SINT64:
-	    PUSHL (*(jlong*)&rvalue);
-	    break;
+	      case FFI_TYPE_UINT16:
+		{
+		  jint value = (*(jint*)&rvalue) & 0xffff;
+		  PUSHI (value);
+		}
+		break;
 
-	  default:
-	    throw_internal_error ("unknown return type in invokeXXX");
-	  }
+	      case FFI_TYPE_FLOAT:
+		PUSHF (*(jfloat*)&rvalue);
+		break;
 
-      }
-      NEXT_INSN;
+	      case FFI_TYPE_DOUBLE:
+		PUSHD (rvalue);
+		break;
 
+	      case FFI_TYPE_SINT64:
+		PUSHL (*(jlong*)&rvalue);
+		break;
 
-     insn_nop:
+	      default:
+		throw_internal_error ("unknown return type in invokeXXX");
+	      }
+	  }
+      }
       NEXT_INSN;
 
-     insn_aconst_null:
+    insn_aconst_null:
       PUSHA (NULL);
       NEXT_INSN;
 
-     insn_iconst_m1:
+    insn_iconst_m1:
       PUSHI (-1);
       NEXT_INSN;
 
-     insn_iconst_0:
+    insn_iconst_0:
       PUSHI (0);
       NEXT_INSN;
 
-     insn_iconst_1:
+    insn_iconst_1:
       PUSHI (1);
       NEXT_INSN;
 
-     insn_iconst_2:
+    insn_iconst_2:
       PUSHI (2);
       NEXT_INSN;
 
-     insn_iconst_3:
+    insn_iconst_3:
       PUSHI (3);
       NEXT_INSN;
 
-     insn_iconst_4:
+    insn_iconst_4:
       PUSHI (4);
       NEXT_INSN;
 
-     insn_iconst_5:
+    insn_iconst_5:
       PUSHI (5);
       NEXT_INSN;
 
-     insn_lconst_0:
+    insn_lconst_0:
       PUSHL (0);
       NEXT_INSN;
 
-     insn_lconst_1:
+    insn_lconst_1:
       PUSHL (1);
       NEXT_INSN;
 
-     insn_fconst_0:
+    insn_fconst_0:
       PUSHF (0);
       NEXT_INSN;
 
-     insn_fconst_1:
+    insn_fconst_1:
       PUSHF (1);
       NEXT_INSN;
 
-     insn_fconst_2:
+    insn_fconst_2:
       PUSHF (2);
       NEXT_INSN;
 
-     insn_dconst_0:
+    insn_dconst_0:
       PUSHD (0);
       NEXT_INSN;
 
-     insn_dconst_1:
+    insn_dconst_1:
       PUSHD (1);
       NEXT_INSN;
 
-     insn_bipush:
-      PUSHI (get1s(pc++));
+    insn_bipush:
+      // For direct threaded, bipush and sipush are the same.
+#ifndef DIRECT_THREADED
+      PUSHI (GET1S ());
       NEXT_INSN;
-
-     insn_sipush:
-      PUSHI (get2s(pc)); pc += 2;
+#endif /* DIRECT_THREADED */
+    insn_sipush:
+      PUSHI (GET2S ());
       NEXT_INSN;
 
-     insn_ldc:
-      {
-	int index = get1u (pc++);
-	PUSHA(pool_data[index].o);
-      }
+    insn_ldc:
+      // For direct threaded, ldc and ldc_w are the same.
+#ifndef DIRECT_THREADED
+      PUSHA ((jobject) AVAL1U ());
       NEXT_INSN;
-
-     insn_ldc_w:
-      {
-	int index = get2u (pc); pc += 2;
-	PUSHA(pool_data[index].o);
-      }
+#endif /* DIRECT_THREADED */
+    insn_ldc_w:
+      PUSHA ((jobject) AVAL2U ());
       NEXT_INSN;
 
-     insn_ldc2_w:
+    insn_ldc2_w:
       {
-	int index = get2u (pc); pc += 2;
-	memcpy (sp, &pool_data[index], 2*sizeof (_Jv_word));
+	void *where = AVAL2UP ();
+	memcpy (sp, where, 2*sizeof (_Jv_word));
 	sp += 2;
       }
       NEXT_INSN;
 
-     insn_lload:
-      LOADL (get1u (pc++));
+    insn_lload:
+      LOADL (GET1U ());
       NEXT_INSN;
 
-     insn_fload:
-      LOADF (get1u (pc++));
+    insn_fload:
+      LOADF (GET1U ());
       NEXT_INSN;
 
-     insn_dload:
-      LOADD (get1u (pc++));
+    insn_dload:
+      LOADD (GET1U ());
       NEXT_INSN;
 
-     insn_aload:
-      LOADA (get1u (pc++));
+    insn_aload:
+      LOADA (GET1U ());
       NEXT_INSN;
 
-     insn_iload_0:
+    insn_iload_0:
       LOADI (0);
       NEXT_INSN;
 
-     insn_iload_2:
+    insn_iload_2:
       LOADI (2);
       NEXT_INSN;
 
-     insn_iload_3:
+    insn_iload_3:
       LOADI (3);
       NEXT_INSN;
 
-     insn_lload_0:
+    insn_lload_0:
       LOADL (0);
       NEXT_INSN;
 
-     insn_lload_1:
+    insn_lload_1:
       LOADL (1);
       NEXT_INSN;
 
-     insn_lload_2:
+    insn_lload_2:
       LOADL (2);
       NEXT_INSN;
 
-     insn_lload_3:
+    insn_lload_3:
       LOADL (3);
       NEXT_INSN;
 
-     insn_fload_0:
+    insn_fload_0:
       LOADF (0);
       NEXT_INSN;
 
-     insn_fload_1:
+    insn_fload_1:
       LOADF (1);
       NEXT_INSN;
 
-     insn_fload_2:
+    insn_fload_2:
       LOADF (2);
       NEXT_INSN;
 
-     insn_fload_3:
+    insn_fload_3:
       LOADF (3);
       NEXT_INSN;
 
-     insn_dload_0:
+    insn_dload_0:
       LOADD (0);
       NEXT_INSN;
 
-     insn_dload_1:
+    insn_dload_1:
       LOADD (1);
       NEXT_INSN;
 
-     insn_dload_2:
+    insn_dload_2:
       LOADD (2);
       NEXT_INSN;
 
-     insn_dload_3:
+    insn_dload_3:
       LOADD (3);
       NEXT_INSN;
 
-     insn_aload_1:
+    insn_aload_1:
       LOADA(1);
       NEXT_INSN;
 
-     insn_aload_2:
+    insn_aload_2:
       LOADA(2);
       NEXT_INSN;
 
-     insn_aload_3:
+    insn_aload_3:
       LOADA(3);
       NEXT_INSN;
 
-     insn_iaload:
+    insn_iaload:
       {
 	jint index = POPI();
 	jintArray arr = (jintArray) POPA();
@@ -991,7 +1380,7 @@
       }
       NEXT_INSN;
 
-     insn_laload:
+    insn_laload:
       {
 	jint index = POPI();
 	jlongArray arr = (jlongArray) POPA();
@@ -1001,7 +1390,7 @@
       }
       NEXT_INSN;
 
-     insn_faload:
+    insn_faload:
       {
 	jint index = POPI();
 	jfloatArray arr = (jfloatArray) POPA();
@@ -1011,7 +1400,7 @@
       }
       NEXT_INSN;
 
-     insn_daload:
+    insn_daload:
       {
 	jint index = POPI();
 	jdoubleArray arr = (jdoubleArray) POPA();
@@ -1021,7 +1410,7 @@
       }
       NEXT_INSN;
 
-     insn_aaload:
+    insn_aaload:
       {
 	jint index = POPI();
 	jobjectArray arr = (jobjectArray) POPA();
@@ -1031,7 +1420,7 @@
       }
       NEXT_INSN;
 
-     insn_baload:
+    insn_baload:
       {
 	jint index = POPI();
 	jbyteArray arr = (jbyteArray) POPA();
@@ -1041,7 +1430,7 @@
       }
       NEXT_INSN;
 
-     insn_caload:
+    insn_caload:
       {
 	jint index = POPI();
 	jcharArray arr = (jcharArray) POPA();
@@ -1051,7 +1440,7 @@
       }
       NEXT_INSN;
 
-     insn_saload:
+    insn_saload:
       {
 	jint index = POPI();
 	jshortArray arr = (jshortArray) POPA();
@@ -1061,107 +1450,107 @@
       }
       NEXT_INSN;
 
-     insn_istore:
-      STOREI (get1u (pc++));
+    insn_istore:
+      STOREI (GET1U ());
       NEXT_INSN;
 
-     insn_lstore:
-      STOREL (get1u (pc++));
+    insn_lstore:
+      STOREL (GET1U ());
       NEXT_INSN;
 
-     insn_fstore:
-      STOREF (get1u (pc++));
+    insn_fstore:
+      STOREF (GET1U ());
       NEXT_INSN;
 
-     insn_dstore:
-      STORED (get1u (pc++));
+    insn_dstore:
+      STORED (GET1U ());
       NEXT_INSN;
 
-     insn_astore:
-      STOREA (get1u (pc++));
+    insn_astore:
+      STOREA (GET1U ());
       NEXT_INSN;
 
-     insn_istore_0:
+    insn_istore_0:
       STOREI (0);
       NEXT_INSN;
 
-     insn_istore_1:
+    insn_istore_1:
       STOREI (1);
       NEXT_INSN;
 
-     insn_istore_2:
+    insn_istore_2:
       STOREI (2);
       NEXT_INSN;
 
-     insn_istore_3:
+    insn_istore_3:
       STOREI (3);
       NEXT_INSN;
 
-     insn_lstore_0:
+    insn_lstore_0:
       STOREL (0);
       NEXT_INSN;
 
-     insn_lstore_1:
+    insn_lstore_1:
       STOREL (1);
       NEXT_INSN;
 
-     insn_lstore_2:
+    insn_lstore_2:
       STOREL (2);
       NEXT_INSN;
 
-     insn_lstore_3:
+    insn_lstore_3:
       STOREL (3);
       NEXT_INSN;
 
-     insn_fstore_0:
+    insn_fstore_0:
       STOREF (0);
       NEXT_INSN;
 
-     insn_fstore_1:
+    insn_fstore_1:
       STOREF (1);
       NEXT_INSN;
 
-     insn_fstore_2:
+    insn_fstore_2:
       STOREF (2);
       NEXT_INSN;
 
-     insn_fstore_3:
+    insn_fstore_3:
       STOREF (3);
       NEXT_INSN;
 
-     insn_dstore_0:
+    insn_dstore_0:
       STORED (0);
       NEXT_INSN;
 
-     insn_dstore_1:
+    insn_dstore_1:
       STORED (1);
       NEXT_INSN;
 
-     insn_dstore_2:
+    insn_dstore_2:
       STORED (2);
       NEXT_INSN;
 
-     insn_dstore_3:
+    insn_dstore_3:
       STORED (3);
       NEXT_INSN;
 
-     insn_astore_0:
+    insn_astore_0:
       STOREA(0);
       NEXT_INSN;
 
-     insn_astore_1:
+    insn_astore_1:
       STOREA(1);
       NEXT_INSN;
 
-     insn_astore_2:
+    insn_astore_2:
       STOREA(2);
       NEXT_INSN;
 
-     insn_astore_3:
+    insn_astore_3:
       STOREA(3);
       NEXT_INSN;
 
-     insn_iastore:
+    insn_iastore:
       {
 	jint value = POPI();
 	jint index  = POPI();
@@ -1172,7 +1561,7 @@
       }
       NEXT_INSN;
 
-     insn_lastore:
+    insn_lastore:
       {
 	jlong value = POPL();
 	jint index  = POPI();
@@ -1183,7 +1572,7 @@
       }
       NEXT_INSN;
 
-     insn_fastore:
+    insn_fastore:
       {
 	jfloat value = POPF();
 	jint index  = POPI();
@@ -1194,7 +1583,7 @@
       }
       NEXT_INSN;
 
-     insn_dastore:
+    insn_dastore:
       {
 	jdouble value = POPD();
 	jint index  = POPI();
@@ -1205,7 +1594,7 @@
       }
       NEXT_INSN;
 
-     insn_aastore:
+    insn_aastore:
       {
 	jobject value = POPA();
 	jint index  = POPI();
@@ -1217,7 +1606,7 @@
       }
       NEXT_INSN;
 
-     insn_bastore:
+    insn_bastore:
       {
 	jbyte value = (jbyte) POPI();
 	jint index  = POPI();
@@ -1228,7 +1617,7 @@
       }
       NEXT_INSN;
 
-     insn_castore:
+    insn_castore:
       {
 	jchar value = (jchar) POPI();
 	jint index  = POPI();
@@ -1239,7 +1628,7 @@
       }
       NEXT_INSN;
 
-     insn_sastore:
+    insn_sastore:
       {
 	jshort value = (jshort) POPI();
 	jint index  = POPI();
@@ -1250,42 +1639,42 @@
       }
       NEXT_INSN;
 
-     insn_pop:
+    insn_pop:
       sp -= 1;
       NEXT_INSN;
 
-     insn_pop2:
+    insn_pop2:
       sp -= 2;
       NEXT_INSN;
 
-     insn_dup:
+    insn_dup:
       sp[0] = sp[-1];
       sp += 1;
       NEXT_INSN;
 
-     insn_dup_x1:
+    insn_dup_x1:
       dupx (sp, 1, 1); sp+=1;
       NEXT_INSN;
 
-     insn_dup_x2:
+    insn_dup_x2:
       dupx (sp, 1, 2); sp+=1;
       NEXT_INSN;
 
-     insn_dup2:
+    insn_dup2:
       sp[0] = sp[-2];
       sp[1] = sp[-1];
       sp += 2;
       NEXT_INSN;
 
-     insn_dup2_x1:
+    insn_dup2_x1:
       dupx (sp, 2, 1); sp+=2;
       NEXT_INSN;
 
-     insn_dup2_x2:
+    insn_dup2_x2:
       dupx (sp, 2, 2); sp+=2;
       NEXT_INSN;
 
-     insn_swap:
+    insn_swap:
       {
 	jobject tmp1 = POPA();
 	jobject tmp2 = POPA();
@@ -1294,56 +1683,55 @@
       }
       NEXT_INSN;
 
-     insn_iadd:
+    insn_iadd:
       BINOPI(+);
       NEXT_INSN;
 
-     insn_ladd:
+    insn_ladd:
       BINOPL(+);
       NEXT_INSN;
 
-     insn_fadd:
+    insn_fadd:
       BINOPF(+);
       NEXT_INSN;
 
-     insn_dadd:
+    insn_dadd:
       BINOPD(+);
       NEXT_INSN;
 
-     insn_isub:
+    insn_isub:
       BINOPI(-);
       NEXT_INSN;
 
-     insn_lsub:
+    insn_lsub:
       BINOPL(-);
       NEXT_INSN;
 
-     insn_fsub:
+    insn_fsub:
       BINOPF(-);
       NEXT_INSN;
 
-     insn_dsub:
+    insn_dsub:
       BINOPD(-);
       NEXT_INSN;
 
-     insn_imul:
+    insn_imul:
       BINOPI(*);
       NEXT_INSN;
 
-     insn_lmul:
+    insn_lmul:
       BINOPL(*);
       NEXT_INSN;
 
-     insn_fmul:
+    insn_fmul:
       BINOPF(*);
       NEXT_INSN;
 
-     insn_dmul:
+    insn_dmul:
       BINOPD(*);
       NEXT_INSN;
 
-     insn_idiv:
-      SAVE_PC;
+    insn_idiv:
       {
 	jint value2 = POPI();
 	jint value1 = POPI();
@@ -1352,8 +1740,7 @@
       }
       NEXT_INSN;
 
-     insn_ldiv:
-      SAVE_PC;
+    insn_ldiv:
       {
 	jlong value2 = POPL();
 	jlong value1 = POPL();
@@ -1362,7 +1749,7 @@
       }
       NEXT_INSN;
 
-     insn_fdiv:
+    insn_fdiv:
       {
 	jfloat value2 = POPF();
 	jfloat value1 = POPF();
@@ -1371,7 +1758,7 @@
       }
       NEXT_INSN;
 
-     insn_ddiv:
+    insn_ddiv:
       {
 	jdouble value2 = POPD();
 	jdouble value1 = POPD();
@@ -1380,8 +1767,7 @@
       }
       NEXT_INSN;
 
-     insn_irem:
-      SAVE_PC;
+    insn_irem:
       {
 	jint value2 = POPI();
 	jint value1 =  POPI();
@@ -1390,8 +1776,7 @@
       }
       NEXT_INSN;
 
-     insn_lrem:
-      SAVE_PC;
+    insn_lrem:
       {
 	jlong value2 = POPL();
 	jlong value1 = POPL();
@@ -1400,7 +1785,7 @@
       }
       NEXT_INSN;
 
-     insn_frem:
+    insn_frem:
       {
 	jfloat value2 = POPF();
 	jfloat value1 = POPF();
@@ -1409,7 +1794,7 @@
       }
       NEXT_INSN;
 
-     insn_drem:
+    insn_drem:
       {
 	jdouble value2 = POPD();
 	jdouble value1 = POPD();
@@ -1418,35 +1803,35 @@
       }
       NEXT_INSN;
 
-     insn_ineg:
+    insn_ineg:
       {
 	jint value = POPI();
 	PUSHI (value * -1);
       }
       NEXT_INSN;
 
-     insn_lneg:
+    insn_lneg:
       {
 	jlong value = POPL();
 	PUSHL (value * -1);
       }
       NEXT_INSN;
 
-     insn_fneg:
+    insn_fneg:
       {
 	jfloat value = POPF();
 	PUSHF (value * -1);
       }
       NEXT_INSN;
 
-     insn_dneg:
+    insn_dneg:
       {
 	jdouble value = POPD();
 	PUSHD (value * -1);
       }
       NEXT_INSN;
 
-     insn_ishl:
+    insn_ishl:
       {
 	jint shift = (POPI() & 0x1f);
 	jint value = POPI();
@@ -1454,7 +1839,7 @@
       }
       NEXT_INSN;
 
-     insn_lshl:
+    insn_lshl:
       {
 	jint shift = (POPI() & 0x3f);
 	jlong value = POPL();
@@ -1462,7 +1847,7 @@
       }
       NEXT_INSN;
 
-     insn_ishr:
+    insn_ishr:
       {
 	jint shift = (POPI() & 0x1f);
 	jint value = POPI();
@@ -1470,7 +1855,7 @@
       }
       NEXT_INSN;
 
-     insn_lshr:
+    insn_lshr:
       {
 	jint shift = (POPI() & 0x3f);
 	jlong value = POPL();
@@ -1478,7 +1863,7 @@
       }
       NEXT_INSN;
 
-     insn_iushr:
+    insn_iushr:
       {
 	jint shift = (POPI() & 0x1f);
 	unsigned long value = POPI();
@@ -1486,7 +1871,7 @@
       }
       NEXT_INSN;
 
-     insn_lushr:
+    insn_lushr:
       {
 	jint shift = (POPI() & 0x3f);
 	UINT64 value = (UINT64) POPL();
@@ -1494,63 +1879,63 @@
       }
       NEXT_INSN;
 
-     insn_iand:
+    insn_iand:
       BINOPI (&);
       NEXT_INSN;
 
-     insn_land:
+    insn_land:
       BINOPL (&);
       NEXT_INSN;
 
-     insn_ior:
+    insn_ior:
       BINOPI (|);
       NEXT_INSN;
 
-     insn_lor:
+    insn_lor:
       BINOPL (|);
       NEXT_INSN;
 
-     insn_ixor:
+    insn_ixor:
       BINOPI (^);
       NEXT_INSN;
 
-     insn_lxor:
+    insn_lxor:
       BINOPL (^);
       NEXT_INSN;
 
-     insn_iinc:
+    insn_iinc:
       {
-	jint index  = get1u (pc++);
-	jint amount = get1s (pc++);
+	jint index  = GET1U ();
+	jint amount = GET1S ();
 	locals[index].i += amount;
       }
       NEXT_INSN;
 
-     insn_i2l:
+    insn_i2l:
       {jlong value = POPI(); PUSHL (value);}
       NEXT_INSN;
 
-     insn_i2f:
+    insn_i2f:
       {jfloat value = POPI(); PUSHF (value);}
       NEXT_INSN;
 
-     insn_i2d:
+    insn_i2d:
       {jdouble value = POPI(); PUSHD (value);}
       NEXT_INSN;
 
-     insn_l2i:
+    insn_l2i:
       {jint value = POPL(); PUSHI (value);}
       NEXT_INSN;
 
-     insn_l2f:
+    insn_l2f:
       {jfloat value = POPL(); PUSHF (value);}
       NEXT_INSN;
 
-     insn_l2d:
+    insn_l2d:
       {jdouble value = POPL(); PUSHD (value);}
       NEXT_INSN;
 
-     insn_f2i:
+    insn_f2i:
       {
 	using namespace java::lang;
 	jint value = convert (POPF (), Integer::MIN_VALUE, Integer::MAX_VALUE);
@@ -1558,7 +1943,7 @@
       }
       NEXT_INSN;
 
-     insn_f2l:
+    insn_f2l:
       {
 	using namespace java::lang;
 	jlong value = convert (POPF (), Long::MIN_VALUE, Long::MAX_VALUE);
@@ -1566,11 +1951,11 @@
       }
       NEXT_INSN;
 
-     insn_f2d:
+    insn_f2d:
       { jdouble value = POPF (); PUSHD(value); }
       NEXT_INSN;
 
-     insn_d2i:
+    insn_d2i:
       {
 	using namespace java::lang;
 	jint value = convert (POPD (), Integer::MIN_VALUE, Integer::MAX_VALUE);
@@ -1578,7 +1963,7 @@
       }
       NEXT_INSN;
 
-     insn_d2l:
+    insn_d2l:
       {
 	using namespace java::lang;
 	jlong value = convert (POPD (), Long::MIN_VALUE, Long::MAX_VALUE);
@@ -1586,23 +1971,23 @@
       }
       NEXT_INSN;
 
-     insn_d2f:
+    insn_d2f:
       { jfloat value = POPD (); PUSHF(value); }
       NEXT_INSN;
 
-     insn_i2b:
+    insn_i2b:
       { jbyte value = POPI (); PUSHI(value); }
       NEXT_INSN;
 
-     insn_i2c:
+    insn_i2c:
       { jchar value = POPI (); PUSHI(value); }
       NEXT_INSN;
 
-     insn_i2s:
+    insn_i2s:
       { jshort value = POPI (); PUSHI(value); }
       NEXT_INSN;
 
-     insn_lcmp:
+    insn_lcmp:
       {
 	jlong value2 = POPL ();
 	jlong value1 = POPL ();
@@ -1615,8 +2000,14 @@
       }
       NEXT_INSN;
 
-     insn_fcmpl:
-     insn_fcmpg:
+    insn_fcmpl:
+      tmpval = -1;
+      goto fcmp;
+
+    insn_fcmpg:
+      tmpval = 1;
+
+    fcmp:
       {
 	jfloat value2 = POPF ();
 	jfloat value1 = POPF ();
@@ -1626,15 +2017,19 @@
 	  PUSHI (0);
 	else if (value1 < value2)
 	  PUSHI (-1);
-	else if ((*(pc-1)) == op_fcmpg)
-	  PUSHI (1);
 	else
-	  PUSHI (-1);
+	  PUSHI (tmpval);
       }
       NEXT_INSN;
 
-     insn_dcmpl:
-     insn_dcmpg:
+    insn_dcmpl:
+      tmpval = 1;
+      goto dcmp;
+
+    insn_dcmpg:
+      tmpval = -1;
+
+    dcmp:
       {
 	jdouble value2 = POPD ();
 	jdouble value1 = POPD ();
@@ -1644,220 +2039,267 @@
 	  PUSHI (0);
 	else if (value1 < value2)
 	  PUSHI (-1);
-	else if ((*(pc-1)) == op_dcmpg)
-	  PUSHI (1);
 	else
-	  PUSHI (-1);
+	  PUSHI (tmpval);
       }
       NEXT_INSN;
 
-     insn_ifeq:
+    insn_ifeq:
       {
-	jint offset = get2s (pc); 
 	if (POPI() == 0)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_ifne:
+    insn_ifne:
       {
-	jint offset = get2s (pc); 
 	if (POPI() != 0)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_iflt:
+    insn_iflt:
       {
-	jint offset = get2s (pc); 
 	if (POPI() < 0)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_ifge:
+    insn_ifge:
       {
-	jint offset = get2s (pc); 
 	if (POPI() >= 0)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_ifgt:
+    insn_ifgt:
       {
-	jint offset = get2s (pc); 
 	if (POPI() > 0)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_ifle:
+    insn_ifle:
       {
-	jint offset = get2s (pc); 
 	if (POPI() <= 0)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_if_icmpeq:
+    insn_if_icmpeq:
       {
-	jint offset = get2s (pc); 
 	jint value2 = POPI();
 	jint value1 = POPI();
 	if (value1 == value2)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_if_icmpne:
+    insn_if_icmpne:
       {
-	jint offset = get2s (pc); 
 	jint value2 = POPI();
 	jint value1 = POPI();
 	if (value1 != value2)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_if_icmplt:
+    insn_if_icmplt:
       {
-	jint offset = get2s (pc); 
 	jint value2 = POPI();
 	jint value1 = POPI();
 	if (value1 < value2)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_if_icmpge:
+    insn_if_icmpge:
       {
-	jint offset = get2s (pc); 
 	jint value2 = POPI();
 	jint value1 = POPI();
 	if (value1 >= value2)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_if_icmpgt:
+    insn_if_icmpgt:
       {
-	jint offset = get2s (pc); 
 	jint value2 = POPI();
 	jint value1 = POPI();
 	if (value1 > value2)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_if_icmple:
+    insn_if_icmple:
       {
-	jint offset = get2s (pc); 
 	jint value2 = POPI();
 	jint value1 = POPI();
 	if (value1 <= value2)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_if_acmpeq:
+    insn_if_acmpeq:
       {
-	jint offset = get2s (pc); 
 	jobject value2 = POPA();
 	jobject value1 = POPA();
 	if (value1 == value2)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_if_acmpne:
+    insn_if_acmpne:
       {
-	jint offset = get2s (pc); 
 	jobject value2 = POPA();
 	jobject value1 = POPA();
 	if (value1 != value2)
-	  pc = pc-1+offset;
+	  TAKE_GOTO;
 	else
-	  pc = pc+2;
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_goto: 
+    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.
       {
-	jint offset = get2s (pc);
-	pc = pc-1+offset;
+	pc_t next = pc - 1 + get4 (pc);
+	pc += 4;
+	PUSHA ((jobject) pc);
+	pc = next;
       }
       NEXT_INSN;
-
-     insn_jsr:
+#endif /* DIRECT_THREADED */
+    insn_jsr:
       {
-	unsigned char *base_pc = pc-1;
-	jint offset = get2s (pc); pc += 2;
-	PUSHA ((jobject)pc);
-	pc = base_pc+offset;
+	pc_t next = GOTO_VAL();
+	SKIP_GOTO;
+	PUSHA ((jobject) pc);
+	pc = next;
       }
       NEXT_INSN;
 
-     insn_ret:
+    insn_ret:
       {
-	jint index = get1u (pc);
-	pc = (unsigned char*) PEEKA (index);
+	jint index = GET1U ();
+	pc = (pc_t) PEEKA (index);
       }
       NEXT_INSN;
 
-     insn_tableswitch:
+    insn_tableswitch:
       {
-	unsigned char *base_pc = pc-1;
+#ifdef DIRECT_THREADED
+	void *def = (pc++)->datum;
+
 	int index = POPI();
 
-	unsigned char* base = bytecode ();
-	while ((pc-base) % 4 != 0)
-	  pc++;
+	jint low = INTVAL ();
+	jint high = INTVAL ();
 
-	jint def     = get4 (pc);
-	jint low     = get4 (pc+4);
-	jint high    = get4 (pc+8);
+	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;    
+	  pc = base_pc + def;
 	else
-	  pc = base_pc + get4 (pc+4*(index-low+3));
+	  pc = base_pc + get4 (pc + 4 * (index - low + 3));
+#endif /* DIRECT_THREADED */
       }
       NEXT_INSN;
 
-     insn_lookupswitch:
+    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++;
+	  ++pc;
 
 	jint def     = get4 (pc);
 	jint npairs  = get4 (pc+4);
@@ -1865,7 +2307,7 @@
 	int max = npairs-1;
 	int min = 0;
 
-	// simple binary search...
+	// Simple binary search...
 	while (min < max)
 	  {
 	    int half = (min+max)/2;
@@ -1873,35 +2315,50 @@
 
 	    if (index == match)
 	      min = max = half;
-
 	    else if (index < match)
-	      max = half-1;
-
+	      // We can use HALF - 1 here because we check again on
+	      // loop exit.
+	      max = half - 1;
 	    else
-	      min = half+1;
+	      // 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;
 
-      /* on return, just save the sp and return to caller */
-     insn_ireturn:
-     insn_lreturn:
-     insn_freturn:
-     insn_dreturn:
-     insn_areturn:
-     insn_return:
-      inv->sp = sp;
+    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_getstatic:
-      SAVE_PC;
+    insn_ireturn:
+      *(jint *) retp = POPI ();
+      return;
+
+    insn_return:
+      return;
+
+    insn_getstatic:
       {
-	jint fieldref_index = get2u (pc); pc += 2;
+	jint fieldref_index = GET2U ();
 	_Jv_ResolvePoolEntry (defining_class, fieldref_index);
 	_Jv_Field *field = pool_data[fieldref_index].field;
 
@@ -1911,41 +2368,84 @@
 
 	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 (*(jbyte*) (field->u.addr));
+		newinsn = AMPAMP (getstatic_resolved_1);
 		break;
 
 	      case 2:
 		if (type == JvPrimClass (char))
-		  PUSHI(*(jchar*) (field->u.addr));
+		  {
+		    PUSHI(*(jchar*) (field->u.addr));
+		    newinsn = AMPAMP (getstatic_resolved_char);
+		  }
 		else
-		  PUSHI(*(jshort*) (field->u.addr));
+		  {
+		    PUSHI(*(jshort*) (field->u.addr));
+		    newinsn = AMPAMP (getstatic_resolved_short);
+		  }
 		break;
 
 	      case 4:
 		PUSHI(*(jint*) (field->u.addr));
+		newinsn = AMPAMP (getstatic_resolved_4);
 		break;
 
 	      case 8:
 		PUSHL(*(jlong*) (field->u.addr));
+		newinsn = AMPAMP (getstatic_resolved_8);
 		break;
 	      }
 	  }
 	else
 	  {
 	    PUSHA(*(jobject*) (field->u.addr));
+	    newinsn = AMPAMP (getstatic_resolved_obj);
 	  }
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = newinsn;
+	pc[-1].datum = field->u.addr;
+#endif /* DIRECT_THREADED */
       }
       NEXT_INSN;
 
-     insn_getfield:
-      SAVE_PC;
+#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:
       {
-	jint fieldref_index = get2u (pc); pc += 2;
+	jint fieldref_index = GET2U ();
 	_Jv_ResolvePoolEntry (defining_class, fieldref_index);
 	_Jv_Field *field = pool_data[fieldref_index].field;
 
@@ -1961,41 +2461,106 @@
 	jobject obj   = POPA();
 	NULLCHECK(obj);
 
+	void *newinsn = NULL;
 	if (type->isPrimitive ())
 	  {
 	    switch (type->size_in_bytes)
 	      {
 	      case 1:
 		PUSHI (*(jbyte*) ((char*)obj + field_offset));
+		newinsn = AMPAMP (getfield_resolved_1);
 		break;
 
 	      case 2:
 		if (type == JvPrimClass (char))
-		  PUSHI (*(jchar*) ((char*)obj + field_offset));
+		  {
+		    PUSHI (*(jchar*) ((char*)obj + field_offset));
+		    newinsn = AMPAMP (getfield_resolved_char);
+		  }
 		else
-		  PUSHI (*(jshort*) ((char*)obj + field_offset));
+		  {
+		    PUSHI (*(jshort*) ((char*)obj + field_offset));
+		    newinsn = AMPAMP (getfield_resolved_short);
+		  }
 		break;
 
 	      case 4:
 		PUSHI (*(jint*) ((char*)obj + field_offset));
+		newinsn = AMPAMP (getfield_resolved_4);
 		break;
 
 	      case 8:
 		PUSHL(*(jlong*) ((char*)obj + field_offset));
+		newinsn = AMPAMP (getfield_resolved_8);
 		break;
 	      }
 	  }
 	else
 	  {
 	    PUSHA(*(jobject*) ((char*)obj + field_offset));
+	    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;
 
-     insn_putstatic:
-      SAVE_PC;
+    getfield_resolved_8:
       {
-	jint fieldref_index = get2u (pc); pc += 2;
+	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:
+      {
+	jint fieldref_index = GET2U ();
 	_Jv_ResolvePoolEntry (defining_class, fieldref_index);
 	_Jv_Field *field = pool_data[fieldref_index].field;
 
@@ -2006,6 +2571,7 @@
 	  throw_incompatible_class_change_error 
 	    (JvNewStringLatin1 ("field no longer static"));
 
+	void *newinsn = NULL;
 	if (type->isPrimitive ())
 	  {
 	    switch (type->size_in_bytes) 
@@ -2014,6 +2580,7 @@
 		{
 		  jint value = POPI();
 		  *(jbyte*) (field->u.addr) = value;
+		  newinsn = AMPAMP (putstatic_resolved_1);
 		  break;
 		}
 
@@ -2021,6 +2588,7 @@
 		{
 		  jint value = POPI();
 		  *(jchar*) (field->u.addr) = value;
+		  newinsn = AMPAMP (putstatic_resolved_2);
 		  break;
 		}
 
@@ -2028,6 +2596,7 @@
 		{
 		  jint value = POPI();
 		  *(jint*) (field->u.addr) = value;
+		  newinsn = AMPAMP (putstatic_resolved_4);
 		  break;
 		}
 
@@ -2035,6 +2604,7 @@
 		{
 		  jlong value = POPL();
 		  *(jlong*) (field->u.addr) = value;
+		  newinsn = AMPAMP (putstatic_resolved_8);
 		  break;
 		}
 	      }
@@ -2043,15 +2613,41 @@
 	  {
 	    jobject value = POPA();
 	    *(jobject*) (field->u.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;
+    insn_putfield:
       {
-	jint fieldref_index = get2u (pc); pc += 2;
+	jint fieldref_index = GET2U ();
 	_Jv_ResolvePoolEntry (defining_class, fieldref_index);
 	_Jv_Field *field = pool_data[fieldref_index].field;
 
@@ -2065,6 +2661,7 @@
 	if (field_offset > 0xffff)
 	  throw new java::lang::VirtualMachineError;
 
+	void *newinsn = NULL;
 	if (type->isPrimitive ())
 	  {
 	    switch (type->size_in_bytes) 
@@ -2075,6 +2672,7 @@
 		  jobject obj   = POPA();
 		  NULLCHECK(obj);
 		  *(jbyte*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_1);
 		  break;
 		}
 
@@ -2084,6 +2682,7 @@
 		  jobject obj   = POPA();
 		  NULLCHECK(obj);
 		  *(jchar*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_2);
 		  break;
 		}
 
@@ -2093,6 +2692,7 @@
 		  jobject obj   = POPA();
 		  NULLCHECK(obj);
 		  *(jint*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_4);
 		  break;
 		}
 
@@ -2102,6 +2702,7 @@
 		  jobject obj   = POPA();
 		  NULLCHECK(obj);
 		  *(jlong*) ((char*)obj + field_offset) = value;
+		  newinsn = AMPAMP (putfield_resolved_8);
 		  break;
 		}
 	      }
@@ -2112,14 +2713,66 @@
 	    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;
+    insn_invokespecial:
       {
-	int index = get2u (pc); pc += 2;
+	int index = GET2U ();
 
 	rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
 
@@ -2128,13 +2781,30 @@
 	NULLCHECK (sp[0].o);
 
 	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;
 
-     insn_invokestatic:
-      SAVE_PC;
+#ifdef DIRECT_THREADED
+    invokespecial_resolved:
       {
-	int index = get2u (pc); pc += 2;
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	NULLCHECK (sp[0].o);
+	fun = (void (*)()) rmeth->method->ncode;
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
+
+    insn_invokestatic:
+      {
+	int index = GET2U ();
 
 	rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
 
@@ -2142,16 +2812,29 @@
 
 	_Jv_InitClass (rmeth->klass);
 	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;
 
-     insn_invokeinterface:
-      SAVE_PC;
+#ifdef DIRECT_THREADED
+    invokestatic_resolved:
       {
-	int index = get2u (pc); pc += 2;
+	rmeth = (_Jv_ResolvedMethod *) AVAL ();
+	sp -= rmeth->stack_item_count;
+	fun = (void (*)()) rmeth->method->ncode;
+      }
+      goto perform_invoke;
+#endif /* DIRECT_THREADED */
 
-	// invokeinterface has two unused bytes...
-	pc += 2;
+    insn_invokeinterface:
+      {
+	int index = GET2U ();
 
 	rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
 
@@ -2165,44 +2848,96 @@
 	  _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:
+      {
+	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;
+    insn_new:
       {
-	int index = get2u (pc); pc += 2;
+	int index = GET2U ();
 	jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
 	_Jv_InitClass (klass);
 	jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
 	PUSHA (res);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&new_resolved;
+	pc[-1].datum = klass;
+#endif /* DIRECT_THREADED */
       }
       NEXT_INSN;
 
-     insn_newarray:
-      SAVE_PC;
+#ifdef DIRECT_THREADED
+    new_resolved:
       {
-	int atype = get1u (pc++);
+	jclass klass = (jclass) AVAL ();
+	jobject res = _Jv_AllocObject (klass, klass->size_in_bytes);
+	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;
+    insn_anewarray:
       {
-	int index = get2u (pc); pc += 2;
+	int index = GET2U ();
 	jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
 	int size  = POPI();
 	_Jv_InitClass (klass);
 	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:
+    insn_arraylength:
       {
 	__JArray *arr = (__JArray*)POPA();
 	NULLARRAYCHECK (arr);
@@ -2210,42 +2945,68 @@
       }
       NEXT_INSN;
 
-     insn_athrow:
-      SAVE_PC;
+    insn_athrow:
       {
 	jobject value = POPA();
 	throw static_cast<jthrowable>(value);
       }
       NEXT_INSN;
 
-     insn_checkcast:
-      SAVE_PC;
+    insn_checkcast:
       {
 	jobject value = POPA();
-	jint index = get2u (pc); pc += 2;
+	jint index = GET2U ();
 	jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
 
 	if (value != NULL && ! to->isInstance (value))
-	  {
-	    throw new java::lang::ClassCastException (to->getName());
-	  }
+	  throw new java::lang::ClassCastException (to->getName());
 
 	PUSHA (value);
+
+#ifdef DIRECT_THREADED
+	pc[-2].insn = &&checkcast_resolved;
+	pc[-1].datum = to;
+#endif /* DIRECT_THREADED */
+      }
+      NEXT_INSN;
+
+#ifdef DIRECT_THREADED
+    checkcast_resolved:
+      {
+	jobject value = POPA ();
+	jclass to = (jclass) AVAL ();
+	if (value != NULL && ! to->isInstance (value))
+	  throw new java::lang::ClassCastException (to->getName());
+	PUSHA (value);
       }
       NEXT_INSN;
+#endif /* DIRECT_THREADED */
 
-     insn_instanceof:
-      SAVE_PC;
+    insn_instanceof:
       {
 	jobject value = POPA();
-	jint index = get2u (pc); pc += 2;
+	jint index = GET2U ();
 	jclass to = (_Jv_ResolvePoolEntry (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:
-      SAVE_PC;
+    insn_monitorenter:
       {
 	jobject value = POPA();
 	NULLCHECK(value);
@@ -2253,8 +3014,7 @@
       }
       NEXT_INSN;
 
-     insn_monitorexit:
-      SAVE_PC;
+    insn_monitorexit:
       {
 	jobject value = POPA();
 	NULLCHECK(value);
@@ -2262,28 +3022,49 @@
       }
       NEXT_INSN;
 
-     insn_ifnull:
+    insn_ifnull:
       {
-	unsigned char* base_pc = pc-1;
-	jint offset = get2s (pc); pc += 2;
 	jobject val = POPA();
 	if (val == NULL)
-	  pc = base_pc+offset;
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_ifnonnull:
+    insn_ifnonnull:
       {
-	unsigned char* base_pc = pc-1;
-	jint offset = get2s (pc); pc += 2;
 	jobject val = POPA();
 	if (val != NULL)
-	  pc = base_pc+offset;
+	  TAKE_GOTO;
+	else
+	  SKIP_GOTO;
       }
       NEXT_INSN;
 
-     insn_wide:
-      SAVE_PC;
+    insn_multianewarray:
+      {
+	int kind_index = GET2U ();
+	int dim        = GET1U ();
+
+	jclass type    
+	  = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
+	_Jv_InitClass (type);
+	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;
@@ -2343,47 +3124,50 @@
 	  }
 
       }
+#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 = exceptions ();
+      jclass exc_class = ex->getClass ();
 
-     insn_multianewarray:
-      SAVE_PC;
-      {
-	int kind_index = get2u (pc); pc += 2;
-	int dim        = get1u (pc); pc += 1;
-
-	jclass type    
-	  = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
-	_Jv_InitClass (type);
-	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;
+      for (int i = 0; i < 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_ResolvePoolEntry (defining_class,
+						 exc[i].handler_type.i)).clazz;
+#endif /* DIRECT_THREADED */
 
-     insn_goto_w:
-      {
-	unsigned char* base_pc = pc-1;
-	int offset = get4 (pc); pc += 4;
-	pc = base_pc+offset;
-      }
-      NEXT_INSN;
+	      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;
+		}
+	    }
+	}
 
-     insn_jsr_w:
-      {
-	unsigned char* base_pc = pc-1;
-	int offset = get4 (pc); pc += 4;
-	PUSHA((jobject)pc);
-	pc = base_pc+offset;
-      }
-      NEXT_INSN;
+      // No handler, so re-throw.
+      throw ex;
+    }
 }
-
 
 static void
 throw_internal_error (char *msg)
Index: verify.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/verify.cc,v
retrieving revision 1.41
diff -u -r1.41 verify.cc
--- verify.cc 26 Apr 2002 22:39:29 -0000 1.41
+++ verify.cc 24 Jun 2002 20:35:44 -0000
@@ -1882,18 +1882,18 @@
     // Verify exception handlers.
     for (int i = 0; i < current_method->exc_count; ++i)
       {
-	if (! (flags[exception[i].handler_pc] & FLAG_INSN_START))
+	if (! (flags[exception[i].handler_pc.i] & FLAG_INSN_START))
 	  verify_fail ("exception handler not at instruction start",
-		       exception[i].handler_pc);
-	if (! (flags[exception[i].start_pc] & FLAG_INSN_START))
+		       exception[i].handler_pc.i);
+	if (! (flags[exception[i].start_pc.i] & FLAG_INSN_START))
 	  verify_fail ("exception start not at instruction start",
-		       exception[i].start_pc);
-	if (exception[i].end_pc != current_method->code_length
-	    && ! (flags[exception[i].end_pc] & FLAG_INSN_START))
+		       exception[i].start_pc.i);
+	if (exception[i].end_pc.i != current_method->code_length
+	    && ! (flags[exception[i].end_pc.i] & FLAG_INSN_START))
 	  verify_fail ("exception end not at instruction start",
-		       exception[i].end_pc);
+		       exception[i].end_pc.i);
 
-	flags[exception[i].handler_pc] |= FLAG_BRANCH_TARGET;
+	flags[exception[i].handler_pc.i] |= FLAG_BRANCH_TARGET;
       }
   }
 
@@ -2186,12 +2186,12 @@
 	// through them all.
 	for (int i = 0; i < current_method->exc_count; ++i)
 	  {
-	    if (PC >= exception[i].start_pc && PC < exception[i].end_pc)
+	    if (PC >= exception[i].start_pc.i && PC < exception[i].end_pc.i)
 	      {
 		type handler (&java::lang::Throwable::class$);
-		if (exception[i].handler_type != 0)
-		  handler = check_class_constant (exception[i].handler_type);
-		push_exception_jump (handler, exception[i].handler_pc);
+		if (exception[i].handler_type.i != 0)
+		  handler = check_class_constant (exception[i].handler_type.i);
+		push_exception_jump (handler, exception[i].handler_pc.i);
 	      }
 	  }
 
Index: include/java-interp.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/java-interp.h,v
retrieving revision 1.16
diff -u -r1.16 java-interp.h
--- include/java-interp.h 26 Nov 2001 06:40:05 -0000 1.16
+++ include/java-interp.h 24 Jun 2002 20:35:44 -0000
@@ -1,6 +1,6 @@
 // java-interp.h - Header file for the bytecode interpreter.  -*- c++ -*-
 
-/* Copyright (C) 1999, 2000, 2001  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -49,14 +49,22 @@
 
 class _Jv_InterpClass;
 class _Jv_InterpMethod;
-class _Jv_InterpMethodInvocation;
+
+// Before a method is "compiled" we store values as the bytecode PC,
+// an int.  Afterwards we store them as pointers into the prepared
+// code itself.
+union _Jv_InterpPC
+{
+  int i;
+  void *p;
+};
 
 class _Jv_InterpException
 {
-  int  start_pc;
-  int  end_pc;
-  int  handler_pc;
-  int  handler_type;
+  _Jv_InterpPC start_pc;
+  _Jv_InterpPC end_pc;
+  _Jv_InterpPC handler_pc;
+  _Jv_InterpPC handler_type;
 
   friend class _Jv_ClassReader;
   friend class _Jv_InterpMethod;
@@ -92,6 +100,8 @@
 
   _Jv_ushort       exc_count;
 
+  void *prepared;
+
   unsigned char* bytecode () 
   {
     return 
@@ -99,7 +109,7 @@
       + ROUND((sizeof (_Jv_InterpMethod)
 	       + exc_count*sizeof (_Jv_InterpException)), 4);
   }
-    
+
   _Jv_InterpException * exceptions ()
   {
     return (_Jv_InterpException*) (this+1);
@@ -115,40 +125,23 @@
 
   // return the method's invocation pointer (a stub).
   void *ncode ();
-  void continue1 (_Jv_InterpMethodInvocation *inv);
+  void compile (const void * const *);
 
   static void run_normal (ffi_cif*, void*, ffi_raw*, void*);
   static void run_synch_object (ffi_cif*, void*, ffi_raw*, void*);
   static void run_synch_class (ffi_cif*, void*, ffi_raw*, void*);
 
-  inline jobject run (ffi_cif*, void*, ffi_raw*, 
-		      _Jv_InterpMethodInvocation*);
-
-  bool find_exception (jobject ex,
-		       _Jv_InterpMethodInvocation *inv);
+  void run (void*, ffi_raw *);
 
  public:
   static void dump_object(jobject o);
 
   friend class _Jv_ClassReader;
-  friend class _Jv_InterpMethodInvocation;
   friend class _Jv_BytecodeVerifier;
 
   friend void _Jv_PrepareClass(jclass);
 };
 
-class _Jv_InterpMethodInvocation {
-  _Jv_InterpMethod *running;
-  _Jv_word         *sp;
-  unsigned char    *pc;
-  _Jv_word          state[0];
-
-  _Jv_word*         stack_base () { return &state[0]; }
-  _Jv_word*         local_base () { return &state[running->max_stack]; }
-
-  friend class _Jv_InterpMethod;
-};
-  
 class _Jv_InterpClass : public java::lang::Class
 {
   _Jv_MethodBase **interpreted_methods;
Index: java/lang/Class.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Class.h,v
retrieving revision 1.44
diff -u -r1.44 Class.h
--- java/lang/Class.h 11 Jun 2002 17:32:55 -0000 1.44
+++ java/lang/Class.h 24 Jun 2002 20:35:45 -0000
@@ -338,7 +338,6 @@
   friend class _Jv_ClassReader;	
   friend class _Jv_InterpClass;
   friend class _Jv_InterpMethod;
-  friend class _Jv_InterpMethodInvocation;
 #endif
 
 #ifdef JV_MARKOBJ_DECL


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]