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]

[BC] Patch: FYI: Class preparation rewrite


I'm checking this in on the binary compatibility branch.

This is a reorganization of class preparation.  In particular most of
the interpreter #ifdefs were removed; execution-engine-specific code
is now encapsulated in an ad hoc class.  Preparation is now
consolidated in resolve.cc, methods were renamed to have less
confusing names, and the interaction between preparation and
initialization in Class.initializeClass is now more understandable
(IMO).

I've tested this by running the test suite, including Mauve and Jacks.
The results there seem reasonable.  Also I compiled Eclipse 2.x to
native with this, and it works fine with various mixes of interpreted
and -findirect-dispatch -compiled code (though you need an uncommitted
gcj front end patch from Andrew for best results).

There are still cleanups to be done, but this is a convenient place to
commit.

Tom

Index: gcc/java/ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* class.c (make_class_data): Correctly initialize "state" field.
	Initialize "engine" field.
	* decl.c (java_init_decl_processing): Add "engine" field.

Index: gcc/java/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.180.2.12
diff -u -r1.180.2.12 class.c
--- gcc/java/class.c 10 Sep 2004 17:15:29 -0000 1.180.2.12
+++ gcc/java/class.c 14 Sep 2004 20:02:16 -0000
@@ -1788,7 +1788,12 @@
   PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
   PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "interface_count", build_int_2 (interface_len, 0));
-  PUSH_FIELD_VALUE (cons, "state", integer_zero_node);
+  PUSH_FIELD_VALUE (cons, "state",
+		    convert (byte_type_node,
+			     build_int_2 (flag_indirect_dispatch
+					  ? JV_STATE_PRELOADING
+					  : JV_STATE_COMPILED,
+					  0)));
 
   PUSH_FIELD_VALUE (cons, "thread", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "depth", integer_zero_node);
@@ -1809,6 +1814,7 @@
   PUSH_FIELD_VALUE (cons, "hack_signers", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "chain", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "aux_info", null_pointer_node);
+  PUSH_FIELD_VALUE (cons, "engine", null_pointer_node);
 
   FINISH_RECORD_CONSTRUCTOR (cons);
 
Index: gcc/java/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.178.4.8
diff -u -r1.178.4.8 decl.c
--- gcc/java/decl.c 10 Sep 2004 17:15:30 -0000 1.178.4.8
+++ gcc/java/decl.c 14 Sep 2004 20:02:17 -0000
@@ -853,6 +853,7 @@
   PUSH_FIELD (class_type_node, field, "hack_signers", ptr_type_node);
   PUSH_FIELD (class_type_node, field, "chain", ptr_type_node);
   PUSH_FIELD (class_type_node, field, "aux_info", ptr_type_node);
+  PUSH_FIELD (class_type_node, field, "engine", ptr_type_node);
   for (t = TYPE_FIELDS (class_type_node);  t != NULL_TREE;  t = TREE_CHAIN (t))
     FIELD_PRIVATE (t) = 1;
   push_super_field (class_type_node, object_type_node);
Index: libjava/ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* java/lang/reflect/natField.cc (getType): Use resolve_field.
	* java/lang/natVMClassLoader.cc (resolveClass): New native
	implementation.
	(linkClass0): Removed.
	(markClassErrorState0): Likewise.
	* java/lang/natClassLoader.cc: Include execution.h.  Moved class
	preparation code to resolve.cc.
	(_Jv_RegisterClassHookDefault): Set class's execution engine if
	not already set.
	(_Jv_FindClass): Use wait_for_state.
	(_Jv_NewArrayClass): Likewise.  Simplified permissions setting.
	* java/lang/natClass.cc (_Jv_IsInstanceOf): Include execution.h.
	Moved interface table and class preparation code to resolve.cc.
	(finalize): Rewrote.
	(initializeClass): Simplified locking and class preparation.
	* java/lang/VMClassLoader.java (linkClass0): Removed.
	(markClassErrorState0): Likewise.
	(resolveClass): Now native.
	(transformException): New method.
	* java/lang/Class.h (getSuperclass): Don't try to resolve super
	reference.
	(getInterface): Likewise.
	(size): Likewise.
	(set_state): New method.
	(Class): Updated friend declarations.
	(verify): Field now private.
	(engine): New field.
	* include/jvm.h (class _Jv_Resolver): New class declaration.
	(_Jv_ResolveField): Removed declaration.
	(_Jv_CheckAccessNoInit): Likewise.
	(_Jv_isBinaryCompatible): Removed.
	* include/java-interp.h (class _Jv_MethodBase): Updated friend
	declarations.
	(class _Jv_InterpMethod): Likewise.
	(class _Jv_InterpClass): Likewise.
	(class _Jv_JNIMethod): Likewise.
	* include/execution.h: New file.
	* gnu/gcj/runtime/natSharedLibLoader.cc: Include execution.h.
	(_Jv_sharedlib_register_hook): Set `engine' on loaded class.
	Register class after setting fields.
	* resolve.cc: Include execution.h, VerifyError.h.  Moved
	interpreter-specific code to interpret.cc.
	(uaddr): New location.
	(struct aligner): Likewise.
	(ALIGNOF): Likewise.
	(INITIAL_IOFFSETS_LEN): Interface dispatch code moved here.
	(INITIAL_IFACES_LEN): Likewise.
	(null_idt): Likewise.
	(_Jv_GetMethodString): Likewise.
	(_Jv_ThrowNoSuchMethodError): Likewise.
	(_Jv_abstractMethodError): Likewise.
	(_Jv_Resolver::get_alignment_from_class): Renamed.
	(_Jv_Resolver::resolve_field): Likewise.
	(_Jv_Resolver::resolve_pool_entry): Likewise.
	(_Jv_Resolver::resolve_class_ref): Likewise.
	(_Jv_Resolver::prepare_constant_time_tables): Likewise.
	(_Jv_Resolver::indexof): Likewise.
	(_Jv_Resolver::get_interfaces): Likewise.
	(_Jv_Resolver::generate_itable): Likewise.
	(_Jv_Resolver::append_partial_itable): Likewise.
	(_Jv_Resolver::find_iindex): Likewise.
	(_Jv_Resolver::link_symbol_table): Likewise.
	(_Jv_Resolver::link_exception_table): Likewise.
	(_Jv_Resolver::layout_interface_methods): Likewise.
	(_Jv_Resolver::layout_vtable_methods): Likewise.
	(_Jv_Resolver::set_vtable_entries): Likewise.
	(_Jv_Resolver::make_vtable): Likewise.
	(_Jv_Resolver::ensure_fields_laid_out): Likewise.
	(_Jv_Resolver::ensure_class_linked): Likewise.
	(_Jv_Resolver::ensure_supers_installed): Likewise.
	(_Jv_Resolver::add_miranda_methods): Likewise.
	(_Jv_Resolver::ensure_method_table_complete): Likewise.
	(_Jv_Resolver::verify_class): Likewise.
	(_Jv_Resolver::wait_for_state): Likewise.
	* prims.cc (_Jv_soleCompiledEngine): New global.
	(_Jv_CheckAccess): Use _Jv_IsAssignableFromSlow.
	(_Jv_CheckAccessNoInit): Removed.
	* jni.cc (_Jv_JNI_GetAnyFieldID): Use resolve_field.
	* interpret.cc: Include platform.h, ClassFormatError.h,
	Modifier.h, execution.h.
	(_Jv_soleInterpreterEngine): New global.
	(compile): Use resolve_pool_entry.
	(run): Likewise.
	(_Jv_InitField): New location.
	(skip_one_type): Likewise.
	(get_ffi_type_from_signature): Likewise.
	(_Jv_count_arguments): Likewise.
	(init_cif): Likewise.
	(ncode_closure): Likewise.
	(ffi_closure_fun): Likewise.
	(ncode): Likewise.
	(throw_class_format_error): Likewise.
	(throw_class_format_error): Likewise.
	(_Jv_InterpreterEngine::do_verify): New method.
	(_Jv_InterpreterEngine::do_create_ncode): Likewise.
	(_Jv_InterpreterEngine::do_allocate_static_fields): Likewise.
	(_Jv_InterpreterEngine::do_resolve_method): Likewise.
	* defineclass.cc: Include execution.h.
	(_Jv_ClassReader): Initialize size_in_bytes, vtable_method_count,
	engine.
	(checkExtends): Ensure superclass has supers installed.
	(_Jv_ClassNameSamePackage): Clarify usage constraints.
	* boehm.cc (GC_enable, GC_disable): Declare at top of file.
	(_Jv_MarkObj): Unconditionally mark vtable.  Mark interface
	dispatch tables.

Index: libjava/boehm.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/boehm.cc,v
retrieving revision 1.42.12.1
diff -u -r1.42.12.1 boehm.cc
--- libjava/boehm.cc 20 Apr 2004 21:59:38 -0000 1.42.12.1
+++ libjava/boehm.cc 14 Sep 2004 20:02:20 -0000
@@ -1,6 +1,6 @@
 // boehm.cc - interface between libjava and Boehm GC.
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -38,6 +38,10 @@
   // These aren't declared in any Boehm GC header.
   void GC_finalize_all (void);
   ptr_t GC_debug_generic_malloc (size_t size, int k, GC_EXTRA_PARAMS);
+
+  // From boehm's misc.c 
+  void GC_enable();
+  void GC_disable();
 };
 
 #define MAYBE_MARK(Obj, Top, Limit, Source, Exit)  \
@@ -123,11 +127,13 @@
 	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5alabel);
 	  p = (ptr_t) c->constants.data;
 	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5blabel);
-	  p = (ptr_t) c->vtable;
-	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5clabel);
 	}
 #endif
 
+      // The vtable might be allocated even for compiled code.
+      p = (ptr_t) c->vtable;
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5clabel);
+
       // If the class is an array, then the methods field holds a
       // pointer to the element class.  If the class is primitive,
       // then the methods field holds a pointer to the array class.
@@ -202,6 +208,29 @@
 	}
       p = (ptr_t) c->loader;
       MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cBlabel);
+
+      // The dispatch tables can be allocated at runtime.
+      p = (ptr_t) c->ancestors;
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cancestorlabel);
+      if (c->idt)
+	{
+	  p = (ptr_t) c->idt;
+	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cIDTlabel);
+
+	  if (c->isInterface())
+	    {
+	      p = (ptr_t) c->idt->iface.ioffsets;
+	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, ciofflabel);
+	    }
+	  else if (! c->isPrimitive())
+	    {
+	      // This field is only valid for ordinary classes.
+	      p = (ptr_t) c->idt->cls.itable;
+	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
+			  ictablelabel);
+	    }
+	}
+
       p = (ptr_t) c->arrayclass;
       MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cDlabel);
       p = (ptr_t) c->protectionDomain;
@@ -490,10 +519,6 @@
   GC_set_max_heap_size ((GC_word) size);
 }
 
-// From boehm's misc.c 
-extern "C" void GC_enable();
-extern "C" void GC_disable();
-
 void
 _Jv_DisableGC (void)
 {
Index: libjava/defineclass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/defineclass.cc,v
retrieving revision 1.35.16.3
diff -u -r1.35.16.3 defineclass.cc
--- libjava/defineclass.cc 20 May 2004 23:33:45 -0000 1.35.16.3
+++ libjava/defineclass.cc 14 Sep 2004 20:02:20 -0000
@@ -1,6 +1,6 @@
 // defineclass.cc - defining a class from .class format.
 
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <java-cpool.h>
 #include <gcj/cni.h>
+#include <execution.h>
 
 #include <java/lang/Class.h>
 #include <java/lang/Float.h>
@@ -225,6 +226,9 @@
     len    = length;
     pos    = 0;
     def    = klass;
+    def->size_in_bytes = -1;
+    def->vtable_method_count = -1;
+    def->engine = &_Jv_soleInterpreterEngine;
     def_interp = (_Jv_InterpClass *) def->aux_info;
   }
 
@@ -334,7 +338,7 @@
   if (pos != len)
     throw_class_format_error ("unused data before end of file");
 
-  // tell everyone we're done.
+  // Tell everyone we're done.
   def->state = JV_STATE_LOADED;
   def->notifyAll ();
 
@@ -947,23 +951,25 @@
   def->notifyAll ();
 }
 
-///// implements the checks described in sect. 5.3.5.3
+///// Implements the checks described in sect. 5.3.5.3
 void
 _Jv_ClassReader::checkExtends (jclass sub, jclass super)
 {
   using namespace java::lang::reflect;
 
-  // having an interface or a final class as a superclass is no good
+  _Jv_Resolver::wait_for_state (super, JV_STATE_LOADING);
+
+  // Having an interface or a final class as a superclass is no good.
   if ((super->accflags & (Modifier::INTERFACE | Modifier::FINAL)) != 0)
     {
       throw_incompatible_class_change_error (sub->getName ());
     }
 
-  // if the super class is not public, we need to check some more
+  // If the super class is not public, we need to check some more.
   if ((super->accflags & Modifier::PUBLIC) == 0)
     {
-      // With package scope, the classes must have the same
-      // class loader.
+      // With package scope, the classes must have the same class
+      // loader.
       if (   sub->loader != super->loader
 	  || !_Jv_ClassNameSamePackage (sub->name, super->name))
 	{
@@ -1625,7 +1631,7 @@
 }
 
 /* Returns true, if NAME1 and NAME2 represent classes in the same
-   package.  */
+   package.  Neither NAME2 nor NAME2 may name an array type.  */
 bool
 _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2)
 {
Index: libjava/interpret.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/interpret.cc,v
retrieving revision 1.40.18.1
diff -u -r1.40.18.1 interpret.cc
--- libjava/interpret.cc 20 Apr 2004 21:59:38 -0000 1.40.18.1
+++ libjava/interpret.cc 14 Sep 2004 20:02:20 -0000
@@ -1,6 +1,6 @@
 // interpret.cc - Code for the interpreter
 
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
 
    This file is part of libgcj.
 
@@ -11,6 +11,7 @@
 /* Author: Kresten Krab Thorup <krab@gnu.org>  */
 
 #include <config.h>
+#include <platform.h>
 
 // Define this to get the direct-threaded interpreter.  If undefined,
 // we revert to a basic bytecode interpreter.  The former is faster
@@ -38,9 +39,15 @@
 #include <java/lang/Thread.h>
 #include <java-insns.h>
 #include <java-signal.h>
+#include <java/lang/ClassFormatError.h>
+#include <execution.h>
+#include <java/lang/reflect/Modifier.h>
 
 #ifdef INTERPRETER
 
+// Execution engine for interpreted code.
+_Jv_InterpreterEngine _Jv_soleInterpreterEngine;
+
 #include <stdlib.h>
 
 using namespace gcj;
@@ -54,6 +61,11 @@
   __attribute__ ((__noreturn__));
 #endif
 
+static void throw_class_format_error (jstring msg)
+	__attribute__ ((__noreturn__));
+static void throw_class_format_error (char *msg)
+	__attribute__ ((__noreturn__));
+
 extern "C" double __ieee754_fmod (double,double);
 
 // This represents a single slot in the "compiled" form of the
@@ -750,8 +762,9 @@
       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;
+      jclass handler
+	= (_Jv_Resolver::resolve_pool_entry (defining_class,
+					     exc[i].handler_type.i)).clazz;
       exc[i].handler_type.p = handler;
     }
 
@@ -1086,13 +1099,14 @@
       {
 	int index = GET2U ();
 
-	/* _Jv_ResolvePoolEntry 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.  */
+	/* _Jv_Resolver::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_ResolvePoolEntry (defining_class, index)).rmethod;
+	rmeth = (_Jv_Resolver::resolve_pool_entry (defining_class,
+						   index)).rmethod;
 
 	sp -= rmeth->stack_item_count;
 	// We don't use NULLCHECK here because we can't rely on that
@@ -2391,7 +2405,7 @@
     insn_getstatic:
       {
 	jint fieldref_index = GET2U ();
-	_Jv_ResolvePoolEntry (defining_class, fieldref_index);
+	_Jv_Resolver::resolve_pool_entry (defining_class, fieldref_index);
 	_Jv_Field *field = pool_data[fieldref_index].field;
 
 	if ((field->flags & Modifier::STATIC) == 0)
@@ -2478,7 +2492,7 @@
     insn_getfield:
       {
 	jint fieldref_index = GET2U ();
-	_Jv_ResolvePoolEntry (defining_class, fieldref_index);
+	_Jv_Resolver::resolve_pool_entry (defining_class, fieldref_index);
 	_Jv_Field *field = pool_data[fieldref_index].field;
 
 	if ((field->flags & Modifier::STATIC) != 0)
@@ -2593,7 +2607,7 @@
     insn_putstatic:
       {
 	jint fieldref_index = GET2U ();
-	_Jv_ResolvePoolEntry (defining_class, fieldref_index);
+	_Jv_Resolver::resolve_pool_entry (defining_class, fieldref_index);
 	_Jv_Field *field = pool_data[fieldref_index].field;
 
 	jclass type = field->type;
@@ -2680,7 +2694,7 @@
     insn_putfield:
       {
 	jint fieldref_index = GET2U ();
-	_Jv_ResolvePoolEntry (defining_class, fieldref_index);
+	_Jv_Resolver::resolve_pool_entry (defining_class, fieldref_index);
 	_Jv_Field *field = pool_data[fieldref_index].field;
 
 	jclass type = field->type;
@@ -2806,7 +2820,8 @@
       {
 	int index = GET2U ();
 
-	rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
+	rmeth = (_Jv_Resolver::resolve_pool_entry (defining_class,
+						   index)).rmethod;
 
 	sp -= rmeth->stack_item_count;
 
@@ -2844,7 +2859,8 @@
       {
 	int index = GET2U ();
 
-	rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
+	rmeth = (_Jv_Resolver::resolve_pool_entry (defining_class,
+						   index)).rmethod;
 
 	sp -= rmeth->stack_item_count;
 
@@ -2873,7 +2889,8 @@
       {
 	int index = GET2U ();
 
-	rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
+	rmeth = (_Jv_Resolver::resolve_pool_entry (defining_class,
+						   index)).rmethod;
 
 	sp -= rmeth->stack_item_count;
 
@@ -2916,7 +2933,8 @@
     insn_new:
       {
 	int index = GET2U ();
-	jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
+	jclass klass = (_Jv_Resolver::resolve_pool_entry (defining_class,
+							  index)).clazz;
 	jobject res = _Jv_AllocObject (klass);
 	PUSHA (res);
 
@@ -2949,7 +2967,8 @@
     insn_anewarray:
       {
 	int index = GET2U ();
-	jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
+	jclass klass = (_Jv_Resolver::resolve_pool_entry (defining_class,
+							  index)).clazz;
 	int size  = POPI();
 	jobject result = _Jv_NewObjectArray (size, klass, 0);
 	PUSHA (result);
@@ -2991,7 +3010,8 @@
       {
 	jobject value = POPA();
 	jint index = GET2U ();
-	jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
+	jclass to = (_Jv_Resolver::resolve_pool_entry (defining_class,
+						       index)).clazz;
 
 	if (value != NULL && ! to->isInstance (value))
 	  throw new java::lang::ClassCastException (to->getName());
@@ -3021,7 +3041,8 @@
       {
 	jobject value = POPA();
 	jint index = GET2U ();
-	jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
+	jclass to = (_Jv_Resolver::resolve_pool_entry (defining_class,
+						       index)).clazz;
 	PUSHI (to->isInstance (value));
 
 #ifdef DIRECT_THREADED
@@ -3083,7 +3104,8 @@
 	int dim        = GET1U ();
 
 	jclass type    
-	  = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
+	  = (_Jv_Resolver::resolve_pool_entry (defining_class,
+					       kind_index)).clazz;
 	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
 
 	for (int i = dim - 1; i >= 0; i--)
@@ -3180,8 +3202,8 @@
 #else
 	      jclass handler = NULL;
 	      if (exc[i].handler_type.i != 0)
-		handler = (_Jv_ResolvePoolEntry (defining_class,
-						 exc[i].handler_type.i)).clazz;
+		handler = (_Jv_Resolver::resolve_pool_entry (defining_class,
+							     exc[i].handler_type.i)).clazz;
 #endif /* DIRECT_THREADED */
 
 	      if (handler == NULL || handler->isAssignableFrom (exc_class))
@@ -3234,4 +3256,536 @@
 }
 #endif
 
+/** 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 == &StringClass
+ 	     || 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->data;
+  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->data;
+
+  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++;
+
+  // assign arg types
+  while (*ptr != ')')
+    {
+      arg_types[arg_index++] = get_ffi_type_from_signature (ptr);
+
+      if (*ptr == 'J' || *ptr == 'D')
+	item_count += 2;
+      else
+	item_count += 1;
+
+      ptr = skip_one_type (ptr);
+    }
+
+  // skip ')'
+  ptr++;
+  ffi_type *rtype = get_ffi_type_from_signature (ptr);
+
+  ptr = skip_one_type (ptr);
+  if (ptr != (unsigned char*)signature->data + signature->length)
+    throw_internal_error ("did not find end of signature");
+
+  if (ffi_prep_cif (cif, FFI_DEFAULT_ABI,
+		    arg_count, rtype, arg_types) != FFI_OK)
+    throw_internal_error ("ffi_prep_cif failed");
+
+  if (rtype_p != NULL)
+    *rtype_p = rtype;
+
+  return item_count;
+}
+
+#if FFI_NATIVE_RAW_API
+#   define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure
+#   define FFI_RAW_SIZE ffi_raw_size
+#else
+#   define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure
+#   define FFI_RAW_SIZE ffi_java_raw_size
+#endif
+
+/* we put this one here, and not in interpret.cc because it
+ * calls the utility routines _Jv_count_arguments 
+ * which are static to this module.  The following struct defines the
+ * layout we use for the stubs, it's only used in the ncode method. */
+
+typedef struct {
+  ffi_raw_closure  closure;
+  ffi_cif   cif;
+  ffi_type *arg_types[0];
+} ncode_closure;
+
+typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_raw*,void*);
+
+void *
+_Jv_InterpMethod::ncode ()
+{
+  using namespace java::lang::reflect;
+
+  if (self->ncode != 0)
+    return self->ncode;
+
+  jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
+  int arg_count = _Jv_count_arguments (self->signature, staticp);
+
+  ncode_closure *closure =
+    (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure)
+					+ arg_count * sizeof (ffi_type*));
+
+  init_cif (self->signature,
+	    arg_count,
+	    staticp,
+	    &closure->cif,
+	    &closure->arg_types[0],
+	    NULL);
+
+  ffi_closure_fun fun;
+
+  args_raw_size = FFI_RAW_SIZE (&closure->cif);
+
+  JvAssert ((self->accflags & Modifier::NATIVE) == 0);
+
+  if ((self->accflags & Modifier::SYNCHRONIZED) != 0)
+    {
+      if (staticp)
+	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
+      else
+	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object; 
+    }
+  else
+    {
+      if (staticp)
+	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
+      else
+	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+    }
+
+  FFI_PREP_RAW_CLOSURE (&closure->closure,
+		        &closure->cif, 
+		        fun,
+		        (void*)this);
+
+  self->ncode = (void*)closure;
+  return self->ncode;
+}
+
+void *
+_Jv_JNIMethod::ncode ()
+{
+  using namespace java::lang::reflect;
+
+  if (self->ncode != 0)
+    return self->ncode;
+
+  jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
+  int arg_count = _Jv_count_arguments (self->signature, staticp);
+
+  ncode_closure *closure =
+    (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure)
+				    + arg_count * sizeof (ffi_type*));
+
+  ffi_type *rtype;
+  init_cif (self->signature,
+	    arg_count,
+	    staticp,
+	    &closure->cif,
+	    &closure->arg_types[0],
+	    &rtype);
+
+  ffi_closure_fun fun;
+
+  args_raw_size = FFI_RAW_SIZE (&closure->cif);
+
+  // Initialize the argument types and CIF that represent the actual
+  // underlying JNI function.
+  int extra_args = 1;
+  if ((self->accflags & Modifier::STATIC))
+    ++extra_args;
+  jni_arg_types = (ffi_type **) _Jv_Malloc ((extra_args + arg_count)
+					    * sizeof (ffi_type *));
+  int offset = 0;
+  jni_arg_types[offset++] = &ffi_type_pointer;
+  if ((self->accflags & Modifier::STATIC))
+    jni_arg_types[offset++] = &ffi_type_pointer;
+  memcpy (&jni_arg_types[offset], &closure->arg_types[0],
+	  arg_count * sizeof (ffi_type *));
+
+  if (ffi_prep_cif (&jni_cif, _Jv_platform_ffi_abi,
+		    extra_args + arg_count, rtype,
+		    jni_arg_types) != FFI_OK)
+    throw_internal_error ("ffi_prep_cif failed for JNI function");
+
+  JvAssert ((self->accflags & Modifier::NATIVE) != 0);
+
+  // FIXME: for now we assume that all native methods for
+  // interpreted code use JNI.
+  fun = (ffi_closure_fun) &_Jv_JNIMethod::call;
+
+  FFI_PREP_RAW_CLOSURE (&closure->closure,
+			&closure->cif, 
+			fun,
+			(void*) this);
+
+  self->ncode = (void *) closure;
+  return self->ncode;
+}
+
+static void
+throw_class_format_error (jstring msg)
+{
+  throw (msg
+	 ? new java::lang::ClassFormatError (msg)
+	 : new java::lang::ClassFormatError);
+}
+
+static void
+throw_class_format_error (char *msg)
+{
+  throw_class_format_error (JvNewStringLatin1 (msg));
+}
+
+
+void
+_Jv_InterpreterEngine::do_verify (jclass klass)
+{
+  _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info;
+  for (int i = 0; i < klass->method_count; i++)
+    {
+      _Jv_MethodBase *imeth = iclass->interpreted_methods[i];
+      if ((klass->methods[i].accflags & java::lang::reflect::Modifier::NATIVE)
+	  == 0)
+	{
+	  _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth);
+	  _Jv_VerifyMethod (im);
+	}
+    }
+}
+
+void
+_Jv_InterpreterEngine::do_create_ncode (jclass klass)
+{
+  _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info;
+  for (int i = 0; i < klass->method_count; i++)
+    {
+      // Just skip abstract methods.  This is particularly important
+      // because we don't resize the interpreted_methods array when
+      // miranda methods are added to it.
+      if ((klass->methods[i].accflags
+	   & java::lang::reflect::Modifier::ABSTRACT)
+	  != 0)
+	continue;
+
+      _Jv_MethodBase *imeth = iclass->interpreted_methods[i];
+
+      if ((klass->methods[i].accflags & java::lang::reflect::Modifier::NATIVE)
+	  != 0)
+	{
+	  // You might think we could use a virtual `ncode' method in
+	  // the _Jv_MethodBase and unify the native and non-native
+	  // cases.  Well, we can't, because we don't allocate these
+	  // objects using `new', and thus they don't get a vtable.
+	  _Jv_JNIMethod *jnim = reinterpret_cast<_Jv_JNIMethod *> (imeth);
+	  klass->methods[i].ncode = jnim->ncode ();
+	}
+      else if (imeth != 0)		// it could be abstract
+	{
+	  _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth);
+	  klass->methods[i].ncode = im->ncode ();
+
+	  // Resolve ctable entries pointing to this method.  See
+	  // _Jv_Defer_Resolution.
+	  void **code = (void **)imeth->deferred;
+	  while (code)
+	    {
+	      void **target = (void **)*code;
+	      *code = klass->methods[i].ncode;
+	      code = target;
+	    }
+	}
+    }
+}
+
+void
+_Jv_InterpreterEngine::do_allocate_static_fields (jclass klass,
+						  int static_size)
+{
+  _Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info;
+
+  char *static_data = (char *) _Jv_AllocBytes (static_size);
+  memset (static_data, 0, static_size);
+
+  for (int i = 0; i < klass->field_count; i++)
+    {
+      _Jv_Field *field = &klass->fields[i];
+
+      if ((field->flags & java::lang::reflect::Modifier::STATIC) != 0)
+	{
+	  field->u.addr  = static_data + field->u.boffset;
+	      
+	  if (iclass->field_initializers[i] != 0)
+	    {
+	      _Jv_Resolver::resolve_field (field, klass->loader);
+	      _Jv_InitField (0, klass, i);
+	    }
+	}
+    }
+
+  // Now we don't need the field_initializers anymore, so let the
+  // collector get rid of it.
+  iclass->field_initializers = 0;
+}
+
+_Jv_ResolvedMethod *
+_Jv_InterpreterEngine::do_resolve_method (_Jv_Method *method, jclass klass,
+					  jboolean staticp, jint vtable_index)
+{
+  int arg_count = _Jv_count_arguments (method->signature, staticp);
+
+  _Jv_ResolvedMethod* result = (_Jv_ResolvedMethod*)
+    _Jv_AllocBytes (sizeof (_Jv_ResolvedMethod)
+		    + arg_count*sizeof (ffi_type*));
+
+  result->stack_item_count
+    = init_cif (method->signature,
+		arg_count,
+		staticp,
+		&result->cif,
+		&result->arg_types[0],
+		NULL);
+
+  result->vtable_index        = vtable_index;
+  result->method              = method;
+  result->klass               = klass;
+
+  return result;
+}
+
 #endif // INTERPRETER
