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


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

ABI: Merged with HEAD


I have merged the CVS head as of 20040514 into the ABI branch. The following diff shows the current changes on the ABI branch relative to the HEAD. You can diff against the tag gcj-abi-2-merge-20040514 to get the current branch diff.

Hopefully future merges won't be as painful as this one was!

The tree-ssa code has caused a failure for --indirect-dispatch:

$ gcj --indirect-dispatch Test.java
Test.java: In class `Test':
Test.java: In method `Test.main(java.lang.String[])':
Test.java:7: internal compiler error: in check_pointer_types_r, at gimplify.c:3631


This doesn't happen on head so some change in the ABI branch is responsible - I'll take a look at this soon unless Andrew beats me to it.

Bryce


Index: gcc/ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ChangeLog,v
retrieving revision 2.3657
diff -u -r2.3657 ChangeLog
--- gcc/ChangeLog	14 May 2004 17:50:52 -0000	2.3657
+++ gcc/ChangeLog	20 May 2004 19:36:12 -0000
@@ -1,3 +1,7 @@
+2004-04-20  Bryce McKinlay  <mckinlay@redhat.com>
+
+	* version.c (version_string): Update for gcj-abi-2-dev-branch.
+
 2004-05-14  Jeff Law  <law@redhat.com>
 
 	* tree-ssa-dom.c (simplify_rhs_and_lookup_avail_expr): Reorganize
Index: gcc/version.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/version.c,v
retrieving revision 1.2331
diff -u -r1.2331 version.c
--- gcc/version.c	14 May 2004 00:16:12 -0000	1.2331
+++ gcc/version.c	20 May 2004 19:36:39 -0000
@@ -5,7 +5,7 @@
    please modify this string to indicate that, e.g. by putting your
    organization's name in parentheses at the end of the string.  */
 
-const char version_string[] = "3.5.0 20040514 (experimental)";
+const char version_string[] = "3.5.0-abi 20040514 (gcj-abi-2-dev-branch)";
 
 /* This is the location of the online document giving instructions for
    reporting bugs.  If you distribute a modified version of GCC,
Index: gcc/java/ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/ChangeLog,v
retrieving revision 1.1365
diff -u -r1.1365 ChangeLog
--- gcc/java/ChangeLog	14 May 2004 02:29:30 -0000	1.1365
+++ gcc/java/ChangeLog	20 May 2004 19:37:46 -0000
@@ -1,3 +1,70 @@
+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-05-13  Diego Novillo  <dnovillo@redhat.com>
 
 	* Make-lang.in, expr.c, java-gimplify.c: Rename
Index: gcc/java/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.184
diff -u -r1.184 class.c
--- gcc/java/class.c	13 May 2004 06:40:34 -0000	1.184
+++ gcc/java/class.c	20 May 2004 19:37:46 -0000
@@ -486,6 +486,10 @@
       TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (this_class)), 0)
 	= super_binfo;
       CLASS_HAS_SUPER (this_class) = 1;
+      /* FIXME: This is wrong.  */
+      if (TYPE_LANG_SPECIFIC (this_class)
+	  && TYPE_LANG_SPECIFIC (super_class))
+	TYPE_DUMMY (this_class) = TYPE_DUMMY (super_class);
     }
 
   set_class_decl_access_flags (access_flags, class_decl);
@@ -963,7 +967,7 @@
 	 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);
 
@@ -1081,7 +1085,10 @@
       return fdecl;
     }
 
