From 367390404d26b7bfc400d77893579e83e2a19fb9 Mon Sep 17 00:00:00 2001
From: Tom Tromey <tromey@gcc.gnu.org>
Date: Thu, 25 Nov 2004 03:47:08 +0000
Subject: [PATCH] * Merged gcj-abi-2-dev-branch to trunk.

(Actual changes too large to list in the commit message;
see ChangeLog.)

From-SVN: r91270
---
 gcc/java/ChangeLog                            |  583 +++
 gcc/java/Make-lang.in                         |    5 +
 gcc/java/check-init.c                         |   60 +-
 gcc/java/class.c                              |  349 +-
 gcc/java/decl.c                               |   76 +-
 gcc/java/expr.c                               |  539 ++-
 gcc/java/gcj.texi                             |   23 +-
 gcc/java/gjavah.c                             |    5 +-
 gcc/java/java-except.h                        |    2 +
 gcc/java/java-tree.h                          |   75 +-
 gcc/java/jcf-parse.c                          |  142 +-
 gcc/java/jvspec.c                             |    2 +-
 gcc/java/lang.c                               |   20 +
 gcc/java/lang.opt                             |    4 +
 gcc/java/parse.y                              |   22 +-
 gcc/java/typeck.c                             |    2 +-
 gcc/java/verify-glue.c                        |  514 +++
 gcc/java/verify-impl.c                        | 3418 +++++++++++++++++
 gcc/java/verify.c                             |  106 +-
 gcc/java/verify.h                             |  160 +
 libjava/ChangeLog                             |  755 ++++
 libjava/Makefile.am                           |   67 +-
 libjava/Makefile.in                           |  393 +-
 libjava/aclocal.m4                            |    2 +-
 libjava/boehm.cc                              |  201 +-
 libjava/configure                             |    9 +-
 libjava/configure.ac                          |    2 +
 libjava/configure.host                        |    2 +-
 libjava/defineclass.cc                        |   82 +-
 libjava/gcj/Makefile.in                       |    1 +
 libjava/gcj/field.h                           |   13 +-
 libjava/gcj/javaprims.h                       |    3 +
 libjava/gij.cc                                |    5 +-
 .../gnu/gcj/runtime/PersistentByteMap.java    |  484 +++
 libjava/gnu/gcj/runtime/SharedLibHelper.java  |   98 +-
 libjava/gnu/gcj/runtime/VMClassLoader.java    |    3 +-
 libjava/gnu/gcj/runtime/natSharedLibLoader.cc |   13 +-
 libjava/gnu/gcj/tools/gcj_dbtool/Main.java    |  272 ++
 libjava/include/Makefile.in                   |    1 +
 libjava/include/execution.h                   |  146 +
 libjava/include/java-interp.h                 |   50 +-
 libjava/include/java-stack.h                  |   84 +
 libjava/include/jvm.h                         |   43 +-
 libjava/interpret.cc                          |  609 ++-
 libjava/java/io/ObjectInputStream.java        |   25 +-
 libjava/java/io/ObjectOutputStream.java       |   12 +-
 libjava/java/lang/Class.h                     |  139 +-
 libjava/java/lang/ClassLoader.java            |   18 +-
 libjava/java/lang/Compiler.java               |   13 +-
 libjava/java/lang/SecurityManager.java        |    6 +-
 libjava/java/lang/VMClassLoader.java          |   47 +-
 libjava/java/lang/VMCompiler.java             |  332 ++
 libjava/java/lang/VMSecurityManager.java      |    3 +-
 libjava/java/lang/natClass.cc                 | 1133 +-----
 libjava/java/lang/natClassLoader.cc           |  194 +-
 libjava/java/lang/natRuntime.cc               |   11 +-
 libjava/java/lang/natString.cc                |   17 +-
 libjava/java/lang/natVMClassLoader.cc         |  136 +-
 libjava/java/lang/reflect/natField.cc         |    4 +-
 libjava/java/lang/reflect/natMethod.cc        |    9 +-
 libjava/java/net/URLClassLoader.java          |  151 +-
 libjava/jni.cc                                |    7 +-
 libjava/link.cc                               | 1764 +++++++++
 libjava/prims.cc                              |    8 +-
 libjava/resolve.cc                            | 1125 ------
 libjava/testsuite/Makefile.in                 |    1 +
 libjava/testsuite/libjava.lang/assign2.java   |   21 +
 libjava/testsuite/libjava.lang/assign2.out    |    1 +
 libjava/testsuite/libjava.loader/loader.exp   |   18 +-
 libjava/verify.cc                             |    2 +-
 70 files changed, 11294 insertions(+), 3348 deletions(-)
 create mode 100644 gcc/java/verify-glue.c
 create mode 100644 gcc/java/verify-impl.c
 create mode 100644 gcc/java/verify.h
 create mode 100644 libjava/gnu/gcj/runtime/PersistentByteMap.java
 create mode 100644 libjava/gnu/gcj/tools/gcj_dbtool/Main.java
 create mode 100644 libjava/include/execution.h
 create mode 100644 libjava/include/java-stack.h
 create mode 100644 libjava/java/lang/VMCompiler.java
 create mode 100644 libjava/link.cc
 delete mode 100644 libjava/resolve.cc
 create mode 100644 libjava/testsuite/libjava.lang/assign2.java
 create mode 100644 libjava/testsuite/libjava.lang/assign2.out

diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 272e8c52ab37..fc28a08c365d 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,586 @@
+2004-11-24  Tom Tromey  <tromey@redhat.com>
+
+	* Merged gcj-abi-2-dev-branch to trunk.
+
+2004-11-24  Andrew Haley  <aph@redhat.com>
+
+	* jcf-parse.c (parse_class_file): Set file_start_location.
+
+2004-11-10  Tom Tromey  <tromey@redhat.com>
+
+	* class.c (make_field_value): Don't call build_static_field_ref.
+	(build_static_field_ref): Don't emit direct references when using
+	indirect dispatch.
+
+	* gcj.texi (Invoking gij): Document -verbose.  Put -verbose and
+	-verbose:class into man page synopsis.
+
+2004-11-09  Tom Tromey  <tromey@redhat.com>
+
+	* expr.c (build_java_arraystore_check): Still generate check if
+	element type is itself an array.
+
+2004-11-08  Tom Tromey  <tromey@redhat.com>
+
+	* java-tree.h (soft_check_assignment_node): Removed.
+	(enum java_tree_index): Removed JTI_SOFT_CHECK_ASSIGNMENT_NODE.
+	* decl.c (java_init_decl_processing): Don't initialize
+	soft_check_assignment_node.
+
+2004-11-05  Tom Tromey  <tromey@redhat.com>
+
+	* class.c (layout_class_methods): Don't add Miranda methods when
+	using indirect dispatch.
+
+2004-11-05  Bryce McKinlay  <mckinlay@redhat.com>
+
+	* class.c (make_class_data): Call emit_assertion_table to set the
+	'assertion_table' field.
+	(build_signature_for_libgcj): Move here from expr.c.
+	(add_assertion_table_entry): New function. Callback for assertion
+	hashtable traversal.
+	(emit_assertion_table): New. Take class argument, and generate 
+	assertion table DECL based on the TYPE_ASSERTIONS hashtable.
+	* decl.c (init_decl_processing): Define assertion_entry_type record.
+	Push 'assertion_table' class field instead of 'verify'.
+	* expr.c (type_assertion_eq): Compare 'assertion_code' field.
+	(type_assertion_hash): Include 'assertion_code' in hash.
+	(add_type_assertion): Rewritten. Take class and assertion_code
+	arguments. Add assertions to the TYPE_ASSERTIONS hashtable.
+	(can_widen_reference_to): Use new add_type_assertion() arguments.
+	* java-tree.h (java_tree_index): Add JTI_ASSERTION_ENTRY_TYPE, 
+	JTI_ASSERTION_TABLE_TYPE. Remove JTI_VERIFY_IDENTIFIER_NODE.
+	(verify_identifier_node): Removed.
+	(assertion_entry_type, assertion_table_type): New.
+	(ASSERTION_TYPES_COMPATIBLE, ASSERTION_IS_INSTANTIABLE): New. Type
+	assertion code definitions.
+	(struct type_assertion): Add assertion_code. Rename 'source_type' and
+	'target_type' to 'op1' and 'op2'.
+	(add_type_assertion): Declare.
+	(lang_printable_name_wls): Remove unused definition.
+	* verify-glue.c: (vfy_is_assignable_from): New. Call add_type_assertion
+	to emit runtime assertion.
+	(vfy_note_stack_type): Clean up non-C90 declarations.
+	(vfy_note_local_type): Likewise.
+	* verify.h (vfy_is_assignable_from): Declare.
+	* verify-impl.c (is_assignable_from_slow): Remove unused function.
+	(ref_compatible): Rename arguments. Call vfy_is_assignable_from() 
+	instead of is_assignable_from_slow().
+	(types_compatible): Reinstate ref_compatible() call.
+
+2004-11-04  Tom Tromey  <tromey@redhat.com>
+
+	* class.c (build_static_field_ref): Reverted previous patch.
+
+	* class.c (build_static_field_ref): Don't emit direct references
+	when using indirect dispatch.
+
+2004-11-03  Tom Tromey  <tromey@redhat.com>
+
+	* expr.c (expand_java_arrayload): Set lhs_type_node.
+	(expand_java_arraystore): Set rhs_type_node.
+
+2004-11-02  Tom Tromey  <tromey@redhat.com>
+
+	* jcf-parse.c (compute_class_name): Use filename length from zip
+	directory, not strlen.
+
+	* expr.c (expand_invoke): Mark new interface methods as abstract.
+
+2004-11-01  Tom Tromey  <tromey@redhat.com>
+
+	* verify-impl.c (push_jump): Removed check for uninitialized
+	objects.
+	(push_exception_jump): Likewise.
+	(handle_ret_insn): Likewise.
+	(handle_jsr_insn): Likewise.
+	(state_check_no_uninitialized_objects): Removed.
+
+	* decl.c (check_local_unnamed_variable): Recognize
+	promoted-to-int parameters when using the new verifier.
+	* expr.c (expand_java_arraystore): Explicitly request array type
+	when using new verifier.
+	(expand_java_arrayload): Likewise.
+	(invoke_build_dtable): Don't pass object_type_node as
+	expression argument to build_java_indirect_ref.
+	(build_java_check_indexed_type): Do nothing.
+	(build_java_arraystore_check): Handle case where array doesn't
+	have array type.
+	(build_java_array_length_access): Likewise.
+	(expand_invoke): Handle case where interface overrides a method
+	from Object.
+	(pop_type_0): Always succeed for reference types.
+	(process_jvm_instruction): Don't pop a value in a dead
+	exception handler.
+	(pop_arguments): Convert arguments to correct types.
+
+2004-10-29  Andrew Haley  <aph@redhat.com>
+
+	* jcf-parse.c (give_name_to_class): Remove line that was
+	incorrectly merged.
+
+2004-10-29  Andrew Haley  <aph@redhat.com>
+
+	* jcf-parse.c (set_source_filename): Add code to build new sfname.
+
+2004-10-20  Andrew Haley  <aph@redhat.com>
+
+	* decl.c (end_java_method): Don't expand if flag_syntax_only.
+
+2004-10-26  Tom Tromey  <tromey@redhat.com>
+
+	* verify.h (vfy_notify_verified): Removed.
+	* verify-glue.c (vfy_notify_verified): Removed.
+
+2004-10-26  Tom Tromey  <tromey@redhat.com>
+
+	* verify-impl.c (debug_print_state): Declare `i' before code.
+	(merge_types): Modify `t' when it is null_type.
+
+2004-10-26  Tom Tromey  <tromey@redhat.com>
+
+	* verify-impl.c (type_print): Renamed from print.  Now static and
+	takes an argument.
+	(debug_print_state): Use type_print.
+
+2004-10-25  Tom Tromey  <tromey@redhat.com>
+
+	* expr.c (build_invokeinterface): Compute correct offset for
+	index into interface methods.
+
+2004-10-20  Tom Tromey  <tromey@redhat.com>
+
+	* java-tree.h (verify_jvm_instructions_new): Declare.
+
+	* jvspec.c (jvgenmain_spec): Remove -fnew-verifier from cc1
+	command line.
+
+	* verify-impl.c (verify_instructions): Correctly handle wide
+	types on the stack.
+	* verify-glue.c (vfy_get_class_name): Use DECL_NAME.
+	(vfy_get_component_type): Strip pointer types.
+	(vfy_find_class): Use get_type_from_signature.  Strip pointer
+	types.
+	Include java-except.h.
+
+2004-10-20  Bryce McKinlay  <mckinlay@redhat.com>
+
+	* verify-impl.c (type_array_elementpop_raw, vfy_pop_type_t, 
+	vfy_push_type_t, set_variable, add_new_state, merge_into,
+	handle_jsr_insn, branch_prepass, check_class_constant,
+	check_wide_constant, get_one_type, compute_static_types, 
+	verify_instructions_0): Clean up C99 declarations after statements.
+
+2004-10-20  Tom Tromey  <tromey@redhat.com>
+
+	* verify-impl.c (merge_refs): Compare reference against iterator,
+	not ref2.
+
+	* verify-glue.c (vfy_tag): Mask off resolved flag.
+
+2004-10-19  Tom Tromey  <tromey@redhat.com>
+
+	* verify-impl.c (verify_instructions): Call vfy_note_local_type.
+	(init_state_with_stack): Initialize `this_type' in state.
+	(verify_method): Use debug_print.
+	* verify-glue.c (vfy_is_primitive): Removed debugging print.
+	(vfy_note_stack_depth): Reverted last patch.
+	(vfy_note_stack_type): Note pointer to Object, not Object.
+	(vfy_note_local_type): Likewise.
+
+	* verify.h (vfy_note_instruction_seen): Declare.
+	* verify-glue.c (verify_jvm_instructions_new): Set
+	BCODE_EXCEPTION_TARGET on target instruction.
+	(vfy_note_instruction_seen): New function.
+	* verify-impl.c (FLAG_INSN_SEEN): New define.
+	(verify_instructions_0): Set flag on instruction.  Save state for
+	PC=0 later.
+	(verify_instructions): Call vfy_note_instruction_seen.
+
+	* verify-glue.c (vfy_note_stack_depth): Fix off-by-one error.
+	(verify_jvm_instructions_new): Call method_init_exceptions,
+	add_handler, and handle_nested_ranges.
+	* verify-impl.c (verify_method): Return 1 on success.
+	(verify_instructions_0): Save the state at PC=0.
+
+	* verify-impl.c (init_type_from_class): Set is_resolved and
+	ref_next on new ref_intersection.
+	(init_type_from_string): Likewise.
+
+2004-10-15  Bryce McKinlay  <mckinlay@redhat.com>
+
+	* expr.c (expand_bytecode): Use verify_jvm_instructions_new
+	if flag_new_verifier is set.
+	* java-tree.h (flag_new_verifier): Declare.
+	* lang.opt (fnew-verifier): New option.
+	* verify-impl.c: Work around namespace pollution by undef'ing 
+	'current_class'.
+	(struct verifier_context): Make 'bytecode' const.
+	(verify_fail_pc): Pass -1 PC argument to vfy_fail.
+	(types_compatible): For the BC-ABI, always consider reference types
+	compatible.
+	(check_class_constant): Use vfr->current_class.
+	(check_constant): Likewise.
+	(check_wide_constant): Likewise.
+	(check_field_constant): Check for 'L' at start of type name.
+	(get_one_type): Return pointer instead of type. Set type result in
+	caller via passed type pointer.
+	(compute_argument_types): Update to use new get_one_type arguments.
+	(compute_return_type): Likewise.
+	(make_verifier_context): New. Allocate and initialize 'vfr'.
+	(free_verifier_context): New. Free 'vfr' and its contents.
+	(verify_method): Remove ATTRIBUTE_UNUSED. Call make_verifier_context
+	and free_verifier_context.
+
+2004-10-15  Tom Tromey  <tromey@redhat.com>
+
+	* verify-glue.c (vfy_note_local_type): Mark argument as unused.
+	* verify.h (vfy_fail): Fixed formatting.
+
+	* verify-impl.c (vfr): Fixed comment formatting.
+	(collapse_type): New function.
+	(verify_instructions): Notify compiler about type map.
+	* verify.h (vfy_note_stack_depth): Updated.
+	(vfy_note_stack_type): Likewise.
+	(vfy_note_local_type): Likewise.
+	(vfy_unsuitable_type, vfy_return_address_type, vfy_null_type):
+	Declare.
+	* verify-glue.c (vfy_note_stack_depth): Correctly size type
+	state.  Added `method' argument.
+	(vfy_note_stack_type): Renamed from vfy_note_type.  Added `method'
+	argument.
+	(vfy_note_local_type): New function.
+	(vfy_unsuitable_type): Likewise.
+	(vfy_return_address_type): Likewise.
+	(vfy_null_type): Likewise.
+
+	* verify.h (VFY_IN_GCC): Removed.
+	(VFY_WANT_TYPEMAP): Removed.
+	* verify-impl.c (verify_instructions_0): Removed useless "\".
+	(struct state) <next>: Uncomment.
+
+2004-10-13  Bryce McKinlay  <mckinlay@redhat.com>
+
+	* verify-impl.c: Formatting fixes. Reformat C++-style comments to 
+	C-style.
+
+2004-10-06  Bryce McKinlay  <mckinlay@redhat.com>
+
+	* Make-lang.in (verify.o): Re-enabled this target.
+	* verify-glue.c (vfy_get_interface_count): Add ATTRIBUTE_UNUSED.
+	(vfy_get_interface): Likewise.
+	(verify_jvm_instructions_new): Renamed from verify_jvm_instructions.
+	* verify.h (verify_jvm_instructions_new): Declare.
+	* verify-impl.c (free_state): Temporarily comment out unused
+	function.
+
+2004-10-06  Tom Tromey  <tromey@redhat.com>
+
+	* java-tree.h (JV_STATE_READ): New enum value.
+
+2004-10-06  Bryce McKinlay  <mckinlay@redhat.com>
+
+	* verify.h: New file.
+
+2004-10-05  Bryce McKinlay  <mckinlay@redhat.com>
+
+	* verify-impl.c, verify-glue.c, verify.h: New files.
+	* Make-lang.in: Add rules for verify-impl.o and verify-glue.o.
+
+2004-09-24  Andrew Haley  <aph@redhat.com>
+
+	* decl.c (check_local_unnamed_variable): Always use the PARM_DECL
+	for a slot if it's of pointer type.
+
+2004-09-14  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.
+
+2004-09-10  Andrew Haley  <aph@redhat.com>
+
+	PR java/12760
+	* expr.c (build_invokeinterface): Use fast method for interface
+	dispatch.
+	* java-tree.h (enum java_tree_index): Add JTI_ITABLE_TYPE,
+	JTI_ITABLE_PTR_TYPE.
+	(struct lang_type): Add  itable_methods, itable_decl, itable_syms_decl.
+	(emit_symbol_table): Add new arg, element_size.
+	* decl.c (java_init_decl_processing): Initialize Class.itable.
+	* class.c (GEN_TABLE): New macro.
+	(gen_indirect_dispatch_tables): Use it.  Add itable.
+	(make_class_data): Add new arg for emit_symbol_table().
+	Emit itable.
+	(add_miranda_methods): Make sure search_class has been parsed.
+	(emit_symbol_table): Add new arg, element_size.
+
+2004-09-06  Andrew Haley  <aph@redhat.com>
+
+	* verify.c (merge_types): Return Object for all merges of
+	interfaces.
+	* expr.c (add_type_assertion): Don't generate assertions when
+	source type is array of Object.
+		
+2004-09-03  Andrew Haley  <aph@redhat.com>
+
+	* class.c (finish_class): Nullify TYPE_VERIFY_METHOD.
+
+	* lang.c (java_post_options): Force flag_verify_invocations if
+	we're not using indirect dispatch.
+
+	* expr.c (pop_type_0): Move test for interfaces before call to
+	can_widen_reference_to().
+	(build_signature_for_libgcj): Remove generation of canonical array
+	type.
+	(add_type_assertion): Canonicalize both arrays.
+	Don't assert that type X can be assigned to Object.
+	Don't assert that type X an be assigned to type X.
+	Don't assert that Object can be assigned to type X.
+	(can_widen_reference_to): Warn whenever we generate an assertion.
+	(process_jvm_instruction): Use throwable_type_node for the type of
+	an exception class.
+
+2004-09-01  Andrew Haley  <aph@redhat.com>
+
+	* decl.c (java_init_decl_processing): Change
+	verify_identifier_node to "__verify".
+	* expr.c (add_type_assertion): Use verify_identifier_node for name.
+	* java-tree.h (verify_identifier_node): Change to "__verify".
+
+	* expr.c (build_signature_for_libgcj): New function.
+	(add_type_assertion): Use it to construct signatures for
+	source_type and target_type.
+
+2004-08-27  Andrew Haley  <aph@redhat.com>
+
+	* java-tree.h (enum java_tree_index): Add JTI_VERIFY_IDENTIFIER_NODE.
+	(verify_identifier_node): New.
+	(TYPE_VERIFY_METHOD): New.
+	(struct type_assertion): New type.
+	* expr.c (type_assertion_eq): New function.
+	(type_assertion_hash): New function.
+	(add_type_assertion): New function.
+	(can_widen_reference_to): Call add_type_assertion().
+	* decl.c (java_init_decl_processing): Add verify_identifier_node.
+	* class.c (make_class_data): Initialize TYPE_VERIFY_METHOD (type).
+	(finish_class): Output TYPE_VERIFY_METHOD (type).
+
+	* decl.c (end_java_method): Nullify unused fields.
+
+2004-08-17  Andrew Haley  <aph@redhat.com>
+
+	* verify.c (defer_merging): Quieten.
+	* jcf-parse.c (load_class): Only try to open a class file if it's
+	java.lang.Object or if it's part of the current compilation.
+	Check that the class we just tried to load is the class we just
+	loaded.  Quieten.
+	(java_parse_file): Set flag_verify_invocations off if we're
+	compiling from .class.
+	(parse_zip_file_entries): Abort if we try to read a dummy class.
+	* expr.c (can_widen_reference_to): Quieten.
+	(build_invokevirtual): Abort if we try to invokevirtual an
+	interface.
+	(expand_invoke): Don't build a non-interface call to an interface.
+	(build_instanceof): Don't do premature optimization if
+	flag_verify_invocations is not set.
+	* class.c (set_super_info): Disable code that inherits TYPE_DUMMY
+	from superclass.
+	(build_static_field_ref): Add correct type conversion for
+	field_address.
+	(add_miranda_methods): Disable generation of Miranda methods for
+	dummy classes.
+	(layout_class_method): Don't complain about non-static method
+	overrides static method with dummy classes.
+
+2004-08-13  Tom Tromey  <tromey@redhat.com>
+
+	* class.c (build_static_field_ref): Re-enable atable lookups for
+	static fields.
+
+	* parse.y (strip_out_static_field_access_decl): Indentation fix.
+
+2004-08-11  Tom Tromey  <tromey@redhat.com>
+
+	* gcj.texi (libgcj Runtime Properties): Document new properties.
+
+2004-08-06  Andrew Haley  <aph@redhat.com>
+
+	* jcf-parse.c (load_class): Check that we really have loaded the
+	class we're looking for.
+
+2004-07-19  Andrew Haley  <aph@redhat.com>
+
+	* verify.c (verify_jvm_instructions): Comment change only.
+
+	* typeck.c (build_java_array_type): Add size field to array name.
+
+	* java-tree.h (LOCAL_SLOT_P): New.
+	(update_aliases): Add PC argument.
+	(pushdecl_function_level): New function.
+
+	* java-gimplify.c (java_gimplify_expr): Handle VAR_DECL,
+	MODIFY_EXPR, and SAVE_EXPR.
+	(java_gimplify_modify_expr): New function.
+
+	* expr.c (push_type_0): Call find_stack_slot() to create temporary.
+	(expand_iinc): Pass PC to update_aliases().
+	(STORE_INTERNAL): Likewise.
+	(process_jvm_instruction): Likewise.
+
+	* decl.c (base_decl_map): New variable.
+	(uniq): New variable.
+	(update_aliases): Rewrite with more thorough checking.
+	(debug_variable_p): New function.
+	(push_jvm_slot): Don't initialize local variable.  Don't pushdecl.
+	(check_local_named_variable): Delete whole function.
+	(initialize_local_variable): New function.
+	(check_local_unnamed_variable): Add checks and comments.
+	(find_local_variable): Rewrite.
+	(java_replace_reference): New function.
+	(function_binding_level): New variable.
+	(pushdecl_function_level): New function.
+	(maybe_pushlevels): Set DECL_LOCAL_END_PC.
+	(maybe_pushlevels): Call pushdecl() on each of the new decls.
+	(start_java_method): Reset uniq.  Create base_decl_map.  Set
+	function_binding_level.
+	(end_java_method): Null unused fields to save memory.
+
+2004-06-29  Andrew Haley  <aph@redhat.com>
+
+	* except.c (expand_start_java_handler): Push a new binding level.
+	Don't build a TRY_CATCH_EXPR now, we'll do it later.  Call
+	register_exception_range() to register where we'll do it.
+	(expand_end_java_handler): Remove old bogus code.  Replace with
+	new logic that simply builds TRY_CATCH_EXPRs and inserts them at
+	the top of the expression we're curently building.
+	(maybe_end_try): Delete.
+	* decl.c (binding_level.exception_range): New field.
+	(clear_binding_level): Add field exception_range.  Reformat.
+	(poplevel): Call expand_end_java_handler().
+	(poplevel): Call java_add_stmt only if functionbody is false.
+	(maybe_poplevels): Don't call maybe_end_try() from here.
+	(end_java_method): Clear no longer used trees in function decl.
+	(register_exception_range): New function.
+	* java-tree.h (register_exception_range, struct eh_range): Declare.
+
+2004-06-22  Andrew Haley  <aph@redhat.com>
+
+	* class.c (gen_indirect_dispatch_tables): Set the DECL_OWNER of
+	the otable.
+	* check-init.c (get_variable_decl): Teach check-init about
+	FIELD_DECLs addressed via the otable.
+	* jcf-parse.c (load_class): Check CLASS_LOADED_P, not
+	CLASS_PARSED_P.
+
+2004-05-28  Andrew Haley  <aph@redhat.com>
+
+	* jcf-parse.c (load_class): Don't try to read a class that we've
+	already read.
+
+	* expr.c (build_invokeinterface): Use the old-fashioned way of
+	doing indirect dispatch: look up interfaces by name.
+	* java-tree.h (enum java_tree_index): Add
+	JTI_SOFT_LOOKUPINTERFACEMETHODBYNAME_NODE
+	* decl.c (java_init_decl_processing): Add
+	soft_lookupinterfacemethodbyname_node.
+
+	* gjavah.c (print_method_info): Final methods have vtable entries,
+	so gjavah needs to output them. 
+	* class.c (layout_class_method): Generate vtable entries for final
+	methods.
+	* parse.y (invocation_mode): Use INVOKE_VIRTUAL for indirect
+	dispatch, even if a method is final.
+
+2004-05-25  Andrew Haley  <aph@redhat.com>
+
+	* class.c (build_symbol_entry): Convert the names of constructors
+	to init_identifier_node when generating an entry for the indirect
+	dispatch table.
+	
+	* expr.c (build_known_method_ref): Generate indirect calls for
+	all methods marked DECL_EXTERNAL or TREE_PUBLIC.
+
+2004-05-24  Andrew Haley  <aph@redhat.com>
+
+        * expr.c (build_known_method_ref): Make sure ARRAY_REF access to
+        atable element is of the right type.
+
+        * class.c (build_static_field_ref): Cast pointer to correct type
+        for field.
+
+2004-04-20  Bryce McKinlay  <mckinlay@redhat.com>
+
+	* Merged with HEAD as of 20040514. Diff against
+	gcj-abi-2-merge-20040514.
+
+2004-04-16  Andrew Haley  <aph@redhat.com>
+
+	* verify.c (check_pending_block): Disable subroutine checks.
+	(defer_merging): New function.
+	(merge_types): If types are dummy, use defer_merging to combine them.
+	(verify_jvm_instructions): If invocation is invokeinterface and
+	target is dummy, assume target really is an interface.
+
+	* parse.y (patch_invoke): Break out call to java_create_object.
+
+	* lang.c (flag_verify_invocations): New.
+
+	* jcf-parse.c (load_class): If we've already failed to load a
+	class, don't try again.
+	(load_class): If we can't find a .class file, don't fail, but emit
+	a warning.
+	(parse_class_file): Don't act on dummy methods.
+
+	* java-tree.h (flag_verify_invocations): New.
+	(TYPE_DUMMY): New.
+	(lang_type.dummy_class): New field.
+	(java_create_object): New function.
+	(METHOD_DUMMY): New.
+
+	* expr.c (build_field_ref): Widen field offset.
+	(pop_type_0): If the type in stack_type_map is a TREE_LIST, check
+	that each of its elements is compatible with the one we're
+	popping.
+	(pop_type_0): Issue a warning to say that we need to generate a
+	runtime check.
+	(java_create_object): New function.
+	(build_field_ref): Only generate hard refs if we're not using
+	indirect dispatch.
+	(expand_java_field_op): If we're using !verify_invocations and we
+	see a missing field, generate a decl for it.
+
+	(expand_invoke): If a class doesn't have the method we seek and
+	we're using !flag_verify_invocations, generate a decl for the
+	method now.
+
+	(build_known_method_ref): Always use indirect dispatch via the
+	atable for static methods.
+
+	(expand_java_NEW): Break out object creation into new function,	
+	java_create_object.
+
+	(can_widen_reference_to): Issue a warning to say that we need to
+	generate a runtime check.
+
+	* class.c (set_super_info): Inherit TYPE_DUMMY from sureclass.
+	(make_method_value): Also use index for interfaces.
+	(make_class_data): Skip dummy field for inherited data.
+	Don't build method array for dummy methods.
+	Set size_in_byte to -1 when using inirect dispatch
+	Don't build a hard class ref if we don't have a hard ref to our
+	superclass, or if we're using inirect dispatch.
+	Null out dispatch tables.
+
+	(layout_class_method): Don't complain about non-static method
+	overrides static method is method is artificial.
+
+	(build_static_field_ref): Disable atable references to static
+	fields for the time being.
+
+	(layout_class_methods): Check for CLASS_INTERFACE as
+	well as CLASS_ABSTRACT.
+
 2004-11-24  Steven Bosscher  <stevenb@suse.de>
 
 	* class.c (make_class_data): Don't check flag_inline_functions.
diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in
index bea8c73d5560..16094b9c28b7 100644
--- a/gcc/java/Make-lang.in
+++ b/gcc/java/Make-lang.in
@@ -102,6 +102,7 @@ gt-java-builtins.h gtype-java.h gt-java-resource.h : s-gtype ; @true
 # Executables built by this Makefile:
 JAVA_OBJS = java/parse.o java/class.o java/decl.o java/expr.o \
   java/constants.o java/lang.o java/typeck.o java/except.o java/verify.o \
+  java/verify-glue.o java/verify-impl.o \
   java/zextract.o java/jcf-io.o java/win32-host.o java/jcf-parse.o java/mangle.o \
   java/mangle_name.o java/builtins.o java/resource.o \
   java/jcf-write.o java/buffer.o java/check-init.o java/jcf-depend.o \
@@ -338,6 +339,10 @@ java/win32-host.o: java/win32-host.c $(CONFIG_H) $(SYSTEM_H) coretypes.h java/jc
 java/verify.o: java/verify.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h \
   java/javaop.h java/java-opcodes.h java/java-except.h toplev.h $(SYSTEM_H) \
   coretypes.h $(TM_H)
+java/verify-glue.o: java/verify-glue.c $(CONFIG_H) $(SYSTEM_H) $(JAVA_TREE_H) \
+  coretypes.h $(TM_H) java/verify.h
+java/verify-impl.o: java/verify-impl.c $(CONFIG_H) java/verify.h $(SYSTEM_H) \
+  coretypes.h  java/jcf.h $(JAVA_TREE_H)
 java/xref.o: java/xref.c java/xref.h $(CONFIG_H) $(JAVA_TREE_H) toplev.h \
   $(SYSTEM_H) coretypes.h $(TM_H)
 java/zextract.o: java/zextract.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
diff --git a/gcc/java/check-init.c b/gcc/java/check-init.c
index dacc4b914b53..05692b0a4c20 100644
--- a/gcc/java/check-init.c
+++ b/gcc/java/check-init.c
@@ -36,7 +36,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 /* The basic idea is that we assign each local variable declaration
    and each blank final field an index, and then we pass around
    bitstrings, where the (2*i)'th bit is set if decl whose DECL_BIT_INDEX
-   is i is definitely assigned, and the (2*i+1)'th bit is set if 
+   is i is definitely assigned, and the the (2*i=1)'th bit is set if 
    decl whose DECL_BIT_INDEX is i is definitely unassigned */
 
 /* One segment of a bitstring. */
@@ -45,7 +45,7 @@ typedef unsigned int word;
 /* Pointer to a bitstring. */
 typedef word *words;
 
-/* Number of local variables currently active. */
+/* Number of locals variables currently active. */
 static int num_current_locals = 0;
 
 /* The value of num_current_locals when we entered the closest
@@ -191,6 +191,50 @@ get_variable_decl (tree exp)
 	    return op1;
 	}
     }
+  else if (TREE_CODE (exp) == INDIRECT_REF)
+    {
+      /* For indirect dispatch, look for an expression of the form 
+      (indirect_ref (+ (array_ref otable <N>) this)).  
+      FIXME: it would probably be better to generate a JAVA_FIELD_REF
+      expression that gets converted to OTABLE access at
+      gimplification time.  */
+      exp = TREE_OPERAND (exp, 0);
+      if (TREE_CODE (exp) == PLUS_EXPR)
+	{
+	  tree op0 = TREE_OPERAND (exp, 0);
+	  STRIP_NOPS (op0);
+	  if (TREE_CODE (op0) == ARRAY_REF)
+	    {
+	      tree table = TREE_OPERAND (op0, 0);
+	      if (TREE_CODE (table) == VAR_DECL
+		  && DECL_LANG_SPECIFIC (table)
+		  && DECL_OWNER (table) 
+		  && TYPE_OTABLE_DECL (DECL_OWNER (table)) == table)
+		{
+		  HOST_WIDE_INT index 
+		    = TREE_INT_CST_LOW (TREE_OPERAND (op0, 1));
+		  tree otable_methods 
+		    = TYPE_OTABLE_METHODS (DECL_OWNER (table));
+		  tree element;
+		  for (element = otable_methods; 
+		       element; 
+		       element = TREE_CHAIN (element))
+		    {
+		      if (index == 1)
+			{
+			  tree purpose = TREE_PURPOSE (element);
+			  if (TREE_CODE (purpose) == FIELD_DECL)
+			    return purpose;
+			  else
+			    return NULL_TREE;
+			}
+		      --index;
+		    }
+		}
+	    }
+	}
+    }
+
   return NULL_TREE;
 }
 
@@ -306,7 +350,7 @@ check_bool2_init (enum tree_code code, tree exp0, tree exp1,
 /* Check a boolean expression EXP for definite [un]assignment.
    BEFORE is the set of variables definitely [un]assigned before the
    conditional.  (This bitstring may be modified arbitrarily in this function.)
-   On output, WHEN_FALSE is the set of variables definitely [un]assigned after
+   On output, WHEN_FALSE is the set of variables [un]definitely assigned after
    the conditional when the conditional is false.
    On output, WHEN_TRUE is the set of variables definitely [un]assigned after
    the conditional when the conditional is true.
@@ -432,8 +476,8 @@ done_alternative (words after, struct alternatives *current)
 	      WORDS_NEEDED (2 * current->num_locals));
 }
 
-/* Used when we are done with a control flow branch and are all merged again.
-   AFTER is the merged state of [un]assigned variables,
+/* Used when we done with a control flow branch and are all merged again.
+ * AFTER is the merged state of [un]assigned variables,
    CURRENT is a struct alt that was passed to BEGIN_ALTERNATIVES. */
 
 #define END_ALTERNATIVES(after, current) \
@@ -445,7 +489,7 @@ done_alternative (words after, struct alternatives *current)
   start_current_locals = current.save_start_current_locals; \
 }
 
-/* Check for [un]initialized local variables in EXP.  */
+/* Check for (un)initialized local variables in EXP.  */
 
 static void
 check_init (tree exp, words before)
@@ -460,7 +504,7 @@ check_init (tree exp, words before)
 	  && DECL_NAME (exp) != this_identifier_node)
 	{
 	  int index = DECL_BIT_INDEX (exp);
-	  /* We don't want to report and mark as non-initialized class
+	  /* We don't want to report and mark as non initialized class
 	     initialization flags. */
 	  if (! LOCAL_CLASS_INITIALIZATION_FLAG_P (exp)
 	      && index >= 0 && ! ASSIGNED_P (before, index))
@@ -604,7 +648,7 @@ check_init (tree exp, words before)
 	   "hypothetical" analysis model.  We do something much
 	   simpler: We just disallow assignments inside loops to final
 	   variables declared outside the loop.  This means we may
-	   disallow some contrived assignments that the JLS allows, but I
+	   disallow some contrived assignments that the JLS, but I
 	   can't see how anything except a very contrived testcase (a
 	   do-while whose condition is false?) would care. */
 
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 543bdf2d9842..391752ad271c 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -43,6 +43,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "stdio.h"
 #include "target.h"
 #include "except.h"
+#include "cgraph.h"
 #include "tree-iterator.h"
 
 /* DOS brain-damage */
@@ -61,6 +62,7 @@ static tree maybe_layout_super_class (tree, tree);
 static void add_miranda_methods (tree, tree);
 static int assume_compiled (const char *);
 static tree build_symbol_entry (tree);
+static tree emit_assertion_table (tree);
 
 struct obstack temporary_obstack;
 
@@ -342,6 +344,34 @@ unmangle_classname (const char *name, int name_length)
   return to_return;
 }
 
+#define GEN_TABLE(TABLE, NAME, TABLE_TYPE, TYPE)			\
+do									\
+{									\
+  const char *typename = IDENTIFIER_POINTER (mangled_classname ("", TYPE)); \
+  char *buf = alloca (strlen (typename) + strlen (#NAME "_syms_") + 1);	\
+  tree decl;								\
+									\
+  sprintf (buf, #NAME "_%s", typename);					\
+  TYPE_## TABLE ##_DECL (type) = decl =					\
+    build_decl (VAR_DECL, get_identifier (buf), TABLE_TYPE);		\
+  DECL_EXTERNAL (decl) = 1;						\
+  TREE_STATIC (decl) = 1;						\
+  TREE_READONLY (decl) = 1;						\
+  TREE_CONSTANT (decl) = 1;						\
+  DECL_IGNORED_P (decl) = 1;						\
+  /* Mark the table as belonging to this class.  */			\
+  pushdecl (decl);							\
+  MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);				\
+  DECL_OWNER (decl) = TYPE;						\
+  sprintf (buf, #NAME "_syms_%s", typename);				\
+  TYPE_## TABLE ##_SYMS_DECL (TYPE) =					\
+    build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);	\
+  TREE_STATIC (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1;			\
+  TREE_CONSTANT (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1;		\
+  DECL_IGNORED_P (TYPE_## TABLE ##_SYMS_DECL (TYPE)) = 1;		\
+  pushdecl (TYPE_## TABLE ##_SYMS_DECL (TYPE));				\
+}									\
+while (0)
 
 /* Given a class, create the DECLs for all its associated indirect
    dispatch tables.  */
@@ -372,54 +402,14 @@ gen_indirect_dispatch_tables (tree type)
 
   if (flag_indirect_dispatch)
     {
-      {
-	char *buf = alloca (strlen (typename) + strlen ("_otable_syms_") + 1);
-
-	sprintf (buf, "_otable_%s", typename);
-	TYPE_OTABLE_DECL (type) = 
-	  build_decl (VAR_DECL, get_identifier (buf), otable_type);
-	DECL_EXTERNAL (TYPE_OTABLE_DECL (type)) = 1;
-	TREE_STATIC (TYPE_OTABLE_DECL (type)) = 1;
-	TREE_READONLY (TYPE_OTABLE_DECL (type)) = 1;
-	TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1;
-	DECL_IGNORED_P (TYPE_OTABLE_DECL (type)) = 1;
-	pushdecl (TYPE_OTABLE_DECL (type));  
-	sprintf (buf, "_otable_syms_%s", typename);
-	TYPE_OTABLE_SYMS_DECL (type) = 
-	  build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);
-	TREE_STATIC (TYPE_OTABLE_SYMS_DECL (type)) = 1;
-	TREE_CONSTANT (TYPE_OTABLE_SYMS_DECL (type)) = 1;
-	DECL_IGNORED_P(TYPE_OTABLE_SYMS_DECL (type)) = 1;
-	pushdecl (TYPE_OTABLE_SYMS_DECL (type));
-      }
-
-      {
-	char *buf = alloca (strlen (typename) + strlen ("_atable_syms_") + 1);
-	tree decl;
-
-	sprintf (buf, "_atable_%s", typename);
-	TYPE_ATABLE_DECL (type) = decl =
-	  build_decl (VAR_DECL, get_identifier (buf), atable_type);
-	DECL_EXTERNAL (decl) = 1;
-	TREE_STATIC (decl) = 1;
-	TREE_READONLY (decl) = 1;
-	TREE_CONSTANT (decl) = 1;
-	DECL_IGNORED_P (decl) = 1;
-	/* Mark the atable as belonging to this class.  */
-	pushdecl (decl);  
-	MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
-	DECL_OWNER (decl) = type;
-	sprintf (buf, "_atable_syms_%s", typename);
-	TYPE_ATABLE_SYMS_DECL (type) = 
-	  build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);
-	TREE_STATIC (TYPE_ATABLE_SYMS_DECL (type)) = 1;
-	TREE_CONSTANT (TYPE_ATABLE_SYMS_DECL (type)) = 1;
-	DECL_IGNORED_P (TYPE_ATABLE_SYMS_DECL (type)) = 1;
-	pushdecl (TYPE_ATABLE_SYMS_DECL (type));
-      }
+      GEN_TABLE (ATABLE, _atable, atable_type, type);
+      GEN_TABLE (OTABLE, _otable, otable_type, type);
+      GEN_TABLE (ITABLE, _itable, itable_type, type);
     }
 }
 
+#undef GEN_TABLE
+
 tree
 push_class (tree class_type, tree class_name)
 {
@@ -959,7 +949,7 @@ build_class_ref (tree type)
 	 we always emit this hard superclass reference.  */
       if  (flag_indirect_dispatch
 	   && type != output_class
-	   && type != CLASSTYPE_SUPER (output_class)
+// 	   && type != CLASSTYPE_SUPER (output_class)
 	   && TREE_CODE (type) == RECORD_TYPE)
 	return build_indirect_class_ref (type);
 
@@ -1062,8 +1052,7 @@ build_static_field_ref (tree fdecl)
      However, currently sometimes gcj is too eager and will end up
      returning the field itself, leading to an incorrect external
      reference being generated.  */
-  if ((is_compiled 
-       && (! flag_indirect_dispatch || current_class == fclass))
+  if ((is_compiled && !flag_indirect_dispatch)
       || (FIELD_FINAL (fdecl) && DECL_INITIAL (fdecl) != NULL_TREE
 	  && (JSTRING_TYPE_P (TREE_TYPE (fdecl))
 	      || JNUMERIC_TYPE_P (TREE_TYPE (fdecl)))
@@ -1084,16 +1073,19 @@ build_static_field_ref (tree fdecl)
 	= build_int_cst (NULL_TREE, get_symbol_table_index 
 			 (fdecl, &TYPE_ATABLE_METHODS (output_class)));
       tree field_address
-	= build4 (ARRAY_REF, build_pointer_type (TREE_TYPE (fdecl)), 
+	= build4 (ARRAY_REF, 
+		  TREE_TYPE (TREE_TYPE (TYPE_ATABLE_DECL (output_class))), 
 		  TYPE_ATABLE_DECL (output_class), table_index,
 		  NULL_TREE, NULL_TREE);
+      field_address = convert (build_pointer_type (TREE_TYPE (fdecl)),
+			       field_address);
       return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl), 
 			   field_address));
     }
   else  
     {
       /* Compile as:
-       * *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */
+       *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */
       tree ref = build_class_ref (fclass);
       tree fld;
       int field_index = 0;
@@ -1117,7 +1109,7 @@ build_static_field_ref (tree fdecl)
 			  ref, build_int_cst (NULL_TREE, field_index)));
       ref = build1 (INDIRECT_REF, field_type_node, ref);
       ref = build3 (COMPONENT_REF, field_info_union_node,
-		    ref, lookup_field (&field_type_node, info_ident),
+		    ref, lookup_field (&field_type_node, info_ident), 
 		    NULL_TREE);
       ref = build3 (COMPONENT_REF, ptr_type_node,
 		    ref, TREE_CHAIN (TYPE_FIELDS (field_info_union_node)),
@@ -1284,7 +1276,7 @@ make_field_value (tree fdecl)
 	      ? TREE_CHAIN (TYPE_FIELDS (field_info_union_node))
 	      : TYPE_FIELDS (field_info_union_node)),
 	     (FIELD_STATIC (fdecl)
-	      ? build_address_of (build_static_field_ref (fdecl))
+	      ? build_address_of (fdecl)
 	      : byte_position (fdecl)))));
 
   FINISH_RECORD_CONSTRUCTOR (finit);
@@ -1565,7 +1557,9 @@ make_class_data (tree type)
 
   /* Build Field array. */
   field = TYPE_FIELDS (type);
-  if (DECL_NAME (field) == NULL_TREE)
+  while (field && DECL_ARTIFICIAL (field))
+    field = TREE_CHAIN (field);  /* Skip dummy fields.  */
+  if (field && DECL_NAME (field) == NULL_TREE)
     field = TREE_CHAIN (field);  /* Skip dummy field for inherited data. */
   for ( ;  field != NULL_TREE;  field = TREE_CHAIN (field))
     {
@@ -1620,6 +1614,11 @@ make_class_data (tree type)
 	  && ! flag_keep_inline_functions
 	  && optimize)
 	continue;
+      /* Even if we have a decl, we don't necessaily have the code.
+	 This can happen if we inherit a method from a superclass for
+	 which we don't have a .class file.  */
+      if (METHOD_DUMMY (method))
+	continue;
       init = make_method_value (method);
       method_count++;
       methods = tree_cons (NULL_TREE, init, methods);
@@ -1663,10 +1662,8 @@ make_class_data (tree type)
   super = CLASSTYPE_SUPER (type);
   if (super == NULL_TREE)
     super = null_pointer_node;
-  else if (/* FIXME: we should also test for (!
-	      flag_indirect_dispatch) here, but libgcj can't cope with
-	      a symbolic reference a superclass in the class data.  */
-	   assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
+  else if (! flag_indirect_dispatch
+	   && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
 	   && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (super)))))
     super = build_class_ref (super);
   else
@@ -1721,13 +1718,19 @@ make_class_data (tree type)
 	= emit_symbol_table 
 	(DECL_NAME (TYPE_OTABLE_DECL (type)), 
 	 TYPE_OTABLE_DECL (type), TYPE_OTABLE_METHODS (type), 
-	 TYPE_OTABLE_SYMS_DECL (type), integer_type_node);
+	 TYPE_OTABLE_SYMS_DECL (type), integer_type_node, 1);
        
       TYPE_ATABLE_DECL (type) 
 	= emit_symbol_table 
 	(DECL_NAME (TYPE_ATABLE_DECL (type)), 
 	 TYPE_ATABLE_DECL (type), TYPE_ATABLE_METHODS (type), 
-	 TYPE_ATABLE_SYMS_DECL (type), ptr_type_node);
+	 TYPE_ATABLE_SYMS_DECL (type), ptr_type_node, 1);
+       
+      TYPE_ITABLE_DECL (type) 
+	= emit_symbol_table 
+	(DECL_NAME (TYPE_ITABLE_DECL (type)), 
+	 TYPE_ITABLE_DECL (type), TYPE_ITABLE_METHODS (type), 
+	 TYPE_ITABLE_SYMS_DECL (type), ptr_type_node, 2);
     }
   
   TYPE_CTABLE_DECL (type) = emit_catch_table (type);
@@ -1765,8 +1768,13 @@ make_class_data (tree type)
   PUSH_FIELD_VALUE (cons, "fields",
 		    fields_decl == NULL_TREE ? null_pointer_node
 		    : build1 (ADDR_EXPR, field_ptr_type_node, fields_decl));
-  PUSH_FIELD_VALUE (cons, "size_in_bytes", size_in_bytes (type));
-  PUSH_FIELD_VALUE (cons, "field_count",
+  /* If we're using the binary compatibility ABI we don't know the
+     size until load time.  */
+  PUSH_FIELD_VALUE (cons, "size_in_bytes", 
+		    (flag_indirect_dispatch 
+		     ? integer_minus_one_node 
+		     : size_in_bytes (type)));
+  PUSH_FIELD_VALUE (cons, "field_count", 
 		    build_int_cst (NULL_TREE, field_count));
   PUSH_FIELD_VALUE (cons, "static_field_count",
 		    build_int_cst (NULL_TREE, static_field_count));
@@ -1810,6 +1818,21 @@ make_class_data (tree type)
       TREE_CONSTANT (TYPE_ATABLE_DECL (type)) = 1;
       TREE_INVARIANT (TYPE_ATABLE_DECL (type)) = 1;
     }
+   if (TYPE_ITABLE_METHODS(type) == NULL_TREE)
+    {
+      PUSH_FIELD_VALUE (cons, "itable", null_pointer_node);
+      PUSH_FIELD_VALUE (cons, "itable_syms", null_pointer_node);
+    }
+  else
+    {
+      PUSH_FIELD_VALUE (cons, "itable",
+			build1 (ADDR_EXPR, itable_ptr_type, TYPE_ITABLE_DECL (type)));
+      PUSH_FIELD_VALUE (cons, "itable_syms",
+			build1 (ADDR_EXPR, symbols_array_ptr_type,
+				TYPE_ITABLE_SYMS_DECL (type)));
+      TREE_CONSTANT (TYPE_ITABLE_DECL (type)) = 1;
+      TREE_INVARIANT (TYPE_ITABLE_DECL (type)) = 1;
+    }
  
   PUSH_FIELD_VALUE (cons, "catch_classes",
 		    build1 (ADDR_EXPR, ptr_type_node, TYPE_CTABLE_DECL (type))); 
@@ -1817,7 +1840,13 @@ make_class_data (tree type)
   PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "interface_count",
 		    build_int_cst (NULL_TREE, interface_len));
-  PUSH_FIELD_VALUE (cons, "state", integer_zero_node);
+  PUSH_FIELD_VALUE 
+    (cons, "state",
+     convert (byte_type_node,
+	      build_int_cst (NULL_TREE,
+			     flag_indirect_dispatch
+			     ? JV_STATE_PRELOADING
+			     : JV_STATE_COMPILED)));
 
   PUSH_FIELD_VALUE (cons, "thread", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "depth", integer_zero_node);
@@ -1825,9 +1854,23 @@ make_class_data (tree type)
   PUSH_FIELD_VALUE (cons, "idt", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "arrayclass", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "protectionDomain", null_pointer_node);
+
+  {
+    tree assertion_table_ref;
+    if (TYPE_ASSERTIONS (type) == NULL)
+      assertion_table_ref = null_pointer_node;
+    else
+      assertion_table_ref = build1 (ADDR_EXPR, 
+				    build_pointer_type (assertion_table_type),
+				    emit_assertion_table (type));
+    
+    PUSH_FIELD_VALUE (cons, "assertion_table", assertion_table_ref);
+  }
+
   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);
 
@@ -1838,11 +1881,26 @@ make_class_data (tree type)
     DECL_ALIGN (decl) = 64; 
   
   rest_of_decl_compilation (decl, 1, 0);
+  
+  TYPE_OTABLE_DECL (type) = NULL_TREE;
+  TYPE_ATABLE_DECL (type) = NULL_TREE;
+  TYPE_CTABLE_DECL (type) = NULL_TREE;
 }
 
 void
 finish_class (void)
 {
+  if (TYPE_VERIFY_METHOD (output_class))
+    {
+      tree verify_method = TYPE_VERIFY_METHOD (output_class);
+      DECL_SAVED_TREE (verify_method) 
+	= add_stmt_to_compound (DECL_SAVED_TREE (verify_method), void_type_node,
+				build (RETURN_EXPR, void_type_node, NULL));
+      java_genericize (verify_method);
+      cgraph_finalize_function (verify_method, false);
+      TYPE_ASSERTIONS (current_class) = NULL;
+    }
+
   java_expand_catch_classes (current_class);
 
   current_function_decl = NULL_TREE;
@@ -2095,20 +2153,22 @@ layout_class (tree this_class)
   if (!CLASS_FROM_SOURCE_P (this_class))
     {
       int i;
-      
-      for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (this_class)) - 1; i > 0; i--)
+            if (TYPE_BINFO (this_class))
 	{
-	  tree binfo = BINFO_BASE_BINFO (TYPE_BINFO (this_class), i);
-	  tree super_interface = BINFO_TYPE (binfo);
-	  tree maybe_super_interface 
-	    = maybe_layout_super_class (super_interface, NULL_TREE);
-	  if (maybe_super_interface == NULL
-	      || TREE_CODE (TYPE_SIZE (maybe_super_interface)) == ERROR_MARK)
+	  for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (this_class)) - 1; i > 0; i--)
 	    {
-	      TYPE_SIZE (this_class) = error_mark_node;
-	      CLASS_BEING_LAIDOUT (this_class) = 0;
-	      class_list = TREE_CHAIN (class_list);
-	      return;
+	      tree binfo = BINFO_BASE_BINFO (TYPE_BINFO (this_class), i);
+	      tree super_interface = BINFO_TYPE (binfo);
+	      tree maybe_super_interface 
+		= maybe_layout_super_class (super_interface, NULL_TREE);
+	      if (maybe_super_interface == NULL
+		  || TREE_CODE (TYPE_SIZE (maybe_super_interface)) == ERROR_MARK)
+		{
+		  TYPE_SIZE (this_class) = error_mark_node;
+		  CLASS_BEING_LAIDOUT (this_class) = 0;
+		  class_list = TREE_CHAIN (class_list);
+		  return;
+		}
 	    }
 	}
     }
@@ -2124,8 +2184,11 @@ layout_class (tree this_class)
 static void
 add_miranda_methods (tree base_class, tree search_class)
 {
-  tree binfo, base_binfo;
   int i;
+  tree binfo, base_binfo;
+
+  if (!CLASS_PARSED_P (search_class))
+    load_class (search_class, 1);
   
   for (binfo = TYPE_BINFO (search_class), i = 1;
        BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
@@ -2133,6 +2196,11 @@ add_miranda_methods (tree base_class, tree search_class)
       tree method_decl;
       tree elt = BINFO_TYPE (base_binfo);
 
+      /* FIXME: This is totally bogus.  We should not be handling
+	 Miranda methods at all if we're using the BC ABI.  */
+      if (TYPE_DUMMY (elt))
+	continue;
+
       /* Ensure that interface methods are seen in declared order.  */
       if (!CLASS_LOADED_P (elt))
 	load_class (elt, 1);
@@ -2193,7 +2261,8 @@ layout_class_methods (tree this_class)
     dtable_count = integer_zero_node;
 
   type_name = TYPE_NAME (this_class);
-  if (CLASS_ABSTRACT (type_name) || CLASS_INTERFACE (type_name))
+  if (!flag_indirect_dispatch
+      && (CLASS_ABSTRACT (type_name) || CLASS_INTERFACE (type_name)))
     {
       /* An abstract class can have methods which are declared only in
 	 an implemented interface.  These are called "Miranda
@@ -2273,7 +2342,9 @@ layout_class_method (tree this_class, tree super_class,
       bool method_override = false;
       tree super_method = lookup_argument_method (super_class, method_name,
 						  method_sig);
-      if (super_method != NULL_TREE)
+      if (super_method != NULL_TREE
+	  && ! METHOD_DUMMY (super_method)
+	  && ! DECL_ARTIFICIAL (super_method))
         {
 	  method_override = true;
 	  if (! METHOD_PUBLIC (super_method) && 
@@ -2296,11 +2367,19 @@ layout_class_method (tree this_class, tree super_class,
 	    error ("%Jnon-static method '%D' overrides static method",
                    method_decl, method_decl);
 	}
-      else if (! METHOD_FINAL (method_decl)
-	       && ! METHOD_PRIVATE (method_decl)
-	       && ! CLASS_FINAL (TYPE_NAME (this_class))
+      else if (this_class == object_type_node
+	       && (METHOD_FINAL (method_decl)
+		   || METHOD_PRIVATE (method_decl)))
+	{
+	  /* We don't generate vtable entries for final Object
+	     methods.  This is simply to save space, since every
+	     object would otherwise have to define them.  */
+	}
+      else if (! METHOD_PRIVATE (method_decl)
 	       && dtable_count)
 	{
+	  /* We generate vtable entries for final methods because they
+	     may one day be changed to non-final.  */
 	  set_method_index (method_decl, dtable_count);
 	  dtable_count = fold (build2 (PLUS_EXPR, integer_type_node,
 				       dtable_count, integer_one_node));
@@ -2387,14 +2466,20 @@ static tree
 build_symbol_entry (tree decl)
 {
   tree clname, name, signature, sym;
-  
   clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
-  name = build_utf8_ref (DECL_NAME (decl));
+  /* ???  Constructors are given the name foo.foo all the way through
+     the compiler, but in the method table they're all renamed
+     foo.<init>.  So, we have to do the same here unless we want an
+     unresolved reference at runtime.  */
+  name = build_utf8_ref ((TREE_CODE (decl) == FUNCTION_DECL 
+			  && DECL_CONSTRUCTOR_P (decl))
+			 ? init_identifier_node
+			 : DECL_NAME (decl));
   signature = build_java_signature (TREE_TYPE (decl));
   signature = build_utf8_ref (unmangle_classname 
 			      (IDENTIFIER_POINTER (signature),
 			       IDENTIFIER_LENGTH (signature)));
-
+      
   START_RECORD_CONSTRUCTOR (sym, symbol_type);
   PUSH_FIELD_VALUE (sym, "clname", clname);
   PUSH_FIELD_VALUE (sym, "name", name);
@@ -2410,7 +2495,8 @@ build_symbol_entry (tree decl)
 
 tree
 emit_symbol_table (tree name, tree the_table, tree decl_list,
-                   tree the_syms_decl, tree the_array_element_type)
+                   tree the_syms_decl, tree the_array_element_type,
+		   int element_size)
 {
   tree method_list, method, table, list, null_symbol;
   tree table_size, the_array_type;
@@ -2457,7 +2543,8 @@ emit_symbol_table (tree name, tree the_table, tree decl_list,
      uninitialized static array of INDEX + 1 elements. The extra entry
      is used by the runtime to track whether the table has been
      initialized. */
-  table_size = build_index_type (build_int_cst (NULL_TREE, index));
+  table_size 
+    = build_index_type (build_int_cst (NULL_TREE, index * element_size + 1));
   the_array_type = build_array_type (the_array_element_type, table_size);
   the_table = build_decl (VAR_DECL, name, the_array_type);
   TREE_STATIC (the_table) = 1;
@@ -2467,7 +2554,7 @@ emit_symbol_table (tree name, tree the_table, tree decl_list,
   return the_table;
 }
 
-/* make an entry for the catch_classes list.  */
+/* Make an entry for the catch_classes list.  */
 tree
 make_catch_class_record (tree catch_class, tree classname)
 {
@@ -2512,7 +2599,95 @@ emit_catch_table (tree this_class)
   rest_of_decl_compilation (table, 1, 0);
   return table;
 }
- 
+
+/* Given a type, return the signature used by
+   _Jv_FindClassFromSignature() in libgcj.  This isn't exactly the
+   same as build_java_signature() because we want the canonical array
+   type.  */
+
+static tree
+build_signature_for_libgcj (tree type)
+{
+  tree sig, ref;
+
+  sig = build_java_signature (type);
+  ref = build_utf8_ref (unmangle_classname (IDENTIFIER_POINTER (sig),
+					    IDENTIFIER_LENGTH (sig)));
+  return ref;
+}
+
+/* Add an entry to the type assertion table. Callback used during hashtable
+   traversal.  */
+
+static int
+add_assertion_table_entry (void **htab_entry, void *ptr)
+{
+  tree entry;
+  tree code_val, op1_utf8, op2_utf8;
+  tree *list = (tree *) ptr;
+  type_assertion *as = (type_assertion *) *htab_entry;
+
+  code_val = build_int_cst (NULL_TREE, as->assertion_code);
+
+  if (as->op1 == NULL_TREE)
+    op1_utf8 = null_pointer_node;
+  else
+    op1_utf8 = build_signature_for_libgcj (as->op1);
+
+  if (as->op2 == NULL_TREE)
+    op2_utf8 = null_pointer_node;
+  else
+    op2_utf8 = build_signature_for_libgcj (as->op2);
+  
+  START_RECORD_CONSTRUCTOR (entry, assertion_entry_type);
+  PUSH_FIELD_VALUE (entry, "assertion_code", code_val);
+  PUSH_FIELD_VALUE (entry, "op1", op1_utf8);
+  PUSH_FIELD_VALUE (entry, "op2", op2_utf8);
+  FINISH_RECORD_CONSTRUCTOR (entry);
+  
+  *list = tree_cons (NULL_TREE, entry, *list);
+  return true;
+}
+
+/* Generate the type assertion table for CLASS, and return its DECL.  */
+
+static tree
+emit_assertion_table (tree class)
+{
+  tree null_entry, ctor, table_decl;
+  tree list = NULL_TREE;
+  htab_t assertions_htab = TYPE_ASSERTIONS (class);
+
+  /* Iterate through the hash table.  */
+  htab_traverse (assertions_htab, add_assertion_table_entry, &list);
+
+  /* Finish with a null entry.  */
+  START_RECORD_CONSTRUCTOR (null_entry, assertion_entry_type);
+  PUSH_FIELD_VALUE (null_entry, "assertion_code", integer_zero_node);
+  PUSH_FIELD_VALUE (null_entry, "op1", null_pointer_node);
+  PUSH_FIELD_VALUE (null_entry, "op2", null_pointer_node);
+  FINISH_RECORD_CONSTRUCTOR (null_entry);
+  
+  list = tree_cons (NULL_TREE, null_entry, list);
+  
+  /* Put the list in the right order and make it a constructor. */
+  list = nreverse (list);
+  ctor = build_constructor (assertion_table_type, list);
+
+  table_decl = build_decl (VAR_DECL, mangled_classname ("_type_assert_", class),
+			   assertion_table_type);
+
+  TREE_STATIC (table_decl) = 1;
+  TREE_READONLY (table_decl) = 1;
+  TREE_CONSTANT (table_decl) = 1;
+  DECL_IGNORED_P (table_decl) = 1;
+
+  DECL_INITIAL (table_decl) = ctor;
+  DECL_ARTIFICIAL (table_decl) = 1;
+  rest_of_decl_compilation (table_decl, 1, 0);
+
+  return table_decl;
+}
 
 void
 init_class_processing (void)
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index 47310220a2ff..54f788e0d7db 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -242,17 +242,44 @@ check_local_unnamed_variable (tree best, tree decl, tree type)
       || (INTEGRAL_TYPE_P (decl_type)
 	  && INTEGRAL_TYPE_P (type)
 	  && TYPE_PRECISION (decl_type) <= 32
-	    && TYPE_PRECISION (type) <= 32
+	  && TYPE_PRECISION (type) <= 32
 	  && TYPE_PRECISION (decl_type) >= TYPE_PRECISION (type))      
-	|| (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
-	    && type == ptr_type_node))
-      {
-	if (best == NULL_TREE
+      /*  ptr_type_node is used for null pointers, which are
+	  assignment compatible with everything.  */
+      || (TREE_CODE (decl_type) == POINTER_TYPE
+	  && type == ptr_type_node)
+      /* Whenever anyone wants to use a slot that is initially
+	 occupied by a PARM_DECL of pointer type they must get that
+	 decl, even if they asked for a pointer to a different type.
+	 However, if someone wants a scalar variable in a slot that
+	 initially held a pointer arg -- or vice versa -- we create a
+	 new VAR_DECL.  
+
+	 ???: As long as verification is correct, this will be a
+	 compatible type.  But maybe we should create a dummy vribale
+	 and replace all references to it with the DECL and a
+	 NOP_EXPR.
+      */
+      || (TREE_CODE (decl_type) == POINTER_TYPE
+	  && TREE_CODE (decl) == PARM_DECL
+	  && TREE_CODE (type) == POINTER_TYPE)
+
+      /* The new verifier requires a similar treatment in the
+	 situation where the parameter has an integral type which
+	 promotes to `int'.  */
+      || (flag_new_verifier
+	  && TREE_CODE (decl) == PARM_DECL
+	  && INTEGRAL_TYPE_P (decl_type)
+	  && TYPE_PRECISION (decl_type) <= 32
+	  && INTEGRAL_TYPE_P (type)
+	  && TYPE_PRECISION (type) <= 32))
+    {
+      if (best == NULL_TREE
 	  || (decl_type == type && TREE_TYPE (best) != type))
-	  return decl;
-      }
+	return decl;
+    }
 
-    return best;
+  return best;
 }
 
 
@@ -286,9 +313,9 @@ find_local_variable (int index, tree type, int pc ATTRIBUTE_UNUSED)
      variable that is used for every reference in that local variable
      slot.  */
   if (! decl)
-  {
-    char buf[64];
-    tree name;
+    {
+      char buf[64];
+      tree name;
       sprintf (buf, "#slot#%d#%d", index, uniq++);
       name = get_identifier (buf);
       decl = build_decl (VAR_DECL, name, type);
@@ -688,6 +715,11 @@ java_init_decl_processing (void)
   TYPE_NONALIASED_COMPONENT (atable_type) = 1;
   atable_ptr_type = build_pointer_type (atable_type);
 
+  itable_type = build_array_type (ptr_type_node, 
+				  one_elt_array_domain_type);
+  TYPE_NONALIASED_COMPONENT (itable_type) = 1;
+  itable_ptr_type = build_pointer_type (itable_type);
+
   symbol_type = make_node (RECORD_TYPE);
   PUSH_FIELD (symbol_type, field, "clname", utf8const_ptr_type);
   PUSH_FIELD (symbol_type, field, "name", utf8const_ptr_type);
@@ -698,6 +730,15 @@ java_init_decl_processing (void)
 					 one_elt_array_domain_type);
   symbols_array_ptr_type = build_pointer_type (symbols_array_type);
 
+  assertion_entry_type = make_node (RECORD_TYPE);
+  PUSH_FIELD (assertion_entry_type, field, "assertion_code", integer_type_node);
+  PUSH_FIELD (assertion_entry_type, field, "op1", utf8const_ptr_type);
+  PUSH_FIELD (assertion_entry_type, field, "op2", utf8const_ptr_type);
+  FINISH_RECORD (assertion_entry_type);
+  
+  assertion_table_type = build_array_type (assertion_entry_type,
+                                           one_elt_array_domain_type);
+
   /* As you're adding items here, please update the code right after
      this section, so that the filename containing the source code of
      the pre-defined class gets registered correctly. */
@@ -813,6 +854,9 @@ java_init_decl_processing (void)
   PUSH_FIELD (class_type_node, field, "atable", atable_ptr_type);
   PUSH_FIELD (class_type_node, field, "atable_syms", 
   	      symbols_array_ptr_type);
+  PUSH_FIELD (class_type_node, field, "itable", itable_ptr_type);
+  PUSH_FIELD (class_type_node, field, "itable_syms", 
+  	      symbols_array_ptr_type);
   PUSH_FIELD (class_type_node, field, "catch_classes", ptr_type_node);
   PUSH_FIELD (class_type_node, field, "interfaces",
 	      build_pointer_type (class_ptr_type));
@@ -825,9 +869,11 @@ java_init_decl_processing (void)
   PUSH_FIELD (class_type_node, field, "idt", ptr_type_node);  
   PUSH_FIELD (class_type_node, field, "arrayclass", ptr_type_node);  
   PUSH_FIELD (class_type_node, field, "protectionDomain", ptr_type_node);
+  PUSH_FIELD (class_type_node, field, "assertion_table", ptr_type_node);
   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);
@@ -993,8 +1039,14 @@ java_init_decl_processing (void)
     = builtin_function ("_Jv_LookupInterfaceMethodIdx",
 			build_function_type (ptr_type_node, t),
 			0, NOT_BUILT_IN, NULL, NULL_TREE);
-
   DECL_IS_PURE (soft_lookupinterfacemethod_node) = 1;
+  t = tree_cons (NULL_TREE, ptr_type_node,
+		 tree_cons (NULL_TREE, ptr_type_node,
+			    tree_cons (NULL_TREE, ptr_type_node, endlink)));
+  soft_lookupinterfacemethodbyname_node 
+    = builtin_function ("_Jv_LookupInterfaceMethod",
+			build_function_type (ptr_type_node, t),
+			0, NOT_BUILT_IN, NULL, NULL_TREE);
   t = tree_cons (NULL_TREE, object_ptr_type_node,
 		 tree_cons (NULL_TREE, ptr_type_node,
 			    tree_cons (NULL_TREE, ptr_type_node, 
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index deb75a9e7f9f..305ab5bdfee0 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -323,26 +323,63 @@ pop_type_0 (tree type, char **messagep)
   t = stack_type_map[--stack_pointer];
   if (type == NULL_TREE || t == type)
     return t;
+  if (TREE_CODE (t) == TREE_LIST)
+    {      
+      do
+	{
+	  tree tt = TREE_PURPOSE (t);
+	  if (! can_widen_reference_to (tt, type))
+	    {
+	      t = tt;
+	      goto fail;
+	    }
+	  t = TREE_CHAIN (t);
+	}
+      while (t);
+      return t;
+    }
   if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (t)
       && TYPE_PRECISION (type) <= 32 && TYPE_PRECISION (t) <= 32)
-      return t;
+    return t;
   if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (t) == POINTER_TYPE)
     {
-      if (type == ptr_type_node || type == object_ptr_type_node)
-	return t;
-      else if (t == ptr_type_node)  /* Special case for null reference. */
-	return type;
-      else if (can_widen_reference_to (t, type))
-	return t;
-      /* This is a kludge, but matches what Sun's verifier does.
-	 It can be tricked, but is safe as long as type errors
-	 (i.e. interface method calls) are caught at run-time. */
-      else if (CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (type))))
-	return object_ptr_type_node;
+      if (flag_new_verifier)
+	{
+	  /* Since the verifier has already run, we know that any
+	     types we see will be compatible.  In BC mode, this fact
+	     may be checked at runtime, but if that is so then we can
+	     assume its truth here as well.  So, we always succeed
+	     here, with the expected type.  */
+	  return type;
+	}
+      else
+	{
+	  if (type == ptr_type_node || type == object_ptr_type_node)
+	    return t;
+	  else if (t == ptr_type_node)  /* Special case for null reference. */
+	    return type;
+	  /* This is a kludge, but matches what Sun's verifier does.
+	     It can be tricked, but is safe as long as type errors
+	     (i.e. interface method calls) are caught at run-time. */
+	  else if (CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (type))))
+	    return object_ptr_type_node;
+	  else if (can_widen_reference_to (t, type))
+	    return t;
+	}
+    }
+
+  if (! flag_verify_invocations && flag_indirect_dispatch
+      && t == object_ptr_type_node)
+    {
+      if (type != ptr_type_node)
+	warning ("need to insert runtime check for %s", 
+		 xstrdup (lang_printable_name (type, 0)));
+      return type;
     }
 
   /* lang_printable_name uses a static buffer, so we must save the result
      from calling it the first time.  */
+ fail:
   {
     char *temp = xstrdup (lang_printable_name (type, 0));
     *messagep = concat ("expected type '", temp,
@@ -370,6 +407,68 @@ pop_type (tree type)
   return type;
 }
 
+
+/* Return true if two type assertions are equal.  */
+
+static int
+type_assertion_eq (const void * k1_p, const void * k2_p)
+{
+  type_assertion k1 = *(type_assertion *)k1_p;
+  type_assertion k2 = *(type_assertion *)k2_p;
+  return (k1.assertion_code == k2.assertion_code
+          && k1.op1 == k2.op1
+	  && k1.op2 == k2.op2);
+}
+
+/* Hash a type assertion.  */
+
+static hashval_t
+type_assertion_hash (const void *p)
+{
+  const type_assertion *k_p = p;
+  hashval_t hash = iterative_hash (&k_p->assertion_code, sizeof
+				   k_p->assertion_code, 0);
+  hash = iterative_hash (&k_p->op1, sizeof k_p->op1, hash);
+  return iterative_hash (&k_p->op2, sizeof k_p->op2, hash);
+}
+
+/* Add an entry to the type assertion table for the given class.  
+   CLASS is the class for which this assertion will be evaluated by the 
+   runtime during loading/initialization.
+   ASSERTION_CODE is the 'opcode' or type of this assertion: see java-tree.h.
+   OP1 and OP2 are the operands. The tree type of these arguments may be
+   specific to each assertion_code. */
+
+void
+add_type_assertion (tree class, int assertion_code, tree op1, tree op2)
+{
+  htab_t assertions_htab;
+  type_assertion as;
+  void **as_pp;
+
+  assertions_htab = TYPE_ASSERTIONS (class);
+  if (assertions_htab == NULL)
+    {
+      assertions_htab = htab_create_ggc (7, type_assertion_hash, 
+					 type_assertion_eq, NULL);
+      TYPE_ASSERTIONS (current_class) = assertions_htab;
+    }
+
+  as.assertion_code = assertion_code;
+  as.op1 = op1;
+  as.op2 = op2;
+
+  as_pp = htab_find_slot (assertions_htab, &as, true);
+
+  /* Don't add the same assertion twice.  */
+  if (*as_pp)
+    return;
+
+  *as_pp = ggc_alloc (sizeof (type_assertion));
+  **(type_assertion **)as_pp = as;
+}
+
+
 /* Return 1 if SOURCE_TYPE can be safely widened to TARGET_TYPE.
    Handles array types and interfaces.  */
 
@@ -387,6 +486,28 @@ can_widen_reference_to (tree source_type, tree target_type)
 
   if (source_type == target_type)
     return 1;
+
+  /* FIXME: This is very pessimistic, in that it checks everything,
+     even if we already know that the types are compatible.  If we're
+     to support full Java class loader semantics, we need this.
+     However, we could do something more optimal.  */
+  if (! flag_verify_invocations)
+    {
+      add_type_assertion (current_class, JV_ASSERT_TYPES_COMPATIBLE, 
+			  source_type, target_type);
+
+      if (!quiet_flag)
+       warning ("assert: %s is assign compatible with %s", 
+		xstrdup (lang_printable_name (target_type, 0)),
+		xstrdup (lang_printable_name (source_type, 0)));
+      /* Punt everything to runtime.  */
+      return 1;
+    }
+
+  if (TYPE_DUMMY (source_type) || TYPE_DUMMY (target_type))
+    {
+      return 1;
+    }
   else
     {
       if (TYPE_ARRAY_P (source_type) || TYPE_ARRAY_P (target_type))
@@ -420,7 +541,16 @@ can_widen_reference_to (tree source_type, tree target_type)
 	  int source_depth = class_depth (source_type);
 	  int target_depth = class_depth (target_type);
 
-	  /* class_depth can return a negative depth if an error occurred */
+	  if (TYPE_DUMMY (source_type) || TYPE_DUMMY (target_type))
+	    {
+	      if (! quiet_flag)
+		warning ("assert: %s is assign compatible with %s", 
+			 xstrdup (lang_printable_name (target_type, 0)),
+			 xstrdup (lang_printable_name (source_type, 0)));
+	      return 1;
+	    }
+
+ 	  /* class_depth can return a negative depth if an error occurred */
 	  if (source_depth < 0 || target_depth < 0)
 	    return 0;
 
@@ -687,13 +817,18 @@ build_java_array_length_access (tree node)
      throws a NullPointerException.  The only way we could get a node
      of type ptr_type_node at this point is `aconst_null; arraylength'
      or something equivalent.  */
-  if (type == ptr_type_node)
+  if (!flag_new_verifier && type == ptr_type_node)
     return build3 (CALL_EXPR, int_type_node, 
 		   build_address_of (soft_nullpointer_node),
 		   NULL_TREE, NULL_TREE);
 
   if (!is_array_type_p (type))
-    abort ();
+    {
+      /* With the new verifier, we will see an ordinary pointer type
+	 here.  In this case, we just use an arbitrary array type.  */
+      array_type = build_java_array_type (object_ptr_type_node, -1);
+      type = promote_type (array_type);
+    }
 
   length = java_array_type_length (type);
   if (length >= 0)
@@ -754,6 +889,13 @@ build_java_arrayaccess (tree array, tree type, tree index)
   tree ref;
   tree array_type = TREE_TYPE (TREE_TYPE (array));
 
+  if (!is_array_type_p (TREE_TYPE (array)))
+    {
+      /* With the new verifier, we will see an ordinary pointer type
+	 here.  In this case, we just use the correct array type.  */
+      array_type = build_java_array_type (type, -1);
+    }
+
   if (flag_bounds_check)
     {
       /* Generate:
@@ -803,11 +945,21 @@ build_java_arraystore_check (tree array, tree object)
   tree array_type_p = TREE_TYPE (array);
   tree object_type = TYPE_NAME (TREE_TYPE (TREE_TYPE (object)));
 
-  if (! is_array_type_p (array_type_p))
-    abort ();
+  if (! flag_verify_invocations)
+    {
+      /* With the new verifier, we don't track precise types.  FIXME:
+	 performance regression here.  */
+      element_type = TYPE_NAME (object_type_node);
+    }
+  else
+    {
+      if (! is_array_type_p (array_type_p))
+	abort ();
 
-  /* Get the TYPE_DECL for ARRAY's element type. */
-  element_type = TYPE_NAME (TREE_TYPE (TREE_TYPE (TREE_TYPE (array_type_p))));
+      /* Get the TYPE_DECL for ARRAY's element type. */
+      element_type
+	= TYPE_NAME (TREE_TYPE (TREE_TYPE (TREE_TYPE (array_type_p))));
+    }
 
   if (TREE_CODE (element_type) != TYPE_DECL   
       || TREE_CODE (object_type) != TYPE_DECL)
@@ -816,13 +968,14 @@ build_java_arraystore_check (tree array, tree object)
   if (!flag_store_check)
     return build1 (NOP_EXPR, array_type_p, array);
 
-  /* No check is needed if the element type is final or is itself an array.  
-     Also check that element_type matches object_type, since in the bytecode 
-     compilation case element_type may be the actual element type of the array
-     rather than its declared type. */
+  /* No check is needed if the element type is final.  Also check that
+     element_type matches object_type, since in the bytecode
+     compilation case element_type may be the actual element type of
+     the array rather than its declared type.  However, if we're doing
+     indirect dispatch, we can't do the `final' optimization.  */
   if (element_type == object_type
-      && (TYPE_ARRAY_P (TREE_TYPE (element_type))
-	  || CLASS_FINAL (element_type)))
+      && ! flag_indirect_dispatch
+      && CLASS_FINAL (element_type))
     return build1 (NOP_EXPR, array_type_p, array);
   
   /* OBJECT might be wrapped by a SAVE_EXPR. */
@@ -864,24 +1017,30 @@ build_java_arraystore_check (tree array, tree object)
    ARRAY_NODE. This function is used to retrieve something less vague than
    a pointer type when indexing the first dimension of something like [[<t>.
    May return a corrected type, if necessary, otherwise INDEXED_TYPE is
-   return unchanged.
-   As a side effect, it also makes sure that ARRAY_NODE is an array.  */
+   return unchanged.  */
 
 static tree
 build_java_check_indexed_type (tree array_node, tree indexed_type)
 {
   tree elt_type;
 
+  /* We used to check to see if ARRAY_NODE really had array type.
+     However, with the new verifier, this is not necessary, as we know
+     that the object will be an array of the appropriate type.  */
+
+  if (flag_new_verifier)
+    return indexed_type;
+
   if (!is_array_type_p (TREE_TYPE (array_node)))
     abort ();
 
   elt_type = (TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (array_node))));
 
-  if (indexed_type == ptr_type_node )
-      return promote_type (elt_type);
+  if (indexed_type == ptr_type_node)
+    return promote_type (elt_type);
 
   /* BYTE/BOOLEAN store and load are used for both type */
-  if (indexed_type == byte_type_node && elt_type == boolean_type_node )
+  if (indexed_type == byte_type_node && elt_type == boolean_type_node)
     return boolean_type_node;
 
   if (indexed_type != elt_type )
@@ -992,7 +1151,25 @@ expand_java_arraystore (tree rhs_type_node)
 				 && TYPE_PRECISION (rhs_type_node) <= 32) ? 
 				 int_type_node : rhs_type_node);
   tree index = pop_value (int_type_node);
-  tree array = pop_value (ptr_type_node);
+  tree array_type, array;
+
+  if (flag_new_verifier)
+    {
+      /* If we're processing an `aaload' we might as well just pick
+	 `Object'.  */
+      if (TREE_CODE (rhs_type_node) == POINTER_TYPE)
+	{
+	  array_type = build_java_array_type (object_ptr_type_node, -1);
+	  rhs_type_node = object_ptr_type_node;
+	}
+      else
+	array_type = build_java_array_type (rhs_type_node, -1);
+    }
+  else
+    array_type = ptr_type_node;
+  array = pop_value (array_type);
+  if (flag_new_verifier)
+    array = build1 (NOP_EXPR, promote_type (array_type), array);
 
   rhs_type_node    = build_java_check_indexed_type (array, rhs_type_node);
 
@@ -1019,25 +1196,45 @@ expand_java_arraystore (tree rhs_type_node)
 */
 
 static void
-expand_java_arrayload (tree lhs_type_node )
+expand_java_arrayload (tree lhs_type_node)
 {
   tree load_node;
   tree index_node = pop_value (int_type_node);
-  tree array_node = pop_value (ptr_type_node);
+  tree array_type;
+  tree array_node;
+
+  if (flag_new_verifier)
+    {
+      /* If we're processing an `aaload' we might as well just pick
+	 `Object'.  */
+      if (TREE_CODE (lhs_type_node) == POINTER_TYPE)
+	{
+	  array_type = build_java_array_type (object_ptr_type_node, -1);
+	  lhs_type_node = object_ptr_type_node;
+	}
+      else
+	array_type = build_java_array_type (lhs_type_node, -1);
+    }
+  else
+    array_type = ptr_type_node;
+  array_node = pop_value (array_type);
+  if (flag_new_verifier)
+    array_node = build1 (NOP_EXPR, promote_type (array_type), array_node);
 
   index_node = save_expr (index_node);
   array_node = save_expr (array_node);
-  
+
   if (TREE_TYPE (array_node) == ptr_type_node)
     /* The only way we could get a node of type ptr_type_node at this
        point is `aconst_null; arraylength' or something equivalent, so
-       unconditionally throw NullPointerException.  */    
+       unconditionally throw NullPointerException.  */
     load_node = build3 (CALL_EXPR, lhs_type_node, 
 			build_address_of (soft_nullpointer_node),
 			NULL_TREE, NULL_TREE);
   else
     {
-      lhs_type_node = build_java_check_indexed_type (array_node, lhs_type_node);
+      lhs_type_node = build_java_check_indexed_type (array_node,
+						     lhs_type_node);
       load_node = build_java_arrayaccess (array_node,
 					  lhs_type_node,
 					  index_node);
@@ -1156,6 +1353,19 @@ class_has_finalize_method (tree type)
     return HAS_FINALIZER_P (type) || class_has_finalize_method (super);
 }
 
+tree
+java_create_object (tree type)
+{
+  tree alloc_node = (class_has_finalize_method (type) 
+		     ? alloc_object_node
+		     : alloc_no_finalizer_node);
+  
+  return build (CALL_EXPR, promote_type (type),
+		build_address_of (alloc_node),
+		build_tree_list (NULL_TREE, build_class_ref (type)),
+		NULL_TREE);
+}
+
 static void
 expand_java_NEW (tree type)
 {
@@ -1221,7 +1431,8 @@ build_instanceof (tree value, tree type)
 	 we only need to check for `null'.  */
       expr = build2 (NE_EXPR, itype, value, null_pointer_node);
     }
-  else if (! TYPE_ARRAY_P (type)
+  else if (flag_verify_invocations
+	   && ! TYPE_ARRAY_P (type)
 	   && ! TYPE_ARRAY_P (valtype)
 	   && DECL_P (klass) && DECL_P (valclass)
 	   && ! CLASS_INTERFACE (valclass)
@@ -1292,7 +1503,7 @@ expand_iinc (unsigned int local_var_index, int ival, int pc)
   update_aliases (local_var, local_var_index, pc);
 }
 
-      
+
 tree
 build_java_soft_divmod (enum tree_code op, tree type, tree op1, tree op2)
 {
@@ -1529,12 +1740,13 @@ build_field_ref (tree self_value, tree self_class, tree name)
       tree base_type = promote_type (base_class);
       if (base_type != TREE_TYPE (self_value))
 	self_value = fold (build1 (NOP_EXPR, base_type, self_value));
-      if (flag_indirect_dispatch
-	  && output_class != self_class)
-	/* FIXME: output_class != self_class is not exactly the right
-	   test.  What we really want to know is whether self_class is
-	   in the same translation unit as output_class.  If it is,
-	   we can make a direct reference.  */
+      if (! flag_syntax_only
+	  && (flag_indirect_dispatch
+	      /* DECL_FIELD_OFFSET == 0 if we have no reference for
+		 the field, perhaps because we couldn't find the class
+		 in which the field is defined.  
+		 FIXME: We should investigate this.  */
+	      || DECL_FIELD_OFFSET (field_decl) == 0))
 	{
 	  tree otable_index
 	    = build_int_cst (NULL_TREE, get_symbol_table_index 
@@ -1696,29 +1908,6 @@ expand_java_add_case (tree switch_expr, int match, int target_pc)
   append_to_statement_list (x, &SWITCH_BODY (switch_expr));
 }
 
-#if 0
-static void
-expand_java_call (int target_pc, int return_address)
-{
-  tree target_label = lookup_label (target_pc);
-  tree value = build_int_cst (NULL_TREE, return_address);
-  push_value (value);
-  flush_quick_stack ();
-  expand_goto (target_label);
-}
-
-static void
-expand_java_ret (tree return_address ATTRIBUTE_UNUSED)
-{
-  warning ("ret instruction not implemented");
-#if 0
-  tree target_label = lookup_label (target_pc);
-  flush_quick_stack ();
-  expand_goto (target_label);
-#endif
-}
-#endif
-
 static tree
 pop_arguments (tree arg_types)
 {
@@ -1729,9 +1918,17 @@ pop_arguments (tree arg_types)
       tree tail = pop_arguments (TREE_CHAIN (arg_types));
       tree type = TREE_VALUE (arg_types);
       tree arg = pop_value (type);
-      if (targetm.calls.promote_prototypes (type)
-	  && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)
-	  && INTEGRAL_TYPE_P (type))
+
+      /* With the new verifier we simply cast each argument to its
+	 proper type.  This is needed since we lose type information
+	 coming out of the verifier.  We also have to do this with the
+	 old verifier when we pop an integer type that must be
+	 promoted for the function call.  */
+      if (flag_new_verifier && TREE_CODE (type) == POINTER_TYPE)
+	arg = build1 (NOP_EXPR, type, arg);
+      else if (targetm.calls.promote_prototypes (type)
+	       && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)
+	       && INTEGRAL_TYPE_P (type))
 	arg = convert (integer_type_node, arg);
       return tree_cons (NULL_TREE, arg, tail);
     }
@@ -1824,8 +2021,12 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED,
   tree func;
   if (is_compiled_class (self_type))
     {
-      if (!flag_indirect_dispatch
-	  || (!TREE_PUBLIC (method) && DECL_CONTEXT (method)))
+      /* With indirect dispatch we have to use indirect calls for all
+	 publically visible methods or gcc will use PLT indirections
+	 to reach them.  We also have to use indirect dispatch for all
+	 external methods.  */
+      if (! flag_indirect_dispatch 
+	  || (! DECL_EXTERNAL (method) && ! TREE_PUBLIC (method)))
 	{
 	  make_decl_rtl (method);
 	  func = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (method)),
@@ -1836,9 +2037,11 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED,
 	  tree table_index
 	    = build_int_cst (NULL_TREE, get_symbol_table_index 
 			     (method, &TYPE_ATABLE_METHODS (output_class)));
-	  func = build4 (ARRAY_REF,  method_ptr_type_node, 
-			 TYPE_ATABLE_DECL (output_class), table_index,
-			 NULL_TREE, NULL_TREE);
+	  func 
+	    = build4 (ARRAY_REF,  
+		      TREE_TYPE (TREE_TYPE (TYPE_ATABLE_DECL (output_class))),
+		      TYPE_ATABLE_DECL (output_class), table_index,
+		      NULL_TREE, NULL_TREE);
 	}
       func = convert (method_ptr_type_node, func);
     }
@@ -1899,9 +2102,9 @@ invoke_build_dtable (int is_invoke_interface, tree arg_list)
      argument is an array then get the dispatch table of the class
      Object rather than the one from the objectref.  */
   objectref = (is_invoke_interface 
-	       && is_array_type_p (TREE_TYPE (TREE_VALUE (arg_list))) ?
-	       object_type_node : TREE_VALUE (arg_list));
-  
+	       && is_array_type_p (TREE_TYPE (TREE_VALUE (arg_list)))
+	       ? build_class_ref (object_type_node) : TREE_VALUE (arg_list));
+
   if (dtable_ident == NULL_TREE)
     dtable_ident = get_identifier ("vtable");
   dtable = build_java_indirect_ref (object_type_node, objectref, 
@@ -1914,8 +2117,8 @@ invoke_build_dtable (int is_invoke_interface, tree arg_list)
 
 /* Determine the index in SYMBOL_TABLE for a reference to the decl
    T. If this decl has not been seen before, it will be added to the
-   otable_methods. If it has, the existing table slot will be
-   reused. */
+   [oa]table_methods. If it has, the existing table slot will be
+   reused.  */
 
 int
 get_symbol_table_index (tree t, tree *symbol_table)
@@ -1935,7 +2138,7 @@ get_symbol_table_index (tree t, tree *symbol_table)
     {
       tree value = TREE_VALUE (method_list);
       if (value == t)
-        return i;
+	return i;
       i++;
       if (TREE_CHAIN (method_list) == NULL_TREE)
         break;
@@ -1958,6 +2161,9 @@ build_invokevirtual (tree dtable, tree method)
 
   if (flag_indirect_dispatch)
     {
+      if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method))))
+	abort ();
+
       otable_index 
 	= build_int_cst (NULL_TREE, get_symbol_table_index 
 			 (method, &TYPE_OTABLE_METHODS (output_class)));
@@ -1997,11 +2203,8 @@ build_invokeinterface (tree dtable, tree method)
   tree lookup_arg;
   tree interface;
   tree idx;
-  tree otable_index;
 
-  /* We expand invokeinterface here.  _Jv_LookupInterfaceMethod() will
-     ensure that the selected method exists, is public and not
-     abstract nor static.  */
+  /* We expand invokeinterface here.  */
 	    
   if (class_ident == NULL_TREE)
     class_ident = get_identifier ("class");
@@ -2018,28 +2221,42 @@ build_invokeinterface (tree dtable, tree method)
   
   if (flag_indirect_dispatch)
     {
-      otable_index
-	= build_int_cst (NULL_TREE, get_symbol_table_index 
-			 (method, &TYPE_OTABLE_METHODS (output_class)));
-      idx = build4 (ARRAY_REF, integer_type_node,
-		    TYPE_OTABLE_DECL (output_class), otable_index,
-		    NULL_TREE, NULL_TREE);
+      int itable_index 
+	= 2 * (get_symbol_table_index 
+	       (method, &TYPE_ITABLE_METHODS (output_class)));
+      interface 
+	= build4 (ARRAY_REF, 
+		 TREE_TYPE (TREE_TYPE (TYPE_ITABLE_DECL (output_class))),
+		 TYPE_ITABLE_DECL (output_class), 
+		  build_int_cst (NULL_TREE, itable_index-1),
+		  NULL_TREE, NULL_TREE);
+      idx 
+	= build4 (ARRAY_REF, 
+		 TREE_TYPE (TREE_TYPE (TYPE_ITABLE_DECL (output_class))),
+		 TYPE_ITABLE_DECL (output_class), 
+		  build_int_cst (NULL_TREE, itable_index),
+		  NULL_TREE, NULL_TREE);
+      interface = convert (class_ptr_type, interface);
+      idx = convert (integer_type_node, idx);
     }
   else
-    idx = build_int_cst (NULL_TREE,
-			 get_interface_method_index (method, interface));
-
-  lookup_arg = tree_cons (NULL_TREE, dtable,
-                          tree_cons (NULL_TREE, build_class_ref (interface),
-			             build_tree_list (NULL_TREE, idx)));
+    {
+      idx = build_int_cst (NULL_TREE, 
+			   get_interface_method_index (method, interface));
+      interface = build_class_ref (interface);
+    }
 				     			  
+  lookup_arg = tree_cons (NULL_TREE, dtable,
+			  tree_cons (NULL_TREE, interface,
+				     build_tree_list (NULL_TREE, idx)));
+
   return build3 (CALL_EXPR, ptr_type_node, 
 		 build_address_of (soft_lookupinterfacemethod_node),
 		 lookup_arg, NULL_TREE);
 }
   
 /* Expand one of the invoke_* opcodes.
-   OCPODE is the specific opcode.
+   OPCODE is the specific opcode.
    METHOD_REF_INDEX is an index into the constant pool.
    NARGS is the number of arguments, or -1 if not specified. */
 
@@ -2048,7 +2265,8 @@ expand_invoke (int opcode, int method_ref_index, int nargs ATTRIBUTE_UNUSED)
 {
   tree method_signature
     = COMPONENT_REF_SIGNATURE(&current_jcf->cpool, method_ref_index);
-  tree method_name = COMPONENT_REF_NAME (&current_jcf->cpool, method_ref_index);
+  tree method_name = COMPONENT_REF_NAME (&current_jcf->cpool,
+					 method_ref_index);
   tree self_type
     = get_class_constant (current_jcf,
                           COMPONENT_REF_CLASS_INDEX(&current_jcf->cpool,
@@ -2071,38 +2289,82 @@ expand_invoke (int opcode, int method_ref_index, int nargs ATTRIBUTE_UNUSED)
     method = lookup_java_constructor (self_type, method_signature);
   else
     method = lookup_java_method (self_type, method_name, method_signature);
+
+  /* We've found a method in an interface, but this isn't an interface
+     call.  */
+  if (opcode != OPCODE_invokeinterface
+      && method
+      && (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method)))))
+    method = NULL_TREE;
+
+  /* We've found a non-interface method but we are making an
+     interface call.  This can happen if the interface overrides a
+     method in Object.  */
+  if (! flag_verify_invocations
+      && opcode == OPCODE_invokeinterface
+      && method
+      && ! CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method))))
+    method = NULL_TREE;
+
   if (method == NULL_TREE)
     {
-      error ("class '%s' has no method named '%s' matching signature '%s'",
-	     self_name,
-	     IDENTIFIER_POINTER (method_name),
-	     IDENTIFIER_POINTER (method_signature));
-    }
-  /* Invoke static can't invoke static/abstract method */
-  else if (opcode == OPCODE_invokestatic)
-    {
-      if (!METHOD_STATIC (method))
+      if (flag_verify_invocations || ! flag_indirect_dispatch)
 	{
-	  error ("invokestatic on non static method");
-	  method = NULL_TREE;
+	  error ("class '%s' has no method named '%s' matching signature '%s'",
+		 self_name,
+		 IDENTIFIER_POINTER (method_name),
+		 IDENTIFIER_POINTER (method_signature));
 	}
-      else if (METHOD_ABSTRACT (method))
+      else
 	{
-	  error ("invokestatic on abstract method");
-	  method = NULL_TREE;
+	  int flags = ACC_PUBLIC;
+	  if (opcode == OPCODE_invokestatic)
+	    flags |= ACC_STATIC;
+	  if (opcode == OPCODE_invokeinterface)
+	    {
+	      flags |= ACC_INTERFACE | ACC_ABSTRACT;
+	      CLASS_INTERFACE (TYPE_NAME (self_type)) = 1;
+	    }
+	  method = add_method (self_type, flags, method_name,
+			       method_signature);
+	  DECL_ARTIFICIAL (method) = 1;
+	  METHOD_DUMMY (method) = 1;
+	  layout_class_method (self_type, NULL,
+			       method, NULL);
 	}
     }
-  else
+
+  /* Invoke static can't invoke static/abstract method */
+  if (method != NULL_TREE)
     {
-      if (METHOD_STATIC (method))
+      if (opcode == OPCODE_invokestatic)
 	{
-	  error ("invoke[non-static] on static method");
-	  method = NULL_TREE;
+	  if (!METHOD_STATIC (method))
+	    {
+	      error ("invokestatic on non static method");
+	      method = NULL_TREE;
+	    }
+	  else if (METHOD_ABSTRACT (method))
+	    {
+	      error ("invokestatic on abstract method");
+	      method = NULL_TREE;
+	    }
+	}
+      else
+	{
+	  if (METHOD_STATIC (method))
+	    {
+	      error ("invoke[non-static] on static method");
+	      method = NULL_TREE;
+	    }
 	}
     }
 
   if (method == NULL_TREE)
     {
+      /* If we got here, we emitted an error message above.  So we
+	 just pop the arguments, push a properly-typed zero, and
+	 continue.  */
       method_type = get_type_from_signature (method_signature);
       pop_arguments (TYPE_ARG_TYPES (method_type));
       if (opcode != OPCODE_invokestatic) 
@@ -2385,6 +2647,7 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index)
   tree new_value = is_putting ? pop_value (field_type) : NULL_TREE;
   tree field_ref;
   int is_error = 0;
+  tree original_self_type = self_type;
   tree field_decl;
   
   if (! CLASS_LOADED_P (self_type))
@@ -2396,9 +2659,23 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index)
     }
   else if (field_decl == NULL_TREE)
     {
-      error ("missing field '%s' in '%s'",
-	     IDENTIFIER_POINTER (field_name), self_name);
-      is_error = 1;
+      if (! flag_verify_invocations)
+	{
+	  int flags = ACC_PUBLIC;
+	  if (is_static)
+	    flags |= ACC_STATIC;
+	  self_type = original_self_type;
+	  field_decl = add_field (original_self_type, field_name,
+				  field_type, flags); 
+	  DECL_ARTIFICIAL (field_decl) = 1;
+	  DECL_IGNORED_P (field_decl) = 1;
+	}
+      else
+	{      
+	  error ("missing field '%s' in '%s'",
+		 IDENTIFIER_POINTER (field_name), self_name);
+	  is_error = 1;
+      }
     }
   else if (build_java_signature (TREE_TYPE (field_decl)) != field_signature)
     {
@@ -2637,8 +2914,16 @@ expand_byte_code (JCF *jcf, tree method)
 	}
     }  
 
-  if (! verify_jvm_instructions (jcf, byte_ops, length))
-    return;
+  if (flag_new_verifier)
+    {
+      if (! verify_jvm_instructions_new (jcf, byte_ops, length))
+        return;
+    }
+  else
+    {
+      if (! verify_jvm_instructions (jcf, byte_ops, length))
+	return;
+    }
 
   /* Translate bytecodes.  */
   linenumber_pointer = linenumber_table;
@@ -2749,8 +3034,14 @@ process_jvm_instruction (int PC, const unsigned char* byte_ops,
      replace the top of the stack with the thrown object reference */
   if (instruction_bits [PC] & BCODE_EXCEPTION_TARGET)
     {
-      tree type = pop_type (ptr_type_node);
-      push_value (build_exception_object_ref (type));
+      /* Note that the new verifier will not emit a type map at all
+	 for dead exception handlers.  In this case we just ignore
+	 the situation.  */
+      if (! flag_new_verifier || (instruction_bits[PC] & BCODE_VERIFIED) != 0)
+	{
+	  tree type = pop_type (promote_type (throwable_type_node));
+	  push_value (build_exception_object_ref (type));
+	}
     }
 
   switch (byte_ops[PC++])
diff --git a/gcc/java/gcj.texi b/gcc/java/gcj.texi
index 1ef0babb4c0f..370585a7affc 100644
--- a/gcc/java/gcj.texi
+++ b/gcc/java/gcj.texi
@@ -873,7 +873,7 @@ gij [@option{-jar}] [@option{OPTION}] @dots{} @var{CLASS} [@var{ARGS}@dots{}]
   [@option{-cp} @var{path}] [@option{-classpath} @var{path}]
   [@option{-D}@var{name}[=@var{value}]@dots{}]
   [@option{-ms=}@var{number}] [@option{-mx=}@var{number}]
-  [@option{-X@var{argument}]
+  [@option{-X@var{argument}}] [@option{-verbose}] [@option{-verbose:class}]
   [@option{--showversion}] [@option{--version}] [@option{--help}][@option{-?}]
 @c man end
 @c man begin SEEALSO gij
@@ -954,7 +954,8 @@ Print version number and continue.
 @item --version
 Print version number, then exit.
 
-@item -verbose:class
+@item -verbose
+@itemx -verbose:class
 Each time a class is initialized, print a short message on standard error.
 @end table
 
@@ -2385,6 +2386,24 @@ property is set to @samp{cache}, then any failed lookups are cached
 and not tried again.  If this property is set to @samp{never}, then
 lookups are never done.  For more information, @xref{Extensions}.
 
+@item gnu.gcj.jit.compiler
+@c FIXME we should probably have a whole node on this...
+This is the full path to @command{gcj} executable which should be
+used to compile classes just-in-time when
+@code{ClassLoader.defineClass} is called.  If not set, @command{gcj}
+will not be invoked by the runtime; this can also be controlled via
+@code{Compiler.disable}.
+
+@item gnu.gcj.jit.options
+This is a space-separated string of options which should be passed to
+@command{gcj} when in JIT mode.  If not set, a sensible default is
+chosen.
+
+@item gnu.gcj.jit.cachedir
+This is the directory where cached shared library files are
+stored.  If not set, JIT compilation is disabled.  This should never
+be set to a directory that is writable by any other user.
+
 @end table
 
 
diff --git a/gcc/java/gjavah.c b/gcc/java/gjavah.c
index abf75c4dc69d..0badaf198295 100644
--- a/gcc/java/gjavah.c
+++ b/gcc/java/gjavah.c
@@ -112,6 +112,9 @@ static JCF_u2 last_access;
 #define METHOD_IS_NATIVE(Method) \
    ((Method) & ACC_NATIVE)
 
+#define METHOD_IS_PRIVATE(Class, Method) \
+  (((Method) & ACC_PRIVATE) != 0)
+
 /* We keep a linked list of all method names we have seen.  This lets
    us determine if a method name and a field name are in conflict.  */
 struct method_name
@@ -937,7 +940,7 @@ print_method_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
       fputs ("  ", out);
       if ((flags & ACC_STATIC))
 	fputs ("static ", out);
-      else if (! METHOD_IS_FINAL (jcf->access_flags, flags))
+      else if (! METHOD_IS_PRIVATE (jcf->access_flags, flags))
 	{
 	  /* Don't print `virtual' if we have a constructor.  */
 	  if (! is_init)
diff --git a/gcc/java/java-except.h b/gcc/java/java-except.h
index 3aa5e0105ef2..45e4f0aa8e94 100644
--- a/gcc/java/java-except.h
+++ b/gcc/java/java-except.h
@@ -53,6 +53,8 @@ struct eh_range
 
     /* The TRY_CATCH_EXPR for this EH range.  */
     tree stmt;
+
+    tree handler;
   };
 
 /* A dummy range that represents the entire method. */
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index 558d0f50cc66..e8144ee908c2 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -227,6 +227,9 @@ extern int flag_indirect_dispatch;
 /* When zero, don't generate runtime array store checks. */
 extern int flag_store_check;
 
+/* When nonzero, use the new bytecode verifier.  */
+extern int flag_new_verifier;
+
 /* Encoding used for source files.  */
 extern const char *current_encoding;
 
@@ -237,6 +240,8 @@ extern GTY(()) struct JCF * current_jcf;
    before static field references.  */
 extern int always_initialize_class_p;
 
+extern int flag_verify_invocations;
+
 typedef struct CPool constant_pool;
 
 #define CONSTANT_ResolvedFlag 16
@@ -367,9 +372,13 @@ enum java_tree_index
   JTI_OTABLE_PTR_TYPE,
   JTI_ATABLE_TYPE,
   JTI_ATABLE_PTR_TYPE,
+  JTI_ITABLE_TYPE,
+  JTI_ITABLE_PTR_TYPE,
   JTI_SYMBOL_TYPE,
   JTI_SYMBOLS_ARRAY_TYPE,
   JTI_SYMBOLS_ARRAY_PTR_TYPE,
+  JTI_ASSERTION_ENTRY_TYPE,
+  JTI_ASSERTION_TABLE_TYPE,
 
   JTI_END_PARAMS_NODE,
 
@@ -388,6 +397,7 @@ enum java_tree_index
   JTI_SOFT_MONITORENTER_NODE,
   JTI_SOFT_MONITOREXIT_NODE,
   JTI_SOFT_LOOKUPINTERFACEMETHOD_NODE,
+  JTI_SOFT_LOOKUPINTERFACEMETHODBYNAME_NODE,
   JTI_SOFT_LOOKUPJNIMETHOD_NODE,
   JTI_SOFT_GETJNIENVNEWFRAME_NODE,
   JTI_SOFT_JNIPOPSYSTEMFRAME_NODE,
@@ -597,18 +607,24 @@ extern GTY(()) tree java_global_trees[JTI_MAX];
   java_global_trees[JTI_OTABLE_TYPE]
 #define atable_type \
   java_global_trees[JTI_ATABLE_TYPE]
+#define itable_type \
+  java_global_trees[JTI_ITABLE_TYPE]
 #define otable_ptr_type \
   java_global_trees[JTI_OTABLE_PTR_TYPE]
 #define atable_ptr_type \
   java_global_trees[JTI_ATABLE_PTR_TYPE]
+#define itable_ptr_type \
+  java_global_trees[JTI_ITABLE_PTR_TYPE]
 #define symbol_type \
   java_global_trees[JTI_SYMBOL_TYPE]
 #define symbols_array_type \
   java_global_trees[JTI_SYMBOLS_ARRAY_TYPE]
 #define symbols_array_ptr_type \
-  java_global_trees[JTI_SYMBOLS_ARRAY_PTR_TYPE]
-#define class_refs_decl \
-  Jjava_global_trees[TI_CLASS_REFS_DECL]
+  java_global_trees[JTI_SYMBOLS_ARRAY_PTR_TYPE]  
+#define assertion_entry_type \
+  java_global_trees[JTI_ASSERTION_ENTRY_TYPE]
+#define assertion_table_type \
+  java_global_trees[JTI_ASSERTION_TABLE_TYPE]
 
 #define end_params_node \
   java_global_trees[JTI_END_PARAMS_NODE]
@@ -644,6 +660,8 @@ extern GTY(()) tree java_global_trees[JTI_MAX];
   java_global_trees[JTI_SOFT_MONITOREXIT_NODE]
 #define soft_lookupinterfacemethod_node \
   java_global_trees[JTI_SOFT_LOOKUPINTERFACEMETHOD_NODE]
+#define soft_lookupinterfacemethodbyname_node \
+  java_global_trees[JTI_SOFT_LOOKUPINTERFACEMETHODBYNAME_NODE]
 #define soft_lookupjnimethod_node \
   java_global_trees[JTI_SOFT_LOOKUPJNIMETHOD_NODE]
 #define soft_getjnienvnewframe_node \
@@ -984,6 +1002,7 @@ struct lang_decl_func GTY(())
   unsigned int invisible : 1;	/* Set for methods we generate
 				   internally but which shouldn't be
 				   written to the .class file.  */
+  unsigned int dummy:1;		
 };
 
 struct treetreehash_entry GTY(())
@@ -992,6 +1011,22 @@ struct treetreehash_entry GTY(())
   tree value;
 };
 
+/* These represent the possible assertion_code's that can be emitted in the
+   type assertion table.  */
+enum
+{
+  JV_ASSERT_END_OF_TABLE = 0,     /* Last entry in table.  */
+  JV_ASSERT_TYPES_COMPATIBLE = 1, /* Operand A is assignable to Operand B.  */
+  JV_ASSERT_IS_INSTANTIABLE = 2   /* Operand A is an instantiable class.  */
+};
+
+typedef struct type_assertion GTY(())
+{
+  int assertion_code; /* 'opcode' for the type of this assertion. */
+  tree op1;           /* First operand. */
+  tree op2;           /* Second operand. */
+} type_assertion;
+
 extern tree java_treetreehash_find (htab_t, tree);
 extern tree * java_treetreehash_new (htab_t, tree);
 extern htab_t java_treetreehash_create (size_t size, int ggc);
@@ -1043,6 +1078,9 @@ struct lang_decl GTY(())
 #define TYPE_II_STMT_LIST(T)     (TYPE_LANG_SPECIFIC (T)->ii_block)
 /* The decl of the synthetic method `class$' used to handle `.class'
    for non primitive types when compiling to bytecode. */
+
+#define TYPE_DUMMY(T)		(TYPE_LANG_SPECIFIC(T)->dummy_class)
+
 #define TYPE_DOT_CLASS(T)        (TYPE_LANG_SPECIFIC (T)->dot_class)
 #define TYPE_PACKAGE_LIST(T)     (TYPE_LANG_SPECIFIC (T)->package_list)
 #define TYPE_IMPORT_LIST(T)      (TYPE_LANG_SPECIFIC (T)->import_list)
@@ -1060,10 +1098,16 @@ struct lang_decl GTY(())
 #define TYPE_OTABLE_SYMS_DECL(T) (TYPE_LANG_SPECIFIC (T)->otable_syms_decl)
 #define TYPE_OTABLE_DECL(T)      (TYPE_LANG_SPECIFIC (T)->otable_decl)
 
+#define TYPE_ITABLE_METHODS(T)   (TYPE_LANG_SPECIFIC (T)->itable_methods)
+#define TYPE_ITABLE_SYMS_DECL(T) (TYPE_LANG_SPECIFIC (T)->itable_syms_decl)
+#define TYPE_ITABLE_DECL(T)      (TYPE_LANG_SPECIFIC (T)->itable_decl)
+
 #define TYPE_CTABLE_DECL(T)      (TYPE_LANG_SPECIFIC (T)->ctable_decl)
 #define TYPE_CATCH_CLASSES(T)    (TYPE_LANG_SPECIFIC (T)->catch_classes)
+#define TYPE_VERIFY_METHOD(T)    (TYPE_LANG_SPECIFIC (T)->verify_method)
 
 #define TYPE_TO_RUNTIME_MAP(T)   (TYPE_LANG_SPECIFIC (T)->type_to_runtime_map)
+#define TYPE_ASSERTIONS(T)   	 (TYPE_LANG_SPECIFIC (T)->type_assertions)
 
 struct lang_type GTY(())
 {
@@ -1092,18 +1136,31 @@ struct lang_type GTY(())
   tree atable_decl;		/* The static address table.  */
   tree atable_syms_decl;
 
+  tree itable_methods;          /* List of interfaces methods referred
+				   to by this class.  */
+  tree itable_decl;		/* The interfaces table.  */
+  tree itable_syms_decl;
+
   tree ctable_decl;             /* The table of classes for the runtime
 				   type matcher.  */
   tree catch_classes;
 
+  tree verify_method;		/* The verify method for this class.
+				   Used in split verification.  */
+
   htab_t GTY ((param_is (struct treetreehash_entry))) type_to_runtime_map;   
                                 /* The mapping of classes to exception region
 				   markers.  */
 
+  htab_t GTY ((param_is (struct type_assertion))) type_assertions;
+				/* Table of type assertions to be evaluated 
+  				   by the runtime when this class is loaded. */
+
   unsigned pic:1;		/* Private Inner Class. */
   unsigned poic:1;		/* Protected Inner Class. */
   unsigned strictfp:1;		/* `strictfp' class.  */
   unsigned assertions:1;	/* Any method uses `assert'.  */
+  unsigned dummy_class:1;		/* Not a real class, just a placeholder.  */
 };
 
 #define JCF_u4 unsigned long
@@ -1243,7 +1300,7 @@ extern void make_class_data (tree);
 extern void register_class (void);
 extern int alloc_name_constant (int, tree);
 extern void emit_register_classes (tree *);
-extern tree emit_symbol_table (tree, tree, tree, tree, tree);
+extern tree emit_symbol_table (tree, tree, tree, tree, tree, int);
 extern void lang_init_source (int);
 extern void write_classfile (tree);
 extern char *print_int_node (tree);
@@ -1259,9 +1316,12 @@ extern int alloc_class_constant (tree);
 extern void init_expr_processing (void);
 extern void push_super_field (tree, tree);
 extern void init_class_processing (void);
+extern void add_type_assertion (tree, int, tree, tree);
 extern int can_widen_reference_to (tree, tree);
 extern int class_depth (tree);
 extern int verify_jvm_instructions (struct JCF *, const unsigned char *, long);
+extern int verify_jvm_instructions_new (struct JCF *, const unsigned char *,
+					long);
 extern void maybe_pushlevels (int);
 extern void maybe_poplevels (int);
 extern void force_poplevels (int);
@@ -1274,6 +1334,7 @@ extern void push_type (tree);
 extern void load_type_state (tree);
 extern void add_interface (tree, tree);
 extern tree force_evaluation_order (tree);
+extern tree java_create_object (tree);
 extern int verify_constant_pool (struct JCF *);
 extern void start_java_method (tree);
 extern void end_java_method (void);
@@ -1321,7 +1382,6 @@ extern tree java_mangle_decl (struct obstack *, tree);
 extern tree java_mangle_class_field (struct obstack *, tree);
 extern tree java_mangle_class_field_from_string (struct obstack *, char *);
 extern tree java_mangle_vtable (struct obstack *, tree);
-extern const char *lang_printable_name_wls (tree, int);
 extern void append_gpp_mangled_name (const char *, int);
 
 extern void add_predefined_file (tree);
@@ -1363,6 +1423,8 @@ extern tree builtin_function (const char *, tree, int, enum built_in_class,
 
 /* Access flags etc for a method (a FUNCTION_DECL): */
 
+#define METHOD_DUMMY(DECL) (DECL_LANG_SPECIFIC (DECL)->u.f.dummy)
+
 #define METHOD_PUBLIC(DECL) DECL_LANG_FLAG_1 (FUNCTION_DECL_CHECK (DECL))
 #define METHOD_PRIVATE(DECL) TREE_PRIVATE (FUNCTION_DECL_CHECK (DECL))
 #define METHOD_PROTECTED(DECL) TREE_PROTECTED (FUNCTION_DECL_CHECK (DECL))
@@ -1800,7 +1862,8 @@ enum
 
   JV_STATE_PRELOADING = 1,	/* Can do _Jv_FindClass.  */
   JV_STATE_LOADING = 3,		/* Has super installed.  */
-  JV_STATE_LOADED = 5,		/* Is complete.  */
+  JV_STATE_READ = 4,		/* Has been completely defined.  */
+  JV_STATE_LOADED = 5,		/* Has Miranda methods defined.  */
 
   JV_STATE_COMPILED = 6,	/* This was a compiled class.  */
 
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index f04b9f958d91..a7cd57a6d77a 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -610,8 +610,14 @@ void
 load_class (tree class_or_name, int verbose)
 {
   tree name, saved;
-  int class_loaded;
-  tree class_decl;
+  int class_loaded = 0;
+  tree class_decl = NULL_TREE;
+  bool is_compiled_class = false;
+
+  /* We've already failed, don't try again.  */
+  if (TREE_CODE (class_or_name) == RECORD_TYPE
+      && TYPE_DUMMY (class_or_name))
+    return;
 
   /* class_or_name can be the name of the class we want to load */
   if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
@@ -624,41 +630,99 @@ load_class (tree class_or_name, int verbose)
   else
     name = DECL_NAME (TYPE_NAME (class_or_name));
 
+  class_decl = IDENTIFIER_CLASS_VALUE (name);
+  if (class_decl != NULL_TREE)
+    {
+      tree type = TREE_TYPE (class_decl);
+      is_compiled_class
+	= ((TYPE_JCF (type) && JCF_SEEN_IN_ZIP (TYPE_JCF (type)))
+	   || CLASS_FROM_CURRENTLY_COMPILED_P (type));
+    }
+
   /* If the class is from source code, then it must already be loaded.  */
   class_decl = IDENTIFIER_CLASS_VALUE (name);
   if (class_decl && CLASS_FROM_SOURCE_P (TREE_TYPE (class_decl)))
     return;
 
   saved = name;
-  while (1)
+  
+  /* If flag_verify_invocations is unset, we don't try to load a class
+     unless we're looking for Object (which is fixed by the ABI) or
+     it's a class that we're going to compile.  */
+  if (flag_verify_invocations
+      || class_or_name == object_type_node
+      || is_compiled_class
+      || TREE_CODE (class_or_name) == IDENTIFIER_NODE)
     {
-      char *separator;
+      while (1)
+	{
+	  char *separator;
 
-      if ((class_loaded = read_class (name)))
-	break;
+	  /* We've already loaded it.  */
+	  if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE)
+	    {
+	      tree tmp_decl = IDENTIFIER_CLASS_VALUE (name);
+	      if (CLASS_PARSED_P (TREE_TYPE (tmp_decl)))
+		break;
+	    }
+	
+	  if (read_class (name))
+	    break;
 
-      /* We failed loading name. Now consider that we might be looking
-	 for a inner class. */
-      if ((separator = strrchr (IDENTIFIER_POINTER (name), '$'))
-	  || (separator = strrchr (IDENTIFIER_POINTER (name), '.')))
-	{
-	  int c = *separator;
-	  *separator = '\0';
-	  name = get_identifier (IDENTIFIER_POINTER (name));
-	  *separator = c;
-
-	  /* Otherwise we might get infinite recursion, if say we have
-	     String.class but not String$CaseInsensitiveComparator.class. */
-	  if (current_jcf && current_jcf->java_source == 0)
+	  /* We failed loading name. Now consider that we might be looking
+	     for a inner class. */
+	  if ((separator = strrchr (IDENTIFIER_POINTER (name), '$'))
+	      || (separator = strrchr (IDENTIFIER_POINTER (name), '.')))
+	    {
+	      int c = *separator;
+	      *separator = '\0';
+	      name = get_identifier (IDENTIFIER_POINTER (name));
+	      *separator = c;
+
+	      /* Otherwise we might get infinite recursion, if say we
+		 have String.class but not
+		 String$CaseInsensitiveComparator.class. */
+	      if (current_jcf && current_jcf->java_source == 0)
+		break;
+	    }
+	  /* Otherwise, we failed, we bail. */
+	  else
 	    break;
 	}
-      /* Otherwise, we failed, we bail. */
-      else
-	break;
-    }
 
-  if (!class_loaded && verbose)
-    error ("cannot find file for class %s", IDENTIFIER_POINTER (saved));
+      {
+	/* have we found the class we're looking for?  */
+	tree type_decl = IDENTIFIER_CLASS_VALUE (saved);
+	tree type = type_decl ? TREE_TYPE (type_decl) : NULL;
+	class_loaded = type && CLASS_PARSED_P (type);
+      }	      
+    }
+  
+  if (!class_loaded)
+    {
+      if (flag_verify_invocations || ! flag_indirect_dispatch
+	  || flag_emit_class_files)
+	{
+	  if (verbose)
+	    error ("cannot find file for class %s", IDENTIFIER_POINTER (saved));
+	}
+      else if (verbose)
+	{
+	  /* This is just a diagnostic during testing, not a real problem.  */
+	  if (!quiet_flag)
+	    warning("cannot find file for class %s", 
+		    IDENTIFIER_POINTER (saved));
+	  
+	  /* Fake it.  */
+	  if (TREE_CODE (class_or_name) == RECORD_TYPE)
+	    {
+	      set_super_info (0, class_or_name, object_type_node, 0);
+	      TYPE_DUMMY (class_or_name) = 1;
+	      /* We won't be able to output any debug info for this class.  */
+	      DECL_IGNORED_P (TYPE_NAME (class_or_name)) = 1;
+	    }
+	}
+    }
 }
 
 /* Parse the .class file JCF. */
@@ -760,6 +824,7 @@ parse_class_file (void)
   java_layout_seen_class_methods ();
 
   input_location = DECL_SOURCE_LOCATION (TYPE_NAME (current_class));
+  file_start_location = input_location;
   (*debug_hooks->start_source_file) (input_line, input_filename);
 
   /* Currently we always have to emit calls to _Jv_InitClass when
@@ -775,7 +840,7 @@ parse_class_file (void)
     {
       JCF *jcf = current_jcf;
 
-      if (METHOD_ABSTRACT (method))
+      if (METHOD_ABSTRACT (method) || METHOD_DUMMY (method))
 	continue;
 
       if (METHOD_NATIVE (method))
@@ -911,6 +976,7 @@ static void
 parse_source_file_2 (void)
 {
   int save_error_count = java_error_count;
+  flag_verify_invocations = true;
   java_complete_class ();	    /* Parse unsatisfied class decl. */
   java_parse_abort_on_error ();
 }
@@ -1196,7 +1262,12 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
       input_location = DECL_SOURCE_LOCATION (node);
       if (CLASS_FILE_P (node))
 	{
+	  /* FIXME: These two flags really should be independent.  We
+	     should be able to compile fully binary compatible, but
+	     with flag_verify_invocations on.  */
+	  flag_verify_invocations = ! flag_indirect_dispatch;
 	  output_class = current_class = TREE_TYPE (node);
+
 	  current_jcf = TYPE_JCF (current_class);
 	  layout_class (current_class);
 	  load_inner_classes (current_class);
@@ -1232,13 +1303,15 @@ compute_class_name (struct ZipDirectory *zdir)
   char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
   char *class_name;
   int i;
-  int filename_length;
+  int filename_length = zdir->filename_length;
 
-  while (strncmp (class_name_in_zip_dir, "./", 2) == 0)
-    class_name_in_zip_dir += 2;
+  while (filename_length > 2 && strncmp (class_name_in_zip_dir, "./", 2) == 0)
+    {
+      class_name_in_zip_dir += 2;
+      filename_length -= 2;
+    }
 
-  filename_length = (strlen (class_name_in_zip_dir)
-		     - strlen (".class"));
+  filename_length -= strlen (".class");
   class_name = ALLOC (filename_length + 1);
   memcpy (class_name, class_name_in_zip_dir, filename_length);
   class_name [filename_length] = '\0';
@@ -1300,6 +1373,13 @@ parse_zip_file_entries (void)
 	    current_jcf = TYPE_JCF (class);
 	    output_class = current_class = class;
 
+	    if (TYPE_DUMMY (class))
+	      {
+		/* This is a dummy class, and now we're compiling it
+		   for real.  */
+		abort ();
+	      }
+
 	    /* This is for a corner case where we have a superclass
 	       but no superclass fields.  
 
diff --git a/gcc/java/jvspec.c b/gcc/java/jvspec.c
index 940cd8c9fff6..a3e8c6fd317a 100644
--- a/gcc/java/jvspec.c
+++ b/gcc/java/jvspec.c
@@ -68,7 +68,7 @@ static const char jvgenmain_spec[] =
 		   %<fcompile-resource* %<fassert %<fno-assert \
 		   %<femit-class-file %<femit-class-files %<fencoding*\
 		   %<fuse-boehm-gc %<fhash-synchronization %<fjni\
-		   %<findirect-dispatch \
+		   %<findirect-dispatch %<fnew-verifier\
 		   %<fno-store-check %<foutput-class-dir\
 		   %<fclasspath* %<fCLASSPATH* %<fbootclasspath*\
 		   %<fextdirs*\
diff --git a/gcc/java/lang.c b/gcc/java/lang.c
index be789fe53818..bcf4e45b4bb9 100644
--- a/gcc/java/lang.c
+++ b/gcc/java/lang.c
@@ -128,6 +128,17 @@ int flag_wall = 0;
 /* The encoding of the source file.  */
 const char *current_encoding = NULL;
 
+/* When nonzero, report use of deprecated classes, methods, or fields.  */
+int flag_deprecated = 1;
+
+/* When zero, don't optimize static class initialization. This flag shouldn't
+   be tested alone, use STATIC_CLASS_INITIALIZATION_OPTIMIZATION_P instead.  */
+/* FIXME: Make this work with gimplify.  */
+/* int flag_optimize_sci = 0;  */
+
+/* Don't attempt to verify invocations.  */
+int flag_verify_invocations = 0; 
+
 /* When nonzero, print extra version information.  */
 static int v_flag = 0;
 
@@ -593,6 +604,11 @@ java_post_options (const char **pfilename)
   if (flag_inline_functions)
     flag_inline_trees = 2;
 
+  /* An absolute requirement: if we're not using indirect dispatch, we
+     must always verify everything.  */
+  if (! flag_indirect_dispatch)
+    flag_verify_invocations = true;
+
   /* Open input file.  */
 
   if (filename == 0 || !strcmp (filename, "-"))
@@ -972,6 +988,10 @@ java_get_callee_fndecl (tree call_expr)
 
   HOST_WIDE_INT index;
 
+  /* FIXME: This is disabled because we end up passing calls through
+     the PLT, and we do NOT want to do that.  */
+  return NULL;
+
   if (TREE_CODE (call_expr) != CALL_EXPR)
     return NULL;
   method = TREE_OPERAND (call_expr, 0);
diff --git a/gcc/java/lang.opt b/gcc/java/lang.opt
index 0e4ffcfd9942..644bd5be2e79 100644
--- a/gcc/java/lang.opt
+++ b/gcc/java/lang.opt
@@ -176,5 +176,9 @@ fuse-divide-subroutine
 Java Var(flag_use_divide_subroutine) Init(1)
 Call a library routine to do integer divisions
 
+fnew-verifier
+Java Var(flag_new_verifier)
+Enable the new bytecode verifier
+
 version
 Java
diff --git a/gcc/java/parse.y b/gcc/java/parse.y
index 1c1a686d7277..91776c6f7f53 100644
--- a/gcc/java/parse.y
+++ b/gcc/java/parse.y
@@ -9690,8 +9690,8 @@ strip_out_static_field_access_decl (tree node)
 	   tree call = TREE_OPERAND (op1, 0);
 	   if (TREE_CODE (call) == CALL_EXPR
 	       && TREE_CODE (TREE_OPERAND (call, 0)) == ADDR_EXPR
-	       && TREE_OPERAND (TREE_OPERAND (call, 0), 0)
-	       == soft_initclass_node)
+	       && (TREE_OPERAND (TREE_OPERAND (call, 0), 0)
+		   == soft_initclass_node))
 	     return TREE_OPERAND (op1, 1);
 	 }
       else if (JDECL_P (op1))
@@ -11025,7 +11025,7 @@ patch_invoke (tree patch, tree method, tree args)
   if (TREE_CODE (original_call) == NEW_CLASS_EXPR)
     {
       tree class = DECL_CONTEXT (method);
-      tree c1, saved_new, size, new;
+      tree c1, saved_new, new;
       tree alloc_node;
 
       if (flag_emit_class_files || flag_emit_xref)
@@ -11035,7 +11035,6 @@ patch_invoke (tree patch, tree method, tree args)
 	}
       if (!TYPE_SIZE (class))
 	safe_layout_class (class);
-      size = size_in_bytes (class);
       alloc_node =
 	(class_has_finalize_method (class) ? alloc_object_node
 		  			   : alloc_no_finalizer_node);
@@ -11109,11 +11108,20 @@ invocation_mode (tree method, int super)
   if (DECL_CONSTRUCTOR_P (method))
     return INVOKE_STATIC;
 
-  if (access & ACC_FINAL || access & ACC_PRIVATE)
+  if (access & ACC_PRIVATE)
     return INVOKE_NONVIRTUAL;
 
-  if (CLASS_FINAL (TYPE_NAME (DECL_CONTEXT (method))))
-    return INVOKE_NONVIRTUAL;
+  /* Binary compatibility: just because it's final today, that doesn't
+     mean it'll be final tomorrow.  */
+  if (! flag_indirect_dispatch  
+      || DECL_CONTEXT (method) == object_type_node)
+    {
+      if (access & ACC_FINAL)
+	return INVOKE_NONVIRTUAL;
+
+      if (CLASS_FINAL (TYPE_NAME (DECL_CONTEXT (method))))
+	return INVOKE_NONVIRTUAL;
+    }
 
   if (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method))))
     return INVOKE_INTERFACE;
diff --git a/gcc/java/typeck.c b/gcc/java/typeck.c
index 0c61174f251c..4db69b4ea0c3 100644
--- a/gcc/java/typeck.c
+++ b/gcc/java/typeck.c
@@ -743,7 +743,7 @@ lookup_java_method (tree searched_class, tree method_name,
 		    method_signature, build_java_signature);
 }
 
-/* Return true iff CLASS (or its ancestors) has a method METHOD_NAME.  */
+/* Return true iff CLASS (or its ancestors) has a method METHOD_NAME.  */
 int
 has_method (tree class, tree method_name)
 {
diff --git a/gcc/java/verify-glue.c b/gcc/java/verify-glue.c
new file mode 100644
index 000000000000..fb213405e432
--- /dev/null
+++ b/gcc/java/verify-glue.c
@@ -0,0 +1,514 @@
+/* Glue to interface gcj with bytecode verifier.
+   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+Java and all Java-based marks are trademarks or registered trademarks
+of Sun Microsystems, Inc. in the United States and other countries.
+The Free Software Foundation is independent of Sun Microsystems, Inc.  */
+
+/* Written by Tom Tromey <tromey@redhat.com>.  */
+
+#include "config.h"
+
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "errors.h"
+#include "parse.h"
+
+#include "verify.h"
+#include "java-tree.h"
+#include "java-except.h"
+
+void *
+vfy_alloc (size_t bytes)
+{
+  return xmalloc (bytes);
+}
+
+void
+vfy_free (void *mem)
+{
+  free (mem);
+}
+
+bool
+vfy_strings_equal (vfy_string one, vfy_string two)
+{
+  return one == two;
+}
+
+const char *
+vfy_string_bytes (vfy_string str)
+{
+  return IDENTIFIER_POINTER (str);
+}
+
+int
+vfy_string_length (vfy_string str)
+{
+  return IDENTIFIER_LENGTH (str);
+}
+
+vfy_string
+vfy_init_name ()
+{
+  return init_identifier_node;
+}
+
+vfy_string
+vfy_clinit_name ()
+{
+  return clinit_identifier_node;
+}
+
+static const char*
+skip_one_type (const char* ptr)
+{
+  int ch = *ptr++;
+
+  while (ch == '[')
+    { 
+      ch = *ptr++;
+    }
+  
+  if (ch == 'L')
+    {
+      do { ch = *ptr++; } while (ch != ';');
+    }
+
+  return ptr;
+}
+
+int
+vfy_count_arguments (vfy_string signature)
+{
+  const char *ptr = IDENTIFIER_POINTER (signature);
+  int arg_count = 0;
+
+  /* Skip '('.  */
+  ptr++;
+
+  /* Count args.  */
+  while (*ptr != ')')
+    {
+      ptr = skip_one_type (ptr);
+      arg_count += 1;
+    }
+
+  return arg_count;
+}
+
+vfy_string
+vfy_get_string (const char *s, int len)
+{
+  return get_identifier_with_length (s, len);
+}
+
+vfy_string
+vfy_get_signature (vfy_method *method)
+{
+  return method->signature;
+}
+
+vfy_string
+vfy_get_method_name (vfy_method *method)
+{
+  return method->name;
+}
+
+bool
+vfy_is_static (vfy_method *method)
+{
+  return METHOD_STATIC (method->method);
+}
+
+const unsigned char *
+vfy_get_bytecode (vfy_method *method)
+{
+  return method->bytes;
+}
+
+vfy_exception *
+vfy_get_exceptions (vfy_method *method)
+{
+  return method->exceptions;
+}
+
+void
+vfy_get_exception (vfy_exception *exceptions, int index, int *handler,
+		   int *start, int *end, int *handler_type)
+{
+  *handler = exceptions[index].handler;
+  *start = exceptions[index].start;
+  *end = exceptions[index].end;
+  *handler_type = exceptions[index].type;
+}
+
+int
+vfy_tag (vfy_constants *pool, int index)
+{
+  int result = JPOOL_TAG (pool, index);
+  /* gcj will resolve constant pool entries other than string and
+     class references.  The verifier doesn't care about the values, so
+     we just strip off the resolved flag.  */
+  if ((result & CONSTANT_ResolvedFlag) != 0
+      && result != CONSTANT_ResolvedString
+      && result != CONSTANT_ResolvedClass)
+    result &= ~ CONSTANT_ResolvedFlag;
+  return result;
+}
+
+void
+vfy_load_indexes (vfy_constants *pool, int index,
+		  vfy_uint_16 *index0, vfy_uint_16 *index1)
+{
+  *index0 = JPOOL_USHORT1 (pool, index);
+  *index1 = JPOOL_USHORT2 (pool, index);
+}
+
+vfy_constants *
+vfy_get_constants (vfy_jclass klass)
+{
+  return TYPE_JCF (klass);
+}
+
+int
+vfy_get_constants_size (vfy_jclass klass)
+{
+  return JPOOL_SIZE (TYPE_JCF (klass));
+}
+
+vfy_string
+vfy_get_pool_string (vfy_constants *pool, int index)
+{
+  return get_name_constant (pool, index);
+}
+
+vfy_jclass
+vfy_get_pool_class (vfy_constants *pool, int index)
+{
+  vfy_jclass k;
+  k = get_class_constant (pool, index);
+  return k;
+}
+
+vfy_string
+vfy_make_string (const char *s, int len)
+{
+  tree result;
+  char *s2 = (char *) s;
+  char save = s2[len];
+  s2[len] = '\0';
+  result = get_identifier (s2);
+  s2[len] = save;
+  return result;  
+}
+
+vfy_string
+vfy_get_class_name (vfy_jclass klass)
+{
+  return DECL_NAME (TYPE_NAME (klass));
+}
+
+bool
+vfy_is_assignable_from (vfy_jclass target, vfy_jclass source)
+{
+  /* At compile time, for the BC-ABI we assume that reference types are always 
+  compatible.  However, a type assertion table entry is emitted so that the
+  runtime can detect binary-incompatible changes.  */
+
+  /* FIXME: implement real test for old ABI.  */
+
+  /* Any class is always assignable to itself, or java.lang.Object. */
+  if (source == target || target == object_type_node)
+    return true;
+
+  /* Otherwise, a type assertion is required.  */
+  add_type_assertion (current_class, JV_ASSERT_TYPES_COMPATIBLE, source,
+		      target);
+  return true;
+}
+
+char
+vfy_get_primitive_char (vfy_jclass klass)
+{
+  tree sig;
+  if (! vfy_is_primitive (klass))
+    abort ();
+  sig = build_java_signature (klass);
+  return (IDENTIFIER_POINTER (sig))[0];
+}
+
+int
+vfy_get_interface_count (vfy_jclass klass ATTRIBUTE_UNUSED)
+{
+  /* FIXME: Need to merge from mainline to get this. */
+  #if 0
+  return BINFO_N_BASE_BINFOS (klass);
+  #endif
+  return -1;
+}
+
+vfy_jclass
+vfy_get_interface (vfy_jclass klass ATTRIBUTE_UNUSED, int index ATTRIBUTE_UNUSED)
+{
+  /* FIXME: Need to merge from mainline to get this. */
+  #if 0
+  vfy_jclass k;
+  k = BINFO_BASE_BINFO (klass, index);
+  return k;
+  #endif
+  return NULL;
+}
+
+bool
+vfy_is_array (vfy_jclass klass)
+{
+  return TYPE_ARRAY_P (klass);
+}
+
+bool
+vfy_is_interface (vfy_jclass klass)
+{
+  return CLASS_INTERFACE (TYPE_NAME (klass));
+}
+
+bool
+vfy_is_primitive (vfy_jclass klass)
+{
+  return JPRIMITIVE_TYPE_P (klass);
+}
+
+vfy_jclass
+vfy_get_superclass (vfy_jclass klass)
+{
+  vfy_jclass k;
+  k = CLASSTYPE_SUPER (klass);
+  return k;
+}
+
+vfy_jclass
+vfy_get_array_class (vfy_jclass klass)
+{
+  vfy_jclass k;
+  k = build_java_array_type (klass, -1);
+  return k;
+}
+
+vfy_jclass
+vfy_get_component_type (vfy_jclass klass)
+{
+  vfy_jclass k;
+  if (! vfy_is_array (klass))
+    abort ();
+  k = TYPE_ARRAY_ELEMENT (klass);
+  if (TREE_CODE (k) == POINTER_TYPE)
+    k = TREE_TYPE (k);
+  return k;
+}
+
+bool
+vfy_is_abstract (vfy_jclass klass)
+{
+  return CLASS_ABSTRACT (TYPE_NAME (klass));
+}
+
+vfy_jclass
+vfy_find_class (vfy_jclass ignore ATTRIBUTE_UNUSED, vfy_string name)
+{
+  vfy_jclass k;
+
+  k = get_type_from_signature (name);
+  if (TREE_CODE (k) == POINTER_TYPE)
+    k = TREE_TYPE (k);
+
+  return k;
+}
+
+vfy_jclass
+vfy_object_type ()
+{
+  vfy_jclass k;
+  k = object_type_node;
+  return k;
+}
+
+vfy_jclass
+vfy_string_type ()
+{
+  vfy_jclass k;
+  k = string_type_node;
+  return k;
+}
+
+vfy_jclass
+vfy_throwable_type ()
+{
+  vfy_jclass k;
+  k = throwable_type_node;
+  return k;
+}
+
+vfy_jclass
+vfy_unsuitable_type (void)
+{
+  return TYPE_SECOND;
+}
+
+vfy_jclass
+vfy_return_address_type (void)
+{
+  return TYPE_RETURN_ADDR;
+}
+
+vfy_jclass
+vfy_null_type (void)
+{
+  return TYPE_NULL;
+}
+
+int
+vfy_fail (const char *message, int pc, vfy_jclass ignore1 ATTRIBUTE_UNUSED,
+	  vfy_method *ignore2 ATTRIBUTE_UNUSED)
+{
+  if (pc == -1)
+    error ("verification failed: %s", message);
+  else
+    error ("verification failed at PC=%d: %s", pc, message);
+  /* We have to return a value for the verifier to throw.  */
+  return 1;
+}
+
+vfy_jclass
+vfy_get_primitive_type (int type)
+{
+  vfy_jclass k;
+  k = decode_newarray_type (type);
+  return k;
+}
+
+void
+vfy_note_stack_depth (vfy_method *method, int pc, int depth)
+{
+  tree label = lookup_label (pc);
+  LABEL_TYPE_STATE (label) = make_tree_vec (method->max_locals + depth);
+}
+
+void
+vfy_note_stack_type (vfy_method *method, int pc, int slot, vfy_jclass type)
+{
+  tree label, vec;
+  
+  slot += method->max_locals;
+
+  if (type == object_type_node)
+    type = object_ptr_type_node;
+
+  label = lookup_label (pc);
+  vec = LABEL_TYPE_STATE (label);
+  TREE_VEC_ELT (vec, slot) = type;
+}
+
+void
+vfy_note_local_type (vfy_method *method ATTRIBUTE_UNUSED, int pc, int slot,
+		     vfy_jclass type)
+{
+  tree label, vec;
+  
+  if (type == object_type_node)
+    type = object_ptr_type_node;
+
+  label = lookup_label (pc);
+  vec = LABEL_TYPE_STATE (label);
+  TREE_VEC_ELT (vec, slot) = type;
+}
+
+void
+vfy_note_instruction_seen (int pc)
+{
+  instruction_bits[pc] |= BCODE_VERIFIED;
+}
+
+/* Verify the bytecodes of the current method.
+   Return 1 on success, 0 on failure. */
+int
+verify_jvm_instructions_new (JCF *jcf, const unsigned char *byte_ops,
+			 long length)
+{
+  vfy_method method;
+  int i, result, eh_count;
+  vfy_exception *exceptions;
+
+  method_init_exceptions ();
+
+  JCF_SEEK (jcf, DECL_CODE_OFFSET (current_function_decl) + length);
+  eh_count = JCF_readu2 (jcf);
+
+  exceptions = (vfy_exception *) xmalloc (eh_count * sizeof (vfy_exception));
+  for (i = 0; i < eh_count; ++i)
+    {
+      int start_pc, end_pc, handler_pc, catch_type;
+      unsigned char *p = jcf->read_ptr + 8 * i;
+      start_pc = GET_u2 (p);
+      end_pc = GET_u2 (p+2);
+      handler_pc = GET_u2 (p+4);
+      catch_type = GET_u2 (p+6);
+
+      if (start_pc < 0 || start_pc >= length
+	  || end_pc < 0 || end_pc > length || start_pc >= end_pc
+	  || handler_pc < 0 || handler_pc >= length)
+	{
+	  error ("bad pc in exception_table");
+	  free (exceptions);
+	  return 0;
+	}
+
+      exceptions[i].handler = handler_pc;
+      exceptions[i].start = start_pc;
+      exceptions[i].end = end_pc;
+      exceptions[i].type = catch_type;
+
+      add_handler (start_pc, end_pc,
+		   lookup_label (handler_pc),
+		   catch_type == 0 ? NULL_TREE
+		   : get_class_constant (jcf, catch_type));
+      instruction_bits[handler_pc] |= BCODE_EXCEPTION_TARGET;
+    }
+
+  handle_nested_ranges ();
+
+  method.method = current_function_decl;
+  method.signature = build_java_signature (TREE_TYPE (current_function_decl));
+  method.name = DECL_NAME (current_function_decl);
+  method.bytes = byte_ops;
+  method.exceptions = exceptions;
+  method.defining_class = DECL_CONTEXT (current_function_decl);
+  method.max_stack = DECL_MAX_STACK (current_function_decl);
+  method.max_locals = DECL_MAX_LOCALS (current_function_decl);
+  method.code_length = length;
+  method.exc_count = eh_count;
+
+  result = verify_method (&method);
+
+  free (exceptions);
+
+  return result;
+}
diff --git a/gcc/java/verify-impl.c b/gcc/java/verify-impl.c
new file mode 100644
index 000000000000..2c402a8c62bc
--- /dev/null
+++ b/gcc/java/verify-impl.c
@@ -0,0 +1,3418 @@
+/* Copyright (C) 2001, 2002, 2003, 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.  */
+
+/* Written by Tom Tromey <tromey@redhat.com>  */
+
+/* Uncomment this to enable debugging output.  */
+/* #define VERIFY_DEBUG */
+
+#include "config.h"
+
+#include "verify.h"
+
+/* Hack to work around namespace pollution from java-tree.h.  */
+#undef current_class
+
+#ifdef VERIFY_DEBUG
+#include <stdio.h>
+#endif /* VERIFY_DEBUG */
+
+/* This is used to mark states which are not scheduled for
+   verification. */
+#define INVALID_STATE ((state *) -1)
+
+#ifdef VERIFY_DEBUG
+static void
+debug_print (const char *fmt, ...)
+{
+  va_list ap;
+  va_start (ap, fmt);
+  vfprintf (stderr, fmt, ap);
+  va_end (ap);
+}
+#else
+static void
+debug_print (const char *fmt ATTRIBUTE_UNUSED, ...)
+{
+}    
+#endif /* VERIFY_DEBUG */
+
+#if 0
+static void debug_print (const char *fmt, ...)
+  __attribute__ ((format (printf, 1, 2)));
+
+static void
+debug_print (const char *fmt, ...)
+{
+#ifdef VERIFY_DEBUG
+  va_list ap;
+  va_start (ap, fmt);
+  vfprintf (stderr, fmt, ap);
+  va_end (ap);
+#endif /* VERIFY_DEBUG */
+}
+#endif
+
+/* This started as a fairly ordinary verifier, and for the most part
+   it remains so.  It works in the obvious way, by modeling the effect
+   of each opcode as it is encountered.  For most opcodes, this is a
+   straightforward operation.
+
+   This verifier does not do type merging.  It used to, but this
+   results in difficulty verifying some relatively simple code
+   involving interfaces, and it pushed some verification work into the
+   interpreter.
+
+   Instead of merging reference types, when we reach a point where two
+   flows of control merge, we simply keep the union of reference types
+   from each branch.  Then, when we need to verify a fact about a
+   reference on the stack (e.g., that it is compatible with the
+   argument type of a method), we check to ensure that all possible
+   types satisfy the requirement.
+
+   Another area this verifier differs from the norm is in its handling
+   of subroutines.  The JVM specification has some confusing things to
+   say about subroutines.  For instance, it makes claims about not
+   allowing subroutines to merge and it rejects recursive subroutines.
+   For the most part these are red herrings; we used to try to follow
+   these things but they lead to problems.  For example, the notion of
+   "being in a subroutine" is not well-defined: is an exception
+   handler in a subroutine?  If you never execute the `ret' but
+   instead `goto 1' do you remain in the subroutine?
+
+   For clarity on what is really required for type safety, read
+   "Simple Verification Technique for Complex Java Bytecode
+   Subroutines" by Alessandro Coglio.  Among other things this paper
+   shows that recursive subroutines are not harmful to type safety.
+   We implement something similar to what he proposes.  Note that this
+   means that this verifier will accept code that is rejected by some
+   other verifiers.
+
+   For those not wanting to read the paper, the basic observation is
+   that we can maintain split states in subroutines.  We maintain one
+   state for each calling `jsr'.  In other words, we re-verify a
+   subroutine once for each caller, using the exact types held by the
+   callers (as opposed to the old approach of merging types and
+   keeping a bitmap registering what did or did not change).  This
+   approach lets us continue to verify correctly even when a
+   subroutine is exited via `goto' or `athrow' and not `ret'.
+
+   In some other areas the JVM specification is (mildly) incorrect,
+   so we diverge.  For instance, you cannot
+   violate type safety by allocating an object with `new' and then
+   failing to initialize it, no matter how one branches or where one
+   stores the uninitialized reference.  See "Improving the official
+   specification of Java bytecode verification" by Alessandro Coglio.
+
+   Note that there's no real point in enforcing that padding bytes or
+   the mystery byte of invokeinterface must be 0, but we do that
+   regardless.
+
+   The verifier is currently neither completely lazy nor eager when it
+   comes to loading classes.  It tries to represent types by name when
+   possible, and then loads them when it needs to verify a fact about
+   the type.  Checking types by name is valid because we only use
+   names which come from the current class' constant pool.  Since all
+   such names are looked up using the same class loader, there is no
+   danger that we might be fooled into comparing different types with
+   the same name.
+
+   In the future we plan to allow for a completely lazy mode of
+   operation, where the verifier will construct a list of type
+   assertions to be checked later.
+
+   Some test cases for the verifier live in the "verify" module of the
+   Mauve test suite.  However, some of these are presently
+   (2004-01-20) believed to be incorrect.  (More precisely the notion
+   of "correct" is not well-defined, and this verifier differs from
+   others while remaining type-safe.)  Some other tests live in the
+   libgcj test suite.
+
+   This verifier is also written to be pluggable.  This means that it
+   is intended for use in a variety of environments, not just libgcj.
+   As a result the verifier expects a number of type and method
+   declarations to be declared in "verify.h".  The intent is that you
+   recompile the verifier for your particular environment.  This
+   approach was chosen so that operations could be inlined in verify.h
+   as much as possible.
+
+   See the verify.h that accompanies this copy of the verifier to see
+   what types, preprocessor defines, and functions must be declared.
+   The interface is ad hoc, but was defined so that it could be
+   implemented to connect to a pure C program.
+*/
+
+#define FLAG_INSN_START 1
+#define FLAG_BRANCH_TARGET 2
+#define FLAG_INSN_SEEN 4
+
+struct state;
+struct type;
+struct ref_intersection;
+
+typedef struct state state;
+typedef struct type type;
+typedef struct ref_intersection ref_intersection;
+
+/*typedef struct state_list state_list;*/
+
+typedef struct state_list
+{
+  state *val;
+  struct state_list *next;
+} state_list;
+
+typedef struct vfy_string_list
+{
+  vfy_string val;
+  struct vfy_string_list *next;
+} vfy_string_list;
+
+typedef struct verifier_context
+{
+  /* The current PC.  */
+  int PC;
+  /* The PC corresponding to the start of the current instruction.  */
+  int start_PC;
+
+  /* The current state of the stack, locals, etc.  */
+  state *current_state;
+
+  /* At each branch target we keep a linked list of all the states we
+     can process at that point.  We'll only have multiple states at a
+     given PC if they both have different return-address types in the
+     same stack or local slot.  This array is indexed by PC and holds
+     the list of all such states.  */
+  state_list **states;
+
+  /* We keep a linked list of all the states which we must reverify.
+     This is the head of the list.  */
+  state *next_verify_state;
+
+  /* We keep some flags for each instruction.  The values are the
+     FLAG_* constants defined above.  This is an array indexed by PC.  */
+  char *flags;
+
+  /* The bytecode itself.  */
+  const unsigned char *bytecode;
+  /* The exceptions.  */
+  vfy_exception *exception;
+
+  /* Defining class.  */
+  vfy_jclass current_class;
+  /* This method.  */
+  vfy_method *current_method;
+
+  /* A linked list of utf8 objects we allocate.  */
+  vfy_string_list *utf8_list;
+
+  /* A linked list of all ref_intersection objects we allocate.  */
+  ref_intersection *isect_list;
+} verifier_context;
+
+/* The current verifier's state data. This is maintained by
+   {push/pop}_verifier_context to provide a shorthand form to access
+   the verification state. */
+static GTY(()) verifier_context *vfr;
+
+/* Local function declarations.  */
+bool type_initialized (type *t);
+int ref_count_dimensions (ref_intersection *ref);
+
+#if 0
+  /* Create a new Utf-8 constant and return it.  We do this to avoid
+     having our Utf-8 constants prematurely collected.  */
+  static vfy_string
+  make_utf8_const (const char *s, int len)
+  {
+    vfy_string val = vfy_make_string (s, len);
+    vfy_string_list *lu = vfy_alloc (sizeof (vfy_string_list));
+    lu->val = val;
+    lu->next = vfr->utf8_list;
+    vfr->utf8_list = lu;
+
+    return val;
+  }
+#endif
+
+static void
+verify_fail_pc (const char *s, int pc)
+{
+  vfy_fail (s, pc, vfr->current_class, vfr->current_method);  
+}
+
+static void
+verify_fail (const char *s)
+{
+  verify_fail_pc (s, -1);
+}
+
+/* This enum holds a list of tags for all the different types we
+   need to handle.  Reference types are treated specially by the
+   type class.  */
+typedef enum type_val
+{
+  void_type,
+
+  /* The values for primitive types are chosen to correspond to values
+     specified to newarray. */
+  boolean_type = 4,
+  char_type = 5,
+  float_type = 6,
+  double_type = 7,
+  byte_type = 8,
+  short_type = 9,
+  int_type = 10,
+  long_type = 11,
+
+  /* Used when overwriting second word of a double or long in the
+     local variables.  Also used after merging local variable states
+     to indicate an unusable value.  */
+  unsuitable_type,
+  return_address_type,
+  /* This is the second word of a two-word value, i.e., a double or
+     a long.  */
+  continuation_type,
+
+  /* Everything after `reference_type' must be a reference type.  */
+  reference_type,
+  null_type,
+  uninitialized_reference_type
+} type_val;
+
+/* This represents a merged class type.  Some verifiers (including
+   earlier versions of this one) will compute the intersection of
+   two class types when merging states.  However, this loses
+   critical information about interfaces implemented by the various
+   classes.  So instead we keep track of all the actual classes that
+   have been merged.  */
+struct ref_intersection
+{
+  /* Whether or not this type has been resolved.  */
+  bool is_resolved;
+
+  /* Actual type data.  */
+  union
+  {
+    /* For a resolved reference type, this is a pointer to the class.  */
+    vfy_jclass klass;
+    /* For other reference types, this it the name of the class.  */
+    vfy_string name;
+  } data;
+
+  /* Link to the next reference in the intersection.  */
+  ref_intersection *ref_next;
+
+  /* This is used to keep track of all the allocated
+     ref_intersection objects, so we can free them.
+     FIXME: we should allocate these in chunks.  */
+  ref_intersection *alloc_next;
+};
+
+static ref_intersection *
+make_ref (void)
+{
+  ref_intersection *new_ref = 
+    (ref_intersection *) vfy_alloc (sizeof (ref_intersection));
+
+  new_ref->alloc_next = vfr->isect_list;
+  vfr->isect_list = new_ref;
+  return new_ref;
+}
+
+static ref_intersection *
+clone_ref (ref_intersection *dup)
+{
+  ref_intersection *new_ref = make_ref ();
+
+  new_ref->is_resolved = dup->is_resolved;
+  new_ref->data = dup->data;
+  return new_ref;
+}
+
+static void 
+resolve_ref (ref_intersection *ref)
+{
+  if (ref->is_resolved)
+    return;
+  ref->data.klass = vfy_find_class (vfr->current_class, ref->data.name);
+  ref->is_resolved = true;
+}
+
+static bool 
+refs_equal (ref_intersection *ref1, ref_intersection *ref2)
+{
+  if (! ref1->is_resolved && ! ref2->is_resolved
+      && vfy_strings_equal (ref1->data.name, ref2->data.name))
+    return true;
+  if (! ref1->is_resolved)
+    resolve_ref (ref1);
+  if (! ref2->is_resolved)
+    resolve_ref (ref2);
+  return ref1->data.klass == ref2->data.klass;
+}
+
+/* Merge REF1 type into REF2, returning the result.  This will
+   return REF2 if all the classes in THIS already appear in
+   REF2.  */
+static ref_intersection *
+merge_refs (ref_intersection *ref1, ref_intersection *ref2)
+{
+  ref_intersection *tail = ref2;
+  for (; ref1 != NULL; ref1 = ref1->ref_next)
+    {
+      bool add = true;
+      ref_intersection *iter;
+      for (iter = ref2; iter != NULL; iter = iter->ref_next)
+	{
+	  if (refs_equal (ref1, iter))
+	    {
+	      add = false;
+	      break;
+	    }
+	}
+
+      if (add)
+        {
+	  ref_intersection *new_tail = clone_ref (ref1);
+	  new_tail->ref_next = tail;
+	  tail = new_tail;
+	}
+    }
+  return tail;
+}
+
+/* See if an object of type SOURCE can be assigned to an object of
+   type TARGET.  This might resolve classes in one chain or the other.  */
+static bool 
+ref_compatible (ref_intersection *target, ref_intersection *source)
+{
+  for (; target != NULL; target = target->ref_next)
+    {
+      ref_intersection *source_iter = source;
+
+      for (; source_iter != NULL; source_iter = source_iter->ref_next)
+	{
+	  /* Avoid resolving if possible.  */
+	  if (! target->is_resolved
+	      && ! source_iter->is_resolved
+	      && vfy_strings_equal (target->data.name,
+				    source_iter->data.name))
+	    continue;
+
+	  if (! target->is_resolved)
+	    resolve_ref (target);
+	  if (! source_iter->is_resolved)
+	    resolve_ref (source_iter);
+
+	  if (! vfy_is_assignable_from (target->data.klass,
+	  			        source_iter->data.klass))
+	    return false;
+	}
+    }
+
+  return true;
+}
+
+static bool 
+ref_isarray (ref_intersection *ref)
+{
+  /* assert (ref_next == NULL);  */
+  if (ref->is_resolved)
+    return vfy_is_array (ref->data.klass);
+  else
+    return vfy_string_bytes (ref->data.name)[0] == '[';
+}
+
+static bool
+ref_isinterface (ref_intersection *ref)
+{
+  /* assert (ref_next == NULL);  */
+  if (! ref->is_resolved)
+    resolve_ref (ref);
+  return vfy_is_interface (ref->data.klass);
+}
+
+static bool
+ref_isabstract (ref_intersection *ref)
+{
+  /* assert (ref_next == NULL); */
+  if (! ref->is_resolved)
+    resolve_ref (ref);
+  return vfy_is_abstract (ref->data.klass);
+}
+
+static vfy_jclass 
+ref_getclass (ref_intersection *ref)
+{
+  if (! ref->is_resolved)
+    resolve_ref (ref);
+  return ref->data.klass;
+}
+
+int
+ref_count_dimensions (ref_intersection *ref)
+{
+  int ndims = 0;
+  if (ref->is_resolved)
+    {
+      vfy_jclass k = ref->data.klass;
+      while (vfy_is_array (k))
+	{
+ 	  k = vfy_get_component_type (k);
+	  ++ndims;
+	}
+    }
+  else
+    {
+      const char *p = vfy_string_bytes (ref->data.name);
+      while (*p++ == '[')
+	++ndims;
+    }
+  return ndims;
+}
+
+/* Return the type_val corresponding to a primitive signature
+   character.  For instance `I' returns `int.class'.  */
+static type_val
+get_type_val_for_signature (char sig)
+{
+  type_val rt;
+  switch (sig)
+    {
+    case 'Z':
+      rt = boolean_type;
+      break;
+    case 'B':
+      rt = byte_type;
+      break;
+    case 'C':
+      rt = char_type;
+      break;
+    case 'S':
+      rt = short_type;
+      break;
+    case 'I':
+      rt = int_type;
+      break;
+    case 'J':
+      rt = long_type;
+      break;
+    case 'F':
+      rt = float_type;
+      break;
+    case 'D':
+      rt = double_type;
+      break;
+    case 'V':
+      rt = void_type;
+      break;
+    default:
+      verify_fail ("invalid signature");
+      return null_type;
+    }
+  return rt;
+}
+
+/* Return the type_val corresponding to a primitive class.  */
+static type_val
+get_type_val_for_primtype (vfy_jclass k)
+{
+  return get_type_val_for_signature (vfy_get_primitive_char (k));
+}
+
+/* The `type' class is used to represent a single type in the verifier.  */
+struct type
+{
+  /* The type key.  */
+  type_val key;
+
+  /* For reference types, the representation of the type.  */
+  ref_intersection *klass;
+
+  /* This is used in two situations.
+  
+     First, when constructing a new object, it is the PC of the
+     `new' instruction which created the object.  We use the special
+     value UNINIT to mean that this is uninitialized, and the
+     special value SELF for the case where the current method is
+     itself the <init> method.
+
+     Second, when the key is return_address_type, this holds the PC
+     of the instruction following the `jsr'.  */
+  int pc;
+
+  #define UNINIT -2
+  #define SELF -1
+};
+
+#if 0
+/* Basic constructor.  */
+static void
+init_type (type *t)
+{
+  t->key = unsuitable_type;
+  t->klass = NULL;
+  t->pc = UNINIT;
+}
+#endif
+
+/* Make a new instance given the type tag.  We assume a generic
+   `reference_type' means Object.  */
+static void
+init_type_from_tag (type *t, type_val k)
+{
+  t->key = k;
+  /* For reference_type, if KLASS==NULL then that means we are
+     looking for a generic object of any kind, including an
+     uninitialized reference.  */
+  t->klass = NULL;
+  t->pc = UNINIT;
+}
+
+/* Make a type for the given type_val tag K.  */
+static type
+make_type (type_val k)
+{
+  type t;
+  init_type_from_tag (&t, k);
+  return t;
+}
+
+/* Make a new instance given a class.  */
+static void
+init_type_from_class (type *t, vfy_jclass k)
+{
+  t->key = reference_type;
+  t->klass = make_ref ();
+  t->klass->is_resolved = true;
+  t->klass->data.klass = k;
+  t->klass->ref_next = NULL;
+  t->pc = UNINIT;
+}
+
+static type
+make_type_from_class (vfy_jclass k)
+{
+  type t;
+  init_type_from_class (&t, k);
+  return t;
+}
+
+static void
+init_type_from_string (type *t, vfy_string n)
+{
+  t->key = reference_type;
+  t->klass = make_ref ();
+  t->klass->is_resolved = false;
+  t->klass->data.name = n;
+  t->klass->ref_next = NULL;
+  t->pc = UNINIT;
+}
+
+static type
+make_type_from_string (vfy_string n)
+{
+  type t;
+  init_type_from_string (&t, n);
+  return t;
+}
+
+#if 0
+    /* Make a new instance given the name of a class.  */
+    type (vfy_string n)
+    {
+      key = reference_type;
+      klass = new ref_intersection (n, verifier);
+      pc = UNINIT;
+    }
+
+    /* Copy constructor.  */
+    static type copy_type (type *t)
+    {
+      type copy;
+      copy.key = t->key;
+      copy.klass = t->klass;
+      copy.pc = t->pc;
+      return copy;
+    }
+#endif
+
+/* Promote a numeric type.  */
+static void
+vfy_promote_type (type *t)
+{
+  if (t->key == boolean_type || t->key == char_type
+      || t->key == byte_type || t->key == short_type)
+    t->key = int_type;
+}
+#define promote_type vfy_promote_type
+
+/* Mark this type as the uninitialized result of `new'.  */
+static void
+type_set_uninitialized (type *t, int npc)
+{
+  if (t->key == reference_type)
+    t->key = uninitialized_reference_type;
+  else
+    verify_fail ("internal error in type::uninitialized");
+  t->pc = npc;
+}
+
+/* Mark this type as now initialized.  */
+static void
+type_set_initialized (type *t, int npc)
+{
+  if (npc != UNINIT && t->pc == npc && t->key == uninitialized_reference_type)
+    {
+      t->key = reference_type;
+      t->pc = UNINIT;
+    }
+}
+
+/* Mark this type as a particular return address.  */
+static void type_set_return_address (type *t, int npc)
+{
+  t->pc = npc;
+}
+
+/* Return true if this type and type OTHER are considered
+   mergeable for the purposes of state merging.  This is related
+   to subroutine handling.  For this purpose two types are
+   considered unmergeable if they are both return-addresses but
+   have different PCs.  */
+static bool
+type_state_mergeable_p (type *t1, type *t2)
+{
+  return (t1->key != return_address_type
+	  || t2->key != return_address_type
+	  || t1->pc == t2->pc);
+}
+
+/* Return true if an object of type K can be assigned to a variable
+   of type T.  Handle various special cases too.  Might modify
+   T or K.  Note however that this does not perform numeric
+   promotion.  */
+static bool 
+types_compatible (type *t, type *k)
+{
+  /* Any type is compatible with the unsuitable type.  */
+  if (k->key == unsuitable_type)
+    return true;
+
+  if (t->key < reference_type || k->key < reference_type)
+    return t->key == k->key;
+
+  /* The `null' type is convertible to any initialized reference
+     type.  */
+  if (t->key == null_type)
+    return k->key != uninitialized_reference_type;
+  if (k->key == null_type)
+    return t->key != uninitialized_reference_type;
+
+  /* A special case for a generic reference.  */
+  if (t->klass == NULL)
+    return true;
+  if (k->klass == NULL)
+    verify_fail ("programmer error in type::compatible");
+
+  /* An initialized type and an uninitialized type are not
+     compatible.  */
+  if (type_initialized (t) != type_initialized (k))
+    return false;
+
+  /* Two uninitialized objects are compatible if either:
+     * The PCs are identical, or
+     * One PC is UNINIT.  */
+  if (type_initialized (t))
+    {
+      if (t->pc != k->pc && t->pc != UNINIT && k->pc != UNINIT)
+	return false;
+    }
+
+  return ref_compatible (t->klass, k->klass);
+}
+
+static bool
+type_isvoid (type *t)
+{
+  return t->key == void_type;
+}
+
+static bool
+type_iswide (type *t)
+{
+  return t->key == long_type || t->key == double_type;
+}
+
+/* Return number of stack or local variable slots taken by this type.  */  
+static int
+type_depth (type *t)
+{
+  return type_iswide (t) ? 2 : 1;
+}
+
+static bool
+type_isarray (type *t)
+{
+  /* We treat null_type as not an array.  This is ok based on the
+     current uses of this method.  */
+  if (t->key == reference_type)
+    return ref_isarray (t->klass);
+  return false;
+}
+
+static bool
+type_isnull (type *t)
+{
+  return t->key == null_type;
+}
+
+static bool
+type_isinterface (type *t)
+{
+  if (t->key != reference_type)
+    return false;
+  return ref_isinterface (t->klass);
+}
+
+static bool
+type_isabstract (type *t)
+{
+  if (t->key != reference_type)
+    return false;
+  return ref_isabstract (t->klass);
+}
+
+/* Return the element type of an array.  */
+static type
+type_array_element (type *t)
+{
+  type et;
+  vfy_jclass k;
+
+  if (t->key != reference_type)
+    verify_fail ("programmer error in type::element_type()");
+
+  k = vfy_get_component_type (ref_getclass (t->klass));
+  if (vfy_is_primitive (k))
+    init_type_from_tag (&et, get_type_val_for_primtype (k));
+  else
+    init_type_from_class (&et, k);
+  return et;
+}
+
+/* Return the array type corresponding to an initialized
+   reference.  We could expand this to work for other kinds of
+   types, but currently we don't need to.  */
+static type 
+type_to_array (type *t)
+{
+  type at;
+  vfy_jclass k;
+
+  if (t->key != reference_type)
+    verify_fail ("internal error in type::to_array()");
+
+  k = ref_getclass (t->klass);
+  init_type_from_class (&at, vfy_get_array_class (k));
+  return at;
+}
+
+static bool
+type_isreference (type *t)
+{
+  return t->key >= reference_type;
+}
+
+static int
+type_get_pc (type *t)
+{
+  return t->pc;
+}
+
+bool
+type_initialized (type *t)
+{
+  return t->key == reference_type || t->key == null_type;
+}
+
+#if 0
+static bool
+type_isresolved (type *t)
+{
+  return (t->key == reference_type
+	  || t->key == null_type
+	  || t->key == uninitialized_reference_type);
+}
+#endif
+
+static void
+type_verify_dimensions (type *t, int ndims)
+{
+  /* The way this is written, we don't need to check isarray().  */
+  if (t->key != reference_type)
+    verify_fail ("internal error in verify_dimensions:"
+			   " not a reference type");
+
+  if (ref_count_dimensions (t->klass) < ndims)
+    verify_fail ("array type has fewer dimensions"
+			   " than required");
+}
+
+/* Merge OLD_TYPE into this.  On error throw exception.  Return
+   true if the merge caused a type change.  */
+static bool
+merge_types (type *t, type *old_type, bool local_semantics)
+{
+  bool changed = false;
+  bool refo = type_isreference (old_type);
+  bool refn = type_isreference (t);
+  if (refo && refn)
+    {
+      if (old_type->key == null_type)
+	;
+      else if (t->key == null_type)
+	{
+	  *t = *old_type;
+	  changed = true;
+	}
+      else if (type_initialized (t) != type_initialized (old_type))
+	verify_fail ("merging initialized and uninitialized types");
+      else
+	{
+	  ref_intersection *merged;
+	  if (! type_initialized (t))
+	    {
+	      if (t->pc == UNINIT)
+		t->pc = old_type->pc;
+	      else if (old_type->pc == UNINIT)
+		;
+	      else if (t->pc != old_type->pc)
+		verify_fail ("merging different uninitialized types");
+	    }
+
+	  merged = merge_refs (old_type->klass, t->klass);
+	  if (merged != t->klass)
+	    {
+	      t->klass = merged;
+	      changed = true;
+	    }
+	}
+    }
+  else if (refo || refn || t->key != old_type->key)
+    {
+      if (local_semantics)
+	{
+	  /* If we already have an `unsuitable' type, then we
+	     don't need to change again.  */
+	  if (t->key != unsuitable_type)
+	    {
+	      t->key = unsuitable_type;
+	      changed = true;
+	    }
+	}
+      else
+	verify_fail ("unmergeable type");
+    }
+  return changed;
+}
+
+#ifdef VERIFY_DEBUG
+static void 
+type_print (type *t)
+{
+  char c = '?';
+  switch (t->key)
+    {
+    case boolean_type: c = 'Z'; break;
+    case byte_type: c = 'B'; break;
+    case char_type: c = 'C'; break;
+    case short_type: c = 'S'; break;
+    case int_type: c = 'I'; break;
+    case long_type: c = 'J'; break;
+    case float_type: c = 'F'; break;
+    case double_type: c = 'D'; break;
+    case void_type: c = 'V'; break;
+    case unsuitable_type: c = '-'; break;
+    case return_address_type: c = 'r'; break;
+    case continuation_type: c = '+'; break;
+    case reference_type: c = 'L'; break;
+    case null_type: c = '@'; break;
+    case uninitialized_reference_type: c = 'U'; break;
+    }
+  debug_print ("%c", c);
+}
+#endif /* VERIFY_DEBUG */
+
+/* This class holds all the state information we need for a given
+   location. */
+struct state
+{
+  /* The current top of the stack, in terms of slots.  */
+  int stacktop;
+  /* The current depth of the stack.  This will be larger than
+     STACKTOP when wide types are on the stack.  */
+  int stackdepth;
+  /* The stack.  */
+  type *stack;
+  /* The local variables.  */
+  type *locals;
+  /* We keep track of the type of `this' specially.  This is used to
+     ensure that an instance initializer invokes another initializer
+     on `this' before returning.  We must keep track of this
+     specially because otherwise we might be confused by code which
+     assigns to locals[0] (overwriting `this') and then returns
+     without really initializing.  */
+  type this_type;
+
+  /* The PC for this state.  This is only valid on states which are
+     permanently attached to a given PC.  For an object like
+     `current_state', which is used transiently, this has no
+     meaning.  */
+  int pc;
+  /* We keep a linked list of all states requiring reverification.
+     If this is the special value INVALID_STATE then this state is
+     not on the list.  NULL marks the end of the linked list.  */
+  state *next;
+};
+
+/* NO_NEXT is the PC value meaning that a new state must be
+   acquired from the verification list.  */
+#define NO_NEXT -1
+
+#if 0
+static void
+init_state (state *s)
+{
+  s->stack = NULL;
+  s->locals = NULL;
+  s->next = INVALID_STATE;  
+}
+#endif
+
+static void
+init_state_with_stack (state *s, int max_stack, int max_locals)
+{
+  int i;
+  s->stacktop = 0;
+  s->stackdepth = 0;
+  s->stack = (type *) vfy_alloc (max_stack * sizeof (type));
+  for (i = 0; i < max_stack; ++i)
+    init_type_from_tag (&s->stack[i], unsuitable_type);
+  s->locals = (type *) vfy_alloc (max_locals * sizeof (type));
+  for (i = 0; i < max_locals; ++i)
+    init_type_from_tag (&s->locals[i], unsuitable_type);
+  init_type_from_tag (&s->this_type, unsuitable_type);
+  s->pc = NO_NEXT;
+  s->next = INVALID_STATE;
+}
+
+static void
+copy_state (state *s, state *copy, int max_stack, int max_locals)
+{
+  int i;
+  s->stacktop = copy->stacktop;
+  s->stackdepth = copy->stackdepth;
+  for (i = 0; i < max_stack; ++i)
+    s->stack[i] = copy->stack[i];
+  for (i = 0; i < max_locals; ++i)
+    s->locals[i] = copy->locals[i];
+
+  s->this_type = copy->this_type;
+  /* Don't modify `next' or `pc'. */
+}
+
+static void
+copy_state_with_stack (state *s, state *orig, int max_stack, int max_locals)
+{
+  init_state_with_stack (s, max_stack, max_locals);
+  copy_state (s, orig, max_stack, max_locals);
+}
+
+/* Allocate a new state, copying ORIG. */
+static state *
+make_state_copy (state *orig, int max_stack, int max_locals)
+{
+  state *s = vfy_alloc (sizeof (state));
+  copy_state_with_stack (s, orig, max_stack, max_locals);
+  return s;
+}
+
+static state *
+make_state (int max_stack, int max_locals)
+{
+  state *s = vfy_alloc (sizeof (state));
+  init_state_with_stack (s, max_stack, max_locals);
+  return s;
+}
+
+#if 0
+static void
+free_state (state *s)
+{
+  if (s->stack != NULL)
+    vfy_free (s->stack);
+  if (s->locals != NULL)
+    vfy_free (s->locals);
+}
+#endif
+
+#if 0
+    void *operator new[] (size_t bytes)
+    {
+      return vfy_alloc (bytes);
+    }
+
+    void operator delete[] (void *mem)
+    {
+      vfy_free (mem);
+    }
+
+    void *operator new (size_t bytes)
+    {
+      return vfy_alloc (bytes);
+    }
+
+    void operator delete (void *mem)
+    {
+      vfy_free (mem);
+    }
+#endif
+
+/* Modify this state to reflect entry to an exception handler.  */
+static void
+state_set_exception (state *s, type *t, int max_stack)
+{
+  int i;
+  s->stackdepth = 1;
+  s->stacktop = 1;
+  s->stack[0] = *t;
+  for (i = s->stacktop; i < max_stack; ++i)
+    init_type_from_tag (&s->stack[i], unsuitable_type);
+}
+
+static int
+state_get_pc (state *s)
+{
+  return s->pc;
+}
+
+#if 0
+static void
+set_pc (state *s, int npc)
+{
+  s->pc = npc;
+}
+#endif
+
+/* Merge STATE_OLD into this state.  Destructively modifies this
+   state.  Returns true if the new state was in fact changed.
+   Will throw an exception if the states are not mergeable.  */
+static bool
+merge_states (state *s, state *state_old, int max_locals)
+{
+  int i;
+  bool changed = false;
+
+  /* Special handling for `this'.  If one or the other is
+     uninitialized, then the merge is uninitialized.  */
+  if (type_initialized (&s->this_type))
+    s->this_type = state_old->this_type;
+
+  /* Merge stacks.  */
+  if (state_old->stacktop != s->stacktop)  /* FIXME stackdepth instead?  */
+    verify_fail ("stack sizes differ");
+  for (i = 0; i < state_old->stacktop; ++i)
+    {
+      if (merge_types (&s->stack[i], &state_old->stack[i], false))
+	changed = true;
+    }
+
+  /* Merge local variables.  */
+  for (i = 0; i < max_locals; ++i)
+    {
+      if (merge_types (&s->locals[i], &state_old->locals[i], true))
+	changed = true;
+    }
+
+  return changed;
+}
+
+/* Ensure that `this' has been initialized.  */
+static void
+state_check_this_initialized (state *s)
+{
+  if (type_isreference (&s->this_type) && ! type_initialized (&s->this_type))
+    verify_fail ("`this' is uninitialized");
+}
+
+/* Set type of `this'.  */
+static void
+state_set_this_type (state *s, type *k)
+{
+  s->this_type = *k;
+}
+
+/* Mark each `new'd object we know of that was allocated at PC as
+   initialized.  */
+static void
+state_set_initialized (state *s, int pc, int max_locals)
+{
+  int i;
+  for (i = 0; i < s->stacktop; ++i)
+    type_set_initialized (&s->stack[i], pc);
+  for (i = 0; i < max_locals; ++i)
+    type_set_initialized (&s->locals[i], pc);
+  type_set_initialized (&s->this_type, pc);
+}
+
+/* This tests to see whether two states can be considered "merge
+   compatible".  If both states have a return-address in the same
+   slot, and the return addresses are different, then they are not
+   compatible and we must not try to merge them.  */
+static bool
+state_mergeable_p (state *s, state *other, int max_locals)
+
+{
+  int i;
+
+  /* This is tricky: if the stack sizes differ, then not only are
+     these not mergeable, but in fact we should give an error, as
+     we've found two execution paths that reach a branch target
+     with different stack depths.  FIXME stackdepth instead?  */
+  if (s->stacktop != other->stacktop)
+    verify_fail ("stack sizes differ");
+
+  for (i = 0; i < s->stacktop; ++i)
+    if (! type_state_mergeable_p (&s->stack[i], &other->stack[i]))
+      return false;
+  for (i = 0; i < max_locals; ++i)
+    if (! type_state_mergeable_p (&s->locals[i], &other->locals[i]))
+      return false;
+  return true;
+}
+
+static void
+state_reverify (state *s)
+{
+  if (s->next == INVALID_STATE)
+    {
+      s->next = vfr->next_verify_state;
+      vfr->next_verify_state = s;
+    }
+}
+
+#ifdef VERIFY_DEBUG
+static void 
+debug_print_state (state *s, const char *leader, int pc, int max_stack, 
+		   int max_locals)
+{
+  int i;
+  debug_print ("%s [%4d]:   [stack] ", leader, pc);
+  for (i = 0; i < s->stacktop; ++i)
+    type_print (&s->stack[i]);
+  for (; i < max_stack; ++i)
+    debug_print (".");
+  debug_print ("    [local] ");
+  for (i = 0; i < max_locals; ++i)
+    type_print (&s->locals[i]);
+  debug_print (" | %p\n", s);
+}
+#else
+static void
+debug_print_state (state *s ATTRIBUTE_UNUSED, 
+		   const char *leader ATTRIBUTE_UNUSED, 
+		   int pc ATTRIBUTE_UNUSED, int max_stack ATTRIBUTE_UNUSED, 
+		   int max_locals ATTRIBUTE_UNUSED)
+{
+}
+#endif /* VERIFY_DEBUG */
+
+static type
+pop_raw (void)
+{
+  type r;
+  state *s = vfr->current_state;
+  if (s->stacktop <= 0)
+    verify_fail ("stack empty");
+  r = s->stack[--s->stacktop];
+  s->stackdepth -= type_depth (&r);
+  if (s->stackdepth < 0)
+    verify_fail_pc ("stack empty", vfr->start_PC);
+  return r;
+}
+
+static type
+pop32 (void)
+{
+  type r = pop_raw ();
+  if (type_iswide (&r))
+    verify_fail ("narrow pop of wide type");
+  return r;
+}
+
+static type
+vfy_pop_type_t (type match)
+{
+  type t;
+  vfy_promote_type (&match);
+  t = pop_raw ();
+  if (! types_compatible (&match, &t))
+    verify_fail ("incompatible type on stack");
+  return t;
+}
+
+static type
+vfy_pop_type (type_val match)
+{
+  type t = make_type (match);
+  return vfy_pop_type_t (t);
+}
+
+#define pop_type vfy_pop_type
+#define pop_type_t vfy_pop_type_t
+
+/* Pop a reference which is guaranteed to be initialized.  MATCH
+   doesn't have to be a reference type; in this case this acts like
+   pop_type.  */
+static type
+pop_init_ref_t (type match)
+{
+  type t = pop_raw ();
+  if (type_isreference (&t) && ! type_initialized (&t))
+    verify_fail ("initialized reference required");
+  else if (! types_compatible (&match, &t))
+    verify_fail ("incompatible type on stack");
+  return t;
+}
+
+static type
+pop_init_ref (type_val match)
+{
+  type t = make_type (match);
+  return pop_init_ref_t (t);
+}
+
+/* Pop a reference type or a return address.  */
+static type
+pop_ref_or_return (void)
+{
+  type t = pop_raw ();
+  if (! type_isreference (&t) && t.key != return_address_type)
+    verify_fail ("expected reference or return address on stack");
+  return t;
+}
+
+static void
+vfy_push_type_t (type t)
+{
+  int depth;
+  state *s = vfr->current_state;
+  /* If T is a numeric type like short, promote it to int.  */
+  promote_type (&t);
+
+  depth = type_depth (&t);
+
+  if (s->stackdepth + depth > vfr->current_method->max_stack)
+    verify_fail ("stack overflow");
+  s->stack[s->stacktop++] = t;
+  s->stackdepth += depth;
+}
+
+static void
+vfy_push_type (type_val tval)
+{
+  type t = make_type (tval);
+  return vfy_push_type_t (t);
+}
+
+#define push_type vfy_push_type
+#define push_type_t vfy_push_type_t
+
+static void
+set_variable (int index, type t)
+{
+  int depth;
+  state *s = vfr->current_state;
+  /* If T is a numeric type like short, promote it to int.  */
+  promote_type (&t);
+
+  depth = type_depth (&t);
+  if (index > vfr->current_method->max_locals - depth)
+    verify_fail ("invalid local variable");
+  s->locals[index] = t;
+
+  if (depth == 2)
+    init_type_from_tag (&s->locals[index + 1], continuation_type);
+  if (index > 0 && type_iswide (&s->locals[index - 1]))
+    init_type_from_tag (&s->locals[index - 1], unsuitable_type);
+}
+
+static type
+get_variable_t (int index, type *t)
+{
+  state *s = vfr->current_state;
+  int depth = type_depth (t);
+  if (index > vfr->current_method->max_locals - depth)
+    verify_fail ("invalid local variable");
+  if (! types_compatible (t, &s->locals[index]))
+    verify_fail ("incompatible type in local variable");
+  if (depth == 2)
+    {
+      type cont = make_type (continuation_type);
+      if (! types_compatible (&s->locals[index + 1], &cont))
+	verify_fail ("invalid local variable");
+    }
+  return s->locals[index];
+}
+
+static type
+get_variable (int index, type_val v)
+{
+  type t = make_type (v);
+  return get_variable_t (index, &t);
+}
+
+/* Make sure ARRAY is an array type and that its elements are
+   compatible with type ELEMENT.  Returns the actual element type.  */
+static type
+require_array_type_t (type array, type element)
+{
+  type t;
+  /* An odd case.  Here we just pretend that everything went ok.  If
+     the requested element type is some kind of reference, return
+     the null type instead.  */
+  if (type_isnull (&array))
+    return type_isreference (&element) ? make_type (null_type) : element;
+
+  if (! type_isarray (&array))
+    verify_fail ("array required");
+
+  t = type_array_element (&array);
+  if (! types_compatible (&element, &t))
+    {
+      /* Special case for byte arrays, which must also be boolean
+         arrays.  */
+      bool ok = true;
+      if (element.key == byte_type)
+	{
+	  type e2 = make_type (boolean_type);
+	  ok = types_compatible (&e2, &t);
+	}
+      if (! ok)
+	verify_fail ("incompatible array element type");
+    }
+
+  /* Return T and not ELEMENT, because T might be specialized.  */
+  return t;
+}
+
+static type
+require_array_type (type array, type_val element)
+{
+  type t = make_type (element);
+  return require_array_type_t (array, t);
+}
+
+static jint
+get_byte (void)
+{
+  if (vfr->PC >= vfr->current_method->code_length)
+    verify_fail ("premature end of bytecode");
+  return (jint) vfr->bytecode[vfr->PC++] & 0xff;
+}
+
+static jint
+get_ushort (void)
+{
+  jint b1 = get_byte ();
+  jint b2 = get_byte ();
+  return (jint) ((b1 << 8) | b2) & 0xffff;
+}
+
+static jint
+get_short (void)
+{
+  jint b1 = get_byte ();
+  jint b2 = get_byte ();
+  jshort s = (b1 << 8) | b2;
+  return (jint) s;
+}
+
+static jint
+get_int (void)
+{
+  jint b1 = get_byte ();
+  jint b2 = get_byte ();
+  jint b3 = get_byte ();
+  jint b4 = get_byte ();
+  return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
+}
+
+static int
+compute_jump (int offset)
+{
+  int npc = vfr->start_PC + offset;
+  if (npc < 0 || npc >= vfr->current_method->code_length)
+    verify_fail_pc ("branch out of range", vfr->start_PC);
+  return npc;
+}
+
+/* Add a new state to the state list at NPC.  */
+static state *
+add_new_state (int npc, state *old_state)
+{
+  state_list *nlink;
+  vfy_method *current_method = vfr->current_method;
+  state *new_state = make_state_copy (old_state, current_method->max_stack,
+				      current_method->max_locals);
+  debug_print ("== New state in add_new_state\n");
+  debug_print_state (new_state, "New", npc, current_method->max_stack,
+		    current_method->max_locals);
+
+  nlink = vfy_alloc (sizeof (state_list));
+  nlink->val = new_state;
+  nlink->next = vfr->states[npc];
+  vfr->states[npc] = nlink;
+  new_state->pc = npc;
+  return new_state;
+}
+
+/* Merge the indicated state into the state at the branch target and
+   schedule a new PC if there is a change.  NPC is the PC of the
+   branch target, and FROM_STATE is the state at the source of the
+   branch.  This method returns true if the destination state
+   changed and requires reverification, false otherwise.  */
+static void
+merge_into (int npc, state *from_state)
+{
+  /* Iterate over all target states and merge our state into each,
+     if applicable.  FIXME one improvement we could make here is
+     "state destruction".  Merging a new state into an existing one
+     might cause a return_address_type to be merged to
+     unsuitable_type.  In this case the resulting state may now be
+     mergeable with other states currently held in parallel at this
+     location.  So in this situation we could pairwise compare and
+     reduce the number of parallel states.  */
+  state_list *iter;
+  bool applicable = false;
+  for (iter = vfr->states[npc]; iter != NULL; iter = iter->next)
+    {
+      state *new_state = iter->val;
+      vfy_method *current_method = vfr->current_method;
+
+      if (state_mergeable_p (new_state, from_state,
+					current_method->max_locals))
+	{
+	  bool changed;
+	  applicable = true;
+
+	  debug_print ("== Merge states in merge_into\n");
+	  debug_print_state (from_state, "Frm", vfr->start_PC, current_method->max_stack,
+			     current_method->max_locals);
+	  debug_print_state (new_state, " To", npc, current_method->max_stack,
+			    current_method->max_locals);
+	  changed = merge_states (new_state, from_state,
+				  current_method->max_locals);
+	  debug_print_state (new_state, "New", npc, current_method->max_stack,
+			    current_method->max_locals);
+
+	  if (changed)
+	    state_reverify (new_state);
+	}
+    }
+
+  if (! applicable)
+    {
+      /* Either we don't yet have a state at NPC, or we have a
+         return-address type that is in conflict with all existing
+         state.  So, we need to create a new entry.  */
+      state *new_state = add_new_state (npc, from_state);
+      /* A new state added in this way must always be reverified.  */
+      state_reverify (new_state);
+    }
+}
+
+static void
+push_jump (int offset)
+{
+  int npc = compute_jump (offset);
+  /* According to the JVM Spec, we need to check for uninitialized
+     objects here.  However, this does not actually affect type
+     safety, and the Eclipse java compiler generates code that
+     violates this constraint.  */
+  merge_into (npc, vfr->current_state);
+}
+
+static void
+push_exception_jump (type t, int pc)
+{
+  state s;
+  /* According to the JVM Spec, we need to check for uninitialized
+     objects here.  However, this does not actually affect type
+     safety, and the Eclipse java compiler generates code that
+     violates this constraint.  */
+  copy_state_with_stack (&s, vfr->current_state, 
+			 vfr->current_method->max_stack,
+			 vfr->current_method->max_locals);
+  if (vfr->current_method->max_stack < 1)
+    verify_fail ("stack overflow at exception handler");
+  state_set_exception (&s, &t, vfr->current_method->max_stack);
+  merge_into (pc, &s);
+  /* FIXME: leak.. need free_state or GC */
+}
+
+static state *
+pop_jump (void)
+{
+  state *new_state = vfr->next_verify_state;
+  if (new_state == INVALID_STATE)
+    verify_fail ("programmer error in pop_jump");
+  if (new_state != NULL)
+    {
+      vfr->next_verify_state = new_state->next;
+      new_state->next = INVALID_STATE;
+    }
+  return new_state;
+}
+
+static void
+invalidate_pc (void)
+{
+  vfr->PC = NO_NEXT;
+}
+
+static void
+note_branch_target (int pc)
+{
+  /* Don't check `pc <= PC', because we've advanced PC after
+     fetching the target and we haven't yet checked the next
+     instruction.  */
+  if (pc < vfr->PC && ! (vfr->flags[pc] & FLAG_INSN_START))
+    verify_fail_pc ("branch not to instruction start", vfr->start_PC);
+  vfr->flags[pc] |= FLAG_BRANCH_TARGET;
+}
+
+static void
+skip_padding (void)
+{
+  while ((vfr->PC % 4) > 0)
+    if (get_byte () != 0)
+      verify_fail ("found nonzero padding byte");
+}
+
+/* Do the work for a `ret' instruction.  INDEX is the index into the
+   local variables.  */
+static void
+handle_ret_insn (int index)
+{
+  type ret = make_type (return_address_type);
+  type ret_addr = get_variable_t (index, &ret);
+  /* It would be nice if we could do this.  However, the JVM Spec
+     doesn't say that this is what happens.  It is implied that
+     reusing a return address is invalid, but there's no actual
+     prohibition against it.  */
+  /* set_variable (index, unsuitable_type); */
+
+  int npc = type_get_pc (&ret_addr);
+  /* We might be returning to a `jsr' that is at the end of the
+     bytecode.  This is ok if we never return from the called
+     subroutine, but if we see this here it is an error.  */
+  if (npc >= vfr->current_method->code_length)
+    verify_fail ("fell off end");
+
+  /* According to the JVM Spec, we need to check for uninitialized
+     objects here.  However, this does not actually affect type
+     safety, and the Eclipse java compiler generates code that
+     violates this constraint.  */
+  merge_into (npc, vfr->current_state);
+  invalidate_pc ();
+}
+
+static void handle_jsr_insn (int offset)
+{
+  type ret_addr;
+  int npc = compute_jump (offset);
+
+  /* According to the JVM Spec, we need to check for uninitialized
+     objects here.  However, this does not actually affect type
+     safety, and the Eclipse java compiler generates code that
+     violates this constraint.  */
+
+  /* Modify our state as appropriate for entry into a subroutine.  */
+  ret_addr = make_type (return_address_type);
+  type_set_return_address (&ret_addr, vfr->PC);
+  vfy_push_type_t (ret_addr);
+  merge_into (npc, vfr->current_state);
+  invalidate_pc ();
+}
+
+static vfy_jclass
+construct_primitive_array_type (type_val prim)
+{
+  vfy_jclass k = NULL;
+  switch (prim)
+    {
+    case boolean_type:
+    case char_type:
+    case float_type:
+    case double_type:
+    case byte_type:
+    case short_type:
+    case int_type:
+    case long_type:
+      k = vfy_get_primitive_type ((int) prim);
+      break;
+
+    /* These aren't used here but we call them out to avoid
+       warnings.  */
+    case void_type:
+    case unsuitable_type:
+    case return_address_type:
+    case continuation_type:
+    case reference_type:
+    case null_type:
+    case uninitialized_reference_type:
+    default:
+      verify_fail ("unknown type in construct_primitive_array_type");
+    }
+  k = vfy_get_array_class (k);
+  return k;
+}
+
+/* This pass computes the location of branch targets and also
+   instruction starts.  */
+static void
+branch_prepass (void)
+{
+  int i, pc;
+  vfr->flags = (char *) vfy_alloc (vfr->current_method->code_length);
+
+  for (i = 0; i < vfr->current_method->code_length; ++i)
+    vfr->flags[i] = 0;
+
+  vfr->PC = 0;
+  while (vfr->PC < vfr->current_method->code_length)
+    {
+      java_opcode opcode;
+      /* Set `start_PC' early so that error checking can have the
+         correct value.  */
+      vfr->start_PC = vfr->PC;
+      vfr->flags[vfr->PC] |= FLAG_INSN_START;
+
+      opcode = (java_opcode) vfr->bytecode[vfr->PC++];
+      switch (opcode)
+	{
+	case op_nop:
+	case op_aconst_null:
+	case op_iconst_m1:
+	case op_iconst_0:
+	case op_iconst_1:
+	case op_iconst_2:
+	case op_iconst_3:
+	case op_iconst_4:
+	case op_iconst_5:
+	case op_lconst_0:
+	case op_lconst_1:
+	case op_fconst_0:
+	case op_fconst_1:
+	case op_fconst_2:
+	case op_dconst_0:
+	case op_dconst_1:
+	case op_iload_0:
+	case op_iload_1:
+	case op_iload_2:
+	case op_iload_3:
+	case op_lload_0:
+	case op_lload_1:
+	case op_lload_2:
+	case op_lload_3:
+	case op_fload_0:
+	case op_fload_1:
+	case op_fload_2:
+	case op_fload_3:
+	case op_dload_0:
+	case op_dload_1:
+	case op_dload_2:
+	case op_dload_3:
+	case op_aload_0:
+	case op_aload_1:
+	case op_aload_2:
+	case op_aload_3:
+	case op_iaload:
+	case op_laload:
+	case op_faload:
+	case op_daload:
+	case op_aaload:
+	case op_baload:
+	case op_caload:
+	case op_saload:
+	case op_istore_0:
+	case op_istore_1:
+	case op_istore_2:
+	case op_istore_3:
+	case op_lstore_0:
+	case op_lstore_1:
+	case op_lstore_2:
+	case op_lstore_3:
+	case op_fstore_0:
+	case op_fstore_1:
+	case op_fstore_2:
+	case op_fstore_3:
+	case op_dstore_0:
+	case op_dstore_1:
+	case op_dstore_2:
+	case op_dstore_3:
+	case op_astore_0:
+	case op_astore_1:
+	case op_astore_2:
+	case op_astore_3:
+	case op_iastore:
+	case op_lastore:
+	case op_fastore:
+	case op_dastore:
+	case op_aastore:
+	case op_bastore:
+	case op_castore:
+	case op_sastore:
+	case op_pop:
+	case op_pop2:
+	case op_dup:
+	case op_dup_x1:
+	case op_dup_x2:
+	case op_dup2:
+	case op_dup2_x1:
+	case op_dup2_x2:
+	case op_swap:
+	case op_iadd:
+	case op_isub:
+	case op_imul:
+	case op_idiv:
+	case op_irem:
+	case op_ishl:
+	case op_ishr:
+	case op_iushr:
+	case op_iand:
+	case op_ior:
+	case op_ixor:
+	case op_ladd:
+	case op_lsub:
+	case op_lmul:
+	case op_ldiv:
+	case op_lrem:
+	case op_lshl:
+	case op_lshr:
+	case op_lushr:
+	case op_land:
+	case op_lor:
+	case op_lxor:
+	case op_fadd:
+	case op_fsub:
+	case op_fmul:
+	case op_fdiv:
+	case op_frem:
+	case op_dadd:
+	case op_dsub:
+	case op_dmul:
+	case op_ddiv:
+	case op_drem:
+	case op_ineg:
+	case op_i2b:
+	case op_i2c:
+	case op_i2s:
+	case op_lneg:
+	case op_fneg:
+	case op_dneg:
+	case op_i2l:
+	case op_i2f:
+	case op_i2d:
+	case op_l2i:
+	case op_l2f:
+	case op_l2d:
+	case op_f2i:
+	case op_f2l:
+	case op_f2d:
+	case op_d2i:
+	case op_d2l:
+	case op_d2f:
+	case op_lcmp:
+	case op_fcmpl:
+	case op_fcmpg:
+	case op_dcmpl:
+	case op_dcmpg:
+	case op_monitorenter:
+	case op_monitorexit:
+	case op_ireturn:
+	case op_lreturn:
+	case op_freturn:
+	case op_dreturn:
+	case op_areturn:
+	case op_return:
+	case op_athrow:
+	case op_arraylength:
+	  break;
+
+	case op_bipush:
+	case op_ldc:
+	case op_iload:
+	case op_lload:
+	case op_fload:
+	case op_dload:
+	case op_aload:
+	case op_istore:
+	case op_lstore:
+	case op_fstore:
+	case op_dstore:
+	case op_astore:
+	case op_ret:
+	case op_newarray:
+	  get_byte ();
+	  break;
+
+	case op_iinc:
+	case op_sipush:
+	case op_ldc_w:
+	case op_ldc2_w:
+	case op_getstatic:
+	case op_getfield:
+	case op_putfield:
+	case op_putstatic:
+	case op_new:
+	case op_anewarray:
+	case op_instanceof:
+	case op_checkcast:
+	case op_invokespecial:
+	case op_invokestatic:
+	case op_invokevirtual:
+	  get_short ();
+	  break;
+
+	case op_multianewarray:
+	  get_short ();
+	  get_byte ();
+	  break;
+
+	case op_jsr:
+	case op_ifeq:
+	case op_ifne:
+	case op_iflt:
+	case op_ifge:
+	case op_ifgt:
+	case op_ifle:
+	case op_if_icmpeq:
+	case op_if_icmpne:
+	case op_if_icmplt:
+	case op_if_icmpge:
+	case op_if_icmpgt:
+	case op_if_icmple:
+	case op_if_acmpeq:
+	case op_if_acmpne:
+	case op_ifnull:
+	case op_ifnonnull:
+	case op_goto:
+	  note_branch_target (compute_jump (get_short ()));
+	  break;
+
+	case op_tableswitch:
+	  {
+	    jint low, hi;
+	    skip_padding ();
+	    note_branch_target (compute_jump (get_int ()));
+	    low = get_int ();
+	    hi = get_int ();
+	    if (low > hi)
+	      verify_fail_pc ("invalid tableswitch", vfr->start_PC);
+	    for (i = low; i <= hi; ++i)
+	      note_branch_target (compute_jump (get_int ()));
+	  }
+	  break;
+
+	case op_lookupswitch:
+	  {
+	    int npairs;
+	    skip_padding ();
+	    note_branch_target (compute_jump (get_int ()));
+	    npairs = get_int ();
+	    if (npairs < 0)
+	      verify_fail_pc ("too few pairs in lookupswitch", vfr->start_PC);
+	    while (npairs-- > 0)
+	      {
+		get_int ();
+		note_branch_target (compute_jump (get_int ()));
+	      }
+	  }
+	  break;
+
+	case op_invokeinterface:
+	  get_short ();
+	  get_byte ();
+	  get_byte ();
+	  break;
+
+	case op_wide:
+	  {
+	    opcode = (java_opcode) get_byte ();
+	    get_short ();
+	    if (opcode == op_iinc)
+	      get_short ();
+	  }
+	  break;
+
+	case op_jsr_w:
+	case op_goto_w:
+	  note_branch_target (compute_jump (get_int ()));
+	  break;
+
+#if 0
+	/* These are unused here, but we call them out explicitly
+	   so that -Wswitch-enum doesn't complain.  */
+	case op_putfield_1:
+	case op_putfield_2:
+	case op_putfield_4:
+	case op_putfield_8:
+	case op_putfield_a:
+	case op_putstatic_1:
+	case op_putstatic_2:
+	case op_putstatic_4:
+	case op_putstatic_8:
+	case op_putstatic_a:
+	case op_getfield_1:
+	case op_getfield_2s:
+	case op_getfield_2u:
+	case op_getfield_4:
+	case op_getfield_8:
+	case op_getfield_a:
+	case op_getstatic_1:
+	case op_getstatic_2s:
+	case op_getstatic_2u:
+	case op_getstatic_4:
+	case op_getstatic_8:
+	case op_getstatic_a:
+#endif /* VFY_FAST_OPCODES  */
+	default:
+	  verify_fail_pc ("unrecognized instruction in branch_prepass",
+			  vfr->start_PC);
+	}
+
+      /* See if any previous branch tried to branch to the middle of
+         this instruction.  */
+      for (pc = vfr->start_PC + 1; pc < vfr->PC; ++pc)
+	{
+	  if ((vfr->flags[pc] & FLAG_BRANCH_TARGET))
+	    verify_fail_pc ("branch to middle of instruction", pc);
+	}
+    }
+
+  /* Verify exception handlers.  */
+  for (i = 0; i < vfr->current_method->exc_count; ++i)
+    {
+      int handler, start, end, htype;
+      vfy_get_exception (vfr->exception, i, &handler, &start, &end, &htype);
+      if (! (vfr->flags[handler] & FLAG_INSN_START))
+	verify_fail_pc ("exception handler not at instruction start", 
+			handler);
+      if (! (vfr->flags[start] & FLAG_INSN_START))
+	verify_fail_pc ("exception start not at instruction start", start);
+      if (end != vfr->current_method->code_length
+	  && ! (vfr->flags[end] & FLAG_INSN_START))
+	verify_fail_pc ("exception end not at instruction start", end);
+
+      vfr->flags[handler] |= FLAG_BRANCH_TARGET;
+    }
+}
+
+static void
+check_pool_index (int index)
+{
+  if (index < 0 || index >= vfy_get_constants_size (vfr->current_class))
+    verify_fail_pc ("constant pool index out of range", vfr->start_PC);
+}
+
+static type
+check_class_constant (int index)
+{
+  type t;
+  vfy_constants *pool;
+
+  check_pool_index (index);
+  pool = vfy_get_constants (vfr->current_class);
+  if (vfy_tag (pool, index) == JV_CONSTANT_ResolvedClass)
+    init_type_from_class (&t, vfy_get_pool_class (pool, index));
+  else if (vfy_tag (pool, index) == JV_CONSTANT_Class)
+    init_type_from_string (&t, vfy_get_pool_string (pool, index));
+  else
+    verify_fail_pc ("expected class constant", vfr->start_PC);      
+  return t;
+}
+
+static type
+check_constant (int index)
+{
+  type t;
+  vfy_constants *pool;
+
+  check_pool_index (index);
+  pool = vfy_get_constants (vfr->current_class);
+  if (vfy_tag (pool, index) == JV_CONSTANT_ResolvedString
+      || vfy_tag (pool, index) == JV_CONSTANT_String)
+    init_type_from_class (&t, vfy_string_type ());
+  else if (vfy_tag (pool, index) == JV_CONSTANT_Integer)
+    init_type_from_tag (&t, int_type);
+  else if (vfy_tag (pool, index) == JV_CONSTANT_Float)
+    init_type_from_tag (&t, float_type);
+  else
+    verify_fail_pc ("String, int, or float constant expected", vfr->start_PC);
+  return t;
+}
+
+static type
+check_wide_constant (int index)
+{
+  type t;
+  vfy_constants *pool;
+
+  check_pool_index (index);
+  pool = vfy_get_constants (vfr->current_class);
+  if (vfy_tag (pool, index) == JV_CONSTANT_Long)
+    init_type_from_tag (&t, long_type);
+  else if (vfy_tag (pool, index) == JV_CONSTANT_Double)
+    init_type_from_tag (&t, double_type);
+  else
+    verify_fail_pc ("long or double constant expected", vfr->start_PC);
+  return t;
+}
+
+/* Helper for both field and method.  These are laid out the same in
+   the constant pool.  */
+static type
+handle_field_or_method (int index, int expected,
+			vfy_string *name, vfy_string *fmtype)
+{
+  vfy_uint_16 class_index, name_and_type_index;
+  vfy_uint_16 name_index, desc_index;
+  vfy_constants *pool;
+
+  check_pool_index (index);
+  pool = vfy_get_constants (vfr->current_class);
+  if (vfy_tag (pool, index) != expected)
+    verify_fail_pc ("didn't see expected constant", vfr->start_PC);
+  /* Once we know we have a Fieldref or Methodref we assume that it
+     is correctly laid out in the constant pool.  I think the code
+     in defineclass.cc guarantees this.  */
+  vfy_load_indexes (pool, index, &class_index, &name_and_type_index);
+  vfy_load_indexes (pool, name_and_type_index, &name_index, &desc_index);
+
+  *name = vfy_get_pool_string (pool, name_index);
+  *fmtype = vfy_get_pool_string (pool, desc_index);
+
+  return check_class_constant (class_index);
+}
+
+/* Return field's type, compute class' type if requested.  */
+static type
+check_field_constant (int index, type *class_type)
+{
+  vfy_string name, field_type;
+  const char *typec;
+  int len;
+  type t;
+
+  type ct = handle_field_or_method (index,
+				    JV_CONSTANT_Fieldref,
+				    &name, &field_type);
+  if (class_type)
+    *class_type = ct;
+  typec = vfy_string_bytes (field_type);
+  len = vfy_string_length (field_type);
+  if (typec[0] == '[' || typec[0] == 'L')
+    init_type_from_string (&t, field_type);
+  else
+    init_type_from_tag (&t, get_type_val_for_signature (typec[0]));
+  return t;
+}
+
+static type
+check_method_constant (int index, bool is_interface,
+			    vfy_string *method_name,
+			    vfy_string *method_signature)
+{
+  return handle_field_or_method (index,
+				 (is_interface
+				  ? JV_CONSTANT_InterfaceMethodref
+				  : JV_CONSTANT_Methodref),
+				 method_name, method_signature);
+}
+
+static char *
+get_one_type (char *p, type *t)
+{
+  const char *start = p;
+  vfy_jclass k;
+  type_val rt;
+  char v;
+
+  int arraycount = 0;
+  while (*p == '[')
+    {
+      ++arraycount;
+      ++p;
+    }
+
+  v = *p++;
+
+  if (v == 'L')
+    {
+      vfy_string name;
+      while (*p != ';')
+	++p;
+      ++p;
+      name = vfy_get_string (start, p - start);
+      *t = make_type_from_string (name);
+      return p;
+    }
+
+  /* Casting to jchar here is ok since we are looking at an ASCII
+     character.  */
+  rt = get_type_val_for_signature (v);
+
+  if (arraycount == 0)
+    {
+      /* Callers of this function eventually push their arguments on
+         the stack.  So, promote them here.  */
+      type new_t = make_type (rt);
+      vfy_promote_type (&new_t);
+      *t = new_t;
+      return p;
+    }
+
+  k = construct_primitive_array_type (rt);
+  while (--arraycount > 0)
+    k = vfy_get_array_class (k);
+  *t = make_type_from_class (k);
+  return p;
+}
+
+static void 
+compute_argument_types (vfy_string signature, type *types)
+{
+  int i;
+  char *p = (char *) vfy_string_bytes (signature);
+
+  /* Skip `('.  */
+  ++p;
+
+  i = 0;
+  while (*p != ')')
+    p = get_one_type (p, &types[i++]);
+}
+
+static type
+compute_return_type (vfy_string signature)
+{
+  char *p = (char *) vfy_string_bytes (signature);
+  type t;
+  while (*p != ')')
+    ++p;
+  ++p;
+  get_one_type (p, &t);
+  return t;
+}
+
+static void
+check_return_type (type onstack)
+{
+  type rt = compute_return_type (vfy_get_signature (vfr->current_method));
+  if (! types_compatible (&rt, &onstack))
+    verify_fail ("incompatible return type");
+}
+
+/* Initialize the stack for the new method.  Returns true if this
+   method is an instance initializer.  */
+static bool
+initialize_stack (void)
+{
+  int arg_count, i;
+  int var = 0;
+  bool is_init = vfy_strings_equal (vfy_get_method_name (vfr->current_method),
+				    vfy_init_name());
+  bool is_clinit = vfy_strings_equal (vfy_get_method_name (vfr->current_method),
+				      vfy_clinit_name());
+
+  if (! vfy_is_static (vfr->current_method))
+    {
+      type kurr = make_type_from_class (vfr->current_class);
+      if (is_init)
+	{
+	  type_set_uninitialized (&kurr, SELF);
+	  is_init = true;
+	}
+      else if (is_clinit)
+	verify_fail ("<clinit> method must be static");
+      set_variable (0, kurr);
+      state_set_this_type (vfr->current_state, &kurr);
+      ++var;
+    }
+  else
+    {
+      if (is_init)
+	verify_fail ("<init> method must be non-static");
+    }
+
+  /* We have to handle wide arguments specially here.  */
+  arg_count = vfy_count_arguments (vfy_get_signature (vfr->current_method));
+  {
+    type arg_types[arg_count];
+    compute_argument_types (vfy_get_signature (vfr->current_method), arg_types);
+    for (i = 0; i < arg_count; ++i)
+      {
+	set_variable (var, arg_types[i]);
+	++var;
+	if (type_iswide (&arg_types[i]))
+	  ++var;
+      }
+  }
+
+  return is_init;
+}
+
+static void
+verify_instructions_0 (void)
+{
+  int i;
+  bool this_is_init;
+
+  vfr->current_state = make_state (vfr->current_method->max_stack,
+				   vfr->current_method->max_locals);
+
+  vfr->PC = 0;
+  vfr->start_PC = 0;
+
+  /*  True if we are verifying an instance initializer.  */
+  this_is_init = initialize_stack ();
+
+  vfr->states = (state_list **) vfy_alloc (sizeof (state_list *)
+				      * vfr->current_method->code_length);
+
+  for (i = 0; i < vfr->current_method->code_length; ++i)
+    vfr->states[i] = NULL;
+
+  vfr->next_verify_state = NULL;
+
+  while (true)
+    {
+      java_opcode opcode;
+
+      /* If the PC was invalidated, get a new one from the work list.  */
+      if (vfr->PC == NO_NEXT)
+	{
+	  state *new_state = pop_jump ();
+	  /* If it is null, we're done.  */
+	  if (new_state == NULL)
+	    break;
+
+	  vfr->PC = state_get_pc (new_state);
+	  debug_print ("== State pop from pending list\n");
+	  /* Set up the current state.  */
+	  copy_state (vfr->current_state, new_state, 
+	    vfr->current_method->max_stack, vfr->current_method->max_locals);
+	}
+      else
+	{
+	  /* We only have to do this checking in the situation where
+	     control flow falls through from the previous
+	     instruction.  Otherwise merging is done at the time we
+	     push the branch.  */
+	  if (vfr->states[vfr->PC] != NULL)
+	    {
+	      /* We've already visited this instruction.  So merge
+	         the states together.  It is simplest, but not most
+	         efficient, to just always invalidate the PC here.  */
+	      merge_into (vfr->PC, vfr->current_state);
+	      invalidate_pc ();
+	      continue;
+	    }
+	}
+
+      /* Control can't fall off the end of the bytecode.  We need to
+         check this in both cases, not just the fall-through case,
+         because we don't check to see whether a `jsr' appears at
+         the end of the bytecode until we process a `ret'.  */
+      if (vfr->PC >= vfr->current_method->code_length)
+	verify_fail ("fell off end");
+      vfr->flags[vfr->PC] |= FLAG_INSN_SEEN;
+
+      /* We only have to keep saved state at branch targets.  If
+         we're at a branch target and the state here hasn't been set
+         yet, we set it now.  You might notice that `ret' targets
+         won't necessarily have FLAG_BRANCH_TARGET set.  This
+         doesn't matter, since those states will be filled in by
+         merge_into.  */
+      /* Note that other parts of the compiler assume that there is a
+	 label with a type map at PC=0.  */
+      if (vfr->states[vfr->PC] == NULL
+	  && (vfr->PC == 0 || (vfr->flags[vfr->PC] & FLAG_BRANCH_TARGET) != 0))
+	add_new_state (vfr->PC, vfr->current_state);
+
+      /* Set this before handling exceptions so that debug output is
+         sane.  */
+      vfr->start_PC = vfr->PC;
+
+      /* Update states for all active exception handlers.  Ordinarily
+         there are not many exception handlers.  So we simply run
+         through them all.  */
+      for (i = 0; i < vfr->current_method->exc_count; ++i)
+	{
+	  int hpc, start, end, htype;
+	  vfy_get_exception (vfr->exception, i, &hpc, &start, &end, &htype);
+	  if (vfr->PC >= start && vfr->PC < end)
+	    {
+	      type handler = make_type_from_class (vfy_throwable_type ());
+	      if (htype != 0)
+		handler = check_class_constant (htype);
+	      push_exception_jump (handler, hpc);
+	    }
+	}
+
+
+      debug_print_state (vfr->current_state, "   ", vfr->PC, 
+			 vfr->current_method->max_stack,
+			 vfr->current_method->max_locals);
+      opcode = (java_opcode) vfr->bytecode[vfr->PC++];
+      switch (opcode)
+	{
+	case op_nop:
+	  break;
+
+	case op_aconst_null:
+	  push_type (null_type);
+	  break;
+
+	case op_iconst_m1:
+	case op_iconst_0:
+	case op_iconst_1:
+	case op_iconst_2:
+	case op_iconst_3:
+	case op_iconst_4:
+	case op_iconst_5:
+	  push_type (int_type);
+	  break;
+
+	case op_lconst_0:
+	case op_lconst_1:
+	  push_type (long_type);
+	  break;
+
+	case op_fconst_0:
+	case op_fconst_1:
+	case op_fconst_2:
+	  push_type (float_type);
+	  break;
+
+	case op_dconst_0:
+	case op_dconst_1:
+	  push_type (double_type);
+	  break;
+
+	case op_bipush:
+	  get_byte ();
+	  push_type (int_type);
+	  break;
+
+	case op_sipush:
+	  get_short ();
+	  push_type (int_type);
+	  break;
+
+	case op_ldc:
+	  push_type_t (check_constant (get_byte ()));
+	  break;
+	case op_ldc_w:
+	  push_type_t (check_constant (get_ushort ()));
+	  break;
+	case op_ldc2_w:
+	  push_type_t (check_wide_constant (get_ushort ()));
+	  break;
+
+	case op_iload:
+	  push_type_t (get_variable (get_byte (), int_type));
+	  break;
+	case op_lload:
+	  push_type_t (get_variable (get_byte (), long_type));
+	  break;
+	case op_fload:
+	  push_type_t (get_variable (get_byte (), float_type));
+	  break;
+	case op_dload:
+	  push_type_t (get_variable (get_byte (), double_type));
+	  break;
+	case op_aload:
+	  push_type_t (get_variable (get_byte (), reference_type));
+	  break;
+
+	case op_iload_0:
+	case op_iload_1:
+	case op_iload_2:
+	case op_iload_3:
+	  push_type_t (get_variable (opcode - op_iload_0, int_type));
+	  break;
+	case op_lload_0:
+	case op_lload_1:
+	case op_lload_2:
+	case op_lload_3:
+	  push_type_t (get_variable (opcode - op_lload_0, long_type));
+	  break;
+	case op_fload_0:
+	case op_fload_1:
+	case op_fload_2:
+	case op_fload_3:
+	  push_type_t (get_variable (opcode - op_fload_0, float_type));
+	  break;
+	case op_dload_0:
+	case op_dload_1:
+	case op_dload_2:
+	case op_dload_3:
+	  push_type_t (get_variable (opcode - op_dload_0, double_type));
+	  break;
+	case op_aload_0:
+	case op_aload_1:
+	case op_aload_2:
+	case op_aload_3:
+	  push_type_t (get_variable (opcode - op_aload_0, reference_type));
+	  break;
+	case op_iaload:
+	  pop_type (int_type);
+	  push_type_t (require_array_type (pop_init_ref (reference_type),
+					 int_type));
+	  break;
+	case op_laload:
+	  pop_type (int_type);
+	  push_type_t (require_array_type (pop_init_ref (reference_type),
+					 long_type));
+	  break;
+	case op_faload:
+	  pop_type (int_type);
+	  push_type_t (require_array_type (pop_init_ref (reference_type),
+					 float_type));
+	  break;
+	case op_daload:
+	  pop_type (int_type);
+	  push_type_t (require_array_type (pop_init_ref (reference_type),
+					 double_type));
+	  break;
+	case op_aaload:
+	  pop_type (int_type);
+	  push_type_t (require_array_type (pop_init_ref (reference_type),
+					 reference_type));
+	  break;
+	case op_baload:
+	  pop_type (int_type);
+	  require_array_type (pop_init_ref (reference_type), byte_type);
+	  push_type (int_type);
+	  break;
+	case op_caload:
+	  pop_type (int_type);
+	  require_array_type (pop_init_ref (reference_type), char_type);
+	  push_type (int_type);
+	  break;
+	case op_saload:
+	  pop_type (int_type);
+	  require_array_type (pop_init_ref (reference_type), short_type);
+	  push_type (int_type);
+	  break;
+	case op_istore:
+	  set_variable (get_byte (), pop_type (int_type));
+	  break;
+	case op_lstore:
+	  set_variable (get_byte (), pop_type (long_type));
+	  break;
+	case op_fstore:
+	  set_variable (get_byte (), pop_type (float_type));
+	  break;
+	case op_dstore:
+	  set_variable (get_byte (), pop_type (double_type));
+	  break;
+	case op_astore:
+	  set_variable (get_byte (), pop_ref_or_return ());
+	  break;
+	case op_istore_0:
+	case op_istore_1:
+	case op_istore_2:
+	case op_istore_3:
+	  set_variable (opcode - op_istore_0, pop_type (int_type));
+	  break;
+	case op_lstore_0:
+	case op_lstore_1:
+	case op_lstore_2:
+	case op_lstore_3:
+	  set_variable (opcode - op_lstore_0, pop_type (long_type));
+	  break;
+	case op_fstore_0:
+	case op_fstore_1:
+	case op_fstore_2:
+	case op_fstore_3:
+	  set_variable (opcode - op_fstore_0, pop_type (float_type));
+	  break;
+	case op_dstore_0:
+	case op_dstore_1:
+	case op_dstore_2:
+	case op_dstore_3:
+	  set_variable (opcode - op_dstore_0, pop_type (double_type));
+	  break;
+	case op_astore_0:
+	case op_astore_1:
+	case op_astore_2:
+	case op_astore_3:
+	  set_variable (opcode - op_astore_0, pop_ref_or_return ());
+	  break;
+	case op_iastore:
+	  pop_type (int_type);
+	  pop_type (int_type);
+	  require_array_type (pop_init_ref (reference_type), int_type);
+	  break;
+	case op_lastore:
+	  pop_type (long_type);
+	  pop_type (int_type);
+	  require_array_type (pop_init_ref (reference_type), long_type);
+	  break;
+	case op_fastore:
+	  pop_type (float_type);
+	  pop_type (int_type);
+	  require_array_type (pop_init_ref (reference_type), float_type);
+	  break;
+	case op_dastore:
+	  pop_type (double_type);
+	  pop_type (int_type);
+	  require_array_type (pop_init_ref (reference_type), double_type);
+	  break;
+	case op_aastore:
+	  pop_type (reference_type);
+	  pop_type (int_type);
+	  require_array_type (pop_init_ref (reference_type), reference_type);
+	  break;
+	case op_bastore:
+	  pop_type (int_type);
+	  pop_type (int_type);
+	  require_array_type (pop_init_ref (reference_type), byte_type);
+	  break;
+	case op_castore:
+	  pop_type (int_type);
+	  pop_type (int_type);
+	  require_array_type (pop_init_ref (reference_type), char_type);
+	  break;
+	case op_sastore:
+	  pop_type (int_type);
+	  pop_type (int_type);
+	  require_array_type (pop_init_ref (reference_type), short_type);
+	  break;
+	case op_pop:
+	  pop32 ();
+	  break;
+	case op_pop2:
+	  {
+	    type t = pop_raw ();
+	    if (! type_iswide (&t))
+	      pop32 ();
+	  }
+	  break;
+	case op_dup:
+	  {
+	    type t = pop32 ();
+	    push_type_t (t);
+	    push_type_t (t);
+	  }
+	  break;
+	case op_dup_x1:
+	  {
+	    type t1 = pop32 ();
+	    type t2 = pop32 ();
+	    push_type_t (t1);
+	    push_type_t (t2);
+	    push_type_t (t1);
+	  }
+	  break;
+	case op_dup_x2:
+	  {
+	    type t1 = pop32 ();
+	    type t2 = pop_raw ();
+	    if (! type_iswide (&t2))
+	      {
+		type t3 = pop32 ();
+		push_type_t (t1);
+		push_type_t (t3);
+	      }
+	    else
+	      push_type_t (t1);
+	    push_type_t (t2);
+	    push_type_t (t1);
+	  }
+	  break;
+	case op_dup2:
+	  {
+	    type t = pop_raw ();
+	    if (! type_iswide (&t))
+	      {
+		type t2 = pop32 ();
+		push_type_t (t2);
+		push_type_t (t);
+		push_type_t (t2);
+	      }
+	    else
+	      push_type_t (t);
+	    push_type_t (t);
+	  }
+	  break;
+	case op_dup2_x1:
+	  {
+	    type t1 = pop_raw ();
+	    type t2 = pop32 ();
+	    if (! type_iswide (&t1))
+	      {
+		type t3 = pop32 ();
+		push_type_t (t2);
+		push_type_t (t1);
+		push_type_t (t3);
+	      }
+	    else
+	      push_type_t (t1);
+	    push_type_t (t2);
+	    push_type_t (t1);
+	  }
+	  break;
+	case op_dup2_x2:
+	  {
+	    type t1 = pop_raw ();
+	    if (type_iswide (&t1))
+	      {
+		type t2 = pop_raw ();
+		if (type_iswide (&t2))
+		  {
+		    push_type_t (t1);
+		    push_type_t (t2);
+		  }
+		else
+		  {
+		    type t3 = pop32 ();
+		    push_type_t (t1);
+		    push_type_t (t3);
+		    push_type_t (t2);
+		  }
+		push_type_t (t1);
+	      }
+	    else
+	      {
+		type t2 = pop32 ();
+		type t3 = pop_raw ();
+		if (type_iswide (&t3))
+		  {
+		    push_type_t (t2);
+		    push_type_t (t1);
+		  }
+		else
+		  {
+		    type t4 = pop32 ();
+		    push_type_t (t2);
+		    push_type_t (t1);
+		    push_type_t (t4);
+		  }
+		push_type_t (t3);
+		push_type_t (t2);
+		push_type_t (t1);
+	      }
+	  }
+	  break;
+	case op_swap:
+	  {
+	    type t1 = pop32 ();
+	    type t2 = pop32 ();
+	    push_type_t (t1);
+	    push_type_t (t2);
+	  }
+	  break;
+	case op_iadd:
+	case op_isub:
+	case op_imul:
+	case op_idiv:
+	case op_irem:
+	case op_ishl:
+	case op_ishr:
+	case op_iushr:
+	case op_iand:
+	case op_ior:
+	case op_ixor:
+	  pop_type (int_type);
+	  push_type_t (pop_type (int_type));
+	  break;
+	case op_ladd:
+	case op_lsub:
+	case op_lmul:
+	case op_ldiv:
+	case op_lrem:
+	case op_land:
+	case op_lor:
+	case op_lxor:
+	  pop_type (long_type);
+	  push_type_t (pop_type (long_type));
+	  break;
+	case op_lshl:
+	case op_lshr:
+	case op_lushr:
+	  pop_type (int_type);
+	  push_type_t (pop_type (long_type));
+	  break;
+	case op_fadd:
+	case op_fsub:
+	case op_fmul:
+	case op_fdiv:
+	case op_frem:
+	  pop_type (float_type);
+	  push_type_t (pop_type (float_type));
+	  break;
+	case op_dadd:
+	case op_dsub:
+	case op_dmul:
+	case op_ddiv:
+	case op_drem:
+	  pop_type (double_type);
+	  push_type_t (pop_type (double_type));
+	  break;
+	case op_ineg:
+	case op_i2b:
+	case op_i2c:
+	case op_i2s:
+	  push_type_t (pop_type (int_type));
+	  break;
+	case op_lneg:
+	  push_type_t (pop_type (long_type));
+	  break;
+	case op_fneg:
+	  push_type_t (pop_type (float_type));
+	  break;
+	case op_dneg:
+	  push_type_t (pop_type (double_type));
+	  break;
+	case op_iinc:
+	  get_variable (get_byte (), int_type);
+	  get_byte ();
+	  break;
+	case op_i2l:
+	  pop_type (int_type);
+	  push_type (long_type);
+	  break;
+	case op_i2f:
+	  pop_type (int_type);
+	  push_type (float_type);
+	  break;
+	case op_i2d:
+	  pop_type (int_type);
+	  push_type (double_type);
+	  break;
+	case op_l2i:
+	  pop_type (long_type);
+	  push_type (int_type);
+	  break;
+	case op_l2f:
+	  pop_type (long_type);
+	  push_type (float_type);
+	  break;
+	case op_l2d:
+	  pop_type (long_type);
+	  push_type (double_type);
+	  break;
+	case op_f2i:
+	  pop_type (float_type);
+	  push_type (int_type);
+	  break;
+	case op_f2l:
+	  pop_type (float_type);
+	  push_type (long_type);
+	  break;
+	case op_f2d:
+	  pop_type (float_type);
+	  push_type (double_type);
+	  break;
+	case op_d2i:
+	  pop_type (double_type);
+	  push_type (int_type);
+	  break;
+	case op_d2l:
+	  pop_type (double_type);
+	  push_type (long_type);
+	  break;
+	case op_d2f:
+	  pop_type (double_type);
+	  push_type (float_type);
+	  break;
+	case op_lcmp:
+	  pop_type (long_type);
+	  pop_type (long_type);
+	  push_type (int_type);
+	  break;
+	case op_fcmpl:
+	case op_fcmpg:
+	  pop_type (float_type);
+	  pop_type (float_type);
+	  push_type (int_type);
+	  break;
+	case op_dcmpl:
+	case op_dcmpg:
+	  pop_type (double_type);
+	  pop_type (double_type);
+	  push_type (int_type);
+	  break;
+	case op_ifeq:
+	case op_ifne:
+	case op_iflt:
+	case op_ifge:
+	case op_ifgt:
+	case op_ifle:
+	  pop_type (int_type);
+	  push_jump (get_short ());
+	  break;
+	case op_if_icmpeq:
+	case op_if_icmpne:
+	case op_if_icmplt:
+	case op_if_icmpge:
+	case op_if_icmpgt:
+	case op_if_icmple:
+	  pop_type (int_type);
+	  pop_type (int_type);
+	  push_jump (get_short ());
+	  break;
+	case op_if_acmpeq:
+	case op_if_acmpne:
+	  pop_type (reference_type);
+	  pop_type (reference_type);
+	  push_jump (get_short ());
+	  break;
+	case op_goto:
+	  push_jump (get_short ());
+	  invalidate_pc ();
+	  break;
+	case op_jsr:
+	  handle_jsr_insn (get_short ());
+	  break;
+	case op_ret:
+	  handle_ret_insn (get_byte ());
+	  break;
+	case op_tableswitch:
+	  {
+	    int i;
+	    jint low, high;
+	    pop_type (int_type);
+	    skip_padding ();
+	    push_jump (get_int ());
+	    low = get_int ();
+	    high = get_int ();
+	    /* Already checked LOW -vs- HIGH.  */
+	    for (i = low; i <= high; ++i)
+	      push_jump (get_int ());
+	    invalidate_pc ();
+	  }
+	  break;
+
+	case op_lookupswitch:
+	  {
+	    int i;
+	    jint npairs, lastkey;
+
+	    pop_type (int_type);
+	    skip_padding ();
+	    push_jump (get_int ());
+	    npairs = get_int ();
+	    /* Already checked NPAIRS >= 0.  */
+	    lastkey = 0;
+	    for (i = 0; i < npairs; ++i)
+	      {
+		jint key = get_int ();
+		if (i > 0 && key <= lastkey)
+		  verify_fail_pc ("lookupswitch pairs unsorted", vfr->start_PC);
+		lastkey = key;
+		push_jump (get_int ());
+	      }
+	    invalidate_pc ();
+	  }
+	  break;
+	case op_ireturn:
+	  check_return_type (pop_type (int_type));
+	  invalidate_pc ();
+	  break;
+	case op_lreturn:
+	  check_return_type (pop_type (long_type));
+	  invalidate_pc ();
+	  break;
+	case op_freturn:
+	  check_return_type (pop_type (float_type));
+	  invalidate_pc ();
+	  break;
+	case op_dreturn:
+	  check_return_type (pop_type (double_type));
+	  invalidate_pc ();
+	  break;
+	case op_areturn:
+	  check_return_type (pop_init_ref (reference_type));
+	  invalidate_pc ();
+	  break;
+	case op_return:
+	  /* We only need to check this when the return type is
+	     void, because all instance initializers return void.  */
+	  if (this_is_init)
+	    state_check_this_initialized (vfr->current_state);
+	  check_return_type (make_type (void_type));
+	  invalidate_pc ();
+	  break;
+	case op_getstatic:
+	  push_type_t (check_field_constant (get_ushort (), NULL));
+	  break;
+	case op_putstatic:
+	  pop_type_t (check_field_constant (get_ushort (), NULL));
+	  break;
+	case op_getfield:
+	  {
+	    type klass;
+	    type field = check_field_constant (get_ushort (), &klass);
+	    pop_type_t (klass);
+	    push_type_t (field);
+	  }
+	  break;
+	case op_putfield:
+	  {
+	    type klass;
+	    type field = check_field_constant (get_ushort (), &klass);
+	    pop_type_t (field);
+
+	    /* We have an obscure special case here: we can use
+	       `putfield' on a field declared in this class, even if
+	       `this' has not yet been initialized.  */
+	    if (! type_initialized (&vfr->current_state->this_type)
+		&& vfr->current_state->this_type.pc == SELF)
+	      type_set_uninitialized (&klass, SELF);
+	    pop_type_t (klass);
+	  }
+	  break;
+
+	case op_invokevirtual:
+	case op_invokespecial:
+	case op_invokestatic:
+	case op_invokeinterface:
+	  {
+	    vfy_string method_name, method_signature;
+	    const char *namec;
+	    int i, arg_count;
+	    type rt;
+	    bool is_init = false;
+
+	    type class_type
+	      = check_method_constant (get_ushort (),
+				       opcode == op_invokeinterface,
+				       &method_name,
+				       &method_signature);
+	    /* NARGS is only used when we're processing
+	       invokeinterface.  It is simplest for us to compute it
+	       here and then verify it later.  */
+	    int nargs = 0;
+	    if (opcode == op_invokeinterface)
+	      {
+		nargs = get_byte ();
+		if (get_byte () != 0)
+		  verify_fail ("invokeinterface dummy byte is wrong");
+	      }
+
+	    namec = vfy_string_bytes (method_name);
+
+	    if (vfy_strings_equal (method_name, vfy_init_name()))
+	      {
+		is_init = true;
+		if (opcode != op_invokespecial)
+		  verify_fail ("can't invoke <init>");
+	      }
+	    else if (namec[0] == '<')
+	      verify_fail ("can't invoke method starting with `<'");
+
+	    arg_count = vfy_count_arguments (method_signature);
+            {
+	      /* Pop arguments and check types.  */
+	      type arg_types[arg_count];
+
+	      compute_argument_types (method_signature, arg_types);
+	      for (i = arg_count - 1; i >= 0; --i)
+		{
+		  /* This is only used for verifying the byte for
+		     invokeinterface.  */
+		  nargs -= type_depth (&arg_types[i]);
+		  pop_init_ref_t (arg_types[i]);
+		}
+	    }
+
+	    if (opcode == op_invokeinterface
+		&& nargs != 1)
+	      verify_fail ("wrong argument count for invokeinterface");
+
+	    if (opcode != op_invokestatic)
+	      {
+	        type raw;
+		type t = class_type;
+		if (is_init)
+		  {
+		    /* In this case the PC doesn't matter.  */
+		    type_set_uninitialized (&t, UNINIT);
+		    /* FIXME: check to make sure that the <init>
+		       call is to the right class.
+		       It must either be super or an exact class
+		       match.  */
+		  }
+		raw = pop_raw ();
+		if (! types_compatible (&t, &raw))
+		  verify_fail ("incompatible type on stack");
+
+		if (is_init)		  
+		  state_set_initialized (vfr->current_state, 
+		    type_get_pc (&raw), vfr->current_method->max_locals);
+	      }
+
+	    rt = compute_return_type (method_signature);
+	    if (! type_isvoid (&rt))
+	      push_type_t (rt);
+	  }
+	  break;
+
+	case op_new:
+	  {
+	    type t = check_class_constant (get_ushort ());
+	    if (type_isarray (&t) || type_isinterface (&t)
+		|| type_isabstract (&t))
+	      verify_fail ("type is array, interface, or abstract");
+	    type_set_uninitialized (&t, vfr->start_PC);
+	    push_type_t (t);
+	  }
+	  break;
+
+	case op_newarray:
+	  {
+	    int atype = get_byte ();
+	    type t;
+	    /* We intentionally have chosen constants to make this
+	       valid.  */
+	    if (atype < boolean_type || atype > long_type)
+	      verify_fail_pc ("type not primitive", vfr->start_PC);
+	    pop_type (int_type);
+	    init_type_from_class (&t, construct_primitive_array_type (atype));
+	    push_type_t (t);
+	  }
+	  break;
+	case op_anewarray:
+	  {
+	    type t;
+	    pop_type (int_type);
+	    t = check_class_constant (get_ushort ());
+	    push_type_t (type_to_array (&t));
+	  }
+	  break;
+	case op_arraylength:
+	  {
+	    type t = pop_init_ref (reference_type);
+	    if (! type_isarray (&t) && ! type_isnull (&t))
+	      verify_fail ("array type expected");
+	    push_type (int_type);
+	  }
+	  break;
+	case op_athrow:
+	  pop_type_t (make_type_from_class (vfy_throwable_type ()));
+	  invalidate_pc ();
+	  break;
+	case op_checkcast:
+	  pop_init_ref (reference_type);
+	  push_type_t (check_class_constant (get_ushort ()));
+	  break;
+	case op_instanceof:
+	  pop_init_ref (reference_type);
+	  check_class_constant (get_ushort ());
+	  push_type (int_type);
+	  break;
+	case op_monitorenter:
+	  pop_init_ref (reference_type);
+	  break;
+	case op_monitorexit:
+	  pop_init_ref (reference_type);
+	  break;
+	case op_wide:
+	  {
+	    switch (get_byte ())
+	      {
+	      case op_iload:
+		push_type_t (get_variable (get_ushort (), int_type));
+		break;
+	      case op_lload:
+		push_type_t (get_variable (get_ushort (), long_type));
+		break;
+	      case op_fload:
+		push_type_t (get_variable (get_ushort (), float_type));
+		break;
+	      case op_dload:
+		push_type_t (get_variable (get_ushort (), double_type));
+		break;
+	      case op_aload:
+		push_type_t (get_variable (get_ushort (), reference_type));
+		break;
+	      case op_istore:
+		set_variable (get_ushort (), pop_type (int_type));
+		break;
+	      case op_lstore:
+		set_variable (get_ushort (), pop_type (long_type));
+		break;
+	      case op_fstore:
+		set_variable (get_ushort (), pop_type (float_type));
+		break;
+	      case op_dstore:
+		set_variable (get_ushort (), pop_type (double_type));
+		break;
+	      case op_astore:
+		set_variable (get_ushort (), pop_init_ref (reference_type));
+		break;
+	      case op_ret:
+		handle_ret_insn (get_short ());
+		break;
+	      case op_iinc:
+		get_variable (get_ushort (), int_type);
+		get_short ();
+		break;
+	      default:
+		verify_fail_pc ("unrecognized wide instruction", vfr->start_PC);
+	      }
+	  }
+	  break;
+	case op_multianewarray:
+	  {
+	    int i;
+	    type atype = check_class_constant (get_ushort ());
+	    int dim = get_byte ();
+	    if (dim < 1)
+	      verify_fail_pc ("too few dimensions to multianewarray", vfr->start_PC);
+            type_verify_dimensions (&atype, dim);
+	    for (i = 0; i < dim; ++i)
+	      pop_type (int_type);
+	    push_type_t (atype);
+	  }
+	  break;
+	case op_ifnull:
+	case op_ifnonnull:
+	  pop_type (reference_type);
+	  push_jump (get_short ());
+	  break;
+	case op_goto_w:
+	  push_jump (get_int ());
+	  invalidate_pc ();
+	  break;
+	case op_jsr_w:
+	  handle_jsr_insn (get_int ());
+	  break;
+
+#if 0
+	/* These are unused here, but we call them out explicitly
+	   so that -Wswitch-enum doesn't complain.  */
+	case op_putfield_1:
+	case op_putfield_2:
+	case op_putfield_4:
+	case op_putfield_8:
+	case op_putfield_a:
+	case op_putstatic_1:
+	case op_putstatic_2:
+	case op_putstatic_4:
+	case op_putstatic_8:
+	case op_putstatic_a:
+	case op_getfield_1:
+	case op_getfield_2s:
+	case op_getfield_2u:
+	case op_getfield_4:
+	case op_getfield_8:
+	case op_getfield_a:
+	case op_getstatic_1:
+	case op_getstatic_2s:
+	case op_getstatic_2u:
+	case op_getstatic_4:
+	case op_getstatic_8:
+	case op_getstatic_a:
+#endif
+	default:
+	  /* Unrecognized opcode.  */
+	  verify_fail_pc ("unrecognized instruction in verify_instructions_0",
+		       vfr->start_PC);
+	}
+    }
+}
+
+/* This turns a `type' into something suitable for use by the type map
+   in the other parts of the compiler.  In particular, reference types
+   are mapped to Object, primitive types are unchanged, and other
+   types are mapped using special functions declared in verify.h.  */
+static vfy_jclass
+collapse_type (type *t)
+{
+  switch (t->key)
+    {
+    case void_type:
+    case boolean_type:
+    case char_type:
+    case float_type:
+    case double_type:
+    case byte_type:
+    case short_type:
+    case int_type:
+    case long_type:
+      return vfy_get_primitive_type (t->key);
+
+    case unsuitable_type:
+    case continuation_type:
+      return vfy_unsuitable_type ();
+
+    case return_address_type:
+      return vfy_return_address_type ();
+
+    case null_type:
+      return vfy_null_type ();
+
+    case reference_type:
+    case uninitialized_reference_type:
+      return vfy_object_type ();
+    }
+
+  abort ();
+}
+
+static void
+verify_instructions (void)
+{
+  int i;
+
+  branch_prepass ();
+  verify_instructions_0 ();
+
+  /* Now tell the rest of the compiler about the types we've found.  */
+  for (i = 0; i < vfr->current_method->code_length; ++i)
+    {
+      int j, slot;
+      struct state *curr;
+
+      if ((vfr->flags[i] & FLAG_INSN_SEEN) != 0)
+	vfy_note_instruction_seen (i);
+
+      if (! vfr->states[i])
+	continue;
+
+      curr = vfr->states[i]->val;
+      vfy_note_stack_depth (vfr->current_method, i, curr->stackdepth);
+
+      /* Tell the compiler about each local variable.  */
+      for (j = 0; j < vfr->current_method->max_locals; ++j)
+	vfy_note_local_type (vfr->current_method, i, j,
+			     collapse_type (&curr->locals[j]));
+      /* Tell the compiler about each stack slot.  */
+      for (slot = j = 0; j < curr->stacktop; ++j, ++slot)
+	{
+	  vfy_note_stack_type (vfr->current_method, i, slot,
+			       collapse_type (&curr->stack[j]));
+	  if (type_iswide (&curr->stack[j]))
+	    {
+	      ++slot;
+	      vfy_note_stack_type (vfr->current_method, i, slot,
+				   vfy_unsuitable_type ());
+	    }
+	}
+      if (slot != curr->stackdepth)
+	abort ();
+    }
+}
+
+#if 0
+_Jv_BytecodeVerifier (_Jv_InterpMethod *m)
+{
+  /* We just print the text as utf-8.  This is just for debugging
+     anyway.  */
+  debug_print ("--------------------------------\n");
+  debug_print ("-- Verifying method `%s'\n", m->self->name->chars());
+
+}
+#endif
+
+static void
+make_verifier_context (vfy_method *m)
+{
+  vfr = (verifier_context *) vfy_alloc (sizeof (struct verifier_context));
+
+  vfr->current_method = m;
+  vfr->bytecode = vfy_get_bytecode (m);
+  vfr->exception = vfy_get_exceptions (m);
+  vfr->current_class = m->defining_class;
+
+  vfr->states = NULL;
+  vfr->flags = NULL;
+  vfr->utf8_list = NULL;
+  vfr->isect_list = NULL;
+}
+
+static void
+free_verifier_context (void)
+{
+  vfy_string_list *utf8_list;
+  ref_intersection *isect_list;
+
+  if (vfr->flags)
+    vfy_free (vfr->flags);
+
+  utf8_list = vfr->utf8_list;
+  while (utf8_list != NULL)
+    {
+      vfy_string_list *n = utf8_list->next;
+      vfy_free (utf8_list);
+      utf8_list = n;
+    }
+
+  isect_list = vfr->isect_list;
+  while (isect_list != NULL)
+    {
+      ref_intersection *next = isect_list->alloc_next;
+      vfy_free (isect_list);
+      isect_list = next;
+    }
+
+  if (vfr->states != NULL)
+    {
+      int i;
+      for (i = 0; i < vfr->current_method->code_length; ++i)
+	{
+	  state_list *iter = vfr->states[i];
+	  while (iter != NULL)
+	    {
+	      state_list *next = iter->next;
+	      vfy_free (iter->val);
+	      vfy_free (iter);
+	      iter = next;
+	    }
+	}
+      vfy_free (vfr->states);
+    }
+  
+  vfy_free (vfr);
+}
+
+int
+verify_method (vfy_method *meth)
+{
+  debug_print ("verify_method (%s) %i\n", vfy_string_bytes (meth->name),
+	       meth->code_length);
+  
+  if (vfr != NULL)
+    verify_fail ("verifier re-entered");
+
+  make_verifier_context (meth);
+  verify_instructions ();
+  free_verifier_context ();
+  vfr = NULL;
+
+  return 1;
+}
diff --git a/gcc/java/verify.c b/gcc/java/verify.c
index aaf7e4df1f42..8eb0c308488e 100644
--- a/gcc/java/verify.c
+++ b/gcc/java/verify.c
@@ -89,23 +89,23 @@ check_pending_block (tree target_label)
 
   if (current_subr == NULL_TREE)
     {
-      if (LABEL_IN_SUBR (target_label))
-	return "might transfer control into subroutine";
+/*       if (LABEL_IN_SUBR (target_label)) */
+/* 	return "might transfer control into subroutine"; */
     }
   else
     {
       if (LABEL_IN_SUBR (target_label))
 	{
-	  if (LABEL_SUBR_START (target_label) != current_subr)
-	    return "transfer out of subroutine";
+/* 	  if (LABEL_SUBR_START (target_label) != current_subr) */
+/* 	    return "transfer out of subroutine"; */
 	}
       else if (! LABEL_VERIFIED (target_label))
 	{
 	  LABEL_IN_SUBR (target_label) = 1;
 	  LABEL_SUBR_START (target_label) = current_subr;
 	}
-      else
-	return "transfer out of subroutine";
+/*       else */
+/* 	return "transfer out of subroutine"; */
     }
   return NULL;
 }
@@ -126,6 +126,54 @@ subroutine_nesting (tree label)
   return nesting;
 }
 
+static tree
+defer_merging (tree type1, tree type2)
+{
+  // FIXME: This is just a placeholder until we replace the verifier
+  // altogether.  We really need to ouput a type assertion for all of
+  // the types, every time they are used.
+  return object_ptr_type_node;
+
+  if (TREE_CODE (type1) == POINTER_TYPE)
+    type1 = TREE_TYPE (type1);
+  if (TREE_CODE (type2) == POINTER_TYPE)
+    type2 = TREE_TYPE (type2);
+
+  if (TREE_CODE (type1) == RECORD_TYPE && TREE_CODE (type2) == RECORD_TYPE)
+    {
+      tree list = build_tree_list (type1, NULL_TREE);
+      list = tree_cons (type2, NULL_TREE, list);
+      return list;
+    }
+
+  if (TREE_CODE (type1) == TREE_LIST && TREE_CODE (type2) == TREE_LIST)
+    {
+      return chainon (copy_list (type1), copy_list (type2));
+    }
+
+  if (TREE_CODE (type1) == TREE_LIST && TREE_CODE (type2) == RECORD_TYPE)
+    {
+      tree tmp = type1;
+      do
+	{
+	  if (TREE_PURPOSE (tmp) == type2)
+	    return type1;
+	  tmp = TREE_CHAIN (tmp);
+	}
+      while (tmp);
+
+      return tree_cons (type2, NULL_TREE, copy_list (type1));
+    }
+
+  if (TREE_CODE (type2) == TREE_LIST && TREE_CODE (type1) == RECORD_TYPE)
+    {
+      return defer_merging (type2, type1);
+    }
+
+  abort ();
+}
+
+
 /* Return the "merged" types of TYPE1 and TYPE2.
    If either is primitive, the other must match (after promotion to int).
    For reference types, return the common super-class.
@@ -138,7 +186,11 @@ merge_types (tree type1, tree type2)
     return type1;
   if (type1 == TYPE_UNKNOWN || type2 == TYPE_UNKNOWN
       || type1 == TYPE_RETURN_ADDR || type2 == TYPE_RETURN_ADDR)
-    return TYPE_UNKNOWN;
+    return TYPE_UNKNOWN;  
+
+  if (TREE_CODE (type1) == TREE_LIST || TREE_CODE (type2) == TREE_LIST)
+    return defer_merging (type1, type2);
+
   if (TREE_CODE (type1) == POINTER_TYPE && TREE_CODE (type2) == POINTER_TYPE)
     {
       int depth1, depth2;
@@ -153,6 +205,9 @@ merge_types (tree type1, tree type2)
       tt1 = TREE_TYPE (type1);
       tt2 = TREE_TYPE (type2);
 
+      if (TYPE_DUMMY (tt1) || TYPE_DUMMY (tt2))
+	return defer_merging (tt1, tt2);
+      
       /* If tt{1,2} haven't been properly loaded, now is a good time
          to do it. */
       if (!TYPE_SIZE (tt1))
@@ -193,31 +248,10 @@ merge_types (tree type1, tree type2)
 	  return object_ptr_type_node;
 	}
 
-      if (CLASS_INTERFACE (TYPE_NAME (tt1)))
-	{
-	  /* FIXME: should see if two interfaces have a common
-	     superinterface.  */
-	  if (CLASS_INTERFACE (TYPE_NAME (tt2)))
-	    {
-	      /* This is a kludge, but matches what Sun's verifier does.
-		 It can be tricked, but is safe as long as type errors
-		 (i.e. interface method calls) are caught at run-time. */
-	      return object_ptr_type_node;
-	    }
-	  else
-	    {
-	      if (can_widen_reference_to (tt2, tt1))
-		return type1;
-	      else
-		return object_ptr_type_node;
-	    }
-	}
-      else if (CLASS_INTERFACE (TYPE_NAME (tt2)))
+      if (CLASS_INTERFACE (TYPE_NAME (tt1))
+	  || (CLASS_INTERFACE (TYPE_NAME (tt2))))
 	{
-	  if (can_widen_reference_to (tt1, tt2))
-	    return type2;
-	  else
-	    return object_ptr_type_node;
+	  return object_ptr_type_node;
 	}
 
       type1 = tt1;
@@ -675,6 +709,8 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
 	  VERIFICATION_ERROR_WITH_INDEX
 	    ("invalid local variable index %d in load");
 	tmp = type_map[index];
+	if (TREE_CODE (tmp) != TREE_LIST)
+	  {
 	if (tmp == TYPE_UNKNOWN)
 	  VERIFICATION_ERROR_WITH_INDEX
 	    ("loading local variable %d which has unknown type");
@@ -688,6 +724,7 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
 		: type != tmp))
 	  VERIFICATION_ERROR_WITH_INDEX
 	    ("loading local variable %d which has invalid type");
+	  }
 	PUSH_TYPE (tmp);
 	goto note_used;
 	case OPCODE_istore:  type = int_type_node;  goto general_store;
@@ -736,7 +773,7 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
 	prev_eh_ranges = NULL_EH_RANGE;
 
 	/* Allocate decl for this variable now, so we get a temporary
-! 	   that survives the whole method. */
+	   that survives the whole method. */
 	find_local_variable (index, type, oldpc);
 
         if (TYPE_IS_WIDE (type))
@@ -1092,6 +1129,10 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
 	    if (! CLASS_LOADED_P (self_type))
 	      load_class (self_type, 1);
 
+	    if (TYPE_DUMMY (self_type) && op_code == OPCODE_invokeinterface)
+	      /* Assume we are an interface.  */
+	      CLASS_INTERFACE (TYPE_NAME (self_type)) = 1;
+
 	    self_is_interface = CLASS_INTERFACE (TYPE_NAME (self_type));
 	    method_name = COMPONENT_REF_NAME (&current_jcf->cpool, index);
 	    method_type = parse_signature_string ((const unsigned char *) IDENTIFIER_POINTER (sig),
@@ -1129,7 +1170,6 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
 		  if (!nargs || notZero)
 		      VERIFICATION_ERROR 
 		        ("invalid argument number in invokeinterface");
-
 		  /* If we verify/resolve the constant pool, as we should,
 		     this test (and the one just following) are redundant.  */
 		  if (! self_is_interface)
diff --git a/gcc/java/verify.h b/gcc/java/verify.h
new file mode 100644
index 000000000000..6657ffc471a9
--- /dev/null
+++ b/gcc/java/verify.h
@@ -0,0 +1,160 @@
+/* Declarations to interface gcj with bytecode verifier.
+   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+Java and all Java-based marks are trademarks or registered trademarks
+of Sun Microsystems, Inc. in the United States and other countries.
+The Free Software Foundation is independent of Sun Microsystems, Inc.  */
+
+/* Written by Tom Tromey <tromey@redhat.com>.  */
+
+#ifndef GCC_VERIFY_H
+#define GCC_VERIFY_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "system.h"
+#include "coretypes.h"
+#include "jcf.h"
+#include "tree.h"
+#include "java-tree.h"
+
+typedef JCF vfy_constants;
+
+/* For our purposes a string is the same as an identifier.  */
+typedef tree vfy_string;
+
+/* The TYPE_DECL for a class or primitive type.  */
+typedef tree vfy_jclass;
+
+/* An unsigned jshort.  */
+typedef uint16 vfy_uint_16;
+
+typedef struct
+{
+  int handler, start, end, type;
+} vfy_exception;
+
+typedef struct
+{
+  tree method;
+  vfy_string signature;
+  vfy_string name;
+  const unsigned char *bytes;
+  vfy_exception *exceptions;
+
+  /* These fields are referred to directly by the verifier.  */
+  vfy_jclass defining_class;
+  int max_stack;
+  int max_locals;
+  int code_length;
+  int exc_count;
+} vfy_method;
+
+/* Entry point to the verifier.  */
+int verify_jvm_instructions_new (JCF *jcf, const unsigned char *byte_ops,
+				 long length);
+
+void *vfy_alloc (size_t bytes);
+void vfy_free (void *mem);
+bool vfy_strings_equal (vfy_string one, vfy_string two);
+const char *vfy_string_bytes (vfy_string str);
+int vfy_string_length (vfy_string str);
+vfy_string vfy_get_string (const char *chars, int length);
+vfy_string vfy_init_name (void);
+vfy_string vfy_clinit_name (void);
+int vfy_count_arguments (vfy_string signature);
+vfy_string vfy_get_signature (vfy_method *method);
+vfy_string vfy_get_method_name (vfy_method *method);
+bool vfy_is_static (vfy_method *method);
+const unsigned char *vfy_get_bytecode (vfy_method *method);
+vfy_exception *vfy_get_exceptions (vfy_method *method);
+void vfy_get_exception (vfy_exception *, int index, int *handler,
+			int *start, int *end, int *handler_type);
+int vfy_tag (vfy_constants *pool, int index);
+void vfy_load_indexes (vfy_constants *pool, int index,
+		       vfy_uint_16 *index0, vfy_uint_16 *index1);
+vfy_constants *vfy_get_constants (vfy_jclass klass);
+int vfy_get_constants_size (vfy_jclass klass);
+vfy_string vfy_get_pool_string (vfy_constants *pool, int index);
+vfy_jclass vfy_get_pool_class (vfy_constants *pool, int index);
+vfy_string vfy_make_string (const char *s, int len);
+vfy_string vfy_get_class_name (vfy_jclass klass);
+bool vfy_is_assignable_from (vfy_jclass target, vfy_jclass source);
+char vfy_get_primitive_char (vfy_jclass klass);
+int vfy_get_interface_count (vfy_jclass klass);
+vfy_jclass vfy_get_interface (vfy_jclass klass, int index);
+bool vfy_is_array (vfy_jclass klass);
+bool vfy_is_interface (vfy_jclass klass);
+bool vfy_is_primitive (vfy_jclass klass);
+vfy_jclass vfy_get_superclass (vfy_jclass klass);
+vfy_jclass vfy_get_array_class (vfy_jclass klass);
+vfy_jclass vfy_get_component_type (vfy_jclass klass);
+bool vfy_is_abstract (vfy_jclass klass);
+vfy_jclass vfy_find_class (vfy_jclass klass, vfy_string name);
+vfy_jclass vfy_object_type (void);
+vfy_jclass vfy_string_type (void);
+vfy_jclass vfy_throwable_type (void);
+vfy_jclass vfy_unsuitable_type (void);
+vfy_jclass vfy_return_address_type (void);
+vfy_jclass vfy_null_type (void);
+int vfy_fail (const char *message, int pc, vfy_jclass ignore1,
+	      vfy_method *method);
+vfy_jclass vfy_get_primitive_type (int type);
+void vfy_note_stack_depth (vfy_method *method, int pc, int depth);
+void vfy_note_stack_type (vfy_method *method, int pc, int slot,
+			  vfy_jclass type);
+void vfy_note_local_type (vfy_method *method, int pc, int slot,
+			  vfy_jclass type);
+void vfy_note_instruction_seen (int pc);
+
+#define GLOM(name, stuff) name ## stuff
+#define VFY_PRIMITIVE_CLASS(name) \
+  vfy_get_primitive_type ((int) (GLOM (name, _type)))
+
+typedef enum
+{
+#define JAVAOP(name, num, ignore1, ignore2, ignore3) \
+  GLOM (op_, name) = num,
+#include "javaop.def"
+} java_opcode;
+
+
+#define JV_CONSTANT_Class CONSTANT_Class
+#define JV_CONSTANT_ResolvedClass CONSTANT_ResolvedClass
+#define JV_CONSTANT_String CONSTANT_String
+#define JV_CONSTANT_ResolvedString CONSTANT_ResolvedString
+#define JV_CONSTANT_Integer CONSTANT_Integer
+#define JV_CONSTANT_Float CONSTANT_Float
+#define JV_CONSTANT_Long CONSTANT_Long
+#define JV_CONSTANT_Double CONSTANT_Double
+#define JV_CONSTANT_Fieldref CONSTANT_Fieldref
+#define JV_CONSTANT_InterfaceMethodref CONSTANT_InterfaceMethodref
+#define JV_CONSTANT_Methodref CONSTANT_Methodref
+
+int verify_method (vfy_method *meth);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! GCC_VERIFY_H */
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 94442652db49..add3919e8fac 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,758 @@
+2004-11-24  Tom Tromey  <tromey@redhat.com>
+
+	* Merged gcj-abi-2-dev-branch to trunk.
+
+2004-11-16  Tom Tromey  <tromey@redhat.com>
+
+	* include/java-interp.h (_Jv_DefineClass): Updated.
+	* java/lang/natVMClassLoader.cc (defineClass): Pass protection
+	domain to class reader.
+	* defineclass.cc (parse): Use print_class_loaded.
+	Include ProtectionDomain.h.
+	(_Jv_DefineClass): Added ProtectionDomain argument.
+	(_Jv_ClassReader): Likewise.
+	* include/jvm.h (_Jv_Linker::print_class_loaded): Declare.
+	* link.cc: Include CodeSource.h.
+	(print_class_loaded): New function.
+	(wait_for_state): Use it.
+
+2004-11-16  Andrew Haley  <aph@redhat.com>
+
+	* gnu/gcj/util/Debug.java (print): Add RawDataManaged.
+
+2004-11-16  Andrew Haley  <aph@redhat.com>
+
+	* configure.ac (LIBGCJ_LD_SYMBOLIC): AC_SUBST this definition.
+	* configure.host: Define libgcj_ld_symbolic for Linux hosts.
+	* Makefile.am (lib_*_la_LDFLAGS): Add LIBGCJ_LD_SYMBOLIC.
+	* configure: Regenerate.
+	* Makefile.in: Regenerate.	
+
+2004-11-15  Andrew Haley  <aph@redhat.com>
+
+	* boehm.cc (_Jv_GCRegisterDisappearingLink): Check that *objp is a
+	gc-allocated object.
+
+2004-11-15  Andrew Haley  <aph@redhat.com>
+
+	* java/net/URLClassLoader.java
+	(URLLoader.getClassPath): New method.
+	(JarURLLoader.JarURLLoader): Read mainfest to parse "Class-Path"
+	attribute and add URLs for each entry.
+	(JarURLLoader.classPath): New field.
+	(JarURLLoader.getClassPath): New method.
+	(addURLImpl): Scan through the list of extraUrls in the new
+	loader, adding them to our urlinfos.
+	(definePackage, findURLResource, findResources): Use
+	urlinfos.size(), not urls.size().
+
+2004-11-11  Tom Tromey  <tromey@redhat.com>
+
+	* gnu/gcj/runtime/natSharedLibLoader.cc (ensureSupersLinked): New
+	method.
+	* gnu/gcj/runtime/SharedLibHelper.java (findClass): Ensure supers
+	linked.
+	(ensureSupersLinked): Declare.
+	* java/lang/natVMClassLoader.cc (loadClass): Ensure supers
+	linked.
+
+2004-11-10  Tom Tromey  <tromey@redhat.com>
+
+	* gij.cc (main): Treat -verbose the same as -verbose:class.
+	(help): Document -verbose and -verbose:class.
+
+	* link.cc (verbose_class_flag): Declare.
+	(wait_for_state): Print message when handling precompiled class.
+	* java/lang/natClass.cc (verbose_class_flag): Moved to link.cc.
+
+2004-11-09  Tom Tromey  <tromey@redhat.com>
+
+	* testsuite/libjava.lang/assign2.out: New file.
+	* testsuite/libjava.lang/assign2.java: New file.
+
+	* java/lang/natRuntime.cc (insertSystemProperties): Set
+	java.version to 1.4.2 and java.specification.version to 1.4.  Set
+	java.runtime.version.
+
+2004-11-08  Tom Tromey  <tromey@redhat.com>
+
+	* java/lang/natClass.cc (_Jv_IsAssignableFromSlow): Ensure
+	supers installed.
+	* link.cc (verify_type_assertions): Don't link supers.
+
+	* include/jvm.h (_Jv_Linker::search_method_in_class): Declare.
+	* include/java-interp.h (class _Jv_InterpClass)
+	<_Jv_PrepareMissingMethods>: No longer `friend'.
+	* java/lang/Class.h (_Jv_SearchMethodInClass): No longer
+	`friend'.
+	(_Jv_PrepareMissingMethods, _Jv_PrepareCompiledClass,
+	_Jv_GetInterfaces, _Jv_GenerateITable, _Jv_FindIIndex,
+	_Jv_AppendPartialITable, _Jv_LinkSymbolTable,
+	_Jv_LayoutInterfaceMethods, _Jv_SetVTableEntries, _Jv_MakeVTable,
+	_Jv_linkExceptionClassTable, _Jv_WaitForState): Likewise.
+	* link.cc (search_method_in_class): Renamed from
+	_Jv_SearchMethodInClass.
+	(resolve_pool_entry): Updated.
+
+	* include/jvm.h (_Jv_CheckAssignment): Removed.
+	* java/lang/natClass.cc (_Jv_CheckAssignment): Removed.
+
+2004-11-05  Tom Tromey  <tromey@redhat.com>
+
+	* link.cc (verify_type_assertions): Ensure classes have supers
+	linked.  Strip off array types first.
+
+2004-11-05  Bryce McKinlay  <mckinlay@redhat.com>
+
+	* link.cc: Include VerifyError.h. 
+	(_Jv_Linker::verify_type_assertions): New. Read and evaluate entries
+	in the type assertion table.
+	* include/execution.h (_Jv_CompiledEngine::do_verify): Use
+	verify_type_assertions.
+	* include/jvm.h (_Jv_Linker::verify_type_assertions): declare.
+	* java/lang/Class.h (JV_ASSERT_END_OF_TABLE, 
+	JV_ASSERT_TYPES_COMPATIBLE, JV_ASSERT_IS_INSTANTIABLE): Declare
+	assertion code values.
+	(struct _Jv_TypeAssertion): Declare.
+	(assertion_table): New class field.
+	(verify): Remove class field.
+
+2004-11-05  Andrew Haley  <aph@redhat.com>
+
+	* Makefile.am: Move jv_dbtool.java to
+	gnu/gcj/tools/gcj_dbtool/Main.java.
+	* Makefile.in: Rebuild.
+	* java/lang/VMCompiler.java: Rename property
+	"gnu.gcj.precompiled.db" to "gnu.gcj.precompiled.db.path".
+	* gnu/gcj/tools/gcj_dbtool/Main.java: moved here from
+	jv_dbtool.java.
+	
+2004-11-05  Andrew Haley  <aph@redhat.com>
+
+	* jv_dbtool.java (main): Allow the user to specify the size of the
+	database.  Display the capacity and the size.
+	(usage): Show the new option.
+		
+2004-11-04  Tom Tromey  <tromey@redhat.com>
+
+	* include/jvm.h (_Jv_Linker::set_vtable_entries): Updated.
+	* link.cc (make_vtable): Use correct index when searching for
+	missing method's name.  Don't use `flags'.
+	(set_vtable_entries): Removed `flags' argument.  Don't recurse
+	into superclasses.
+	(link_symbol_table): Ensure target class method table is
+	complete.  Ensure target fields are laid out before entering
+	loop.
+
+	* java/lang/natClass.cc (_Jv_getInterfaceMethod): Indentation
+	fix.
+
+	* interpret.cc (do_verify): Don't verify abstract methods.
+
+2004-11-01  Tom Tromey  <tromey@redhat.com>
+
+	* link.cc (wait_for_state): Call verify_class.
+
+	* verify.cc (state::check_no_uninitialized_objects): Removed.
+	(push_jump): Updated.
+	(push_exception_jump): Likewise.
+	(handle_ret_insn): Likewise.
+	(handle_jsr_insn): Likewise.
+
+2004-10-28  Andrew Haley  <aph@redhat.com>
+
+	* gnu/gcj/runtime/PersistentByteMap.java: New file.
+	* jv_dbtool.java: New file.
+	* Makefile.am (bin_PROGRAMS): Add jv-dbtool
+	(jv_dbtool_SOURCES, jv_dbtool_LDFLAGS, jv_dbtool_LINK)
+	(jv_dbtool_LDADD, jv_dbtool_DEPENDENCIES): New.
+	* Makefile.in: Regenerate,
+	* java/lang/VMCompiler.java: Import NoSuchAlgorithmException,
+	Enumeration, StringTokenizer, Vector, PersistentByteMap.
+	(precompiledMapFiles): New variable.
+	(VMCompiler static intializer): Read "gnu.gcj.precompiled.db" to
+	initialize precompiledMapFiles.
+	(compileClass): Look at the database of precompiled class files
+	before firing up gcj.
+
+	* gnu/gcj/runtime/VMClassLoader.java (findClass): Fix comment.
+
+2004-10-27  Andrew Haley  <aph@redhat.com>
+
+	* java/lang/VMCompiler.java (compileClass): try looking for
+	precompiledMapFiles.
+	* gnu/gcj/runtime/PersistentByteMap.java: New file.
+
+2004-10-27  Tom Tromey  <tromey@redhat.com>
+
+	* link.cc (ensure_class_linked): Only resolve classes for
+	compiled classes.
+	(add_miranda_methods): Ensure interface supers are installed.
+	(resolve_pool_entry): Better error message.
+
+2004-10-25  Tom Tromey  <tromey@redhat.com>
+
+	* boehm.cc (_Jv_MarkObj): Test aux_info before dereferencing it.
+
+	* java/util/ResourceBundle.java (tryBundle): Use
+	Class.isAssignableFrom rather than catching ClassCastException.
+
+	* java/util/zip/InflaterInputStream.java (fill): Don't throw an
+	exception if we hit EOF of `in'.
+	(read): Handle case where inflating returns -1.
+
+	* gnu/java/text/WordBreakIterator.java (WordBreakIterator): Don't
+	initialize `iter'.
+	* gnu/java/text/SentenceBreakIterator.java
+	(SentenceBreakIterator): Don't initialize `iter'.
+	* gnu/java/text/LineBreakIterator.java (LineBreakIterator): Don't
+	initialize `iter'.
+	* gnu/java/text/CharacterBreakIterator.java
+	(CharacterBreakIterator): Don't initialize `iter'.
+	* gnu/java/text/BaseBreakIterator.java (BaseBreakIterator): New
+	constructor.
+	* java/text/BreakIterator.java: Updated documentation.
+
+2004-10-20  Tom Tromey  <tromey@redhat.com>
+
+	* java/util/ResourceBundle.java (tryBundle): Also ignore
+	ClassCastException.
+
+2004-10-18  Tom Tromey  <tromey@redhat.com>
+
+	* interpret.cc (do_post_miranda_hook): New method.
+	* include/execution.h (_Jv_ExecutionEngine::post_miranda_hook):
+	New field.
+	(_Jv_CompiledEngine::do_post_miranda_hook): New method.
+	(_Jv_CompiledEngine): Initialize new field.
+	(_Jv_InterpreterEngine::do_post_miranda_hook): Declare.
+	(_Jv_InterpreterEngine): Initialize new field.
+	* link.cc (resolve_pool_entry): Put Miranda methods in target
+	class.
+	(ensure_method_table_complete): Call post_miranda_hook.
+	* java/lang/natVMClassLoader.cc (defineClass): Don't set class'
+	aux_info.
+	* defineclass.cc (read_one_method_attribute): Use _Jv_AllocBytes.
+	(parse): Set class' aux_info here.
+
+	* boehm.cc (_Jv_MarkObj): Mark `throws'.
+
+	* boehm.cc: Re-merged with trunk.
+
+2004-10-18  Andrew Haley  <aph@redhat.com>
+
+	PR java/18036:
+	* gnu/gcj/runtime/natStackTrace.cc (fillInStackTrace): Reorganize
+	and correct logic used to find interpreter.
+
+2004-10-13  Andrew Haley  <aph@redhat.com>
+
+	* interpret.cc (_Jv_InterpMethod::run): Initialize
+	_Jv_StartOfInterpreter.
+	(_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): Functions removed.
+	(_Jv_StartOfInterpreter, _Jv_EndOfInterpreter): New variables.
+	* gnu/gcj/runtime/natStackTrace.cc (fillInStackTrace): Use
+	_Unwind_FindEnclosingFunction to discover whether PC is within the
+	interpreter.
+
+2004-10-13  Tom Tromey  <tromey@redhat.com>
+
+	* link.cc (find_iindex): Copy correct number of slots to new
+	ioffsets.
+
+2004-10-12  Tom Tromey  <tromey@redhat.com>
+
+	* testsuite/libjava.loader/loader.exp (gcj_object_file_name): New
+	proc.
+	(gcj_loader_test_one): Use it.
+	(gcj_loader_run): Likewise.
+
+	* prims.cc: Don't include FirstThread.h.
+
+2004-10-06  Tom Tromey  <tromey@redhat.com>
+
+	* link.cc (ensure_method_table_complete): Ensure superclass
+	Miranda methods installed.
+
+	* include/java-interp.h (class _Jv_JNIMethod): Added
+	JV_MARKOBJ_DECL as a friend.
+	* interpret.cc (ncode): Allocate jni_arg_types field with GC.
+	* boehm.cc (_Jv_MarkObj): Skip abstract methods when marking
+	interpreter method structures.  Mark jni_arg_types of JNI
+	methods.
+
+	* defineclass.cc (parse): Use JV_STATE_READ.
+	* java/lang/Class.h (JV_STATE_READ): New enum value.
+
+2004-10-05  Tom Tromey  <tromey@redhat.com>
+
+	* link.cc (resolve_pool_entry): Add signature info to missing
+	method's information.
+
+	* gnu/gcj/util/Debug.java (Debug(int,boolean)): New constructor.
+	* gnu/gcj/util/natDebug.cc (_Jv_StaticDeepDebug): New function.
+
+2004-10-04  Tom Tromey  <tromey@redhat.com>
+
+	* boehm.cc (_Jv_MarkObj): Correctly indicate base pointer when
+	marking IDT.
+
+2004-09-29  Tom Tromey  <tromey@redhat.com>
+
+	* Makefile.am (libgcj_la_SOURCES): Mention link.cc, not
+	resolve.cc.
+	* include/jvm.h (class _Jv_Linker): Renamed from _Jv_Resolver.
+	* jni.cc: Use _Jv_Linker.
+	* interpret.cc: Use _Jv_Linker.
+	* java/lang/reflect/natField.cc (getType): Use _Jv_Linker.
+	* java/lang/natClassLoader.cc: Use _Jv_Linker.
+	* java/lang/natVMClassLoader.cc (resolveClass): Use _Jv_Linker.
+	* java/lang/Class.h: Use _Jv_Linker.
+	* java/lang/natClass.cc (initializeClass): Use _Jv_Linker.
+	* resolve.cc: Renamed ...
+	* link.cc: ... here.  Use _Jv_Linker.
+	* defineclass.cc (checkExtends): Use _Jv_Linker.
+
+2004-09-17  Tom Tromey  <tromey@redhat.com>
+
+	* defineclass.cc (handleCodeAttribute): Don't reference
+	`deferred'.
+	(handleMethodsEnd): Likewise.
+	* include/java-interp.h (_Jv_MethodBase::deferred): Removed
+	field.
+	(_Jv_Defer_Resolution): Don't declare or define.
+	* interpret.cc (do_create_ncode): Don't resolve deferred method
+	pointers.
+	* java/lang/Class.h (_Jv_Defer_Resolution): Don't declare.
+	* resolve.cc (link_symbol_table): No need to defer resolution.
+
+2004-09-14  Tom Tromey  <tromey@redhat.com>
+
+	* boehm.cc (MAYBE_MARK): Remove unused `Exit' argument.
+	(_Jv_MarkObj): Updated.
+	(_Jv_MarkArray): Likewise.
+
+	* include/jvm.h (StringClass): Removed.
+	* jni.cc (_Jv_JNI_ThrowNew): Don't use StringClass.
+	* interpret.cc (_Jv_InitField): Don't use StringClass.
+	* java/lang/natString.cc (_Jv_StringFindSlot): Don't use
+	StringClass.
+	(rehash): Likewise
+	(intern): Likewise.
+	(_Jv_FinalizeString): Likewise.
+	(_Jv_NewStringUtf8Const): Likewise.
+	(equals): Likewise.
+	* prims.cc (JvConvertArgv): Don't use StringClass.
+
+	* gcj/field.h (struct _Jv_Field): Don't mention COMPACT_FIELDS.
+	* resolve.cc (ensure_fields_laid_out): Don't mention
+	COMPACT_FIELDS.
+	* defineclass.cc (handleField): Don't mention COMPACT_FIELDS.
+	* boehm.cc (_Jv_MarkObj): Don't mention COMPACT_FIELDS.
+
+	* 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.
+
+2004-09-13  Tom Tromey  <tromey@redhat.com>
+
+	* mauve-libgcj: List some classes we don't have.
+
+2004-09-10  Andrew Haley  <aph@redhat.com>
+
+	* java/lang/Class.h (_Jv_getInterfaceMethod(): new friend.
+	* java/lang/natClass.cc (initializeClass): Check itable.
+	(_Jv_getInterfaceMethod): New.
+	(_Jv_LinkSymbolTable): Rewrite code that handles inerface calls.
+	Check that an interface method isn't called with invokevirtual.
+
+	* java/lang/natClass.cc (_Jv_LayoutVTableMethods): Make sure
+	super_meth is virtual.
+
+2004-09-01  Tom Tromey  <tromey@redhat.com>
+
+	* java/lang/Class.h (_Jv_CheckAccessNoInit): Declare as friend.
+	* java/lang/natClass.cc (_Jv_LayoutVTableMethods): Use
+	_Jv_CheckAccessNoInit.
+	* include/jvm.h (_Jv_CheckAccessNoInit): Declare.
+	* prims.cc (_Jv_CheckAccessNoInit): New method.
+
+	* java/lang/reflect/natMethod.cc (invoke): Check access against
+	declaring class, not object's class.
+	* java/lang/natClass.cc (_Jv_LookupDeclaredMethod): Added another
+	argument.
+	(_Jv_LayoutVTableMethods): Perform checks of accessibility of
+	overridden method.
+	* java/lang/Class.h (_Jv_LookupDeclaredMethod): Added another
+	argument.
+
+2004-08-30  Andrew Haley  <aph@redhat.com>
+
+	* java/lang/natClass.cc (_Jv_CheckAssignment): Catch
+	ClassNotFoundException.
+	Throw NoClassDefFoundError.
+
+	* java/lang/natClassLoader.cc (_Jv_FindClassInCache): Remove call
+	to klass->verify() from here ...
+	(_Jv_PrepareCompiledClass): ...and put it here.
+
+2004-08-27  Andrew Haley  <aph@redhat.com>
+
+	* java/lang/natClassLoader.cc (_Jv_FindClassInCache): Call
+	klass->verify().
+	* java/lang/natClass.cc (_Jv_LinkSymbolTable): Add debugging.
+	(_Jv_LinkSymbolTable): Call Jv_LayoutClass on target class.
+
+2004-08-27  Tom Tromey  <tromey@redhat.com>
+
+	* java/lang/Class.h (_Jv_IsAssignableFromSlow): Declare as
+	friend.
+	* java/lang/natClass.cc (_Jv_CheckAssignment): New function.
+	(_Jv_IsAssignableFromSlow): New function.
+	Include VerifyError.h.
+	* include/jvm.h (_Jv_CheckAssignment): Declare.
+
+2004-08-18  Andrew Haley  <aph@redhat.com>
+
+	* java/lang/VMCompiler.java (loadSharedLibrary): Add className
+	argument.  Pass it to findClass instead of fileName.
+	(compileClass): Pass class name to loadSharedLibrary.
+
+2004-06-22  Andrew Haley  <aph@redhat.com>
+
+	* testsuite/libjava.compile/compile.exp: Force indirect dispatch.
+
+2004-06-15  Andrew Haley  <aph@redhat.com>
+
+	* java/lang/natSystem.cc (getenv0): Don't assume environment
+	variable is Latin 1 coded.
+
+2004-06-07  Andrew Haley  <aph@redhat.com>
+
+	* java/lang/System.java: (getenv0): New method.
+	(getenv): Add security check.  Do the right thing.
+	* java/lang/natSystem.cc (getenv0): New method.
+
+2004-04-19    Andrew Haley  <aph@redhat.com>
+
+	* gnu/gcj/runtime/NameFinder.java: Call waitFor() on the processes
+	we destroy.
+
+	* gnu/java/net/natPlainSocketImplPosix.cc (read): The value byte
+	is returned as an int in the range 0 to 255.
+
+2004-08-13  Tom Tromey  <tromey@redhat.com>
+
+	* java/lang/natClass.cc (_Jv_LinkSymbolTable): Prepare the target
+	class if it is interpreted.
+
+2004-08-12  Tom Tromey  <tromey@redhat.com>
+
+	* java/lang/natClassLoader.cc (_Jv_WaitForState): Updated.
+	* java/lang/Class.h (_Jv_ResolveClassRef): Updated declaration.
+	(Class::getSuperclass): Updated.
+	(Class::getInterfaces): Likewise.
+	(Class::size): Updated.
+	(_Jv_LayoutClass): Updated declaration.
+	* java/lang/natClass.cc (_Jv_ResolveClassRef): Changed interface.
+	Synchronize on class.
+	(_Jv_LayoutClass): Changed interface.
+	(initializeClass): Updated.
+	(_Jv_LinkSymbolTable): Likewise.
+
+	* java/lang/Class.h (Class::_Jv_isBinaryCompatible): Declare as
+	friend.
+	* java/lang/natClassLoader.cc (_Jv_WaitForState): Use
+	_Jv_isBinaryCompatible.
+	* java/lang/natClass.cc (initializeClass): Use
+	_Jv_isBinaryCompatible.
+	(_Jv_LinkSymbolTable): Likewise.
+	* include/jvm.h (_Jv_isBinaryCompatible): New function.
+
+2004-08-11  Tom Tromey  <tromey@redhat.com>
+
+	* gcj/javaprims.h: Regenerated.
+	* java/lang/natClassLoader.cc (getClassLoader0): Removed.
+	(_registerClass): Likewise.
+	* Makefile.in: Rebuilt.
+	* Makefile.am (core_java_source_files): Added VMCompiler.
+	* java/lang/Compiler.java: Rewrote in terms of VMCompiler.
+	* java/lang/VMCompiler.java: New file.
+	* gnu/gcj/runtime/SharedLibHelper.java (findClass): Removed
+	`verbose' code.
+	(copyFile): Don't use fully-qualified name.
+	(h): Removed.
+	* java/lang/natVMClassLoader.cc: Include VMCompiler.h.
+	(defineClass): Use VMCompiler.
+	* java/lang/ClassLoader.java (defineClass): Removed jit
+	compilation code and `verbose' code.
+	(getClassLoader0): Removed.
+	(_registerClass): Likewise.
+	(SharedLibHelpers): Removed.
+
+2004-08-10  Tom Tromey  <tromey@redhat.com>
+
+	* java/net/URLClassLoader.java (URLLoader(URLClassLoader, URL,
+	URL)): New constructor.
+	(SoURLLoader): Likewise.
+	(JarURLLoader): Create SoURLLoader with override URL.
+
+2004-08-10  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.in: Rebuilt.
+	* Makefile.am (interpret.lo): New rule.
+
+2004-08-05  Andrew Haley  <aph@redhat.com>
+
+	* java/net/URLClassLoader.java (JarURLLoader.JarURLLoader): Look
+	aside for "GCJLIBS" in directory where jarfiles are loaded.	
+	(JarURLLoader.getClass): New method.
+	(JarURLLoader.toString):  New method.
+	(FileResource.toString):  New method.
+	* java/lang/natClassLoader.cc (_Jv_RegisterClassHookDefault):
+	Remove "Duplicate class registration: " bug.
+	(_registerClass): New method.
+	* java/lang/natClass.cc (_Jv_LinkSymbolTable): Check method index.
+	(_Jv_LinkSymbolTable): Call _Jv_LayoutClass().
+	Add debugging.
+	(_Jv_LayoutClass): Use getSuperclass() rather than directly
+	accessing the field.
+	* java/lang/ClassLoader.java (SharedLibHelpers): New variable.
+	(defineClass): Call gcj to JIT-compile a class.
+	(_registerClass): New method.
+	* gnu/gcj/runtime/SharedLibHelper.java (findHelper): A shared
+	library name can refer to more than one loaded library, so use a
+	Set of SharedLibHelpers.
+	If a shared library is already loaded, take a copy.
+	(copyFile): New function.
+
+	* testsuite/libjava.compile/compile.exp: Force
+	-findirect-dispatch.
+
+	* java/security/BasicPermission.java: Remove bogus checks.
+
+	* java/lang/System.java (getenv0): New method.
+	* java/lang/natSystem.cc (getenv0): New method.
+
+2004-05-24  Andrew Haley  <aph@redhat.com>
+
+	* java/lang/natClass.cc (_Jv_LayoutClass): Remove warning message.
+
+2004-04-20  Bryce McKinlay  <mckinlay@redhat.com>
+
+	* Merged with HEAD as of 20040514. Diff against
+	gcj-abi-2-merge-20040514.
+
+2004-04-16  Andrew Haley  <aph@redhat.com>
+
+	* java/lang/natClassLoader.cc (_Jv_WaitForState): Call
+	_Jv_LayoutClass.
+	(_Jv_PrepareCompiledClass): Cast address to uaddr for comparison.
+	(_Jv_PrepareCompiledClass): If we throw an exception during
+	preparation, restore state.
+	(ClassLoader::getClassLoader0): New method.
+
+	* java/lang/natClass.cc (get_alignment_from_class): Moved here
+	from resolve.cc.
+	(ALIGNOF): Use offsetof, not __alignof__.
+	(_Jv_ResolveClassRef): Resolve a reference to a class in a
+	constant pool.
+	(getInterfaces): Emit debug output if interface hasn't been
+	resolved.
+	(initializeClass): Call _Jv_LayoutClass.
+	(_Jv_LinkSymbolTable): Add debugging output.
+	(_Jv_LinkSymbolTable): NoClassDefFoundError if target_class isn't
+	found.
+	(_Jv_LinkSymbolTable): Call _Jv_PrepareClass.
+	(_Jv_LinkSymbolTable): Pass the real class loader to
+	_Jv_FindClass.
+	(_Jv_linkExceptionClassTable): Don't throw if we fail to find an
+	exception class.
+	(_Jv_LinkSymbolTable): Assert if we find a static field reference
+	to an interpreted class.
+	(_Jv_LayoutVTableMethods): Use klass->getSuperclass to get the
+	superclass.
+	(_Jv_LayoutClass): Moved here; it was part of _Jv_PrepareClass in
+	resolve.cc.
+	
+	* java/lang/VMSecurityManager.java: Check for the system class
+	loader as well as loader != null.
+	
+	* java/lang/SecurityManager.java (checkPermission): Remove
+	security check.
+	(checkRead): Likewise.
+	(checkConnect): Likewise.
+
+	* java/lang/ClassLoader.java (loadClass): Include all class
+	loaders in stack trace string.
+	Look for class in "gcjlib.so" in the same directory.
+	(getSystemClassLoader) Use getClassLoader0.
+	(getClassLoader0): New native method.
+
+	* java/lang/Class.h (getSuperclass): New method.
+	(getInterface): New method.
+	(size): Lay out class if needed.
+	(firstMethodIndex): New method.
+	(Jv_ResolveClassRef): New declaration.
+	(_Jv_LinkSymbolTable): New declaration.
+
+	* java/io/ObjectOutputStream.java: Add DEBUG statements
+	everywhere.
+	(dumpElementln): New method.
+	(depth): New field.
+	* java/io/ObjectInputStream.java (MyIOException): new, for
+	debugging.
+	Everywhere: use MyIOException rather than IOException.
+	Indent debugging output to make nesting visible.
+	(currentClassLoader): Make native
+	(callersClassLoader): New field.
+	(depth): New field.
+	* java/io/natObjectInputStream.cc (getCallersClassLoader): New
+	method.
+	
+	(readObject): ENDBLOCKDATA is generated if the class has a write
+	method, not if it has a read method.
+
+	* include/jvm.h (_Jv_CallAnyMethodA): Add new arg, iface.
+
+	* gnu/javax/rmi/CORBA/DelegateFactory.java: Use the
+	getContextClassLoader form the current thread after our own class
+	loader.
+
+	* gnu/gcj/runtime/SharedLibHelper.java (findClass): Class loader
+	debugging.
+	(toString): New method.
+
+	* verify.cc (class _Jv_BytecodeVerifier): Don't directly access
+	interfaces array.
+
+	* resolve.cc (_Jv_PrepareMissingMethods): If interface looks like
+	a constant pool entry, resolve it now.
+	(_Jv_PrepareClass): Break out part of this function to Jv_LayoutClass
+	in natClass.cc.
+	Move get_alignment_from_class to natClass.cc.
+
+	* prims.cc (_Jv_AllocObjectNoFinalizer): Use size field from class.
+	(_Jv_AllocObjectNoInitNoFinalizer): Likewise.
+
+	* defineclass.cc (checkExtends): Don't access superclass field
+	directly.
+
+	* Makefile.in: regenerate.
+
+	* gnu/gcj/util/natDebug.cc: New
+	* gnu/gcj/util/Debug.java: New.
+
+	* Makefile.am (java/io/ObjectInputStream.lo): Use
+	-fno-optimize-sibling-calls.
+
+	* java/lang/reflect/natMethod.cc (_Jv_CallAnyMethodA): Use
+	_Jv_LookupInterfaceMethodIdx to calculate the address of a method
+	in an interface.
+	* include/jvm.h (_Jv_CallAnyMethodA): Add new arg: iface.
+
 2004-11-24  Kelley Cook  <kcook@gcc.gnu.org>
 
 	* configure: Regenerate for libtool change.
diff --git a/libjava/Makefile.am b/libjava/Makefile.am
index 192845f2cc5e..0b07288b1489 100644
--- a/libjava/Makefile.am
+++ b/libjava/Makefile.am
@@ -124,7 +124,7 @@ propdir = $(libdir)
 
 ## For now, only on native systems.  FIXME.
 if NATIVE
-bin_PROGRAMS = jv-convert gij grmic grmiregistry
+bin_PROGRAMS = jv-convert gij grmic grmiregistry gcj-dbtool
 endif
 
 bin_SCRIPTS = addr2name.awk
@@ -207,7 +207,7 @@ libgij_la_LIBADD = libgcj.la
 libgij_la_DEPENDENCIES = libgcj.la libgcj.spec
 
 libgcj_la_SOURCES = prims.cc jni.cc exception.cc \
-	resolve.cc defineclass.cc interpret.cc verify.cc \
+	link.cc defineclass.cc interpret.cc verify.cc \
 	$(nat_source_files) $(math_c_source_files) $(java_source_files) \
 	$(built_java_source_files) \
 	$(BOEHMGC_SRC) $(NOGC_SRC) \
@@ -363,7 +363,7 @@ lib_gnu_java_awt_peer_gtk_la_LIBADD = $(GTK_LIBS) $(GLIB_LIBS) $(LIBART_LIBS) $(
 lib_gnu_java_awt_peer_gtk_la_DEPENDENCIES = $(gtk_jni_headers) libgcj-@gcc_version@.jar libgcj.la libgcj.spec
 ## The mysterious backslash in the grep pattern is consumed by make.
 lib_gnu_java_awt_peer_gtk_la_LDFLAGS = \
-        -version-info `grep -v '^\#' $(srcdir)/libtool-version`
+        -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC)
 lib_gnu_java_awt_peer_gtk_la_LINK = $(LIBLINK)
 
 lib_org_ietf_jgss_la_SOURCES = \
@@ -384,7 +384,7 @@ lib_org_ietf_jgss_la_LIBADD = -L$(here)/.libs  $(jgss_propertyo_files) \
 
 ## The mysterious backslash in the grep pattern is consumed by make.
 lib_org_ietf_jgss_la_LDFLAGS = -rpath $(toolexeclibdir) \
-	-version-info `grep -v '^\#' $(srcdir)/libtool-version`
+	-version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC)
 
 lib_org_w3c_dom_la_SOURCES = org/w3c/dom/Attr.java \
 org/w3c/dom/CDATASection.java \
@@ -415,7 +415,7 @@ org/w3c/dom/traversal/TreeWalker.java
 lib_org_w3c_dom_la_LIBADD = -L$(here)/.libs libgcj.la
 ## The mysterious backslash in the grep pattern is consumed by make.
 lib_org_w3c_dom_la_LDFLAGS = -rpath $(toolexeclibdir) \
-        -version-info `grep -v '^\#' $(srcdir)/libtool-version`
+        -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC)
 
 lib_org_xml_sax_la_SOURCES = org/xml/sax/ext/DeclHandler.java \
 org/xml/sax/ext/LexicalHandler.java \
@@ -451,7 +451,7 @@ org/xml/sax/XMLReader.java
 lib_org_xml_sax_la_LIBADD = -L$(here)/.libs libgcj.la
 ## The mysterious backslash in the grep pattern is consumed by make.
 lib_org_xml_sax_la_LDFLAGS = -rpath $(toolexeclibdir) \
-        -version-info `grep -v '^\#' $(srcdir)/libtool-version`
+        -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC)
 
 lib_gnu_awt_xlib_la_SOURCES = \
 	$(xlib_java_source_files) \
@@ -467,7 +467,7 @@ lib_gnu_awt_xlib_la_CPPFLAGS = \
 lib_gnu_awt_xlib_la_LDFLAGS = ../libstdc++-v3/src/libstdc++.la \
 	@X_PRE_LIBS@ @X_LIBS@ -lX11 @X_EXTRA_LIBS@ \
         -rpath $(toolexeclibdir) \
-        -version-info `grep -v '^\#' $(srcdir)/libtool-version`
+        -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC)
 lib_gnu_awt_xlib_la_LINK = $(LIBLINK)
 
 all_java_source_files = \
@@ -945,6 +945,25 @@ jv_convert_LDADD = -L$(here)/.libs libgcj.la
 ## linking this program.
 jv_convert_DEPENDENCIES = libgcj.la libgcj.spec
 
+gcj_dbtool_SOURCES = gnu/gcj/tools/gcj_dbtool/Main.java
+## We need -nodefaultlibs because we want to avoid gcj's `-lgcj'.  We
+## need this because we are explicitly using libtool to link using the
+## `.la' file.
+gcj_dbtool_LDFLAGS = --main=gnu.gcj.tools.gcj_dbtool.Main \
+	-rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
+gcj_dbtool_LINK = $(GCJLINK)
+## We don't explicitly link in the libraries we need; libgcj.la brings
+## in all dependencies.  We need the -L so that gcj can find libgcj
+## with `-lgcj', but it must come first, otherwise the -L flags
+## brought in from libgcj.la would cause the install directories to be
+## searched before the build-tree ones, and we'd get errors because of
+## different libraries with the same SONAME from picky linkers such as
+## Solaris'.  FIXME: should be _libs on some systems.
+gcj_dbtool_LDADD = -L$(here)/.libs libgcj.la
+## Depend on the spec file to make sure it is up to date before
+## linking this program.
+gcj_dbtool_DEPENDENCIES = libgcj.la libgcj.spec
+
 gij_SOURCES = 
 ## We need -nodefaultlibs because we want to avoid gcj's `-lgcj'.  We
 ## need this because we are explicitly using libtool to link using the
@@ -2140,65 +2159,35 @@ javax/print/attribute/SupportedValuesAttribute.java \
 javax/print/attribute/TextSyntax.java \
 javax/print/attribute/UnmodifiableSetException.java \
 javax/print/attribute/URISyntax.java \
-javax/print/attribute/standard/ColorSupported.java \
-javax/print/attribute/standard/Compression.java \
 javax/print/attribute/standard/Copies.java \
-javax/print/attribute/standard/CopiesSupported.java \
 javax/print/attribute/standard/DateTimeAtCompleted.java \
 javax/print/attribute/standard/DateTimeAtCreation.java \
 javax/print/attribute/standard/DateTimeAtProcessing.java \
 javax/print/attribute/standard/DocumentName.java \
-javax/print/attribute/standard/Fidelity.java \
-javax/print/attribute/standard/Finishings.java \
 javax/print/attribute/standard/JobHoldUntil.java \
 javax/print/attribute/standard/JobImpressions.java \
 javax/print/attribute/standard/JobImpressionsCompleted.java \
-javax/print/attribute/standard/JobImpressionsSupported.java \
 javax/print/attribute/standard/JobKOctets.java \
 javax/print/attribute/standard/JobKOctetsProcessed.java \
-javax/print/attribute/standard/JobKOctetsSupported.java \
 javax/print/attribute/standard/JobMediaSheets.java \
 javax/print/attribute/standard/JobMediaSheetsCompleted.java \
-javax/print/attribute/standard/JobMediaSheetsSupported.java \
 javax/print/attribute/standard/JobMessageFromOperator.java \
 javax/print/attribute/standard/JobName.java \
 javax/print/attribute/standard/JobOriginatingUserName.java \
 javax/print/attribute/standard/JobPriority.java \
 javax/print/attribute/standard/JobPrioritySupported.java \
-javax/print/attribute/standard/JobSheets.java \
-javax/print/attribute/standard/JobState.java \
-javax/print/attribute/standard/JobStateReason.java \
-javax/print/attribute/standard/JobStateReasons.java \
-javax/print/attribute/standard/Media.java \
-javax/print/attribute/standard/MediaSizeName.java \
-javax/print/attribute/standard/MultipleDocumentHandling.java \
 javax/print/attribute/standard/NumberOfDocuments.java \
 javax/print/attribute/standard/NumberOfInterveningJobs.java \
 javax/print/attribute/standard/NumberUp.java \
-javax/print/attribute/standard/NumberUpSupported.java \
-javax/print/attribute/standard/OrientationRequested.java \
 javax/print/attribute/standard/OutputDeviceAssigned.java \
-javax/print/attribute/standard/PDLOverrideSupported.java \
-javax/print/attribute/standard/PageRanges.java \
 javax/print/attribute/standard/PagesPerMinute.java \
 javax/print/attribute/standard/PagesPerMinuteColor.java \
-javax/print/attribute/standard/PresentationDirection.java \
-javax/print/attribute/standard/PrintQuality.java \
 javax/print/attribute/standard/PrinterInfo.java \
-javax/print/attribute/standard/PrinterIsAcceptingJobs.java \
 javax/print/attribute/standard/PrinterLocation.java \
 javax/print/attribute/standard/PrinterMakeAndModel.java \
 javax/print/attribute/standard/PrinterMessageFromOperator.java \
-javax/print/attribute/standard/PrinterMoreInfo.java \
-javax/print/attribute/standard/PrinterMoreInfoManufacturer.java \
 javax/print/attribute/standard/PrinterName.java \
-javax/print/attribute/standard/PrinterResolution.java \
-javax/print/attribute/standard/PrinterState.java \
-javax/print/attribute/standard/PrinterStateReason.java \
-javax/print/attribute/standard/PrinterStateReasons.java \
-javax/print/attribute/standard/PrinterURI.java \
 javax/print/attribute/standard/QueuedJobCount.java \
-javax/print/attribute/standard/ReferenceUriSchemesSupported.java \
 javax/print/attribute/standard/RequestingUserName.java \
 javax/print/attribute/standard/Severity.java \
 javax/print/attribute/standard/SheetCollate.java \
@@ -2379,6 +2368,7 @@ java/lang/UnsupportedOperationException.java \
 java/lang/VerifyError.java \
 java/lang/VirtualMachineError.java \
 java/lang/VMClassLoader.java \
+java/lang/VMCompiler.java \
 java/lang/VMSecurityManager.java \
 java/lang/VMThrowable.java \
 java/lang/Void.java \
@@ -2567,11 +2557,13 @@ gnu/gcj/runtime/FinalizerThread.java \
 gnu/gcj/runtime/JNIWeakRef.java \
 gnu/gcj/runtime/MethodRef.java \
 gnu/gcj/runtime/NameFinder.java \
+gnu/gcj/runtime/PersistentByteMap.java \
 gnu/gcj/runtime/SharedLibHelper.java \
 gnu/gcj/runtime/SharedLibLoader.java \
 gnu/gcj/runtime/StackTrace.java \
 gnu/gcj/runtime/StringBuffer.java \
 gnu/gcj/runtime/VMClassLoader.java \
+gnu/gcj/util/Debug.java \
 gnu/java/io/ASN1ParsingException.java \
 gnu/java/io/Base64InputStream.java \
 gnu/java/io/ClassLoaderObjectInputStream.java \
@@ -3282,6 +3274,7 @@ gnu/gcj/runtime/natSharedLibLoader.cc \
 gnu/gcj/runtime/natStackTrace.cc \
 gnu/gcj/runtime/natStringBuffer.cc \
 gnu/gcj/runtime/natVMClassLoader.cc \
+gnu/gcj/util/natDebug.cc \
 gnu/java/lang/natMainThread.cc \
 gnu/java/net/natPlainDatagramSocketImpl.cc \
 gnu/java/net/natPlainSocketImpl.cc \
diff --git a/libjava/Makefile.in b/libjava/Makefile.in
index 31032fc6f021..60161a4bee98 100644
--- a/libjava/Makefile.in
+++ b/libjava/Makefile.in
@@ -17,7 +17,7 @@
 
 
 
-SOURCES = $(lib_gnu_awt_xlib_la_SOURCES) $(lib_gnu_java_awt_peer_gtk_la_SOURCES) $(lib_org_ietf_jgss_la_SOURCES) $(lib_org_w3c_dom_la_SOURCES) $(lib_org_xml_sax_la_SOURCES) $(libgcj_la_SOURCES) $(libgij_la_SOURCES) $(gen_from_JIS_SOURCES) $(gij_SOURCES) $(grmic_SOURCES) $(grmiregistry_SOURCES) $(jv_convert_SOURCES)
+SOURCES = $(lib_gnu_awt_xlib_la_SOURCES) $(lib_gnu_java_awt_peer_gtk_la_SOURCES) $(lib_org_ietf_jgss_la_SOURCES) $(lib_org_w3c_dom_la_SOURCES) $(lib_org_xml_sax_la_SOURCES) $(libgcj_la_SOURCES) $(libgij_la_SOURCES) $(gcj_dbtool_SOURCES) $(gen_from_JIS_SOURCES) $(gij_SOURCES) $(grmic_SOURCES) $(grmiregistry_SOURCES) $(jv_convert_SOURCES)
 
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
@@ -43,7 +43,8 @@ build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
 @NATIVE_TRUE@bin_PROGRAMS = jv-convert$(EXEEXT) gij$(EXEEXT) \
-@NATIVE_TRUE@	grmic$(EXEEXT) grmiregistry$(EXEEXT)
+@NATIVE_TRUE@	grmic$(EXEEXT) grmiregistry$(EXEEXT) \
+@NATIVE_TRUE@	gcj-dbtool$(EXEEXT)
 @MAINTAINER_MODE_TRUE@@NATIVE_TRUE@noinst_PROGRAMS =  \
 @MAINTAINER_MODE_TRUE@@NATIVE_TRUE@	gen-from-JIS$(EXEEXT)
 DIST_COMMON = README $(am__configure_deps) $(srcdir)/../compile \
@@ -371,7 +372,7 @@ lib_org_xml_sax_la_OBJECTS = $(am_lib_org_xml_sax_la_OBJECTS)
 am__DEPENDENCIES_4 = gnu/regexp/MessagesBundle.properties.lo \
 	gnu/regexp/MessagesBundle_fr.properties.lo
 am__DEPENDENCIES_5 = $(am__DEPENDENCIES_4)
-am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc resolve.cc \
+am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc link.cc \
 	defineclass.cc interpret.cc verify.cc gnu/gcj/natCore.cc \
 	gnu/gcj/convert/JIS0208_to_Unicode.cc \
 	gnu/gcj/convert/JIS0212_to_Unicode.cc \
@@ -386,7 +387,7 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc resolve.cc \
 	gnu/gcj/runtime/natSharedLibLoader.cc \
 	gnu/gcj/runtime/natStackTrace.cc \
 	gnu/gcj/runtime/natStringBuffer.cc \
-	gnu/gcj/runtime/natVMClassLoader.cc \
+	gnu/gcj/runtime/natVMClassLoader.cc gnu/gcj/util/natDebug.cc \
 	gnu/java/lang/natMainThread.cc \
 	gnu/java/net/natPlainDatagramSocketImpl.cc \
 	gnu/java/net/natPlainSocketImpl.cc \
@@ -481,9 +482,9 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc resolve.cc \
 	java/lang/UnsupportedClassVersionError.java \
 	java/lang/UnsupportedOperationException.java \
 	java/lang/VerifyError.java java/lang/VirtualMachineError.java \
-	java/lang/VMClassLoader.java java/lang/VMSecurityManager.java \
-	java/lang/VMThrowable.java java/lang/Void.java \
-	java/io/BufferedInputStream.java \
+	java/lang/VMClassLoader.java java/lang/VMCompiler.java \
+	java/lang/VMSecurityManager.java java/lang/VMThrowable.java \
+	java/lang/Void.java java/io/BufferedInputStream.java \
 	java/io/BufferedOutputStream.java java/io/BufferedReader.java \
 	java/io/BufferedWriter.java java/io/ByteArrayInputStream.java \
 	java/io/ByteArrayOutputStream.java \
@@ -597,11 +598,12 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc resolve.cc \
 	gnu/gcj/runtime/FinalizerThread.java \
 	gnu/gcj/runtime/JNIWeakRef.java gnu/gcj/runtime/MethodRef.java \
 	gnu/gcj/runtime/NameFinder.java \
+	gnu/gcj/runtime/PersistentByteMap.java \
 	gnu/gcj/runtime/SharedLibHelper.java \
 	gnu/gcj/runtime/SharedLibLoader.java \
 	gnu/gcj/runtime/StackTrace.java \
 	gnu/gcj/runtime/StringBuffer.java \
-	gnu/gcj/runtime/VMClassLoader.java \
+	gnu/gcj/runtime/VMClassLoader.java gnu/gcj/util/Debug.java \
 	gnu/java/io/ASN1ParsingException.java \
 	gnu/java/io/Base64InputStream.java \
 	gnu/java/io/ClassLoaderObjectInputStream.java \
@@ -2174,65 +2176,35 @@ am__libgcj_la_SOURCES_DIST = prims.cc jni.cc exception.cc resolve.cc \
 	javax/print/attribute/TextSyntax.java \
 	javax/print/attribute/UnmodifiableSetException.java \
 	javax/print/attribute/URISyntax.java \
-	javax/print/attribute/standard/ColorSupported.java \
-	javax/print/attribute/standard/Compression.java \
 	javax/print/attribute/standard/Copies.java \
-	javax/print/attribute/standard/CopiesSupported.java \
 	javax/print/attribute/standard/DateTimeAtCompleted.java \
 	javax/print/attribute/standard/DateTimeAtCreation.java \
 	javax/print/attribute/standard/DateTimeAtProcessing.java \
 	javax/print/attribute/standard/DocumentName.java \
-	javax/print/attribute/standard/Fidelity.java \
-	javax/print/attribute/standard/Finishings.java \
 	javax/print/attribute/standard/JobHoldUntil.java \
 	javax/print/attribute/standard/JobImpressions.java \
 	javax/print/attribute/standard/JobImpressionsCompleted.java \
-	javax/print/attribute/standard/JobImpressionsSupported.java \
 	javax/print/attribute/standard/JobKOctets.java \
 	javax/print/attribute/standard/JobKOctetsProcessed.java \
-	javax/print/attribute/standard/JobKOctetsSupported.java \
 	javax/print/attribute/standard/JobMediaSheets.java \
 	javax/print/attribute/standard/JobMediaSheetsCompleted.java \
-	javax/print/attribute/standard/JobMediaSheetsSupported.java \
 	javax/print/attribute/standard/JobMessageFromOperator.java \
 	javax/print/attribute/standard/JobName.java \
 	javax/print/attribute/standard/JobOriginatingUserName.java \
 	javax/print/attribute/standard/JobPriority.java \
 	javax/print/attribute/standard/JobPrioritySupported.java \
-	javax/print/attribute/standard/JobSheets.java \
-	javax/print/attribute/standard/JobState.java \
-	javax/print/attribute/standard/JobStateReason.java \
-	javax/print/attribute/standard/JobStateReasons.java \
-	javax/print/attribute/standard/Media.java \
-	javax/print/attribute/standard/MediaSizeName.java \
-	javax/print/attribute/standard/MultipleDocumentHandling.java \
 	javax/print/attribute/standard/NumberOfDocuments.java \
 	javax/print/attribute/standard/NumberOfInterveningJobs.java \
 	javax/print/attribute/standard/NumberUp.java \
-	javax/print/attribute/standard/NumberUpSupported.java \
-	javax/print/attribute/standard/OrientationRequested.java \
 	javax/print/attribute/standard/OutputDeviceAssigned.java \
-	javax/print/attribute/standard/PDLOverrideSupported.java \
-	javax/print/attribute/standard/PageRanges.java \
 	javax/print/attribute/standard/PagesPerMinute.java \
 	javax/print/attribute/standard/PagesPerMinuteColor.java \
-	javax/print/attribute/standard/PresentationDirection.java \
-	javax/print/attribute/standard/PrintQuality.java \
 	javax/print/attribute/standard/PrinterInfo.java \
-	javax/print/attribute/standard/PrinterIsAcceptingJobs.java \
 	javax/print/attribute/standard/PrinterLocation.java \
 	javax/print/attribute/standard/PrinterMakeAndModel.java \
 	javax/print/attribute/standard/PrinterMessageFromOperator.java \
-	javax/print/attribute/standard/PrinterMoreInfo.java \
-	javax/print/attribute/standard/PrinterMoreInfoManufacturer.java \
 	javax/print/attribute/standard/PrinterName.java \
-	javax/print/attribute/standard/PrinterResolution.java \
-	javax/print/attribute/standard/PrinterState.java \
-	javax/print/attribute/standard/PrinterStateReason.java \
-	javax/print/attribute/standard/PrinterStateReasons.java \
-	javax/print/attribute/standard/PrinterURI.java \
 	javax/print/attribute/standard/QueuedJobCount.java \
-	javax/print/attribute/standard/ReferenceUriSchemesSupported.java \
 	javax/print/attribute/standard/RequestingUserName.java \
 	javax/print/attribute/standard/Severity.java \
 	javax/print/attribute/standard/SheetCollate.java \
@@ -2337,7 +2309,7 @@ am__objects_6 = gnu/gcj/natCore.lo \
 	gnu/gcj/runtime/natSharedLibLoader.lo \
 	gnu/gcj/runtime/natStackTrace.lo \
 	gnu/gcj/runtime/natStringBuffer.lo \
-	gnu/gcj/runtime/natVMClassLoader.lo \
+	gnu/gcj/runtime/natVMClassLoader.lo gnu/gcj/util/natDebug.lo \
 	gnu/java/lang/natMainThread.lo \
 	gnu/java/net/natPlainDatagramSocketImpl.lo \
 	gnu/java/net/natPlainSocketImpl.lo \
@@ -2428,11 +2400,11 @@ am__objects_9 = java/lang/AbstractMethodError.lo \
 	java/lang/UnsupportedClassVersionError.lo \
 	java/lang/UnsupportedOperationException.lo \
 	java/lang/VerifyError.lo java/lang/VirtualMachineError.lo \
-	java/lang/VMClassLoader.lo java/lang/VMSecurityManager.lo \
-	java/lang/VMThrowable.lo java/lang/Void.lo \
-	java/io/BufferedInputStream.lo java/io/BufferedOutputStream.lo \
-	java/io/BufferedReader.lo java/io/BufferedWriter.lo \
-	java/io/ByteArrayInputStream.lo \
+	java/lang/VMClassLoader.lo java/lang/VMCompiler.lo \
+	java/lang/VMSecurityManager.lo java/lang/VMThrowable.lo \
+	java/lang/Void.lo java/io/BufferedInputStream.lo \
+	java/io/BufferedOutputStream.lo java/io/BufferedReader.lo \
+	java/io/BufferedWriter.lo java/io/ByteArrayInputStream.lo \
 	java/io/ByteArrayOutputStream.lo java/io/CharArrayReader.lo \
 	java/io/CharArrayWriter.lo java/io/CharConversionException.lo \
 	java/io/DataInput.lo java/io/DataInputStream.lo \
@@ -3435,65 +3407,35 @@ am__objects_13 = javax/accessibility/Accessible.lo \
 	javax/print/attribute/TextSyntax.lo \
 	javax/print/attribute/UnmodifiableSetException.lo \
 	javax/print/attribute/URISyntax.lo \
-	javax/print/attribute/standard/ColorSupported.lo \
-	javax/print/attribute/standard/Compression.lo \
 	javax/print/attribute/standard/Copies.lo \
-	javax/print/attribute/standard/CopiesSupported.lo \
 	javax/print/attribute/standard/DateTimeAtCompleted.lo \
 	javax/print/attribute/standard/DateTimeAtCreation.lo \
 	javax/print/attribute/standard/DateTimeAtProcessing.lo \
 	javax/print/attribute/standard/DocumentName.lo \
-	javax/print/attribute/standard/Fidelity.lo \
-	javax/print/attribute/standard/Finishings.lo \
 	javax/print/attribute/standard/JobHoldUntil.lo \
 	javax/print/attribute/standard/JobImpressions.lo \
 	javax/print/attribute/standard/JobImpressionsCompleted.lo \
-	javax/print/attribute/standard/JobImpressionsSupported.lo \
 	javax/print/attribute/standard/JobKOctets.lo \
 	javax/print/attribute/standard/JobKOctetsProcessed.lo \
-	javax/print/attribute/standard/JobKOctetsSupported.lo \
 	javax/print/attribute/standard/JobMediaSheets.lo \
 	javax/print/attribute/standard/JobMediaSheetsCompleted.lo \
-	javax/print/attribute/standard/JobMediaSheetsSupported.lo \
 	javax/print/attribute/standard/JobMessageFromOperator.lo \
 	javax/print/attribute/standard/JobName.lo \
 	javax/print/attribute/standard/JobOriginatingUserName.lo \
 	javax/print/attribute/standard/JobPriority.lo \
 	javax/print/attribute/standard/JobPrioritySupported.lo \
-	javax/print/attribute/standard/JobSheets.lo \
-	javax/print/attribute/standard/JobState.lo \
-	javax/print/attribute/standard/JobStateReason.lo \
-	javax/print/attribute/standard/JobStateReasons.lo \
-	javax/print/attribute/standard/Media.lo \
-	javax/print/attribute/standard/MediaSizeName.lo \
-	javax/print/attribute/standard/MultipleDocumentHandling.lo \
 	javax/print/attribute/standard/NumberOfDocuments.lo \
 	javax/print/attribute/standard/NumberOfInterveningJobs.lo \
 	javax/print/attribute/standard/NumberUp.lo \
-	javax/print/attribute/standard/NumberUpSupported.lo \
-	javax/print/attribute/standard/OrientationRequested.lo \
 	javax/print/attribute/standard/OutputDeviceAssigned.lo \
-	javax/print/attribute/standard/PDLOverrideSupported.lo \
-	javax/print/attribute/standard/PageRanges.lo \
 	javax/print/attribute/standard/PagesPerMinute.lo \
 	javax/print/attribute/standard/PagesPerMinuteColor.lo \
-	javax/print/attribute/standard/PresentationDirection.lo \
-	javax/print/attribute/standard/PrintQuality.lo \
 	javax/print/attribute/standard/PrinterInfo.lo \
-	javax/print/attribute/standard/PrinterIsAcceptingJobs.lo \
 	javax/print/attribute/standard/PrinterLocation.lo \
 	javax/print/attribute/standard/PrinterMakeAndModel.lo \
 	javax/print/attribute/standard/PrinterMessageFromOperator.lo \
-	javax/print/attribute/standard/PrinterMoreInfo.lo \
-	javax/print/attribute/standard/PrinterMoreInfoManufacturer.lo \
 	javax/print/attribute/standard/PrinterName.lo \
-	javax/print/attribute/standard/PrinterResolution.lo \
-	javax/print/attribute/standard/PrinterState.lo \
-	javax/print/attribute/standard/PrinterStateReason.lo \
-	javax/print/attribute/standard/PrinterStateReasons.lo \
-	javax/print/attribute/standard/PrinterURI.lo \
 	javax/print/attribute/standard/QueuedJobCount.lo \
-	javax/print/attribute/standard/ReferenceUriSchemesSupported.lo \
 	javax/print/attribute/standard/RequestingUserName.lo \
 	javax/print/attribute/standard/Severity.lo \
 	javax/print/attribute/standard/SheetCollate.lo \
@@ -3585,10 +3527,11 @@ am__objects_14 = $(am__objects_9) gnu/classpath/ServiceFactory.lo \
 	gnu/gcj/runtime/FinalizerThread.lo \
 	gnu/gcj/runtime/JNIWeakRef.lo gnu/gcj/runtime/MethodRef.lo \
 	gnu/gcj/runtime/NameFinder.lo \
+	gnu/gcj/runtime/PersistentByteMap.lo \
 	gnu/gcj/runtime/SharedLibHelper.lo \
 	gnu/gcj/runtime/SharedLibLoader.lo \
 	gnu/gcj/runtime/StackTrace.lo gnu/gcj/runtime/StringBuffer.lo \
-	gnu/gcj/runtime/VMClassLoader.lo \
+	gnu/gcj/runtime/VMClassLoader.lo gnu/gcj/util/Debug.lo \
 	gnu/java/io/ASN1ParsingException.lo \
 	gnu/java/io/Base64InputStream.lo \
 	gnu/java/io/ClassLoaderObjectInputStream.lo \
@@ -4151,7 +4094,7 @@ am__objects_16 = java/lang/ConcreteProcess.lo \
 @USING_POSIX_THREADS_TRUE@am__objects_24 = posix-threads.lo
 @USING_WIN32_THREADS_TRUE@am__objects_25 = win32-threads.lo
 @USING_NO_THREADS_TRUE@am__objects_26 = no-threads.lo
-am_libgcj_la_OBJECTS = prims.lo jni.lo exception.lo resolve.lo \
+am_libgcj_la_OBJECTS = prims.lo jni.lo exception.lo link.lo \
 	defineclass.lo interpret.lo verify.lo $(am__objects_6) \
 	$(am__objects_7) $(am__objects_15) $(am__objects_16) \
 	$(am__objects_17) $(am__objects_18) $(am__objects_19) \
@@ -4163,6 +4106,8 @@ am_libgij_la_OBJECTS = gij.lo
 libgij_la_OBJECTS = $(am_libgij_la_OBJECTS)
 binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+am_gcj_dbtool_OBJECTS = gnu/gcj/tools/gcj_dbtool/Main.$(OBJEXT)
+gcj_dbtool_OBJECTS = $(am_gcj_dbtool_OBJECTS)
 am__gen_from_JIS_SOURCES_DIST = gnu/gcj/convert/gen-from-JIS.c \
 	gnu/gcj/convert/make-trie.c
 @MAINTAINER_MODE_TRUE@@NATIVE_TRUE@am_gen_from_JIS_OBJECTS = gnu/gcj/convert/gen-from-JIS.$(OBJEXT) \
@@ -4206,15 +4151,16 @@ SOURCES = $(lib_gnu_awt_xlib_la_SOURCES) \
 	$(lib_gnu_java_awt_peer_gtk_la_SOURCES) \
 	$(lib_org_ietf_jgss_la_SOURCES) $(lib_org_w3c_dom_la_SOURCES) \
 	$(lib_org_xml_sax_la_SOURCES) $(libgcj_la_SOURCES) \
-	$(libgij_la_SOURCES) $(gen_from_JIS_SOURCES) $(gij_SOURCES) \
-	$(grmic_SOURCES) $(grmiregistry_SOURCES) $(jv_convert_SOURCES)
+	$(libgij_la_SOURCES) $(gcj_dbtool_SOURCES) \
+	$(gen_from_JIS_SOURCES) $(gij_SOURCES) $(grmic_SOURCES) \
+	$(grmiregistry_SOURCES) $(jv_convert_SOURCES)
 DIST_SOURCES = $(lib_gnu_awt_xlib_la_SOURCES) \
 	$(am__lib_gnu_java_awt_peer_gtk_la_SOURCES_DIST) \
 	$(lib_org_ietf_jgss_la_SOURCES) $(lib_org_w3c_dom_la_SOURCES) \
 	$(lib_org_xml_sax_la_SOURCES) $(am__libgcj_la_SOURCES_DIST) \
-	$(libgij_la_SOURCES) $(am__gen_from_JIS_SOURCES_DIST) \
-	$(gij_SOURCES) $(grmic_SOURCES) $(grmiregistry_SOURCES) \
-	$(jv_convert_SOURCES)
+	$(libgij_la_SOURCES) $(gcj_dbtool_SOURCES) \
+	$(am__gen_from_JIS_SOURCES_DIST) $(gij_SOURCES) \
+	$(grmic_SOURCES) $(grmiregistry_SOURCES) $(jv_convert_SOURCES)
 RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
 	html-recursive info-recursive install-data-recursive \
 	install-exec-recursive install-info-recursive \
@@ -4314,6 +4260,7 @@ LIBGCJTESTSPEC = @LIBGCJTESTSPEC@
 LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@
 LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@
 LIBGCJ_JAVAFLAGS = @LIBGCJ_JAVAFLAGS@
+LIBGCJ_LD_SYMBOLIC = @LIBGCJ_LD_SYMBOLIC@
 LIBICONV = @LIBICONV@
 LIBLTDL = @LIBLTDL@
 LIBOBJS = @LIBOBJS@
@@ -4546,7 +4493,7 @@ libgij_la_SOURCES = gij.cc
 libgij_la_LIBADD = libgcj.la
 libgij_la_DEPENDENCIES = libgcj.la libgcj.spec
 libgcj_la_SOURCES = prims.cc jni.cc exception.cc \
-	resolve.cc defineclass.cc interpret.cc verify.cc \
+	link.cc defineclass.cc interpret.cc verify.cc \
 	$(nat_source_files) $(math_c_source_files) $(java_source_files) \
 	$(built_java_source_files) \
 	$(BOEHMGC_SRC) $(NOGC_SRC) \
@@ -4686,7 +4633,7 @@ lib_gnu_java_awt_peer_gtk_la_GCJFLAGS = $(AM_GCJFLAGS) -fjni
 lib_gnu_java_awt_peer_gtk_la_LIBADD = $(GTK_LIBS) $(GLIB_LIBS) $(LIBART_LIBS) $(CAIRO_LIBS) $(PANGOFT2_LIBS)
 lib_gnu_java_awt_peer_gtk_la_DEPENDENCIES = $(gtk_jni_headers) libgcj-@gcc_version@.jar libgcj.la libgcj.spec
 lib_gnu_java_awt_peer_gtk_la_LDFLAGS = \
-        -version-info `grep -v '^\#' $(srcdir)/libtool-version`
+        -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC)
 
 lib_gnu_java_awt_peer_gtk_la_LINK = $(LIBLINK)
 lib_org_ietf_jgss_la_SOURCES = \
@@ -4706,7 +4653,7 @@ lib_org_ietf_jgss_la_LIBADD = -L$(here)/.libs  $(jgss_propertyo_files) \
 	libgcj.la
 
 lib_org_ietf_jgss_la_LDFLAGS = -rpath $(toolexeclibdir) \
-	-version-info `grep -v '^\#' $(srcdir)/libtool-version`
+	-version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC)
 
 lib_org_w3c_dom_la_SOURCES = org/w3c/dom/Attr.java \
 org/w3c/dom/CDATASection.java \
@@ -4736,7 +4683,7 @@ org/w3c/dom/traversal/TreeWalker.java
 
 lib_org_w3c_dom_la_LIBADD = -L$(here)/.libs libgcj.la
 lib_org_w3c_dom_la_LDFLAGS = -rpath $(toolexeclibdir) \
-        -version-info `grep -v '^\#' $(srcdir)/libtool-version`
+        -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC)
 
 lib_org_xml_sax_la_SOURCES = org/xml/sax/ext/DeclHandler.java \
 org/xml/sax/ext/LexicalHandler.java \
@@ -4771,7 +4718,7 @@ org/xml/sax/XMLReader.java
 
 lib_org_xml_sax_la_LIBADD = -L$(here)/.libs libgcj.la
 lib_org_xml_sax_la_LDFLAGS = -rpath $(toolexeclibdir) \
-        -version-info `grep -v '^\#' $(srcdir)/libtool-version`
+        -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC)
 
 lib_gnu_awt_xlib_la_SOURCES = \
 	$(xlib_java_source_files) \
@@ -4787,7 +4734,7 @@ lib_gnu_awt_xlib_la_CPPFLAGS = \
 lib_gnu_awt_xlib_la_LDFLAGS = ../libstdc++-v3/src/libstdc++.la \
 	@X_PRE_LIBS@ @X_LIBS@ -lX11 @X_EXTRA_LIBS@ \
         -rpath $(toolexeclibdir) \
-        -version-info `grep -v '^\#' $(srcdir)/libtool-version`
+        -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC)
 
 lib_gnu_awt_xlib_la_LINK = $(LIBLINK)
 all_java_source_files = \
@@ -4851,6 +4798,13 @@ jv_convert_LDFLAGS = --main=gnu.gcj.convert.Convert \
 jv_convert_LINK = $(GCJLINK)
 jv_convert_LDADD = -L$(here)/.libs libgcj.la
 jv_convert_DEPENDENCIES = libgcj.la libgcj.spec
+gcj_dbtool_SOURCES = gnu/gcj/tools/gcj_dbtool/Main.java
+gcj_dbtool_LDFLAGS = --main=gnu.gcj.tools.gcj_dbtool.Main \
+	-rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
+
+gcj_dbtool_LINK = $(GCJLINK)
+gcj_dbtool_LDADD = -L$(here)/.libs libgcj.la
+gcj_dbtool_DEPENDENCIES = libgcj.la libgcj.spec
 gij_SOURCES = 
 gij_LDFLAGS = -rpath $(toolexeclibdir) -shared-libgcc $(THREADLDFLAGS)
 gij_LINK = $(GCJLINK)
@@ -6022,65 +5976,35 @@ javax/print/attribute/SupportedValuesAttribute.java \
 javax/print/attribute/TextSyntax.java \
 javax/print/attribute/UnmodifiableSetException.java \
 javax/print/attribute/URISyntax.java \
-javax/print/attribute/standard/ColorSupported.java \
-javax/print/attribute/standard/Compression.java \
 javax/print/attribute/standard/Copies.java \
-javax/print/attribute/standard/CopiesSupported.java \
 javax/print/attribute/standard/DateTimeAtCompleted.java \
 javax/print/attribute/standard/DateTimeAtCreation.java \
 javax/print/attribute/standard/DateTimeAtProcessing.java \
 javax/print/attribute/standard/DocumentName.java \
-javax/print/attribute/standard/Fidelity.java \
-javax/print/attribute/standard/Finishings.java \
 javax/print/attribute/standard/JobHoldUntil.java \
 javax/print/attribute/standard/JobImpressions.java \
 javax/print/attribute/standard/JobImpressionsCompleted.java \
-javax/print/attribute/standard/JobImpressionsSupported.java \
 javax/print/attribute/standard/JobKOctets.java \
 javax/print/attribute/standard/JobKOctetsProcessed.java \
-javax/print/attribute/standard/JobKOctetsSupported.java \
 javax/print/attribute/standard/JobMediaSheets.java \
 javax/print/attribute/standard/JobMediaSheetsCompleted.java \
-javax/print/attribute/standard/JobMediaSheetsSupported.java \
 javax/print/attribute/standard/JobMessageFromOperator.java \
 javax/print/attribute/standard/JobName.java \
 javax/print/attribute/standard/JobOriginatingUserName.java \
 javax/print/attribute/standard/JobPriority.java \
 javax/print/attribute/standard/JobPrioritySupported.java \
-javax/print/attribute/standard/JobSheets.java \
-javax/print/attribute/standard/JobState.java \
-javax/print/attribute/standard/JobStateReason.java \
-javax/print/attribute/standard/JobStateReasons.java \
-javax/print/attribute/standard/Media.java \
-javax/print/attribute/standard/MediaSizeName.java \
-javax/print/attribute/standard/MultipleDocumentHandling.java \
 javax/print/attribute/standard/NumberOfDocuments.java \
 javax/print/attribute/standard/NumberOfInterveningJobs.java \
 javax/print/attribute/standard/NumberUp.java \
-javax/print/attribute/standard/NumberUpSupported.java \
-javax/print/attribute/standard/OrientationRequested.java \
 javax/print/attribute/standard/OutputDeviceAssigned.java \
-javax/print/attribute/standard/PDLOverrideSupported.java \
-javax/print/attribute/standard/PageRanges.java \
 javax/print/attribute/standard/PagesPerMinute.java \
 javax/print/attribute/standard/PagesPerMinuteColor.java \
-javax/print/attribute/standard/PresentationDirection.java \
-javax/print/attribute/standard/PrintQuality.java \
 javax/print/attribute/standard/PrinterInfo.java \
-javax/print/attribute/standard/PrinterIsAcceptingJobs.java \
 javax/print/attribute/standard/PrinterLocation.java \
 javax/print/attribute/standard/PrinterMakeAndModel.java \
 javax/print/attribute/standard/PrinterMessageFromOperator.java \
-javax/print/attribute/standard/PrinterMoreInfo.java \
-javax/print/attribute/standard/PrinterMoreInfoManufacturer.java \
 javax/print/attribute/standard/PrinterName.java \
-javax/print/attribute/standard/PrinterResolution.java \
-javax/print/attribute/standard/PrinterState.java \
-javax/print/attribute/standard/PrinterStateReason.java \
-javax/print/attribute/standard/PrinterStateReasons.java \
-javax/print/attribute/standard/PrinterURI.java \
 javax/print/attribute/standard/QueuedJobCount.java \
-javax/print/attribute/standard/ReferenceUriSchemesSupported.java \
 javax/print/attribute/standard/RequestingUserName.java \
 javax/print/attribute/standard/Severity.java \
 javax/print/attribute/standard/SheetCollate.java \
@@ -6255,6 +6179,7 @@ java/lang/UnsupportedOperationException.java \
 java/lang/VerifyError.java \
 java/lang/VirtualMachineError.java \
 java/lang/VMClassLoader.java \
+java/lang/VMCompiler.java \
 java/lang/VMSecurityManager.java \
 java/lang/VMThrowable.java \
 java/lang/Void.java \
@@ -6437,11 +6362,13 @@ gnu/gcj/runtime/FinalizerThread.java \
 gnu/gcj/runtime/JNIWeakRef.java \
 gnu/gcj/runtime/MethodRef.java \
 gnu/gcj/runtime/NameFinder.java \
+gnu/gcj/runtime/PersistentByteMap.java \
 gnu/gcj/runtime/SharedLibHelper.java \
 gnu/gcj/runtime/SharedLibLoader.java \
 gnu/gcj/runtime/StackTrace.java \
 gnu/gcj/runtime/StringBuffer.java \
 gnu/gcj/runtime/VMClassLoader.java \
+gnu/gcj/util/Debug.java \
 gnu/java/io/ASN1ParsingException.java \
 gnu/java/io/Base64InputStream.java \
 gnu/java/io/ClassLoaderObjectInputStream.java \
@@ -7147,6 +7074,7 @@ gnu/gcj/runtime/natSharedLibLoader.cc \
 gnu/gcj/runtime/natStackTrace.cc \
 gnu/gcj/runtime/natStringBuffer.cc \
 gnu/gcj/runtime/natVMClassLoader.cc \
+gnu/gcj/util/natDebug.cc \
 gnu/java/lang/natMainThread.cc \
 gnu/java/net/natPlainDatagramSocketImpl.cc \
 gnu/java/net/natPlainSocketImpl.cc \
@@ -8042,6 +7970,14 @@ gnu/gcj/runtime/natStringBuffer.lo: gnu/gcj/runtime/$(am__dirstamp) \
 	gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp)
 gnu/gcj/runtime/natVMClassLoader.lo: gnu/gcj/runtime/$(am__dirstamp) \
 	gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp)
+gnu/gcj/util/$(am__dirstamp):
+	@$(mkdir_p) gnu/gcj/util
+	@: > gnu/gcj/util/$(am__dirstamp)
+gnu/gcj/util/$(DEPDIR)/$(am__dirstamp):
+	@$(mkdir_p) gnu/gcj/util/$(DEPDIR)
+	@: > gnu/gcj/util/$(DEPDIR)/$(am__dirstamp)
+gnu/gcj/util/natDebug.lo: gnu/gcj/util/$(am__dirstamp) \
+	gnu/gcj/util/$(DEPDIR)/$(am__dirstamp)
 gnu/java/lang/$(am__dirstamp):
 	@$(mkdir_p) gnu/java/lang
 	@: > gnu/java/lang/$(am__dirstamp)
@@ -8456,6 +8392,8 @@ java/lang/VirtualMachineError.lo: java/lang/$(am__dirstamp) \
 	java/lang/$(DEPDIR)/$(am__dirstamp)
 java/lang/VMClassLoader.lo: java/lang/$(am__dirstamp) \
 	java/lang/$(DEPDIR)/$(am__dirstamp)
+java/lang/VMCompiler.lo: java/lang/$(am__dirstamp) \
+	java/lang/$(DEPDIR)/$(am__dirstamp)
 java/lang/VMSecurityManager.lo: java/lang/$(am__dirstamp) \
 	java/lang/$(DEPDIR)/$(am__dirstamp)
 java/lang/VMThrowable.lo: java/lang/$(am__dirstamp) \
@@ -8852,6 +8790,8 @@ gnu/gcj/runtime/MethodRef.lo: gnu/gcj/runtime/$(am__dirstamp) \
 	gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp)
 gnu/gcj/runtime/NameFinder.lo: gnu/gcj/runtime/$(am__dirstamp) \
 	gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp)
+gnu/gcj/runtime/PersistentByteMap.lo: gnu/gcj/runtime/$(am__dirstamp) \
+	gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp)
 gnu/gcj/runtime/SharedLibHelper.lo: gnu/gcj/runtime/$(am__dirstamp) \
 	gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp)
 gnu/gcj/runtime/SharedLibLoader.lo: gnu/gcj/runtime/$(am__dirstamp) \
@@ -8862,6 +8802,8 @@ gnu/gcj/runtime/StringBuffer.lo: gnu/gcj/runtime/$(am__dirstamp) \
 	gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp)
 gnu/gcj/runtime/VMClassLoader.lo: gnu/gcj/runtime/$(am__dirstamp) \
 	gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp)
+gnu/gcj/util/Debug.lo: gnu/gcj/util/$(am__dirstamp) \
+	gnu/gcj/util/$(DEPDIR)/$(am__dirstamp)
 gnu/java/io/$(am__dirstamp):
 	@$(mkdir_p) gnu/java/io
 	@: > gnu/java/io/$(am__dirstamp)
@@ -13836,18 +13778,9 @@ javax/print/attribute/standard/$(am__dirstamp):
 javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp):
 	@$(mkdir_p) javax/print/attribute/standard/$(DEPDIR)
 	@: > javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/ColorSupported.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/Compression.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/Copies.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/CopiesSupported.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/DateTimeAtCompleted.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
@@ -13860,12 +13793,6 @@ javax/print/attribute/standard/DateTimeAtProcessing.lo:  \
 javax/print/attribute/standard/DocumentName.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/Fidelity.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/Finishings.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/JobHoldUntil.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
@@ -13875,27 +13802,18 @@ javax/print/attribute/standard/JobImpressions.lo:  \
 javax/print/attribute/standard/JobImpressionsCompleted.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/JobImpressionsSupported.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/JobKOctets.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/JobKOctetsProcessed.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/JobKOctetsSupported.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/JobMediaSheets.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/JobMediaSheetsCompleted.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/JobMediaSheetsSupported.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/JobMessageFromOperator.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
@@ -13911,27 +13829,6 @@ javax/print/attribute/standard/JobPriority.lo:  \
 javax/print/attribute/standard/JobPrioritySupported.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/JobSheets.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/JobState.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/JobStateReason.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/JobStateReasons.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/Media.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/MediaSizeName.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/MultipleDocumentHandling.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/NumberOfDocuments.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
@@ -13941,39 +13838,18 @@ javax/print/attribute/standard/NumberOfInterveningJobs.lo:  \
 javax/print/attribute/standard/NumberUp.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/NumberUpSupported.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/OrientationRequested.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/OutputDeviceAssigned.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/PDLOverrideSupported.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/PageRanges.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/PagesPerMinute.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/PagesPerMinuteColor.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/PresentationDirection.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/PrintQuality.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/PrinterInfo.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/PrinterIsAcceptingJobs.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/PrinterLocation.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
@@ -13983,36 +13859,12 @@ javax/print/attribute/standard/PrinterMakeAndModel.lo:  \
 javax/print/attribute/standard/PrinterMessageFromOperator.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/PrinterMoreInfo.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/PrinterMoreInfoManufacturer.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/PrinterName.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/PrinterResolution.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/PrinterState.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/PrinterStateReason.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/PrinterStateReasons.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/PrinterURI.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/QueuedJobCount.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
-javax/print/attribute/standard/ReferenceUriSchemesSupported.lo:  \
-	javax/print/attribute/standard/$(am__dirstamp) \
-	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
 javax/print/attribute/standard/RequestingUserName.lo:  \
 	javax/print/attribute/standard/$(am__dirstamp) \
 	javax/print/attribute/standard/$(DEPDIR)/$(am__dirstamp)
@@ -14379,6 +14231,18 @@ clean-noinstPROGRAMS:
 	  echo " rm -f $$p $$f"; \
 	  rm -f $$p $$f ; \
 	done
+gnu/gcj/tools/gcj_dbtool/$(am__dirstamp):
+	@$(mkdir_p) gnu/gcj/tools/gcj_dbtool
+	@: > gnu/gcj/tools/gcj_dbtool/$(am__dirstamp)
+gnu/gcj/tools/gcj_dbtool/$(DEPDIR)/$(am__dirstamp):
+	@$(mkdir_p) gnu/gcj/tools/gcj_dbtool/$(DEPDIR)
+	@: > gnu/gcj/tools/gcj_dbtool/$(DEPDIR)/$(am__dirstamp)
+gnu/gcj/tools/gcj_dbtool/Main.$(OBJEXT):  \
+	gnu/gcj/tools/gcj_dbtool/$(am__dirstamp) \
+	gnu/gcj/tools/gcj_dbtool/$(DEPDIR)/$(am__dirstamp)
+gcj-dbtool$(EXEEXT): $(gcj_dbtool_OBJECTS) $(gcj_dbtool_DEPENDENCIES) 
+	@rm -f gcj-dbtool$(EXEEXT)
+	$(gcj_dbtool_LINK) $(gcj_dbtool_LDFLAGS) $(gcj_dbtool_OBJECTS) $(gcj_dbtool_LDADD) $(LIBS)
 gnu/gcj/convert/gen-from-JIS.$(OBJEXT):  \
 	gnu/gcj/convert/$(am__dirstamp) \
 	gnu/gcj/convert/$(DEPDIR)/$(am__dirstamp)
@@ -14549,6 +14413,8 @@ mostlyclean-compile:
 	-rm -f gnu/gcj/runtime/MethodRef.lo
 	-rm -f gnu/gcj/runtime/NameFinder.$(OBJEXT)
 	-rm -f gnu/gcj/runtime/NameFinder.lo
+	-rm -f gnu/gcj/runtime/PersistentByteMap.$(OBJEXT)
+	-rm -f gnu/gcj/runtime/PersistentByteMap.lo
 	-rm -f gnu/gcj/runtime/SharedLibHelper.$(OBJEXT)
 	-rm -f gnu/gcj/runtime/SharedLibHelper.lo
 	-rm -f gnu/gcj/runtime/SharedLibLoader.$(OBJEXT)
@@ -14571,6 +14437,11 @@ mostlyclean-compile:
 	-rm -f gnu/gcj/runtime/natStringBuffer.lo
 	-rm -f gnu/gcj/runtime/natVMClassLoader.$(OBJEXT)
 	-rm -f gnu/gcj/runtime/natVMClassLoader.lo
+	-rm -f gnu/gcj/tools/gcj_dbtool/Main.$(OBJEXT)
+	-rm -f gnu/gcj/util/Debug.$(OBJEXT)
+	-rm -f gnu/gcj/util/Debug.lo
+	-rm -f gnu/gcj/util/natDebug.$(OBJEXT)
+	-rm -f gnu/gcj/util/natDebug.lo
 	-rm -f gnu/gcj/xlib/Clip.$(OBJEXT)
 	-rm -f gnu/gcj/xlib/Clip.lo
 	-rm -f gnu/gcj/xlib/Colormap.$(OBJEXT)
@@ -16531,6 +16402,8 @@ mostlyclean-compile:
 	-rm -f java/lang/UnsupportedOperationException.lo
 	-rm -f java/lang/VMClassLoader.$(OBJEXT)
 	-rm -f java/lang/VMClassLoader.lo
+	-rm -f java/lang/VMCompiler.$(OBJEXT)
+	-rm -f java/lang/VMCompiler.lo
 	-rm -f java/lang/VMSecurityManager.$(OBJEXT)
 	-rm -f java/lang/VMSecurityManager.lo
 	-rm -f java/lang/VMThrowable.$(OBJEXT)
@@ -18259,14 +18132,8 @@ mostlyclean-compile:
 	-rm -f javax/print/attribute/URISyntax.lo
 	-rm -f javax/print/attribute/UnmodifiableSetException.$(OBJEXT)
 	-rm -f javax/print/attribute/UnmodifiableSetException.lo
-	-rm -f javax/print/attribute/standard/ColorSupported.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/ColorSupported.lo
-	-rm -f javax/print/attribute/standard/Compression.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/Compression.lo
 	-rm -f javax/print/attribute/standard/Copies.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/Copies.lo
-	-rm -f javax/print/attribute/standard/CopiesSupported.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/CopiesSupported.lo
 	-rm -f javax/print/attribute/standard/DateTimeAtCompleted.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/DateTimeAtCompleted.lo
 	-rm -f javax/print/attribute/standard/DateTimeAtCreation.$(OBJEXT)
@@ -18275,30 +18142,20 @@ mostlyclean-compile:
 	-rm -f javax/print/attribute/standard/DateTimeAtProcessing.lo
 	-rm -f javax/print/attribute/standard/DocumentName.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/DocumentName.lo
-	-rm -f javax/print/attribute/standard/Fidelity.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/Fidelity.lo
-	-rm -f javax/print/attribute/standard/Finishings.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/Finishings.lo
 	-rm -f javax/print/attribute/standard/JobHoldUntil.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/JobHoldUntil.lo
 	-rm -f javax/print/attribute/standard/JobImpressions.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/JobImpressions.lo
 	-rm -f javax/print/attribute/standard/JobImpressionsCompleted.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/JobImpressionsCompleted.lo
-	-rm -f javax/print/attribute/standard/JobImpressionsSupported.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/JobImpressionsSupported.lo
 	-rm -f javax/print/attribute/standard/JobKOctets.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/JobKOctets.lo
 	-rm -f javax/print/attribute/standard/JobKOctetsProcessed.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/JobKOctetsProcessed.lo
-	-rm -f javax/print/attribute/standard/JobKOctetsSupported.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/JobKOctetsSupported.lo
 	-rm -f javax/print/attribute/standard/JobMediaSheets.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/JobMediaSheets.lo
 	-rm -f javax/print/attribute/standard/JobMediaSheetsCompleted.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/JobMediaSheetsCompleted.lo
-	-rm -f javax/print/attribute/standard/JobMediaSheetsSupported.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/JobMediaSheetsSupported.lo
 	-rm -f javax/print/attribute/standard/JobMessageFromOperator.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/JobMessageFromOperator.lo
 	-rm -f javax/print/attribute/standard/JobName.$(OBJEXT)
@@ -18309,74 +18166,30 @@ mostlyclean-compile:
 	-rm -f javax/print/attribute/standard/JobPriority.lo
 	-rm -f javax/print/attribute/standard/JobPrioritySupported.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/JobPrioritySupported.lo
-	-rm -f javax/print/attribute/standard/JobSheets.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/JobSheets.lo
-	-rm -f javax/print/attribute/standard/JobState.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/JobState.lo
-	-rm -f javax/print/attribute/standard/JobStateReason.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/JobStateReason.lo
-	-rm -f javax/print/attribute/standard/JobStateReasons.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/JobStateReasons.lo
-	-rm -f javax/print/attribute/standard/Media.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/Media.lo
-	-rm -f javax/print/attribute/standard/MediaSizeName.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/MediaSizeName.lo
-	-rm -f javax/print/attribute/standard/MultipleDocumentHandling.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/MultipleDocumentHandling.lo
 	-rm -f javax/print/attribute/standard/NumberOfDocuments.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/NumberOfDocuments.lo
 	-rm -f javax/print/attribute/standard/NumberOfInterveningJobs.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/NumberOfInterveningJobs.lo
 	-rm -f javax/print/attribute/standard/NumberUp.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/NumberUp.lo
-	-rm -f javax/print/attribute/standard/NumberUpSupported.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/NumberUpSupported.lo
-	-rm -f javax/print/attribute/standard/OrientationRequested.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/OrientationRequested.lo
 	-rm -f javax/print/attribute/standard/OutputDeviceAssigned.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/OutputDeviceAssigned.lo
-	-rm -f javax/print/attribute/standard/PDLOverrideSupported.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/PDLOverrideSupported.lo
-	-rm -f javax/print/attribute/standard/PageRanges.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/PageRanges.lo
 	-rm -f javax/print/attribute/standard/PagesPerMinute.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/PagesPerMinute.lo
 	-rm -f javax/print/attribute/standard/PagesPerMinuteColor.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/PagesPerMinuteColor.lo
-	-rm -f javax/print/attribute/standard/PresentationDirection.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/PresentationDirection.lo
-	-rm -f javax/print/attribute/standard/PrintQuality.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/PrintQuality.lo
 	-rm -f javax/print/attribute/standard/PrinterInfo.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/PrinterInfo.lo
-	-rm -f javax/print/attribute/standard/PrinterIsAcceptingJobs.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/PrinterIsAcceptingJobs.lo
 	-rm -f javax/print/attribute/standard/PrinterLocation.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/PrinterLocation.lo
 	-rm -f javax/print/attribute/standard/PrinterMakeAndModel.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/PrinterMakeAndModel.lo
 	-rm -f javax/print/attribute/standard/PrinterMessageFromOperator.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/PrinterMessageFromOperator.lo
-	-rm -f javax/print/attribute/standard/PrinterMoreInfo.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/PrinterMoreInfo.lo
-	-rm -f javax/print/attribute/standard/PrinterMoreInfoManufacturer.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/PrinterMoreInfoManufacturer.lo
 	-rm -f javax/print/attribute/standard/PrinterName.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/PrinterName.lo
-	-rm -f javax/print/attribute/standard/PrinterResolution.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/PrinterResolution.lo
-	-rm -f javax/print/attribute/standard/PrinterState.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/PrinterState.lo
-	-rm -f javax/print/attribute/standard/PrinterStateReason.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/PrinterStateReason.lo
-	-rm -f javax/print/attribute/standard/PrinterStateReasons.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/PrinterStateReasons.lo
-	-rm -f javax/print/attribute/standard/PrinterURI.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/PrinterURI.lo
 	-rm -f javax/print/attribute/standard/QueuedJobCount.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/QueuedJobCount.lo
-	-rm -f javax/print/attribute/standard/ReferenceUriSchemesSupported.$(OBJEXT)
-	-rm -f javax/print/attribute/standard/ReferenceUriSchemesSupported.lo
 	-rm -f javax/print/attribute/standard/RequestingUserName.$(OBJEXT)
 	-rm -f javax/print/attribute/standard/RequestingUserName.lo
 	-rm -f javax/print/attribute/standard/Severity.$(OBJEXT)
@@ -19490,12 +19303,12 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gij.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interpret.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jni.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/link.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/no-threads.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nogc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/posix-threads.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/posix.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prims.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resolve.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32-threads.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/win32.Plo@am__quote@
@@ -19564,6 +19377,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/JNIWeakRef.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/MethodRef.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/NameFinder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/PersistentByteMap.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/SharedLibHelper.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/SharedLibLoader.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/StackTrace.Plo@am__quote@
@@ -19575,6 +19389,9 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/natStackTrace.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/natStringBuffer.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/runtime/$(DEPDIR)/natVMClassLoader.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/tools/gcj_dbtool/$(DEPDIR)/Main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/util/$(DEPDIR)/Debug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/util/$(DEPDIR)/natDebug.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/xlib/$(DEPDIR)/Clip.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/xlib/$(DEPDIR)/Colormap.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gnu/gcj/xlib/$(DEPDIR)/Display.Plo@am__quote@
@@ -20555,6 +20372,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/UnsupportedClassVersionError.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/UnsupportedOperationException.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/VMClassLoader.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/VMCompiler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/VMSecurityManager.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/VMThrowable.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@java/lang/$(DEPDIR)/VerifyError.Plo@am__quote@
@@ -21419,65 +21237,35 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/$(DEPDIR)/TextSyntax.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/$(DEPDIR)/URISyntax.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/$(DEPDIR)/UnmodifiableSetException.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/ColorSupported.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/Compression.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/Copies.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/CopiesSupported.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/DateTimeAtCompleted.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/DateTimeAtCreation.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/DateTimeAtProcessing.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/DocumentName.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/Fidelity.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/Finishings.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobHoldUntil.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobImpressions.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobImpressionsCompleted.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobImpressionsSupported.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobKOctets.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobKOctetsProcessed.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobKOctetsSupported.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobMediaSheets.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobMediaSheetsCompleted.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobMediaSheetsSupported.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobMessageFromOperator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobName.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobOriginatingUserName.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobPriority.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobPrioritySupported.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobSheets.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobState.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobStateReason.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/JobStateReasons.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/Media.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/MediaSizeName.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/MultipleDocumentHandling.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/NumberOfDocuments.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/NumberOfInterveningJobs.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/NumberUp.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/NumberUpSupported.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/OrientationRequested.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/OutputDeviceAssigned.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PDLOverrideSupported.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PageRanges.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PagesPerMinute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PagesPerMinuteColor.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PresentationDirection.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrintQuality.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterInfo.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterIsAcceptingJobs.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterLocation.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterMakeAndModel.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterMessageFromOperator.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterMoreInfo.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterMoreInfoManufacturer.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterName.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterResolution.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterState.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterStateReason.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterStateReasons.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/PrinterURI.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/QueuedJobCount.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/ReferenceUriSchemesSupported.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/RequestingUserName.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/Severity.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@javax/print/attribute/standard/$(DEPDIR)/SheetCollate.Plo@am__quote@
@@ -22857,6 +22645,7 @@ clean-libtool:
 	-rm -rf gnu/gcj/convert/.libs gnu/gcj/convert/_libs
 	-rm -rf gnu/gcj/io/.libs gnu/gcj/io/_libs
 	-rm -rf gnu/gcj/runtime/.libs gnu/gcj/runtime/_libs
+	-rm -rf gnu/gcj/util/.libs gnu/gcj/util/_libs
 	-rm -rf gnu/gcj/xlib/.libs gnu/gcj/xlib/_libs
 	-rm -rf gnu/java/awt/.libs gnu/java/awt/_libs
 	-rm -rf gnu/java/awt/image/.libs gnu/java/awt/image/_libs
@@ -23358,6 +23147,10 @@ distclean-generic:
 	-rm -f gnu/gcj/io/$(am__dirstamp)
 	-rm -f gnu/gcj/runtime/$(DEPDIR)/$(am__dirstamp)
 	-rm -f gnu/gcj/runtime/$(am__dirstamp)
+	-rm -f gnu/gcj/tools/gcj_dbtool/$(DEPDIR)/$(am__dirstamp)
+	-rm -f gnu/gcj/tools/gcj_dbtool/$(am__dirstamp)
+	-rm -f gnu/gcj/util/$(DEPDIR)/$(am__dirstamp)
+	-rm -f gnu/gcj/util/$(am__dirstamp)
 	-rm -f gnu/gcj/xlib/$(DEPDIR)/$(am__dirstamp)
 	-rm -f gnu/gcj/xlib/$(am__dirstamp)
 	-rm -f gnu/java/awt/$(DEPDIR)/$(am__dirstamp)
@@ -23646,7 +23439,7 @@ clean-am: clean-binPROGRAMS clean-generic clean-libtool clean-local \
 
 distclean: distclean-recursive
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-	-rm -rf ./$(DEPDIR) gnu/awt/$(DEPDIR) gnu/awt/j2d/$(DEPDIR) gnu/awt/xlib/$(DEPDIR) gnu/classpath/$(DEPDIR) gnu/gcj/$(DEPDIR) gnu/gcj/convert/$(DEPDIR) gnu/gcj/io/$(DEPDIR) gnu/gcj/runtime/$(DEPDIR) gnu/gcj/xlib/$(DEPDIR) gnu/java/awt/$(DEPDIR) gnu/java/awt/image/$(DEPDIR) gnu/java/awt/peer/$(DEPDIR) gnu/java/awt/peer/gtk/$(DEPDIR) gnu/java/beans/$(DEPDIR) gnu/java/beans/editors/$(DEPDIR) gnu/java/beans/info/$(DEPDIR) gnu/java/io/$(DEPDIR) gnu/java/lang/$(DEPDIR) gnu/java/lang/reflect/$(DEPDIR) gnu/java/locale/$(DEPDIR) gnu/java/math/$(DEPDIR) gnu/java/net/$(DEPDIR) gnu/java/net/protocol/core/$(DEPDIR) gnu/java/net/protocol/file/$(DEPDIR) gnu/java/net/protocol/gcjlib/$(DEPDIR) gnu/java/net/protocol/http/$(DEPDIR) gnu/java/net/protocol/jar/$(DEPDIR) gnu/java/nio/$(DEPDIR) gnu/java/nio/channels/$(DEPDIR) gnu/java/nio/charset/$(DEPDIR) gnu/java/rmi/$(DEPDIR) gnu/java/rmi/dgc/$(DEPDIR) gnu/java/rmi/registry/$(DEPDIR) gnu/java/rmi/rmic/$(DEPDIR) gnu/java/rmi/server/$(DEPDIR) gnu/java/security/$(DEPDIR) gnu/java/security/action/$(DEPDIR) gnu/java/security/der/$(DEPDIR) gnu/java/security/provider/$(DEPDIR) gnu/java/security/util/$(DEPDIR) gnu/java/security/x509/$(DEPDIR) gnu/java/security/x509/ext/$(DEPDIR) gnu/java/text/$(DEPDIR) gnu/java/util/$(DEPDIR) gnu/java/util/prefs/$(DEPDIR) gnu/regexp/$(DEPDIR) java/applet/$(DEPDIR) java/awt/$(DEPDIR) java/awt/color/$(DEPDIR) java/awt/datatransfer/$(DEPDIR) java/awt/dnd/$(DEPDIR) java/awt/dnd/peer/$(DEPDIR) java/awt/event/$(DEPDIR) java/awt/font/$(DEPDIR) java/awt/geom/$(DEPDIR) java/awt/im/$(DEPDIR) java/awt/im/spi/$(DEPDIR) java/awt/image/$(DEPDIR) java/awt/image/renderable/$(DEPDIR) java/awt/peer/$(DEPDIR) java/awt/print/$(DEPDIR) java/beans/$(DEPDIR) java/beans/beancontext/$(DEPDIR) java/io/$(DEPDIR) java/lang/$(DEPDIR) java/lang/ref/$(DEPDIR) java/lang/reflect/$(DEPDIR) java/math/$(DEPDIR) java/net/$(DEPDIR) java/nio/$(DEPDIR) java/nio/channels/$(DEPDIR) java/nio/channels/spi/$(DEPDIR) java/nio/charset/$(DEPDIR) java/nio/charset/spi/$(DEPDIR) java/rmi/$(DEPDIR) java/rmi/activation/$(DEPDIR) java/rmi/dgc/$(DEPDIR) java/rmi/registry/$(DEPDIR) java/rmi/server/$(DEPDIR) java/security/$(DEPDIR) java/security/acl/$(DEPDIR) java/security/cert/$(DEPDIR) java/security/interfaces/$(DEPDIR) java/security/spec/$(DEPDIR) java/sql/$(DEPDIR) java/text/$(DEPDIR) java/util/$(DEPDIR) java/util/jar/$(DEPDIR) java/util/logging/$(DEPDIR) java/util/prefs/$(DEPDIR) java/util/regex/$(DEPDIR) java/util/zip/$(DEPDIR) javax/accessibility/$(DEPDIR) javax/crypto/$(DEPDIR) javax/crypto/interfaces/$(DEPDIR) javax/crypto/spec/$(DEPDIR) javax/imageio/$(DEPDIR) javax/imageio/event/$(DEPDIR) javax/imageio/metadata/$(DEPDIR) javax/imageio/spi/$(DEPDIR) javax/imageio/stream/$(DEPDIR) javax/naming/$(DEPDIR) javax/naming/directory/$(DEPDIR) javax/naming/event/$(DEPDIR) javax/naming/ldap/$(DEPDIR) javax/naming/spi/$(DEPDIR) javax/net/$(DEPDIR) javax/net/ssl/$(DEPDIR) javax/print/$(DEPDIR) javax/print/attribute/$(DEPDIR) javax/print/attribute/standard/$(DEPDIR) javax/print/event/$(DEPDIR) javax/security/auth/$(DEPDIR) javax/security/auth/callback/$(DEPDIR) javax/security/auth/login/$(DEPDIR) javax/security/auth/spi/$(DEPDIR) javax/security/auth/x500/$(DEPDIR) javax/security/cert/$(DEPDIR) javax/security/sasl/$(DEPDIR) javax/sql/$(DEPDIR) javax/swing/$(DEPDIR) javax/swing/border/$(DEPDIR) javax/swing/colorchooser/$(DEPDIR) javax/swing/event/$(DEPDIR) javax/swing/filechooser/$(DEPDIR) javax/swing/plaf/$(DEPDIR) javax/swing/plaf/basic/$(DEPDIR) javax/swing/plaf/metal/$(DEPDIR) javax/swing/table/$(DEPDIR) javax/swing/text/$(DEPDIR) javax/swing/text/html/$(DEPDIR) javax/swing/text/html/parser/$(DEPDIR) javax/swing/tree/$(DEPDIR) javax/swing/undo/$(DEPDIR) javax/transaction/$(DEPDIR) javax/transaction/xa/$(DEPDIR) jni/classpath/$(DEPDIR) jni/gtk-peer/$(DEPDIR) org/ietf/jgss/$(DEPDIR) org/w3c/dom/$(DEPDIR) org/w3c/dom/ranges/$(DEPDIR) org/w3c/dom/traversal/$(DEPDIR) org/xml/sax/$(DEPDIR) org/xml/sax/ext/$(DEPDIR) org/xml/sax/helpers/$(DEPDIR) sysdep/$(DEPDIR)
+	-rm -rf ./$(DEPDIR) gnu/awt/$(DEPDIR) gnu/awt/j2d/$(DEPDIR) gnu/awt/xlib/$(DEPDIR) gnu/classpath/$(DEPDIR) gnu/gcj/$(DEPDIR) gnu/gcj/convert/$(DEPDIR) gnu/gcj/io/$(DEPDIR) gnu/gcj/runtime/$(DEPDIR) gnu/gcj/tools/gcj_dbtool/$(DEPDIR) gnu/gcj/util/$(DEPDIR) gnu/gcj/xlib/$(DEPDIR) gnu/java/awt/$(DEPDIR) gnu/java/awt/image/$(DEPDIR) gnu/java/awt/peer/$(DEPDIR) gnu/java/awt/peer/gtk/$(DEPDIR) gnu/java/beans/$(DEPDIR) gnu/java/beans/editors/$(DEPDIR) gnu/java/beans/info/$(DEPDIR) gnu/java/io/$(DEPDIR) gnu/java/lang/$(DEPDIR) gnu/java/lang/reflect/$(DEPDIR) gnu/java/locale/$(DEPDIR) gnu/java/math/$(DEPDIR) gnu/java/net/$(DEPDIR) gnu/java/net/protocol/core/$(DEPDIR) gnu/java/net/protocol/file/$(DEPDIR) gnu/java/net/protocol/gcjlib/$(DEPDIR) gnu/java/net/protocol/http/$(DEPDIR) gnu/java/net/protocol/jar/$(DEPDIR) gnu/java/nio/$(DEPDIR) gnu/java/nio/channels/$(DEPDIR) gnu/java/nio/charset/$(DEPDIR) gnu/java/rmi/$(DEPDIR) gnu/java/rmi/dgc/$(DEPDIR) gnu/java/rmi/registry/$(DEPDIR) gnu/java/rmi/rmic/$(DEPDIR) gnu/java/rmi/server/$(DEPDIR) gnu/java/security/$(DEPDIR) gnu/java/security/action/$(DEPDIR) gnu/java/security/der/$(DEPDIR) gnu/java/security/provider/$(DEPDIR) gnu/java/security/util/$(DEPDIR) gnu/java/security/x509/$(DEPDIR) gnu/java/security/x509/ext/$(DEPDIR) gnu/java/text/$(DEPDIR) gnu/java/util/$(DEPDIR) gnu/java/util/prefs/$(DEPDIR) gnu/regexp/$(DEPDIR) java/applet/$(DEPDIR) java/awt/$(DEPDIR) java/awt/color/$(DEPDIR) java/awt/datatransfer/$(DEPDIR) java/awt/dnd/$(DEPDIR) java/awt/dnd/peer/$(DEPDIR) java/awt/event/$(DEPDIR) java/awt/font/$(DEPDIR) java/awt/geom/$(DEPDIR) java/awt/im/$(DEPDIR) java/awt/im/spi/$(DEPDIR) java/awt/image/$(DEPDIR) java/awt/image/renderable/$(DEPDIR) java/awt/peer/$(DEPDIR) java/awt/print/$(DEPDIR) java/beans/$(DEPDIR) java/beans/beancontext/$(DEPDIR) java/io/$(DEPDIR) java/lang/$(DEPDIR) java/lang/ref/$(DEPDIR) java/lang/reflect/$(DEPDIR) java/math/$(DEPDIR) java/net/$(DEPDIR) java/nio/$(DEPDIR) java/nio/channels/$(DEPDIR) java/nio/channels/spi/$(DEPDIR) java/nio/charset/$(DEPDIR) java/nio/charset/spi/$(DEPDIR) java/rmi/$(DEPDIR) java/rmi/activation/$(DEPDIR) java/rmi/dgc/$(DEPDIR) java/rmi/registry/$(DEPDIR) java/rmi/server/$(DEPDIR) java/security/$(DEPDIR) java/security/acl/$(DEPDIR) java/security/cert/$(DEPDIR) java/security/interfaces/$(DEPDIR) java/security/spec/$(DEPDIR) java/sql/$(DEPDIR) java/text/$(DEPDIR) java/util/$(DEPDIR) java/util/jar/$(DEPDIR) java/util/logging/$(DEPDIR) java/util/prefs/$(DEPDIR) java/util/regex/$(DEPDIR) java/util/zip/$(DEPDIR) javax/accessibility/$(DEPDIR) javax/crypto/$(DEPDIR) javax/crypto/interfaces/$(DEPDIR) javax/crypto/spec/$(DEPDIR) javax/imageio/$(DEPDIR) javax/imageio/event/$(DEPDIR) javax/imageio/metadata/$(DEPDIR) javax/imageio/spi/$(DEPDIR) javax/imageio/stream/$(DEPDIR) javax/naming/$(DEPDIR) javax/naming/directory/$(DEPDIR) javax/naming/event/$(DEPDIR) javax/naming/ldap/$(DEPDIR) javax/naming/spi/$(DEPDIR) javax/net/$(DEPDIR) javax/net/ssl/$(DEPDIR) javax/print/$(DEPDIR) javax/print/attribute/$(DEPDIR) javax/print/attribute/standard/$(DEPDIR) javax/print/event/$(DEPDIR) javax/security/auth/$(DEPDIR) javax/security/auth/callback/$(DEPDIR) javax/security/auth/login/$(DEPDIR) javax/security/auth/spi/$(DEPDIR) javax/security/auth/x500/$(DEPDIR) javax/security/cert/$(DEPDIR) javax/security/sasl/$(DEPDIR) javax/sql/$(DEPDIR) javax/swing/$(DEPDIR) javax/swing/border/$(DEPDIR) javax/swing/colorchooser/$(DEPDIR) javax/swing/event/$(DEPDIR) javax/swing/filechooser/$(DEPDIR) javax/swing/plaf/$(DEPDIR) javax/swing/plaf/basic/$(DEPDIR) javax/swing/plaf/metal/$(DEPDIR) javax/swing/table/$(DEPDIR) javax/swing/text/$(DEPDIR) javax/swing/text/html/$(DEPDIR) javax/swing/text/html/parser/$(DEPDIR) javax/swing/tree/$(DEPDIR) javax/swing/undo/$(DEPDIR) javax/transaction/$(DEPDIR) javax/transaction/xa/$(DEPDIR) jni/classpath/$(DEPDIR) jni/gtk-peer/$(DEPDIR) org/ietf/jgss/$(DEPDIR) org/w3c/dom/$(DEPDIR) org/w3c/dom/ranges/$(DEPDIR) org/w3c/dom/traversal/$(DEPDIR) org/xml/sax/$(DEPDIR) org/xml/sax/ext/$(DEPDIR) org/xml/sax/helpers/$(DEPDIR) sysdep/$(DEPDIR)
 	-rm -f Makefile
 distclean-am: clean-am distclean-compile distclean-generic \
 	distclean-libtool distclean-local distclean-tags
@@ -23676,7 +23469,7 @@ installcheck-am:
 maintainer-clean: maintainer-clean-recursive
 	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
 	-rm -rf $(top_srcdir)/autom4te.cache
-	-rm -rf ./$(DEPDIR) gnu/awt/$(DEPDIR) gnu/awt/j2d/$(DEPDIR) gnu/awt/xlib/$(DEPDIR) gnu/classpath/$(DEPDIR) gnu/gcj/$(DEPDIR) gnu/gcj/convert/$(DEPDIR) gnu/gcj/io/$(DEPDIR) gnu/gcj/runtime/$(DEPDIR) gnu/gcj/xlib/$(DEPDIR) gnu/java/awt/$(DEPDIR) gnu/java/awt/image/$(DEPDIR) gnu/java/awt/peer/$(DEPDIR) gnu/java/awt/peer/gtk/$(DEPDIR) gnu/java/beans/$(DEPDIR) gnu/java/beans/editors/$(DEPDIR) gnu/java/beans/info/$(DEPDIR) gnu/java/io/$(DEPDIR) gnu/java/lang/$(DEPDIR) gnu/java/lang/reflect/$(DEPDIR) gnu/java/locale/$(DEPDIR) gnu/java/math/$(DEPDIR) gnu/java/net/$(DEPDIR) gnu/java/net/protocol/core/$(DEPDIR) gnu/java/net/protocol/file/$(DEPDIR) gnu/java/net/protocol/gcjlib/$(DEPDIR) gnu/java/net/protocol/http/$(DEPDIR) gnu/java/net/protocol/jar/$(DEPDIR) gnu/java/nio/$(DEPDIR) gnu/java/nio/channels/$(DEPDIR) gnu/java/nio/charset/$(DEPDIR) gnu/java/rmi/$(DEPDIR) gnu/java/rmi/dgc/$(DEPDIR) gnu/java/rmi/registry/$(DEPDIR) gnu/java/rmi/rmic/$(DEPDIR) gnu/java/rmi/server/$(DEPDIR) gnu/java/security/$(DEPDIR) gnu/java/security/action/$(DEPDIR) gnu/java/security/der/$(DEPDIR) gnu/java/security/provider/$(DEPDIR) gnu/java/security/util/$(DEPDIR) gnu/java/security/x509/$(DEPDIR) gnu/java/security/x509/ext/$(DEPDIR) gnu/java/text/$(DEPDIR) gnu/java/util/$(DEPDIR) gnu/java/util/prefs/$(DEPDIR) gnu/regexp/$(DEPDIR) java/applet/$(DEPDIR) java/awt/$(DEPDIR) java/awt/color/$(DEPDIR) java/awt/datatransfer/$(DEPDIR) java/awt/dnd/$(DEPDIR) java/awt/dnd/peer/$(DEPDIR) java/awt/event/$(DEPDIR) java/awt/font/$(DEPDIR) java/awt/geom/$(DEPDIR) java/awt/im/$(DEPDIR) java/awt/im/spi/$(DEPDIR) java/awt/image/$(DEPDIR) java/awt/image/renderable/$(DEPDIR) java/awt/peer/$(DEPDIR) java/awt/print/$(DEPDIR) java/beans/$(DEPDIR) java/beans/beancontext/$(DEPDIR) java/io/$(DEPDIR) java/lang/$(DEPDIR) java/lang/ref/$(DEPDIR) java/lang/reflect/$(DEPDIR) java/math/$(DEPDIR) java/net/$(DEPDIR) java/nio/$(DEPDIR) java/nio/channels/$(DEPDIR) java/nio/channels/spi/$(DEPDIR) java/nio/charset/$(DEPDIR) java/nio/charset/spi/$(DEPDIR) java/rmi/$(DEPDIR) java/rmi/activation/$(DEPDIR) java/rmi/dgc/$(DEPDIR) java/rmi/registry/$(DEPDIR) java/rmi/server/$(DEPDIR) java/security/$(DEPDIR) java/security/acl/$(DEPDIR) java/security/cert/$(DEPDIR) java/security/interfaces/$(DEPDIR) java/security/spec/$(DEPDIR) java/sql/$(DEPDIR) java/text/$(DEPDIR) java/util/$(DEPDIR) java/util/jar/$(DEPDIR) java/util/logging/$(DEPDIR) java/util/prefs/$(DEPDIR) java/util/regex/$(DEPDIR) java/util/zip/$(DEPDIR) javax/accessibility/$(DEPDIR) javax/crypto/$(DEPDIR) javax/crypto/interfaces/$(DEPDIR) javax/crypto/spec/$(DEPDIR) javax/imageio/$(DEPDIR) javax/imageio/event/$(DEPDIR) javax/imageio/metadata/$(DEPDIR) javax/imageio/spi/$(DEPDIR) javax/imageio/stream/$(DEPDIR) javax/naming/$(DEPDIR) javax/naming/directory/$(DEPDIR) javax/naming/event/$(DEPDIR) javax/naming/ldap/$(DEPDIR) javax/naming/spi/$(DEPDIR) javax/net/$(DEPDIR) javax/net/ssl/$(DEPDIR) javax/print/$(DEPDIR) javax/print/attribute/$(DEPDIR) javax/print/attribute/standard/$(DEPDIR) javax/print/event/$(DEPDIR) javax/security/auth/$(DEPDIR) javax/security/auth/callback/$(DEPDIR) javax/security/auth/login/$(DEPDIR) javax/security/auth/spi/$(DEPDIR) javax/security/auth/x500/$(DEPDIR) javax/security/cert/$(DEPDIR) javax/security/sasl/$(DEPDIR) javax/sql/$(DEPDIR) javax/swing/$(DEPDIR) javax/swing/border/$(DEPDIR) javax/swing/colorchooser/$(DEPDIR) javax/swing/event/$(DEPDIR) javax/swing/filechooser/$(DEPDIR) javax/swing/plaf/$(DEPDIR) javax/swing/plaf/basic/$(DEPDIR) javax/swing/plaf/metal/$(DEPDIR) javax/swing/table/$(DEPDIR) javax/swing/text/$(DEPDIR) javax/swing/text/html/$(DEPDIR) javax/swing/text/html/parser/$(DEPDIR) javax/swing/tree/$(DEPDIR) javax/swing/undo/$(DEPDIR) javax/transaction/$(DEPDIR) javax/transaction/xa/$(DEPDIR) jni/classpath/$(DEPDIR) jni/gtk-peer/$(DEPDIR) org/ietf/jgss/$(DEPDIR) org/w3c/dom/$(DEPDIR) org/w3c/dom/ranges/$(DEPDIR) org/w3c/dom/traversal/$(DEPDIR) org/xml/sax/$(DEPDIR) org/xml/sax/ext/$(DEPDIR) org/xml/sax/helpers/$(DEPDIR) sysdep/$(DEPDIR)
+	-rm -rf ./$(DEPDIR) gnu/awt/$(DEPDIR) gnu/awt/j2d/$(DEPDIR) gnu/awt/xlib/$(DEPDIR) gnu/classpath/$(DEPDIR) gnu/gcj/$(DEPDIR) gnu/gcj/convert/$(DEPDIR) gnu/gcj/io/$(DEPDIR) gnu/gcj/runtime/$(DEPDIR) gnu/gcj/tools/gcj_dbtool/$(DEPDIR) gnu/gcj/util/$(DEPDIR) gnu/gcj/xlib/$(DEPDIR) gnu/java/awt/$(DEPDIR) gnu/java/awt/image/$(DEPDIR) gnu/java/awt/peer/$(DEPDIR) gnu/java/awt/peer/gtk/$(DEPDIR) gnu/java/beans/$(DEPDIR) gnu/java/beans/editors/$(DEPDIR) gnu/java/beans/info/$(DEPDIR) gnu/java/io/$(DEPDIR) gnu/java/lang/$(DEPDIR) gnu/java/lang/reflect/$(DEPDIR) gnu/java/locale/$(DEPDIR) gnu/java/math/$(DEPDIR) gnu/java/net/$(DEPDIR) gnu/java/net/protocol/core/$(DEPDIR) gnu/java/net/protocol/file/$(DEPDIR) gnu/java/net/protocol/gcjlib/$(DEPDIR) gnu/java/net/protocol/http/$(DEPDIR) gnu/java/net/protocol/jar/$(DEPDIR) gnu/java/nio/$(DEPDIR) gnu/java/nio/channels/$(DEPDIR) gnu/java/nio/charset/$(DEPDIR) gnu/java/rmi/$(DEPDIR) gnu/java/rmi/dgc/$(DEPDIR) gnu/java/rmi/registry/$(DEPDIR) gnu/java/rmi/rmic/$(DEPDIR) gnu/java/rmi/server/$(DEPDIR) gnu/java/security/$(DEPDIR) gnu/java/security/action/$(DEPDIR) gnu/java/security/der/$(DEPDIR) gnu/java/security/provider/$(DEPDIR) gnu/java/security/util/$(DEPDIR) gnu/java/security/x509/$(DEPDIR) gnu/java/security/x509/ext/$(DEPDIR) gnu/java/text/$(DEPDIR) gnu/java/util/$(DEPDIR) gnu/java/util/prefs/$(DEPDIR) gnu/regexp/$(DEPDIR) java/applet/$(DEPDIR) java/awt/$(DEPDIR) java/awt/color/$(DEPDIR) java/awt/datatransfer/$(DEPDIR) java/awt/dnd/$(DEPDIR) java/awt/dnd/peer/$(DEPDIR) java/awt/event/$(DEPDIR) java/awt/font/$(DEPDIR) java/awt/geom/$(DEPDIR) java/awt/im/$(DEPDIR) java/awt/im/spi/$(DEPDIR) java/awt/image/$(DEPDIR) java/awt/image/renderable/$(DEPDIR) java/awt/peer/$(DEPDIR) java/awt/print/$(DEPDIR) java/beans/$(DEPDIR) java/beans/beancontext/$(DEPDIR) java/io/$(DEPDIR) java/lang/$(DEPDIR) java/lang/ref/$(DEPDIR) java/lang/reflect/$(DEPDIR) java/math/$(DEPDIR) java/net/$(DEPDIR) java/nio/$(DEPDIR) java/nio/channels/$(DEPDIR) java/nio/channels/spi/$(DEPDIR) java/nio/charset/$(DEPDIR) java/nio/charset/spi/$(DEPDIR) java/rmi/$(DEPDIR) java/rmi/activation/$(DEPDIR) java/rmi/dgc/$(DEPDIR) java/rmi/registry/$(DEPDIR) java/rmi/server/$(DEPDIR) java/security/$(DEPDIR) java/security/acl/$(DEPDIR) java/security/cert/$(DEPDIR) java/security/interfaces/$(DEPDIR) java/security/spec/$(DEPDIR) java/sql/$(DEPDIR) java/text/$(DEPDIR) java/util/$(DEPDIR) java/util/jar/$(DEPDIR) java/util/logging/$(DEPDIR) java/util/prefs/$(DEPDIR) java/util/regex/$(DEPDIR) java/util/zip/$(DEPDIR) javax/accessibility/$(DEPDIR) javax/crypto/$(DEPDIR) javax/crypto/interfaces/$(DEPDIR) javax/crypto/spec/$(DEPDIR) javax/imageio/$(DEPDIR) javax/imageio/event/$(DEPDIR) javax/imageio/metadata/$(DEPDIR) javax/imageio/spi/$(DEPDIR) javax/imageio/stream/$(DEPDIR) javax/naming/$(DEPDIR) javax/naming/directory/$(DEPDIR) javax/naming/event/$(DEPDIR) javax/naming/ldap/$(DEPDIR) javax/naming/spi/$(DEPDIR) javax/net/$(DEPDIR) javax/net/ssl/$(DEPDIR) javax/print/$(DEPDIR) javax/print/attribute/$(DEPDIR) javax/print/attribute/standard/$(DEPDIR) javax/print/event/$(DEPDIR) javax/security/auth/$(DEPDIR) javax/security/auth/callback/$(DEPDIR) javax/security/auth/login/$(DEPDIR) javax/security/auth/spi/$(DEPDIR) javax/security/auth/x500/$(DEPDIR) javax/security/cert/$(DEPDIR) javax/security/sasl/$(DEPDIR) javax/sql/$(DEPDIR) javax/swing/$(DEPDIR) javax/swing/border/$(DEPDIR) javax/swing/colorchooser/$(DEPDIR) javax/swing/event/$(DEPDIR) javax/swing/filechooser/$(DEPDIR) javax/swing/plaf/$(DEPDIR) javax/swing/plaf/basic/$(DEPDIR) javax/swing/plaf/metal/$(DEPDIR) javax/swing/table/$(DEPDIR) javax/swing/text/$(DEPDIR) javax/swing/text/html/$(DEPDIR) javax/swing/text/html/parser/$(DEPDIR) javax/swing/tree/$(DEPDIR) javax/swing/undo/$(DEPDIR) javax/transaction/$(DEPDIR) javax/transaction/xa/$(DEPDIR) jni/classpath/$(DEPDIR) jni/gtk-peer/$(DEPDIR) org/ietf/jgss/$(DEPDIR) org/w3c/dom/$(DEPDIR) org/w3c/dom/ranges/$(DEPDIR) org/w3c/dom/traversal/$(DEPDIR) org/xml/sax/$(DEPDIR) org/xml/sax/ext/$(DEPDIR) org/xml/sax/helpers/$(DEPDIR) sysdep/$(DEPDIR)
 	-rm -f Makefile
 maintainer-clean-am: distclean-am maintainer-clean-generic
 
diff --git a/libjava/aclocal.m4 b/libjava/aclocal.m4
index 3afc98f67d26..ffc535707c84 100644
--- a/libjava/aclocal.m4
+++ b/libjava/aclocal.m4
@@ -417,7 +417,7 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
 # 02111-1307, USA.
 
 AC_DEFUN([AM_PROG_GCJ],[
-AC_CHECK_PROGS(GCJ, [gcj gcj-3.2 gcj-3.1 gcj-3.0 gcj-2.95], gcj)
+AC_CHECK_PROGS(GCJ, gcj, gcj)
 test -z "$GCJ" && AC_MSG_ERROR([no acceptable gcj found in \$PATH])
 if test "x${GCJFLAGS-unset}" = xunset; then
    GCJFLAGS="-g -O2"
diff --git a/libjava/boehm.cc b/libjava/boehm.cc
index c2a93a57b047..d2902326e816 100644
--- a/libjava/boehm.cc
+++ b/libjava/boehm.cc
@@ -1,6 +1,7 @@
 // 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.
 
@@ -10,6 +11,21 @@ details.  */
 
 #include <config.h>
 
+#include <stdio.h>
+#include <limits.h>
+
+#include <jvm.h>
+#include <gcj/cni.h>
+
+#include <java/lang/Class.h>
+#include <java/lang/reflect/Modifier.h>
+#include <java-interp.h>
+
+// More nastiness: the GC wants to define TRUE and FALSE.  We don't
+// need the Java definitions (themselves a hack), so we undefine them.
+#undef TRUE
+#undef FALSE
+
 extern "C"
 {
 #include <gc_config.h>
@@ -27,26 +43,20 @@ extern "C"
 # define GC_REDIRECT_TO_LOCAL
 # include <gc_local_alloc.h>
 #endif
-};
 
-#include <stdio.h>
-#include <limits.h>
-
-#include <jvm.h>
-#include <gcj/cni.h>
-
-#include <java/lang/Class.h>
-#include <java/lang/reflect/Modifier.h>
-#include <java-interp.h>
+  // From boehm's misc.c 
+  void GC_enable();
+  void GC_disable();
+};
 
-#define MAYBE_MARK(Obj, Top, Limit, Source, Exit)  \
-	Top=GC_MARK_AND_PUSH((GC_PTR)Obj, Top, Limit, (GC_PTR *)Source)
+#define MAYBE_MARK(Obj, Top, Limit, Source)  \
+	Top=GC_MARK_AND_PUSH((GC_PTR) Obj, Top, Limit, (GC_PTR *) Source)
 
 // `kind' index used when allocating Java arrays.
 static int array_kind_x;
 
 // Freelist used for Java arrays.
-static void * *array_free_list;
+static void **array_free_list;
 
 
 
@@ -54,7 +64,7 @@ static void * *array_free_list;
 // object.  We use `void *' arguments and return, and not what the
 // Boehm GC wants, to avoid pollution in our headers.
 void *
-_Jv_MarkObj (void *addr, void *msp, void *msl, void * env)
+_Jv_MarkObj (void *addr, void *msp, void *msl, void *env)
 {
   struct GC_ms_entry *mark_stack_ptr = (struct GC_ms_entry *)msp;
   struct GC_ms_entry *mark_stack_limit = (struct GC_ms_entry *)msl;
@@ -78,11 +88,11 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env)
 # ifndef JV_HASH_SYNCHRONIZATION
     // Every object has a sync_info pointer.
     p = (GC_PTR) obj->sync_info;
-    MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o1label);
+    MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj);
 # endif
   // Mark the object's class.
   p = (GC_PTR) klass;
-  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj, o2label);
+  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj);
 
   if (__builtin_expect (klass == &java::lang::Class::class$, false))
     {
@@ -101,33 +111,35 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env)
       jclass c = (jclass) addr;
 
       p = (GC_PTR) c->name;
-      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c3label);
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
       p = (GC_PTR) c->superclass;
-      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c4label);
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
       for (int i = 0; i < c->constants.size; ++i)
 	{
 	  /* FIXME: We could make this more precise by using the tags -KKT */
 	  p = (GC_PTR) c->constants.data[i].p;
-	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5label);
+	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
 	}
 
 #ifdef INTERPRETER
       if (_Jv_IsInterpretedClass (c))
 	{
 	  p = (GC_PTR) c->constants.tags;
-	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5alabel);
+	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
 	  p = (GC_PTR) c->constants.data;
-	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5blabel);
-	  p = (GC_PTR) c->vtable;
-	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c5clabel);
+	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
 	}
 #endif
 
+      // The vtable might be allocated even for compiled code.
+      p = (GC_PTR) c->vtable;
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
+
       // 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.
       p = (GC_PTR) c->methods;
-      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c6label);
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
 
       // The vtable might have been set, but the rest of the class
       // could still be uninitialized.  If this is the case, then
@@ -143,34 +155,35 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env)
 	  for (int i = 0; i < c->method_count; ++i)
 	    {
 	      p = (GC_PTR) c->methods[i].name;
-	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
-			     cm1label);
+	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
 	      p = (GC_PTR) c->methods[i].signature;
-	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
-			     cm2label);
+	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
+
+	      // Note that we don't have to mark each individual throw
+	      // separately, as these are stored in the constant pool.
+	      p = (GC_PTR) c->methods[i].throws;
+	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
 	    }
 	}
 
       // Mark all the fields.
       p = (GC_PTR) c->fields;
-      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8label);
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
       for (int i = 0; i < c->field_count; ++i)
 	{
 	  _Jv_Field* field = &c->fields[i];
 
-#ifndef COMPACT_FIELDS
 	  p = (GC_PTR) field->name;
-	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8alabel);
-#endif
+	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
 	  p = (GC_PTR) field->type;
-	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8blabel);
+	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
 
 	  // For the interpreter, we also need to mark the memory
 	  // containing static members
 	  if ((field->flags & java::lang::reflect::Modifier::STATIC))
 	    {
 	      p = (GC_PTR) field->u.addr;
-	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c8clabel);
+	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
 
 	      // also, if the static member is a reference,
 	      // mark also the value pointed to.  We check for isResolved
@@ -180,69 +193,110 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env)
 		{
 		  jobject val = *(jobject*) field->u.addr;
 		  p = (GC_PTR) val;
-		  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit,
-			      c, c8elabel);
+		  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
 		}
 	    }
 	}
 
       p = (GC_PTR) c->vtable;
-      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, c9label);
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
       p = (GC_PTR) c->interfaces;
-      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cAlabel);
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
       for (int i = 0; i < c->interface_count; ++i)
 	{
 	  p = (GC_PTR) c->interfaces[i];
-	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cClabel);
+	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
 	}
       p = (GC_PTR) c->loader;
-      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cBlabel);
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
+
+      // The dispatch tables can be allocated at runtime.
+      p = (GC_PTR) c->ancestors;
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
+      if (c->idt)
+	{
+	  p = (GC_PTR) c->idt;
+	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
+
+	  if (c->isInterface())
+	    {
+	      p = (GC_PTR) c->idt->iface.ioffsets;
+	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c->idt);
+	    }
+	  else if (! c->isPrimitive())
+	    {
+	      // This field is only valid for ordinary classes.
+	      p = (GC_PTR) c->idt->cls.itable;
+	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c->idt);
+	    }
+	}
+
       p = (GC_PTR) c->arrayclass;
-      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cDlabel);
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
       p = (GC_PTR) c->protectionDomain;
-      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cPlabel);
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
       p = (GC_PTR) c->hack_signers;
-      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cSlabel);
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
       p = (GC_PTR) c->aux_info;
-      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c, cTlabel);
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
 
 #ifdef INTERPRETER
-      if (_Jv_IsInterpretedClass (c))
+      if (_Jv_IsInterpretedClass (c) && c->aux_info)
 	{
 	  _Jv_InterpClass* ic = (_Jv_InterpClass*) c->aux_info;
 
 	  p = (GC_PTR) ic->interpreted_methods;
-	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, cElabel);
+	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic);
 
 	  for (int i = 0; i < c->method_count; i++)
 	    {
+	      // The interpreter installs a heap-allocated trampoline
+	      // here, so we'll mark it.
+	      p = (GC_PTR) c->methods[i].ncode;
+	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c);
+
+	      using namespace java::lang::reflect;
+
+	      // Mark the direct-threaded code.  Note a subtlety here:
+	      // when we add Miranda methods to a class, we don't
+	      // resize its interpreted_methods array.  If we try to
+	      // reference one of these methods, we may crash.
+	      // However, we know these are all abstract, and we know
+	      // that abstract methods have nothing useful in this
+	      // array.  So, we skip all abstract methods to avoid the
+	      // problem.  FIXME: this is pretty obscure, it may be
+	      // better to add a methods to the execution engine and
+	      // resize the array.
+	      if ((c->methods[i].accflags & Modifier::ABSTRACT) != 0)
+		continue;
+
 	      p = (GC_PTR) ic->interpreted_methods[i];
-	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, \
-			  cFlabel);
+	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic);
 
-	      // Mark the direct-threaded code.
-	      if ((c->methods[i].accflags
-		   & java::lang::reflect::Modifier::NATIVE) == 0)
+	      if ((c->methods[i].accflags & Modifier::NATIVE) != 0)
+		{
+		  _Jv_JNIMethod *jm
+		    = (_Jv_JNIMethod *) ic->interpreted_methods[i];
+		  if (jm)
+		    {
+		      p = (GC_PTR) jm->jni_arg_types;
+		      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, p);
+		    }
+		}
+	      else
 		{
 		  _Jv_InterpMethod *im
 		    = (_Jv_InterpMethod *) ic->interpreted_methods[i];
 		  if (im)
 		    {
 		      p = (GC_PTR) im->prepared;
-		      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, \
-				  cFlabel);
+		      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic);
 		    }
 		}
-
-	      // The interpreter installs a heap-allocated trampoline
-	      // here, so we'll mark it.
-	      p = (GC_PTR) c->methods[i].ncode;
-	      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, c,
-			  cm3label);
 	    }
 
 	  p = (GC_PTR) ic->field_initializers;
-	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic, cGlabel);
+	  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, ic);
 	  
 	}
 #endif
@@ -269,8 +323,7 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env)
 		{
 		  jobject val = JvGetObjectField (obj, field);
 		  p = (GC_PTR) val;
-		  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit,
-			      obj, elabel);
+		  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, obj);
 		}
 	      field = field->getNextField ();
 	    }
@@ -285,7 +338,7 @@ _Jv_MarkObj (void *addr, void *msp, void *msl, void * env)
 // array (of objects).  We use `void *' arguments and return, and not
 // what the Boehm GC wants, to avoid pollution in our headers.
 void *
-_Jv_MarkArray (void *addr, void *msp, void *msl, void * env)
+_Jv_MarkArray (void *addr, void *msp, void *msl, void *env)
 {
   struct GC_ms_entry *mark_stack_ptr = (struct GC_ms_entry *)msp;
   struct GC_ms_entry *mark_stack_limit = (struct GC_ms_entry *)msl;
@@ -306,17 +359,17 @@ _Jv_MarkArray (void *addr, void *msp, void *msl, void * env)
 # ifndef JV_HASH_SYNCHRONIZATION
     // Every object has a sync_info pointer.
     p = (GC_PTR) array->sync_info;
-    MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array, e1label);
+    MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array);
 # endif
   // Mark the object's class.
   p = (GC_PTR) klass;
-  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, &(dt -> clas), o2label);
+  MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, &(dt -> clas));
 
   for (int i = 0; i < JvGetArrayLength (array); ++i)
     {
       jobject obj = elements (array)[i];
       p = (GC_PTR) obj;
-      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array, e2label);
+      MAYBE_MARK (p, mark_stack_ptr, mark_stack_limit, array);
     }
 
   return mark_stack_ptr;
@@ -364,7 +417,7 @@ _Jv_BuildGCDescr(jclass self)
 	      // If we find a field outside the range of our bitmap,
 	      // fall back to procedure marker. The bottom 2 bits are
 	      // reserved.
-	      if (off >= (unsigned)bits_per_word - 2)
+	      if (off >= (unsigned) bits_per_word - 2)
 		return (void *) (GCJ_DEFAULT_DESCR);
 	      desc |= 1ULL << (bits_per_word - off - 1);
 	    }
@@ -514,10 +567,6 @@ _Jv_GCSetMaximumHeapSize (size_t size)
   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)
 {
@@ -585,7 +634,7 @@ _Jv_InitGC (void)
   proc = GC_new_proc((GC_mark_proc)_Jv_MarkArray);
   array_kind_x = GC_new_kind(array_free_list, GC_MAKE_PROC (proc, 0), 0, 1);
 
-  /* Arrange to have the GC print Java class names in backtraces, etc. 	*/
+  // Arrange to have the GC print Java class names in backtraces, etc.
   GC_register_describe_type_fn(GC_gcj_kind, gcj_describe_type_fn);
   GC_register_describe_type_fn(GC_gcj_debug_kind, gcj_describe_type_fn);
 }
@@ -640,7 +689,11 @@ _Jv_GCInitializeFinalizers (void (*notifier) (void))
 void
 _Jv_GCRegisterDisappearingLink (jobject *objp)
 {
-  GC_general_register_disappearing_link ((GC_PTR *) objp, (GC_PTR) *objp);
+  // This test helps to ensure that we meet a precondition of
+  // GC_general_register_disappearing_link, viz. "Obj must be a
+  // pointer to the first word of an object we allocated."
+  if (GC_base(*objp))
+    GC_general_register_disappearing_link ((GC_PTR *) objp, (GC_PTR) *objp);
 }
 
 jboolean
diff --git a/libjava/configure b/libjava/configure
index 5929c250c527..cf52939df11e 100755
--- a/libjava/configure
+++ b/libjava/configure
@@ -310,7 +310,7 @@ ac_includes_default="\
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS libgcj_basedir build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical LN_S mkinstalldirs CC ac_ct_CC EXEEXT OBJEXT CXX ac_ct_CXX CFLAGS CXXFLAGS LDFLAGS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE AS ac_ct_AS AR ac_ct_AR RANLIB ac_ct_RANLIB MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBGCJ_CFLAGS LIBGCJ_CXXFLAGS LIBGCJ_JAVAFLAGS INCLTDL LIBLTDL DIRLTDL LIBTOOL CXXCPP CPPFLAGS GCJ GCJFLAGS GCJDEPMODE am__fastdepGCJ_TRUE am__fastdepGCJ_FALSE subdirs COMPPATH TESTSUBDIR_TRUE TESTSUBDIR_FALSE ONESTEP_TRUE ONESTEP_FALSE LIBGCJDEBUG INTERPRETER LIBFFI LIBFFIINCS PLATFORM_INNER_NAT_HDRS CPP EGREP USING_WIN32_PLATFORM_TRUE USING_WIN32_PLATFORM_FALSE USING_POSIX_PLATFORM_TRUE USING_POSIX_PLATFORM_FALSE USING_ECOS_PLATFORM_TRUE USING_ECOS_PLATFORM_FALSE USING_DARWIN_CRT_TRUE USING_DARWIN_CRT_FALSE SYSTEMSPEC LIBGCJTESTSPEC ZLIBSPEC ZLIBTESTSPEC X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS TOOLKIT XLIB_AWT_TRUE XLIB_AWT_FALSE GTK_AWT_TRUE GTK_AWT_FALSE GTK_CAIRO_TRUE GTK_CAIRO_FALSE PKG_CONFIG CAIRO_CFLAGS CAIRO_LIBS PANGOFT2_CFLAGS PANGOFT2_LIBS GCLIBS GCINCS GCDEPS GCSPEC JC1GCSPEC GCTESTSPEC USING_BOEHMGC_TRUE USING_BOEHMGC_FALSE USING_NOGC_TRUE USING_NOGC_FALSE THREADLIBS THREADINCS THREADDEPS THREADSPEC THREADLDFLAGS THREADCXXFLAGS USING_POSIX_THREADS_TRUE USING_POSIX_THREADS_FALSE USING_WIN32_THREADS_TRUE USING_WIN32_THREADS_FALSE USING_NO_THREADS_TRUE USING_NO_THREADS_FALSE HASH_SYNC_SPEC USING_GCC_TRUE USING_GCC_FALSE tool_include_dir gcc_version LIBICONV LTLIBICONV GTK_CFLAGS GTK_LIBS GLIB_CFLAGS GLIB_LIBS LIBART_CFLAGS LIBART_LIBS SUPPLY_BACKTRACE_TRUE SUPPLY_BACKTRACE_FALSE GCJH ZIP CLASSPATH_SEPARATOR ac_ct_GCJ ZLIBS SYS_ZLIBS ZINCS DIVIDESPEC CHECKREFSPEC EXCEPTIONSPEC IEEESPEC NATIVE_TRUE NATIVE_FALSE NEEDS_DATA_START_TRUE NEEDS_DATA_START_FALSE GCC_UNWIND_INCLUDE toolexecdir toolexecmainlibdir toolexeclibdir GCJVERSION ALLOCA PERL BACKTRACESPEC SYSDEP_SOURCES here LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS libgcj_basedir build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os target_noncanonical LN_S mkinstalldirs CC ac_ct_CC EXEEXT OBJEXT CXX ac_ct_CXX CFLAGS CXXFLAGS LDFLAGS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE AS ac_ct_AS AR ac_ct_AR RANLIB ac_ct_RANLIB MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LIBGCJ_CFLAGS LIBGCJ_CXXFLAGS LIBGCJ_JAVAFLAGS LIBGCJ_LD_SYMBOLIC INCLTDL LIBLTDL DIRLTDL LIBTOOL CXXCPP CPPFLAGS GCJ GCJFLAGS GCJDEPMODE am__fastdepGCJ_TRUE am__fastdepGCJ_FALSE subdirs COMPPATH TESTSUBDIR_TRUE TESTSUBDIR_FALSE ONESTEP_TRUE ONESTEP_FALSE LIBGCJDEBUG INTERPRETER LIBFFI LIBFFIINCS PLATFORM_INNER_NAT_HDRS CPP EGREP USING_WIN32_PLATFORM_TRUE USING_WIN32_PLATFORM_FALSE USING_POSIX_PLATFORM_TRUE USING_POSIX_PLATFORM_FALSE USING_ECOS_PLATFORM_TRUE USING_ECOS_PLATFORM_FALSE USING_DARWIN_CRT_TRUE USING_DARWIN_CRT_FALSE SYSTEMSPEC LIBGCJTESTSPEC ZLIBSPEC ZLIBTESTSPEC X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS TOOLKIT XLIB_AWT_TRUE XLIB_AWT_FALSE GTK_AWT_TRUE GTK_AWT_FALSE GTK_CAIRO_TRUE GTK_CAIRO_FALSE PKG_CONFIG CAIRO_CFLAGS CAIRO_LIBS PANGOFT2_CFLAGS PANGOFT2_LIBS GCLIBS GCINCS GCDEPS GCSPEC JC1GCSPEC GCTESTSPEC USING_BOEHMGC_TRUE USING_BOEHMGC_FALSE USING_NOGC_TRUE USING_NOGC_FALSE THREADLIBS THREADINCS THREADDEPS THREADSPEC THREADLDFLAGS THREADCXXFLAGS USING_POSIX_THREADS_TRUE USING_POSIX_THREADS_FALSE USING_WIN32_THREADS_TRUE USING_WIN32_THREADS_FALSE USING_NO_THREADS_TRUE USING_NO_THREADS_FALSE HASH_SYNC_SPEC USING_GCC_TRUE USING_GCC_FALSE tool_include_dir gcc_version LIBICONV LTLIBICONV GTK_CFLAGS GTK_LIBS GLIB_CFLAGS GLIB_LIBS LIBART_CFLAGS LIBART_LIBS SUPPLY_BACKTRACE_TRUE SUPPLY_BACKTRACE_FALSE GCJH ZIP CLASSPATH_SEPARATOR ac_ct_GCJ ZLIBS SYS_ZLIBS ZINCS DIVIDESPEC CHECKREFSPEC EXCEPTIONSPEC IEEESPEC NATIVE_TRUE NATIVE_FALSE NEEDS_DATA_START_TRUE NEEDS_DATA_START_FALSE GCC_UNWIND_INCLUDE toolexecdir toolexecmainlibdir toolexeclibdir GCJVERSION ALLOCA PERL BACKTRACESPEC SYSDEP_SOURCES here LIBOBJS LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -3983,6 +3983,8 @@ libgcj_javaflags=
 LIBGCJ_CFLAGS="${libgcj_cflags}"
 LIBGCJ_CXXFLAGS="${libgcj_cxxflags}"
 LIBGCJ_JAVAFLAGS="${libgcj_javaflags}"
+LIBGCJ_LD_SYMBOLIC="${libgcj_ld_symbolic}"
+
 
 
 
@@ -4741,7 +4743,7 @@ test x"$pic_mode" = xno && libtool_flags="$libtool_flags --prefer-non-pic"
 case $host in
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 4744 "configure"' > conftest.$ac_ext
+  echo '#line 4746 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -5772,7 +5774,7 @@ if test "${enable_sjlj_exceptions+set}" = set; then
   :
 else
   cat > conftest.$ac_ext << EOF
-#line 5775 "configure"
+#line 5777 "configure"
 struct S { ~S(); };
 void bar();
 void foo()
@@ -17182,6 +17184,7 @@ s,@MAINT@,$MAINT,;t t
 s,@LIBGCJ_CFLAGS@,$LIBGCJ_CFLAGS,;t t
 s,@LIBGCJ_CXXFLAGS@,$LIBGCJ_CXXFLAGS,;t t
 s,@LIBGCJ_JAVAFLAGS@,$LIBGCJ_JAVAFLAGS,;t t
+s,@LIBGCJ_LD_SYMBOLIC@,$LIBGCJ_LD_SYMBOLIC,;t t
 s,@INCLTDL@,$INCLTDL,;t t
 s,@LIBLTDL@,$LIBLTDL,;t t
 s,@DIRLTDL@,$DIRLTDL,;t t
diff --git a/libjava/configure.ac b/libjava/configure.ac
index 269b64a3e6c7..43156b7f68d3 100644
--- a/libjava/configure.ac
+++ b/libjava/configure.ac
@@ -134,9 +134,11 @@ libgcj_javaflags=
 LIBGCJ_CFLAGS="${libgcj_cflags}"
 LIBGCJ_CXXFLAGS="${libgcj_cxxflags}"
 LIBGCJ_JAVAFLAGS="${libgcj_javaflags}"
+LIBGCJ_LD_SYMBOLIC="${libgcj_ld_symbolic}"
 AC_SUBST(LIBGCJ_CFLAGS)
 AC_SUBST(LIBGCJ_CXXFLAGS)
 AC_SUBST(LIBGCJ_JAVAFLAGS)
+AC_SUBST(LIBGCJ_LD_SYMBOLIC)
 
 AC_CONFIG_HEADERS([include/config.h gcj/libgcj-config.h])
 
diff --git a/libjava/configure.host b/libjava/configure.host
index 437566a3079b..e1eaa1bab1e3 100644
--- a/libjava/configure.host
+++ b/libjava/configure.host
@@ -173,6 +173,7 @@ case "${host}" in
   hppa*-linux* | \
   sh-linux* | sh[34]*-linux*)
   	can_unwind_signal=yes
+	libgcj_ld_symbolic='-Wl,-Bsymbolic'
 	if test x$slow_pthread_self = xyes \
 	   && test x$cross_compiling != xyes; then
 	  cat > conftest.c <<EOF
@@ -226,7 +227,6 @@ EOF
   mips*-*-linux* )
   	sysdeps_dir=mips
   	can_unwind_signal=yes
-	libgcj_interpreter=yes
 	libgcj_flags="${libgcj_flags} -mxgot"
 	DIVIDESPEC=-fno-use-divide-subroutine
 	case "${host}" in
diff --git a/libjava/defineclass.cc b/libjava/defineclass.cc
index 86df0d2aa72d..1a0c4e4da603 100644
--- a/libjava/defineclass.cc
+++ b/libjava/defineclass.cc
@@ -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.
 
@@ -26,6 +26,7 @@ details.  */
 #include <stdio.h>
 #include <java-cpool.h>
 #include <gcj/cni.h>
+#include <execution.h>
 
 #include <java/lang/Class.h>
 #include <java/lang/Float.h>
@@ -38,6 +39,7 @@ details.  */
 #include <java/lang/ClassCircularityError.h>
 #include <java/lang/IncompatibleClassChangeError.h>
 #include <java/lang/reflect/Modifier.h>
+#include <java/security/ProtectionDomain.h>
 
 using namespace gcj;
 
@@ -216,7 +218,8 @@ struct _Jv_ClassReader {
       throw_class_format_error ("erroneous type descriptor");
   }
 
-  _Jv_ClassReader (jclass klass, jbyteArray data, jint offset, jint length)
+  _Jv_ClassReader (jclass klass, jbyteArray data, jint offset, jint length,
+		   java::security::ProtectionDomain *pd)
   {
     if (klass == 0 || length < 0 || offset+length > data->length)
       throw_internal_error ("arguments to _Jv_DefineClass");
@@ -226,7 +229,10 @@ struct _Jv_ClassReader {
     len    = length;
     pos    = 0;
     def    = klass;
-    def_interp = (_Jv_InterpClass *) def->aux_info;
+    def->size_in_bytes = -1;
+    def->vtable_method_count = -1;
+    def->engine = &_Jv_soleInterpreterEngine;
+    def->protectionDomain = pd;
   }
 
   /** and here goes the parser members defined out-of-line */
@@ -273,9 +279,10 @@ struct _Jv_ClassReader {
 };
 
 void
-_Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length)
+_Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length,
+		 java::security::ProtectionDomain *pd)
 {
-  _Jv_ClassReader reader (klass, data, offset, length);
+  _Jv_ClassReader reader (klass, data, offset, length, pd);
   reader.parse();
 
   /* that's it! */
@@ -311,8 +318,13 @@ _Jv_ClassReader::parse ()
 
   handleClassBegin (access_flags, this_class, super_class);
 
+  // Allocate our aux_info here, after the name is set, to fulfill our
+  // contract with the collector interface.
+  def->aux_info = (void *) _Jv_AllocBytes (sizeof (_Jv_InterpClass));
+  def_interp = (_Jv_InterpClass *) def->aux_info;
+
   int interfaces_count = read2u (); 
-	
+
   handleInterfacesBegin (interfaces_count);
 
   for (int i = 0; i < interfaces_count; i++)
@@ -335,12 +347,11 @@ _Jv_ClassReader::parse ()
   if (pos != len)
     throw_class_format_error ("unused data before end of file");
 
-  // tell everyone we're done.
-  def->state = JV_STATE_LOADED;
+  // Tell everyone we're done.
+  def->state = JV_STATE_READ;
   if (gcj::verbose_class_flag)
-    fprintf (stderr, "[Loaded (bytecode) %s]\n", def->name->chars());
+    _Jv_Linker::print_class_loaded (def);
   def->notifyAll ();
-
 }
 
 void _Jv_ClassReader::read_constpool ()
@@ -517,30 +528,20 @@ void _Jv_ClassReader::read_one_method_attribute (int method_index)
 	throw_class_format_error ("only one Exceptions attribute allowed per method");
 
       int num_exceptions = read2u ();
-      // We use malloc here because the GC won't scan the method
-      // objects.  FIXME this means a memory leak if we GC a class.
-      // (Currently we never do.)
       _Jv_Utf8Const **exceptions =
-	(_Jv_Utf8Const **) _Jv_Malloc ((num_exceptions + 1) * sizeof (_Jv_Utf8Const *));
+	(_Jv_Utf8Const **) _Jv_AllocBytes ((num_exceptions + 1)
+					   * sizeof (_Jv_Utf8Const *));
 
       int out = 0;
       _Jv_word *pool_data = def->constants.data;
       for (int i = 0; i < num_exceptions; ++i)
 	{
-	  try
+	  int ndx = read2u ();
+	  // JLS 2nd Ed. 4.7.5 requires that the tag not be 0.
+	  if (ndx != 0)
 	    {
-	      int ndx = read2u ();
-	      // JLS 2nd Ed. 4.7.5 requires that the tag not be 0.
-	      if (ndx != 0)
-		{
-		  check_tag (ndx, JV_CONSTANT_Class);
-		  exceptions[out++] = pool_data[ndx].utf8; 
-		}
-	    }
-	  catch (java::lang::Throwable *exc)
-	    {
-	      _Jv_Free (exceptions);
-	      throw exc;
+	      check_tag (ndx, JV_CONSTANT_Class);
+	      exceptions[out++] = pool_data[ndx].utf8; 
 	    }
 	}
       exceptions[out] = NULL;
@@ -854,8 +855,7 @@ _Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
 
 
 void
-_Jv_ClassReader::handleClassBegin
-  (int access_flags, int this_class, int super_class)
+_Jv_ClassReader::handleClassBegin (int access_flags, int this_class, int super_class)
 {
   using namespace java::lang::reflect;
 
@@ -950,23 +950,25 @@ _Jv_ClassReader::handleClassBegin
   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_Linker::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))
 	{
@@ -974,7 +976,7 @@ _Jv_ClassReader::checkExtends (jclass sub, jclass super)
 	}
     } 
 
-  for (; super != 0; super = super->superclass)
+  for (; super != 0; super = super->getSuperclass ())
     {
       if (super == sub)
 	throw_class_circularity_error (sub->getName ());
@@ -1072,11 +1074,7 @@ void _Jv_ClassReader::handleField (int field_no,
   _Jv_Field *field = &def->fields[field_no];
   _Jv_Utf8Const *field_name = pool_data[name].utf8;
 
-#ifndef COMPACT_FIELDS
   field->name      = field_name;
-#else
-  field->nameIndex = name;
-#endif
 
   // Ignore flags we don't know about.  
   field->flags = flags & Modifier::ALL_FLAGS;
@@ -1234,7 +1232,7 @@ void _Jv_ClassReader::handleMethod
   // ignore unknown flags
   method->accflags = accflags & Modifier::ALL_FLAGS;
 
-  // intialize...
+  // Initialize...
   method->ncode = 0;
   method->throws = NULL;
   
@@ -1276,7 +1274,6 @@ void _Jv_ClassReader::handleCodeAttribute
   _Jv_InterpMethod *method = 
     (_Jv_InterpMethod*) (_Jv_AllocBytes (size));
 
-  method->deferred	 = NULL;
   method->max_stack      = max_stack;
   method->max_locals     = max_locals;
   method->code_length    = code_length;
@@ -1335,7 +1332,6 @@ void _Jv_ClassReader::handleMethodsEnd ()
 	      m->self = method;
 	      m->function = NULL;
 	      def_interp->interpreted_methods[i] = m;
-	      m->deferred = NULL;
 
 	      if ((method->accflags & Modifier::STATIC))
 		{
@@ -1626,7 +1622,7 @@ _Jv_VerifyClassName (_Jv_Utf8Const *name)
 }
 
 /* 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)
 {
diff --git a/libjava/gcj/Makefile.in b/libjava/gcj/Makefile.in
index b4c32fb9ea15..b40dd2a398a7 100644
--- a/libjava/gcj/Makefile.in
+++ b/libjava/gcj/Makefile.in
@@ -146,6 +146,7 @@ LIBGCJTESTSPEC = @LIBGCJTESTSPEC@
 LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@
 LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@
 LIBGCJ_JAVAFLAGS = @LIBGCJ_JAVAFLAGS@
+LIBGCJ_LD_SYMBOLIC = @LIBGCJ_LD_SYMBOLIC@
 LIBICONV = @LIBICONV@
 LIBLTDL = @LIBLTDL@
 LIBOBJS = @LIBOBJS@
diff --git a/libjava/gcj/field.h b/libjava/gcj/field.h
index bd6b2c38046e..8421bc7e0464 100644
--- a/libjava/gcj/field.h
+++ b/libjava/gcj/field.h
@@ -1,6 +1,6 @@
 // field.h - Header file for fieldID instances.  -*- c++ -*-
 
-/* Copyright (C) 1998, 1999, 2000  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2004  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -21,9 +21,7 @@ details.  */
 
 struct _Jv_Field
 {
-#ifndef COMPACT_FIELDS
   struct _Jv_Utf8Const*	name;
-#endif
 
   /* The type of the field, if isResolved().
      If !isResolved():  The fields's signature as a (Utf8Const*). */
@@ -31,11 +29,7 @@ struct _Jv_Field
 
   _Jv_ushort		flags;
 
-#ifdef COMPACT_FIELDS
-  jshort		nameIndex;  /* offset in class's name table */
-#else
   _Jv_ushort		bsize;  /* not really needed ... */
-#endif
 
   union {
     jint		boffset;  /* offset in bytes for instance field */
@@ -91,13 +85,8 @@ struct _Jv_Field
     return flags & java::lang::reflect::Modifier::ALL_FLAGS;
   }
 
-#ifdef COMPACT_FIELDS
-  _Jv_Utf8Const * getNameUtf8Const (jclass cls)
-  { return clas->fieldNames + nameIndex; }
-#else
   _Jv_Utf8Const * getNameUtf8Const (jclass) { return name; }
 #endif
-#endif
 };
 
 #ifdef __cplusplus
diff --git a/libjava/gcj/javaprims.h b/libjava/gcj/javaprims.h
index 3120184650fd..53c26fe1a8e5 100644
--- a/libjava/gcj/javaprims.h
+++ b/libjava/gcj/javaprims.h
@@ -1,5 +1,6 @@
 // javaprims.h - Main external header file for libgcj.  -*- c++ -*-
 
+
 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
    Free Software Foundation
 
@@ -84,6 +85,7 @@ extern "Java"
       class LineNumberInputStream;
       class LineNumberReader;
       class MemberComparator;
+      class MyIOException;
       class NotActiveException;
       class NotSerializableException;
       class ObjectInput;
@@ -214,6 +216,7 @@ extern "Java"
       class UnsupportedClassVersionError;
       class UnsupportedOperationException;
       class VMClassLoader;
+      class VMCompiler;
       class VMSecurityManager;
       class VMThrowable;
       class VerifyError;
diff --git a/libjava/gij.cc b/libjava/gij.cc
index 8c75fa6db7af..64457857a132 100644
--- a/libjava/gij.cc
+++ b/libjava/gij.cc
@@ -1,4 +1,4 @@
-/* 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.
 
@@ -35,6 +35,7 @@ help ()
   printf ("  -X                print help on supported -X options, then exit\n");
   printf ("  --ms=NUMBER       set initial heap size\n");
   printf ("  --mx=NUMBER       set maximum heap size\n");
+  printf ("  --verbose[:class] print information about class loading\n");
   printf ("  --showversion     print version number, then keep going\n");
   printf ("  --version         print version number, then exit\n");
   printf ("\nOptions can be specified with `-' or `--'.\n");
@@ -133,7 +134,7 @@ main (int argc, const char **argv)
 	  // correct behavior.
 	  _Jv_Jar_Class_Path = argv[++i];
 	}
-      else if (! strcmp (arg, "-verbose:class"))
+      else if (! strcmp (arg, "-verbose") || ! strcmp (arg, "-verbose:class"))
 	gcj::verbose_class_flag = true;
       else if (arg[1] == 'X')
 	{
diff --git a/libjava/gnu/gcj/runtime/PersistentByteMap.java b/libjava/gnu/gcj/runtime/PersistentByteMap.java
new file mode 100644
index 000000000000..90b7d33a8f4e
--- /dev/null
+++ b/libjava/gnu/gcj/runtime/PersistentByteMap.java
@@ -0,0 +1,484 @@
+/* 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.  */
+
+
+
+/*  A PersistentByteMap maps a byte array to another byte array.  It
+uses a file that does not need to be serialized but may be
+memory-mapped and read in-place.  So, even if there are many instances
+of gcj applications running, the can share PersistentByteMaps.
+
+The idea is to make searches as fast as possible: opening a
+PersistentByteMap is cheap and search time doesn't grow with the
+number of entries in the table.  On the other hand, enumerating the
+map is slow, but that is a relatively uncommon operation.
+
+The main use of this class is to provide a way to map the
+MessageDigest of a class file to the location of a DSO that contains
+the compiled version of that class.  It is up the the installer of an
+application to keep the DSO up to date with the jar.  
+
+USAGE:
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        digest = md.digest(bytes);
+
+        PersistentByteMap map 
+          = new PersistentByteMap
+            (fileName, PersistentByteMap.AccessMode.READ_ONLY);
+
+        byte[] soName = map.get(digest);
+        if (soName)
+          {
+            String SharedLibraryName = new String(soName);
+
+BUGS/FEATURES:
+        remove() isn't written yet.
+
+	we can't change the capacity of a PersistentByteMap.
+
+        0x12345678 is a bad choice for the magic number.
+
+        capacity is fixed once the map has been created.
+
+        We use linear probing to resolve collisions.  It might be
+        better to use a scheme that results in fewer probes to
+        determine that an item isn't found.  However, even when the
+        table is half full there are only on average 1.5 probes for a
+        successful search and 2.5 probes for an unsuccessful one.
+
+        We don't use unique strings.  This wastes space.
+
+        capacity should probably be prime, but we don't check that.
+
+	we don't do any locking at all: adding to a PersistentByteMap
+	at runtime is possible, but it requires filesystem locks
+	around get(), put(), and remove().
+*/
+
+package gnu.gcj.runtime;
+
+import java.io.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.util.*;
+import java.security.MessageDigest;
+
+public class PersistentByteMap
+{
+  private MappedByteBuffer buf;
+
+  static private final int MAGIC = 0;
+  static private final int VERSION = 4;
+  static private final int CAPACITY = 8;
+  static private final int TABLE_BASE = 12;
+  static private final int STRING_BASE = 16;
+  static private final int STRING_SIZE = 20;
+  static private final int FILE_SIZE = 24;
+  static private final int ELEMENTS = 28;
+  
+  static private final int INT_SIZE = 4;
+
+  static private final int TABLE_ENTRY_SIZE = 2 * INT_SIZE;
+
+  private int capacity;   // number of entries
+  private int table_base;   // offset from start of file, in bytes
+  private int string_base;  // offset from start of file, in bytes
+  private int string_size;  // size of string table, in bytes
+  private int file_size;    // size of file, in bytes;
+  private int elements;     // number of elements in table
+
+  private long length;      // the length of the underlying file
+
+  static private final int UNUSED_ENTRY = -1; 
+
+  static public final int KEYS = 0;
+  static public final int VALUES = 1;
+  static public final int ENTRIES = 2;
+
+  static final public class AccessMode
+  {
+    private final FileChannel.MapMode mapMode;
+
+    static
+    {
+      READ_ONLY = new AccessMode(FileChannel.MapMode.READ_ONLY);
+      READ_WRITE = new AccessMode(FileChannel.MapMode.READ_WRITE);
+    }
+
+    public static final AccessMode READ_ONLY;
+    public static final AccessMode READ_WRITE; 
+
+    private AccessMode(FileChannel.MapMode mode)
+    {
+      this.mapMode = mode;
+    }
+  }
+
+  private PersistentByteMap()
+  {
+  }
+
+  public PersistentByteMap(String filename, AccessMode mode)
+    throws IOException 
+  {
+    this(new File(filename), mode);
+  }
+
+  public PersistentByteMap(File f, AccessMode mode)
+    throws IOException 
+  {
+    FileChannel fc;
+
+    if (mode == AccessMode.READ_ONLY)
+      {
+        FileInputStream fis = new FileInputStream(f);
+        fc = fis.getChannel();
+      }
+    else
+      {
+        RandomAccessFile fos = new RandomAccessFile(f, "rw");
+        fc = fos.getChannel();
+      }
+
+    length = fc.size();
+    buf = fc.map(mode.mapMode, 0, length);
+
+    int magic = getWord (MAGIC);
+    if (magic != 0x12345678)
+      throw new IllegalArgumentException(f.getName());
+
+    table_base = getWord (TABLE_BASE);
+    capacity = getWord (CAPACITY);
+    string_base = getWord (STRING_BASE);
+    string_size = getWord (STRING_SIZE);
+    file_size = getWord (FILE_SIZE);
+    elements = getWord (ELEMENTS);
+
+    // FIXME:  Insert a bunch of sanity checks here
+  }
+
+  private void init (PersistentByteMap m, File f, int capacity, int strtabSize)
+    throws IOException 
+  {
+    f.createNewFile();
+    RandomAccessFile raf = new RandomAccessFile(f, "rw");
+        
+    this.capacity = capacity;
+    table_base = 64;
+    string_base = table_base + capacity * TABLE_ENTRY_SIZE;
+    string_size = 0;
+    file_size = string_base;
+    elements = 0;
+
+    int totalFileSize = string_base + strtabSize;
+
+    // Create the file; this rounds up the size of the file to a fixed
+    // number of 4k pages.
+    byte[] _4k = new byte[4096];
+    for (long i = 0; i < totalFileSize; i+= 4096)
+      raf.write(_4k);
+        
+    FileChannel fc = raf.getChannel();
+    buf = fc.map(FileChannel.MapMode.READ_WRITE, 0, raf.length());
+
+    for (int i = 0; i < capacity; i++)
+      putKeyPos(UNUSED_ENTRY, i);
+        
+    putWord(0x12345678, MAGIC);
+    putWord(0x01, VERSION);
+    putWord(capacity, CAPACITY);
+    putWord(table_base, TABLE_BASE);
+    putWord(string_base, STRING_BASE);
+    putWord(file_size, FILE_SIZE);
+    putWord(elements, ELEMENTS);
+    buf.force();
+  }     
+
+  static public PersistentByteMap emptyPersistentByteMap(String filename, 
+                                                         int capacity, int strtabSize)
+    throws IOException 
+  {
+    File f = new File(filename);
+    PersistentByteMap m = new PersistentByteMap();
+    m.init(m, f, capacity, strtabSize);
+    return m;
+  }     
+
+  private int getWord (int index)
+  {
+    buf.position(index);
+    byte[] wordBuf = new byte[4];
+    buf.get(wordBuf);
+
+    int result = (int)wordBuf[0]&0xff;
+    result += ((int)wordBuf[1]&0xff) << 8;
+    result += ((int)wordBuf[2]&0xff) << 16;
+    result += ((int)wordBuf[3]&0xff) << 24;
+    return result;
+  }
+
+  private void putWord (int word, int index)
+  {
+    buf.position(index);
+    byte[] wordBuf = new byte[4];
+    wordBuf[0] = (byte)(word);
+    wordBuf[1] = (byte)(word >>> 8);
+    wordBuf[2] = (byte)(word >>> 16);
+    wordBuf[3] = (byte)(word >>> 24);
+    buf.put(wordBuf);
+  }
+
+  public Set entrySet()
+  {
+    return null;
+  }
+
+  private int getBucket(int n)
+  {
+    return table_base + (2*n * INT_SIZE);
+  }
+
+  private int getKeyPos(int n)
+  {
+    return getWord(getBucket(n));
+  }
+  
+  private int getValuePos(int n)
+  {
+    return getWord(getBucket(n) + INT_SIZE);
+  }
+
+  private void putKeyPos(int index, int n)
+  {
+    putWord(index, getBucket(n));
+  }
+
+  private void putValuePos(int index, int n)
+  {
+    putWord(index, getBucket(n) + INT_SIZE);
+  }
+
+  private byte[] getBytes(int n)
+  {
+    int len = getWord (string_base + n);
+    int base = string_base + n + INT_SIZE;
+    byte[] key = new byte[len];
+    buf.position(base);
+    buf.get(key, 0, len);
+    return key;
+  }
+
+  private int hash (byte[] b)
+  {    
+    // We assume that the message digest is evenly distributed, so we
+    // only need to use a few bytes of it as the hash function.
+    long hashIndex 
+      = ((b[0]&0xffL)
+         + ((b[1]&0xffL)<<8) 
+         + ((b[2]&0xffL)<<16) 
+         + ((b[3]&0xffL)<<24));
+    long result = hashIndex % (long)capacity;
+    return (int)result;
+  }
+        
+  public byte[] get(byte[] digest)
+  {
+    int hashIndex = hash(digest);
+
+    do
+      {
+        int k = getKeyPos(hashIndex);
+        if (k == UNUSED_ENTRY)
+          return null;
+
+        if (Arrays.equals ((byte[])digest, getBytes(k)))
+          return getBytes(getValuePos(hashIndex));
+                
+        // Use linear probing to resolve hash collisions.  This may
+        // not be theoretically as good as open addressing, but it has
+        // good cache behviour.
+        hashIndex++;
+        hashIndex %= capacity;
+      }
+    while (true);
+  }
+
+  public void put(byte[] digest, byte[] value)
+    throws IllegalAccessException
+  {
+    int hashIndex = hash(digest);
+
+    // With the the table 2/3 full there will be on average 2 probes
+    // for a successful search and 5 probes for an unsuccessful one.
+    if (elements >= capacity * 2/3)
+      throw new IllegalAccessException("Table Full: " + elements);
+
+    do
+      {
+        int k = getKeyPos(hashIndex);
+        if (k == UNUSED_ENTRY)
+          {
+            int newKey = addBytes(digest);
+            putKeyPos(newKey, hashIndex);
+            int newValue = addBytes(value);
+            putValuePos(newValue, hashIndex);
+            elements++;
+            putWord(elements, ELEMENTS);            
+            return;
+          }
+        else if (Arrays.equals (digest, getBytes(k)))
+          {
+            int newValue = addBytes((byte[])value);
+            putValuePos(newValue, hashIndex);
+            return;
+          }         
+                
+        hashIndex++;
+        hashIndex %= capacity;
+      }
+    while (true);
+  }
+
+  private int addBytes (byte[] data)
+    throws IllegalAccessException
+  {
+    if (data.length + INT_SIZE >= this.length)
+      throw new IllegalAccessException("String table Full");
+
+    int extent = string_base+string_size;
+    int top = extent;
+    putWord(data.length, extent);
+    extent += INT_SIZE;
+    buf.position(extent);
+    buf.put(data, 0, data.length);
+    extent += data.length;
+    extent += INT_SIZE-1;
+    extent &= ~(INT_SIZE-1); // align
+    string_size = extent - string_base;
+    file_size = extent;
+    putWord (string_size, STRING_SIZE);
+    putWord (file_size, FILE_SIZE);
+        
+    return top - string_base;
+  }
+
+  public Iterator iterator(int type)
+  {
+    return new HashIterator(type);
+  }
+
+  public int size()
+  {
+    return elements;
+  }
+
+  public int capacity()
+  {
+    return capacity;
+  }
+
+  private final class HashIterator implements Iterator
+  {
+    /** Current index in the physical hash table. */
+
+    private int idx;
+    private int count;
+    private final int type;
+
+    /**
+     * Construct a new HashIterator with the supplied type.
+     * @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
+     */
+    HashIterator(int type)
+    {
+      this.type = type;
+      count = elements;
+      idx = 0;
+    }
+
+    /**
+     * Returns true if the Iterator has more elements.
+     * @return true if there are more elements
+     * @throws ConcurrentModificationException if the HashMap was modified
+     */
+    public boolean hasNext()
+    {
+      return count > 0;
+    }
+
+    /**
+     * Returns the next element in the Iterator's sequential view.
+     * @return the next element
+     * @throws ConcurrentModificationException if the HashMap was modified
+     * @throws NoSuchElementException if there is none
+     */
+    public Object next()
+    {
+      count--;
+      for (int i = idx; i < capacity; i++)
+        if (getKeyPos(i) != UNUSED_ENTRY)
+          {
+            idx = i+1;
+            if (type == VALUES)
+              return getBytes(getValuePos(i));
+            if (type == KEYS)
+              return getBytes(getKeyPos(i));
+            return new MapEntry(i,
+                                getBytes(getKeyPos(i)),
+                                getBytes(getValuePos(i)));
+          }
+      return null;
+    }    
+
+    /**
+     * Remove from the underlying collection the last element returned
+     * by next (optional operation). This method can be called only
+     * once after each call to <code>next()</code>. It does not affect
+     * what will be returned by subsequent calls to next.
+     *
+     * @throws IllegalStateException if next has not yet been called
+     *         or remove has already been called since the last call
+     *         to next.
+     * @throws UnsupportedOperationException if this Iterator does not
+     *         support the remove operation.
+     */
+     public void remove()
+    {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  static public final class MapEntry
+  {
+    private final Object key;
+    private final Object value;
+    private final int bucket;
+
+    public MapEntry(int bucket, Object newKey, Object newValue)
+    {
+      this.key = newKey;
+      this.value = newValue;
+      this.bucket = bucket;
+    }
+
+    public final Object getKey()
+    {
+      return key;
+    }
+
+    public final Object getValue()
+    {
+      return value;
+    }
+
+    public final int getBucket()
+    {
+      return bucket;
+    }
+  }
+}
diff --git a/libjava/gnu/gcj/runtime/SharedLibHelper.java b/libjava/gnu/gcj/runtime/SharedLibHelper.java
index 9e170a120bee..a0bfe68b83c3 100644
--- a/libjava/gnu/gcj/runtime/SharedLibHelper.java
+++ b/libjava/gnu/gcj/runtime/SharedLibHelper.java
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2003  Free Software Foundation
+/* Copyright (C) 2001, 2003, 2004  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -13,6 +13,12 @@ import java.net.MalformedURLException;
 import java.util.HashMap;
 import java.security.*;
 import gnu.gcj.Core;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.nio.channels.FileChannel;
+import java.io.*;
 
 public class SharedLibHelper
 {
@@ -36,34 +42,82 @@ public class SharedLibHelper
   {
     synchronized (map)
       {
-	WeakReference ref = (WeakReference) map.get(libname);
-	if (ref != null)
-	  return (SharedLibHelper) ref.get();
+	Set s = (Set)map.get(libname);
+	if (s == null)
+	  return null;
+	for (Iterator i=s.iterator(); i.hasNext();)
+	  {
+	    WeakReference ref = (WeakReference)i.next();
+	    if (ref != null)
+	      return (SharedLibHelper) ref.get();
+	  }
 	return null;
       }
   }
 
+  static void copyFile (File in, File out) throws IOException 
+  {
+    FileChannel source = new FileInputStream(in).getChannel();
+    FileChannel destination = new FileOutputStream(out).getChannel();
+    source.transferTo(0, source.size(), destination);
+    source.close();
+    destination.close();
+  }
+
   public static SharedLibHelper findHelper (ClassLoader loader, String libname,
 					    CodeSource source)
   {
     synchronized (map)
       {
 	SharedLibHelper result;
-	WeakReference ref = (WeakReference) map.get(libname);
-	if (ref != null)
+	Set s = (Set)map.get(libname);
+	if (s == null)
+	  {
+	    s = new HashSet();
+	    map.put(libname, s);
+	  }
+	else
 	  {
-	    result = (SharedLibHelper) ref.get();
-	    if (result != null)
+	    for (Iterator i=s.iterator(); i.hasNext();)
 	      {
-		if (result.loader != loader)
-		  // FIXME
-		  throw new UnknownError();
-		return result;
+		WeakReference ref = (WeakReference)i.next();
+		if (ref != null)
+		  {
+		    result = (SharedLibHelper) ref.get();
+		    if (result != null)
+		      {			
+			// A match succeeds if the library is already
+			// loaded by LOADER or any of its ancestors.
+			ClassLoader l = loader;
+			do
+			  {
+			    if (result.loader == l)
+			      return result;
+			    l = l.getParent();
+			  }
+			while (l != null);
+		      }
+		  }
 	      }
-	  }
 
+	    // Oh dear.  We've already mapped this shared library, but
+	    // with a different class loader.  We need to copy it.
+	    try
+	      {
+		File copy 
+		  = File.createTempFile(new File(libname).getName(), 
+					".so", new File ("/tmp"));
+		File src = new File(libname);
+		copyFile (src, copy);
+		libname = copy.getPath();
+	      }
+	    catch (IOException e)
+	      {
+		return null;
+	      }
+	  }
 	result = new SharedLibHelper(libname, loader, source, 0);
-	map.put(libname, new WeakReference(result));
+	s.add(new WeakReference(result));
 	return result;
       }
   }
@@ -73,7 +127,15 @@ public class SharedLibHelper
   public Class findClass(String name)
   {
     ensureInit();
-    return (Class) classMap.get(name);
+    Class result = (Class) classMap.get(name);
+    if (result != null)
+      {
+	// We never want to return a class without its supers linked.
+	// It isn't clear from the spec, but this is what other
+	// implementations do in practice.
+	ensureSupersLinked(result);
+      }
+    return result;
   }
 
   public URL findResource (String name)
@@ -106,6 +168,12 @@ public class SharedLibHelper
 
   native boolean hasResource(String name);
   native void init();
+  native void ensureSupersLinked(Class k);
+
+  public String toString ()
+  {
+    return "shared object " + baseName;
+  }
 
   /** Called during dlopen's processing of the init section. */
   void registerClass(String name, Class cls)
diff --git a/libjava/gnu/gcj/runtime/VMClassLoader.java b/libjava/gnu/gcj/runtime/VMClassLoader.java
index 1fc7081bb784..f9ef872b30a5 100644
--- a/libjava/gnu/gcj/runtime/VMClassLoader.java
+++ b/libjava/gnu/gcj/runtime/VMClassLoader.java
@@ -105,7 +105,8 @@ public final class VMClassLoader extends java.net.URLClassLoader
   /** This is overridden to search the internal hash table, which 
    * will only search existing linked-in classes.   This will make
    * the default implementation of loadClass (in ClassLoader) work right.
-   * The implementation of this method is in java/lang/natClassLoader.cc.
+   * The implementation of this method is in
+   * gnu/gcj/runtime/natVMClassLoader.cc.
    */
   protected native Class findClass(String name) 
     throws java.lang.ClassNotFoundException;
diff --git a/libjava/gnu/gcj/runtime/natSharedLibLoader.cc b/libjava/gnu/gcj/runtime/natSharedLibLoader.cc
index 46eef755a091..184692e10403 100644
--- a/libjava/gnu/gcj/runtime/natSharedLibLoader.cc
+++ b/libjava/gnu/gcj/runtime/natSharedLibLoader.cc
@@ -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 @@ details.  */
 
 #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 @@ typedef void (*CoreHookFunc) (_Jv_core_chain *);
 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
@@ -122,3 +125,9 @@ gnu::gcj::runtime::SharedLibHelper::finalize()
   dlclose (handler);
 #endif
 }
+
+void
+gnu::gcj::runtime::SharedLibHelper::ensureSupersLinked(jclass k)
+{
+  _Jv_Linker::wait_for_state (k, JV_STATE_LOADING);
+}
diff --git a/libjava/gnu/gcj/tools/gcj_dbtool/Main.java b/libjava/gnu/gcj/tools/gcj_dbtool/Main.java
new file mode 100644
index 000000000000..a478f9342975
--- /dev/null
+++ b/libjava/gnu/gcj/tools/gcj_dbtool/Main.java
@@ -0,0 +1,272 @@
+/* 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.  */
+
+package gnu.gcj.tools.gcj_dbtool;
+
+
+import gnu.gcj.runtime.PersistentByteMap;
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+import java.security.MessageDigest;
+import java.math.BigInteger;
+
+public class Main
+{
+  public static void main (String[] s)
+  {
+    insist (s.length >= 1);
+    if (s[0].equals("-v"))
+      {
+	insist (s.length == 1);
+	System.out.println("jv-dbtool ("
+			   + System.getProperty("java.vm.name")
+			   + ") "
+			   + System.getProperty("java.vm.version"));
+	System.out.println();
+	System.out.println("Copyright 2004 Free Software Foundation, Inc.");
+	System.out.println("This is free software; see the source for copying conditions.  There is NO");
+	System.out.println("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
+	return;
+      }
+
+    if (s[0].equals("-n"))
+      {
+	insist (s.length >= 2 && s.length <= 3);
+
+	int capacity = 32749;
+
+	if (s.length == 3)
+	  {
+	    // The user has explicitly provided a size for the table.
+	    // We're going to make that size prime.  This isn't
+	    // strictly necessary but it can't hurt.
+
+	    BigInteger size = new BigInteger(s[2], 10);
+	    BigInteger two = BigInteger.ONE.add(BigInteger.ONE);
+
+	    if (size.getLowestSetBit() != 0) // A hard way to say isEven()
+	      size = size.add(BigInteger.ONE);
+
+	    while (! size.isProbablePrime(10))
+	      size = size.add(two);
+
+	    capacity = size.intValue();
+
+	    if (capacity <= 2)
+	      {
+		usage();
+		System.exit(1);
+	      }
+	  }
+	    
+	try
+	  {
+	    PersistentByteMap b 
+	      = PersistentByteMap.emptyPersistentByteMap (s[1], capacity, capacity*64);
+	  }
+	catch (Exception e)
+	  {
+	    System.err.println ("error: could not create " 
+				+ s[1] + ": " + e.toString());
+	    System.exit(2);
+	  }
+	return;
+      }
+
+    if (s[0].equals("-a"))
+      {
+	try
+	  {
+	    insist (s.length == 4);
+	    File jar = new File(s[2]);
+	    PersistentByteMap b 
+	      = new PersistentByteMap(new File(s[1]), 
+				      PersistentByteMap.AccessMode.READ_WRITE);
+	    File soFile = new File(s[3]);
+	    if (! soFile.isFile())
+	      throw new IllegalArgumentException(s[3] + " is not a file");
+	    
+	    addJar(jar, b, soFile);
+	  }
+	catch (Exception e)
+	  {
+	    System.err.println ("error: could not update " + s[1] 
+				+ ": " + e.toString());
+	    System.exit(2);
+	  }
+	return;
+      }
+
+    if (s[0].equals("-t"))
+      {
+	try
+	  {
+	    insist (s.length == 2);
+	    PersistentByteMap b 
+	      = new PersistentByteMap(new File(s[1]),
+				      PersistentByteMap.AccessMode.READ_ONLY);
+	    Iterator iterator = b.iterator(PersistentByteMap.ENTRIES);
+	
+	    while (iterator.hasNext())
+	      {
+		PersistentByteMap.MapEntry entry 
+		  = (PersistentByteMap.MapEntry)iterator.next();
+		byte[] key = (byte[])entry.getKey();
+		byte[] value = (byte[])b.get(key);
+		if (! Arrays.equals (value, (byte[])entry.getValue()))
+		  {
+		    String err 
+		      = ("Key " + bytesToString(key) + " at bucket " 
+			 + entry.getBucket());
+		  
+		    throw new RuntimeException(err);
+		  }
+	      }
+	  }
+	catch (Exception e)
+	  {
+	    e.printStackTrace();
+	    System.exit(3);
+	  }
+	return;
+      }
+	 
+    if (s[0].equals("-l"))
+      {
+	insist (s.length == 2);
+	try
+	  {
+	    PersistentByteMap b 
+	      = new PersistentByteMap(new File(s[1]),
+				      PersistentByteMap.AccessMode.READ_ONLY);
+
+	    System.out.println ("Capacity: " + b.capacity());
+	    System.out.println ("Size: " + b.size());
+	    System.out.println ();
+
+	    System.out.println ("Elements: ");
+	    Iterator iterator = b.iterator(PersistentByteMap.ENTRIES);
+    
+	    while (iterator.hasNext())
+	      {
+		PersistentByteMap.MapEntry entry 
+		  = (PersistentByteMap.MapEntry)iterator.next();
+		byte[] digest = (byte[])entry.getKey();
+		System.out.print ("[" + entry.getBucket() + "] " 
+				  + bytesToString(digest)
+				  + " -> ");
+		System.out.println (new String((byte[])entry.getValue()));
+	      }
+	  }
+	catch (Exception e)
+	  {
+	    System.err.println ("error: could not list " 
+				+ s[1] + ": " + e.toString());
+	    System.exit(2);
+	  }
+	return;
+      }
+
+    if (s[0].equals("-d"))
+      {
+	insist (s.length == 2);
+	try
+	  {    
+	    MessageDigest md = MessageDigest.getInstance("MD5");
+	    PersistentByteMap b 
+	      = new PersistentByteMap(new File(s[1]), 
+				      PersistentByteMap.AccessMode.READ_WRITE);
+	    int N = b.capacity();
+	    byte[] bytes = new byte[1];
+	    byte digest[] = md.digest(bytes);
+	    for (int i = 0; i < N; i++)
+	      {
+		digest = md.digest(digest);
+		b.put(digest, digest);
+	      }
+	  }
+	catch (Exception e)
+	  {
+	    e.printStackTrace();
+	    System.exit(3);
+	  }	    
+	return;
+      }
+    
+    usage();
+    System.exit(1);	    
+  }
+
+  private static void insist(boolean ok)
+  {
+    if (! ok)
+      {
+	usage();
+	System.exit(1);
+      }	    
+  }
+
+  private static void usage()
+  {
+    System.err.println
+      ("jv-dbtool: Manipulate gcj map database files\n"
+       + "\n"
+       + "  Usage: \n"
+       + "    jv-dbtool -n file.gcjdb [size]     - Create a new gcj map database\n"
+       + "    jv-dbtool -a file.gcjdb file.jar file.so\n"
+       + "            - Add the contents of file.jar to the database\n"
+       + "    jv-dbtool -t file.gcjdb            - Test a gcj map database\n"
+       + "    jv-dbtool -l file.gcjdb            - List a gcj map database\n");
+  }
+      
+
+  private static void addJar(File f, PersistentByteMap b, File soFile)
+   throws Exception
+  {
+    MessageDigest md = MessageDigest.getInstance("MD5");
+
+    JarFile jar = new JarFile (f);
+    Enumeration entries = jar.entries();
+
+    while (entries.hasMoreElements())
+      {
+	JarEntry classfile = (JarEntry)entries.nextElement();
+	if (classfile.getName().endsWith(".class"))
+	  {
+	    InputStream str = jar.getInputStream(classfile);
+	    long length = classfile.getSize();
+	    if (length == -1)
+	      throw new EOFException();
+
+	    byte[] data = new byte[length];
+	    int pos = 0;
+	    while (length - pos > 0)
+	      {
+		int len = str.read(data, pos, (int)(length - pos));
+		if (len == -1)
+		  throw new EOFException("Not enough data reading from: "
+					 + classfile.getName());
+		pos += len;
+	      }
+	    b.put(md.digest(data), 
+		  soFile.getCanonicalPath().getBytes());
+	  }
+      }	      
+  }    
+
+  static String bytesToString(byte[] b)
+  {
+    StringBuffer hexBytes = new StringBuffer();
+    int length = b.length;
+    for (int i = 0; i < length; ++i)
+      hexBytes.append(Integer.toHexString(b[i] & 0xff));
+    return hexBytes.toString();
+  }
+}
+    
diff --git a/libjava/include/Makefile.in b/libjava/include/Makefile.in
index 426f958b262d..82cef6f29a27 100644
--- a/libjava/include/Makefile.in
+++ b/libjava/include/Makefile.in
@@ -145,6 +145,7 @@ LIBGCJTESTSPEC = @LIBGCJTESTSPEC@
 LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@
 LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@
 LIBGCJ_JAVAFLAGS = @LIBGCJ_JAVAFLAGS@
+LIBGCJ_LD_SYMBOLIC = @LIBGCJ_LD_SYMBOLIC@
 LIBICONV = @LIBICONV@
 LIBLTDL = @LIBLTDL@
 LIBOBJS = @LIBOBJS@
diff --git a/libjava/include/execution.h b/libjava/include/execution.h
new file mode 100644
index 000000000000..b8f47468fc75
--- /dev/null
+++ b/libjava/include/execution.h
@@ -0,0 +1,146 @@
+// 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);
+  void (*post_miranda_hook) (jclass);
+};
+
+// 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)
+  {
+    _Jv_Linker::verify_type_assertions (klass);
+  }
+
+  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.
+  }
+
+  static void do_post_miranda_hook (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;
+    post_miranda_hook = do_post_miranda_hook;
+  }
+
+  // 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);
+  }
+
+  static void do_post_miranda_hook (jclass);
+
+  _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;
+    post_miranda_hook = do_post_miranda_hook;
+  }
+
+  // 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__
diff --git a/libjava/include/java-interp.h b/libjava/include/java-interp.h
index 12bc21f24360..c8e041ae3876 100644
--- a/libjava/include/java-interp.h
+++ b/libjava/include/java-interp.h
@@ -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.
 
@@ -36,7 +36,8 @@ _Jv_IsInterpretedClass (jclass c)
 struct _Jv_ResolvedMethod;
 
 void _Jv_InitInterpreter ();
-void _Jv_DefineClass (jclass, jbyteArray, jint, jint);
+void _Jv_DefineClass (jclass, jbyteArray, jint, jint,
+		      java::security::ProtectionDomain *);
 
 void _Jv_InitField (jobject, jclass, int);
 void * _Jv_AllocMethodInvocation (jsize size);
@@ -88,11 +89,7 @@ protected:
   // Size of raw arguments.
   _Jv_ushort args_raw_size;
 
-  // Chain of addresses to fill in.  See _Jv_Defer_Resolution.
-  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 ()
@@ -150,10 +147,9 @@ class _Jv_InterpMethod : public _Jv_MethodBase
   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
@@ -166,43 +162,15 @@ class _Jv_InterpClass
 
   friend class _Jv_ClassReader;
   friend class _Jv_InterpMethod;
-  friend void  _Jv_PrepareClass(jclass);
-  friend void  _Jv_PrepareMissingMethods (jclass base2, jclass iface_class);
+  friend class _Jv_InterpreterEngine;
   friend void  _Jv_InitField (jobject, jclass, int);
 #ifdef JV_MARKOBJ_DECL
   friend JV_MARKOBJ_DECL;
 #endif
 
   friend _Jv_MethodBase ** _Jv_GetFirstMethod (_Jv_InterpClass *klass);
-  friend void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **);
 };
 
-// We have an interpreted class CL and we're trying to find the
-// address of the ncode of a method METH.  That interpreted class
-// hasn't yet been prepared, so we defer fixups until they are ready.
-// To do this, we create a chain of fixups that will be resolved by
-// _Jv_PrepareClass.
-extern inline void 
-_Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **address)
-{
-  int i;
-  jclass self = (jclass) cl;
-  _Jv_InterpClass *interp_cl = (_Jv_InterpClass*) self->aux_info;
-
-  for (i = 0; i < self->method_count; i++)
-    {
-      _Jv_Method *m = &self->methods[i];
-      if (m == meth)
-	{
-	  _Jv_MethodBase *imeth = interp_cl->interpreted_methods[i];
-	  *address = imeth->deferred;
-	  imeth->deferred = address;
-	  return;
-	}
-    }
-  return;
-}    
-
 extern inline _Jv_MethodBase **
 _Jv_GetFirstMethod (_Jv_InterpClass *klass)
 {
@@ -240,7 +208,11 @@ class _Jv_JNIMethod : public _Jv_MethodBase
   void *ncode ();
 
   friend class _Jv_ClassReader;
-  friend void _Jv_PrepareClass(jclass);
+  friend class _Jv_InterpreterEngine;
+
+#ifdef JV_MARKOBJ_DECL
+  friend JV_MARKOBJ_DECL;
+#endif
 
 public:
   // FIXME: this is ugly.
diff --git a/libjava/include/java-stack.h b/libjava/include/java-stack.h
new file mode 100644
index 000000000000..6c3103ce0568
--- /dev/null
+++ b/libjava/include/java-stack.h
@@ -0,0 +1,84 @@
+// java-stack.h - Definitions for unwinding & inspecting the call stack.
+
+/* Copyright (C) 2003  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 __JV_STACKTRACE_H__
+#define __JV_STACKTRACE_H__
+
+#include <unwind.h>
+
+#include <gcj/cni.h>
+#include <gcj/javaprims.h>
+
+#include <java-interp.h>
+
+#include <java/lang/Class.h>
+#include <java/lang/StackTraceElement.h>
+#include <java/lang/Throwable.h>
+
+#include <gnu/gcj/runtime/NameFinder.h>
+
+using namespace gnu::gcj::runtime;
+
+enum _Jv_FrameType
+{
+  frame_native,
+  frame_interpreter
+};
+
+#ifdef INTERPRETER
+struct _Jv_InterpFrameInfo
+{
+  _Jv_InterpMethod *meth;
+  pc_t pc;
+};
+#endif
+
+union _Jv_FrameInfo
+{
+};
+
+struct _Jv_StackFrame
+{
+  _Jv_FrameType type;   /* Native or interpreted.  */
+  union {
+#ifdef INTERPRETER
+    _Jv_InterpFrameInfo interp;
+#endif
+    void *ip;  
+  };
+//  _Jv_FrameInfo info;   /* Frame-type specific data.  */
+  jclass klass;
+  _Jv_Method *meth;
+};
+
+class _Jv_StackTrace
+{
+private:
+  int length;
+  _Jv_StackFrame frames[];
+
+  static void UpdateNCodeMap ();
+  static jclass ClassForIP (void *ip, void **ncode);
+  static void FillInFrameInfo (_Jv_StackFrame *frame);
+  static void getLineNumberForFrame(_Jv_StackFrame *frame, NameFinder *finder, 
+			     jstring *sourceFileName, jint *lineNum);
+  
+  static _Unwind_Reason_Code UnwindTraceFn (struct _Unwind_Context *context, 
+    void *state_ptr);
+
+public:
+  static _Jv_StackTrace *GetStackTrace (void);
+  static JArray< ::java::lang::StackTraceElement *>*
+    GetStackTraceElements (_Jv_StackTrace *trace, 
+    java::lang::Throwable *throwable);
+  static jclass GetCallingClass (void);
+};
+
+#endif /* __JV_STACKTRACE_H__ */
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index 55799515c05e..a3d06e7b09fe 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -1,6 +1,6 @@
 // jvm.h - Header file for private implementation information. -*- c++ -*-
 
-/* 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.
 
@@ -231,9 +231,6 @@ inline _Jv_TempUTFString::~_Jv_TempUTFString ()
   char utfstr##_buf[utfstr##_len <= 256 ? utfstr##_len : 0]; \
   _Jv_TempUTFString utfstr(utfstr##thejstr, sizeof(utfstr##_buf)==0 ? 0 : utfstr##_buf)
 
-// FIXME: remove this define.
-#define StringClass java::lang::String::class$
-
 namespace gcj
 {
   /* Some constants used during lookup of special class methods.  */
@@ -249,6 +246,43 @@ namespace gcj
   extern bool verbose_class_flag;
 }
 
+// This class handles all aspects of class preparation and linking.
+class _Jv_Linker
+{
+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 *);
+  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);
+  static _Jv_Method *search_method_in_class (jclass, jclass,
+					     _Jv_Utf8Const *,
+					     _Jv_Utf8Const *);
+
+public:
+
+  static void print_class_loaded (jclass);
+  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 *);
+  static void verify_type_assertions (jclass);
+};
+
 /* Type of pointer used as finalizer.  */
 typedef void _Jv_FinalizerFunc (jobject);
 
@@ -416,7 +450,6 @@ extern "C" void _Jv_RegisterClasses_Counted (const jclass *classes,
 					     size_t count);
 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);
diff --git a/libjava/interpret.cc b/libjava/interpret.cc
index 0446c7296237..91d4b194774e 100644
--- a/libjava/interpret.cc
+++ b/libjava/interpret.cc
@@ -11,6 +11,7 @@ details.  */
 /* 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 @@ details.  */
 #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 @@ static void throw_null_pointer_exception ()
   __attribute__ ((__noreturn__));
 #endif
 
+static void throw_class_format_error (jstring msg)
+	__attribute__ ((__noreturn__));
+static void throw_class_format_error (char *msg)
+	__attribute__ ((__noreturn__));
+
 #ifdef DIRECT_THREADED
 // Lock to ensure that methods are not compiled concurrently.
 // We could use a finer-grained lock here, however it is not safe to use
@@ -765,8 +777,9 @@ _Jv_InterpMethod::compile (const void * const *insn_targets)
       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_Linker::resolve_pool_entry (defining_class,
+					     exc[i].handler_type.i)).clazz;
       exc[i].handler_type.p = handler;
     }
 
@@ -1113,13 +1126,14 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
       {
 	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_Linker::resolve_pool_entry returns immediately if the
+	 * value already is resolved.  If we want to clutter up the
+	 * code here to gain a little performance, then we can check
+	 * the corresponding bit JV_CONSTANT_ResolvedFlag in the tag
+	 * directly.  For now, I don't think it is worth it.  */
 
-	rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
+	rmeth = (_Jv_Linker::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
@@ -2409,7 +2423,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
     insn_getstatic:
       {
 	jint fieldref_index = GET2U ();
-	_Jv_ResolvePoolEntry (defining_class, fieldref_index);
+	_Jv_Linker::resolve_pool_entry (defining_class, fieldref_index);
 	_Jv_Field *field = pool_data[fieldref_index].field;
 
 	if ((field->flags & Modifier::STATIC) == 0)
@@ -2496,7 +2510,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
     insn_getfield:
       {
 	jint fieldref_index = GET2U ();
-	_Jv_ResolvePoolEntry (defining_class, fieldref_index);
+	_Jv_Linker::resolve_pool_entry (defining_class, fieldref_index);
 	_Jv_Field *field = pool_data[fieldref_index].field;
 
 	if ((field->flags & Modifier::STATIC) != 0)
@@ -2612,7 +2626,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
     insn_putstatic:
       {
 	jint fieldref_index = GET2U ();
-	_Jv_ResolvePoolEntry (defining_class, fieldref_index);
+	_Jv_Linker::resolve_pool_entry (defining_class, fieldref_index);
 	_Jv_Field *field = pool_data[fieldref_index].field;
 
 	jclass type = field->type;
@@ -2699,7 +2713,7 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
     insn_putfield:
       {
 	jint fieldref_index = GET2U ();
-	_Jv_ResolvePoolEntry (defining_class, fieldref_index);
+	_Jv_Linker::resolve_pool_entry (defining_class, fieldref_index);
 	_Jv_Field *field = pool_data[fieldref_index].field;
 
 	jclass type = field->type;
@@ -2825,7 +2839,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
       {
 	int index = GET2U ();
 
-	rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
+	rmeth = (_Jv_Linker::resolve_pool_entry (defining_class,
+						   index)).rmethod;
 
 	sp -= rmeth->stack_item_count;
 
@@ -2863,7 +2878,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
       {
 	int index = GET2U ();
 
-	rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
+	rmeth = (_Jv_Linker::resolve_pool_entry (defining_class,
+						   index)).rmethod;
 
 	sp -= rmeth->stack_item_count;
 
@@ -2892,7 +2908,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
       {
 	int index = GET2U ();
 
-	rmeth = (_Jv_ResolvePoolEntry (defining_class, index)).rmethod;
+	rmeth = (_Jv_Linker::resolve_pool_entry (defining_class,
+						   index)).rmethod;
 
 	sp -= rmeth->stack_item_count;
 
@@ -2935,7 +2952,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
     insn_new:
       {
 	int index = GET2U ();
-	jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
+	jclass klass = (_Jv_Linker::resolve_pool_entry (defining_class,
+							  index)).clazz;
 	jobject res = _Jv_AllocObject (klass);
 	PUSHA (res);
 
@@ -2968,7 +2986,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
     insn_anewarray:
       {
 	int index = GET2U ();
-	jclass klass = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
+	jclass klass = (_Jv_Linker::resolve_pool_entry (defining_class,
+							  index)).clazz;
 	int size  = POPI();
 	jobject result = _Jv_NewObjectArray (size, klass, 0);
 	PUSHA (result);
@@ -3010,7 +3029,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
       {
 	jobject value = POPA();
 	jint index = GET2U ();
-	jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
+	jclass to = (_Jv_Linker::resolve_pool_entry (defining_class,
+						       index)).clazz;
 
 	if (value != NULL && ! to->isInstance (value))
 	  throw new java::lang::ClassCastException (to->getName());
@@ -3040,7 +3060,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
       {
 	jobject value = POPA();
 	jint index = GET2U ();
-	jclass to = (_Jv_ResolvePoolEntry (defining_class, index)).clazz;
+	jclass to = (_Jv_Linker::resolve_pool_entry (defining_class,
+						       index)).clazz;
 	PUSHI (to->isInstance (value));
 
 #ifdef DIRECT_THREADED
@@ -3102,7 +3123,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
 	int dim        = GET1U ();
 
 	jclass type    
-	  = (_Jv_ResolvePoolEntry (defining_class, kind_index)).clazz;
+	  = (_Jv_Linker::resolve_pool_entry (defining_class,
+					       kind_index)).clazz;
 	jint *sizes    = (jint*) __builtin_alloca (sizeof (jint)*dim);
 
 	for (int i = dim - 1; i >= 0; i--)
@@ -3203,8 +3225,8 @@ _Jv_InterpMethod::run (void *retp, ffi_raw *args)
 #else
 	      jclass handler = NULL;
 	      if (exc[i].handler_type.i != 0)
-		handler = (_Jv_ResolvePoolEntry (defining_class,
-						 exc[i].handler_type.i)).clazz;
+		handler = (_Jv_Linker::resolve_pool_entry (defining_class,
+							     exc[i].handler_type.i)).clazz;
 #endif /* DIRECT_THREADED */
 
 	      if (handler == NULL || handler->isAssignableFrom (exc_class))
@@ -3250,4 +3272,547 @@ throw_null_pointer_exception ()
 }
 #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 == &java::lang::String::class$
+ 	     || field->type == &java::lang::Class::class$))
+	throw_class_format_error ("string initialiser to non-string field");
+
+      *(jstring*)addr = pool->data[init].string;
+      break;
+
+    case JV_CONSTANT_Integer:
+      {
+	int value = pool->data[init].i;
+
+	if (field->type == JvPrimClass (boolean))
+	  *(jboolean*)addr = (jboolean)value;
+	
+	else if (field->type == JvPrimClass (byte))
+	  *(jbyte*)addr = (jbyte)value;
+	
+	else if (field->type == JvPrimClass (char))
+	  *(jchar*)addr = (jchar)value;
+
+	else if (field->type == JvPrimClass (short))
+	  *(jshort*)addr = (jshort)value;
+	
+	else if (field->type == JvPrimClass (int))
+	  *(jint*)addr = (jint)value;
+
+	else
+	  throw_class_format_error ("erroneous field initializer");
+      }  
+      break;
+
+    case JV_CONSTANT_Long:
+      if (field->type != JvPrimClass (long))
+	throw_class_format_error ("erroneous field initializer");
+
+      *(jlong*)addr = _Jv_loadLong (&pool->data[init]);
+      break;
+
+    case JV_CONSTANT_Float:
+      if (field->type != JvPrimClass (float))
+	throw_class_format_error ("erroneous field initializer");
+
+      *(jfloat*)addr = pool->data[init].f;
+      break;
+
+    case JV_CONSTANT_Double:
+      if (field->type != JvPrimClass (double))
+	throw_class_format_error ("erroneous field initializer");
+
+      *(jdouble*)addr = _Jv_loadDouble (&pool->data[init]);
+      break;
+
+    default:
+      throw_class_format_error ("erroneous field initializer");
+    }
+}
+
+inline static unsigned char*
+skip_one_type (unsigned char* ptr)
+{
+  int ch = *ptr++;
+
+  while (ch == '[')
+    { 
+      ch = *ptr++;
+    }
+  
+  if (ch == 'L')
+    {
+      do { ch = *ptr++; } while (ch != ';');
+    }
+
+  return ptr;
+}
+
+static ffi_type*
+get_ffi_type_from_signature (unsigned char* ptr)
+{
+  switch (*ptr) 
+    {
+    case 'L':
+    case '[':
+      return &ffi_type_pointer;
+      break;
+
+    case 'Z':
+      // On some platforms a bool is a byte, on others an int.
+      if (sizeof (jboolean) == sizeof (jbyte))
+	return &ffi_type_sint8;
+      else
+	{
+	  JvAssert (sizeof (jbyte) == sizeof (jint));
+	  return &ffi_type_sint32;
+	}
+      break;
+
+    case 'B':
+      return &ffi_type_sint8;
+      break;
+      
+    case 'C':
+      return &ffi_type_uint16;
+      break;
+	  
+    case 'S': 
+      return &ffi_type_sint16;
+      break;
+	  
+    case 'I':
+      return &ffi_type_sint32;
+      break;
+	  
+    case 'J':
+      return &ffi_type_sint64;
+      break;
+	  
+    case 'F':
+      return &ffi_type_float;
+      break;
+	  
+    case 'D':
+      return &ffi_type_double;
+      break;
+
+    case 'V':
+      return &ffi_type_void;
+      break;
+    }
+
+  throw_internal_error ("unknown type in signature");
+}
+
+/* this function yields the number of actual arguments, that is, if the
+ * function is non-static, then one is added to the number of elements
+ * found in the signature */
+
+int 
+_Jv_count_arguments (_Jv_Utf8Const *signature,
+		     jboolean staticp)
+{
+  unsigned char *ptr = (unsigned char*) signature->chars();
+  int arg_count = staticp ? 0 : 1;
+
+  /* first, count number of arguments */
+
+  // skip '('
+  ptr++;
+
+  // count args
+  while (*ptr != ')')
+    {
+      ptr = skip_one_type (ptr);
+      arg_count += 1;
+    }
+
+  return arg_count;
+}
+
+/* This beast will build a cif, given the signature.  Memory for
+ * the cif itself and for the argument types must be allocated by the
+ * caller.
+ */
+
+static int 
+init_cif (_Jv_Utf8Const* signature,
+	  int arg_count,
+	  jboolean staticp,
+	  ffi_cif *cif,
+	  ffi_type **arg_types,
+	  ffi_type **rtype_p)
+{
+  unsigned char *ptr = (unsigned char*) signature->chars();
+
+  int arg_index = 0;		// arg number
+  int item_count = 0;		// stack-item count
+
+  // setup receiver
+  if (!staticp)
+    {
+      arg_types[arg_index++] = &ffi_type_pointer;
+      item_count += 1;
+    }
+
+  // skip '('
+  ptr++;
+
+  // 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->chars() + signature->len())
+    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_AllocBytes ((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++)
+    {
+      using namespace java::lang::reflect;
+      _Jv_MethodBase *imeth = iclass->interpreted_methods[i];
+      _Jv_ushort accflags = klass->methods[i].accflags;
+      if ((accflags & (Modifier::NATIVE | Modifier::ABSTRACT)) == 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 ();
+	}
+    }
+}
+
+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_Linker::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;
+}
+
+void
+_Jv_InterpreterEngine::do_post_miranda_hook (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;
+      // Miranda method additions mean that the `methods' array moves.
+      // We cache a pointer into this array, so we have to update.
+      iclass->interpreted_methods[i]->self = &klass->methods[i];
+    }
+}
+
 #endif // INTERPRETER
diff --git a/libjava/java/io/ObjectInputStream.java b/libjava/java/io/ObjectInputStream.java
index 646eaebe4c78..0c79d332700a 100644
--- a/libjava/java/io/ObjectInputStream.java
+++ b/libjava/java/io/ObjectInputStream.java
@@ -121,15 +121,15 @@ public class ObjectInputStream extends InputStream
    */
   public final Object readObject() throws ClassNotFoundException, IOException
   {
-      if (callersClassLoader == null)
-	{
-	  callersClassLoader = getCallersClassLoader ();
-	  if (Configuration.DEBUG && dump)
-	    {
-	      dumpElementln ("CallersClassLoader = " + callersClassLoader);
-	    }
-	}
-
+	if (callersClassLoader == null)
+	  {
+		callersClassLoader = getCallersClassLoader ();
+		if (Configuration.DEBUG && dump)
+		  {
+			dumpElementln ("CallersClassLoader = " + callersClassLoader);
+		  }
+	  }
+	
     if (this.useSubclassMethod)
       return readObjectOverride();
 
@@ -271,7 +271,7 @@ public class ObjectInputStream extends InputStream
 	      readArrayElements(array, componentType);
 	      if(dump)
 	        for (int i = 0, len = Array.getLength(array); i < len; i++)
-		  dumpElementln("  ELEMENT[" + i + "]=" + Array.get(array, i));
+			  dumpElementln("  ELEMENT[" + i + "]=" + Array.get(array, i));
 	      ret_val = processResolution(null, array, handle);
 	      break;
 	    }
@@ -398,6 +398,8 @@ public class ObjectInputStream extends InputStream
 	setBlockDataMode(old_mode);
 	
 	this.isDeserializing = was_deserializing;
+
+	depth -= 2;
 	
 	depth -= 2;
 	
@@ -1806,6 +1808,7 @@ public class ObjectInputStream extends InputStream
    * @param sm SecurityManager instance which should be called.
    * @return The current class loader in the calling stack.
    */
+
   private static native ClassLoader currentClassLoader (SecurityManager sm);
   
   private native ClassLoader getCallersClassLoader();
@@ -1875,7 +1878,7 @@ public class ObjectInputStream extends InputStream
   private int depth = 0;
 
   private void dumpElement (String msg)
-  {
+  {	
     System.out.print(msg);
   }
   
diff --git a/libjava/java/io/ObjectOutputStream.java b/libjava/java/io/ObjectOutputStream.java
index 6a5eed7a24c3..3482225232a1 100644
--- a/libjava/java/io/ObjectOutputStream.java
+++ b/libjava/java/io/ObjectOutputStream.java
@@ -347,8 +347,8 @@ public class ObjectOutputStream extends OutputStream
 		    fieldsAlreadyWritten = false;
 		    if (currentObjectStreamClass.hasWriteMethod())
 		      {
-			if (dump)
-			  dumpElementln ("WRITE METHOD CALLED FOR: " + obj);
+				if (dump)
+				  dumpElementln ("WRITE METHOD CALLED FOR: " + obj);
 			setBlockDataMode(true);
 			callWriteMethod(obj, currentObjectStreamClass);
 			setBlockDataMode(false);
@@ -358,10 +358,10 @@ public class ObjectOutputStream extends OutputStream
 		      }
 		    else
 		      {
-			if (dump)
-			  dumpElementln ("WRITE FIELDS CALLED FOR: " + obj);
-		      writeFields(obj, currentObjectStreamClass);
-		  }
+				if (dump)
+				  dumpElementln ("WRITE FIELDS CALLED FOR: " + obj);
+				writeFields(obj, currentObjectStreamClass);
+			  }
 		  }
 
 		this.currentObject = prevObject;
diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h
index a60e80a22d9c..320b09965d0e 100644
--- a/libjava/java/lang/Class.h
+++ b/libjava/java/lang/Class.h
@@ -42,13 +42,15 @@ enum
 
   JV_STATE_PRELOADING = 1,	// Can do _Jv_FindClass.
   JV_STATE_LOADING = 3,		// Has super installed.
-  JV_STATE_COMPILED = 5,	// This was a compiled class.
+  JV_STATE_READ = 4,		// Has been completely defined.
+  JV_STATE_LOADED = 5,		// Has Miranda methods defined.
+
+  JV_STATE_COMPILED = 6,	// This was a compiled class.
 
-  JV_STATE_LOADED = 6,		// Is complete.
   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,
 
@@ -59,6 +61,9 @@ struct _Jv_Field;
 struct _Jv_VTable;
 union _Jv_word;
 struct _Jv_ArrayVTable;
+class _Jv_ExecutionEngine;
+class _Jv_CompiledEngine;
+class _Jv_InterpreterEngine;
 
 struct _Jv_Constants
 {
@@ -106,7 +111,7 @@ union _Jv_IDispatchTable
   } iface;
 };
 
-// Used by _Jv_GetInterfaces ()
+// Used by _Jv_Linker::get_interfaces ()
 struct _Jv_ifaces
 {
   jclass *list;
@@ -139,6 +144,23 @@ struct _Jv_CatchClass
   _Jv_Utf8Const *classname;
 };
 
+// Possible values for the assertion_code field in the type assertion table.
+enum
+{
+  JV_ASSERT_END_OF_TABLE = 0,
+  JV_ASSERT_TYPES_COMPATIBLE = 1,
+  JV_ASSERT_IS_INSTANTIABLE = 2
+};
+
+// Entry in the type assertion table, used to validate type constraints
+// for binary compatibility.
+struct _Jv_TypeAssertion
+{
+  jint assertion_code;
+  _Jv_Utf8Const *op1;
+  _Jv_Utf8Const *op2;
+};
+
 #define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
 
 #define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
@@ -149,11 +171,11 @@ struct _Jv_CatchClass
 _Jv_Method *_Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
 				_Jv_Utf8Const *signature);
 jboolean _Jv_IsAssignableFrom (jclass, jclass);
+jboolean _Jv_IsAssignableFromSlow (jclass, jclass);
 jboolean _Jv_InterfaceAssignableFrom (jclass, jclass);
-void _Jv_InitClass (jclass klass);
 
 _Jv_Method* _Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *, 
-				      _Jv_Utf8Const*);
+				      _Jv_Utf8Const*, jclass * = NULL);
 jfieldID JvGetFirstInstanceField (jclass);
 jint JvNumInstanceFields (jclass);
 jfieldID JvGetFirstStaticField (jclass);
@@ -183,10 +205,6 @@ class java::io::ObjectOutputStream;
 class java::io::ObjectInputStream;
 class java::io::ObjectStreamClass;
 
-void _Jv_WaitForState (jclass, int);
-void _Jv_RegisterClasses (const jclass *classes);
-void _Jv_RegisterClasses_Counted (const jclass *classes, 
-				  size_t count);
 void _Jv_RegisterClassHookDefault (jclass klass);
 void _Jv_RegisterInitiatingLoader (jclass,java::lang::ClassLoader*);
 void _Jv_UnregisterClass (jclass);
@@ -205,19 +223,7 @@ void _Jv_InitNewClassFields (jclass klass);
 
 // Friend functions and classes in prims.cc
 void _Jv_InitPrimClass (jclass, char *, char, int);
-void _Jv_PrepareCompiledClass (jclass);
-void _Jv_PrepareConstantTimeTables (jclass);
-jshort _Jv_GetInterfaces (jclass, _Jv_ifaces *);
-void _Jv_GenerateITable (jclass, _Jv_ifaces *, jshort *);
 jstring _Jv_GetMethodString (jclass, _Jv_Utf8Const *);
-jshort _Jv_AppendPartialITable (jclass, jclass, void **, jshort);
-jshort _Jv_FindIIndex (jclass *, jshort *, jshort);
-void _Jv_LinkSymbolTable (jclass);
-void _Jv_LayoutInterfaceMethods (jclass);
-void _Jv_LayoutVTableMethods (jclass klass);
-void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
-void _Jv_MakeVTable (jclass);
-void _Jv_linkExceptionClassTable (jclass);
 
 jboolean _Jv_CheckAccess (jclass self_klass, jclass other_klass,
 			  jint flags);
@@ -225,25 +231,14 @@ jclass _Jv_GetArrayClass (jclass klass, java::lang::ClassLoader *loader);
 
 #ifdef INTERPRETER
 jboolean _Jv_IsInterpretedClass (jclass);
-void _Jv_InitField (jobject, jclass, _Jv_Field*);
 void _Jv_InitField (jobject, jclass, int);
-_Jv_word _Jv_ResolvePoolEntry (jclass, int);
-_Jv_Method *_Jv_SearchMethodInClass (jclass cls, jclass klass, 
-				     _Jv_Utf8Const *method_name, 
-				     _Jv_Utf8Const *method_signature);
 
-void _Jv_PrepareClass (jclass);
-void _Jv_PrepareMissingMethods (jclass base, jclass iface_class);
-
-void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **);
-  
 class _Jv_ClassReader;	
 class _Jv_InterpClass;
 class _Jv_InterpMethod;
 #endif
 
 class _Jv_BytecodeVerifier;
-class _Jv_StackTrace;
 class gnu::gcj::runtime::StackTrace;
 class java::io::VMObjectStreamClass;
 
@@ -316,9 +311,14 @@ public:
   void setSigners(JArray<jobject> *);
 
   inline jclass getSuperclass (void)
-    {
-      return superclass;
-    }
+  {
+    return superclass;
+  }
+
+  inline jclass getInterface (jint n)
+  {
+    return interfaces[n];
+  }
 
   inline jboolean isArray (void)
     {
@@ -351,9 +351,16 @@ public:
 
   // FIXME: this probably shouldn't be public.
   jint size (void)
-    {
-      return size_in_bytes;
-    }
+  {
+    return size_in_bytes;
+  }
+
+  // The index of the first method we declare ourself (as opposed to
+  // inheriting).
+  inline jint firstMethodIndex (void)
+  {
+    return vtable_method_count - method_count;
+  }
     
   // finalization
   void finalize ();
@@ -372,10 +379,17 @@ private:
 
   static jstring getPackagePortion (jstring);
 
+  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);
   friend jboolean (::_Jv_IsAssignableFrom) (jclass, jclass);
+  friend jboolean (::_Jv_IsAssignableFromSlow) (jclass, jclass);
   friend jboolean (::_Jv_InterfaceAssignableFrom) (jclass, jclass);
   friend void *::_Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, 
 					       int method_idx);
@@ -383,7 +397,7 @@ private:
   friend void ::_Jv_InitClass (jclass klass);
 
   friend _Jv_Method* ::_Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *, 
-						 _Jv_Utf8Const*);
+						 _Jv_Utf8Const*, jclass *);
   friend jfieldID (::JvGetFirstInstanceField) (jclass);
   friend jint (::JvNumInstanceFields) (jclass);
   friend jfieldID (::JvGetFirstStaticField) (jclass);
@@ -413,7 +427,6 @@ private:
   friend class java::io::ObjectInputStream;
   friend class java::io::ObjectStreamClass;
 
-  friend void ::_Jv_WaitForState (jclass, int);
   friend void ::_Jv_RegisterClasses (const jclass *classes);
   friend void ::_Jv_RegisterClasses_Counted (const jclass *classes, 
 					     size_t count);
@@ -436,40 +449,22 @@ private:
   // in prims.cc
   friend void ::_Jv_InitPrimClass (jclass, char *, char, int);
 
-  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 *);
-  friend jshort (::_Jv_AppendPartialITable) (jclass, jclass, void **, jshort);
-  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 bool _Jv_getInterfaceMethod(jclass, jclass&, int&, 
+				     const _Jv_Utf8Const*,
+				     const _Jv_Utf8Const*);
 
   friend jclass (::_Jv_GetArrayClass) (jclass klass,
 				       java::lang::ClassLoader *loader);
 
 #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 **);
-  
   friend class ::_Jv_ClassReader;	
   friend class ::_Jv_InterpClass;
   friend class ::_Jv_InterpMethod;
@@ -480,10 +475,14 @@ private:
 #endif
 
   friend class ::_Jv_BytecodeVerifier;
-  friend class ::_Jv_StackTrace;
   friend class gnu::gcj::runtime::StackTrace;
   friend class java::io::VMObjectStreamClass;
 
+  friend class _Jv_Linker;
+  friend class _Jv_ExecutionEngine;
+  friend class _Jv_CompiledEngine;
+  friend class _Jv_InterpreterEngine;
+
   friend void ::_Jv_sharedlib_register_hook (jclass klass);
 
   // Chain for class pool.
@@ -518,8 +517,12 @@ private:
   _Jv_OffsetTable *otable;
   // Offset table symbols.
   _Jv_MethodSymbol *otable_syms;
+  // Address table
   _Jv_AddressTable *atable;
   _Jv_MethodSymbol *atable_syms;
+  // Interface table
+  _Jv_AddressTable *itable;
+  _Jv_MethodSymbol *itable_syms;
   _Jv_CatchClass *catch_classes;
   // Interfaces implemented by this class.
   jclass *interfaces;
@@ -542,13 +545,17 @@ private:
   jclass arrayclass;
   // Security Domain to which this class belongs (or null).
   java::security::ProtectionDomain *protectionDomain;
+  // Pointer to the type assertion table for this class.
+  _Jv_TypeAssertion *assertion_table;
   // Signers of this class (or null).
   JArray<jobject> *hack_signers;
   // Used by Jv_PopClass and _Jv_PushClass to communicate with StackTrace.
   jclass chain;
-  // Additional data, specific to the generator (JIT, native, interpreter) of this 
-  // class.
+  // Additional data, specific to the generator (JIT, native,
+  // interpreter) of this class.
   void *aux_info;
+  // Execution engine.
+  _Jv_ExecutionEngine *engine;
 };
 
 // Inline functions that are friends of java::lang::Class
diff --git a/libjava/java/lang/ClassLoader.java b/libjava/java/lang/ClassLoader.java
index 75f07169f390..648afca5435c 100644
--- a/libjava/java/lang/ClassLoader.java
+++ b/libjava/java/lang/ClassLoader.java
@@ -288,6 +288,8 @@ public abstract class ClassLoader
     if (c != null)
       return c;
 
+    ClassNotFoundException ex = null;
+
     // Can the class be loaded by a parent?
     try
       {
@@ -304,9 +306,20 @@ public abstract class ClassLoader
       }
     catch (ClassNotFoundException e)
       {
+	ex = e;
       }
     // Still not found, we have to do it ourself.
-    c = findClass(name);
+    try
+      {
+	c = findClass(name);
+      }
+    catch (ClassNotFoundException cause)
+      {
+	if (ex != null)
+	  throw new ClassNotFoundException(ex.toString(), cause);
+	else
+	  throw cause;
+      }
     if (resolve)
       resolveClass(c);
     return c;
@@ -435,8 +448,9 @@ public abstract class ClassLoader
       domain = defaultProtectionDomain;
     if (! initialized)
       throw new SecurityException("attempt to define class from uninitialized class loader");
+    
     Class retval = VMClassLoader.defineClass(this, name, data,
-                                             offset, len, domain);
+					     offset, len, domain);
     loadedClasses.put(retval.getName(), retval);
     return retval;
   }
diff --git a/libjava/java/lang/Compiler.java b/libjava/java/lang/Compiler.java
index f520a7e0dda2..858f63ee9933 100644
--- a/libjava/java/lang/Compiler.java
+++ b/libjava/java/lang/Compiler.java
@@ -1,5 +1,5 @@
 /* Compiler.java -- placeholder for Java-to-native runtime compilers
-   Copyright (C) 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2001, 2002, 2004 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -76,8 +76,7 @@ public final class Compiler
    */
   public static boolean compileClass(Class oneClass)
   {
-    // Never succeed.
-    return false;
+    return VMCompiler.compileClass(oneClass);
   }
 
   /**
@@ -90,8 +89,7 @@ public final class Compiler
    */
   public static boolean compileClasses(String classNames)
   {
-    // Note the incredibly lame interface.  Always fail.
-    return false;
+    return VMCompiler.compileClasses(classNames);
   }
 
   /**
@@ -105,8 +103,7 @@ public final class Compiler
    */
   public static Object command(Object arg)
   {
-    // Our implementation defines this to a no-op.
-    return null;
+    return VMCompiler.command(arg);
   }
 
   /**
@@ -116,6 +113,7 @@ public final class Compiler
    */
   public static void enable()
   {
+    VMCompiler.enable();
   }
 
   /**
@@ -124,5 +122,6 @@ public final class Compiler
    */
   public static void disable()
   {
+    VMCompiler.disable();
   }
 }
diff --git a/libjava/java/lang/SecurityManager.java b/libjava/java/lang/SecurityManager.java
index 2e82a475b5f9..972b312d9436 100644
--- a/libjava/java/lang/SecurityManager.java
+++ b/libjava/java/lang/SecurityManager.java
@@ -324,7 +324,7 @@ public class SecurityManager
   public void checkPermission(Permission perm)
   {
     // XXX Should be: AccessController.checkPermission(perm);
-    throw new SecurityException("Operation not allowed");
+    //.throw new SecurityException("Operation not allowed");
   }
 
   /**
@@ -553,7 +553,7 @@ public class SecurityManager
     //   throw new SecurityException("Missing context");
     // AccessControlContext ac = (AccessControlContext) context;
     // ac.checkPermission(new FilePermission(filename, "read"));
-    throw new SecurityException("Cannot read files via file names.");
+    // throw new SecurityException("Cannot read files via file names.");
   }
 
   /**
@@ -677,7 +677,7 @@ public class SecurityManager
     //   // Use the toString() hack to do the null check.
     //   ac.checkPermission(new SocketPermission(host.toString + ":" +port,
     //                                           "connect"));
-    throw new SecurityException("Cannot make network connections.");
+    // throw new SecurityException("Cannot make network connections.");
   }
 
   /**
diff --git a/libjava/java/lang/VMClassLoader.java b/libjava/java/lang/VMClassLoader.java
index ac7a05e3cd9f..8f78f9bb6666 100644
--- a/libjava/java/lang/VMClassLoader.java
+++ b/libjava/java/lang/VMClassLoader.java
@@ -97,44 +97,31 @@ final class VMClassLoader
 					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;
   }
 
   /**
diff --git a/libjava/java/lang/VMCompiler.java b/libjava/java/lang/VMCompiler.java
new file mode 100644
index 000000000000..98efc7ee44fc
--- /dev/null
+++ b/libjava/java/lang/VMCompiler.java
@@ -0,0 +1,332 @@
+/* VMClassLoader.java -- Reference implementation of compiler interface
+   Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.security.MessageDigest;
+import java.security.ProtectionDomain;
+import java.security.NoSuchAlgorithmException;
+import java.util.WeakHashMap;
+import java.util.HashSet;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import gnu.gcj.runtime.SharedLibHelper;
+import gnu.gcj.runtime.PersistentByteMap;
+
+/**
+ * This class is just a per-VM reflection of java.lang.Compiler.
+ * All methods are defined identically.
+ */
+final class VMCompiler
+{
+  // True if we want to use gcj-jit.
+  public static boolean useCompiler = true;
+
+  // True if we're able to use gcj-jit.
+  public static final boolean canUseCompiler;
+
+  // Compiler to use.
+  public static String gcjJitCompiler;
+
+  // Compiler options.
+  public static String gcjJitCompilerOptions;
+
+  // Temporary directory to use.
+  public static String gcjJitTmpdir;
+
+  // This maps a ClassLoader to a set of SharedLibHelper objects that
+  // it has used.  We do things this way to ensure that a
+  // SharedLibHelper is collected if and only if the ClassLoader is.
+  private static WeakHashMap sharedHelperMap = new WeakHashMap();
+
+  private static Vector precompiledMapFiles;
+
+  static
+  {
+    gcjJitCompiler = System.getProperty("gnu.gcj.jit.compiler");
+    if (gcjJitCompiler == null)
+      canUseCompiler = false;
+    else
+      {
+	gcjJitCompilerOptions = System.getProperty("gnu.gcj.jit.options",
+						   "-g");
+	gcjJitTmpdir = System.getProperty("gnu.gcj.jit.cachedir");
+	// Note that we *don't* choose java.io.tmpdir as a default --
+	// that would allow easy attacks against the VM.
+	if (gcjJitTmpdir == null)
+	  canUseCompiler = false;
+	else
+	  canUseCompiler = true;
+      }
+
+    String prop = System.getProperty ("gnu.gcj.precompiled.db.path");
+    if (prop != null)
+      {
+	precompiledMapFiles = new Vector();
+	// Add the 
+	StringTokenizer st
+	  = new StringTokenizer (prop,
+				 System.getProperty ("path.separator", ":"));
+	{
+	  while (st.hasMoreElements ()) 
+	    {  
+	      String e = st.nextToken ();
+	      try
+		{
+		  PersistentByteMap map 
+		    = new PersistentByteMap
+		    (e, PersistentByteMap.AccessMode.READ_ONLY);
+		  precompiledMapFiles.add(map);
+		}
+	      catch (IllegalArgumentException _)
+		{
+		  // Not a map file	      
+		}
+	      catch (java.io.IOException _)
+		{
+		}
+	    }
+	}
+      }
+  }
+
+  /**
+   * Don't allow new `Compiler's to be made.
+   */
+  private VMCompiler()
+  {
+  }
+
+  private static Class loadSharedLibrary(ClassLoader loader,
+					 String fileName,
+					 ProtectionDomain domain,
+					 String className)
+  {
+    Class c = null;
+    SharedLibHelper helper 
+      = SharedLibHelper.findHelper (loader, fileName, domain.getCodeSource());
+    c = helper.findClass (className);
+    if (c != null)
+      {
+	HashSet hs = (HashSet) sharedHelperMap.get(loader);
+	if (hs == null)
+	  {
+	    hs = new HashSet();
+	    sharedHelperMap.put(loader, hs);
+	  }
+	hs.add(helper);
+      }
+    return c;
+  }
+
+  /**
+   * Compile a class given the bytes for it.  Returns the Class, or
+   * null if compilation failed or otherwise could not be done.
+   */
+  public static Class compileClass(ClassLoader loader,
+				   String name, byte[] data,
+				   int offset, int len,
+				   ProtectionDomain domain)
+  {
+    if (precompiledMapFiles == null
+	&& (! useCompiler || ! canUseCompiler))
+      return null;
+
+    byte digest[];
+
+    try
+      {
+	MessageDigest md = MessageDigest.getInstance("MD5");
+	digest = md.digest(data);
+      }
+    catch (NoSuchAlgorithmException _)
+      {
+	return null;
+      }
+
+    // We use lookaside cache files to determine whether these bytes
+    // correspond to a class file that is part of a precompiled DSO.
+    if (precompiledMapFiles != null)
+      {
+	try
+	  {
+	    Enumeration elements = precompiledMapFiles.elements();
+	    while (elements.hasMoreElements())
+	      {
+		PersistentByteMap map = (PersistentByteMap)elements.nextElement();
+		byte[] soName = map.get(digest);
+		if (soName != null)
+		  return loadSharedLibrary(loader, 
+					   new String(soName), 
+					   domain, name);
+	      }
+	  }
+	catch (Exception _)
+	  {
+	  }
+      }
+ 
+    if (! useCompiler || ! canUseCompiler)
+      return null;
+
+    try
+      {
+	// FIXME: Make sure that the class represented by the
+	// bytes in DATA really is the class named in NAME.  Make
+	// sure it's not "java.*".
+	StringBuffer hexBytes = new StringBuffer(gcjJitTmpdir);
+	hexBytes.append(File.separatorChar);
+	int digestLength = digest.length;
+	for (int i = 0; i < digestLength; ++i)
+	  hexBytes.append(Integer.toHexString(digest[i] & 0xff));
+
+	// FIXME: use System.mapLibraryName?
+	// I'm thinking we should use that, plus a class specified
+	// via a property that determines lookup policy.
+	File soFile = new File(hexBytes + ".so");
+	if (soFile.isFile())
+          return loadSharedLibrary (loader, soFile.toString(), domain,
+				    name);
+
+	File classFile = new File(hexBytes + ".class");
+	classFile.delete();
+	if (classFile.createNewFile() != true)	  
+	  return null;
+
+	FileOutputStream f = new FileOutputStream (classFile);
+	// FIXME: race condition if bytes change... ?
+	f.write(data, offset, len);
+
+	// Invoke the compiler.
+	StringBuffer command = new StringBuffer(gcjJitCompiler);
+	command.append(" ");
+	command.append(classFile);
+	command.append(" ");
+	command.append(gcjJitCompilerOptions);
+	// These options are required.
+	command.append(" -findirect-dispatch -fjni -shared -fPIC -o ");
+	command.append(soFile);
+	Process p = Runtime.getRuntime().exec(command.toString());
+
+	// Read the process' stderr into a string.
+	StringBuffer err = new StringBuffer();
+	InputStreamReader stderr = new InputStreamReader (p.getErrorStream());
+	char[] inBuf = new char[500];
+	int bytesRead;
+	while ((bytesRead = stderr.read (inBuf)) != -1)
+	  err.append(inBuf, 0, bytesRead);
+
+	if (p.waitFor() != 0)
+	  {
+	    // FIXME: we could log err.toString() somewhere...
+	    return null;
+	  }
+
+	return loadSharedLibrary(loader, soFile.toString(), domain, name);
+      }
+    catch (Exception _)
+      {
+	return null;
+      }
+  }
+
+  /**
+   * Compile the class named by <code>oneClass</code>.
+   *
+   * @param oneClass the class to compile
+   * @return <code>false</code> if no compiler is available or
+   *         compilation failed, <code>true</code> if compilation succeeded
+   * @throws NullPointerException if oneClass is null
+   */
+  public static boolean compileClass(Class oneClass)
+  {
+    // Never succeed.
+    return false;
+  }
+
+  /**
+   * Compile the classes whose name matches <code>classNames</code>.
+   *
+   * @param classNames the name of classes to compile
+   * @return <code>false</code> if no compiler is available or
+   *         compilation failed, <code>true</code> if compilation succeeded
+   * @throws NullPointerException if classNames is null
+   */
+  public static boolean compileClasses(String classNames)
+  {
+    // Note the incredibly lame interface.  Always fail.
+    return false;
+  }
+
+  /**
+   * This method examines the argument and performs an operation
+   * according to the compilers documentation.  No specific operation
+   * is required.
+   *
+   * @param arg a compiler-specific argument
+   * @return a compiler-specific value, including null
+   * @throws NullPointerException if the compiler doesn't like a null arg
+   */
+  public static Object command(Object arg)
+  {
+    // Our implementation defines this to a no-op.
+    return null;
+  }
+
+  /**
+   * Calling <code>Compiler.enable()</code> will cause the compiler
+   * to resume operation if it was previously disabled; provided that a
+   * compiler even exists.
+   */
+  public static void enable()
+  {
+    useCompiler = true;
+  }
+
+  /**
+   * Calling <code>Compiler.disable()</code> will cause the compiler
+   * to be suspended; provided that a compiler even exists.
+   */
+  public static void disable()
+  {
+    useCompiler = false;
+  }
+}
diff --git a/libjava/java/lang/VMSecurityManager.java b/libjava/java/lang/VMSecurityManager.java
index f6f0645ac753..604f8ecb428e 100644
--- a/libjava/java/lang/VMSecurityManager.java
+++ b/libjava/java/lang/VMSecurityManager.java
@@ -54,11 +54,12 @@ class VMSecurityManager
     // The docs above are wrong.  See the online docs.
     // FIXME this implementation is a bit wrong too -- the docs say we
     // must also consider ancestors of the system class loader.
+    ClassLoader systemClassLoader = VMClassLoader.getSystemClassLoader();
     Class[] classStack = getClassContext ();
     for (int i = 0; i < classStack.length; i++)
       {
 	ClassLoader loader = classStack[i].getClassLoader();
-	if (loader != null)
+	if (loader != null && loader != systemClassLoader)
 	  return loader;
       }
 
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc
index 920245cd586f..0e9c26c7b4fa 100644
--- a/libjava/java/lang/natClass.cc
+++ b/libjava/java/lang/natClass.cc
@@ -14,6 +14,7 @@ details.  */
 #include <limits.h>
 #include <string.h>
 #include <stddef.h>
+#include <stdio.h>
 
 #pragma implementation "Class.h"
 
@@ -56,16 +57,17 @@ details.  */
 #include <gcj/method.h>
 #include <gnu/gcj/runtime/MethodRef.h>
 #include <gnu/gcj/RawData.h>
+#include <java/lang/VerifyError.h>
 
 #include <java-cpool.h>
 #include <java-interp.h>
+#include <java-assert.h>
+#include <execution.h>
 
 
 
 using namespace gcj;
 
-bool gcj::verbose_class_flag;
-
 jclass
 java::lang::Class::forName (jstring className, jboolean initialize,
                             java::lang::ClassLoader *loader)
@@ -485,7 +487,12 @@ java::lang::Class::getInterfaces (void)
   jobjectArray r = JvNewObjectArray (interface_count, getClass (), NULL);
   jobject *data = elements (r);
   for (int i = 0; i < interface_count; ++i)
-    data[i] = interfaces[i];
+    {
+      typedef unsigned int uaddr __attribute__ ((mode (pointer)));
+      data[i] = interfaces[i];
+      if ((uaddr)data[i] < (uaddr)constants.size)
+	fprintf (stderr, "ERROR !!!\n");
+    }
   return reinterpret_cast<JArray<jclass> *> (r);
 }
 
@@ -495,7 +502,8 @@ java::lang::Class::_getMethod (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())
+
+   for (Class *klass = this; klass; klass = klass->getSuperclass())
     {
       int i = klass->isPrimitive () ? 0 : klass->method_count;
       while (--i >= 0)
@@ -699,10 +707,7 @@ java::lang::Class::newInstance (void)
 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
@@ -710,67 +715,37 @@ java::lang::Class::finalize (void)
 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);
+  // Step 1.  We introduce a new scope so we can synchronize more
+  // easily.
+  {
+    JvSynchronize sync (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();
-  // FIXME: `self' can be null at startup.  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);
+    if (state < JV_STATE_LINKED)
+      java::lang::VMClassLoader::resolveClass (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 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_Linker::wait_for_state (this, JV_STATE_LINKED);
+    state = JV_STATE_IN_PROGRESS;
+  }
 
   // Step 7.
   if (! isInterface () && superclass)
@@ -782,24 +757,13 @@ java::lang::Class::initializeClass (void)
       catch (java::lang::Throwable *except)
 	{
 	  // Caught an exception.
-	  _Jv_MonitorEnter (this);
+	  JvSynchronize sync (this);
 	  state = JV_STATE_ERROR;
 	  notifyAll ();
-	  _Jv_MonitorExit (this);
 	  throw except;
 	}
     }
 
-  _Jv_PrepareConstantTimeTables (this);
-
-  if (vtable == NULL)
-    _Jv_MakeVTable(this);
-
-  if (otable || atable)
-    _Jv_LinkSymbolTable(this);
-
-  _Jv_linkExceptionClassTable (this);
-
   // Steps 8, 9, 10, 11.
   try
     {
@@ -821,17 +785,91 @@ java::lang::Class::initializeClass (void)
 	      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;
 }
 
 
@@ -857,14 +895,19 @@ _Jv_GetMethodLocal (jclass klass, _Jv_Utf8Const *name,
 
 _Jv_Method *
 _Jv_LookupDeclaredMethod (jclass klass, _Jv_Utf8Const *name,
-                          _Jv_Utf8Const *signature)
+                          _Jv_Utf8Const *signature,
+			  jclass *declarer_result)
 {
   for (; klass; klass = klass->getSuperclass())
     {
       _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature);
 
       if (meth)
-        return meth;
+	{
+	  if (declarer_result)
+	    *declarer_result = klass;
+	  return meth;
+	}
     }
 
   return NULL;
@@ -886,7 +929,7 @@ _Jv_FindMethodInCache (jclass klass,
                        _Jv_Utf8Const *name,
                        _Jv_Utf8Const *signature)
 {
-  int index = name->hash16() & MCACHE_SIZE;
+  int index = name->hash16 () & MCACHE_SIZE;
   _Jv_mcache *mc = method_cache + index;
   _Jv_Method *m = mc->method;
 
@@ -904,7 +947,7 @@ _Jv_AddMethodToCache (jclass klass,
 {
   _Jv_MonitorEnter (&java::lang::Class::class$); 
 
-  int index = method->name->hash16() & MCACHE_SIZE;
+  int index = method->name->hash16 () & MCACHE_SIZE;
 
   method_cache[index].method = method;
   method_cache[index].klass = klass;
@@ -1085,898 +1128,104 @@ _Jv_CheckArrayStore (jobject arr, jobject obj)
     }
 }
 
-#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)
+jboolean
+_Jv_IsAssignableFromSlow (jclass target, jclass source)
 {
-  for (int i=0; i < list_len; i++)
+  // First, strip arrays.
+  while (target->isArray ())
     {
-      if (list[i] == item)
-        return i;
+      // If target is array, source must be as well.
+      if (! source->isArray ())
+       return false;
+      target = target->getComponentType ();
+      source = source->getComponentType ();
     }
-  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);
+  // Quick success.
+  if (target == &java::lang::Object::class$)
+    return true;
 
-      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++;
+  // Ensure that the classes have their supers installed.
+  _Jv_Linker::wait_for_state (source, JV_STATE_LOADING);
+  _Jv_Linker::wait_for_state (target, JV_STATE_LOADING);
 
-	  result += _Jv_GetInterfaces (klass->interfaces[i], ifaces);
-	}
-    }
-    
-  if (klass->isInterface())
-    {
-      result += klass->method_count + 1;
-    }
-  else
+  do
     {
-      if (klass->superclass)
-        {
-	  result += _Jv_GetInterfaces (klass->superclass, ifaces);
-	}
+      if (source == target)
+       return true;
+
+      if (target->isPrimitive () || source->isPrimitive ())
+       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;
+           }
+       }
+      source = source->getSuperclass ();
     }
-  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 = klass->name->toString();
-  r = r->concat (JvNewStringUTF ("."));
-  r = r->concat (name->toString());
-  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;
-	}
+  while (source != NULL);
 
-      if (meth && (meth->name->first() == '<'))
-	{
-	  // 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;
+  return false;
 }
 
-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.
+// 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.
 //
-// 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)
+// 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,  
+			const _Jv_Utf8Const *utf_sig)
 {
-  int hash = name->hashCode ();
-
-  java::lang::reflect::Field* rfield;
-  for (int i = 0;  i < field_count;  i++)
+   for (jclass klass = search_class; klass; klass = klass->getSuperclass())
     {
-      _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;
+      // FIXME: Throw an exception?
+      if (!klass->isInterface ())
+	return false;
+      
+      int i = 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))
+	      && _Jv_equalUtf8Consts (klass->methods[i].signature, utf_sig))
 	    {
 	      // 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;
-}
-
-// Functions for indirect dispatch (symbolic virtual binding) support.
-
-// There are two tables, atable and otable.  atable is an array of
-// addresses, and otable is an array of offsets, and these are used
-// for static and virtual members respectively.
-
-// {a,o}table_syms is an array of _Jv_MethodSymbols.  Each such symbol
-// is a tuple of {classname, member name, signature}.
-// _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;
-
-  for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++)
-    {
-      // FIXME: Why are we passing NULL as the class loader?
-      jclass target_class = _Jv_FindClass (sym.class_name, NULL);
-      _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)
-	continue;
-
-      if (target_class->isInterface())
-	{
-	  // FIXME: This does not yet fully conform to binary compatibility
-	  // rules. It will break if a declaration is moved into a 
-	  // superinterface.
-	  for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
-	    {
-	      for (int i=0; i < cls->method_count; i++)
-		{
-		  meth = &cls->methods[i];
-		  if (_Jv_equalUtf8Consts (sym.name, meth->name)
-		      && _Jv_equalUtf8Consts (signature, meth->signature))
-		    {
-		      klass->otable->offsets[index] = i + 1;
-		      goto found;
-		    }
-		}
-	    
-	    }
-	found:
-	  continue;
-	}
-
-      // We're looking for a field or a method, and we can tell
-      // which is needed by looking at the signature.
-      if (signature->first() == '(' && signature->len() >= 2)
-	{
- 	  // 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);
-	    }
-		
-	  meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
-					  sym.signature);
-		
-	  if (meth != NULL)
-	    {
-	      klass->otable->offsets[index] = 
-		_Jv_VTable::idx_to_offset (meth->index);	      
-	    }
-
-	  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 ())
-		  _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;
-		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)
-    return;
-
-  klass->atable->state = 1;
-
-  for (index = 0; sym = klass->atable_syms[index], sym.name != NULL; index++)
-    {
-      // FIXME: Why are we passing NULL as the class loader?
-      jclass target_class = _Jv_FindClass (sym.class_name, NULL);
-      _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)
-	continue;
-      
-      // 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->first() == '(' && signature->len() >= 2)
-	{
- 	  // 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);
-	    }
-	  
-	  meth = _Jv_LookupDeclaredMethod(target_class, sym.name,
-					  sym.signature);
-	  
-	  if (meth != NULL)
-	    {
-	      if (meth->ncode) // Maybe abstract?
-		klass->atable->addresses[index] = meth->ncode;
-#ifdef INTERPRETER
-	      else if (_Jv_IsInterpretedClass (target_class))
-		_Jv_Defer_Resolution (target_class, meth, 
-				      &klass->atable->addresses[index]);
-#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 ())
-		  _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;
-		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));
-	  }
-      }
-    }
-}
-
-
-// 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)
-    {
-      jclass target_class = _Jv_FindClass (catch_record->classname,  
-					   self->getClassLoaderInternal ());
-      *catch_record->address = target_class;
-      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->superclass;
-
-  typedef unsigned int uaddr __attribute__ ((mode (pointer)));
+	      // FIXME: Method must be public.  Throw an exception?
+	      if (! Modifier::isPublic (klass->methods[i].accflags))
+		break;
 
-  // If superclass looks like a constant pool entry,
-  // resolve it now.
-  if ((uaddr) superclass < (uaddr) klass->constants.size)
-    {
-      if (klass->state < JV_STATE_LINKED)
-	{
-	  _Jv_Utf8Const *name = klass->constants.data[(uaddr) superclass].utf8;
-	  superclass = _Jv_FindClass (name, klass->loader);
-	  if (! superclass)
-	    {
-	      throw new java::lang::NoClassDefFoundError (name->toString());
+	      found_class = klass;
+	      // Interface method indexes count from 1.
+	      index = i+1;
+	      return true;
 	    }
 	}
-      else
-	superclass = klass->constants.data[(uaddr) superclass].clazz;
-    }
-
-  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;
-
-      // FIXME: Must check that we don't override:
-      // - Package-private method where superclass is in different package.
-      // - Final or less-accessible declaration in superclass (check binary 
-      //   spec, do we allocate new vtable entry or put throw node in vtable?)
-      // - Static or private method in superclass.
-
-      if (superclass != NULL)
-	{
-	  super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name, 
-						 meth->signature);
-	}
-
-      if (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)
+  // If we haven't found a match, and this class is an interface, then
+  // check all the superinterfaces.
+  if (search_class->isInterface())
     {
-      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)
+      for (int i = 0; i < search_class->interface_count; ++i)
 	{
-	  vtable->set_method (i, superclass->vtable->get_method (i));
-	  flags[i] = true;
+	  using namespace java::lang::reflect;
+	  bool found = _Jv_getInterfaceMethod (search_class->interfaces[i], 
+					   found_class, index,
+					   utf_name, utf_sig);
+	  if (found)
+	    return 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 ();
-	  }
-    }
+  return false;
 }
diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc
index 5a0898a93c4e..dd5cd463cfaa 100644
--- a/libjava/java/lang/natClassLoader.cc
+++ b/libjava/java/lang/natClassLoader.cc
@@ -18,6 +18,7 @@ details.  */
 
 #include <gcj/cni.h>
 #include <jvm.h>
+#include <execution.h>
 
 #include <java-threads.h>
 #include <java-interp.h>
@@ -33,6 +34,7 @@ details.  */
 #include <java/lang/ClassNotFoundException.h>
 #include <java/lang/ClassCircularityError.h>
 #include <java/lang/IncompatibleClassChangeError.h>
+#include <java/lang/ClassFormatError.h>
 #include <java/lang/VirtualMachineError.h>
 #include <java/lang/VMClassLoader.h>
 #include <java/lang/reflect/Modifier.h>
@@ -41,156 +43,6 @@ details.  */
 #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 (klass->state == JV_STATE_COMPILED)
-    {
-      klass->state = JV_STATE_LOADED;
-      if (gcj::verbose_class_flag)
-	fprintf (stderr, "[Loaded (pre-compiled) %s]\n", klass->name->chars());
-    }
-  if (state == JV_STATE_LINKED)
-    {
-      // Must call _Jv_PrepareCompiledClass while holding the class
-      // mutex.
-#ifdef INTERPRETER
-      if (_Jv_IsInterpretedClass (klass))
-	_Jv_PrepareClass (klass);
-#endif
-      _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)
-{
-  jint state = klass->state;
-  if (state >= JV_STATE_LINKED)
-    return;
-
-  // 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->first() == '[')
-	    found = _Jv_FindClassFromSignature (name->chars(),
-						klass->loader);
-	  else
-	    found = _Jv_FindClass (name, klass->loader);
-		
-	  if (! found)
-	    {
-	      jstring str = name->toString();
-	      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 < pool->size)
-    klass->superclass = pool->data[(uaddr) klass->superclass].clazz;
-
-  // Likewise for interfaces.
-  for (int i = 0; i < klass->interface_count; i++)
-    if ((uaddr) klass->interfaces[i] < pool->size)
-      klass->interfaces[i] = pool->data[(uaddr) 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 */
-
-  if (klass->isInterface ())
-    _Jv_LayoutInterfaceMethods (klass);
-
-  if (state == JV_STATE_COMPILED && gcj::verbose_class_flag)
-    fprintf (stderr, "[Loaded (pre-compiled) %s]\n",
-	     klass->name->chars());
-
-  klass->notifyAll ();
-
-  _Jv_PushClass (klass);
-}
-
-
 //
 //  A single class can have many "initiating" class loaders,
 //  and a single "defining" class loader.  The Defining
@@ -221,6 +73,8 @@ static _Jv_LoaderInfo *initiated_classes[HASH_LEN];
 static jclass loaded_classes[HASH_LEN];
 
 // This is the root of a linked list of classes
+static jclass stack_head;
+
 
 
 
@@ -323,11 +177,6 @@ _Jv_RegisterClasses (const jclass *classes)
       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;
     }
 }
 
@@ -341,11 +190,6 @@ _Jv_RegisterClasses_Counted (const jclass * classes, size_t count)
       jclass klass = classes[i];
 
       (*_Jv_RegisterClassHook) (klass);
-
-      // registering a compiled class causes
-      // it to be immediately "prepared".  
-      if (klass->state == JV_STATE_NOTHING)
-	klass->state = JV_STATE_COMPILED;
     }
 }
 
@@ -354,8 +198,10 @@ _Jv_RegisterClassHookDefault (jclass klass)
 {
   jint hash = HASH_UTF (klass->name);
 
-  jclass check_class = loaded_classes[hash];
-
+  // The BC ABI makes this check unnecessary: we always resolve all
+  // data references via the appropriate class loader, so the kludge
+  // that required this check has gone.
+#if 0
   // If the class is already registered, don't re-register it.
   while (check_class != NULL)
     {
@@ -381,7 +227,11 @@ _Jv_RegisterClassHookDefault (jclass klass)
 
       check_class = check_class->next;
     }
+#endif
 
+  // FIXME: this is really bogus!
+  if (! klass->engine)
+    klass->engine = &_Jv_soleCompiledEngine;
   klass->next = loaded_classes[hash];
   loaded_classes[hash] = klass;
 }
@@ -442,7 +292,7 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
     {
       // 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_Linker::wait_for_state (klass, JV_STATE_LOADED);
     }
 
   return klass;
@@ -555,7 +405,7 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
   // cache one and reuse it. It is not necessary to synchronize this.
   if (!array_idt)
     {
-      _Jv_PrepareConstantTimeTables (array_class);
+      _Jv_Linker::wait_for_state(array_class, JV_STATE_PREPARED);
       array_idt = array_class->idt;
       array_depth = array_class->depth;
       array_ancestors = array_class->ancestors;
@@ -569,19 +419,19 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
 
   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
@@ -591,8 +441,6 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
   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.
diff --git a/libjava/java/lang/natRuntime.cc b/libjava/java/lang/natRuntime.cc
index 1e57f50113dc..332f2c7b625d 100644
--- a/libjava/java/lang/natRuntime.cc
+++ b/libjava/java/lang/natRuntime.cc
@@ -1,6 +1,6 @@
 // natRuntime.cc - Implementation of native side of Runtime class.
 
-/* 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.
 
@@ -388,8 +388,11 @@ java::lang::Runtime::insertSystemProperties (java::util::Properties *newprops)
 	newprops->put(JvNewStringLatin1 (Prop), JvNewStringLatin1 (Val))
 
   // A mixture of the Java Product Versioning Specification
-  // (introduced in 1.2), and earlier versioning properties.
-  SET ("java.version", GCJVERSION);
+  // (introduced in 1.2), and earlier versioning properties.  Some
+  // programs rely on seeing values that they expect, so we claim to
+  // be a 1.4-ish VM for their sake.
+  SET ("java.version", "1.4.2");
+  SET ("java.runtime.version", "1.4.2");
   SET ("java.vendor", "Free Software Foundation, Inc.");
   SET ("java.vendor.url", "http://gcc.gnu.org/java/");
   SET ("java.class.version", "46.0");
@@ -399,7 +402,7 @@ java::lang::Runtime::insertSystemProperties (java::util::Properties *newprops)
   SET ("java.vm.version", __VERSION__);
   SET ("java.vm.vendor", "Free Software Foundation, Inc.");
   SET ("java.vm.name", "GNU libgcj");
-  SET ("java.specification.version", "1.3");
+  SET ("java.specification.version", "1.4");
   SET ("java.specification.name", "Java(tm) Platform API Specification");
   SET ("java.specification.vendor", "Sun Microsystems Inc.");
 
diff --git a/libjava/java/lang/natString.cc b/libjava/java/lang/natString.cc
index cba0976bd959..e2558f4f7473 100644
--- a/libjava/java/lang/natString.cc
+++ b/libjava/java/lang/natString.cc
@@ -1,7 +1,6 @@
 // natString.cc - Implementation of java.lang.String native methods.
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
-   Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -57,7 +56,7 @@ static int strhash_size = 0;  /* Number of slots available in strhash.
 jstring*
 _Jv_StringFindSlot (jchar* data, jint len, jint hash)
 {
-  JvSynchronize sync (&StringClass);
+  JvSynchronize sync (&java::lang::String::class$);
 
   int start_index = hash & (strhash_size - 1);
   int deleted_index = -1;
@@ -120,7 +119,7 @@ _Jv_StringGetSlot (jstring str)
 static void
 rehash ()
 {
-  JvSynchronize sync (&StringClass);
+  JvSynchronize sync (&java::lang::String::class$);
 
   if (strhash == NULL)
     {
@@ -167,7 +166,7 @@ rehash ()
 jstring
 java::lang::String::intern()
 {
-  JvSynchronize sync (&StringClass);
+  JvSynchronize sync (&java::lang::String::class$);
   if (3 * strhash_count >= 2 * strhash_size)
     rehash();
   jstring* ptr = _Jv_StringGetSlot(this);
@@ -194,7 +193,7 @@ java::lang::String::intern()
 void
 _Jv_FinalizeString (jobject obj)
 {
-  JvSynchronize sync (&StringClass);
+  JvSynchronize sync (&java::lang::String::class$);
 
   // We might not actually have intern()d any strings at all, if
   // we're being called from Reference.
@@ -286,9 +285,9 @@ _Jv_NewStringUtf8Const (Utf8Const* str)
     }
   chrs -= length;
 
-  JvSynchronize sync (&StringClass);
+  JvSynchronize sync (&java::lang::String::class$);
   if (3 * strhash_count >= 2 * strhash_size)
-    rehash ();
+    rehash();
   jstring* ptr = _Jv_StringFindSlot (chrs, length, hash);
   if (*ptr != NULL && *ptr != DELETED_STRING)
     return (jstring) UNMASK_PTR (*ptr);
@@ -527,7 +526,7 @@ java::lang::String::equals(jobject anObject)
     return false;
   if (anObject == this)
     return true;
-  if (anObject->getClass() != &StringClass)
+  if (anObject->getClass() != &java::lang::String::class$)
     return false;
   jstring other = (jstring) anObject;
   if (count != other->count)
diff --git a/libjava/java/lang/natVMClassLoader.cc b/libjava/java/lang/natVMClassLoader.cc
index 1ed3851fbb35..841b3e0789e1 100644
--- a/libjava/java/lang/natVMClassLoader.cc
+++ b/libjava/java/lang/natVMClassLoader.cc
@@ -22,6 +22,7 @@ details.  */
 #include <java-interp.h>
 
 #include <java/lang/VMClassLoader.h>
+#include <java/lang/VMCompiler.h>
 #include <gnu/gcj/runtime/VMClassLoader.h>
 #include <java/lang/ClassLoader.h>
 #include <java/lang/Class.h>
@@ -29,6 +30,21 @@ details.  */
 #include <java/security/ProtectionDomain.h>
 #include <java/lang/ClassFormatError.h>
 
+void
+java::lang::VMClassLoader::resolveClass (jclass klass)
+{
+  JvSynchronize sync (klass);
+  try
+    {
+      _Jv_Linker::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,
@@ -37,72 +53,61 @@ java::lang::VMClassLoader::defineClass (java::lang::ClassLoader *loader,
 					jint length,
 					java::security::ProtectionDomain *pd)
 {
-#ifdef INTERPRETER
-  jclass klass;
-  klass = new java::lang::Class ();
-  klass->aux_info = (void *) _Jv_AllocBytes (sizeof (_Jv_InterpClass));
-
-  // Synchronize on the class, so that it is not attempted initialized
-  // until we're done loading.
-  JvSynchronize sync (klass);
-
-  // Record the defining loader.  For the system class loader, we
-  // record NULL.
-  if (loader != java::lang::ClassLoader::getSystemClassLoader())
-    klass->loader = loader;
-
-  if (name != 0)
-    {
-      _Jv_Utf8Const *name2 = _Jv_makeUtf8Const (name);
-
-      if (! _Jv_VerifyClassName (name2))
-	throw new java::lang::ClassFormatError
-	  (JvNewStringLatin1 ("erroneous class name"));
-
-      klass->name = name2;
-    }
+  jclass klass = VMCompiler::compileClass(loader, name, data,
+					  offset, length, pd);
 
-  try
+  if (klass != NULL)
     {
-      _Jv_DefineClass (klass, data, offset, length);
+      JvSynchronize sync (&java::lang::Class::class$);
+      _Jv_RegisterClass (klass);
     }
-  catch (java::lang::Throwable *ex)
+#ifdef INTERPRETER
+  else
     {
-      klass->state = JV_STATE_ERROR;
-      klass->notifyAll ();
-
-      _Jv_UnregisterClass (klass);
-
-      // If EX is not a ClassNotFoundException, that's ok, because we
-      // account for the possibility in defineClass().
-      throw ex;
+      klass = new java::lang::Class ();
+
+      // Synchronize on the class, so that it is not attempted initialized
+      // until we're done loading.
+      JvSynchronize sync (klass);
+
+      // Record the defining loader.  For the system class loader, we
+      // record NULL.
+      if (loader != java::lang::ClassLoader::getSystemClassLoader())
+	klass->loader = loader;
+
+      if (name != 0)
+	{
+	  _Jv_Utf8Const *name2 = _Jv_makeUtf8Const (name);
+
+	  if (! _Jv_VerifyClassName (name2))
+	    throw new java::lang::ClassFormatError
+	      (JvNewStringLatin1 ("erroneous class name"));
+
+	  klass->name = name2;
+	}
+
+      try
+	{
+	  _Jv_DefineClass (klass, data, offset, length, pd);
+	}
+      catch (java::lang::Throwable *ex)
+	{
+	  klass->state = JV_STATE_ERROR;
+	  klass->notifyAll ();
+
+	  _Jv_UnregisterClass (klass);
+
+	  // If EX is not a ClassNotFoundException, that's ok, because we
+	  // account for the possibility in defineClass().
+	  throw ex;
+	}
+
+      // if everything proceeded sucessfully, we're loaded.
+      JvAssert (klass->state == JV_STATE_LOADED);
     }
-    
-  klass->protectionDomain = pd;
-
-  // if everything proceeded sucessfully, we're loaded.
-  JvAssert (klass->state == JV_STATE_LOADED);
+#endif // INTERPRETER
 
   return klass;
-
-#else // INTERPRETER
-
-  return 0;
-#endif
-}
-
-// 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 *
@@ -125,9 +130,16 @@ jclass
 java::lang::VMClassLoader::loadClass(jstring name, jboolean resolve)
 {
   _Jv_Utf8Const *utf = _Jv_makeUtf8Const (name);
-  // FIXME: we culd make _Jv_FindClassFromSignature a template.
   jclass klass = _Jv_FindClassInCache (utf, NULL);
-  if (klass && resolve)
-    _Jv_InitClass (klass);
+  if (klass)
+    {
+      // We never want to return a class without its supers linked.
+      // It isn't clear from the spec, but this is what other
+      // implementations do in practice.
+      if (resolve)
+	_Jv_InitClass (klass);
+      else
+	_Jv_Linker::wait_for_state (klass, JV_STATE_LOADING);
+    }
   return klass;
 }
diff --git a/libjava/java/lang/reflect/natField.cc b/libjava/java/lang/reflect/natField.cc
index 469cf74de8ef..7eb032227abc 100644
--- a/libjava/java/lang/reflect/natField.cc
+++ b/libjava/java/lang/reflect/natField.cc
@@ -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 @@ java::lang::reflect::Field::getType ()
 {
   jfieldID fld = _Jv_FromReflectedField (this);
   JvSynchronize sync (declaringClass);
-  _Jv_ResolveField (fld, declaringClass->getClassLoaderInternal ());
+  _Jv_Linker::resolve_field (fld, declaringClass->getClassLoaderInternal ());
   return fld->type;
 }
 
diff --git a/libjava/java/lang/reflect/natMethod.cc b/libjava/java/lang/reflect/natMethod.cc
index 8c6efc487cdf..b194067300b3 100644
--- a/libjava/java/lang/reflect/natMethod.cc
+++ b/libjava/java/lang/reflect/natMethod.cc
@@ -1,6 +1,6 @@
 // natMethod.cc - Native code for Method class.
 
-/* 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.
 
@@ -149,7 +149,6 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
     getType ();
     
   jmethodID meth = _Jv_FromReflectedMethod (this);
-  jclass objClass;
 
   if (Modifier::isStatic(meth->accflags))
     {
@@ -157,12 +156,10 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
       // here and not in _Jv_CallAnyMethodA because JNI initializes a
       // class whenever a method lookup is done.
       _Jv_InitClass (declaringClass);
-      objClass = declaringClass;
     }
   else
     {
-      objClass = JV_CLASS (obj);
-     
+      jclass objClass = JV_CLASS (obj);
       if (! _Jv_IsAssignableFrom (declaringClass, objClass))
         throw new java::lang::IllegalArgumentException;
     }
@@ -184,7 +181,7 @@ java::lang::reflect::Method::invoke (jobject obj, jobjectArray args)
 	{
 	}
 
-      if (! _Jv_CheckAccess(caller, objClass, meth->accflags))
+      if (! _Jv_CheckAccess(caller, declaringClass, meth->accflags))
 	throw new IllegalAccessException;
     }
 
diff --git a/libjava/java/net/URLClassLoader.java b/libjava/java/net/URLClassLoader.java
index 4ffd4c532db4..3efc5dca76f0 100644
--- a/libjava/java/net/URLClassLoader.java
+++ b/libjava/java/net/URLClassLoader.java
@@ -54,6 +54,8 @@ import java.security.SecureClassLoader;
 import java.security.cert.Certificate;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.StringTokenizer;
 import java.util.Vector;
 import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
@@ -144,9 +146,10 @@ public class URLClassLoader extends SecureClassLoader
   private final Vector urls = new Vector();
 
   /**
-   * Store pre-parsed information for each url into this vector
-   * each element is a URL loader, corresponding to the URL of
-   * the same index in "urls"
+   * Store pre-parsed information for each url into this vector: each
+   * element is a URL loader.  A jar file has its own class-path
+   * attribute which adds to the URLs that will be searched, but this
+   * does not add to the list of urls.
    */
   private final Vector urlinfos = new Vector();
 
@@ -188,10 +191,15 @@ public class URLClassLoader extends SecureClassLoader
     final CodeSource noCertCodeSource;
 
     URLLoader(URLClassLoader classloader, URL baseURL)
+    {
+      this(classloader, baseURL, baseURL);
+    }
+
+    URLLoader(URLClassLoader classloader, URL baseURL, URL overrideURL)
     {
       this.classloader = classloader;
       this.baseURL = baseURL;
-      this.noCertCodeSource = new CodeSource(baseURL, null);
+      this.noCertCodeSource = new CodeSource(overrideURL, null);
     }
 
     /**
@@ -221,6 +229,11 @@ public class URLClassLoader extends SecureClassLoader
     {
       return null;
     }
+
+    Vector getClassPath()
+    {
+      return null;
+    }
   }
 
   /**
@@ -290,6 +303,10 @@ public class URLClassLoader extends SecureClassLoader
     final JarFile jarfile; // The jar file for this url
     final URL baseJarURL; // Base jar: url for all resources loaded from jar
 
+    Vector classPath;	// The "Class-Path" attribute of this Jar's manifest
+
+    SoURLLoader soURLLoader;
+
     public JarURLLoader(URLClassLoader classloader, URL baseURL)
     {
       super(classloader, baseURL);
@@ -302,25 +319,87 @@ public class URLClassLoader extends SecureClassLoader
       sb.append("!/");
       String jarURL = sb.toString();
 
+      this.soURLLoader = null;
+      this.classPath = null;
       URL baseJarURL = null;
       JarFile jarfile = null;
       try
-        {
-          baseJarURL =
-            new URL(null, jarURL, classloader.getURLStreamHandler("jar"));
-
-          jarfile =
-            ((JarURLConnection) baseJarURL.openConnection()).getJarFile();
-        }
+	{
+	  baseJarURL
+	    = new URL(null, jarURL, classloader.getURLStreamHandler("jar"));
+	  jarfile
+	    = ((JarURLConnection) baseJarURL.openConnection()).getJarFile();
+
+	  if (jarfile != null)
+	    {
+	      String fileName = baseURL.getFile();
+	      if (fileName != null)
+		{
+		  File f = new File(fileName);
+		  String libDirName = f.getCanonicalFile().getParent()
+		    + File.separator + "GCJLIBS";
+		  File libDir = new File(libDirName);
+		  if (libDir != null && (libDir.isDirectory()))
+		    {
+		      File soFile = new File (libDirName 
+					      + File.separator + f.getName() 
+					      + ".so");
+		      if (soFile != null && soFile.isFile())
+			this.soURLLoader
+			  = new SoURLLoader (classloader, soFile.toURL(),
+					     baseURL);
+		    }
+		}
+
+	      Manifest manifest;
+	      Attributes attributes;
+	      String classPathString;
+
+	      if ((manifest = jarfile.getManifest()) != null
+		  && (attributes = manifest.getMainAttributes()) != null
+		  && ((classPathString 
+		       = attributes.getValue(Attributes.Name.CLASS_PATH)) 
+		      != null))
+		{
+		  this.classPath = new Vector();
+
+		  StringTokenizer st
+		    = new StringTokenizer 
+		      (classPathString,
+		       System.getProperty ("path.separator", ":"));
+      
+		  while (st.hasMoreElements ()) 
+		    {  
+		      String e = st.nextToken ();
+		      try
+			{
+			  URL url = new URL(baseURL, e);
+			  this.classPath.add(url);
+			} 
+		      catch (java.net.MalformedURLException xx)
+			{
+			  // Give up
+			}
+		    }
+		}
+ 	    }
+	}
       catch (IOException ioe)
         {
-          /* ignored */
+	  /* ignored */
         }
 
       this.baseJarURL = baseJarURL;
       this.jarfile = jarfile;
     }
 
+    Class getClass(String className)
+    {
+      if (soURLLoader != null)
+	return soURLLoader.getClass(className);
+      return null;
+    }
+
     /** get resource with the name "name" in the jar url */
     Resource getResource(String name)
     {
@@ -337,6 +416,11 @@ public class URLClassLoader extends SecureClassLoader
         return null;
     }
 
+    public String toString ()
+    {
+	return "jarfile " + jarfile.getName();
+    }
+
     Manifest getManifest()
     {
       try
@@ -348,6 +432,11 @@ public class URLClassLoader extends SecureClassLoader
           return null;
         }
     }
+
+    Vector getClassPath()
+    {
+      return classPath;
+    }
   }
 
   static final class JarURLResource extends Resource
@@ -486,7 +575,12 @@ public class URLClassLoader extends SecureClassLoader
 
     SoURLLoader(URLClassLoader classloader, URL url)
     {
-      super(classloader, url);
+      this(classloader, url, url);
+    }
+
+    SoURLLoader(URLClassLoader classloader, URL url, URL overrideURL)
+    {
+      super(classloader, url, overrideURL);
       helper = SharedLibHelper.findHelper(classloader, url.getFile(),
 					  noCertCodeSource);
     }
@@ -577,6 +671,11 @@ public class URLClassLoader extends SecureClassLoader
       return (int) file.length();
     }
 
+    public String toString ()
+    {
+	return "file " +file.getAbsolutePath();
+    }
+
     public URL getURL()
     {
       try
@@ -729,6 +828,7 @@ public class URLClassLoader extends SecureClassLoader
    */
   protected void addURL(URL newUrl)
   {
+    urls.add(newUrl);
     addURLImpl(newUrl);
   }
 
@@ -761,8 +861,21 @@ public class URLClassLoader extends SecureClassLoader
             urlloaders.put(newUrl, loader);
           }
 
-        urls.add(newUrl);
-        urlinfos.add(loader);
+	urlinfos.add(loader);
+
+	Vector extraUrls = loader.getClassPath();
+	if (extraUrls != null)
+	  {
+	    Iterator it = extraUrls.iterator();
+	    while (it.hasNext())
+	      {
+		URL url = (URL)it.next();
+		URLLoader extraLoader = (URLLoader) urlloaders.get(url);
+		if (! urlinfos.contains (extraLoader))
+		  addURLImpl(url);
+	      }
+	  }
+
       }
   }
 
@@ -773,7 +886,7 @@ public class URLClassLoader extends SecureClassLoader
   private void addURLs(URL[] newUrls)
   {
     for (int i = 0; i < newUrls.length; i++)
-      addURLImpl(newUrls[i]);
+      addURL(newUrls[i]);
   }
 
   /**
@@ -830,7 +943,7 @@ public class URLClassLoader extends SecureClassLoader
   {
     // Just try to find the resource by the (almost) same name
     String resourceName = className.replace('.', '/') + ".class";
-    int max = urls.size();
+    int max = urlinfos.size();
     Resource resource = null;
     for (int i = 0; i < max && resource == null; i++)
       {
@@ -939,7 +1052,7 @@ public class URLClassLoader extends SecureClassLoader
    */
   private Resource findURLResource(String resourceName)
   {
-    int max = urls.size();
+    int max = urlinfos.size();
     for (int i = 0; i < max; i++)
       {
         URLLoader loader = (URLLoader) urlinfos.elementAt(i);
@@ -1010,7 +1123,7 @@ public class URLClassLoader extends SecureClassLoader
     throws IOException
   {
     Vector resources = new Vector();
-    int max = urls.size();
+    int max = urlinfos.size();
     for (int i = 0; i < max; i++)
       {
         URLLoader loader = (URLLoader) urlinfos.elementAt(i);
diff --git a/libjava/jni.cc b/libjava/jni.cc
index 6bfc4812d96e..6138334ebaff 100644
--- a/libjava/jni.cc
+++ b/libjava/jni.cc
@@ -563,11 +563,12 @@ _Jv_JNI_ThrowNew (JNIEnv *env, jclass clazz, const char *message)
 					       NULL);
 
       jclass *elts = elements (argtypes);
-      elts[0] = &StringClass;
+      elts[0] = &java::lang::String::class$;
 
       Constructor *cons = clazz->getConstructor (argtypes);
 
-      jobjectArray values = JvNewObjectArray (1, &StringClass, NULL);
+      jobjectArray values = JvNewObjectArray (1, &java::lang::String::class$,
+					      NULL);
       jobject *velts = elements (values);
       velts[0] = JvNewStringUTF (message);
 
@@ -1204,7 +1205,7 @@ _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
 
 	      // The field might be resolved or it might not be.  It
 	      // is much simpler to always resolve it.
-	      _Jv_ResolveField (field, loader);
+	      _Jv_Linker::resolve_field (field, loader);
 	      if (_Jv_equalUtf8Consts (f_name, a_name)
 		  && field->getClass() == field_class)
 		return field;
diff --git a/libjava/link.cc b/libjava/link.cc
new file mode 100644
index 000000000000..39ade1481a36
--- /dev/null
+++ b/libjava/link.cc
@@ -0,0 +1,1764 @@
+// link.cc - Code for linking and resolving classes and pool entries.
+
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 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.  */
+
+/* Author: Kresten Krab Thorup <krab@gnu.org>  */
+
+#include <config.h>
+#include <platform.h>
+
+#include <java-interp.h>
+
+#include <jvm.h>
+#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>
+#include <java/lang/IllegalAccessError.h>
+#include <java/lang/AbstractMethodError.h>
+#include <java/lang/NoClassDefFoundError.h>
+#include <java/lang/IncompatibleClassChangeError.h>
+#include <java/lang/VerifyError.h>
+#include <java/lang/VMClassLoader.h>
+#include <java/lang/reflect/Modifier.h>
+#include <java/security/CodeSource.h>
+
+using namespace gcj;
+
+// When true, print debugging information about class loading.
+bool gcj::verbose_class_flag;
+
+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_Linker::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_Linker::resolve_field (_Jv_Field *field, java::lang::ClassLoader *loader)
+{
+  if (! field->isResolved ())
+    {
+      _Jv_Utf8Const *sig = (_Jv_Utf8Const*)field->type;
+      field->type = _Jv_FindClassFromSignature (sig->chars(), loader);
+      field->flags &= ~_Jv_FIELD_UNRESOLVED_FLAG;
+    }
+}
+
+_Jv_word
+_Jv_Linker::resolve_pool_entry (jclass klass, int index)
+{
+  using namespace java::lang::reflect;
+
+  _Jv_Constants *pool = &klass->constants;
+
+  if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0)
+    return pool->data[index];
+
+  switch (pool->tags[index])
+    {
+    case JV_CONSTANT_Class:
+      {
+	_Jv_Utf8Const *name = pool->data[index].utf8;
+
+	jclass found;
+	if (name->first() == '[')
+	  found = _Jv_FindClassFromSignature (name->chars(),
+					      klass->loader);
+	else
+	  found = _Jv_FindClass (name, klass->loader);
+
+	if (! found)
+	  throw new java::lang::NoClassDefFoundError (name->toString());
+
+	// 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
+	  {
+	    java::lang::StringBuffer *sb = new java::lang::StringBuffer ();
+	    sb->append(klass->getName());
+	    sb->append(JvNewStringLatin1(" can't access class "));
+	    sb->append(found->getName());
+	    throw new java::lang::IllegalAccessError(sb->toString());
+	  }
+      }
+      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 = (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->chars(),
+						   klass->loader);
+      
+	_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))
+		  {
+		    // 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->chars()));
+	    sb->append(JvNewStringLatin1(" was not found."));
+	    throw
+	      new java::lang::IncompatibleClassChangeError (sb->toString());
+	  }
+
+	pool->data[index].field = the_field;
+	pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+      }
+      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 = (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;
+
+	// We're going to cache a pointer to the _Jv_Method object
+	// when we find it.  So, to ensure this doesn't get moved from
+	// beneath us, we first put all the needed Miranda methods
+	// into the target class.
+	wait_for_state (klass, JV_STATE_LOADED);
+
+	// First search the class itself.
+	the_method = search_method_in_class (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 *));
+
+	    get_interfaces (owner, &ifaces);	  
+
+	    for (int i = 0; i < ifaces.count; i++)
+	      {
+		jclass cls = ifaces.list[i];
+		the_method = search_method_in_class (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 = search_method_in_class (cls, klass, method_name,
+						 method_signature);
+	    if (the_method != 0)
+	      {
+		found_class = cls;
+		break;
+	      }
+	  }
+
+      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->chars()));
+	    sb->append(JvNewStringLatin1(" with signature "));
+	    sb->append(_Jv_NewStringUTF(method_signature->chars()));
+	    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;
+    }
+  return pool->data[index];
+}
+
+// This function is used to lazily locate superclasses and
+// superinterfaces.  This must be called with the class lock held.
+void
+_Jv_Linker::resolve_class_ref (jclass klass, jclass *classref)
+{
+  jclass ret = *classref;
+
+  // 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)
+	{
+	  _Jv_Utf8Const *name = klass->constants.data[(uaddr) *classref].utf8;
+	  ret = _Jv_FindClass (name, klass->loader);
+	  if (! ret)
+	    {
+	      throw new java::lang::NoClassDefFoundError (name->toString());
+	    }
+	}
+      else
+	ret = klass->constants.data[(uaddr) classref].clazz;
+      *classref = ret;
+    }
+}
+
+// Find a method declared in the cls that is referenced from klass and
+// perform access checks.
+_Jv_Method *
+_Jv_Linker::search_method_in_class (jclass cls, jclass klass, 
+				    _Jv_Utf8Const *method_name, 
+				    _Jv_Utf8Const *method_signature)
+{
+  using namespace java::lang::reflect;
+
+  for (int i = 0;  i < cls->method_count;  i++)
+    {
+      _Jv_Method *method = &cls->methods[i];
+      if (   (!_Jv_equalUtf8Consts (method->name,
+				    method_name))
+	  || (!_Jv_equalUtf8Consts (method->signature,
+				    method_signature)))
+	continue;
+
+      if (_Jv_CheckAccess (klass, cls, method->accflags))
+	return method;
+      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_NewStringUTF(method_name->chars()));
+	  sb->append(_Jv_NewStringUTF(method_signature->chars()));
+	  throw new java::lang::IllegalAccessError (sb->toString());
+	}
+    }
+  return 0;
+}
+
+
+#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_Linker::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$)
+    {
+      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.
+
+  // 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;
+    }
+
+  if ((klass->accflags & java::lang::reflect::Modifier::ABSTRACT) != 0)
+    return;
+
+  // Optimization: If class implements no interfaces, use a common
+  // predefined interface table.
+  if (!has_interfaces)
+    {
+      klass->idt = &null_idt;
+      return;
+    }
+
+  // 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 *));
+
+  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];
+	}
+
+      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_Linker::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_Linker::get_interfaces (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.  */
+      wait_for_state(iface, JV_STATE_LINKED);
+
+      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++;
+
+	  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;
+}
+
+// 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_Linker::generate_itable (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 = append_partial_itable (klass, iface, itable, itable_pos);
+
+      /* Create interface dispatch table for iface */
+      if (iface->idt == NULL)
+	{
+	  // 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;
+
+	  iface->idt->iface.ioffsets = ioffsets;	    
+	}
+    }
+}
+
+// Format method name for use in error messages.
+jstring
+_Jv_GetMethodString (jclass klass, _Jv_Utf8Const *name)
+{
+  jstring r = klass->name->toString();
+  r = r->concat (JvNewStringUTF ("."));
+  r = r->concat (name->toString());
+  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_Linker::append_partial_itable (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->first() == '<'))
+	{
+	  // leave a placeholder in the itable for hidden init methods.
+          itable[pos] = NULL;	
+	}
+      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));
+
+	  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_Linker::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)
+    {
+      _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 - 1) * 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;
+}
+
+
+// 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;
+
+// link_symbol_table() 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.
+
+// This must be called while holding the class lock.
+
+void
+_Jv_Linker::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->chars());
+  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;            
+
+      _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->chars()));
+
+      // We're looking for a field or a method, and we can tell
+      // which is needed by looking at the signature.
+      if (signature->first() == '(' && signature->len() >= 2)
+	{
+	  // 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);
+
+	  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",
+		     (int)index,
+		     (int)klass->otable->offsets[index],
+		     (const char*)target_class->name->chars(),
+		     target_class,
+		     (const char*)sym.name->chars(),
+		     (const char*)signature->chars());
+	  continue;
+	}
+
+      // try fields
+      {
+	_Jv_Field *the_field = NULL;
+
+	wait_for_state(target_class, JV_STATE_PREPARED);
+	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);
+
+// 		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",
+			   (int)index,
+			   (int)field->u.boffset,
+			   (const char*)cls->name->chars(),
+			   cls,
+			   (const char*)field->name->chars());
+		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;            
+      _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->chars()));
+      
+      // 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->first() == '(' && signature->len() >= 2)
+	{
+ 	  // 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);
+
+	  // 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->chars(),
+			     klass,
+			     (const char*)sym.name->chars(),
+			     (const char*)signature->chars());
+		}
+	    }
+	  else
+	    klass->atable->addresses[index]
+	      = (void *)_Jv_ThrowNoSuchMethodError;
+
+	  continue;
+	}
+
+      // try fields
+      {
+	_Jv_Field *the_field = NULL;
+
+	wait_for_state(target_class, JV_STATE_PREPARED);
+	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);
+
+// 		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 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]).class_name != NULL; 
+       ++index)
+    {
+      jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
+      _Jv_Utf8Const *signature = sym.signature;
+
+      jclass cls;
+      int i;
+
+      wait_for_state(target_class, JV_STATE_LOADED);
+      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 *)(intptr_t) 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->chars(),
+		       cls,
+		       (const char*)sym.name->chars(),
+		       (const char*)signature->chars());
+	      fprintf (stderr, "            [%d] = offset %d\n",
+		       index + 1,
+		       (int)(intptr_t)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_Linker::link_exception_table (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_Linker::layout_interface_methods (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_Linker::layout_vtable_methods (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);
+      layout_vtable_methods (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_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());
+		}
+	    }
+	}
+
+      if (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.
+void
+_Jv_Linker::set_vtable_entries (jclass klass, _Jv_VTable *vtable)
+{
+  for (int i = klass->method_count - 1; i >= 0; i--)
+    {
+      using namespace java::lang::reflect;
+
+      _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);
+      else
+	vtable->set_method(meth->index, meth->ncode);
+    }
+}
+
+// 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_Linker::make_vtable (jclass klass)
+{
+  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;
+
+  // Ensure all the `ncode' entries are set.
+  klass->engine->create_ncode(klass);
+
+  // 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;
+
+  // 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)
+    vtable->set_method (i, superclass->vtable->get_method (i));
+
+  // Set the class pointer and GC descriptor.
+  vtable->clas = klass;
+  vtable->gc_descr = _Jv_BuildGCDescr (klass);
+
+  // For each virtual declared in klass, set new vtable entry or
+  // override an old one.
+  set_vtable_entries (klass, vtable);
+
+  // 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 (vtable->get_method(i) == (void *) &_Jv_abstractMethodError)
+	  {
+	    using namespace java::lang;
+	    while (klass != NULL)
+	      {
+		for (int j = 0; j < klass->method_count; ++j)
+		  {
+		    if (klass->methods[j].index == i)
+		      {
+			StringBuffer *buf = new StringBuffer ();
+			buf->append (_Jv_NewStringUtf8Const (klass->methods[j].name));
+			buf->append ((jchar) ' ');
+			buf->append (_Jv_NewStringUtf8Const (klass->methods[j].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, allocating space for static fields and computing
+// offsets of instance fields.  The class lock must be held by the
+// caller.
+void
+_Jv_Linker::ensure_fields_laid_out (jclass klass)
+{  
+  if (klass->size_in_bytes != -1)
+    return;
+
+  // 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();
+    }
+
+  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 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);
+
+	  field_size = field->type->size ();
+	  field_align = get_alignment_from_class (field->type);
+	}
+      else 
+	{
+	  field_size = sizeof (jobject);
+	  field_align = __alignof__ (jobject);
+	}
+
+      field->bsize = field_size;
+
+      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);
+
+  // 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;
+}
+
+// This takes the class to state JV_STATE_LINKED.  The class lock must
+// be held when calling this.
+void
+_Jv_Linker::ensure_class_linked (jclass klass)
+{
+  if (klass->state >= JV_STATE_LINKED)
+    return;
+
+  int state = klass->state;
+  try
+    {
+      // Short-circuit, so that mutually dependent classes are ok.
+      klass->state = JV_STATE_LINKED;
+
+      _Jv_Constants *pool = &klass->constants;
+
+      // Compiled classes require that their class constants be
+      // resolved here.  However, interpreted classes need their
+      // constants to be resolved lazily.  If we resolve an
+      // interpreted class' constants eagerly, we can end up with
+      // spurious IllegalAccessErrors when the constant pool contains
+      // a reference to a class we can't access.  This can validly
+      // occur in an obscure case involving the InnerClasses
+      // attribute.
+      if (! _Jv_IsInterpretedClass (klass))
+	{
+	  // 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);
+	    }
+	}
+
+#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[(uaddr) 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[(uaddr) klass->interfaces[i]].clazz;
+	}
+#endif
+
+      // 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;
+	    }
+	}
+
+      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);
+    }
+  catch (java::lang::Throwable *t)
+    {
+      klass->state = state;
+      throw t;
+    }
+}
+
+// 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_Linker::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);
+
+  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);
+    }
+}
+
+// This adds missing `Miranda methods' to a class.
+void
+_Jv_Linker::add_miranda_methods (jclass base, jclass iface_class)
+{
+  // Note that at this point, all our supers, and the supers of all
+  // our superclasses and superinterfaces, will have been installed.
+
+  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->first() == '<')
+	    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);
+
+	      // 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;
+
+	      base->methods = new_m;
+	      base->method_count = new_count;
+	    }
+	}
+
+      wait_for_state (interface, JV_STATE_LOADED);
+      add_miranda_methods (base, interface);
+    }
+}
+
+// This ensures that the class' method table is "complete".  This must
+// be called with the class lock held.
+void
+_Jv_Linker::ensure_method_table_complete (jclass klass)
+{
+  if (klass->vtable != NULL || klass->isInterface())
+    return;
+
+  // We need our superclass to have its own Miranda methods installed.
+  wait_for_state (klass->getSuperclass (), JV_STATE_LOADED);
+
+  // 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.
+  int pre_count = klass->method_count;
+  add_miranda_methods (klass, klass);
+
+  // Let the execution engine know that we've added methods.
+  if (klass->method_count != pre_count)
+    klass->engine->post_miranda_hook(klass);
+}
+
+// Verify a class.  Must be called with class lock held.
+void
+_Jv_Linker::verify_class (jclass klass)
+{
+  klass->engine->verify(klass);
+}
+
+// Check the assertions contained in the type assertion table for KLASS.
+// This is the equivilent of bytecode verification for native, BC-ABI code.
+void
+_Jv_Linker::verify_type_assertions (jclass klass)
+{
+  if (debug_link)
+    fprintf (stderr, "Evaluating type assertions for %s:\n",
+	     klass->name->chars());
+
+  if (klass->assertion_table == NULL)
+    return;
+
+  for (int i = 0;; i++)
+    {
+      int assertion_code = klass->assertion_table[i].assertion_code;
+      _Jv_Utf8Const *op1 = klass->assertion_table[i].op1;
+      _Jv_Utf8Const *op2 = klass->assertion_table[i].op2;
+      
+      if (assertion_code == JV_ASSERT_END_OF_TABLE)
+        return;
+      else if (assertion_code == JV_ASSERT_TYPES_COMPATIBLE)
+        {
+	  if (debug_link)
+	    {
+	      fprintf (stderr, "  code=%i, operand A=%s B=%s\n",
+		       assertion_code, op1->chars(), op2->chars());
+	    }
+	
+	  // The operands are class signatures. op1 is the source, 
+	  // op2 is the target.
+	  jclass cl1 = _Jv_FindClassFromSignature (op1->chars(), 
+	    klass->getClassLoaderInternal());
+	  jclass cl2 = _Jv_FindClassFromSignature (op2->chars(),
+	    klass->getClassLoaderInternal());
+	    
+	  // If the class doesn't exist, ignore the assertion. An exception
+	  // will be thrown later if an attempt is made to actually 
+	  // instantiate the class.
+	  if (cl1 == NULL || cl2 == NULL)
+	    continue;
+
+          if (! _Jv_IsAssignableFromSlow (cl2, cl1))
+	    {
+	      jstring s = JvNewStringUTF ("Incompatible types: In class ");
+	      s = s->concat (klass->getName());
+	      s = s->concat (JvNewStringUTF (": "));
+	      s = s->concat (cl1->getName());
+	      s = s->concat (JvNewStringUTF (" is not assignable to "));
+	      s = s->concat (cl2->getName());
+	      throw new java::lang::VerifyError (s);
+	    }
+	}
+      else if (assertion_code == JV_ASSERT_IS_INSTANTIABLE)
+        {
+	  // TODO: Implement this.
+	}
+      // Unknown assertion codes are ignored, for forwards-compatibility.
+    }
+}
+   
+void
+_Jv_Linker::print_class_loaded (jclass klass)
+{
+  char *codesource = NULL;
+  if (klass->protectionDomain != NULL)
+    {
+      java::security::CodeSource *cs
+	= klass->protectionDomain->getCodeSource();
+      if (cs != NULL)
+	{
+	  jstring css = cs->toString();
+	  int len = JvGetStringUTFLength(css);
+	  codesource = (char *) _Jv_AllocBytes(len + 1);
+	  JvGetStringUTFRegion(css, 0, css->length(), codesource);
+	  codesource[len] = '\0';
+	}
+    }
+  if (codesource == NULL)
+    codesource = "<no code source>";
+
+  // We use a somewhat bogus test for the ABI here.
+  char *abi;
+  if (_Jv_IsInterpretedClass (klass))
+    abi = "bytecode";
+  else if (klass->state == JV_STATE_PRELOADING)
+    abi = "BC-compiled";
+  else
+    abi = "pre-compiled";
+
+  fprintf (stderr, "[Loaded (%s) %s from %s]\n", abi, klass->name->chars(),
+	   codesource);
+}
+
+// FIXME: mention invariants and stuff.
+void
+_Jv_Linker::wait_for_state (jclass klass, int state)
+{
+  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 ();
+
+  java::lang::Thread *save = klass->thread;
+  klass->thread = self;
+
+  // Print some debugging info if requested.  Interpreted classes are
+  // handled in defineclass, so we only need to handle the two
+  // pre-compiled cases here.
+  if (gcj::verbose_class_flag
+      && (klass->state == JV_STATE_COMPILED
+	  || klass->state == JV_STATE_PRELOADING)
+      && ! _Jv_IsInterpretedClass (klass))
+    print_class_loaded (klass);
+
+  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)
+	{
+	  verify_class (klass);
+
+	  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;
+}
diff --git a/libjava/prims.cc b/libjava/prims.cc
index 70ede2765cbe..e3d5750cd1ce 100644
--- a/libjava/prims.cc
+++ b/libjava/prims.cc
@@ -61,12 +61,16 @@ details.  */
 #include <java/lang/VirtualMachineError.h>
 #include <gnu/gcj/runtime/VMClassLoader.h>
 #include <gnu/gcj/runtime/FinalizerThread.h>
+#include <execution.h>
 #include <gnu/java/lang/MainThread.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;
@@ -723,7 +727,7 @@ JvConvertArgv (int argc, const char **argv)
 {
   if (argc < 0)
     argc = 0;
-  jobjectArray ar = JvNewObjectArray(argc, &StringClass, NULL);
+  jobjectArray ar = JvNewObjectArray(argc, &java::lang::String::class$, NULL);
   jobject *ptr = elements(ar);
   jbyteArray bytes = NULL;
   for (int i = 0;  i < argc;  i++)
@@ -1204,7 +1208,7 @@ _Jv_CheckAccess (jclass self_klass, jclass other_klass, jint flags)
   return ((self_klass == other_klass)
 	  || ((flags & Modifier::PUBLIC) != 0)
 	  || (((flags & Modifier::PROTECTED) != 0)
-	      && other_klass->isAssignableFrom (self_klass))
+	      && _Jv_IsAssignableFromSlow (other_klass, self_klass))
 	  || (((flags & Modifier::PRIVATE) == 0)
 	      && _Jv_ClassNameSamePackage (self_klass->name,
 					   other_klass->name)));
diff --git a/libjava/resolve.cc b/libjava/resolve.cc
deleted file mode 100644
index 5ebefebecef5..000000000000
--- a/libjava/resolve.cc
+++ /dev/null
@@ -1,1125 +0,0 @@
-// resolve.cc - Code for linking and resolving classes and pool entries.
-
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 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.  */
-
-/* Author: Kresten Krab Thorup <krab@gnu.org>  */
-
-#include <config.h>
-#include <platform.h>
-
-#include <java-interp.h>
-
-#include <jvm.h>
-#include <gcj/cni.h>
-#include <string.h>
-#include <java-cpool.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/NoSuchFieldError.h>
-#include <java/lang/NoSuchMethodError.h>
-#include <java/lang/ClassFormatError.h>
-#include <java/lang/IllegalAccessError.h>
-#include <java/lang/AbstractMethodError.h>
-#include <java/lang/NoClassDefFoundError.h>
-#include <java/lang/IncompatibleClassChangeError.h>
-#include <java/lang/VMClassLoader.h>
-#include <java/lang/reflect/Modifier.h>
-
-using namespace gcj;
-
-void
-_Jv_ResolveField (_Jv_Field *field, java::lang::ClassLoader *loader)
-{
-  if (! field->isResolved ())
-    {
-      _Jv_Utf8Const *sig = (_Jv_Utf8Const*)field->type;
-      field->type = _Jv_FindClassFromSignature (sig->chars(), loader);
-      field->flags &= ~_Jv_FIELD_UNRESOLVED_FLAG;
-    }
-}
-
-#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 int get_alignment_from_class (jclass);
-
-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)
-{
-  using namespace java::lang::reflect;
-
-  _Jv_Constants *pool = &klass->constants;
-
-  if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0)
-    return pool->data[index];
-
-  switch (pool->tags[index]) {
-  case JV_CONSTANT_Class:
-    {
-      _Jv_Utf8Const *name = pool->data[index].utf8;
-
-      jclass found;
-      if (name->first() == '[')
-	found = _Jv_FindClassFromSignature (name->chars(),
-					    klass->loader);
-      else
-	found = _Jv_FindClass (name, klass->loader);
-
-      if (! found)
-	{
-	  jstring str = name->toString();
-	  // This exception is specified in JLS 2nd Ed, section 5.1.
-	  throw new java::lang::NoClassDefFoundError (str);
-	}
-
-      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
-	{
-	  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.
-
-      jclass field_type = 0;
-
-      if (owner->loader != klass->loader)
-	field_type = _Jv_FindClassFromSignature (field_type_name->chars(),
-						 klass->loader);
-      
-      _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 */
-
-		  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;
-		  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(field_name->toString());
-	  sb->append(JvNewStringLatin1(" was not found."));
-	  throw_incompatible_class_change_error(sb->toString());
-	}
-
-      pool->data[index].field = the_field;
-      pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
-    }
-    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);
-
-	  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;
-	    }
-	}
-
-    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(method_name->toString());
-	  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;
-    }
-    break;
-
-  }
-
-  return pool->data[index];
-}
-
-// Find a method declared in the cls that is referenced from klass and
-// perform access checks.
-_Jv_Method *
-_Jv_SearchMethodInClass (jclass cls, jclass klass, 
-                         _Jv_Utf8Const *method_name, 
-			 _Jv_Utf8Const *method_signature)
-{
-  using namespace java::lang::reflect;
-
-  for (int i = 0;  i < cls->method_count;  i++)
-    {
-      _Jv_Method *method = &cls->methods[i];
-      if (   (!_Jv_equalUtf8Consts (method->name,
-				    method_name))
-	  || (!_Jv_equalUtf8Consts (method->signature,
-				    method_signature)))
-	continue;
-
-      if (_Jv_CheckAccess (klass, cls, method->accflags))
-	return method;
-      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(method_name->toString());
-	  sb->append(method_signature->toString());
-	  throw new java::lang::IllegalAccessError (sb->toString());
-	}
-    }
-  return 0;
-}
-
-// A helper for _Jv_PrepareClass.  This adds missing `Miranda methods'
-// to a class.
-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)
-    {
-      for (int j = 0; j < iface_class->interfaces[i]->method_count; ++j)
-	{
-	  _Jv_Method *meth = &iface_class->interfaces[i]->methods[j];
-	  // Don't bother with <clinit>.
-	  if (meth->name->first() == '<')
-	    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);
-
-	      // 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;
-
-	      _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);
-
-	      base->methods = new_m;
-	      interp_base->interpreted_methods = new_im;
-	      base->method_count = new_count;
-	    }
-	}
-
-      _Jv_PrepareMissingMethods (base, iface_class->interfaces[i]);
-    }
-}
-
-void 
-_Jv_PrepareClass(jclass klass)
-{
-  using namespace java::lang::reflect;
-
- /*
-  * 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.
-
-  if (klass->superclass)
-    java::lang::VMClassLoader::resolveClass (klass->superclass);
-
-  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
-
-  /************ PART ONE: OBJECT LAYOUT ***************/
-
-  // 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->superclass;
-  while (super != NULL)
-    {
-      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->superclass;
-    }
-
-  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 & Modifier::STATIC)
-	{
-	  /* 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;
-
-  // allocate static memory
-  if (static_size != 0)
-    {
-      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 & 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);
-		}
-	    }
-	}
-
-      // now we don't need the field_initializers anymore, so let the
-      // collector get rid of it!
-
-      iclass->field_initializers = 0;
-    }
-
-  /************ PART TWO: VTABLE LAYOUT ***************/
-
-  /* preparation: build the vtable stubs (even interfaces can)
-     have code -- for static constructors. */
-  for (int i = 0; i < klass->method_count; i++)
-    {
-      _Jv_MethodBase *imeth = iclass->interpreted_methods[i];
-
-      if ((klass->methods[i].accflags & 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);
-	  _Jv_VerifyMethod (im);
-	  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;
-	    }
-	}
-    }
-
-  if ((klass->accflags & Modifier::INTERFACE))
-    {
-      klass->state = JV_STATE_PREPARED;
-      klass->notifyAll ();
-      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.  We only need to do this for
-  // abstract classes.
-  if ((klass->accflags & Modifier::ABSTRACT))
-    _Jv_PrepareMissingMethods (klass, klass);
-
-  klass->vtable_method_count = -1;
-  _Jv_MakeVTable (klass);
-
-  /* wooha! we're done. */
-  klass->state = JV_STATE_PREPARED;
-  klass->notifyAll ();
-}
-
-/** 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:
-      {
-	_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);
-      }
-      /* 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");
-    }
-}
-
-template<typename T>
-struct aligner
-{
-  T field;
-};
-
-#define ALIGNOF(TYPE) (__alignof__ (((aligner<TYPE> *) 0)->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);
-}
-
-
-inline static unsigned char*
-skip_one_type (unsigned char* ptr)
-{
-  int ch = *ptr++;
-
-  while (ch == '[')
-    { 
-      ch = *ptr++;
-    }
-  
-  if (ch == 'L')
-    {
-      do { ch = *ptr++; } while (ch != ';');
-    }
-
-  return ptr;
-}
-
-static ffi_type*
-get_ffi_type_from_signature (unsigned char* ptr)
-{
-  switch (*ptr) 
-    {
-    case 'L':
-    case '[':
-      return &ffi_type_pointer;
-      break;
-
-    case 'Z':
-      // On some platforms a bool is a byte, on others an int.
-      if (sizeof (jboolean) == sizeof (jbyte))
-	return &ffi_type_sint8;
-      else
-	{
-	  JvAssert (sizeof (jbyte) == sizeof (jint));
-	  return &ffi_type_sint32;
-	}
-      break;
-
-    case 'B':
-      return &ffi_type_sint8;
-      break;
-      
-    case 'C':
-      return &ffi_type_uint16;
-      break;
-	  
-    case 'S': 
-      return &ffi_type_sint16;
-      break;
-	  
-    case 'I':
-      return &ffi_type_sint32;
-      break;
-	  
-    case 'J':
-      return &ffi_type_sint64;
-      break;
-	  
-    case 'F':
-      return &ffi_type_float;
-      break;
-	  
-    case 'D':
-      return &ffi_type_double;
-      break;
-
-    case 'V':
-      return &ffi_type_void;
-      break;
-    }
-
-  throw_internal_error ("unknown type in signature");
-}
-
-/* this function yields the number of actual arguments, that is, if the
- * function is non-static, then one is added to the number of elements
- * found in the signature */
-
-int 
-_Jv_count_arguments (_Jv_Utf8Const *signature,
-		     jboolean staticp)
-{
-  unsigned char *ptr = (unsigned char*) signature->chars();
-  int arg_count = staticp ? 0 : 1;
-
-  /* first, count number of arguments */
-
-  // skip '('
-  ptr++;
-
-  // count args
-  while (*ptr != ')')
-    {
-      ptr = skip_one_type (ptr);
-      arg_count += 1;
-    }
-
-  return arg_count;
-}
-
-/* This beast will build a cif, given the signature.  Memory for
- * the cif itself and for the argument types must be allocated by the
- * caller.
- */
-
-static int 
-init_cif (_Jv_Utf8Const* signature,
-	  int arg_count,
-	  jboolean staticp,
-	  ffi_cif *cif,
-	  ffi_type **arg_types,
-	  ffi_type **rtype_p)
-{
-  unsigned char *ptr = (unsigned char*) signature->chars();
-
-  int arg_index = 0;		// arg number
-  int item_count = 0;		// stack-item count
-
-  // setup receiver
-  if (!staticp)
-    {
-      arg_types[arg_index++] = &ffi_type_pointer;
-      item_count += 1;
-    }
-
-  // skip '('
-  ptr++;
-
-  // 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->chars() + signature->len())
-    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;
-}
-
-
-/* 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;
-
-  return result;
-}
-
-
-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));
-}
-
-static void
-throw_internal_error (char *msg)
-{
-  throw new java::lang::InternalError (JvNewStringLatin1 (msg));
-}
-
-
-#endif /* INTERPRETER */
diff --git a/libjava/testsuite/Makefile.in b/libjava/testsuite/Makefile.in
index 2e51cd9e63ae..2fe07c88e310 100644
--- a/libjava/testsuite/Makefile.in
+++ b/libjava/testsuite/Makefile.in
@@ -134,6 +134,7 @@ LIBGCJTESTSPEC = @LIBGCJTESTSPEC@
 LIBGCJ_CFLAGS = @LIBGCJ_CFLAGS@
 LIBGCJ_CXXFLAGS = @LIBGCJ_CXXFLAGS@
 LIBGCJ_JAVAFLAGS = @LIBGCJ_JAVAFLAGS@
+LIBGCJ_LD_SYMBOLIC = @LIBGCJ_LD_SYMBOLIC@
 LIBICONV = @LIBICONV@
 LIBLTDL = @LIBLTDL@
 LIBOBJS = @LIBOBJS@
diff --git a/libjava/testsuite/libjava.lang/assign2.java b/libjava/testsuite/libjava.lang/assign2.java
new file mode 100644
index 000000000000..41fdcb594d9f
--- /dev/null
+++ b/libjava/testsuite/libjava.lang/assign2.java
@@ -0,0 +1,21 @@
+// Test for an array assignment bug we've had.
+
+public class assign2
+{
+  public static Object[][] c () { return new Long[5][5]; }
+
+  public static Object[] d () { return new Integer[3]; }
+
+  public static void main(String[] args)
+  {
+    try
+      {
+	Object[][] x = c();
+	x[0] = d();
+      }
+    catch (ArrayStoreException _)
+      {
+	System.out.println("good");
+      }
+  }
+}
diff --git a/libjava/testsuite/libjava.lang/assign2.out b/libjava/testsuite/libjava.lang/assign2.out
new file mode 100644
index 000000000000..12799ccbe7ce
--- /dev/null
+++ b/libjava/testsuite/libjava.lang/assign2.out
@@ -0,0 +1 @@
+good
diff --git a/libjava/testsuite/libjava.loader/loader.exp b/libjava/testsuite/libjava.loader/loader.exp
index e306a312c83d..86e518170c4f 100644
--- a/libjava/testsuite/libjava.loader/loader.exp
+++ b/libjava/testsuite/libjava.loader/loader.exp
@@ -1,5 +1,15 @@
 # Tests for ClassLoader and native library loader code.
 
+# Compute the correct name for an object file.
+# This is an awful hack.
+proc gcj_object_file_name {compiler base} {
+  verbose "OBJECT: compiler = $compiler"
+  if {[string match *libtool* $compiler]} {
+    return $base.lo
+  }
+  return $base.o
+}
+
 # Do all the work for a single JNI test.  Return 0 on failure.
 proc gcj_loader_test_one {srcfile} {
   global objdir srcdir subdir
@@ -9,9 +19,9 @@ proc gcj_loader_test_one {srcfile} {
   regsub "^.*/(\[^/.\]+)\[.\]\[^/]*$" "$srcfile" "\\1" out
   set executable "${objdir}/$out.exe"
 
-    set errname [file rootname [file tail $srcfile]]
-    set args [libjava_arguments link]
-    lappend args "additional_flags=--main=[file rootname [file tail $srcfile]] $srcdir/$subdir/MyLoader.java $objdir/dummy.o"
+  set errname [file rootname [file tail $srcfile]]
+  set args [libjava_arguments link]
+  lappend args "additional_flags=--main=[file rootname [file tail $srcfile]] $srcdir/$subdir/MyLoader.java $objdir/[gcj_object_file_name $args dummy]"
   set x [libjava_prune_warnings \
 	     [libjava_tcompile $srcfile "$executable" executable $args]]
 
@@ -47,7 +57,7 @@ proc gcj_loader_run {} {
   set args [libjava_arguments compile]
   lappend args "additional_flags=--resource $objdir/dummy.class"
   set x [libjava_prune_warnings \
-	   [libjava_tcompile "$objdir/dummy.class" "$objdir/dummy.o" object $args]]
+	   [libjava_tcompile "$objdir/dummy.class" "$objdir/[gcj_object_file_name $args dummy]" object $args]]
 
     if { $x != "" } {
 	verbose "resource compilation failed: $x" 2
diff --git a/libjava/verify.cc b/libjava/verify.cc
index 63857d0341ee..988b5aab67ee 100644
--- a/libjava/verify.cc
+++ b/libjava/verify.cc
@@ -553,7 +553,7 @@ private:
 	      {
 		// We use a recursive call because we also need to
 		// check superinterfaces.
-		if (is_assignable_from_slow (target, source->interfaces[i]))
+		if (is_assignable_from_slow (target, source->getInterface (i)))
 		  return true;
 	      }
 	  }
-- 
GitLab