Index: libjava/jni.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/jni.cc,v
retrieving revision 1.81.6.1
diff -u -r1.81.6.1 jni.cc
--- libjava/jni.cc 20 Apr 2004 21:59:38 -0000 1.81.6.1
+++ libjava/jni.cc 14 Sep 2004 20:02:21 -0000
@@ -1,6 +1,6 @@
 // jni.cc - JNI implementation, including the jump table.
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -1198,7 +1198,7 @@
 
 	      // The field might be resolved or it might not be.  It
 	      // is much simpler to always resolve it.
-	      _Jv_ResolveField (field, loader);
+	      _Jv_Resolver::resolve_field (field, loader);
 	      if (_Jv_equalUtf8Consts (f_name, a_name)
 		  && field->getClass() == field_class)
 		return field;
Index: libjava/prims.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/prims.cc,v
retrieving revision 1.87.10.4
diff -u -r1.87.10.4 prims.cc
--- libjava/prims.cc 1 Sep 2004 21:52:43 -0000 1.87.10.4
+++ libjava/prims.cc 14 Sep 2004 20:02:21 -0000
@@ -61,11 +61,15 @@
 #include <gnu/gcj/runtime/VMClassLoader.h>
 #include <gnu/gcj/runtime/FinalizerThread.h>
 #include <gnu/gcj/runtime/FirstThread.h>
+#include <execution.h>
 
 #ifdef USE_LTDL
 #include <ltdl.h>
 #endif
 
+// Execution engine for compiled code.
+_Jv_CompiledEngine _Jv_soleCompiledEngine;
+
 // We allocate a single OutOfMemoryError exception which we keep
 // around for use if we run out of memory.
 static java::lang::OutOfMemoryError *no_memory;
@@ -1228,20 +1232,6 @@
   return ((self_klass == other_klass)
 	  || ((flags & Modifier::PUBLIC) != 0)
 	  || (((flags & Modifier::PROTECTED) != 0)
-	      && other_klass->isAssignableFrom (self_klass))
-	  || (((flags & Modifier::PRIVATE) == 0)
-	      && _Jv_ClassNameSamePackage (self_klass->name,
-					   other_klass->name)));
-}
-
-// Like _Jv_CheckAccess, but won't cause classes to be initialized.
-jboolean
-_Jv_CheckAccessNoInit (jclass self_klass, jclass other_klass, jint flags)
-{
-  using namespace java::lang::reflect;
-  return ((self_klass == other_klass)
-	  || ((flags & Modifier::PUBLIC) != 0)
-	  || (((flags & Modifier::PROTECTED) != 0)
 	      && _Jv_IsAssignableFromSlow (other_klass, self_klass))
 	  || (((flags & Modifier::PRIVATE) == 0)
 	      && _Jv_ClassNameSamePackage (self_klass->name,
Index: libjava/resolve.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/resolve.cc,v
retrieving revision 1.44.2.4
diff -u -r1.44.2.4 resolve.cc
--- libjava/resolve.cc 12 Aug 2004 23:16:26 -0000 1.44.2.4
+++ libjava/resolve.cc 14 Sep 2004 20:02:21 -0000
@@ -19,12 +19,14 @@
 #include <gcj/cni.h>
 #include <string.h>
 #include <java-cpool.h>
+#include <execution.h>
 #include <java/lang/Class.h>
 #include <java/lang/String.h>
 #include <java/lang/StringBuffer.h>
 #include <java/lang/Thread.h>
 #include <java/lang/InternalError.h>
 #include <java/lang/VirtualMachineError.h>
+#include <java/lang/VerifyError.h>
 #include <java/lang/NoSuchFieldError.h>
 #include <java/lang/NoSuchMethodError.h>
 #include <java/lang/ClassFormatError.h>
@@ -37,8 +39,46 @@
 
 using namespace gcj;
 
+typedef unsigned int uaddr __attribute__ ((mode (pointer)));
+
+template<typename T>
+struct aligner
+{
+  char c;
+  T field;
+};
+
+#define ALIGNOF(TYPE) (offsetof (aligner<TYPE>, field))
+
+// This returns the alignment of a type as it would appear in a
+// structure.  This can be different from the alignment of the type
+// itself.  For instance on x86 double is 8-aligned but struct{double}
+// is 4-aligned.
+int
+_Jv_Resolver::get_alignment_from_class (jclass klass)
+{
+  if (klass == JvPrimClass (byte))
+    return ALIGNOF (jbyte);
+  else if (klass == JvPrimClass (short))
+    return ALIGNOF (jshort);
+  else if (klass == JvPrimClass (int)) 
+    return ALIGNOF (jint);
+  else if (klass == JvPrimClass (long))
+    return ALIGNOF (jlong);
+  else if (klass == JvPrimClass (boolean))
+    return ALIGNOF (jboolean);
+  else if (klass == JvPrimClass (char))
+    return ALIGNOF (jchar);
+  else if (klass == JvPrimClass (float))
+    return ALIGNOF (jfloat);
+  else if (klass == JvPrimClass (double))
+    return ALIGNOF (jdouble);
+  else
+    return ALIGNOF (jobject);
+}
+
 void
-_Jv_ResolveField (_Jv_Field *field, java::lang::ClassLoader *loader)
+_Jv_Resolver::resolve_field (_Jv_Field *field, java::lang::ClassLoader *loader)
 {
   if (! field->isResolved ())
     {
@@ -48,29 +88,8 @@
     }
 }
 
-#ifdef INTERPRETER
-
-static void throw_internal_error (char *msg)
-	__attribute__ ((__noreturn__));
-static void throw_class_format_error (jstring msg)
-	__attribute__ ((__noreturn__));
-static void throw_class_format_error (char *msg)
-	__attribute__ ((__noreturn__));
-
-static _Jv_ResolvedMethod* 
-_Jv_BuildResolvedMethod (_Jv_Method*,
-			 jclass,
-			 jboolean,
-			 jint);
-
-
-static void throw_incompatible_class_change_error (jstring msg)
-{
-  throw new java::lang::IncompatibleClassChangeError (msg);
-}
-
 _Jv_word
-_Jv_ResolvePoolEntry (jclass klass, int index)
+_Jv_Resolver::resolve_pool_entry (jclass klass, int index)
 {
   using namespace java::lang::reflect;
 
@@ -79,252 +98,284 @@
   if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0)
     return pool->data[index];
 
-  switch (pool->tags[index]) {
-  case JV_CONSTANT_Class:
+  switch (pool->tags[index])
     {
-      _Jv_Utf8Const *name = pool->data[index].utf8;
-
-      jclass found;
-      if (name->data[0] == '[')
-	found = _Jv_FindClassFromSignature (&name->data[0],
-					    klass->loader);
-      else
-	found = _Jv_FindClass (name, klass->loader);
+    case JV_CONSTANT_Class:
+      {
+	_Jv_Utf8Const *name = pool->data[index].utf8;
 
-      if (! found)
-	{
-	  jstring str = _Jv_NewStringUTF (name->data);
-	  // This exception is specified in JLS 2nd Ed, section 5.1.
-	  throw new java::lang::NoClassDefFoundError (str);
-	}
+	jclass found;
+	if (name->data[0] == '[')
+	  found = _Jv_FindClassFromSignature (&name->data[0],
+					      klass->loader);
+	else
+	  found = _Jv_FindClass (name, klass->loader);
 
-      if ((found->accflags & Modifier::PUBLIC) == Modifier::PUBLIC
-	  || (_Jv_ClassNameSamePackage (found->name,
-					klass->name)))
-	{
-	  pool->data[index].clazz = found;
-	  pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
-	}
-      else
-	{
+	if (! found)
+	  {
+	    jstring str = _Jv_NewStringUTF (name->data);
+	    // This exception is specified in JLS 2nd Ed, section 5.1.
+	    throw new java::lang::NoClassDefFoundError (str);
+	  }
+
+	// Check accessibility, but first strip array types as
+	// _Jv_ClassNameSamePackage can't handle arrays.
+	jclass check;
+	for (check = found;
+	     check && check->isArray();
+	     check = check->getComponentType())
+	  ;
+	if ((found->accflags & Modifier::PUBLIC) == Modifier::PUBLIC
+	    || (_Jv_ClassNameSamePackage (check->name,
+					  klass->name)))
+	  {
+	    pool->data[index].clazz = found;
+	    pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+	  }
+	else
 	  throw new java::lang::IllegalAccessError (found->getName());
-	}
-    }
-    break;
-
-  case JV_CONSTANT_String:
-    {
-      jstring str;
-      str = _Jv_NewStringUtf8Const (pool->data[index].utf8);
-      pool->data[index].o = str;
-      pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
-    }
-    break;
-
-
-  case JV_CONSTANT_Fieldref:
-    {
-      _Jv_ushort class_index, name_and_type_index;
-      _Jv_loadIndexes (&pool->data[index],
-		       class_index,
-		       name_and_type_index);
-      jclass owner = (_Jv_ResolvePoolEntry (klass, class_index)).clazz;
-
-      if (owner != klass)
-	_Jv_InitClass (owner);
-
-      _Jv_ushort name_index, type_index;
-      _Jv_loadIndexes (&pool->data[name_and_type_index],
-		       name_index,
-		       type_index);
-
-      _Jv_Utf8Const *field_name = pool->data[name_index].utf8;
-      _Jv_Utf8Const *field_type_name = pool->data[type_index].utf8;
-
-      // FIXME: The implementation of this function
-      // (_Jv_FindClassFromSignature) will generate an instance of
-      // _Jv_Utf8Const for each call if the field type is a class name
-      // (Lxx.yy.Z;).  This may be too expensive to do for each and
-      // every fieldref being resolved.  For now, we fix the problem by
-      // only doing it when we have a loader different from the class
-      // declaring the field.
+      }
+      break;
 
-      jclass field_type = 0;
+    case JV_CONSTANT_String:
+      {
+	jstring str;
+	str = _Jv_NewStringUtf8Const (pool->data[index].utf8);
+	pool->data[index].o = str;
+	pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+      }
+      break;
 
-      if (owner->loader != klass->loader)
-	field_type = _Jv_FindClassFromSignature (field_type_name->data,
-						 klass->loader);
+    case JV_CONSTANT_Fieldref:
+      {
+	_Jv_ushort class_index, name_and_type_index;
+	_Jv_loadIndexes (&pool->data[index],
+			 class_index,
+			 name_and_type_index);
+	jclass owner = (resolve_pool_entry (klass, class_index)).clazz;
+
+	if (owner != klass)
+	  _Jv_InitClass (owner);
+
+	_Jv_ushort name_index, type_index;
+	_Jv_loadIndexes (&pool->data[name_and_type_index],
+			 name_index,
+			 type_index);
+
+	_Jv_Utf8Const *field_name = pool->data[name_index].utf8;
+	_Jv_Utf8Const *field_type_name = pool->data[type_index].utf8;
+
+	// FIXME: The implementation of this function
+	// (_Jv_FindClassFromSignature) will generate an instance of
+	// _Jv_Utf8Const for each call if the field type is a class name
+	// (Lxx.yy.Z;).  This may be too expensive to do for each and
+	// every fieldref being resolved.  For now, we fix the problem by
+	// only doing it when we have a loader different from the class
+	// declaring the field.
+
+	jclass field_type = 0;
+
+	if (owner->loader != klass->loader)
+	  field_type = _Jv_FindClassFromSignature (field_type_name->data,
+						   klass->loader);
       
-      _Jv_Field* the_field = 0;
+	_Jv_Field* the_field = 0;
 
-      for (jclass cls = owner; cls != 0; cls = cls->getSuperclass ())
-	{
-	  for (int i = 0;  i < cls->field_count;  i++)
-	    {
-	      _Jv_Field *field = &cls->fields[i];
-	      if (! _Jv_equalUtf8Consts (field->name, field_name))
-		continue;
-
-	      if (_Jv_CheckAccess (klass, cls, field->flags))
-		{
-		  /* resove the field using the class' own loader
-		     if necessary */
+	for (jclass cls = owner; cls != 0; cls = cls->getSuperclass ())
+	  {
+	    for (int i = 0;  i < cls->field_count;  i++)
+	      {
+		_Jv_Field *field = &cls->fields[i];
+		if (! _Jv_equalUtf8Consts (field->name, field_name))
+		  continue;
+
+		if (_Jv_CheckAccess (klass, cls, field->flags))
+		  {
+		    // Resolve the field using the class' own loader if
+		    // necessary.
+
+		    if (!field->isResolved ())
+		      resolve_field (field, cls->loader);
+
+		    if (field_type != 0 && field->type != field_type)
+		      throw new java::lang::LinkageError
+			(JvNewStringLatin1 
+			 ("field type mismatch with different loaders"));
+
+		    the_field = field;
+		    goto end_of_field_search;
+		  }
+		else
+		  {
+		    java::lang::StringBuffer *sb
+		      = new java::lang::StringBuffer ();
+		    sb->append(klass->getName());
+		    sb->append(JvNewStringLatin1(": "));
+		    sb->append(cls->getName());
+		    sb->append(JvNewStringLatin1("."));
+		    sb->append(_Jv_NewStringUtf8Const (field_name));
+		    throw new java::lang::IllegalAccessError(sb->toString());
+		  }
+	      }
+	  }
+
+      end_of_field_search:
+	if (the_field == 0)
+	  {
+	    java::lang::StringBuffer *sb = new java::lang::StringBuffer();
+	    sb->append(JvNewStringLatin1("field "));
+	    sb->append(owner->getName());
+	    sb->append(JvNewStringLatin1("."));
+	    sb->append(_Jv_NewStringUTF(field_name->data));
+	    sb->append(JvNewStringLatin1(" was not found."));
+	    throw
+	      new java::lang::IncompatibleClassChangeError (sb->toString());
+	  }
 
-		  if (!field->isResolved ())
-		    _Jv_ResolveField (field, cls->loader);
-
-		  if (field_type != 0 && field->type != field_type)
-		    throw new java::lang::LinkageError
-		      (JvNewStringLatin1 
-		       ("field type mismatch with different loaders"));
+	pool->data[index].field = the_field;
+	pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+      }
+      break;
 
-		  the_field = field;
-		  goto end_of_field_search;
-		}
-	      else
-		{
-		  java::lang::StringBuffer *sb
-		    = new java::lang::StringBuffer ();
-		  sb->append(klass->getName());
-		  sb->append(JvNewStringLatin1(": "));
-		  sb->append(cls->getName());
-		  sb->append(JvNewStringLatin1("."));
-		  sb->append(_Jv_NewStringUtf8Const (field_name));
-		  throw new java::lang::IllegalAccessError(sb->toString());
-		}
-	    }
-	}
+    case JV_CONSTANT_Methodref:
+    case JV_CONSTANT_InterfaceMethodref:
+      {
+	_Jv_ushort class_index, name_and_type_index;
+	_Jv_loadIndexes (&pool->data[index],
+			 class_index,
+			 name_and_type_index);
+	jclass owner = (resolve_pool_entry (klass, class_index)).clazz;
+
+	if (owner != klass)
+	  _Jv_InitClass (owner);
+
+	_Jv_ushort name_index, type_index;
+	_Jv_loadIndexes (&pool->data[name_and_type_index],
+			 name_index,
+			 type_index);
+
+	_Jv_Utf8Const *method_name = pool->data[name_index].utf8;
+	_Jv_Utf8Const *method_signature = pool->data[type_index].utf8;
+
+	_Jv_Method *the_method = 0;
+	jclass found_class = 0;
+
+	// First search the class itself.
+	the_method = _Jv_SearchMethodInClass (owner, klass, 
+					      method_name, method_signature);
+
+	if (the_method != 0)
+	  {
+	    found_class = owner;
+	    goto end_of_method_search;
+	  }
 
-    end_of_field_search:
-      if (the_field == 0)
-	{
-	  java::lang::StringBuffer *sb = new java::lang::StringBuffer();
-	  sb->append(JvNewStringLatin1("field "));
-	  sb->append(owner->getName());
-	  sb->append(JvNewStringLatin1("."));
-	  sb->append(_Jv_NewStringUTF(field_name->data));
-	  sb->append(JvNewStringLatin1(" was not found."));
-	  throw_incompatible_class_change_error(sb->toString());
-	}
+	// If we are resolving an interface method, search the
+	// interface's superinterfaces (A superinterface is not an
+	// interface's superclass - a superinterface is implemented by
+	// the interface).
+	if (pool->tags[index] == JV_CONSTANT_InterfaceMethodref)
+	  {
+	    _Jv_ifaces ifaces;
+	    ifaces.count = 0;
+	    ifaces.len = 4;
+	    ifaces.list = (jclass *) _Jv_Malloc (ifaces.len
+						 * sizeof (jclass *));
+
+	    get_interfaces (owner, &ifaces);	  
+
+	    for (int i = 0; i < ifaces.count; i++)
+	      {
+		jclass cls = ifaces.list[i];
+		the_method = _Jv_SearchMethodInClass (cls, klass, method_name, 
+						      method_signature);
+		if (the_method != 0)
+		  {
+		    found_class = cls;
+		    break;
+		  }
+	      }
+
+	    _Jv_Free (ifaces.list);
+
+	    if (the_method != 0)
+	      goto end_of_method_search;
+	  }
+
+	// Finally, search superclasses. 
+	for (jclass cls = owner->getSuperclass (); cls != 0; 
+	     cls = cls->getSuperclass ())
+	  {
+	    the_method = _Jv_SearchMethodInClass (cls, klass, method_name,
+						  method_signature);
+	    if (the_method != 0)
+	      {
+		found_class = cls;
+		break;
+	      }
+	  }
 
-      pool->data[index].field = the_field;
-      pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+      end_of_method_search:
+    
+	// FIXME: if (cls->loader != klass->loader), then we
+	// must actually check that the types of arguments
+	// correspond.  That is, for each argument type, and
+	// the return type, doing _Jv_FindClassFromSignature
+	// with either loader should produce the same result,
+	// i.e., exactly the same jclass object. JVMS 5.4.3.3    
+    
+	if (the_method == 0)
+	  {
+	    java::lang::StringBuffer *sb = new java::lang::StringBuffer();
+	    sb->append(JvNewStringLatin1("method "));
+	    sb->append(owner->getName());
+	    sb->append(JvNewStringLatin1("."));
+	    sb->append(_Jv_NewStringUTF(method_name->data));
+	    sb->append(JvNewStringLatin1(" was not found."));
+	    throw new java::lang::NoSuchMethodError (sb->toString());
+	  }
+      
+	int vtable_index = -1;
+	if (pool->tags[index] != JV_CONSTANT_InterfaceMethodref)
+	  vtable_index = (jshort)the_method->index;
+
+	pool->data[index].rmethod
+	  = klass->engine->resolve_method(the_method,
+					  found_class,
+					  ((the_method->accflags
+					    & Modifier::STATIC) != 0),
+					  vtable_index);
+	pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+      }
+      break;
     }
-    break;
-
-  case JV_CONSTANT_Methodref:
-  case JV_CONSTANT_InterfaceMethodref:
-    {
-      _Jv_ushort class_index, name_and_type_index;
-      _Jv_loadIndexes (&pool->data[index],
-		       class_index,
-		       name_and_type_index);
-      jclass owner = (_Jv_ResolvePoolEntry (klass, class_index)).clazz;
-
-      if (owner != klass)
-	_Jv_InitClass (owner);
-
-      _Jv_ushort name_index, type_index;
-      _Jv_loadIndexes (&pool->data[name_and_type_index],
-		       name_index,
-		       type_index);
-
-      _Jv_Utf8Const *method_name = pool->data[name_index].utf8;
-      _Jv_Utf8Const *method_signature = pool->data[type_index].utf8;
-
-      _Jv_Method *the_method = 0;
-      jclass found_class = 0;
-
-      // First search the class itself.
-      the_method = _Jv_SearchMethodInClass (owner, klass, 
-					    method_name, method_signature);
-
-      if (the_method != 0)
-        {
-	  found_class = owner;
-          goto end_of_method_search;
-	}
-
-      // If we are resolving an interface method, search the
-      // interface's superinterfaces (A superinterface is not an
-      // interface's superclass - a superinterface is implemented by
-      // the interface).
-      if (pool->tags[index] == JV_CONSTANT_InterfaceMethodref)
-        {
-	  _Jv_ifaces ifaces;
-	  ifaces.count = 0;
-	  ifaces.len = 4;
-	  ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *));
-
-	  _Jv_GetInterfaces (owner, &ifaces);	  
-
-	  for (int i = 0; i < ifaces.count; i++)
-	    {
-	      jclass cls = ifaces.list[i];
-	      the_method = _Jv_SearchMethodInClass (cls, klass, method_name, 
-	                                            method_signature);
-	      if (the_method != 0)
-	        {
-		  found_class = cls;
-                  break;
-		}
-	    }
-
-	  _Jv_Free (ifaces.list);
+  return pool->data[index];
+}
 
-	  if (the_method != 0)
-	    goto end_of_method_search;
-	}
+// This function is used to lazily locate superclasses and
+// superinterfaces.  This must be called with the class lock held.
+void
+_Jv_Resolver::resolve_class_ref (jclass klass, jclass *classref)
+{
+  jclass ret = *classref;
 
-      // Finally, search superclasses. 
-      for (jclass cls = owner->getSuperclass (); cls != 0; 
-           cls = cls->getSuperclass ())
+  // If superclass looks like a constant pool entry, resolve it now.
+  if (ret && (uaddr) ret < (uaddr) klass->constants.size)
+    {
+      if (klass->state < JV_STATE_LINKED)
 	{
-	  the_method = _Jv_SearchMethodInClass (cls, klass, 
-						method_name, method_signature);
-          if (the_method != 0)
+	  _Jv_Utf8Const *name = klass->constants.data[(uaddr) *classref].utf8;
+	  ret = _Jv_FindClass (name, klass->loader);
+	  if (! ret)
 	    {
-	      found_class = cls;
-	      break;
+	      jstring str = _Jv_NewStringUTF (name->data);
+	      throw new java::lang::NoClassDefFoundError (str);
 	    }
 	}
-
-    end_of_method_search:
-    
-      // FIXME: if (cls->loader != klass->loader), then we
-      // must actually check that the types of arguments
-      // correspond.  That is, for each argument type, and
-      // the return type, doing _Jv_FindClassFromSignature
-      // with either loader should produce the same result,
-      // i.e., exactly the same jclass object. JVMS 5.4.3.3    
-    
-      if (the_method == 0)
-	{
-	  java::lang::StringBuffer *sb = new java::lang::StringBuffer();
-	  sb->append(JvNewStringLatin1("method "));
-	  sb->append(owner->getName());
-	  sb->append(JvNewStringLatin1("."));
-	  sb->append(_Jv_NewStringUTF(method_name->data));
-	  sb->append(JvNewStringLatin1(" was not found."));
-	  throw new java::lang::NoSuchMethodError (sb->toString());
-	}
-      
-      int vtable_index = -1;
-      if (pool->tags[index] != JV_CONSTANT_InterfaceMethodref)
-	vtable_index = (jshort)the_method->index;
-
-      pool->data[index].rmethod = 
-	_Jv_BuildResolvedMethod(the_method,
-				found_class,
-				(the_method->accflags & Modifier::STATIC) != 0,
-				vtable_index);
-      pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+      else
+	ret = klass->constants.data[(uaddr) classref].clazz;
+      *classref = ret;
     }
-    break;
-
-  }
-
-  return pool->data[index];
 }
 
 // Find a method declared in the cls that is referenced from klass and
@@ -362,667 +413,1253 @@
   return 0;
 }
 
-// A helper for _Jv_PrepareClass.  This adds missing `Miranda methods'
-// to a class.
+
+#define INITIAL_IOFFSETS_LEN 4
+#define INITIAL_IFACES_LEN 4
+
+static _Jv_IDispatchTable null_idt = { {SHRT_MAX, 0, NULL} };
+
+// Generate tables for constant-time assignment testing and interface
+// method lookup. This implements the technique described by Per Bothner
+// <per@bothner.com> on the java-discuss mailing list on 1999-09-02:
+// http://gcc.gnu.org/ml/java/1999-q3/msg00377.html
 void
-_Jv_PrepareMissingMethods (jclass base, jclass iface_class)
-{
-  _Jv_InterpClass *interp_base = (_Jv_InterpClass *) base->aux_info;
-  for (int i = 0; i < iface_class->interface_count; ++i)
+_Jv_Resolver::prepare_constant_time_tables (jclass klass)
+{  
+  if (klass->isPrimitive () || klass->isInterface ())
+    return;
+
+  // Short-circuit in case we've been called already.
+  if ((klass->idt != NULL) || klass->depth != 0)
+    return;
+
+  // Calculate the class depth and ancestor table. The depth of a class 
+  // is how many "extends" it is removed from Object. Thus the depth of 
+  // java.lang.Object is 0, but the depth of java.io.FilterOutputStream 
+  // is 2. Depth is defined for all regular and array classes, but not 
+  // interfaces or primitive types.
+   
+  jclass klass0 = klass;
+  jboolean has_interfaces = 0;
+  while (klass0 != &java::lang::Object::class$)
     {
-      jclass interface = iface_class->interfaces[i];
-      
-      typedef unsigned int uaddr __attribute__ ((mode (pointer)));
+      has_interfaces += klass0->interface_count;
+      klass0 = klass0->superclass;
+      klass->depth++;
+    }
 
-      // If interface looks like a constant pool entry,
-      // resolve it now.
-      if (interface && (uaddr)interface < (uaddr)iface_class->constants.size)
-	{
-	  if (iface_class->state < JV_STATE_LINKED) // This can't ever happen
-	    {
-	      _Jv_Utf8Const *name = iface_class->constants.data[(int)interface].utf8;
-	      interface = _Jv_FindClass (name, iface_class->loader);
-	      if (! interface)
-		{
-		  jstring str = _Jv_NewStringUTF (name->data);
-		  throw new java::lang::NoClassDefFoundError (str);
-		}
-	    }
-	  else
-	    interface = iface_class->constants.data[(int)interface].clazz;
-	}
+  // We do class member testing in constant time by using a small table 
+  // of all the ancestor classes within each class. The first element is 
+  // a pointer to the current class, and the rest are pointers to the 
+  // classes ancestors, ordered from the current class down by decreasing 
+  // depth. We do not include java.lang.Object in the table of ancestors, 
+  // since it is redundant.
+
+  // FIXME: _Jv_AllocBytes
+  klass->ancestors = (jclass *) _Jv_Malloc (klass->depth
+						* sizeof (jclass));
+  klass0 = klass;
+  for (int index = 0; index < klass->depth; index++)
+    {
+      klass->ancestors[index] = klass0;
+      klass0 = klass0->superclass;
+    }
 
-      for (int j = 0; j < interface->method_count; ++j)
-	{
- 	  _Jv_Method *meth = &interface->methods[j];
-	  // Don't bother with <clinit>.
-	  if (meth->name->data[0] == '<')
-	    continue;
-	  _Jv_Method *new_meth = _Jv_LookupDeclaredMethod (base, meth->name,
-							   meth->signature);
-	  if (! new_meth)
-	    {
-	      // We assume that such methods are very unlikely, so we
-	      // just reallocate the method array each time one is
-	      // found.  This greatly simplifies the searching --
-	      // otherwise we have to make sure that each such method
-	      // found is really unique among all superinterfaces.
-	      int new_count = base->method_count + 1;
-	      _Jv_Method *new_m
-		= (_Jv_Method *) _Jv_AllocBytes (sizeof (_Jv_Method)
-						 * new_count);
-	      memcpy (new_m, base->methods,
-		      sizeof (_Jv_Method) * base->method_count);
+  if ((klass->accflags & java::lang::reflect::Modifier::ABSTRACT) != 0)
+    return;
 
-	      // Add new method.
-	      new_m[base->method_count] = *meth;
-	      new_m[base->method_count].index = (_Jv_ushort) -1;
-	      new_m[base->method_count].accflags
-		|= java::lang::reflect::Modifier::INVISIBLE;
+  // Optimization: If class implements no interfaces, use a common
+  // predefined interface table.
+  if (!has_interfaces)
+    {
+      klass->idt = &null_idt;
+      return;
+    }
 
-	      _Jv_MethodBase **new_im
-		= (_Jv_MethodBase **) _Jv_AllocBytes (sizeof (_Jv_MethodBase *)
-						      * new_count);
-	      memcpy (new_im, interp_base->interpreted_methods,
-		      sizeof (_Jv_MethodBase *) * base->method_count);
+  // FIXME: _Jv_AllocBytes
+  klass->idt = 
+    (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable));
+
+  _Jv_ifaces ifaces;
+  ifaces.count = 0;
+  ifaces.len = INITIAL_IFACES_LEN;
+  ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *));
 
-	      base->methods = new_m;
-	      interp_base->interpreted_methods = new_im;
-	      base->method_count = new_count;
-	    }
+  int itable_size = get_interfaces (klass, &ifaces);
+
+  if (ifaces.count > 0)
+    {
+      klass->idt->cls.itable = 
+	// FIXME: _Jv_AllocBytes
+	(void **) _Jv_Malloc (itable_size * sizeof (void *));
+      klass->idt->cls.itable_length = itable_size;
+
+      jshort *itable_offsets = 
+	(jshort *) _Jv_Malloc (ifaces.count * sizeof (jshort));
+
+      generate_itable (klass, &ifaces, itable_offsets);
+
+      jshort cls_iindex = find_iindex (ifaces.list, itable_offsets,
+				       ifaces.count);
+
+      for (int i = 0; i < ifaces.count; i++)
+	{
+	  ifaces.list[i]->idt->iface.ioffsets[cls_iindex] =
+	    itable_offsets[i];
 	}
 
-      _Jv_PrepareMissingMethods (base, interface);
+      klass->idt->cls.iindex = cls_iindex;	    
+
+      _Jv_Free (ifaces.list);
+      _Jv_Free (itable_offsets);
+    }
+  else 
+    {
+      klass->idt->cls.iindex = SHRT_MAX;
     }
 }
 