-  if (flag_indirect_dispatch)
+  /* FIXME: The gcj runtime is broken in that atable references to
+     static fields in interpreted classes aren't fixed up until too
+     late.  When this is fixed we can re-enable this code.  */
+  if (0 && flag_indirect_dispatch)
     {
       tree table_index 
 	= build_int_2 (get_symbol_table_index 
@@ -1509,7 +1516,9 @@
 
   /* 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))
     {
@@ -1564,6 +1573,11 @@
 	  && ! flag_keep_inline_functions
 	  && (flag_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);
@@ -1607,10 +1621,8 @@
   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
@@ -1706,8 +1718,14 @@
   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", build_int_2 (field_count, 0));
+  /* 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_2 (field_count, 0));
   PUSH_FIELD_VALUE (cons, "static_field_count",
 		    build_int_2 (static_field_count, 0));
 
@@ -1776,6 +1794,10 @@
     DECL_ALIGN (decl) = 64; 
   
   rest_of_decl_compilation (decl, (char*) 0, 1, 0);
+  
+  TYPE_OTABLE_DECL (type) = NULL_TREE;
+  TYPE_ATABLE_DECL (type) = NULL_TREE;
+  TYPE_CTABLE_DECL (type) = NULL_TREE;
 }
 
 void
@@ -2210,7 +2232,8 @@
 	build_java_argument_signature (TREE_TYPE (method_decl));
       tree super_method = lookup_argument_method (super_class, method_name,
 						  method_sig);
-      if (super_method != NULL_TREE && ! METHOD_PRIVATE (super_method))
+      if (super_method != NULL_TREE && ! METHOD_PRIVATE (super_method)
+	  && ! DECL_ARTIFICIAL (super_method))
 	{
 	  tree method_index = get_method_index (super_method);
 	  set_method_index (method_decl, method_index);
Index: gcc/java/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.191
diff -u -r1.191 expr.c
--- gcc/java/expr.c	14 May 2004 02:29:32 -0000	1.191
+++ gcc/java/expr.c	20 May 2004 19:37:46 -0000
@@ -317,6 +317,21 @@
   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;
@@ -335,8 +350,18 @@
 	return object_ptr_type_node;
     }
 
+  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,
@@ -355,7 +380,7 @@
 pop_type (tree type)
 {
   char *message = NULL;
-  type = pop_type_0 (type, &message);
+   type = pop_type_0 (type, &message);
   if (message != NULL)
     {
       error ("%s", message);
@@ -381,6 +406,14 @@
 
   if (source_type == target_type)
     return 1;
+
+  if (TYPE_DUMMY (source_type) || TYPE_DUMMY (target_type))
+    {
+      warning ("assert: %s is assign compatible with %s", 
+	       xstrdup (lang_printable_name (target_type, 0)),
+	       xstrdup (lang_printable_name (source_type, 0)));
+      return 1;
+    }
   else
     {
       if (TYPE_ARRAY_P (source_type) || TYPE_ARRAY_P (target_type))
@@ -414,7 +447,14 @@
 	  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))
+	    {
+	      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;
 
@@ -1147,6 +1187,19 @@
     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)
 {
@@ -1157,10 +1210,7 @@
   if (! CLASS_LOADED_P (type))
     load_class (type, 1);
   safe_layout_class (type);
-  push_value (build (CALL_EXPR, promote_type (type),
-		     build_address_of (alloc_node),
-		     build_tree_list (NULL_TREE, build_class_ref (type)),
-		     NULL_TREE));
+  push_value (java_create_object (type));
 }
 
 /* This returns an expression which will extract the class of an
@@ -1520,12 +1570,13 @@
       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_2 (get_symbol_table_index 
@@ -1813,8 +1864,16 @@
   tree func;
   if (is_compiled_class (self_type))
     {
-      if (!flag_indirect_dispatch
-	  || (!TREE_PUBLIC (method) && DECL_CONTEXT (method)))
+      /* At one point I used 
+
+      (!TREE_PUBLIC (method) && DECL_CONTEXT (method))) 
+      
+      here, meaning that we would make a direct call to methods that
+      are in the current compilation unit and not public.  That ought
+      to work, right?  Wrong.  Unfortunately, for some reason we still
+      generate a PLT jump for such methods, and they can end up being
+      resolved in some other library.  Sigh.  */
+      if (!flag_indirect_dispatch)
 	{
 	  make_decl_rtl (method, NULL);
 	  func = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (method)),
@@ -2059,31 +2118,54 @@
     method = lookup_java_method (self_type, method_name, method_signature);
   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;
+	      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)
+	{
+	  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
 	{
-	  error ("invoke[non-static] on static method");
-	  method = NULL_TREE;
+	  if (METHOD_STATIC (method))
+	    {
+	      error ("invoke[non-static] on static method");
+	      method = NULL_TREE;
+	    }
 	}
     }
 
@@ -2358,10 +2440,11 @@
 expand_java_field_op (int is_static, int is_putting, int field_ref_index)
 {
   tree self_type = 
-      get_class_constant (current_jcf, 
-			  COMPONENT_REF_CLASS_INDEX (&current_jcf->cpool, 
-						     field_ref_index));
-  const char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
+    get_class_constant (current_jcf, 
+			COMPONENT_REF_CLASS_INDEX (&current_jcf->cpool, 
+						   field_ref_index));
+  const char *self_name = 
+    IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
   tree field_name = COMPONENT_REF_NAME (&current_jcf->cpool, field_ref_index);
   tree field_signature = COMPONENT_REF_SIGNATURE (&current_jcf->cpool, 
 						  field_ref_index);
@@ -2369,6 +2452,7 @@
   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 = lookup_field (&self_type, field_name);
   if (field_decl == error_mark_node)
     {
@@ -2376,9 +2460,23 @@
     }
   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)
     {
Index: gcc/java/java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.200
diff -u -r1.200 java-tree.h
--- gcc/java/java-tree.h	13 May 2004 06:40:35 -0000	1.200
+++ gcc/java/java-tree.h	20 May 2004 19:37:47 -0000
@@ -244,6 +244,8 @@
    before static field references.  */
 extern int always_initialize_class_p;
 
+extern int flag_verify_invocations;
+
 typedef struct CPool constant_pool;
 
 #define CONSTANT_ResolvedFlag 16
@@ -986,6 +988,7 @@
   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(())
@@ -1044,6 +1047,9 @@
 #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)
@@ -1105,6 +1111,7 @@
   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
@@ -1271,6 +1278,7 @@
 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);
@@ -1357,6 +1365,8 @@
 #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
 
 /* 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))
Index: gcc/java/jcf-parse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-parse.c,v
retrieving revision 1.159
diff -u -r1.159 jcf-parse.c
--- gcc/java/jcf-parse.c	13 May 2004 06:40:36 -0000	1.159
+++ gcc/java/jcf-parse.c	20 May 2004 19:37:47 -0000
@@ -566,6 +566,11 @@
   tree name, saved;
   int class_loaded;
 
+  /* 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)
     name = class_or_name;
@@ -600,8 +605,30 @@
 	break;
     }
 
-  if (!class_loaded && verbose)
-    error ("cannot find file for class %s", IDENTIFIER_POINTER (saved));
+  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.  */
+	  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. */
@@ -716,7 +743,7 @@
     {
       JCF *jcf = current_jcf;
 
-      if (METHOD_ABSTRACT (method))
+      if (METHOD_ABSTRACT (method) || METHOD_DUMMY (method))
 	continue;
 
       if (METHOD_NATIVE (method))
Index: gcc/java/lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lang.c,v
retrieving revision 1.152
diff -u -r1.152 lang.c
--- gcc/java/lang.c	13 May 2004 06:40:36 -0000	1.152
+++ gcc/java/lang.c	20 May 2004 19:37:47 -0000
@@ -179,6 +179,9 @@
    in order to improve binary compatibility. */
 int flag_indirect_dispatch = 0;
 
+/* Don't attempt to verify invocations.  */
+int flag_verify_invocations = 0; 
+
 /* When zero, don't generate runtime array store checks. */
 int flag_store_check = 1;
 
@@ -1127,6 +1130,10 @@
   tree method, table, element, atable_methods;
 
   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;
Index: gcc/java/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.479
diff -u -r1.479 parse.y
--- gcc/java/parse.y	13 May 2004 06:40:36 -0000	1.479
+++ gcc/java/parse.y	20 May 2004 19:37:48 -0000
@@ -10805,8 +10805,7 @@
   if (TREE_CODE (original_call) == NEW_CLASS_EXPR)
     {
       tree class = DECL_CONTEXT (method);
-      tree c1, saved_new, size, new;
-      tree alloc_node;
+      tree c1, saved_new, new;
 
       if (flag_emit_class_files || flag_emit_xref)
 	{
@@ -10815,14 +10814,7 @@
 	}
       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);
-      new = build (CALL_EXPR, promote_type (class),
-		     build_address_of (alloc_node),
-		     build_tree_list (NULL_TREE, build_class_ref (class)),
-		     NULL_TREE);
+      new = java_create_object (class);
       saved_new = save_expr (new);
       c1 = build_tree_list (NULL_TREE, saved_new);
       TREE_CHAIN (c1) = TREE_OPERAND (original_call, 1);
Index: gcc/java/verify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/verify.c,v
retrieving revision 1.59
diff -u -r1.59 verify.c
--- gcc/java/verify.c	20 Dec 2003 15:38:28 -0000	1.59
+++ gcc/java/verify.c	20 May 2004 19:37:48 -0000
@@ -84,23 +84,23 @@
 
   if (current_subr == NULL)
     {
-      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;
 }
@@ -121,6 +121,58 @@
   return nesting;
 }
 
+static tree
+defer_merging (tree type1, tree type2)
+{
+  if (TYPE_DUMMY (type1) || TYPE_DUMMY (type2))
+    {
+      warning ("assert: cannot merge types %s and %s", 
+	       xstrdup (lang_printable_name (type1, 0)),
+	       xstrdup (lang_printable_name (type2, 0)));
+    }
+
+  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.
@@ -133,7 +185,11 @@
     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;
@@ -148,6 +204,9 @@
       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))
@@ -650,6 +709,8 @@
 	  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");
@@ -663,6 +724,7 @@
 		: 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;
@@ -1023,6 +1085,11 @@
 						       index));
 	    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 (IDENTIFIER_POINTER (sig),
@@ -1057,6 +1124,7 @@
 		  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)
Index: libjava/ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/libjava/ChangeLog,v
retrieving revision 1.2824
diff -u -r1.2824 ChangeLog
--- libjava/ChangeLog	14 May 2004 16:35:05 -0000	1.2824
+++ libjava/ChangeLog	20 May 2004 19:37:59 -0000
@@ -1,3 +1,111 @@
+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-05-14  Steven Augart  <augart@watson.ibm.com>
 
 	* include/jni.h (_Jv_func): Removed.
Index: libjava/Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.375
diff -u -r1.375 Makefile.am
--- libjava/Makefile.am	6 May 2004 10:25:01 -0000	1.375
+++ libjava/Makefile.am	20 May 2004 19:37:59 -0000
@@ -500,6 +500,9 @@
 gnu/gcj/runtime/StackTrace.lo: gnu/gcj/runtime/StackTrace.java
 	$(GCJCOMPILE) -fno-optimize-sibling-calls -o $@ $<
 
+java/io/ObjectInputStream.lo: java/io/ObjectInputStream.java
+	$(GCJCOMPILE) -fno-optimize-sibling-calls -o $@ $<
+
 ## Pass the list of object files to libtool in a temporary file to 
 ## avoid tripping platform command line length limits.
 libgcj.la: $(libgcj_la_OBJECTS) $(libgcj_la_DEPENDENCIES)
@@ -2225,6 +2228,7 @@
 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 \
@@ -2898,6 +2902,7 @@
 gnu/gcj/runtime/natStackTrace.cc \
 gnu/gcj/runtime/natStringBuffer.cc \
 gnu/gcj/runtime/natVMClassLoader.cc \