-void 
-_Jv_PrepareClass(jclass klass)
+// Return index of item in list, or -1 if item is not present.
+inline jshort
+_Jv_Resolver::indexof (void *item, void **list, jshort list_len)
 {
-  using namespace java::lang::reflect;
+  for (int i=0; i < list_len; i++)
+    {
+      if (list[i] == item)
+        return i;
+    }
+  return -1;
+}
 
- /*
-  * The job of this function is to: 1) assign storage to fields, and 2)
-  * build the vtable.  static fields are assigned real memory, instance
-  * fields are assigned offsets.
-  *
-  * NOTE: we have a contract with the garbage collector here.  Static
-  * reference fields must not be resolved, until after they have storage
-  * assigned which is the check used by the collector to see if it
-  * should indirect the static field reference and mark the object
-  * pointed to. 
-  *
-  * Most fields are resolved lazily (i.e. have their class-type
-  * assigned) when they are accessed the first time by calling as part
-  * of _Jv_ResolveField, which is allways called after _Jv_PrepareClass.
-  * Static fields with initializers are resolved as part of this
-  * function, as are fields with primitive types.
-  */
-
-  if (! _Jv_IsInterpretedClass (klass))
-    return;
-
-  if (klass->state >= JV_STATE_PREPARED)
-    return;
-
-  // Make sure super-class is linked.  This involves taking a lock on
-  // the super class, so we use the Java method resolveClass, which
-  // will unlock it properly, should an exception happen.  If there's
-  // no superclass, do nothing -- Object will already have been
-  // resolved.
+// Find all unique interfaces directly or indirectly implemented by klass.
+// Returns the size of the interface dispatch table (itable) for klass, which 
+// is the number of unique interfaces plus the total number of methods that 
+// those interfaces declare. May extend ifaces if required.
+jshort
+_Jv_Resolver::get_interfaces (jclass klass, _Jv_ifaces *ifaces)
+{
+  jshort result = 0;
+  
+  for (int i = 0; i < klass->interface_count; i++)
+    {
+      jclass iface = klass->interfaces[i];
 
-  if (klass->superclass)
-    java::lang::VMClassLoader::resolveClass (klass->getSuperclass());
+      /* Make sure interface is linked.  */
+      wait_for_state(iface, JV_STATE_LINKED);
 
-  /************ PART ONE: OBJECT LAYOUT ***************/
-  int static_size = _Jv_LayoutClass(klass);
+      if (indexof (iface, (void **) ifaces->list, ifaces->count) == -1)
+        {
+	  if (ifaces->count + 1 >= ifaces->len)
+	    {
+	      /* Resize ifaces list */
+	      ifaces->len = ifaces->len * 2;
+	      ifaces->list
+		= (jclass *) _Jv_Realloc (ifaces->list,
+					  ifaces->len * sizeof(jclass));
+	    }
+	  ifaces->list[ifaces->count] = iface;
+	  ifaces->count++;
 
-  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
+	  result += get_interfaces (klass->interfaces[i], ifaces);
+	}
+    }
+    
+  if (klass->isInterface())
+    result += klass->method_count + 1;
+  else if (klass->superclass)
+    result += get_interfaces (klass->superclass, ifaces);
+  return result;
+}
 
-  // allocate static memory
-  if (static_size != 0)
-    {
-      char *static_data = (char*)_Jv_AllocBytes (static_size);
+// Fill out itable in klass, resolving method declarations in each ifaces.
+// itable_offsets is filled out with the position of each iface in itable,
+// such that itable[itable_offsets[n]] == ifaces.list[n].
+void
+_Jv_Resolver::generate_itable (jclass klass, _Jv_ifaces *ifaces,
+			       jshort *itable_offsets)
+{
+  void **itable = klass->idt->cls.itable;
+  jshort itable_pos = 0;
 
-      memset (static_data, 0, static_size);
+  for (int i = 0; i < ifaces->count; i++)
+    { 
+      jclass iface = ifaces->list[i];
+      itable_offsets[i] = itable_pos;
+      itable_pos = append_partial_itable (klass, iface, itable, itable_pos);
 
-      for (int i = 0; i < klass->field_count; i++)
+      /* Create interface dispatch table for iface */
+      if (iface->idt == NULL)
 	{
-	  _Jv_Field *field = &klass->fields[i];
+	  // FIXME: _Jv_AllocBytes
+	  iface->idt
+	    = (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable));
+
+	  // The first element of ioffsets is its length (itself included).
+	  // FIXME: _Jv_AllocBytes
+	  jshort *ioffsets = (jshort *) _Jv_Malloc (INITIAL_IOFFSETS_LEN
+						    * sizeof (jshort));
+	  ioffsets[0] = INITIAL_IOFFSETS_LEN;
+	  for (int i = 1; i < INITIAL_IOFFSETS_LEN; i++)
+	    ioffsets[i] = -1;
 
-	  if ((field->flags & Modifier::STATIC) != 0)
-	    {
-	      field->u.addr  = static_data + field->u.boffset;
-	      
-	      if (iclass->field_initializers[i] != 0)
-		{
-		  _Jv_ResolveField (field, klass->loader);
-		  _Jv_InitField (0, klass, i);
-		}
-	    }
+	  iface->idt->iface.ioffsets = ioffsets;	    
 	}
+    }
+}
 
-      // now we don't need the field_initializers anymore, so let the
-      // collector get rid of it!
+// Format method name for use in error messages.
+jstring
+_Jv_GetMethodString (jclass klass, _Jv_Utf8Const *name)
+{
+  jstring r = JvNewStringUTF (klass->name->data);
+  r = r->concat (JvNewStringUTF ("."));
+  r = r->concat (JvNewStringUTF (name->data));
+  return r;
+}
 
-      iclass->field_initializers = 0;
-    }
+void 
+_Jv_ThrowNoSuchMethodError ()
+{
+  throw new java::lang::NoSuchMethodError;
+}
 
-  /************ PART TWO: VTABLE LAYOUT ***************/
+// Each superinterface of a class (i.e. each interface that the class
+// directly or indirectly implements) has a corresponding "Partial
+// Interface Dispatch Table" whose size is (number of methods + 1) words.
+// The first word is a pointer to the interface (i.e. the java.lang.Class
+// instance for that interface).  The remaining words are pointers to the
+// actual methods that implement the methods declared in the interface,
+// in order of declaration.
+//
+// Append partial interface dispatch table for "iface" to "itable", at
+// position itable_pos.
+// Returns the offset at which the next partial ITable should be appended.
+jshort
+_Jv_Resolver::append_partial_itable (jclass klass, jclass iface,
+				     void **itable, jshort pos)
+{
+  using namespace java::lang::reflect;
 
-  /* preparation: build the vtable stubs (even interfaces can)
-     have code -- for static constructors. */
-  for (int i = 0; i < klass->method_count; i++)
+  itable[pos++] = (void *) iface;
+  _Jv_Method *meth;
+  
+  for (int j=0; j < iface->method_count; j++)
     {
-      _Jv_MethodBase *imeth = iclass->interpreted_methods[i];
+      meth = NULL;
+      for (jclass cl = klass; cl; cl = cl->getSuperclass())
+        {
+	  meth = _Jv_GetMethodLocal (cl, iface->methods[j].name,
+				     iface->methods[j].signature);
+		 
+	  if (meth)
+	    break;
+	}
 
-      if ((klass->methods[i].accflags & Modifier::NATIVE) != 0)
+      if (meth && (meth->name->data[0] == '<'))
 	{
-	  // You might think we could use a virtual `ncode' method in
-	  // the _Jv_MethodBase and unify the native and non-native
-	  // cases.  Well, we can't, because we don't allocate these
-	  // objects using `new', and thus they don't get a vtable.
-	  _Jv_JNIMethod *jnim = reinterpret_cast<_Jv_JNIMethod *> (imeth);
-	  klass->methods[i].ncode = jnim->ncode ();
+	  // leave a placeholder in the itable for hidden init methods.
+          itable[pos] = NULL;	
 	}
-      else if (imeth != 0)		// it could be abstract
-	{
-	  _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth);
-	  _Jv_VerifyMethod (im);
-	  klass->methods[i].ncode = im->ncode ();
+      else if (meth)
+        {
+	  if ((meth->accflags & Modifier::STATIC) != 0)
+	    throw new java::lang::IncompatibleClassChangeError
+	      (_Jv_GetMethodString (klass, meth->name));
+	  if ((meth->accflags & Modifier::ABSTRACT) != 0)
+	    throw new java::lang::AbstractMethodError
+	      (_Jv_GetMethodString (klass, meth->name));
+	  if ((meth->accflags & Modifier::PUBLIC) == 0)
+	    throw new java::lang::IllegalAccessError
+	      (_Jv_GetMethodString (klass, meth->name));
 
-	  // Resolve ctable entries pointing to this method.  See
-	  // _Jv_Defer_Resolution.
-	  void **code = (void **)imeth->deferred;
-	  while (code)
-	    {
-	      void **target = (void **)*code;
-	      *code = klass->methods[i].ncode;
-	      code = target;
-	    }
+	  itable[pos] = meth->ncode;
+	}
+      else
+        {
+	  // The method doesn't exist in klass. Binary compatibility rules
+	  // permit this, so we delay the error until runtime using a pointer
+	  // to a method which throws an exception.
+	  itable[pos] = (void *) _Jv_ThrowNoSuchMethodError;
 	}
+      pos++;
     }
+    
+  return pos;
+}
+
+static _Jv_Mutex_t iindex_mutex;
+static bool iindex_mutex_initialized = false;
 
-  if ((klass->accflags & Modifier::INTERFACE))
+// We need to find the correct offset in the Class Interface Dispatch 
+// Table for a given interface. Once we have that, invoking an interface 
+// method just requires combining the Method's index in the interface 
+// (known at compile time) to get the correct method.  Doing a type test 
+// (cast or instanceof) is the same problem: Once we have a possible Partial 
+// Interface Dispatch Table, we just compare the first element to see if it 
+// matches the desired interface. So how can we find the correct offset?  
+// Our solution is to keep a vector of candiate offsets in each interface 
+// (idt->iface.ioffsets), and in each class we have an index 
+// (idt->cls.iindex) used to select the correct offset from ioffsets.
+//
+// Calculate and return iindex for a new class. 
+// ifaces is a vector of num interfaces that the class implements.
+// offsets[j] is the offset in the interface dispatch table for the
+// interface corresponding to ifaces[j].
+// May extend the interface ioffsets if required.
+jshort
+_Jv_Resolver::find_iindex (jclass *ifaces, jshort *offsets, jshort num)
+{
+  int i;
+  int j;
+  
+  // Acquire a global lock to prevent itable corruption in case of multiple 
+  // classes that implement an intersecting set of interfaces being linked
+  // simultaneously. We can assume that the mutex will be initialized
+  // single-threaded.
+  if (! iindex_mutex_initialized)
     {
-      klass->state = JV_STATE_PREPARED;
-      klass->notifyAll ();
-      return;
+      _Jv_MutexInit (&iindex_mutex);
+      iindex_mutex_initialized = true;
     }
+  
+  _Jv_MutexLock (&iindex_mutex);
+  
+  for (i=1;; i++)  /* each potential position in ioffsets */
+    {
+      for (j=0;; j++)  /* each iface */
+        {
+	  if (j >= num)
+	    goto found;
+	  if (i >= ifaces[j]->idt->iface.ioffsets[0])
+	    continue;
+	  int ioffset = ifaces[j]->idt->iface.ioffsets[i];
+	  /* We can potentially share this position with another class. */
+	  if (ioffset >= 0 && ioffset != offsets[j])
+	    break; /* Nope. Try next i. */	  
+	}
+    }
+  found:
+  for (j = 0; j < num; j++)
+    {
+      int len = ifaces[j]->idt->iface.ioffsets[0];
+      if (i >= len) 
+	{
+	  /* Resize ioffsets. */
+	  int newlen = 2 * len;
+	  if (i >= newlen)
+	    newlen = i + 3;
+	  jshort *old_ioffsets = ifaces[j]->idt->iface.ioffsets;
+	  // FIXME: _Jv_AllocBytes
+	  jshort *new_ioffsets = (jshort *) _Jv_Malloc (newlen
+							* sizeof(jshort));
+	  memcpy (&new_ioffsets[1], &old_ioffsets[1], len * sizeof (jshort));
+	  new_ioffsets[0] = newlen;
 
-  // A class might have so-called "Miranda methods".  This is a method
-  // that is declared in an interface and not re-declared in an
-  // abstract class.  Some compilers don't emit declarations for such
-  // methods in the class; this will give us problems since we expect
-  // a declaration for any method requiring a vtable entry.  We handle
-  // this here by searching for such methods and constructing new
-  // internal declarations for them.  We only need to do this for
-  // abstract classes.
-  if ((klass->accflags & Modifier::ABSTRACT))
-    _Jv_PrepareMissingMethods (klass, klass);
+	  while (len < newlen)
+	    new_ioffsets[len++] = -1;
+	  
+	  ifaces[j]->idt->iface.ioffsets = new_ioffsets;
+	}
+      ifaces[j]->idt->iface.ioffsets[i] = offsets[j];
+    }
 
-  klass->vtable_method_count = -1;
-  _Jv_MakeVTable (klass);
+  _Jv_MutexUnlock (&iindex_mutex);
 
-  /* wooha! we're done. */
-  klass->state = JV_STATE_PREPARED;
-  klass->notifyAll ();
+  return i;
 }
 
-/** 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 ();
+// Functions for indirect dispatch (symbolic virtual binding) support.
 
-  if (!_Jv_IsInterpretedClass (klass))
-    return;
+// There are three tables, atable otable and itable.  atable is an
+// array of addresses, and otable is an array of offsets, and these
+// are used for static and virtual members respectively.  itable is an
+// array of pairs {address, index} where each address is a pointer to
+// an interface.
 
-  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
+// {a,o,i}table_syms is an array of _Jv_MethodSymbols.  Each such
+// symbol is a tuple of {classname, member name, signature}.
 
-  _Jv_Field * field = (&klass->fields[0]) + index;
+// Set this to true to enable debugging of indirect dispatch tables/linking.
+static bool debug_link = false;
 
-  if (index > klass->field_count)
-    throw_internal_error ("field out of range");
+// _Jv_LinkSymbolTable() scans these two arrays and fills in the
+// corresponding atable and otable with the addresses of static
+// members and the offsets of virtual members.
 
-  int init = iclass->field_initializers[index];
-  if (init == 0)
-    return;
+// The offset (in bytes) for each resolved method or field is placed
+// at the corresponding position in the virtual method offset table
+// (klass->otable). 
 
-  _Jv_Constants *pool = &klass->constants;
-  int tag = pool->tags[init];
+// The same otable and atable may be shared by many classes.
 
-  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");
+// This must be called while holding the class lock.
 
-  void *addr = 0;
+void
+_Jv_Resolver::link_symbol_table (jclass klass)
+{
+  int index = 0;
+  _Jv_MethodSymbol sym;
+  if (klass->otable == NULL
+      || klass->otable->state != 0)
+    goto atable;
+   
+  klass->otable->state = 1;
+
+  if (debug_link)
+    fprintf (stderr, "Fixing up otable in %s:\n", klass->name->data);
+  for (index = 0;
+       (sym = klass->otable_syms[index]).class_name != NULL;
+       ++index)
+    {
+      jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
+      _Jv_Method *meth = NULL;            
 
-  if ((field->flags & Modifier::STATIC) != 0)
-    addr = (void*) field->u.addr;
-  else
-    addr = (void*) (((char*)obj) + field->u.boffset);
+      const _Jv_Utf8Const *signature = sym.signature;
 
-  switch (tag)
-    {
-    case JV_CONSTANT_String:
       {
-	_Jv_MonitorEnter (klass);
-	jstring str;
-	str = _Jv_NewStringUtf8Const (pool->data[init].utf8);
-	pool->data[init].string = str;
-	pool->tags[init] = JV_CONSTANT_ResolvedString;
-	_Jv_MonitorExit (klass);
+	static char *bounce = (char *)_Jv_ThrowNoSuchMethodError;
+	ptrdiff_t offset = (char *)(klass->vtable) - bounce;
+	klass->otable->offsets[index] = offset;
       }
-      /* fall through */
 
-    case JV_CONSTANT_ResolvedString:
-      if (! (field->type == &StringClass
- 	     || field->type == &java::lang::Class::class$))
-	throw_class_format_error ("string initialiser to non-string field");
+      if (target_class == NULL)
+	throw new java::lang::NoClassDefFoundError 
+	  (_Jv_NewStringUTF (sym.class_name->data));
+
+      // We're looking for a field or a method, and we can tell
+      // which is needed by looking at the signature.
+      if (signature->length >= 2
+	  && signature->data[0] == '(')
+	{
+	  // Looks like someone is trying to invoke an interface method
+	  if (target_class->isInterface())
+	    {
+	      using namespace java::lang;
+	      StringBuffer *sb = new StringBuffer();
+	      sb->append(JvNewStringLatin1("found interface "));
+	      sb->append(target_class->getName());
+	      sb->append(JvNewStringLatin1(" when searching for a class"));
+	      throw new VerifyError(sb->toString());
+	    }
+
+ 	  // If the target class does not have a vtable_method_count yet, 
+	  // then we can't tell the offsets for its methods, so we must lay 
+	  // it out now.
+	  wait_for_state(target_class, JV_STATE_PREPARED);
 
-      *(jstring*)addr = pool->data[init].string;
-      break;
+	  meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
+					  sym.signature);
+
+	  if (meth != NULL)
+	    {
+	      int offset = _Jv_VTable::idx_to_offset (meth->index);
+	      if (offset == -1)
+		JvFail ("Bad method index");
+	      JvAssert (meth->index < target_class->vtable_method_count);
+	      klass->otable->offsets[index] = offset;
+	    }
+	  if (debug_link)
+	    fprintf (stderr, "  offsets[%d] = %d (class %s@%p : %s(%s))\n",
+		     index,
+		     klass->otable->offsets[index],
+		     (const char*)target_class->name->data,
+		     target_class,
+		     (const char*)sym.name->data,
+		     (const char*)signature->data);
+	  continue;
+	}
 
-    case JV_CONSTANT_Integer:
+      // try fields
       {
-	int value = pool->data[init].i;
+	_Jv_Field *the_field = NULL;
+
+	for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
+	  {
+	    for (int i = 0; i < cls->field_count; i++)
+	      {
+		_Jv_Field *field = &cls->fields[i];
+		if (! _Jv_equalUtf8Consts (field->name, sym.name))
+		  continue;
+
+		// FIXME: What access checks should we perform here?
+// 		if (_Jv_CheckAccess (klass, cls, field->flags))
+// 		  {
+
+		wait_for_state(cls, JV_STATE_PREPARED);
+
+		if (!field->isResolved ())
+		  resolve_field (field, cls->loader);
+
+// 		if (field_type != 0 && field->type != field_type)
+// 		  throw new java::lang::LinkageError
+// 		    (JvNewStringLatin1 
+// 		     ("field type mismatch with different loaders"));
+
+		the_field = field;
+		if (debug_link)
+		  fprintf (stderr, "  offsets[%d] = %d (class %s@%p : %s)\n",
+			   index,
+			   field->u.boffset,
+			   (const char*)cls->name->data,
+			   cls,
+			   (const char*)field->name->data);
+		goto end_of_field_search;
+	      }
+	  }
+      end_of_field_search:
+	if (the_field != NULL)
+	  {
+	    if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
+	      throw new java::lang::IncompatibleClassChangeError;
+	    else
+	      klass->otable->offsets[index] = the_field->u.boffset;
+	  }
+	else
+	  {
+	    throw new java::lang::NoSuchFieldError
+	      (_Jv_NewStringUtf8Const (sym.name));
+	  }
+      }
+    }
+
+ atable:
+  if (klass->atable == NULL || klass->atable->state != 0)
+    goto itable;
+
+  klass->atable->state = 1;
+
+  for (index = 0;
+       (sym = klass->atable_syms[index]).class_name != NULL;
+       ++index)
+    {
+      jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
+      _Jv_Method *meth = NULL;            
+      const _Jv_Utf8Const *signature = sym.signature;
+
+      // ??? Setting this pointer to null will at least get us a
+      // NullPointerException
+      klass->atable->addresses[index] = NULL;
+      
+      if (target_class == NULL)
+	throw new java::lang::NoClassDefFoundError 
+	  (_Jv_NewStringUTF (sym.class_name->data));
+      
+      // We're looking for a static field or a static method, and we
+      // can tell which is needed by looking at the signature.
+      if (signature->length >= 2
+	  && signature->data[0] == '(')
+	{
+ 	  // If the target class does not have a vtable_method_count yet, 
+	  // then we can't tell the offsets for its methods, so we must lay 
+	  // it out now.
+	  wait_for_state (target_class, JV_STATE_PREPARED);
 
-	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;
+	  // Interface methods cannot have bodies.
+	  if (target_class->isInterface())
+	    {
+	      using namespace java::lang;
+	      StringBuffer *sb = new StringBuffer();
+	      sb->append(JvNewStringLatin1("class "));
+	      sb->append(target_class->getName());
+	      sb->append(JvNewStringLatin1(" is an interface: "
+					   "class expected"));
+	      throw new VerifyError(sb->toString());
+	    }
 
+	  meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
+					  sym.signature);
+
+	  if (meth != NULL)
+	    {
+	      if (meth->ncode) // Maybe abstract?
+		{
+		  klass->atable->addresses[index] = meth->ncode;
+		  if (debug_link)
+		    fprintf (stderr, "  addresses[%d] = %p (class %s@%p : %s(%s))\n",
+			     index,
+			     &klass->atable->addresses[index],
+			     (const char*)target_class->name->data,
+			     klass,
+			     (const char*)sym.name->data,
+			     (const char*)signature->data);
+		}
+#ifdef INTERPRETER
+	      else if (_Jv_IsInterpretedClass (target_class))
+		{
+		  _Jv_Defer_Resolution (target_class, meth, 
+					&klass->atable->addresses[index]);
+		  if (debug_link)
+		    fprintf (stderr, "  addresses[%d] = DEFERRED@%p (class %s@%p : %s(%s))\n",
+			     index,
+			     klass->atable->addresses[index],
+			     (const char*)target_class->name->data,
+			     klass,
+			     (const char*)sym.name->data,
+			     (const char*)signature->data);
+		
+		}
+#endif
+	    }
+	  else
+	    klass->atable->addresses[index] = (void *)_Jv_ThrowNoSuchMethodError;
+
+	  continue;
+	}
+
+      // try fields
+      {
+	_Jv_Field *the_field = NULL;
+
+	for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
+	  {
+	    for (int i = 0; i < cls->field_count; i++)
+	      {
+		_Jv_Field *field = &cls->fields[i];
+		if (! _Jv_equalUtf8Consts (field->name, sym.name))
+		  continue;
+
+		// FIXME: What access checks should we perform here?
+// 		if (_Jv_CheckAccess (klass, cls, field->flags))
+// 		  {
+
+		if (!field->isResolved ())
+		  resolve_field (field, cls->loader);
+
+		wait_for_state(target_class, JV_STATE_PREPARED);
+
+// 		if (field_type != 0 && field->type != field_type)
+// 		  throw new java::lang::LinkageError
+// 		    (JvNewStringLatin1 
+// 		     ("field type mismatch with different loaders"));
+
+		the_field = field;
+		goto end_of_static_field_search;
+	      }
+	  }
+      end_of_static_field_search:
+	if (the_field != NULL)
+	  {
+	    if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
+	      klass->atable->addresses[index] = the_field->u.addr;
+	    else
+	      throw new java::lang::IncompatibleClassChangeError;
+	  }
 	else
-	  throw_class_format_error ("erroneous field initializer");
-      }  
-      break;
+	  {
+	    throw new java::lang::NoSuchFieldError
+	      (_Jv_NewStringUtf8Const (sym.name));
+	  }
+      }
+    }
 
-    case JV_CONSTANT_Long:
-      if (field->type != JvPrimClass (long))
-	throw_class_format_error ("erroneous field initializer");
+ itable:
+  if (klass->itable == NULL
+      || klass->itable->state != 0)
+    return;
 
-      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
-      break;
+  klass->itable->state = 1;
 
-    case JV_CONSTANT_Float:
-      if (field->type != JvPrimClass (float))
-	throw_class_format_error ("erroneous field initializer");
+  for (index = 0;
+       (sym = klass->itable_syms[index]).class_name != NULL; 
+       ++index)
+    {
+      jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
+      const _Jv_Utf8Const *signature = sym.signature;
 
-      *(jfloat*)addr = pool->data[init].f;
-      break;
+      jclass cls;
+      int i;
 
-    case JV_CONSTANT_Double:
-      if (field->type != JvPrimClass (double))
-	throw_class_format_error ("erroneous field initializer");
+      bool found = _Jv_getInterfaceMethod (target_class, cls, i,
+					   sym.name, sym.signature);
 
-      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
-      break;
+      if (found)
+	{
+	  klass->itable->addresses[index * 2] = cls;
+	  klass->itable->addresses[index * 2 + 1] = (void *) i;
+	  if (debug_link)
+	    {
+	      fprintf (stderr, "  interfaces[%d] = %p (interface %s@%p : %s(%s))\n",
+		       index,
+		       klass->itable->addresses[index * 2],
+		       (const char*)cls->name->data,
+		       cls,
+		       (const char*)sym.name->data,
+		       (const char*)signature->data);
+	      fprintf (stderr, "            [%d] = offset %d\n",
+		       index + 1,
+		       (int)klass->itable->addresses[index * 2 + 1]);
+	    }
 
-    default:
-      throw_class_format_error ("erroneous field initializer");
+	}
+      else
+	throw new java::lang::IncompatibleClassChangeError;
     }
+
 }
 
-inline static unsigned char*
-skip_one_type (unsigned char* ptr)
+// For each catch_record in the list of caught classes, fill in the
+// address field.
+void 
+_Jv_Resolver::link_exception_table (jclass self)
 {
-  int ch = *ptr++;
-
-  while (ch == '[')
-    { 
-      ch = *ptr++;
-    }
-  
-  if (ch == 'L')
+  struct _Jv_CatchClass *catch_record = self->catch_classes;
+  if (!catch_record || catch_record->classname)
+    return;  
+  catch_record++;
+  while (catch_record->classname)
     {
-      do { ch = *ptr++; } while (ch != ';');
+      try
+	{
+	  jclass target_class
+	    = _Jv_FindClass (catch_record->classname,  
+			     self->getClassLoaderInternal ());
+	  *catch_record->address = target_class;
+	}
+      catch (::java::lang::Throwable *t)
+	{
+	  // FIXME: We need to do something better here.
+	  *catch_record->address = 0;
+	}
+      catch_record++;
     }
+  self->catch_classes->classname = (_Jv_Utf8Const *)-1;
+}
+  
+// This is put in empty vtable slots.
+static void
+_Jv_abstractMethodError (void)
+{
+  throw new java::lang::AbstractMethodError();
+}
+
+// Set itable method indexes for members of interface IFACE.
+void
+_Jv_Resolver::layout_interface_methods (jclass iface)
+{
+  if (! iface->isInterface())
+    return;
 
-  return ptr;
+  // itable indexes start at 1. 
+  // FIXME: Static initalizers currently get a NULL placeholder entry in the
+  // itable so they are also assigned an index here.
+  for (int i = 0; i < iface->method_count; i++)
+    iface->methods[i].index = i + 1;
 }
 
-static ffi_type*
-get_ffi_type_from_signature (unsigned char* ptr)
+// Prepare virtual method declarations in KLASS, and any superclasses
+// as required, by determining their vtable index, setting
+// method->index, and finally setting the class's vtable_method_count.
+// Must be called with the lock for KLASS held.
+void
+_Jv_Resolver::layout_vtable_methods (jclass klass)
 {
-  switch (*ptr) 
+  if (klass->vtable != NULL || klass->isInterface() 
+      || klass->vtable_method_count != -1)
+    return;
+
+  jclass superclass = klass->getSuperclass();
+
+  if (superclass != NULL && superclass->vtable_method_count == -1)
     {
-    case 'L':
-    case '[':
-      return &ffi_type_pointer;
-      break;
+      JvSynchronize sync (superclass);
+      layout_vtable_methods (superclass);
+    }
 
-    case 'Z':
-      // On some platforms a bool is a byte, on others an int.
-      if (sizeof (jboolean) == sizeof (jbyte))
-	return &ffi_type_sint8;
-      else
+  int index = (superclass == NULL ? 0 : superclass->vtable_method_count);
+
+  for (int i = 0; i < klass->method_count; ++i)
+    {
+      _Jv_Method *meth = &klass->methods[i];
+      _Jv_Method *super_meth = NULL;
+
+      if (! _Jv_isVirtualMethod (meth))
+	continue;
+
+      if (superclass != NULL)
 	{
-	  JvAssert (sizeof (jbyte) == sizeof (jint));
-	  return &ffi_type_sint32;
+	  jclass declarer;
+	  super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name,
+						 meth->signature, &declarer);
+	  // See if this method actually overrides the other method
+	  // we've found.
+	  if (super_meth)
+	    {
+	      if (! _Jv_isVirtualMethod (super_meth)
+		  || ! _Jv_CheckAccess (klass, declarer,
+					super_meth->accflags))
+		super_meth = NULL;
+	      else if ((super_meth->accflags
+			& java::lang::reflect::Modifier::FINAL) != 0)
+		{
+		  using namespace java::lang;
+		  StringBuffer *sb = new StringBuffer();
+		  sb->append(JvNewStringLatin1("method "));
+		  sb->append(_Jv_GetMethodString(klass, meth->name));
+		  sb->append(JvNewStringLatin1(" overrides final method "));
+		  sb->append(_Jv_GetMethodString(declarer, super_meth->name));
+		  throw new VerifyError(sb->toString());
+		}
+	    }
 	}
-      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;
+      if (super_meth)
+        meth->index = super_meth->index;
+      else
+	meth->index = index++;
     }
 
-  throw_internal_error ("unknown type in signature");
+  klass->vtable_method_count = index;
 }
 
-/* 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)
+// Set entries in VTABLE for virtual methods declared in KLASS. If
+// KLASS has an immediate abstract parent, recursively do its methods
+// first.  FLAGS is used to determine which slots we've actually set.
+void
+_Jv_Resolver::set_vtable_entries (jclass klass, _Jv_VTable *vtable,
+				  jboolean *flags)
 {
-  unsigned char *ptr = (unsigned char*) signature->data;
-  int arg_count = staticp ? 0 : 1;
+  using namespace java::lang::reflect;
 
-  /* first, count number of arguments */
+  jclass superclass = klass->getSuperclass();
 
-  // skip '('
-  ptr++;
+  if (superclass != NULL && (superclass->getModifiers() & Modifier::ABSTRACT))
+    set_vtable_entries (superclass, vtable, flags);
 
-  // count args
-  while (*ptr != ')')
+  for (int i = klass->method_count - 1; i >= 0; i--)
     {
-      ptr = skip_one_type (ptr);
-      arg_count += 1;
+      _Jv_Method *meth = &klass->methods[i];
+      if (meth->index == (_Jv_ushort) -1)
+	continue;
+      if ((meth->accflags & Modifier::ABSTRACT))
+	{
+	  vtable->set_method(meth->index, (void *) &_Jv_abstractMethodError);
+	  flags[meth->index] = false;
+	}
+      else
+	{
+	  vtable->set_method(meth->index, meth->ncode);
+	  flags[meth->index] = true;
+	}
     }
-
-  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)
+// Allocate and lay out the virtual method table for KLASS.  This will
+// also cause vtables to be generated for any non-abstract
+// superclasses, and virtual method layout to occur for any abstract
+// superclasses.  Must be called with monitor lock for KLASS held.
+void
+_Jv_Resolver::make_vtable (jclass klass)
 {
-  unsigned char *ptr = (unsigned char*) signature->data;
+  using namespace java::lang::reflect;  
+
+  // If the vtable exists, or for interface classes, do nothing.  All
+  // other classes, including abstract classes, need a vtable.
+  if (klass->vtable != NULL || klass->isInterface())
+    return;
 
-  int arg_index = 0;		// arg number
-  int item_count = 0;		// stack-item count
+  // Ensure all the `ncode' entries are set.
+  klass->engine->create_ncode(klass);
 
-  // setup receiver
-  if (!staticp)
+  // Class must be laid out before we can create a vtable. 
+  if (klass->vtable_method_count == -1)
+    layout_vtable_methods (klass);
+
+  // Allocate the new vtable.
+  _Jv_VTable *vtable = _Jv_VTable::new_vtable (klass->vtable_method_count);
+  klass->vtable = vtable;
+
+  jboolean flags[klass->vtable_method_count];
+  for (int i = 0; i < klass->vtable_method_count; ++i)
+    flags[i] = false;
+
+  // Copy the vtable of the closest superclass.
+  jclass superclass = klass->superclass;
+  {
+    JvSynchronize sync (superclass);
+    make_vtable (superclass);
+  }
+  for (int i = 0; i < superclass->vtable_method_count; ++i)
     {
-      arg_types[arg_index++] = &ffi_type_pointer;
-      item_count += 1;
+      vtable->set_method (i, superclass->vtable->get_method (i));
+      flags[i] = true;
     }
 
-  // skip '('
-  ptr++;
+  // Set the class pointer and GC descriptor.
+  vtable->clas = klass;
+  vtable->gc_descr = _Jv_BuildGCDescr (klass);
+
+  // For each virtual declared in klass and any immediate abstract 
+  // superclasses, set new vtable entry or override an old one.
+  set_vtable_entries (klass, vtable, flags);
 
-  // assign arg types
-  while (*ptr != ')')
+  // It is an error to have an abstract method in a concrete class.
+  if (! (klass->accflags & Modifier::ABSTRACT))
     {
-      arg_types[arg_index++] = get_ffi_type_from_signature (ptr);
+      for (int i = 0; i < klass->vtable_method_count; ++i)
+	if (! flags[i])
+	  {
+	    using namespace java::lang;
+	    while (klass != NULL)
+	      {
+		for (int j = 0; j < klass->method_count; ++j)
+		  {
+		    if (klass->methods[i].index == i)
+		      {
+			StringBuffer *buf = new StringBuffer ();
+			buf->append (_Jv_NewStringUtf8Const (klass->methods[i].name));
+			buf->append ((jchar) ' ');
+			buf->append (_Jv_NewStringUtf8Const (klass->methods[i].signature));
+			throw new AbstractMethodError (buf->toString ());
+		      }
+		  }
+		klass = klass->getSuperclass ();
+	      }
+	    // Couldn't find the name, which is weird.
+	    // But we still must throw the error.
+	    throw new AbstractMethodError ();
+	  }
+    }
+}
 