+gnu/gcj/util/natDebug.cc \
 gnu/java/awt/natEmbeddedWindow.cc \
 gnu/java/net/natPlainDatagramSocketImpl.cc \
 gnu/java/net/natPlainSocketImpl.cc \
Index: libjava/Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.in,v
retrieving revision 1.399
diff -u -r1.399 Makefile.in
--- libjava/Makefile.in	6 May 2004 10:25:01 -0000	1.399
+++ libjava/Makefile.in	20 May 2004 19:38:00 -0000
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am
 
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
@@ -1897,6 +1897,7 @@
 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 \
@@ -2569,6 +2570,7 @@
 gnu/gcj/runtime/natStackTrace.cc \
 gnu/gcj/runtime/natStringBuffer.cc \
 gnu/gcj/runtime/natVMClassLoader.cc \
+gnu/gcj/util/natDebug.cc \
 gnu/java/awt/natEmbeddedWindow.cc \
 gnu/java/net/natPlainDatagramSocketImpl.cc \
 gnu/java/net/natPlainSocketImpl.cc \
@@ -2750,7 +2752,7 @@
 gnu/gcj/runtime/natFirstThread.lo gnu/gcj/runtime/natNameFinder.lo \
 gnu/gcj/runtime/natSharedLibLoader.lo gnu/gcj/runtime/natStackTrace.lo \
 gnu/gcj/runtime/natStringBuffer.lo gnu/gcj/runtime/natVMClassLoader.lo \
-gnu/java/awt/natEmbeddedWindow.lo \
+gnu/gcj/util/natDebug.lo gnu/java/awt/natEmbeddedWindow.lo \
 gnu/java/net/natPlainDatagramSocketImpl.lo \
 gnu/java/net/natPlainSocketImpl.lo \
 gnu/java/net/protocol/core/natCoreInputStream.lo \
@@ -3079,7 +3081,8 @@
 .deps/gnu/gcj/runtime/natSharedLibLoader.P \
 .deps/gnu/gcj/runtime/natStackTrace.P \
 .deps/gnu/gcj/runtime/natStringBuffer.P \
-.deps/gnu/gcj/runtime/natVMClassLoader.P .deps/gnu/gcj/xlib/Clip.P \
+.deps/gnu/gcj/runtime/natVMClassLoader.P .deps/gnu/gcj/util/Debug.P \
+.deps/gnu/gcj/util/natDebug.P .deps/gnu/gcj/xlib/Clip.P \
 .deps/gnu/gcj/xlib/Colormap.P .deps/gnu/gcj/xlib/Display.P \
 .deps/gnu/gcj/xlib/Drawable.P .deps/gnu/gcj/xlib/Font.P \
 .deps/gnu/gcj/xlib/GC.P .deps/gnu/gcj/xlib/Pixmap.P \
@@ -5043,7 +5046,7 @@
 	dot_seen=no; \
 	rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
 	  rev="$$subdir $$rev"; \
-	  test "$$subdir" = "." && dot_seen=yes; \
+	  test "$$subdir" != "." || dot_seen=yes; \
 	done; \
 	test "$$dot_seen" = "no" && rev=". $$rev"; \
 	target=`echo $@ | sed s/-recursive//`; \
@@ -5404,6 +5407,9 @@
 	$(GCJCOMPILE) -fjni -o $@ $<
 
 gnu/gcj/runtime/StackTrace.lo: gnu/gcj/runtime/StackTrace.java
+	$(GCJCOMPILE) -fno-optimize-sibling-calls -o $@ $<
+
+java/io/ObjectInputStream.lo: java/io/ObjectInputStream.java
 	$(GCJCOMPILE) -fno-optimize-sibling-calls -o $@ $<
 
 libgcj.la: $(libgcj_la_OBJECTS) $(libgcj_la_DEPENDENCIES)
Index: libjava/defineclass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/defineclass.cc,v
retrieving revision 1.37
diff -u -r1.37 defineclass.cc
--- libjava/defineclass.cc	6 May 2004 14:06:28 -0000	1.37
+++ libjava/defineclass.cc	20 May 2004 19:38:00 -0000
@@ -971,7 +971,7 @@
 	}
     } 
 
-  for (; super != 0; super = super->superclass)
+  for (; super != 0; super = super->getSuperclass ())
     {
       if (super == sub)
 	throw_class_circularity_error (sub->getName ());
Index: libjava/resolve.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/resolve.cc,v
retrieving revision 1.45
diff -u -r1.45 resolve.cc
--- libjava/resolve.cc	20 Apr 2004 01:38:44 -0000	1.45
+++ libjava/resolve.cc	20 May 2004 19:38:00 -0000
@@ -57,8 +57,6 @@
 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,
@@ -372,9 +370,31 @@
   _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)
+      jclass interface = iface_class->interfaces[i];
+      
+      typedef unsigned int uaddr __attribute__ ((mode (pointer)));
+
+      // If interface looks like a constant pool entry,
+      // resolve it now.
+      if (interface && (uaddr)interface < (uaddr)iface_class->constants.size)
+	{
+	  if (iface_class->state < JV_STATE_LINKED) // This can't ever happen
+	    {
+	      _Jv_Utf8Const *name = iface_class->constants.data[(int)interface].utf8;
+	      interface = _Jv_FindClass (name, iface_class->loader);
+	      if (! interface)
+		{
+		  jstring str = _Jv_NewStringUTF (name->data);
+		  throw new java::lang::NoClassDefFoundError (str);
+		}
+	    }
+	  else
+	    interface = iface_class->constants.data[(int)interface].clazz;
+	}
+
+      for (int j = 0; j < interface->method_count; ++j)
 	{
-	  _Jv_Method *meth = &iface_class->interfaces[i]->methods[j];
+ 	  _Jv_Method *meth = &interface->methods[j];
 	  // Don't bother with <clinit>.
 	  if (meth->name->data[0] == '<')
 	    continue;
@@ -412,7 +432,7 @@
 	    }
 	}
 
-      _Jv_PrepareMissingMethods (base, iface_class->interfaces[i]);
+      _Jv_PrepareMissingMethods (base, interface);
     }
 }
 
@@ -452,93 +472,13 @@
   // resolved.
 
   if (klass->superclass)
-    java::lang::VMClassLoader::resolveClass (klass->superclass);
-
-  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
+    java::lang::VMClassLoader::resolveClass (klass->getSuperclass());
 
   /************ 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;
+  _Jv_LayoutClass(klass, &static_size);
 
-  // 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;
+  _Jv_InterpClass *iclass = (_Jv_InterpClass*)klass->aux_info;
 
   // allocate static memory
   if (static_size != 0)
@@ -739,42 +679,6 @@
       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)
Index: libjava/verify.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/verify.cc,v
retrieving revision 1.62
retrieving revision 1.62.2.1
diff -u -r1.62 -r1.62.2.1
--- libjava/verify.cc	19 Mar 2004 17:38:23 -0000	1.62
+++ libjava/verify.cc	16 Apr 2004 12:49:48 -0000	1.62.2.1
@@ -559,7 +559,7 @@
 	      {
 		// 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;
 	      }
 	  }
Index: libjava/gnu/gcj/runtime/SharedLibHelper.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/runtime/SharedLibHelper.java,v
retrieving revision 1.1
diff -u -r1.1 SharedLibHelper.java
--- libjava/gnu/gcj/runtime/SharedLibHelper.java	28 Aug 2003 22:17:36 -0000	1.1
+++ libjava/gnu/gcj/runtime/SharedLibHelper.java	20 May 2004 19:38:00 -0000
@@ -16,6 +16,9 @@
 
 public class SharedLibHelper
 {
+   private final java.util.HashMap h = 
+     new java.util.HashMap();
+
   /** Load a shared library, and associate a ClassLoader with it.
    * @param libname named of shared library (passed to dlopen)
    * @param parent the parent ClassLoader
@@ -73,7 +76,19 @@
   public Class findClass(String name)
   {
     ensureInit();
-    return (Class) classMap.get(name);
+    Class c = (Class) classMap.get(name);
+    if (c != null)
+    {
+      String s = System.getProperty("gnu.classpath.verbose");
+      if (s != null && s.equals("class"))
+	if (h.get(name) == null)
+	  {
+	    System.err.println("[Loading class " + name 
+			       + " from " + this + "]");
+	    h.put(name,name);
+	  }
+    }
+    return c;
   }
 
   public URL findResource (String name)
@@ -106,6 +121,11 @@
 
   native boolean hasResource(String name);
   native void init();
+
+  public String toString ()
+  {
+    return "shared object " + baseName;
+  }
 
   /** Called during dlopen's processing of the init section. */
   void registerClass(String name, Class cls)