-      if (*ptr == 'J' || *ptr == 'D')
-	item_count += 2;
-      else
-	item_count += 1;
+// Lay out the class, allocating space for static fields and computing
+// offsets of instance fields.  The class lock must be held by the
+// caller.
+void
+_Jv_Resolver::ensure_fields_laid_out (jclass klass)
+{  
+  if (klass->size_in_bytes != -1)
+    return;
 
-      ptr = skip_one_type (ptr);
+  // Compute the alignment for this type by searching through the
+  // superclasses and finding the maximum required alignment.  We
+  // could consider caching this in the Class.
+  int max_align = __alignof__ (java::lang::Object);
+  jclass super = klass->getSuperclass();
+  while (super != NULL)
+    {
+      // Ensure that our super has its super installed before
+      // recursing.
+      wait_for_state(super, JV_STATE_LOADING);
+      ensure_fields_laid_out(super);
+      int num = JvNumInstanceFields (super);
+      _Jv_Field *field = JvGetFirstInstanceField (super);
+      while (num > 0)
+	{
+	  int field_align = get_alignment_from_class (field->type);
+	  if (field_align > max_align)
+	    max_align = field_align;
+	  ++field;
+	  --num;
+	}
+      super = super->getSuperclass();
     }
 
-  // skip ')'
-  ptr++;
-  ffi_type *rtype = get_ffi_type_from_signature (ptr);
+  int instance_size;
+  int static_size = 0;
+
+  // Although java.lang.Object is never interpreted, an interface can
+  // have a null superclass.  Note that we have to lay out an
+  // interface because it might have static fields.
+  if (klass->superclass)
+    instance_size = klass->superclass->size();
+  else
+    instance_size = java::lang::Object::class$.size();
 
-  ptr = skip_one_type (ptr);
-  if (ptr != (unsigned char*)signature->data + signature->length)
-    throw_internal_error ("did not find end of signature");
+  for (int i = 0; i < klass->field_count; i++)
+    {
+      int field_size;
+      int field_align;
 
-  if (ffi_prep_cif (cif, FFI_DEFAULT_ABI,
-		    arg_count, rtype, arg_types) != FFI_OK)
-    throw_internal_error ("ffi_prep_cif failed");
+      _Jv_Field *field = &klass->fields[i];
 
-  if (rtype_p != NULL)
-    *rtype_p = rtype;
+      if (! field->isRef ())
+	{
+	  // It is safe to resolve the field here, since it's a
+	  // primitive class, which does not cause loading to happen.
+	  resolve_field (field, klass->loader);
 
-  return item_count;
-}
+	  field_size = field->type->size ();
+	  field_align = get_alignment_from_class (field->type);
+	}
+      else 
+	{
+	  field_size = sizeof (jobject);
+	  field_align = __alignof__ (jobject);
+	}
 
-#if FFI_NATIVE_RAW_API
-#   define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure
-#   define FFI_RAW_SIZE ffi_raw_size
-#else
-#   define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure
-#   define FFI_RAW_SIZE ffi_java_raw_size
+#ifndef COMPACT_FIELDS
+      field->bsize = field_size;
 #endif
 
-/* we put this one here, and not in interpret.cc because it
- * calls the utility routines _Jv_count_arguments 
- * which are static to this module.  The following struct defines the
- * layout we use for the stubs, it's only used in the ncode method. */
-
-typedef struct {
-  ffi_raw_closure  closure;
-  ffi_cif   cif;
-  ffi_type *arg_types[0];
-} ncode_closure;
+      if ((field->flags & java::lang::reflect::Modifier::STATIC))
+	{
+	  if (field->u.addr == NULL)
+	    {
+	      // This computes an offset into a region we'll allocate
+	      // shortly, and then add this offset to the start
+	      // address.
+	      static_size       = ROUND (static_size, field_align);
+	      field->u.boffset   = static_size;
+	      static_size       += field_size;
+	    }
+	}
+      else
+	{
+	  instance_size      = ROUND (instance_size, field_align);
+	  field->u.boffset   = instance_size;
+	  instance_size     += field_size;
+	  if (field_align > max_align)
+	    max_align = field_align;
+	}
+    }
+
+  if (static_size != 0)
+    klass->engine->allocate_static_fields (klass, static_size);
 
-typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_raw*,void*);
+  // Set the instance size for the class.  Note that first we round it
+  // to the alignment required for this object; this keeps us in sync
+  // with our current ABI.
+  instance_size = ROUND (instance_size, max_align);
+  klass->size_in_bytes = instance_size;
+}
 
-void *
-_Jv_InterpMethod::ncode ()
+// This takes the class to state JV_STATE_LINKED.  The class lock must
+// be held when calling this.
+void
+_Jv_Resolver::ensure_class_linked (jclass klass)
 {
-  using namespace java::lang::reflect;
+  if (klass->state >= JV_STATE_LINKED)
+    return;
 
-  if (self->ncode != 0)
-    return self->ncode;
+  int state = klass->state;
+  try
+    {
+      // Short-circuit, so that mutually dependent classes are ok.
+      klass->state = JV_STATE_LINKED;
 
-  jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
-  int arg_count = _Jv_count_arguments (self->signature, staticp);
+      _Jv_Constants *pool = &klass->constants;
 
-  ncode_closure *closure =
-    (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure)
-					+ arg_count * sizeof (ffi_type*));
+      // Resolve class constants first, since other constant pool
+      // entries may rely on these.
+      for (int index = 1; index < pool->size; ++index)
+	{
+	  if (pool->tags[index] == JV_CONSTANT_Class)
+	    resolve_pool_entry (klass, index);
+	}
 
-  init_cif (self->signature,
-	    arg_count,
-	    staticp,
-	    &closure->cif,
-	    &closure->arg_types[0],
-	    NULL);
+#if 0  // Should be redundant now
+      // If superclass looks like a constant pool entry,
+      // resolve it now.
+      if ((uaddr) klass->superclass < (uaddr) pool->size)
+	klass->superclass = pool->data[(int) klass->superclass].clazz;
 
-  ffi_closure_fun fun;
+      // Likewise for interfaces.
+      for (int i = 0; i < klass->interface_count; i++)
+	{
+	  if ((uaddr) klass->interfaces[i] < (uaddr) pool->size)
+	    klass->interfaces[i]
+	      = pool->data[(int) klass->interfaces[i]].clazz;
+	}
+#endif
 
-  args_raw_size = FFI_RAW_SIZE (&closure->cif);
+      // Resolve the remaining constant pool entries.
+      for (int index = 1; index < pool->size; ++index)
+	{
+	  if (pool->tags[index] == JV_CONSTANT_String)
+	    {
+	      jstring str;
 
-  JvAssert ((self->accflags & Modifier::NATIVE) == 0);
+	      str = _Jv_NewStringUtf8Const (pool->data[index].utf8);
+	      pool->data[index].o = str;
+	      pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+	    }
+	}
 
-  if ((self->accflags & Modifier::SYNCHRONIZED) != 0)
-    {
-      if (staticp)
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_class;
-      else
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_synch_object; 
+      if (klass->engine->need_resolve_string_fields())
+	{
+	  jfieldID f = JvGetFirstStaticField (klass);
+	  for (int n = JvNumStaticFields (klass); n > 0; --n)
+	    {
+	      int mod = f->getModifiers ();
+	      // If we have a static String field with a non-null initial
+	      // value, we know it points to a Utf8Const.
+	      resolve_field(f, klass->loader);
+	      if (f->getClass () == &java::lang::String::class$
+		  && (mod & java::lang::reflect::Modifier::STATIC) != 0)
+		{
+		  jstring *strp = (jstring *) f->u.addr;
+		  if (*strp)
+		    *strp = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) *strp);
+		}
+	      f = f->getNextField ();
+	    }
+	}
+
+      klass->notifyAll ();
+
+      _Jv_PushClass (klass);
     }
-  else
+  catch (java::lang::Throwable *t)
     {
-      if (staticp)
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_class;
-      else
-	fun = (ffi_closure_fun)&_Jv_InterpMethod::run_normal;
+      klass->state = state;
+      throw t;
     }
+}
 
-  FFI_PREP_RAW_CLOSURE (&closure->closure,
-		        &closure->cif, 
-		        fun,
-		        (void*)this);
+// This ensures that symbolic superclass and superinterface references
+// are resolved for the indicated class.  This must be called with the
+// class lock held.
+void
+_Jv_Resolver::ensure_supers_installed (jclass klass)
+{
+  resolve_class_ref (klass, &klass->superclass);
+  // An interface won't have a superclass.
+  if (klass->superclass)
+    wait_for_state (klass->superclass, JV_STATE_LOADING);
 
-  self->ncode = (void*)closure;
-  return self->ncode;
+  for (int i = 0; i < klass->interface_count; ++i)
+    {
+      resolve_class_ref (klass, &klass->interfaces[i]);
+      wait_for_state (klass->interfaces[i], JV_STATE_LOADING);
+    }
 }
 
-void *
-_Jv_JNIMethod::ncode ()
+// This adds missing `Miranda methods' to a class.
+void
+_Jv_Resolver::add_miranda_methods (jclass base, jclass iface_class)
 {
-  using namespace java::lang::reflect;
+  // Note that at this point, all our supers, and the supers of all
+  // our superclasses and superinterfaces, will have been installed.
 
-  if (self->ncode != 0)
-    return self->ncode;
+  for (int i = 0; i < iface_class->interface_count; ++i)
+    {
+      jclass interface = iface_class->interfaces[i];
+
+      for (int j = 0; j < interface->method_count; ++j)
+	{
+ 	  _Jv_Method *meth = &interface->methods[j];
+	  // Don't bother with <clinit>.
+	  if (meth->name->data[0] == '<')
+	    continue;
+	  _Jv_Method *new_meth = _Jv_LookupDeclaredMethod (base, meth->name,
+							   meth->signature);
+	  if (! new_meth)
+	    {
+	      // We assume that such methods are very unlikely, so we
+	      // just reallocate the method array each time one is
+	      // found.  This greatly simplifies the searching --
+	      // otherwise we have to make sure that each such method
+	      // found is really unique among all superinterfaces.
+	      int new_count = base->method_count + 1;
+	      _Jv_Method *new_m
+		= (_Jv_Method *) _Jv_AllocBytes (sizeof (_Jv_Method)
+						 * new_count);
+	      memcpy (new_m, base->methods,
+		      sizeof (_Jv_Method) * base->method_count);
 
-  jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
-  int arg_count = _Jv_count_arguments (self->signature, staticp);
+	      // Add new method.
+	      new_m[base->method_count] = *meth;
+	      new_m[base->method_count].index = (_Jv_ushort) -1;
+	      new_m[base->method_count].accflags
+		|= java::lang::reflect::Modifier::INVISIBLE;
 
-  ncode_closure *closure =
-    (ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure)
-				    + arg_count * sizeof (ffi_type*));
-
-  ffi_type *rtype;
-  init_cif (self->signature,
-	    arg_count,
-	    staticp,
-	    &closure->cif,
-	    &closure->arg_types[0],
-	    &rtype);
-
-  ffi_closure_fun fun;
-
-  args_raw_size = FFI_RAW_SIZE (&closure->cif);
-
-  // Initialize the argument types and CIF that represent the actual
-  // underlying JNI function.
-  int extra_args = 1;
-  if ((self->accflags & Modifier::STATIC))
-    ++extra_args;
-  jni_arg_types = (ffi_type **) _Jv_Malloc ((extra_args + arg_count)
-					    * sizeof (ffi_type *));
-  int offset = 0;
-  jni_arg_types[offset++] = &ffi_type_pointer;
-  if ((self->accflags & Modifier::STATIC))
-    jni_arg_types[offset++] = &ffi_type_pointer;
-  memcpy (&jni_arg_types[offset], &closure->arg_types[0],
-	  arg_count * sizeof (ffi_type *));
-
-  if (ffi_prep_cif (&jni_cif, _Jv_platform_ffi_abi,
-		    extra_args + arg_count, rtype,
-		    jni_arg_types) != FFI_OK)
-    throw_internal_error ("ffi_prep_cif failed for JNI function");
-
-  JvAssert ((self->accflags & Modifier::NATIVE) != 0);
-
-  // FIXME: for now we assume that all native methods for
-  // interpreted code use JNI.
-  fun = (ffi_closure_fun) &_Jv_JNIMethod::call;
-
-  FFI_PREP_RAW_CLOSURE (&closure->closure,
-			&closure->cif, 
-			fun,
-			(void*) this);
-
-  self->ncode = (void *) closure;
-  return self->ncode;
-}
-
-
-/* A _Jv_ResolvedMethod is what is put in the constant pool for a
- * MethodRef or InterfacemethodRef.  */
-static _Jv_ResolvedMethod*
-_Jv_BuildResolvedMethod (_Jv_Method* method,
-			 jclass      klass,
-			 jboolean staticp,
-			 jint vtable_index)
-{
-  int arg_count = _Jv_count_arguments (method->signature, staticp);
-
-  _Jv_ResolvedMethod* result = (_Jv_ResolvedMethod*)
-    _Jv_AllocBytes (sizeof (_Jv_ResolvedMethod)
-		    + arg_count*sizeof (ffi_type*));
-
-  result->stack_item_count
-    = init_cif (method->signature,
-		arg_count,
-		staticp,
-		&result->cif,
-		&result->arg_types[0],
-		NULL);
-
-  result->vtable_index        = vtable_index;
-  result->method              = method;
-  result->klass               = klass;
+	      base->methods = new_m;
+	      base->method_count = new_count;
+	    }
+	}
 
-  return result;
+      add_miranda_methods (base, interface);
+    }
 }
 
-
-static void
-throw_class_format_error (jstring msg)
+// This ensures that the class' method table is "complete".  This must
+// be called with the class lock held.
+void
+_Jv_Resolver::ensure_method_table_complete (jclass klass)
 {
-  throw (msg
-	 ? new java::lang::ClassFormatError (msg)
-	 : new java::lang::ClassFormatError);
+  if (klass->vtable != NULL || klass->isInterface())
+    return;
+  // A class might have so-called "Miranda methods".  This is a method
+  // that is declared in an interface and not re-declared in an
+  // abstract class.  Some compilers don't emit declarations for such
+  // methods in the class; this will give us problems since we expect
+  // a declaration for any method requiring a vtable entry.  We handle
+  // this here by searching for such methods and constructing new
+  // internal declarations for them.  Note that we do this
+  // unconditionally, and not just for abstract classes, to correctly
+  // account for cases where a class is modified to be concrete and
+  // still incorrectly inherits an abstract method.
+  add_miranda_methods (klass, klass);
 }
 
-static void
-throw_class_format_error (char *msg)
+// Verify a class.  Must be called with class lock held.
+void
+_Jv_Resolver::verify_class (jclass klass)
 {
-  throw_class_format_error (JvNewStringLatin1 (msg));
+  klass->engine->verify(klass);
 }
 
-static void
-throw_internal_error (char *msg)
+// FIXME: mention invariants and stuff.
+void
+_Jv_Resolver::wait_for_state (jclass klass, int state)
 {
-  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
-}
+  if (klass->state >= state)
+    return;
+
+  JvSynchronize sync (klass);
 
+  // This is similar to the strategy for class initialization.  If we
+  // already hold the lock, just leave.
+  java::lang::Thread *self = java::lang::Thread::currentThread();
+  while (klass->state <= state
+	 && klass->thread 
+	 && klass->thread != self)
+    klass->wait ();
 
-#endif /* INTERPRETER */
+  java::lang::Thread *save = klass->thread;
+  klass->thread = self;
+
+  try
+    {
+      if (state >= JV_STATE_LOADING && klass->state < JV_STATE_LOADING)
+	{
+	  ensure_supers_installed (klass);
+	  klass->set_state(JV_STATE_LOADING);
+	}
+
+      if (state >= JV_STATE_LOADED && klass->state < JV_STATE_LOADED)
+	{
+	  ensure_method_table_complete (klass);
+	  klass->set_state(JV_STATE_LOADED);
+	}
+
+      if (state >= JV_STATE_PREPARED && klass->state < JV_STATE_PREPARED)
+	{
+	  ensure_fields_laid_out (klass);
+	  make_vtable (klass);
+	  layout_interface_methods (klass);
+	  prepare_constant_time_tables (klass);
+	  klass->set_state(JV_STATE_PREPARED);
+	}
+
+      if (state >= JV_STATE_LINKED && klass->state < JV_STATE_LINKED)
+	{
+	  ensure_class_linked (klass);
+	  link_exception_table (klass);
+	  link_symbol_table (klass);
+	  klass->set_state(JV_STATE_LINKED);
+	}
+    }
+  catch (java::lang::Throwable *exc)
+    {
+      klass->thread = save;
+      klass->set_state(JV_STATE_ERROR);
+      throw exc;
+    }
+
+  klass->thread = save;
+
+  if (klass->state == JV_STATE_ERROR)
+    throw new java::lang::LinkageError;
+}
Index: libjava/gnu/gcj/runtime/natSharedLibLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/runtime/natSharedLibLoader.cc,v
retrieving revision 1.5
diff -u -r1.5 natSharedLibLoader.cc
--- libjava/gnu/gcj/runtime/natSharedLibLoader.cc 28 Aug 2003 22:17:36 -0000 1.5
+++ libjava/gnu/gcj/runtime/natSharedLibLoader.cc 14 Sep 2004 20:02:21 -0000
@@ -1,6 +1,6 @@
 // natSharedLibLoader.cc - Implementation of SharedLibHelper native methods.
 
-/* Copyright (C) 2001, 2003  Free Software Foundation
+/* Copyright (C) 2001, 2003, 2004  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -12,6 +12,8 @@
 
 #include <gcj/cni.h>
 #include <jvm.h>
+#include <execution.h>
+
 #include <gnu/gcj/runtime/SharedLibHelper.h>
 #include <java/io/IOException.h>
 #include <java/lang/UnsupportedOperationException.h>
@@ -30,9 +32,10 @@
 void
 _Jv_sharedlib_register_hook (jclass cls)
 {
-  curHelper->registerClass(cls->getName(), cls);
   cls->protectionDomain = curHelper->domain;
   cls->loader = curLoader;
+  cls->engine = &_Jv_soleCompiledEngine;
+  curHelper->registerClass(cls->getName(), cls);
 }
 
 static void
Index: libjava/include/execution.h
===================================================================
RCS file: libjava/include/execution.h
diff -N libjava/include/execution.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libjava/include/execution.h 14 Sep 2004 20:02:22 -0000
@@ -0,0 +1,140 @@
+// execution.h - Execution engines. -*- c++ -*-
+
+/* Copyright (C) 2004  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.  */
+
+#ifndef __JAVA_EXECUTION_H__
+#define __JAVA_EXECUTION_H__
+
+// This represents one execution engine.  Note that we use function
+// pointers and not virtual methods to avoid calls to
+// __cxa_call_unexpected and the like.
+struct _Jv_ExecutionEngine
+{
+ public:
+
+  void (*unregister) (jclass);
+  // FIXME: probably should handle this elsewhere, see how
+  // interpreter does it.
+  bool (*need_resolve_string_fields) ();
+  void (*verify) (jclass);
+  void (*allocate_static_fields) (jclass, int);
+  void (*create_ncode) (jclass);
+  _Jv_ResolvedMethod *(*resolve_method) (_Jv_Method *, jclass,
+					 jboolean, jint);
+};
+
+// This handles all gcj-compiled code, including BC ABI.
+struct _Jv_CompiledEngine : public _Jv_ExecutionEngine
+{
+ public:
+
+  static void do_unregister (jclass)
+  {
+  }
+
+  static bool do_need_resolve_string_fields ()
+  {
+    return true;
+  }
+
+  static void do_verify (jclass klass)
+  {
+    if (klass->verify)
+      {
+	klass->verify(klass->getClassLoaderInternal());
+	klass->verify = NULL;
+      }
+  }
+
+  static _Jv_ResolvedMethod *do_resolve_method (_Jv_Method *, jclass,
+						jboolean, jint)
+  {
+    return NULL;
+  }
+
+  static void do_allocate_static_fields (jclass, int)
+  {
+    // Compiled classes don't need this.
+  }
+
+  static void do_create_ncode (jclass)
+  {
+    // Not needed.
+  }
+
+  _Jv_CompiledEngine ()
+  {
+    unregister = do_unregister;
+    need_resolve_string_fields = do_need_resolve_string_fields;
+    verify = do_verify;
+    allocate_static_fields = do_allocate_static_fields;
+    create_ncode = do_create_ncode;
+    resolve_method = do_resolve_method;
+  }
+
+  // These operators make it so we don't have to link in libstdc++.
+  void *operator new (size_t bytes)
+  {
+    return _Jv_Malloc(bytes);
+  }
+
+  void operator delete (void *mem)
+  {
+    _Jv_Free(mem);
+  }
+};
+
+// This handles interpreted code.
+class _Jv_InterpreterEngine : public _Jv_ExecutionEngine
+{
+ public:
+
+  static void do_verify (jclass);
+  static void do_allocate_static_fields (jclass, int);
+  static void do_create_ncode (jclass);
+  static _Jv_ResolvedMethod *do_resolve_method (_Jv_Method *, jclass,
+						jboolean, jint);
+
+  static bool do_need_resolve_string_fields ()
+  {
+    return false;
+  }
+
+  static void do_unregister(jclass klass)
+  {
+    _Jv_UnregisterClass(klass);
+  }
+
+  _Jv_InterpreterEngine ()
+  {
+    unregister = do_unregister;
+    need_resolve_string_fields = do_need_resolve_string_fields;
+    verify = do_verify;
+    allocate_static_fields = do_allocate_static_fields;
+    create_ncode = do_create_ncode;
+    resolve_method = do_resolve_method;
+  }
+
+  // These operators make it so we don't have to link in libstdc++.
+  void *operator new (size_t bytes)
+  {
+    return _Jv_Malloc(bytes);
+  }
+
+  void operator delete (void *mem)
+  {
+    _Jv_Free(mem);
+  }
+};
+
+
+extern _Jv_InterpreterEngine _Jv_soleInterpreterEngine;
+extern _Jv_CompiledEngine _Jv_soleCompiledEngine;
+
+#endif // __JAVA_EXECUTION_H__
Index: libjava/include/java-interp.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/java-interp.h,v
retrieving revision 1.23.16.1
diff -u -r1.23.16.1 java-interp.h
--- libjava/include/java-interp.h 20 Apr 2004 21:59:39 -0000 1.23.16.1
+++ libjava/include/java-interp.h 14 Sep 2004 20:02:22 -0000
@@ -1,6 +1,6 @@
 // java-interp.h - Header file for the bytecode interpreter.  -*- c++ -*-
 
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -91,7 +91,7 @@
   void *deferred;
 
   friend void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **);
-  friend void _Jv_PrepareClass(jclass);
+  friend class _Jv_InterpreterEngine;
 
 public:
   _Jv_Method *get_method ()
@@ -149,10 +149,9 @@
   friend class _Jv_BytecodeVerifier;
   friend class gnu::gcj::runtime::NameFinder;
   friend class gnu::gcj::runtime::StackTrace;
+  friend class _Jv_InterpreterEngine;
   
 
-  friend void _Jv_PrepareClass(jclass);
-
 #ifdef JV_MARKOBJ_DECL
   friend JV_MARKOBJ_DECL;
 #endif
@@ -165,7 +164,7 @@
 
   friend class _Jv_ClassReader;
   friend class _Jv_InterpMethod;
-  friend void  _Jv_PrepareClass(jclass);
+  friend class _Jv_InterpreterEngine;
   friend void  _Jv_PrepareMissingMethods (jclass base2, jclass iface_class);
   friend void  _Jv_InitField (jobject, jclass, int);
 #ifdef JV_MARKOBJ_DECL
@@ -239,7 +238,7 @@
   void *ncode ();
 
   friend class _Jv_ClassReader;
-  friend void _Jv_PrepareClass(jclass);
+  friend class _Jv_InterpreterEngine;
 
 public:
   // FIXME: this is ugly.
Index: libjava/include/jvm.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/jvm.h,v
retrieving revision 1.63.6.4
diff -u -r1.63.6.4 jvm.h
--- libjava/include/jvm.h 1 Sep 2004 21:52:44 -0000 1.63.6.4
+++ libjava/include/jvm.h 14 Sep 2004 20:02:22 -0000
@@ -240,6 +240,38 @@
   extern bool runtimeInitialized;
 }
 
+// This class handles all aspects of class preparation and linking.
+class _Jv_Resolver
+{
+private:
+  static void prepare_constant_time_tables(jclass);
+  static jshort get_interfaces(jclass, _Jv_ifaces *);
+  static void link_symbol_table(jclass);
+  static void link_exception_table(jclass);
+  static void layout_interface_methods(jclass);
+  static void layout_vtable_methods(jclass);
+  static void set_vtable_entries(jclass, _Jv_VTable *, jboolean *);
+  static void make_vtable(jclass);
+  static void ensure_fields_laid_out(jclass);
+  static void ensure_class_linked(jclass);
+  static void ensure_supers_installed(jclass);
+  static void add_miranda_methods(jclass, jclass);
+  static void ensure_method_table_complete(jclass);
+  static void verify_class(jclass);
+  static jshort find_iindex(jclass *, jshort *, jshort);
+  static jshort indexof(void *, void **, jshort);
+  static int get_alignment_from_class(jclass);
+  static void generate_itable(jclass, _Jv_ifaces *, jshort *);
+  static jshort append_partial_itable(jclass, jclass, void **, jshort);
+
+public:
+
+  static void resolve_class_ref (jclass, jclass *);
+  static void wait_for_state(jclass, int);
+  static _Jv_word resolve_pool_entry (jclass, int);
+  static void resolve_field (_Jv_Field *, java::lang::ClassLoader *);
+};
+
 /* Type of pointer used as finalizer.  */
 typedef void _Jv_FinalizerFunc (jobject);
 