Index: libjava/gnu/javax/rmi/CORBA/DelegateFactory.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/javax/rmi/CORBA/Attic/DelegateFactory.java,v
retrieving revision 1.2
retrieving revision 1.2.2.1
diff -u -r1.2 -r1.2.2.1
--- libjava/gnu/javax/rmi/CORBA/DelegateFactory.java	16 Mar 2004 09:41:31 -0000	1.2
+++ libjava/gnu/javax/rmi/CORBA/DelegateFactory.java	16 Apr 2004 12:49:56 -0000	1.2.2.1
@@ -54,23 +54,33 @@
     String dcname = System.getProperty("javax.rmi.CORBA." + type + "Class");
     if (dcname == null)
       {
-	//throw new DelegateException
-	//  ("no javax.rmi.CORBA.XXXClass property sepcified.");
-	dcname = "gnu.javax.rmi.CORBA." + type + "DelegateImpl";
+		//throw new DelegateException
+		//  ("no javax.rmi.CORBA.XXXClass property sepcified.");
+		dcname = "gnu.javax.rmi.CORBA." + type + "DelegateImpl";
       }
     try
       {
-	Class dclass = Class.forName(dcname, 
-				     true,
-				     Thread.currentThread().getContextClassLoader());
-	r = dclass.newInstance();
-	cache.put(type, r);
-	return r;
+		Class dclass;
+		try
+	      {
+			dclass = Class.forName(dcname);
+	      }
+		catch (ClassNotFoundException c)
+	      {
+			ClassLoader loader = Thread.currentThread().getContextClassLoader();
+			if (loader != null)
+		      dclass = Class.forName(dcname, true, loader);
+			else
+		      throw c;
+	      }
+		r = dclass.newInstance();
+		cache.put(type, r);
+		return r;
       }
     catch(Exception e)
       {
-	throw new GetDelegateInstanceException
-	  ("Exception when trying to get delegate instance:" + dcname, e);
+		throw new GetDelegateInstanceException
+		  ("Exception when trying to get delegate instance:" + dcname, e);
       }
   }
 }
Index: libjava/java/io/ObjectInputStream.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectInputStream.java,v
retrieving revision 1.31
diff -u -r1.31 ObjectInputStream.java
--- libjava/java/io/ObjectInputStream.java	20 Apr 2004 11:37:41 -0000	1.31
+++ libjava/java/io/ObjectInputStream.java	20 May 2004 19:38:02 -0000
@@ -52,6 +52,20 @@
 import java.util.Vector;
 
 
+class MyIOException extends IOException
+{
+    MyIOException (String s)
+    {
+	super(s);
+	if (Configuration.DEBUG)
+	    {
+		String val = System.getProperty("gcj.dumpobjects");
+		if (val != null && !val.equals(""))
+		    System.out.println (this);
+	    }
+    }
+}
+
 public class ObjectInputStream extends InputStream
   implements ObjectInput, ObjectStreamConstants
 {
@@ -120,6 +134,15 @@
    */
   public final Object readObject() throws ClassNotFoundException, IOException
   {
+      if (callersClassLoader == null)
+	{
+	  callersClassLoader = getCallersClassLoader ();
+	  if (Configuration.DEBUG)
+	    {
+	      dumpElementln ("CallersClassLoader = " + callersClassLoader);
+	    }
+	}
+
     if (this.useSubclassMethod)
       return readObjectOverride();
 
@@ -134,6 +157,9 @@
     this.isDeserializing = true;
 
     byte marker = this.realInputStream.readByte();
+
+    depth += 2;
+
     if(dump) dumpElement("MARKER: 0x" + Integer.toHexString(marker) + " ");
 
     try
@@ -151,9 +177,9 @@
 	  case TC_BLOCKDATALONG:
 	    {
 	      if (marker == TC_BLOCKDATALONG)
-		if(dump) dumpElementln("BLOCKDATALONG");
+		{ if(dump) dumpElementln("BLOCKDATALONG"); }
 	      else
-		if(dump) dumpElementln("BLOCKDATA");
+		{ if(dump) dumpElementln("BLOCKDATA"); }
 	      readNextBlock(marker);
 	      throw new StreamCorruptedException("Unexpected blockData");
 	    }
@@ -207,7 +233,7 @@
 		{
 		  byte b = this.realInputStream.readByte();
 		  if (b != TC_ENDBLOCKDATA)
-		    throw new IOException("Data annotated to class was not consumed." + b);
+		    throw new MyIOException("Data annotated to class was not consumed." + b);
 		}
 	      else
 		is_consumed = false;
@@ -225,7 +251,7 @@
 		{
 		  byte b = this.realInputStream.readByte();
 		  if (b != TC_ENDBLOCKDATA)
-		    throw new IOException("Data annotated to class was not consumed." + b);
+		    throw new MyIOException("Data annotated to class was not consumed." + b);
 		}
 	      else
 		is_consumed = false;
@@ -258,7 +284,7 @@
 	      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;
 	    }
@@ -319,6 +345,9 @@
 	      Object obj = newObject(clazz, osc.firstNonSerializableParent);
 	      
 	      int handle = assignNewHandle(obj);
+	      Object prevObject = this.currentObject;
+	      ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
+	      
 	      this.currentObject = obj;
 	      ObjectStreamClass[] hierarchy =
 		inputGetObjectStreamClasses(clazz);
@@ -341,34 +370,42 @@
 		      boolean oldmode = setBlockDataMode(true);
 		      callReadMethod(readObjectMethod, this.currentObjectStreamClass.forClass(), obj);
 		      setBlockDataMode(oldmode);
+		    }
+		  else
+		    {
+		      readFields(obj, currentObjectStreamClass);
+		    }
+
+		  if (this.currentObjectStreamClass.hasWriteMethod())
+		    {
 		      if(dump) dumpElement("ENDBLOCKDATA? ");
 		      try
 			{
-			  // FIXME: XXX: This try block is to catch EOF which is
-			  // thrown for some objects.  That indicates a bug in the logic.
+			  // FIXME: XXX: This try block is to
+			  // catch EOF which is thrown for some
+			  // objects.  That indicates a bug in
+			  // the logic.
+
 			  if (this.realInputStream.readByte() != TC_ENDBLOCKDATA)
-			    throw new IOException
+			    throw new MyIOException
 			      ("No end of block data seen for class with readObject (ObjectInputStream) method.");
 			  if(dump) dumpElementln("yes");
 			}
-		      catch (EOFException e)
-			{
-			  if(dump) dumpElementln("no, got EOFException");
-			}
+// 		      catch (EOFException e)
+// 			{
+// 			  if(dump) dumpElementln("no, got EOFException");
+// 			}
 		      catch (IOException e)
 			{
 			  if(dump) dumpElementln("no, got IOException");
 			}
 		    }