@@ -407,7 +439,6 @@
 extern "C" void _Jv_RegisterClasses (jclass *classes);
 extern "C" void _Jv_RegisterResource (void *vptr);
 extern void _Jv_UnregisterClass (_Jv_Utf8Const*, java::lang::ClassLoader*);
-extern void _Jv_ResolveField (_Jv_Field *, java::lang::ClassLoader*);
 
 extern jclass _Jv_FindClass (_Jv_Utf8Const *name,
 			     java::lang::ClassLoader *loader);
@@ -420,8 +451,6 @@
 
 extern jboolean _Jv_CheckAccess (jclass self_klass, jclass other_klass,
 				 jint flags);
-extern jboolean _Jv_CheckAccessNoInit (jclass self_klass, jclass other_klass,
-				       jint flags);
 
 extern jobject _Jv_CallAnyMethodA (jobject obj, jclass return_type,
 				   jmethodID meth, jboolean is_constructor,
@@ -515,14 +544,4 @@
 extern void (*_Jv_JVMPI_Notify_THREAD_END) (JVMPI_Event *event);
 #endif
 
-
-// This returns true if and only if the class in question was compiled
-// using the binary compatibility flag.
-inline bool
-_Jv_isBinaryCompatible (jclass k)
-{
-  // FIXME: ugly implementation.
-  return k->size_in_bytes == -1;
-}
-
 #endif /* __JAVA_JVM_H__ */
Index: libjava/java/lang/Class.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Class.h,v
retrieving revision 1.63.12.10
diff -u -r1.63.12.10 Class.h
--- libjava/java/lang/Class.h 10 Sep 2004 17:15:19 -0000 1.63.12.10
+++ libjava/java/lang/Class.h 14 Sep 2004 20:02:22 -0000
@@ -40,13 +40,13 @@
   JV_STATE_PRELOADING = 1,	// Can do _Jv_FindClass.
   JV_STATE_LOADING = 3,		// Has super installed.
   JV_STATE_LOADED = 5,		// Is complete.
-    
+
   JV_STATE_COMPILED = 6,	// This was a compiled class.
 
   JV_STATE_PREPARED = 7,	// Layout & static init done.
   JV_STATE_LINKED = 9,		// Strings interned.
 
-  JV_STATE_IN_PROGRESS = 10,	// <Clinit> running.
+  JV_STATE_IN_PROGRESS = 10,	// <clinit> running.
 
   JV_STATE_ERROR = 12,
 
@@ -57,6 +57,9 @@
 struct _Jv_VTable;
 union _Jv_word;
 struct _Jv_ArrayVTable;
+class _Jv_ExecutionEngine;
+class _Jv_CompiledEngine;
+class _Jv_InterpreterEngine;
 
 struct _Jv_Constants
 {
@@ -208,15 +211,11 @@
 
   inline jclass getSuperclass (void)
   {
-    if (state < JV_STATE_LINKED)
-      _Jv_ResolveClassRef (this, &superclass);
     return superclass;
   }
 
   inline jclass getInterface (jint n)
   {
-    if (state < JV_STATE_LINKED)
-      _Jv_ResolveClassRef (this, &interfaces[n]);
     return interfaces[n];
   }
 
@@ -251,14 +250,9 @@
 
   // FIXME: this probably shouldn't be public.
   jint size (void)
-    {
-      // FIXME: ugly implementation.
-      // FIXME: can't use _Jv_isBinaryCompatible here.
-      if (size_in_bytes == -1)
-	_Jv_LayoutClass(this);
-
-      return size_in_bytes;
-    }
+  {
+    return size_in_bytes;
+  }
 
   // The index of the first method we declare ourself (as opposed to
   // inheriting).
@@ -284,6 +278,20 @@
 
   static jstring getPackagePortion (jstring);
 
+  inline friend void 
+  _Jv_InitClass (jclass klass)
+  {
+    if (__builtin_expect (klass->state == JV_STATE_DONE, true))
+      return;
+    klass->initializeClass ();  
+  }
+
+  void set_state (jint nstate)
+  {
+    state = nstate;
+    notifyAll ();
+  }
+
   // Friend functions implemented in natClass.cc.
   friend _Jv_Method *_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
 					 _Jv_Utf8Const *signature);
@@ -293,18 +301,6 @@
 					     int method_idx);
   friend jboolean _Jv_IsAssignableFromSlow(jclass, jclass);
 
-  friend void _Jv_ResolveClassRef (jclass, jclass *);
-
-  inline friend void 
-  _Jv_InitClass (jclass klass)
-  {
-    if (__builtin_expect (klass->state == JV_STATE_DONE, true))
-      return;
-    klass->initializeClass ();  
-  }
-  
-  friend int _Jv_LayoutClass(jclass);
-
   friend _Jv_Method* _Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *, 
 					       _Jv_Utf8Const*,
 					       jclass * = 0);
@@ -337,7 +333,6 @@
   friend class java::io::ObjectInputStream;
   friend class java::io::ObjectStreamClass;
 
-  friend void _Jv_WaitForState (jclass, int);
   friend void _Jv_RegisterClasses (jclass *classes);
   friend void _Jv_RegisterClassHookDefault (jclass klass);
   friend void _Jv_RegisterInitiatingLoader (jclass,java::lang::ClassLoader*);
@@ -359,7 +354,6 @@
   friend void _Jv_InitPrimClass (jclass, char *, char, int, _Jv_ArrayVTable *);
 
   friend void _Jv_PrepareCompiledClass (jclass);
-  friend void _Jv_PrepareConstantTimeTables (jclass);
   friend jshort _Jv_GetInterfaces (jclass, _Jv_ifaces *);
   friend void _Jv_GenerateITable (jclass, _Jv_ifaces *, jshort *);
   friend jstring _Jv_GetMethodString(jclass, _Jv_Utf8Const *);
@@ -367,19 +361,16 @@
   friend jshort _Jv_FindIIndex (jclass *, jshort *, jshort);
   friend void _Jv_LinkSymbolTable (jclass);
   friend void _Jv_LayoutInterfaceMethods (jclass);
-  friend void _Jv_LayoutVTableMethods (jclass klass);
   friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
   friend void _Jv_MakeVTable (jclass);
   friend void _Jv_linkExceptionClassTable (jclass);
 
   friend jboolean _Jv_CheckAccess (jclass self_klass, jclass other_klass,
 				   jint flags);
-  friend jboolean _Jv_CheckAccessNoInit (jclass self_klass, jclass other_klass,
-					 jint flags);
   
-  friend bool _Jv_isBinaryCompatible (jclass);
   friend bool _Jv_getInterfaceMethod(jclass, jclass&, int&, 
-				     const _Jv_Utf8Const*, const _Jv_Utf8Const*);
+				     const _Jv_Utf8Const*,
+				     const _Jv_Utf8Const*);
 
   // Return array class corresponding to element type KLASS, creating it if
   // necessary.
@@ -396,14 +387,11 @@
 
 #ifdef INTERPRETER
   friend jboolean _Jv_IsInterpretedClass (jclass);
-  friend void _Jv_InitField (jobject, jclass, _Jv_Field*);
   friend void _Jv_InitField (jobject, jclass, int);
-  friend _Jv_word _Jv_ResolvePoolEntry (jclass, int);
   friend _Jv_Method *_Jv_SearchMethodInClass (jclass cls, jclass klass, 
                         		      _Jv_Utf8Const *method_name, 
 					      _Jv_Utf8Const *method_signature);
 
-  friend void _Jv_PrepareClass (jclass);
   friend void _Jv_PrepareMissingMethods (jclass base, jclass iface_class);
 
   friend void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **);
@@ -421,6 +409,11 @@
   friend class gnu::gcj::runtime::StackTrace;
   friend class java::io::VMObjectStreamClass;
 
+  friend class _Jv_Resolver;
+  friend class _Jv_ExecutionEngine;
+  friend class _Jv_CompiledEngine;
+  friend class _Jv_InterpreterEngine;
+
   friend void _Jv_sharedlib_register_hook (jclass klass);
 
   // Chain for class pool.
@@ -483,10 +476,8 @@
   jclass arrayclass;
   // Security Domain to which this class belongs (or null).
   java::security::ProtectionDomain *protectionDomain;
-public:
   // Pointer to verify method for this class.
   void (*verify)(java::lang::ClassLoader *loader);
-private:
   // Signers of this class (or null).
   JArray<jobject> *hack_signers;
   // Used by Jv_PopClass and _Jv_PushClass to communicate with StackTrace.
@@ -494,6 +485,8 @@
   // Additional data, specific to the generator (JIT, native,
   // interpreter) of this class.
   void *aux_info;
+  // Execution engine.
+  _Jv_ExecutionEngine *engine;
 };
 
 #endif /* __JAVA_LANG_CLASS_H__ */
Index: libjava/java/lang/VMClassLoader.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/VMClassLoader.java,v
retrieving revision 1.10
diff -u -r1.10 VMClassLoader.java
--- libjava/java/lang/VMClassLoader.java 23 Jan 2004 15:29:38 -0000 1.10
+++ libjava/java/lang/VMClassLoader.java 14 Sep 2004 20:02:23 -0000
@@ -97,44 +97,31 @@
 					ProtectionDomain pd)
     throws ClassFormatError;
 
-  static final native void linkClass0 (Class klass);
-  static final native void markClassErrorState0 (Class klass);
-
   /**
    * Helper to resolve all references to other classes from this class.
    *
    * @param c the class to resolve
    */
-  static final void resolveClass(Class clazz)
+  static final native void resolveClass(Class clazz);
+
+  static final void transformException(Class clazz, Throwable x)
   {
-    synchronized (clazz)
+    LinkageError e;
+    if (x instanceof LinkageError)
+      e = (LinkageError) x;
+    else if (x instanceof ClassNotFoundException)
       {
-	try
-	  {
-	    linkClass0 (clazz);
-	  }
-	catch (Throwable x)
-	  {
-	    markClassErrorState0 (clazz);
-
-	    LinkageError e;
-	    if (x instanceof LinkageError)
-	      e = (LinkageError) x;
-	    else if (x instanceof ClassNotFoundException)
-	      {
-		e = new NoClassDefFoundError("while resolving class: "
-					     + clazz.getName());
-		e.initCause (x);
-	      }
-	    else
-	      {
-		e = new LinkageError ("unexpected exception during linking: "
-				      + clazz.getName());
-		e.initCause (x);
-	      }
-	    throw e;
-	  }
+	e = new NoClassDefFoundError("while resolving class: "
+				     + clazz.getName());
+	e.initCause (x);
+      }
+    else
+      {
+	e = new LinkageError ("unexpected exception during linking: "
+			      + clazz.getName());
+	e.initCause (x);
       }
+    throw e;
   }
 
   /**
Index: libjava/java/lang/natClass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClass.cc,v
retrieving revision 1.75.2.14
diff -u -r1.75.2.14 natClass.cc
--- libjava/java/lang/natClass.cc 10 Sep 2004 17:15:19 -0000 1.75.2.14
+++ libjava/java/lang/natClass.cc 14 Sep 2004 20:02:24 -0000
@@ -62,75 +62,12 @@
 #include <java-cpool.h>
 #include <java-interp.h>
 #include <java-assert.h>
+#include <execution.h>
+
 
 
 using namespace gcj;
 
-template<typename T>
-struct aligner
-{
-  char c;
-  T field;
-};
-
-#define ALIGNOF(TYPE) (offsetof (aligner<TYPE>, field))
-
-// This returns the alignment of a type as it would appear in a
-// structure.  This can be different from the alignment of the type
-// itself.  For instance on x86 double is 8-aligned but struct{double}
-// is 4-aligned.
-static int
-get_alignment_from_class (jclass klass)
-{
-  if (klass == JvPrimClass (byte))
-    return ALIGNOF (jbyte);
-  else if (klass == JvPrimClass (short))
-    return ALIGNOF (jshort);
-  else if (klass == JvPrimClass (int)) 
-    return ALIGNOF (jint);
-  else if (klass == JvPrimClass (long))
-    return ALIGNOF (jlong);
-  else if (klass == JvPrimClass (boolean))
-    return ALIGNOF (jboolean);
-  else if (klass == JvPrimClass (char))
-    return ALIGNOF (jchar);
-  else if (klass == JvPrimClass (float))
-    return ALIGNOF (jfloat);
-  else if (klass == JvPrimClass (double))
-    return ALIGNOF (jdouble);
-  else
-    return ALIGNOF (jobject);
-}
-
-// This function is used to lazily locate superclasses and
-// superinterfaces.
-void
-_Jv_ResolveClassRef (jclass klass, jclass *classref)
-{
-  jclass ret = *classref;
-
-  typedef unsigned int uaddr __attribute__ ((mode (pointer)));
-
-  // If superclass looks like a constant pool entry, resolve it now.
-  if (ret && (uaddr) ret < (uaddr) klass->constants.size)
-    {
-      JvSynchronize sync (klass);
-      if (klass->state < JV_STATE_LINKED)
-	{
-	  _Jv_Utf8Const *name = klass->constants.data[(uaddr) *classref].utf8;
-	  ret = _Jv_FindClass (name, klass->loader);
-	  if (! ret)
-	    {
-	      jstring str = _Jv_NewStringUTF (name->data);
-	      throw new java::lang::NoClassDefFoundError (str);
-	    }
-	}
-      else
-	ret = klass->constants.data[(uaddr) classref].clazz;
-      *classref = ret;
-    }
-}
-
 jclass
 java::lang::Class::forName (jstring className, jboolean initialize,
                             java::lang::ClassLoader *loader)
@@ -773,10 +710,7 @@
 void
 java::lang::Class::finalize (void)
 {
-#ifdef INTERPRETER
-  JvAssert (_Jv_IsInterpretedClass (this));
-  _Jv_UnregisterClass (this);
-#endif
+  engine->unregister(this);
 }
 
 // This implements the initialization process for a class.  From Spec
@@ -784,68 +718,37 @@
 void
 java::lang::Class::initializeClass (void)
 {
-  // short-circuit to avoid needless locking.
+  // Short-circuit to avoid needless locking.
   if (state == JV_STATE_DONE)
     return;
-  
-  // Step 1.
-  _Jv_MonitorEnter (this);
-  
-  if (state < JV_STATE_LINKED)
-    {    
-#ifdef INTERPRETER
-      if (_Jv_IsInterpretedClass (this))
-	{
-	  // this can throw exceptions, so exit the monitor as a precaution.
-	  _Jv_MonitorExit (this);
-	  java::lang::VMClassLoader::resolveClass (this);
-	  _Jv_MonitorEnter (this);
-	}
-      else
-#endif
-        {
-	  _Jv_PrepareCompiledClass (this);
-	}
-    }
-
-  // Step 2.
-  java::lang::Thread *self = java::lang::Thread::currentThread();
-  // Note that `self' can be null at startup (at least this was the
-  // case with the old qthread system).  Hence this nasty trick.
-  self = (java::lang::Thread *) ((long) self | 1);
-  while (state == JV_STATE_IN_PROGRESS && thread && thread != self)
-    wait ();
-
-  // Steps 3 &  4.
-  if (state == JV_STATE_DONE)
-    {
-      _Jv_MonitorExit (this);
-      return;
-    }
-  if (state == JV_STATE_IN_PROGRESS)
-    {
-      _Jv_MonitorExit (this);
 
-      /* Initialization in progress.  The class is linked now,
-         so ensure internal tables are built.  */
-      _Jv_PrepareConstantTimeTables (this);
-      _Jv_MakeVTable(this);
-      _Jv_LinkSymbolTable(this);
+  // Step 1.  We introduce a new scope so we can synchronize more
+  // easily.
+  {
+    JvSynchronize sync (this);
+
+    if (state < JV_STATE_LINKED)
+      java::lang::VMClassLoader::resolveClass (this);
+
+    // Step 2.
+    java::lang::Thread *self = java::lang::Thread::currentThread();
+    self = (java::lang::Thread *) ((long) self | 1);
+    while (state == JV_STATE_IN_PROGRESS && thread && thread != self)
+      wait ();
 
+    // Steps 3 &  4.
+    if (state == JV_STATE_DONE || state == JV_STATE_IN_PROGRESS)
       return;
-    }
 
-  // Step 5.
-  if (state == JV_STATE_ERROR)
-    {
-      _Jv_MonitorExit (this);
+    // Step 5.
+    if (state == JV_STATE_ERROR)
       throw new java::lang::NoClassDefFoundError (getName());
-    }
 
-  // Step 6.
-  thread = self;
-  state = JV_STATE_IN_PROGRESS;
-  _Jv_MonitorExit (this);
+    // Step 6.
+    thread = self;
+    _Jv_Resolver::wait_for_state (this, JV_STATE_LINKED);
+    state = JV_STATE_IN_PROGRESS;
+  }
 
   // Step 7.
   if (! isInterface () && superclass)
@@ -857,31 +760,13 @@
       catch (java::lang::Throwable *except)
 	{
 	  // Caught an exception.
-	  _Jv_MonitorEnter (this);
+	  JvSynchronize sync (this);
 	  state = JV_STATE_ERROR;
 	  notifyAll ();
-	  _Jv_MonitorExit (this);
 	  throw except;
 	}
     }
 
-  if (isInterface ())
-    _Jv_LayoutInterfaceMethods (this);
-
-  _Jv_PrepareConstantTimeTables (this);
-  
-  // Assign storage to fields
-  if (_Jv_isBinaryCompatible (this))
-    _Jv_LayoutClass(this);
-
-  if (vtable == NULL)
-    _Jv_MakeVTable(this);
-
-  if (otable || atable || itable)
-    _Jv_LinkSymbolTable(this);
-
-  _Jv_linkExceptionClassTable (this);
-
   // Steps 8, 9, 10, 11.
   try
     {
@@ -903,17 +788,91 @@
 	      except = t;
 	    }
 	}
-      _Jv_MonitorEnter (this);
+
+      JvSynchronize sync (this);
       state = JV_STATE_ERROR;
       notifyAll ();
-      _Jv_MonitorExit (this);
       throw except;
     }
 
-  _Jv_MonitorEnter (this);
+  JvSynchronize sync (this);
   state = JV_STATE_DONE;
   notifyAll ();
-  _Jv_MonitorExit (this);
+}
+
+// Only used by serialization
+java::lang::reflect::Field *
+java::lang::Class::getPrivateField (jstring name)
+{
+  int hash = name->hashCode ();
+
+  java::lang::reflect::Field* rfield;
+  for (int i = 0;  i < field_count;  i++)
+    {
+      _Jv_Field *field = &fields[i];
+      if (! _Jv_equal (field->name, name, hash))
+	continue;
+      rfield = new java::lang::reflect::Field ();
+      rfield->offset = (char*) field - (char*) fields;
+      rfield->declaringClass = this;
+      rfield->name = name;
+      return rfield;
+    }
+  jclass superclass = getSuperclass();
+  if (superclass == NULL)
+    return NULL;
+  rfield = superclass->getPrivateField(name);
+  for (int i = 0; i < interface_count && rfield == NULL; ++i)
+    rfield = interfaces[i]->getPrivateField (name);
+  return rfield;
+}
+
+// Only used by serialization
+java::lang::reflect::Method *
+java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types)
+{
+  jstring partial_sig = getSignature (param_types, false);
+  jint p_len = partial_sig->length();
+  _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
+  for (Class *klass = this; klass; klass = klass->getSuperclass())
+    {
+      int i = klass->isPrimitive () ? 0 : klass->method_count;
+      while (--i >= 0)
+	{
+	  if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
+	      && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
+	    {
+	      // Found it.
+	      using namespace java::lang::reflect;
+
+	      Method *rmethod = new Method ();
+	      rmethod->offset = ((char *) (&klass->methods[i])
+				 - (char *) klass->methods);
+	      rmethod->declaringClass = klass;
+	      return rmethod;
+	    }
+	}
+    }
+  throw new java::lang::NoSuchMethodException (name);
+}
+
+// Private accessor method for Java code to retrieve the protection domain.
+java::security::ProtectionDomain *
+java::lang::Class::getProtectionDomain0 ()
+{
+  return protectionDomain;
+}
+
+JArray<jobject> *
+java::lang::Class::getSigners()
+{
+  return hack_signers;
+}
+
+void
+java::lang::Class::setSigners(JArray<jobject> *s)
+{
+  hack_signers = s;
 }
 
 
@@ -1172,7 +1131,6 @@
     }
 }
 
-
 jboolean
 _Jv_IsAssignableFromSlow (jclass target, jclass source)
 {
@@ -1181,7 +1139,7 @@
     {
       // If target is array, source must be as well.
       if (! source->isArray ())
-	return false;
+       return false;
       target = target->getComponentType ();
       source = source->getComponentType ();
     }
@@ -1193,21 +1151,21 @@
   do
     {
       if (source == target)
-	return true;
+       return true;
 
       if (target->isPrimitive () || source->isPrimitive ())
-	return false;
+       return false;
 
       if (target->isInterface ())
-	{
-	  for (int i = 0; i < source->interface_count; ++i)
-	    {
-	      // We use a recursive call because we also need to
-	      // check superinterfaces.
-	      if (_Jv_IsAssignableFromSlow (target, source->getInterface (i)))
-		return true;
-	    }
-	}
+       {
+         for (int i = 0; i < source->interface_count; ++i)
+           {
+             // We use a recursive call because we also need to
+             // check superinterfaces.
+             if (_Jv_IsAssignableFromSlow (target, source->getInterface (i)))
+               return true;
+           }
+       }
       source = source->getSuperclass ();
     }
   while (source != NULL);
@@ -1220,28 +1178,11 @@
 // Throws appropriate exception, usually VerifyError, on failure.
 void
 _Jv_CheckAssignment (java::lang::ClassLoader *loader,
-		     _Jv_Utf8Const *source_name,
-		     _Jv_Utf8Const *dest_name)
+                    _Jv_Utf8Const *source_name,
+                    _Jv_Utf8Const *dest_name)
 {
-  jclass source = NULL;
-  jclass dest = NULL;
-
-  try
-    {
-      source = _Jv_FindClassFromSignature (source_name->data, loader);
-      dest = _Jv_FindClassFromSignature (dest_name->data, loader);
-    }
-  catch (java::lang::ClassNotFoundException *e)
-    {
-    }
-
-  if (! source || ! dest)
-    {
-      throw new java::lang::NoClassDefFoundError 
-	(_Jv_NewStringUTF ((! source
-			    ? source_name->data 
-			    : dest_name->data)));
-    }
+  jclass source = _Jv_FindClassFromSignature (source_name->data, loader);
+  jclass dest = _Jv_FindClassFromSignature (dest_name->data, loader);
 
   if (! _Jv_IsAssignableFromSlow (dest, source))
     {
@@ -1254,441 +1195,12 @@
     }
 }
 