-		  else
-		    {
-		      readFields(obj, currentObjectStreamClass);
-		    }
 		}
 
-	      this.currentObject = null;
-	      this.currentObjectStreamClass = null;
+	      this.currentObject = prevObject;
+	      this.currentObjectStreamClass = prevObjectStreamClass;
 	      ret_val = processResolution(osc, obj, handle);
+		  
 	      break;
 	    }
 
@@ -388,7 +425,7 @@
 	    }
 
 	  default:
-	    throw new IOException("Unknown marker on stream: " + marker);
+	    throw new MyIOException("Unknown marker on stream: " + marker);
 	  }
       }
     finally
@@ -396,6 +433,8 @@
 	setBlockDataMode(old_mode);
 	
 	this.isDeserializing = was_deserializing;
+
+	depth -= 2;
 	
 	if (! was_deserializing)
 	  {
@@ -710,7 +749,7 @@
   protected Class resolveClass(ObjectStreamClass osc)
     throws ClassNotFoundException, IOException
   {
-    return Class.forName(osc.getName(), true, currentLoader());
+    return Class.forName(osc.getName(), true, callersClassLoader);
   }
 
   /**
@@ -1802,11 +1841,9 @@
    * @param sm SecurityManager instance which should be called.
    * @return The current class loader in the calling stack.
    */
-  private static ClassLoader currentClassLoader (SecurityManager sm)
-  {
-    // FIXME: This is too simple.
-    return ClassLoader.getSystemClassLoader ();
-  }
+    private static native ClassLoader currentClassLoader (SecurityManager sm);
+
+    private native ClassLoader getCallersClassLoader();
 
   private void callReadMethod (Method readObject, Class klass, Object obj) throws IOException
   {
@@ -1864,14 +1901,21 @@
 
   private static boolean dump = false && Configuration.DEBUG;
 
+  private ClassLoader callersClassLoader;
+
+  private int depth = 0;
+
   private void dumpElement (String msg)
-  {
+  {	
     System.out.print(msg);
   }
   
   private void dumpElementln (String msg)
   {
     System.out.println(msg);
+    for (int i = 0; i < depth; i++)
+      System.out.print (" ");
+    System.out.print (Thread.currentThread() + ": ");
   }
 
   static
Index: libjava/java/io/ObjectOutputStream.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectOutputStream.java,v
retrieving revision 1.24
diff -u -r1.24 ObjectOutputStream.java
--- libjava/java/io/ObjectOutputStream.java	31 Dec 2003 11:04:21 -0000	1.24
+++ libjava/java/io/ObjectOutputStream.java	20 May 2004 19:38:02 -0000
@@ -172,10 +172,26 @@
   {
     if (useSubclassMethod)
       {
+	if (Configuration.DEBUG)
+	  {
+	    String val = System.getProperty("gcj.dumpobjects");
+	    if (val != null && !val.equals(""))
+	      dumpElementln ("WRITE OVERRIDE: " + obj);
+	  }
+	  
 	writeObjectOverride(obj);
 	return;
       }
 
+    if (Configuration.DEBUG)
+      {
+	String val = System.getProperty("gcj.dumpobjects");
+	if (val != null && !val.equals(""))
+	  dumpElementln ("WRITE: " + obj);
+      }
+    
+    depth += 2;    
+
     boolean was_serializing = isSerializing;
     boolean old_mode = setBlockDataMode(false);
     try
@@ -318,6 +334,8 @@
 
 	    if (obj instanceof Serializable)
 	      {
+		Object prevObject = this.currentObject;
+		ObjectStreamClass prevObjectStreamClass = this.currentObjectStreamClass;
 		currentObject = obj;
 		ObjectStreamClass[] hierarchy =
 		  ObjectStreamClass.getObjectStreamClasses(clazz);
@@ -329,17 +347,22 @@
 		    fieldsAlreadyWritten = false;
 		    if (currentObjectStreamClass.hasWriteMethod())
 		      {
+			dumpElementln ("WRITE METHOD CALLED FOR: " + obj);
 			setBlockDataMode(true);
 			callWriteMethod(obj, currentObjectStreamClass);
 			setBlockDataMode(false);
 			realOutput.writeByte(TC_ENDBLOCKDATA);
+			dumpElementln ("WRITE ENDBLOCKDATA FOR: " + obj);
 		      }
 		    else
-		      writeFields(obj, currentObjectStreamClass);
+		      {
+			dumpElementln ("WRITE FIELDS CALLED FOR: " + obj);
+			writeFields(obj, currentObjectStreamClass);
+		      }
 		  }
 
-		currentObject = null;
-		currentObjectStreamClass = null;
+		this.currentObject = prevObject;
+		this.currentObjectStreamClass = prevObjectStreamClass;
 		currentPutField = null;
 		break;
 	      }
@@ -360,12 +383,22 @@
 	setBlockDataMode(false);
 	try
 	  {
+	    if (Configuration.DEBUG)
+	      {
+		e.printStackTrace(System.out);
+	      }
 	    writeObject(e);
 	  }
 	catch (IOException ioe)
 	  {
-	    throw new StreamCorruptedException
-	      ("Exception " + ioe + " thrown while exception was being written to stream.");
+	    StreamCorruptedException ex = 
+	      new StreamCorruptedException
+	      (ioe + " thrown while exception was being written to stream.");
+	    if (Configuration.DEBUG)
+	      {
+		ex.printStackTrace(System.out);
+	      }
+	    throw ex;
 	  }
 
 	reset (true);
@@ -375,6 +408,15 @@
       {
 	isSerializing = was_serializing;
 	setBlockDataMode(old_mode);
+	depth -= 2;
+
+	if (Configuration.DEBUG)
+	  {
+	    String val = System.getProperty("gcj.dumpobjects");
+	    if (val != null && !val.equals(""))
+	      dumpElementln ("END: " + obj);
+	  }
+    
       }
   }
 
@@ -1171,6 +1213,14 @@
 	field_name = fields[i].getName();
 	type = fields[i].getType();
 
+	if (Configuration.DEBUG)
+	  {
+	    String val = System.getProperty("gcj.dumpobjects");
+	    if (val != null && !val.equals(""))
+	      dumpElementln ("WRITE FIELD: " + field_name + " type=" + type);
+	  }
+
+
 	if (type == Boolean.TYPE)
 	  realOutput.writeBoolean(getBooleanField(obj, osc.forClass(), field_name));
 	else if (type == Byte.TYPE)
@@ -1512,6 +1562,14 @@
     return m;
   }
 
+   private void dumpElementln (String msg)
+  {
+    for (int i = 0; i < depth; i++)
+      System.out.print (" ");
+    System.out.print (Thread.currentThread() + ": ");
+    System.out.println(msg);
+  }
+
   // this value comes from 1.2 spec, but is used in 1.1 as well
   private final static int BUFFER_SIZE = 1024;
 
@@ -1533,6 +1591,8 @@
   private Hashtable OIDLookupTable;
   private int protocolVersion;
   private boolean useSubclassMethod;
+
+  private int depth = 0;
 
   static
   {
Index: libjava/java/io/natObjectInputStream.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/natObjectInputStream.cc,v
retrieving revision 1.7
diff -u -r1.7 natObjectInputStream.cc
--- libjava/java/io/natObjectInputStream.cc	20 Apr 2004 01:38:45 -0000	1.7
+++ libjava/java/io/natObjectInputStream.cc	20 May 2004 19:38:03 -0000
@@ -19,6 +19,8 @@
 #include <java/lang/Class.h>
 #include <java/lang/reflect/Modifier.h>
 #include <java/lang/reflect/Method.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+#include <java/lang/SecurityManager.h>
 
 #ifdef DEBUG
 #include <java/lang/System.h>
@@ -69,3 +71,33 @@
 				+ m->offset);
   _Jv_CallAnyMethodA (obj, JvPrimClass (void), meth, false, arg_types, NULL);
 }
+
+java::lang::ClassLoader* 
+java::io::ObjectInputStream::getCallersClassLoader ()
+{
+  java::lang::ClassLoader *loader = NULL;
+  gnu::gcj::runtime::StackTrace *t 
+    = new gnu::gcj::runtime::StackTrace(4);
+  java::lang::Class *klass = NULL;
+  try
+    {
+      for (int i = 2; !klass; i++)
+	{
+	  klass = t->classAt (i);
+	}
+      loader = klass->getClassLoaderInternal();
+    }
+  catch (::java::lang::ArrayIndexOutOfBoundsException *e)
+    {
+      // FIXME: RuntimeError
+    }
+
+  return loader;
+}
+
+java::lang::ClassLoader*
+java::io::ObjectInputStream::currentClassLoader (::java::lang::SecurityManager *sm)
+{
+  return sm->currentClassLoader ();
+}
+
Index: libjava/java/lang/Class.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Class.h,v
retrieving revision 1.66
diff -u -r1.66 Class.h
--- libjava/java/lang/Class.h	21 Apr 2004 19:26:22 -0000	1.66
+++ libjava/java/lang/Class.h	20 May 2004 19:38:03 -0000
@@ -208,9 +208,20 @@
 
   inline jclass getSuperclass (void)
     {
+      if (state < JV_STATE_LINKED)
+	superclass =_Jv_ResolveClassRef (this, superclass);
+      
       return superclass;
     }
 
+  inline jclass getInterface (jint n)
+    {
+      if (state < JV_STATE_LINKED)
+	interfaces[n] =_Jv_ResolveClassRef (this, interfaces[n]);
+      
+      return interfaces[n];
+    }
+
   inline jboolean isArray (void)
     {
       return name->data[0] == '[';
@@ -243,8 +254,22 @@
   // FIXME: this probably shouldn't be public.
   jint size (void)
     {
+      // FIXME size_in_bytes == -1 is an evil way to test for BC compiled programs
+      if (size_in_bytes == (jint)-1)
+	{
+	  int static_size;
+	  _Jv_LayoutClass(this, &static_size);
+	}
+
       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 ();
@@ -271,6 +296,8 @@
   friend void *_Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, 
 					     int method_idx);
 
+  friend jclass _Jv_ResolveClassRef (jclass, jclass);
+
   inline friend void 
   _Jv_InitClass (jclass klass)
   {
@@ -278,6 +305,8 @@
       return;
     klass->initializeClass ();  
   }
+  
+  friend void _Jv_LayoutClass(jclass, int*);
 
   friend _Jv_Method* _Jv_LookupDeclaredMethod (jclass, _Jv_Utf8Const *, 
 					       _Jv_Utf8Const*);
@@ -347,7 +376,7 @@
 
   friend jboolean _Jv_CheckAccess (jclass self_klass, jclass other_klass,
 				   jint flags);
-
+  
   // Return array class corresponding to element type KLASS, creating it if
   // necessary.
   inline friend jclass
@@ -385,7 +414,6 @@
 #endif
 
   friend class _Jv_BytecodeVerifier;
-  friend class _Jv_StackTrace;
   friend class gnu::gcj::runtime::StackTrace;
   friend class java::io::VMObjectStreamClass;
 
Index: libjava/java/lang/ClassLoader.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/ClassLoader.java,v
retrieving revision 1.33
diff -u -r1.33 ClassLoader.java
--- libjava/java/lang/ClassLoader.java	3 May 2004 19:52:29 -0000	1.33
+++ libjava/java/lang/ClassLoader.java	20 May 2004 19:38:03 -0000
@@ -40,7 +40,9 @@
 
 import gnu.java.util.DoubleEnumeration;
 import gnu.java.util.EmptyEnumeration;
+import gnu.gcj.runtime.SharedLibHelper;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
@@ -288,6 +290,8 @@
     if (c != null)
       return c;
 
+    ClassNotFoundException ex = null;
+
     // Can the class be loaded by a parent?
     try
       {
@@ -304,9 +308,20 @@
       }
     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 +450,56 @@
       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);
+
+    // FIXME: This is a temporary hack that allows you to compile some
+    // class files into a .so called "gcjlib.so" in the same
+    // directory.  To be removed as soon as gcj-JIT is ready.
+    java.security.CodeSource source = domain.getCodeSource();
+    java.net.URL url = source != null ? source.getLocation() : null;
+    String filename = url.getFile();
+    if (filename != null)
+      {
+	File f = new File(filename);
+	if (f.isDirectory())
+	  {
+	    try
+	      {
+		Class c = null;
+		String libname = filename + "gcjlib.so";
+		File soFile = new File (libname);
+		if (soFile.isFile())
+		  {
+		    SharedLibHelper helper 
+		      = SharedLibHelper.findHelper (this, libname, source);
+		    c = helper.findClass (retval.getName());
+		  }
+		if (c != null)
+		  retval = c;
+	      }
+	    catch (UnknownError _)
+	      {
+	      }
+	  }
+      }
+    
+    {	    
+      String s = System.getProperty("gnu.classpath.verbose");
+      if (s != null && s.equals("class"))
+	{
+// 		java.security.CodeSource source = domain.getCodeSource();
+// 		java.net.URL url = source != null ? source.getLocation() : null;
+	  String URLname = url != null ? url.toString() : null;
+	  if (URLname == null)
+	    URLname = "unknown location";
+	  System.err.println("[Loading class " + retval.getName()
+			     + " from  " + URLname + "]");
+	}
+		
+    }
+
     loadedClasses.put(retval.getName(), retval);
     return retval;
   }
@@ -729,7 +792,7 @@
     if (sm != null)
       {
 	Class c = VMSecurityManager.getClassContext()[1];
-	ClassLoader cl = c.getClassLoader();
+	ClassLoader cl = getClassLoader0(c);
 	if (cl != null && cl != systemClassLoader)
 	  sm.checkPermission(new RuntimePermission("getClassLoader"));
       }
@@ -950,4 +1013,6 @@
       }
     return false;
   }
+
+    static private final native ClassLoader getClassLoader0(Class c);
 }