-#define INITIAL_IOFFSETS_LEN 4
-#define INITIAL_IFACES_LEN 4
-
-static _Jv_IDispatchTable null_idt = { {SHRT_MAX, 0, NULL} };
-
-// Generate tables for constant-time assignment testing and interface
-// method lookup. This implements the technique described by Per Bothner
-// <per@bothner.com> on the java-discuss mailing list on 1999-09-02:
-// http://gcc.gnu.org/ml/java/1999-q3/msg00377.html
-void 
-_Jv_PrepareConstantTimeTables (jclass klass)
-{  
-  if (klass->isPrimitive () || klass->isInterface ())
-    return;
-  
-  // Short-circuit in case we've been called already.
-  if ((klass->idt != NULL) || klass->depth != 0)
-    return;
-
-  // Calculate the class depth and ancestor table. The depth of a class 
-  // is how many "extends" it is removed from Object. Thus the depth of 
-  // java.lang.Object is 0, but the depth of java.io.FilterOutputStream 
-  // is 2. Depth is defined for all regular and array classes, but not 
-  // interfaces or primitive types.
-   
-  jclass klass0 = klass;
-  jboolean has_interfaces = 0;
-  while (klass0 != &java::lang::Object::class$)
-    {
-      has_interfaces += klass0->interface_count;
-      klass0 = klass0->superclass;
-      klass->depth++;
-    }
-
-  // We do class member testing in constant time by using a small table 
-  // of all the ancestor classes within each class. The first element is 
-  // a pointer to the current class, and the rest are pointers to the 
-  // classes ancestors, ordered from the current class down by decreasing 
-  // depth. We do not include java.lang.Object in the table of ancestors, 
-  // since it is redundant.
-	
-  klass->ancestors = (jclass *) _Jv_Malloc (klass->depth * sizeof (jclass));
-  klass0 = klass;
-  for (int index = 0; index < klass->depth; index++)
-    {
-      klass->ancestors[index] = klass0;
-      klass0 = klass0->superclass;
-    }
-    
-  if (java::lang::reflect::Modifier::isAbstract (klass->accflags))
-    return;
-  
-  // Optimization: If class implements no interfaces, use a common
-  // predefined interface table.
-  if (!has_interfaces)
-    {
-      klass->idt = &null_idt;
-      return;
-    }
-
-  klass->idt = 
-    (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable));
-    
-  _Jv_ifaces ifaces;
-
-  ifaces.count = 0;
-  ifaces.len = INITIAL_IFACES_LEN;
-  ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *));
-
-  int itable_size = _Jv_GetInterfaces (klass, &ifaces);
-
-  if (ifaces.count > 0)
-    {
-      klass->idt->cls.itable = 
-	(void **) _Jv_Malloc (itable_size * sizeof (void *));
-      klass->idt->cls.itable_length = itable_size;
-          
-      jshort *itable_offsets = 
-	(jshort *) _Jv_Malloc (ifaces.count * sizeof (jshort));
-
-      _Jv_GenerateITable (klass, &ifaces, itable_offsets);
-
-      jshort cls_iindex = 
-	_Jv_FindIIndex (ifaces.list, itable_offsets, ifaces.count);
-
-      for (int i=0; i < ifaces.count; i++)
-	{
-	  ifaces.list[i]->idt->iface.ioffsets[cls_iindex] =
-	    itable_offsets[i];
-	}
-
-      klass->idt->cls.iindex = cls_iindex;	    
-
-      _Jv_Free (ifaces.list);
-      _Jv_Free (itable_offsets);
-    }
-  else 
-    {
-      klass->idt->cls.iindex = SHRT_MAX;
-    }
-}
-
-// Return index of item in list, or -1 if item is not present.
-inline jshort
-_Jv_IndexOf (void *item, void **list, jshort list_len)
-{
-  for (int i=0; i < list_len; i++)
-    {
-      if (list[i] == item)
-        return i;
-    }
-  return -1;
-}
-
-// Find all unique interfaces directly or indirectly implemented by klass.
-// Returns the size of the interface dispatch table (itable) for klass, which 
-// is the number of unique interfaces plus the total number of methods that 
-// those interfaces declare. May extend ifaces if required.
-jshort
-_Jv_GetInterfaces (jclass klass, _Jv_ifaces *ifaces)
-{
-  jshort result = 0;
-  
-  for (int i=0; i < klass->interface_count; i++)
-    {
-      jclass iface = klass->interfaces[i];
-
-      /* Make sure interface is linked.  */
-      _Jv_WaitForState(iface, JV_STATE_LINKED);
-
-      if (_Jv_IndexOf (iface, (void **) ifaces->list, ifaces->count) == -1)
-        {
-	  if (ifaces->count + 1 >= ifaces->len)
-	    {
-	      /* Resize ifaces list */
-	      ifaces->len = ifaces->len * 2;
-	      ifaces->list = (jclass *) _Jv_Realloc (ifaces->list, 
-	                     ifaces->len * sizeof(jclass));
-	    }
-	  ifaces->list[ifaces->count] = iface;
-	  ifaces->count++;
-
-	  result += _Jv_GetInterfaces (klass->interfaces[i], ifaces);
-	}
-    }
-    
-  if (klass->isInterface())
-    {
-      result += klass->method_count + 1;
-    }
-  else
-    {
-      if (klass->superclass)
-        {
-	  result += _Jv_GetInterfaces (klass->superclass, ifaces);
-	}
-    }
-  return result;
-}
-
-// Fill out itable in klass, resolving method declarations in each ifaces.
-// itable_offsets is filled out with the position of each iface in itable,
-// such that itable[itable_offsets[n]] == ifaces.list[n].
-void
-_Jv_GenerateITable (jclass klass, _Jv_ifaces *ifaces, jshort *itable_offsets)
-{
-  void **itable = klass->idt->cls.itable;
-  jshort itable_pos = 0;
-
-  for (int i=0; i < ifaces->count; i++)
-    { 
-      jclass iface = ifaces->list[i];
-      itable_offsets[i] = itable_pos;
-      itable_pos = _Jv_AppendPartialITable (klass, iface, itable, itable_pos);
-      
-      /* Create interface dispatch table for iface */
-      if (iface->idt == NULL)
-	{
-	  iface->idt = 
-	    (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable));
-
-	  // The first element of ioffsets is its length (itself included).
-	  jshort *ioffsets = 
-	    (jshort *) _Jv_Malloc (INITIAL_IOFFSETS_LEN * sizeof (jshort));
-	  ioffsets[0] = INITIAL_IOFFSETS_LEN;
-	  for (int i=1; i < INITIAL_IOFFSETS_LEN; i++)
-	    ioffsets[i] = -1;
-
-	  iface->idt->iface.ioffsets = ioffsets;	    
-	}
-    }
-}
-
-// Format method name for use in error messages.
-jstring
-_Jv_GetMethodString (jclass klass, _Jv_Utf8Const *name)
-{
-  jstring r = JvNewStringUTF (klass->name->data);
-  r = r->concat (JvNewStringUTF ("."));
-  r = r->concat (JvNewStringUTF (name->data));
-  return r;
-}
-
-void 
-_Jv_ThrowNoSuchMethodError ()
-{
-  throw new java::lang::NoSuchMethodError;
-}
-
-// Each superinterface of a class (i.e. each interface that the class
-// directly or indirectly implements) has a corresponding "Partial
-// Interface Dispatch Table" whose size is (number of methods + 1) words.
-// The first word is a pointer to the interface (i.e. the java.lang.Class
-// instance for that interface).  The remaining words are pointers to the
-// actual methods that implement the methods declared in the interface,
-// in order of declaration.
-//
-// Append partial interface dispatch table for "iface" to "itable", at
-// position itable_pos.
-// Returns the offset at which the next partial ITable should be appended.
-jshort
-_Jv_AppendPartialITable (jclass klass, jclass iface, void **itable, 
-                         jshort pos)
-{
-  using namespace java::lang::reflect;
-
-  itable[pos++] = (void *) iface;
-  _Jv_Method *meth;
-  
-  for (int j=0; j < iface->method_count; j++)
-    {
-      meth = NULL;
-      for (jclass cl = klass; cl; cl = cl->getSuperclass())
-        {
-	  meth = _Jv_GetMethodLocal (cl, iface->methods[j].name,
-				     iface->methods[j].signature);
-		 
-	  if (meth)
-	    break;
-	}
-
-      if (meth && (meth->name->data[0] == '<'))
-	{
-	  // leave a placeholder in the itable for hidden init methods.
-          itable[pos] = NULL;	
-	}
-      else if (meth)
-        {
-	  if (Modifier::isStatic(meth->accflags))
-	    throw new java::lang::IncompatibleClassChangeError
-	      (_Jv_GetMethodString (klass, meth->name));
-	  if (Modifier::isAbstract(meth->accflags))
-	    throw new java::lang::AbstractMethodError
-	      (_Jv_GetMethodString (klass, meth->name));
-	  if (! Modifier::isPublic(meth->accflags))
-	    throw new java::lang::IllegalAccessError
-	      (_Jv_GetMethodString (klass, meth->name));
-
-	  itable[pos] = meth->ncode;
-	}
-      else
-        {
-	  // The method doesn't exist in klass. Binary compatibility rules
-	  // permit this, so we delay the error until runtime using a pointer
-	  // to a method which throws an exception.
-	  itable[pos] = (void *) _Jv_ThrowNoSuchMethodError;
-	}
-      pos++;
-    }
-    
-  return pos;
-}
-
-static _Jv_Mutex_t iindex_mutex;
-static bool iindex_mutex_initialized = false;
-
-// We need to find the correct offset in the Class Interface Dispatch 
-// Table for a given interface. Once we have that, invoking an interface 
-// method just requires combining the Method's index in the interface 
-// (known at compile time) to get the correct method.  Doing a type test 
-// (cast or instanceof) is the same problem: Once we have a possible Partial 
-// Interface Dispatch Table, we just compare the first element to see if it 
-// matches the desired interface. So how can we find the correct offset?  
-// Our solution is to keep a vector of candiate offsets in each interface 
-// (idt->iface.ioffsets), and in each class we have an index 
-// (idt->cls.iindex) used to select the correct offset from ioffsets.
-//
-// Calculate and return iindex for a new class. 
-// ifaces is a vector of num interfaces that the class implements.
-// offsets[j] is the offset in the interface dispatch table for the
-// interface corresponding to ifaces[j].
-// May extend the interface ioffsets if required.
-jshort
-_Jv_FindIIndex (jclass *ifaces, jshort *offsets, jshort num)
-{
-  int i;
-  int j;
-  
-  // Acquire a global lock to prevent itable corruption in case of multiple 
-  // classes that implement an intersecting set of interfaces being linked
-  // simultaneously. We can assume that the mutex will be initialized
-  // single-threaded.
-  if (! iindex_mutex_initialized)
-    {
-      _Jv_MutexInit (&iindex_mutex);
-      iindex_mutex_initialized = true;
-    }
-  
-  _Jv_MutexLock (&iindex_mutex);
-  
-  for (i=1;; i++)  /* each potential position in ioffsets */
-    {
-      for (j=0;; j++)  /* each iface */
-        {
-	  if (j >= num)
-	    goto found;
-	  if (i >= ifaces[j]->idt->iface.ioffsets[0])
-	    continue;
-	  int ioffset = ifaces[j]->idt->iface.ioffsets[i];
-	  /* We can potentially share this position with another class. */
-	  if (ioffset >= 0 && ioffset != offsets[j])
-	    break; /* Nope. Try next i. */	  
-	}
-    }
-  found:
-  for (j = 0; j < num; j++)
-    {
-      int len = ifaces[j]->idt->iface.ioffsets[0];
-      if (i >= len) 
-	{
-	  /* Resize ioffsets. */
-	  int newlen = 2 * len;
-	  if (i >= newlen)
-	    newlen = i + 3;
-	  jshort *old_ioffsets = ifaces[j]->idt->iface.ioffsets;
-	  jshort *new_ioffsets = (jshort *) _Jv_Realloc (old_ioffsets, 
-	                                  newlen * sizeof(jshort));	  
-	  new_ioffsets[0] = newlen;
-
-	  while (len < newlen)
-	    new_ioffsets[len++] = -1;
-	  
-	  ifaces[j]->idt->iface.ioffsets = new_ioffsets;
-	}
-      ifaces[j]->idt->iface.ioffsets[i] = offsets[j];
-    }
-
-  _Jv_MutexUnlock (&iindex_mutex);
-
-  return i;
-}
-
-// Only used by serialization
-java::lang::reflect::Field *
-java::lang::Class::getPrivateField (jstring name)
-{
-  int hash = name->hashCode ();
-
-  java::lang::reflect::Field* rfield;
-  for (int i = 0;  i < field_count;  i++)
-    {
-      _Jv_Field *field = &fields[i];
-      if (! _Jv_equal (field->name, name, hash))
-	continue;
-      rfield = new java::lang::reflect::Field ();
-      rfield->offset = (char*) field - (char*) fields;
-      rfield->declaringClass = this;
-      rfield->name = name;
-      return rfield;
-    }
-  jclass superclass = getSuperclass();
-  if (superclass == NULL)
-    return NULL;
-  rfield = superclass->getPrivateField(name);
-  for (int i = 0; i < interface_count && rfield == NULL; ++i)
-    rfield = interfaces[i]->getPrivateField (name);
-  return rfield;
-}
-
-// Only used by serialization
-java::lang::reflect::Method *
-java::lang::Class::getPrivateMethod (jstring name, JArray<jclass> *param_types)
-{
-  jstring partial_sig = getSignature (param_types, false);
-  jint p_len = partial_sig->length();
-  _Jv_Utf8Const *utf_name = _Jv_makeUtf8Const (name);
-  for (Class *klass = this; klass; klass = klass->getSuperclass())
-    {
-      int i = klass->isPrimitive () ? 0 : klass->method_count;
-      while (--i >= 0)
-	{
-	  if (_Jv_equalUtf8Consts (klass->methods[i].name, utf_name)
-	      && _Jv_equaln (klass->methods[i].signature, partial_sig, p_len))
-	    {
-	      // Found it.
-	      using namespace java::lang::reflect;
-
-	      Method *rmethod = new Method ();
-	      rmethod->offset = ((char *) (&klass->methods[i])
-				 - (char *) klass->methods);
-	      rmethod->declaringClass = klass;
-	      return rmethod;
-	    }
-	}
-    }
-  throw new java::lang::NoSuchMethodException (name);
-}
-
-// Private accessor method for Java code to retrieve the protection domain.
-java::security::ProtectionDomain *
-java::lang::Class::getProtectionDomain0 ()
-{
-  return protectionDomain;
-}
-
-JArray<jobject> *
-java::lang::Class::getSigners()
-{
-  return hack_signers;
-}
-
-void
-java::lang::Class::setSigners(JArray<jobject> *s)
-{
-  hack_signers = s;
-}
-
-
 // Lookup an interface method by name.  This is very similar to
 // purpose to _getMethod, but the interfaces are quite different.  It
 // might be a good idea for _getMethod to call this function.
 //
 // Return true of the method is found, with the class in FOUND_CLASS
 // and the index in INDEX.
-
 bool
 _Jv_getInterfaceMethod (jclass search_class, jclass &found_class, int &index,
 		    const _Jv_Utf8Const *utf_name,  
@@ -1738,691 +1250,3 @@
 
   return false;
 }
-
-
-// Functions for indirect dispatch (symbolic virtual binding) support.
-
-// There are three tables, atable otable and itable.  atable is an
-// array of addresses, and otable is an array of offsets, and these
-// are used for static and virtual members respectively.  itable is an
-// array of pairs {address, index} where each address is a pointer to
-// an interface.
-
-// {a,o,i}table_syms is an array of _Jv_MethodSymbols.  Each such
-// symbol is a tuple of {classname, member name, signature}.
-
-
-// Set this to true to enable debugging of indirect dispatch tables/linking.
-static bool debug_link = false;
-
-
-// _Jv_LinkSymbolTable() scans these two arrays and fills in the
-// corresponding atable and otable with the addresses of static
-// members and the offsets of virtual members.
-
-// The offset (in bytes) for each resolved method or field is placed
-// at the corresponding position in the virtual method offset table
-// (klass->otable). 
-
-// The same otable and atable may be shared by many classes.
-
-void
-_Jv_LinkSymbolTable(jclass klass)
-{
-  //// FIXME: Need to lock the tables ////
-  
-  int index = 0;
-  _Jv_MethodSymbol sym;
-  if (klass->otable == NULL
-      || klass->otable->state != 0)
-    goto atable;
-   
-  klass->otable->state = 1;
-
-  if (debug_link)
-    fprintf (stderr, "Fixing up otable in %s:\n", klass->name->data);
-  for (index = 0; sym = klass->otable_syms[index], sym.class_name != NULL; 
-       index++)
-    {
-      jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
-      _Jv_Method *meth = NULL;            
-
-      const _Jv_Utf8Const *signature = sym.signature;
-
-      {
-	static char *bounce = (char *)_Jv_ThrowNoSuchMethodError;
-	ptrdiff_t offset = (char *)(klass->vtable) - bounce;
-	klass->otable->offsets[index] = offset;
-      }
-
-      if (target_class == NULL)
-	throw new java::lang::NoClassDefFoundError 
-	  (_Jv_NewStringUTF (sym.class_name->data));
-
-      // We're looking for a field or a method, and we can tell
-      // which is needed by looking at the signature.
-      if (signature->length >= 2
-	  && signature->data[0] == '(')
-	{
-	  // Looks like someone is trying to invoke an interface method
-	  if (target_class->isInterface())
-	    {
-	      using namespace java::lang;
-	      StringBuffer *sb = new StringBuffer();
-	      sb->append(JvNewStringLatin1("found interface "));
-	      sb->append(target_class->getName());
-	      sb->append(JvNewStringLatin1(" when searching for a class"));
-	      throw new VerifyError(sb->toString());
-	    }
-
- 	  // If the target class does not have a vtable_method_count yet, 
-	  // then we can't tell the offsets for its methods, so we must lay 
-	  // it out now.
-	  {
-	    JvSynchronize sync (target_class);
-	    _Jv_PrepareClass(target_class);
-	  }
-	  if (target_class->vtable_method_count == -1)
-	    {
-	      JvSynchronize sync (target_class);
-	      _Jv_LayoutVTableMethods (target_class);
-	    }
-	  
-	  meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
-					  sym.signature);
-	  
-	  if (meth != NULL)
-	    {
-	      int offset = _Jv_VTable::idx_to_offset (meth->index);
-	      if (offset == -1)
-		JvFail ("Bad method index");
-	      JvAssert (meth->index < target_class->vtable_method_count);
-	      klass->otable->offsets[index] = offset;
-	    }
-	  if (debug_link)
-	    fprintf (stderr, "  offsets[%d] = %d (class %s@%p : %s(%s))\n",
-		     index,
-		     klass->otable->offsets[index],
-		     (const char*)target_class->name->data,
-		     target_class,
-		     (const char*)sym.name->data,
-		     (const char*)signature->data);
-	  continue;
-	}
-
-      // try fields
-      {
-	_Jv_Field *the_field = NULL;
-
-	for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
-	  {
-	    for (int i = 0; i < cls->field_count; i++)
-	      {
-		_Jv_Field *field = &cls->fields[i];
-		if (! _Jv_equalUtf8Consts (field->name, sym.name))
-		  continue;
-
-		// FIXME: What access checks should we perform here?
-// 		if (_Jv_CheckAccess (klass, cls, field->flags))
-// 		  {
-
-		if (_Jv_isBinaryCompatible (cls))
-		  _Jv_LayoutClass(cls);
-
-		if (!field->isResolved ())
-		  _Jv_ResolveField (field, cls->loader);
-
-// 		if (field_type != 0 && field->type != field_type)
-// 		  throw new java::lang::LinkageError
-// 		    (JvNewStringLatin1 
-// 		     ("field type mismatch with different loaders"));
-
-		the_field = field;
-		if (debug_link)
-		  fprintf (stderr, "  offsets[%d] = %d (class %s@%p : %s)\n",
-			   index,
-			   field->u.boffset,
-			   (const char*)cls->name->data,
-			   cls,
-			   (const char*)field->name->data);
-		goto end_of_field_search;
-	      }
-	  }
-      end_of_field_search:
-	if (the_field != NULL)
-	  {
-	    if (the_field->flags & 0x0008 /* Modifier::STATIC */)
-	      {	      
-		throw new java::lang::IncompatibleClassChangeError;
-	      }
-	    else
-	      {
-		klass->otable->offsets[index] = the_field->u.boffset;
-	      }
-	  }
-	else
-	  {
-	    throw new java::lang::NoSuchFieldError
-	      (_Jv_NewStringUtf8Const (sym.name));
-	  }
-      }
-    }
-
- atable:
-  if (klass->atable == NULL
-      || klass->atable->state != 0)
-    goto itable;
-
-  klass->atable->state = 1;
-
-  for (index = 0; sym = klass->atable_syms[index], sym.class_name != NULL; 
-       index++)
-    {
-      jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
-      _Jv_Method *meth = NULL;            
-      const _Jv_Utf8Const *signature = sym.signature;
-
-      // ??? Setting this pointer to null will at least get us a
-      // NullPointerException
-      klass->atable->addresses[index] = NULL;
-      
-      if (target_class == NULL)
-	throw new java::lang::NoClassDefFoundError 
-	  (_Jv_NewStringUTF (sym.class_name->data));
-      
-      // We're looking for a static field or a static method, and we
-      // can tell which is needed by looking at the signature.
-      if (signature->length >= 2
-	  && signature->data[0] == '(')
-	{
- 	  // If the target class does not have a vtable_method_count yet, 
-	  // then we can't tell the offsets for its methods, so we must lay 
-	  // it out now.
-	  if (target_class->vtable_method_count == -1)
-	    {
-	      JvSynchronize sync (target_class);
-	      _Jv_LayoutVTableMethods (target_class);
-	    }
-	  
-	  // Interface methods cannot have bodies.
-	  if (target_class->isInterface())
-	    {
-	      using namespace java::lang;
-	      StringBuffer *sb = new StringBuffer();
-	      sb->append(JvNewStringLatin1("class "));
-	      sb->append(target_class->getName());
-	      sb->append(JvNewStringLatin1(" is an interface: class expected"));
-	      throw new VerifyError(sb->toString());
-	    }
-
-	  meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
-					  sym.signature);
-	  
-	  if (meth != NULL)
-	    {
-	      if (meth->ncode) // Maybe abstract?
-		{
-		  klass->atable->addresses[index] = meth->ncode;
-		  if (debug_link)
-		    fprintf (stderr, "  addresses[%d] = %p (class %s@%p : %s(%s))\n",
-			     index,
-			     &klass->atable->addresses[index],
-			     (const char*)target_class->name->data,
-			     klass,
-			     (const char*)sym.name->data,
-			     (const char*)signature->data);
-		}
-#ifdef INTERPRETER
-	      else if (_Jv_IsInterpretedClass (target_class))
-		{
-		  _Jv_Defer_Resolution (target_class, meth, 
-					&klass->atable->addresses[index]);
-		  if (debug_link)
-		    fprintf (stderr, "  addresses[%d] = DEFERRED@%p (class %s@%p : %s(%s))\n",
-			     index,
-			     klass->atable->addresses[index],
-			     (const char*)target_class->name->data,
-			     klass,
-			     (const char*)sym.name->data,
-			     (const char*)signature->data);
-		
-		}
-#endif
-	    }
-	  else
-	    klass->atable->addresses[index] = (void *)_Jv_ThrowNoSuchMethodError;
-
-	  continue;
-	}
-
-      // try fields
-      {
-	_Jv_Field *the_field = NULL;
-
-	for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
-	  {
-	    for (int i = 0; i < cls->field_count; i++)
-	      {
-		_Jv_Field *field = &cls->fields[i];
-		if (! _Jv_equalUtf8Consts (field->name, sym.name))
-		  continue;
-
-		// FIXME: What access checks should we perform here?
-// 		if (_Jv_CheckAccess (klass, cls, field->flags))
-// 		  {
-
-		if (_Jv_isBinaryCompatible (cls))
-		  {
-		    _Jv_LayoutClass(cls);
-		  }
-
-		if (!field->isResolved ())
-		  _Jv_ResolveField (field, cls->loader);
-
-		if (_Jv_IsInterpretedClass (target_class))
-		  {
-		    JvSynchronize sync (target_class);
-		    _Jv_PrepareClass(target_class);
-		  }
-
-// 		if (field_type != 0 && field->type != field_type)
-// 		  throw new java::lang::LinkageError
-// 		    (JvNewStringLatin1 
-		if (debug_link)
-		  fprintf (stderr, "  offsets[%d] = %d (class %s@%p : %s)\n",
-			   index,
-			   field->u.boffset,
-			   (const char*)cls->name->data,
-			   cls,
-			   (const char*)field->name->data);
-// 		     ("field type mismatch with different loaders"));
-
-		the_field = field;
-		goto end_of_static_field_search;
-	      }
-	  }
-      end_of_static_field_search:
-	if (the_field != NULL)
-	  {
-	    if (the_field->flags & 0x0008 /* Modifier::STATIC */)
-	      {	      
-		klass->atable->addresses[index] = the_field->u.addr;
-	      }
-	    else
-	      {
-		throw new java::lang::IncompatibleClassChangeError;
-	      }
-	  }
-	else
-	  {
-	    throw new java::lang::NoSuchFieldError
-	      (_Jv_NewStringUtf8Const (sym.name));
-	  }
-      }
-    }
-
- itable:
-  if (klass->itable == NULL
-      || klass->itable->state != 0)
-    return;
-
-  klass->itable->state = 1;
-
-  for (index = 0; sym = klass->itable_syms[index], sym.class_name != NULL; 
-       index++)
-    {
-      jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
-      const _Jv_Utf8Const *signature = sym.signature;
-
-      jclass cls;
-      int i;
-      
-      bool found 
-	= _Jv_getInterfaceMethod (target_class, cls, i, sym.name, sym.signature);
-      
-      if (found)
-	{
-	  klass->itable->addresses[index*2] = cls;
-	  klass->itable->addresses[index*2 + 1] = (void*)i;			  
-	  if (debug_link)
-	    {
-	      fprintf (stderr, "  interfaces[%d] = %p (interface %s@%p : %s(%s))\n",
-		       index,
-		       klass->itable->addresses[index*2],
-		       (const char*)cls->name->data,
-		       cls,
-		       (const char*)sym.name->data,
-		       (const char*)signature->data);
-	      fprintf (stderr, "            [%d] = offset %d\n",
-		       index + 1,
-		       (int)klass->itable->addresses[index*2 + 1]);
-	    }
-
-	}
-      else
-	throw new java::lang::IncompatibleClassChangeError;
-    }
-
-}
-
-
-// For each catch_record in the list of caught classes, fill in the
-// address field.
-void 
-_Jv_linkExceptionClassTable (jclass self)
-{
-  struct _Jv_CatchClass *catch_record = self->catch_classes;
-  if (!catch_record || catch_record->classname)
-    return;  
-  catch_record++;
-  while (catch_record->classname)
-    {
-      try
-	{
-	  jclass target_class = _Jv_FindClass (catch_record->classname,  
-					       self->getClassLoaderInternal ());
-	  *catch_record->address = target_class;
-	}
-      catch (::java::lang::Throwable *t)
-	{
-	  // FIXME: We need to do something better here.
-	  *catch_record->address = 0;
-	}
-      catch_record++;
-    }
-  self->catch_classes->classname = (_Jv_Utf8Const *)-1;
-}
-  
-// This is put in empty vtable slots.
-static void
-_Jv_abstractMethodError (void)
-{
-  throw new java::lang::AbstractMethodError();
-}
-
-// Set itable method indexes for members of interface IFACE.
-void
-_Jv_LayoutInterfaceMethods (jclass iface)
-{
-  if (! iface->isInterface())
-    return;
-  
-  // itable indexes start at 1. 
-  // FIXME: Static initalizers currently get a NULL placeholder entry in the
-  // itable so they are also assigned an index here.
-  for (int i = 0; i < iface->method_count; i++)
-    iface->methods[i].index = i + 1;
-}
-
-// Prepare virtual method declarations in KLASS, and any superclasses as 
-// required, by determining their vtable index, setting method->index, and
-// finally setting the class's vtable_method_count. Must be called with the
-// lock for KLASS held.
-void
-_Jv_LayoutVTableMethods (jclass klass)
-{
-  if (klass->vtable != NULL || klass->isInterface() 
-      || klass->vtable_method_count != -1)
-    return;
-
-  jclass superclass = klass->getSuperclass();
-
-  if (superclass != NULL && superclass->vtable_method_count == -1)
-    {
-      JvSynchronize sync (superclass);
-      _Jv_LayoutVTableMethods (superclass);
-    }
-
-  int index = (superclass == NULL ? 0 : superclass->vtable_method_count);
-
-  for (int i = 0; i < klass->method_count; ++i)
-    {
-      _Jv_Method *meth = &klass->methods[i];
-      _Jv_Method *super_meth = NULL;
-
-      if (! _Jv_isVirtualMethod (meth))
-	continue;
-
-      if (superclass != NULL)
-	{
-	  jclass declarer;
-	  super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name, 
-						 meth->signature, &declarer);
-	  // See if this method actually overrides the other method
-	  // we've found.
-	  if (super_meth)
-	    {
-	      if (! _Jv_isVirtualMethod (super_meth)
-		  || ! _Jv_CheckAccessNoInit (klass, declarer,
-					      super_meth->accflags))
-		super_meth = NULL;
-	      else if ((super_meth->accflags
-			& java::lang::reflect::Modifier::FINAL) != 0)
-		{
-		  using namespace java::lang;
-		  StringBuffer *sb = new StringBuffer();
-		  sb->append(JvNewStringLatin1("method "));
-		  sb->append(_Jv_GetMethodString(klass, meth->name));
-		  sb->append(JvNewStringLatin1(" overrides final method "));
-		  sb->append(_Jv_GetMethodString(declarer, super_meth->name));
-		  throw new VerifyError(sb->toString());
-		}
-	    }
-	}
-
-      if (super_meth && _Jv_isVirtualMethod (super_meth))
-        meth->index = super_meth->index;
-      else
-	meth->index = index++;
-    }
-
-  klass->vtable_method_count = index;
-}
-
-// Set entries in VTABLE for virtual methods declared in KLASS. If
-// KLASS has an immediate abstract parent, recursively do its methods
-// first.  FLAGS is used to determine which slots we've actually set.
-void
-_Jv_SetVTableEntries (jclass klass, _Jv_VTable *vtable, jboolean *flags)
-{
-  using namespace java::lang::reflect;
-
-  jclass superclass = klass->getSuperclass();
-
-  if (superclass != NULL && (superclass->getModifiers() & Modifier::ABSTRACT))
-    _Jv_SetVTableEntries (superclass, vtable, flags);
-
-  for (int i = klass->method_count - 1; i >= 0; i--)
-    {
-      _Jv_Method *meth = &klass->methods[i];
-      if (meth->index == (_Jv_ushort) -1)
-	continue;
-      if ((meth->accflags & Modifier::ABSTRACT))
-	{
-	  vtable->set_method(meth->index, (void *) &_Jv_abstractMethodError);
-	  flags[meth->index] = false;
-	}
-      else
-	{
-	  vtable->set_method(meth->index, meth->ncode);
-	  flags[meth->index] = true;
-	}
-    }
-}
-
-// Allocate and lay out the virtual method table for KLASS. This will also
-// cause vtables to be generated for any non-abstract superclasses, and
-// virtual method layout to occur for any abstract superclasses. Must be
-// called with monitor lock for KLASS held.
-void
-_Jv_MakeVTable (jclass klass)
-{
-  using namespace java::lang::reflect;  
-
-  if (klass->vtable != NULL || klass->isInterface() 
-      || (klass->accflags & Modifier::ABSTRACT))
-    return;
-
-  // Class must be laid out before we can create a vtable. 
-  if (klass->vtable_method_count == -1)
-    _Jv_LayoutVTableMethods (klass);
-
-  // Allocate the new vtable.
-  _Jv_VTable *vtable = _Jv_VTable::new_vtable (klass->vtable_method_count);
-  klass->vtable = vtable;
-
-  jboolean flags[klass->vtable_method_count];
-  for (int i = 0; i < klass->vtable_method_count; ++i)
-    flags[i] = false;
-
-  // Copy the vtable of the closest non-abstract superclass.
-  jclass superclass = klass->superclass;
-  if (superclass != NULL)
-    {
-      while ((superclass->accflags & Modifier::ABSTRACT) != 0)
-	superclass = superclass->superclass;
-
-      if (superclass->vtable == NULL)
-	{
-	  JvSynchronize sync (superclass);
-	  _Jv_MakeVTable (superclass);
-	}
-
-      for (int i = 0; i < superclass->vtable_method_count; ++i)
-	{
-	  vtable->set_method (i, superclass->vtable->get_method (i));
-	  flags[i] = true;
-	}
-    }
-
-  // Set the class pointer and GC descriptor.
-  vtable->clas = klass;
-  vtable->gc_descr = _Jv_BuildGCDescr (klass);
-
-  // For each virtual declared in klass and any immediate abstract 
-  // superclasses, set new vtable entry or override an old one.
-  _Jv_SetVTableEntries (klass, vtable, flags);
-
-  // It is an error to have an abstract method in a concrete class.
-  if (! (klass->accflags & Modifier::ABSTRACT))
-    {
-      for (int i = 0; i < klass->vtable_method_count; ++i)
-	if (! flags[i])
-	  {
-	    using namespace java::lang;
-	    while (klass != NULL)
-	      {
-		for (int j = 0; j < klass->method_count; ++j)
-		  {
-		    if (klass->methods[i].index == i)
-		      {
-			StringBuffer *buf = new StringBuffer ();
-			buf->append (_Jv_NewStringUtf8Const (klass->methods[i].name));
-			buf->append ((jchar) ' ');
-			buf->append (_Jv_NewStringUtf8Const (klass->methods[i].signature));
-			throw new AbstractMethodError (buf->toString ());
-		      }
-		  }
-		klass = klass->getSuperclass ();
-	      }
-	    // Couldn't find the name, which is weird.
-	    // But we still must throw the error.
-	    throw new AbstractMethodError ();
-	  }
-    }
-}
-
-// Lay out the class, returning the number of bytes needed for the
-// class' static variables.
-int
-_Jv_LayoutClass(jclass klass)
-{  
-  // Compute the alignment for this type by searching through the
-  // superclasses and finding the maximum required alignment.  We
-  // could consider caching this in the Class.
-  int max_align = __alignof__ (java::lang::Object);
-  jclass super = klass->getSuperclass();
-  while (super != NULL)
-    {
-      if (_Jv_isBinaryCompatible (super))
-	_Jv_LayoutClass(super);
-      int num = JvNumInstanceFields (super);
-      _Jv_Field *field = JvGetFirstInstanceField (super);
-      while (num > 0)
-	{
-	  int field_align = get_alignment_from_class (field->type);
-	  if (field_align > max_align)
-	    max_align = field_align;
-	  ++field;
-	  --num;
-	}
-      super = super->getSuperclass();
-    }
-
-  int instance_size;
-  int static_size = 0;
-
-  // Although java.lang.Object is never interpreted, an interface can
-  // have a null superclass.  Note that we have to lay out an
-  // interface because it might have static fields.
-  if (klass->superclass)
-    instance_size = klass->superclass->size();
-  else
-    instance_size = java::lang::Object::class$.size();
-
-  for (int i = 0; i < klass->field_count; i++)
-    {
-      int field_size;
-      int field_align;
-
-      _Jv_Field *field = &klass->fields[i];
-
-      if (! field->isRef ())
-	{
-	  // it's safe to resolve the field here, since it's 
-	  // a primitive class, which does not cause loading to happen.
-	  _Jv_ResolveField (field, klass->loader);
-
-	  field_size = field->type->size ();
-	  field_align = get_alignment_from_class (field->type);
-	}
-      else 
-	{
-	  field_size = sizeof (jobject);
-	  field_align = __alignof__ (jobject);
-	}
-
-#ifndef COMPACT_FIELDS
-      field->bsize = field_size;
-#endif
-
-      if (field->flags & java::lang::reflect::Modifier::STATIC)
-	{
-	  if (_Jv_IsInterpretedClass (klass))
-	    {
-	      // This computes an offset into a region we'll allocate
-	      // shortly, and then add this offset to the start
-	      // address.
-	      static_size       = ROUND (static_size, field_align);
-	      field->u.boffset   = static_size;
-	      static_size       += field_size;
-	    }
-	}
-      else
-	{
-	  instance_size      = ROUND (instance_size, field_align);
-	  field->u.boffset   = instance_size;
-	  instance_size     += field_size;
-	  if (field_align > max_align)
-	    max_align = field_align;
-	}
-    }
-
-  // Set the instance size for the class.  Note that first we round it
-  // to the alignment required for this object; this keeps us in sync
-  // with our current ABI.
-  instance_size = ROUND (instance_size, max_align);
-  klass->size_in_bytes = instance_size;
-
-  return static_size;
-}
Index: libjava/java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.64.8.8
diff -u -r1.64.8.8 natClassLoader.cc
--- libjava/java/lang/natClassLoader.cc 30 Aug 2004 15:45:25 -0000 1.64.8.8
+++ libjava/java/lang/natClassLoader.cc 14 Sep 2004 20:02:24 -0000
@@ -17,6 +17,7 @@
 
 #include <gcj/cni.h>
 #include <jvm.h>
+#include <execution.h>
 
 #include <java-threads.h>
 #include <java-interp.h>
@@ -41,161 +42,6 @@
 #include <java/io/Serializable.h>
 #include <java/lang/Cloneable.h>
 
-void
-_Jv_WaitForState (jclass klass, int state)
-{
-  if (klass->state >= state)
-    return;
-  
-  _Jv_MonitorEnter (klass) ;
-
-  if (state == JV_STATE_LINKED)
-    {
-      // Must call _Jv_PrepareCompiledClass while holding the class
-      // mutex.
-#ifdef INTERPRETER
-      if (_Jv_IsInterpretedClass (klass))
-	_Jv_PrepareClass (klass);
-      else
-#endif
-	// Assign storage to fields.
-	if (_Jv_isBinaryCompatible (klass))
-	  _Jv_LayoutClass(klass);
-      _Jv_PrepareCompiledClass (klass);
-      _Jv_MonitorExit (klass);
-      return;
-    }
-	
-  java::lang::Thread *self = java::lang::Thread::currentThread();
-
-  // this is similar to the strategy for class initialization.
-  // if we already hold the lock, just leave.
-  while (klass->state <= state
-	 && klass->thread 
-	 && klass->thread != self)
-    klass->wait ();
-
-  _Jv_MonitorExit (klass);
-
-  if (klass->state == JV_STATE_ERROR)
-    throw new java::lang::LinkageError;
-}
-
-typedef unsigned int uaddr __attribute__ ((mode (pointer)));
-
-/** This function does class-preparation for compiled classes.  
-    NOTE: It contains replicated functionality from
-    _Jv_ResolvePoolEntry, and this is intentional, since that function
-    lives in resolve.cc which is entirely conditionally compiled.
- */
-void
-_Jv_PrepareCompiledClass (jclass klass)
-{
-  if (klass->state >= JV_STATE_LINKED)
-    return;
-
-  // We don't need to do any locking here because the class mutex
-  // should be locked by whoever calls _Jv_PrepareCompiledClass.
-  if (klass->verify)
-    klass->verify (klass->getClassLoaderInternal ());
-  klass->verify = NULL;
-
-  int state = klass->state;
-  try
-    {
-      // Short-circuit, so that mutually dependent classes are ok.
-      klass->state = JV_STATE_LINKED;
-
-      _Jv_Constants *pool = &klass->constants;
-
-      // Resolve class constants first, since other constant pool
-      // entries may rely on these.
-      for (int index = 1; index < pool->size; ++index)
-	{
-	  if (pool->tags[index] == JV_CONSTANT_Class)
-	    {
-	      _Jv_Utf8Const *name = pool->data[index].utf8;
-	  
-	      jclass found;
-	      if (name->data[0] == '[')
-		found = _Jv_FindClassFromSignature (&name->data[0],
-						    klass->loader);
-	      else
-		found = _Jv_FindClass (name, klass->loader);
-		
-	      if (! found)
-		{
-		  jstring str = _Jv_NewStringUTF (name->data);
-		  throw new java::lang::NoClassDefFoundError (str);
-		}
-
-	      pool->data[index].clazz = found;
-	      pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
-	    }
-	}
-
-      // If superclass looks like a constant pool entry,
-      // resolve it now.
-      if ((uaddr) klass->superclass < (uaddr)pool->size)
-	{
-	  klass->superclass = pool->data[(int) klass->superclass].clazz;
-	}
-      // Likewise for interfaces.
-      for (int i = 0; i < klass->interface_count; i++)
-	if ((uaddr) klass->interfaces[i] < (uaddr)pool->size)
-	  klass->interfaces[i] = pool->data[(int) klass->interfaces[i]].clazz;
-
-      // Resolve the remaining constant pool entries.
-      for (int index = 1; index < pool->size; ++index)
-	{
-	  if (pool->tags[index] == JV_CONSTANT_String)
-	    {
-	      jstring str;
-
-	      str = _Jv_NewStringUtf8Const (pool->data[index].utf8);
-	      pool->data[index].o = str;
-	      pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
-	    }
-	}
-
-#ifdef INTERPRETER
-      // FIXME: although the comment up top says that this function is
-      // only called for compiled classes, it is actually called for every
-      // class.
-      if (! _Jv_IsInterpretedClass (klass))
-	{
-#endif /* INTERPRETER */
-	  jfieldID f = JvGetFirstStaticField (klass);
-	  for (int n = JvNumStaticFields (klass); n > 0; --n)
-	    {
-	      int mod = f->getModifiers ();
-	      // If we have a static String field with a non-null initial
-	      // value, we know it points to a Utf8Const.
-	      _Jv_ResolveField(f, klass->loader);
-	      if (f->getClass () == &java::lang::String::class$
-		  && java::lang::reflect::Modifier::isStatic (mod))
-		{
-		  jstring *strp = (jstring *) f->u.addr;
-		  if (*strp)
-		    *strp = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) *strp);
-		}
-	      f = f->getNextField ();
-	    }
-#ifdef INTERPRETER
-	}
-#endif /* INTERPRETER */
-
-      klass->notifyAll ();
-
-      _Jv_PushClass (klass);
-    }
-  catch (java::lang::Throwable *t)
-    {
-      klass->state = state;
-      throw t;
-    }
-}
-
 
 //
 //  A single class can have many "initiating" class loaders,
@@ -227,6 +73,8 @@
 static jclass loaded_classes[HASH_LEN];
 
 // This is the root of a linked list of classes
+static jclass stack_head;
+
 
 
 
@@ -329,11 +177,6 @@
       jclass klass = *classes;
 
       (*_Jv_RegisterClassHook) (klass);
-
-      // registering a compiled class causes
-      // it to be immediately "prepared".  
-      if (klass->state == JV_STATE_NOTHING)
-	klass->state = JV_STATE_COMPILED;
     }
 }
 
@@ -375,6 +218,9 @@
     }
 #endif
 
+  // FIXME: this is really bogus!
+  if (! klass->engine)
+    klass->engine = &_Jv_soleCompiledEngine;
   klass->next = loaded_classes[hash];
   loaded_classes[hash] = klass;
 }
@@ -435,7 +281,7 @@
     {
       // we need classes to be in the hash while
       // we're loading, so that they can refer to themselves. 
-      _Jv_WaitForState (klass, JV_STATE_LOADED);
+      _Jv_Resolver::wait_for_state (klass, JV_STATE_LOADED);
     }
 
   return klass;
@@ -548,7 +394,7 @@
   // cache one and reuse it. It is not necessary to synchronize this.
   if (!array_idt)
     {
-      _Jv_PrepareConstantTimeTables (array_class);
+      _Jv_Resolver::wait_for_state(array_class, JV_STATE_PREPARED);
       array_idt = array_class->idt;
       array_depth = array_class->depth;
       array_ancestors = array_class->ancestors;
@@ -562,19 +408,19 @@
 
   using namespace java::lang::reflect;
   {
-    // Array classes are "abstract final"...
-    _Jv_ushort accflags = Modifier::FINAL | Modifier::ABSTRACT;
-    // ... and inherit accessibility from element type, per vmspec 5.3.3.2
-    accflags |= (element->accflags & Modifier::PUBLIC);
-    accflags |= (element->accflags & Modifier::PROTECTED);
-    accflags |= (element->accflags & Modifier::PRIVATE);      
+    // Array classes are "abstract final" and inherit accessibility
+    // from element type, per vmspec 5.3.3.2
+    _Jv_ushort accflags = (Modifier::FINAL | Modifier::ABSTRACT
+			   | (element->accflags
+			      & (Modifier::PUBLIC | Modifier::PROTECTED
+				 | Modifier::PRIVATE)));
     array_class->accflags = accflags;
   }
 
   // An array class has no visible instance fields. "length" is invisible to 
   // reflection.
 
-  // say this class is initialized and ready to go!
+  // Say this class is initialized and ready to go!
   array_class->state = JV_STATE_DONE;
 
   // vmspec, section 5.3.3 describes this
@@ -584,8 +430,6 @@
   element->arrayclass = array_class;
 }
 
-static jclass stack_head;
-
 // These two functions form a stack of classes.   When a class is loaded
 // it is pushed onto the stack by the class loader; this is so that
 // StackTrace can quickly determine which classes have been loaded.
Index: libjava/java/lang/natVMClassLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natVMClassLoader.cc,v
retrieving revision 1.1.18.2
diff -u -r1.1.18.2 natVMClassLoader.cc
--- libjava/java/lang/natVMClassLoader.cc 12 Aug 2004 17:58:15 -0000 1.1.18.2
+++ libjava/java/lang/natVMClassLoader.cc 14 Sep 2004 20:02:24 -0000
@@ -30,6 +30,21 @@
 #include <java/security/ProtectionDomain.h>
 #include <java/lang/ClassFormatError.h>
 
+void
+java::lang::VMClassLoader::resolveClass (jclass klass)
+{
+  JvSynchronize sync (klass);
+  try
+    {
+      _Jv_Resolver::wait_for_state (klass, JV_STATE_LINKED);
+    }
+  catch (java::lang::Throwable *x)
+    {
+      klass->set_state(JV_STATE_ERROR);
+      transformException(klass, x);
+    }
+}
+
 java::lang::Class *
 java::lang::VMClassLoader::defineClass (java::lang::ClassLoader *loader,
 					jstring name,
@@ -98,20 +113,6 @@
   return klass;
 }
 
-// Finish linking a class.  Only called from ClassLoader::resolveClass.
-void
-java::lang::VMClassLoader::linkClass0 (java::lang::Class *klass)
-{
-  _Jv_WaitForState (klass, JV_STATE_LINKED);
-}
-
-void
-java::lang::VMClassLoader::markClassErrorState0 (java::lang::Class *klass)
-{
-  klass->state = JV_STATE_ERROR;
-  klass->notifyAll ();
-}
-
 java::lang::ClassLoader *
 java::lang::VMClassLoader::getSystemClassLoaderInternal()
 {
Index: libjava/java/lang/reflect/natField.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/reflect/natField.cc,v
retrieving revision 1.15
diff -u -r1.15 natField.cc
--- libjava/java/lang/reflect/natField.cc 25 Oct 2003 06:49:20 -0000 1.15
+++ libjava/java/lang/reflect/natField.cc 14 Sep 2004 20:02:24 -0000
@@ -1,6 +1,6 @@
 // natField.cc - Implementation of java.lang.reflect.Field native methods.
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2003  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -47,7 +47,7 @@
 {
   jfieldID fld = _Jv_FromReflectedField (this);
   JvSynchronize sync (declaringClass);
-  _Jv_ResolveField (fld, declaringClass->getClassLoaderInternal ());
+  _Jv_Resolver::resolve_field (fld, declaringClass->getClassLoaderInternal ());
   return fld->type;
 }
 


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