Index: libjava/java/lang/SecurityManager.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/SecurityManager.java,v
retrieving revision 1.11
diff -u -r1.11 SecurityManager.java
--- libjava/java/lang/SecurityManager.java	20 Apr 2004 12:30:18 -0000	1.11
+++ libjava/java/lang/SecurityManager.java	20 May 2004 19:38:03 -0000
@@ -324,7 +324,7 @@
   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 @@
     //   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 @@
     //   // 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.");
   }
 
   /**
Index: libjava/java/lang/VMSecurityManager.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/VMSecurityManager.java,v
retrieving revision 1.2
diff -u -r1.2 VMSecurityManager.java
--- libjava/java/lang/VMSecurityManager.java	5 Dec 2002 00:49:29 -0000	1.2
+++ libjava/java/lang/VMSecurityManager.java	20 May 2004 19:38:03 -0000
@@ -54,11 +54,12 @@
     // 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;
       }
 
Index: libjava/java/lang/natClass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClass.cc,v
retrieving revision 1.77
diff -u -r1.77 natClass.cc
--- libjava/java/lang/natClass.cc	21 Apr 2004 19:26:22 -0000	1.77
+++ libjava/java/lang/natClass.cc	20 May 2004 19:38:03 -0000
@@ -14,6 +14,7 @@
 #include <limits.h>
 #include <string.h>
 #include <stddef.h>
+#include <stdio.h>
 
 #pragma implementation "Class.h"
 
@@ -59,10 +60,75 @@
 
 #include <java-cpool.h>
 #include <java-interp.h>
+#include <java-assert.h>
 
 
 using namespace gcj;
 
+template<typename T>
+struct aligner
+{
+  char c;
+  T field;
+};
+
+#define ALIGNOF(TYPE) (offsetof (aligner<TYPE>, field))
+
+// This returns the alignment of a type as it would appear in a
+// structure.  This can be different from the alignment of the type
+// itself.  For instance on x86 double is 8-aligned but struct{double}
+// is 4-aligned.
+static int
+get_alignment_from_class (jclass klass)
+{
+  if (klass == JvPrimClass (byte))
+    return ALIGNOF (jbyte);
+  else if (klass == JvPrimClass (short))
+    return ALIGNOF (jshort);
+  else if (klass == JvPrimClass (int)) 
+    return ALIGNOF (jint);
+  else if (klass == JvPrimClass (long))
+    return ALIGNOF (jlong);
+  else if (klass == JvPrimClass (boolean))
+    return ALIGNOF (jboolean);
+  else if (klass == JvPrimClass (char))
+    return ALIGNOF (jchar);
+  else if (klass == JvPrimClass (float))
+    return ALIGNOF (jfloat);
+  else if (klass == JvPrimClass (double))
+    return ALIGNOF (jdouble);
+  else
+    return ALIGNOF (jobject);
+}
+
+jclass
+_Jv_ResolveClassRef (jclass klass, jclass classref)
+{
+  jclass ret = classref;
+
+  typedef unsigned int uaddr __attribute__ ((mode (pointer)));
+
+  // If superclass looks like a constant pool entry,
+  // resolve it now.
+  if (classref && (uaddr)classref < (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)
+	    {
+	      jstring str = _Jv_NewStringUTF (name->data);
+	      throw new java::lang::NoClassDefFoundError (str);
+	    }
+	}
+      else
+	ret = klass->constants.data[(uaddr)classref].clazz;
+    }
+
+  return ret;
+}
+
 jclass
 java::lang::Class::forName (jstring className, jboolean initialize,
                             java::lang::ClassLoader *loader)
@@ -485,7 +551,12 @@
   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 +566,8 @@
   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)
@@ -794,6 +866,14 @@
     _Jv_LayoutInterfaceMethods (this);
 
   _Jv_PrepareConstantTimeTables (this);
+  
+  // Assign storage to fields
+  // FIXME size_in_bytes == -1 is an evil way to test for BC compiled programs
+  if (size_in_bytes == (jint)-1)
+    {
+      int static_size;
+      _Jv_LayoutClass(this, &static_size);
+    }
 
   if (vtable == NULL)
     _Jv_MakeVTable(this);
@@ -1515,6 +1595,9 @@
   hack_signers = s;
 }
 
+// Set this to true to enable debugging of indirect dispatch tables/linking.
+static bool debug_link = false;
+
 // Functions for indirect dispatch (symbolic virtual binding) support.
 
 // There are two tables, atable and otable.  atable is an array of
@@ -1546,10 +1629,11 @@
    
   klass->otable->state = 1;
 
+  if (debug_link)
+    fprintf (stderr, "Fixing up otable in %s:\n", klass->name->data);
   for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++)
     {
-      // FIXME: Why are we passing NULL as the class loader?
-      jclass target_class = _Jv_FindClass (sym.class_name, NULL);
+      jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
       _Jv_Method *meth = NULL;            
 
       const _Jv_Utf8Const *signature = sym.signature;
@@ -1561,7 +1645,8 @@
       }
 
       if (target_class == NULL)
-	continue;
+	throw new java::lang::NoClassDefFoundError 
+	  (_Jv_NewStringUTF (sym.class_name->data));
 
       if (target_class->isInterface())
 	{
@@ -1577,6 +1662,14 @@
 		      && _Jv_equalUtf8Consts (signature, meth->signature))
 		    {
 		      klass->otable->offsets[index] = i + 1;
+		      if (debug_link)
+			fprintf (stderr, "  offsets[%d] = %d (interface %s@%p : %s(%s))\n",
+				 index,
+				 klass->otable->offsets[index],
+				 (const char*)cls->name->data,
+				 klass,
+				 (const char*)sym.name->data,
+				 (const char*)signature->data);
 		      goto found;
 		    }
 		}
@@ -1594,21 +1687,32 @@
  	  // If the target class does not have a vtable_method_count yet, 
 	  // then we can't tell the offsets for its methods, so we must lay 
 	  // it out now.
+	  {
+	    JvSynchronize sync (target_class);
+	    _Jv_PrepareClass(target_class);
+	  }
 	  if (target_class->vtable_method_count == -1)
 	    {
 	      JvSynchronize sync (target_class);
 	      _Jv_LayoutVTableMethods (target_class);
 	    }
-		
+	  
 	  meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
 					  sym.signature);
-		
+	  
 	  if (meth != NULL)
 	    {
 	      klass->otable->offsets[index] = 
 		_Jv_VTable::idx_to_offset (meth->index);	      
 	    }
-
+	  if (debug_link)
+	    fprintf (stderr, "  offsets[%d] = %d (class %s@%p : %s(%s))\n",
+		     index,
+		     klass->otable->offsets[index],
+		     (const char*)target_class->name->data,
+		     target_class,
+		     (const char*)sym.name->data,
+		     (const char*)signature->data);
 	  continue;
 	}
 
@@ -1669,8 +1773,7 @@
 
   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);
+      jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
       _Jv_Method *meth = NULL;            
       const _Jv_Utf8Const *signature = sym.signature;
 
@@ -1679,7 +1782,8 @@
       klass->atable->addresses[index] = NULL;
       
       if (target_class == NULL)
-	continue;
+	throw new java::lang::NoClassDefFoundError 
+	  (_Jv_NewStringUTF (sym.class_name->data));
       
       // We're looking for a static field or a static method, and we
       // can tell which is needed by looking at the signature.
@@ -1701,11 +1805,32 @@
 	  if (meth != NULL)
 	    {
 	      if (meth->ncode) // Maybe abstract?
-		klass->atable->addresses[index] = meth->ncode;
+		{
+		  klass->atable->addresses[index] = meth->ncode;
+		  if (debug_link)
+		    fprintf (stderr, "  addresses[%d] = %p (class %s@%p : %s(%s))\n",
+			     index,
+			     &klass->atable->addresses[index],
+			     (const char*)target_class->name->data,
+			     klass,
+			     (const char*)sym.name->data,
+			     (const char*)signature->data);
+		}
 #ifdef INTERPRETER
 	      else if (_Jv_IsInterpretedClass (target_class))
-		_Jv_Defer_Resolution (target_class, meth, 
-				      &klass->atable->addresses[index]);
+		{
+		  _Jv_Defer_Resolution (target_class, meth, 
+					&klass->atable->addresses[index]);
+		  if (debug_link)
+		    fprintf (stderr, "  addresses[%d] = DEFERRED@%p (class %s@%p : %s(%s))\n",
+			     index,
+			     klass->atable->addresses[index],
+			     (const char*)target_class->name->data,
+			     klass,
+			     (const char*)sym.name->data,
+			     (const char*)signature->data);
+		
+		}
 #endif
 	    }
 	  else
@@ -1732,6 +1857,9 @@
 
 		if (!field->isResolved ())
 		  _Jv_ResolveField (field, cls->loader);
+
+		if (_Jv_IsInterpretedClass (target_class))
+		  _Jv_AssertDoCall ("can't fixup reference to static field in interpreted class");
 		
 // 		if (field_type != 0 && field->type != field_type)
 // 		  throw new java::lang::LinkageError
@@ -1775,9 +1903,17 @@
   catch_record++;
   while (catch_record->classname)
     {
-      jclass target_class = _Jv_FindClass (catch_record->classname,  
-					   self->getClassLoaderInternal ());
-      *catch_record->address = target_class;
+      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;
@@ -1815,27 +1951,7 @@
       || klass->vtable_method_count != -1)
     return;
 
-  jclass superclass = klass->superclass;
-
-  typedef unsigned int uaddr __attribute__ ((mode (pointer)));
-
-  // 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[(int)superclass].utf8;
-	  superclass = _Jv_FindClass (name, klass->loader);
-	  if (! superclass)
-	    {
-	      jstring str = _Jv_NewStringUTF (name->data);
-	      throw new java::lang::NoClassDefFoundError (str);
-	    }
-	}
-      else
-	superclass = klass->constants.data[(int)superclass].clazz;
-    }
+  jclass superclass = klass->getSuperclass();
 
   if (superclass != NULL && superclass->vtable_method_count == -1)
     {
@@ -1986,3 +2102,101 @@
 	  }
     }
 }
+
+void 
+_Jv_LayoutClass(jclass klass, int *static_size)
+{  
+  // 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)
+    {
+      // FIXME size_in_bytes == -1 is an evil way to test for BC compiled programs
+      if (super->size_in_bytes == (jint)-1)
+	_Jv_LayoutClass(super, static_size);
+      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;
+
+  // Although java.lang.Object is never interpreted, an interface can
+  // have a null superclass.  Note that we have to lay out an
+  // interface because it might have static fields.
+  if (klass->superclass)
+    instance_size = klass->superclass->size();
+  else
+    instance_size = java::lang::Object::class$.size();
+
+  for (int i = 0; i < klass->field_count; i++)
+    {
+      int field_size;
+      int field_align;
+
+      _Jv_Field *field = &klass->fields[i];
+
+      if (! field->isRef ())
+	{
+	  // it's safe to resolve the field here, since it's 
+	  // a primitive class, which does not cause loading to happen.
+	  _Jv_ResolveField (field, klass->loader);
+
+	  field_size = field->type->size ();
+	  field_align = get_alignment_from_class (field->type);
+	}
+      else 
+	{
+	  field_size = sizeof (jobject);
+	  field_align = __alignof__ (jobject);
+	}
+
+#ifndef COMPACT_FIELDS
+      field->bsize = field_size;
+#endif
+
+      if (field->flags & java::lang::reflect::Modifier::STATIC)
+	{
+	  if (_Jv_IsInterpretedClass (klass))
+	    {
+	      /* this computes an offset into a region we'll allocate
+		 shortly, and then add this offset to the start
+		 address */
+
+	      *static_size       = ROUND (*static_size, field_align);
+	      field->u.boffset   = *static_size;
+	      *static_size       += field_size;
+	    }
+	}
+      else
+	{
+	  instance_size      = ROUND (instance_size, field_align);
+	  if (field->u.boffset != instance_size)
+	    fprintf (stderr, "change to %s.%s: old = %d new=%d\n",
+		     (const char*)(klass->name->data), 
+		     (const char*)(field->name->data), 
+		     field->u.boffset, instance_size);
+	  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;
+}
+
Index: libjava/java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.65
diff -u -r1.65 natClassLoader.cc
--- libjava/java/lang/natClassLoader.cc	20 Apr 2004 01:38:46 -0000	1.65
+++ libjava/java/lang/natClassLoader.cc	20 May 2004 19:38:03 -0000
@@ -32,6 +32,7 @@
 #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>
@@ -55,7 +56,15 @@
 #ifdef INTERPRETER
       if (_Jv_IsInterpretedClass (klass))
 	_Jv_PrepareClass (klass);
+      else
 #endif
+	// Assign storage to fields
+	// FIXME size_in_bytes == -1 is an evil way to test for BC compiled programs
+	if (klass->size_in_bytes == (jint)-1)
+	  {   
+	    int static_size;
+	    _Jv_LayoutClass(klass, &static_size);
+	  }
       _Jv_PrepareCompiledClass (klass);
       _Jv_MonitorExit (klass);
       return;
@@ -89,90 +98,100 @@
   if (klass->state >= JV_STATE_LINKED)
     return;
 
-  // Short-circuit, so that mutually dependent classes are ok.
-  klass->state = JV_STATE_LINKED;
+  int state = klass->state;
+  try
+    {
+      // Short-circuit, so that mutually dependent classes are ok.
+      klass->state = JV_STATE_LINKED;
 
-  _Jv_Constants *pool = &klass->constants;
+      _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)
+      // Resolve class constants first, since other constant pool
+      // entries may rely on these.
+      for (int index = 1; index < pool->size; ++index)
 	{
-	  _Jv_Utf8Const *name = pool->data[index].utf8;
+	  if (pool->tags[index] == JV_CONSTANT_Class)
+	    {
+	      _Jv_Utf8Const *name = pool->data[index].utf8;
 	  
-	  jclass found;
-	  if (name->data[0] == '[')
-	    found = _Jv_FindClassFromSignature (&name->data[0],
-						klass->loader);
-	  else
-	    found = _Jv_FindClass (name, klass->loader);
+	      jclass found;
+	      if (name->data[0] == '[')
+		found = _Jv_FindClassFromSignature (&name->data[0],
+						    klass->loader);
+	      else
+		found = _Jv_FindClass (name, klass->loader);
 		
-	  if (! found)
-	    {
-	      jstring str = _Jv_NewStringUTF (name->data);
-	      throw new java::lang::NoClassDefFoundError (str);
-	    }
+	      if (! found)
+		{
+		  jstring str = _Jv_NewStringUTF (name->data);
+		  throw new java::lang::NoClassDefFoundError (str);
+		}
 
-	  pool->data[index].clazz = found;
-	  pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
+	      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[(int) 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[(int) klass->interfaces[i]].clazz;
+      // If superclass looks like a constant pool entry,
+      // resolve it now.
+      if ((uaddr) klass->superclass < (uaddr)pool->size)
+	{
+	  klass->superclass = pool->data[(int) klass->superclass].clazz;
+	}
+      // Likewise for interfaces.
+      for (int i = 0; i < klass->interface_count; i++)
+	if ((uaddr) klass->interfaces[i] < (uaddr)pool->size)
+	  klass->interfaces[i] = pool->data[(int) klass->interfaces[i]].clazz;
 
-  // Resolve the remaining constant pool entries.
-  for (int index = 1; index < pool->size; ++index)
-    {
-      if (pool->tags[index] == JV_CONSTANT_String)
+      // Resolve the remaining constant pool entries.
+      for (int index = 1; index < pool->size; ++index)
 	{
-	  jstring str;
+	  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;
+	      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)
+      // 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))
 	{
-	  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))
+#endif /* INTERPRETER */
+	  jfieldID f = JvGetFirstStaticField (klass);
+	  for (int n = JvNumStaticFields (klass); n > 0; --n)
 	    {
-	      jstring *strp = (jstring *) f->u.addr;
-	      if (*strp)
-		*strp = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) *strp);
+	      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 ();
 	    }
-	  f = f->getNextField ();
-	}
 #ifdef INTERPRETER
-    }
+	}
 #endif /* INTERPRETER */
 
-  klass->notifyAll ();
+      klass->notifyAll ();
 
-  _Jv_PushClass (klass);
+      _Jv_PushClass (klass);
+    }
+  catch (java::lang::Throwable *t)
+    {
+      klass->state = state;
+      throw t;
+    }
 }
 
 
@@ -556,6 +575,13 @@
     _Jv_RegisterInitiatingLoader (array_class, loader);
 
   element->arrayclass = array_class;
+}
+
+// Return the true ClassLoader for a class, without doing security checks
+::java::lang::ClassLoader *
+::java::lang::ClassLoader::getClassLoader0 (::java::lang::Class *c)
+{
+  return c->loader;
 }
 
 static jclass stack_head;

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