OSDN Git Service

* class.c (add_method_1): Set both DECL_EXTERNAL and METHOD_NATIVE
[pf3gnuchains/gcc-fork.git] / gcc / java / class.c
index 4a2d8fa..ca29eb9 100644 (file)
@@ -1,5 +1,5 @@
 /* Functions related to building classes and their related objects.
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -28,18 +28,179 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "system.h"
 #include "tree.h"
 #include "rtl.h"
+#include "flags.h"
 #include "java-tree.h"
 #include "jcf.h"
 #include "obstack.h"
 #include "toplev.h"
-
-static tree mangle_class_field PROTO ((tree class));
+#include "output.h"
+#include "parse.h"
+
+static tree mangle_class_field PARAMS ((tree class));
+static tree make_method_value PARAMS ((tree));
+static tree build_java_method_type PARAMS ((tree, tree, int));
+static int32 hashUtf8String PARAMS ((const char *, int));
+static tree make_field_value PARAMS ((tree));
+static tree get_dispatch_vector PARAMS ((tree));
+static tree get_dispatch_table PARAMS ((tree, tree));
+static void append_gpp_mangled_type PARAMS ((struct obstack *, tree));
+static tree mangle_static_field PARAMS ((tree));
+static void add_interface_do PARAMS ((tree, tree, int));
+static tree maybe_layout_super_class PARAMS ((tree, tree));
+static int assume_compiled PARAMS ((const char *));
+static struct hash_entry *init_test_hash_newfunc PARAMS ((struct hash_entry *,
+                                                         struct hash_table *,
+                                                         hash_table_key));
 
 static rtx registerClass_libfunc;
 
 extern struct obstack permanent_obstack;
 extern struct obstack temporary_obstack;
 
+/* The compiler generates different code depending on whether or not
+   it can assume certain classes have been compiled down to native
+   code or not.  The compiler options -fassume-compiled= and
+   -fno-assume-compiled= are used to create a tree of
+   assume_compiled_node objects.  This tree is queried to determine if
+   a class is assume to be compiled or not.  Each node in the tree
+   represents either a package or a specific class.  */
+
+typedef struct assume_compiled_node_struct
+{
+  /* The class or package name.  */
+  const char *ident;
+
+  /* Non-zero if this represents an exclusion.  */
+  int excludep;
+
+  /* Pointers to other nodes in the tree.  */
+  struct assume_compiled_node_struct *parent;
+  struct assume_compiled_node_struct *sibling;
+  struct assume_compiled_node_struct *child;
+} assume_compiled_node;
+
+static assume_compiled_node *find_assume_compiled_node
+                       PARAMS ((assume_compiled_node *, const char *));
+
+/* This is the root of the include/exclude tree.  */
+
+static assume_compiled_node *assume_compiled_tree;
+
+/* Return the node that most closely represents the class whose name
+   is IDENT.  Start the search from NODE.  Return NULL if an
+   appropriate node does not exist.  */
+
+static assume_compiled_node *
+find_assume_compiled_node (node, ident)
+     assume_compiled_node *node;
+     const char *ident;
+{
+  while (node)
+    {
+      size_t node_ident_length = strlen (node->ident);
+
+      /* node_ident_length is zero at the root of the tree.  If the
+        identifiers are the same length, then we have matching
+        classes.  Otherwise check if we've matched an enclosing
+        package name.  */
+
+      if (node_ident_length == 0
+         || (strncmp (ident, node->ident, node_ident_length) == 0
+             && (strlen (ident) == node_ident_length
+                 || ident[node_ident_length] == '.')))
+       {
+         /* We've found a match, however, there might be a more
+             specific match.  */
+
+         assume_compiled_node *found = find_assume_compiled_node (node->child,
+                                                                  ident);
+         if (found)
+           return found;
+         else
+           return node;
+       }
+
+      /* No match yet.  Continue through the sibling list.  */
+      node = node->sibling;
+    }
+
+  /* No match at all in this tree.  */
+  return NULL;
+}
+
+/* Add a new IDENT to the include/exclude tree.  It's an exclusion
+   if EXCLUDEP is non-zero.  */
+
+void
+add_assume_compiled (ident, excludep)
+     const char *ident;
+     int excludep;
+{
+  assume_compiled_node *parent;
+  assume_compiled_node *node = 
+    (assume_compiled_node *) xmalloc (sizeof (assume_compiled_node));
+
+  node->ident = xstrdup (ident);
+  node->excludep = excludep;
+  node->child = NULL;
+
+  /* Create the root of the tree if it doesn't exist yet.  */
+
+  if (NULL == assume_compiled_tree)
+    {
+      assume_compiled_tree = 
+       (assume_compiled_node *) xmalloc (sizeof (assume_compiled_node));
+      assume_compiled_tree->ident = "";
+      assume_compiled_tree->excludep = 0;
+      assume_compiled_tree->sibling = NULL;
+      assume_compiled_tree->child = NULL;
+      assume_compiled_tree->parent = NULL;
+    }
+
+  /* Calling the function with the empty string means we're setting
+     excludep for the root of the hierarchy.  */
+
+  if (0 == ident[0])
+    {
+      assume_compiled_tree->excludep = excludep;
+      return;
+    }
+
+  /* Find the parent node for this new node.  PARENT will either be a
+     class or a package name.  Adjust PARENT accordingly.  */
+
+  parent = find_assume_compiled_node (assume_compiled_tree, ident);
+  if (ident[strlen (parent->ident)] != '.')
+    parent = parent->parent;
+
+  /* Insert NODE into the tree.  */
+
+  node->parent = parent;
+  node->sibling = parent->child;
+  parent->child = node;
+}
+
+/* Returns non-zero if IDENT is the name of a class that the compiler
+   should assume has been compiled to FIXME  */
+
+static int
+assume_compiled (ident)
+     const char *ident;
+{
+  assume_compiled_node *i;
+  int result;
+  
+  if (NULL == assume_compiled_tree)
+    return 1;
+
+  i = find_assume_compiled_node (assume_compiled_tree,
+                                ident);
+
+  result = ! i->excludep;
+  
+  return (result);
+}
+
 /* Return an IDENTIFIER_NODE the same as (OLD_NAME, OLD_LENGTH).
    except that characters matching OLD_CHAR are substituted by NEW_CHAR.
    Also, PREFIX is prepended, and SUFFIX is appended. */
@@ -94,13 +255,13 @@ identifier_subst (old_id, prefix, old_char, new_char, suffix)
 
 tree
 mangled_classname (prefix, type)
-     char *prefix;
-     tree type;
+  const char *prefix;
+  tree type;
 {
   tree ident = TYPE_NAME (type);
   if (TREE_CODE (ident) != IDENTIFIER_NODE)
     ident = DECL_NAME (ident);
-  return identifier_subst (ident, prefix, '/', '_', "");
+  return identifier_subst (ident, prefix, '.', '_', "");
 }
 
 tree
@@ -124,7 +285,7 @@ make_class ()
 #else
   TYPE_BINFO (type) = make_tree_vec (6);
 #endif
-  CLASS_P (type) = 1;
+  MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type);
   pop_obstacks ();
 
   return type;
@@ -138,7 +299,20 @@ tree
 unmangle_classname (name, name_length)
      const char *name;  int name_length;
 {
-  return ident_subst (name, name_length, "", '/', '.', "");
+  tree to_return = ident_subst (name, name_length, "", '/', '.', "");
+  /* It's not sufficient to compare to_return and get_identifier
+     (name) to determine whether to_return is qualified. There are
+     cases in signature analysis where name will be stripped of a
+     trailing ';'. */
+  name = IDENTIFIER_POINTER (to_return);
+  while (*name)
+    if (*name++ == '.') 
+      {
+       QUALIFIED_P (to_return) = 1;
+       break;
+      }
+  
+  return to_return;
 }
 
 tree
@@ -150,6 +324,7 @@ push_class (class_type, class_name)
   int save_lineno = lineno;
   tree source_name = identifier_subst (class_name, "", '.', '/', ".java");
   push_obstacks (&permanent_obstack, &permanent_obstack);
+  CLASS_P (class_type) = 1;
   input_filename = IDENTIFIER_POINTER (source_name);
   lineno = 0;
   decl = build_decl (TYPE_DECL, class_name, class_type);
@@ -218,12 +393,13 @@ set_super_info (access_flags, this_class, super_class, interfaces_count)
       CLASS_HAS_SUPER (this_class) = 1;
     }
   pop_obstacks ();
-  
+
   if (access_flags & ACC_PUBLIC)    CLASS_PUBLIC (class_decl) = 1;
   if (access_flags & ACC_FINAL)     CLASS_FINAL (class_decl) = 1;
   if (access_flags & ACC_SUPER)     CLASS_SUPER (class_decl) = 1;
   if (access_flags & ACC_INTERFACE) CLASS_INTERFACE (class_decl) = 1;
   if (access_flags & ACC_ABSTRACT)  CLASS_ABSTRACT (class_decl) = 1;
+  if (access_flags & ACC_STATIC)    CLASS_STATIC (class_decl) = 1;
 }
 
 /* Return length of inheritance chain of CLAS, where java.lang.Object is 0,
@@ -236,6 +412,8 @@ class_depth (clas)
   int depth = 0;
   if (! CLASS_LOADED_P (clas))
     load_class (clas, 1);
+  if (TYPE_SIZE (clas) == error_mark_node)
+    return -1;
   while (clas != object_type_node)
     {
       depth++;
@@ -287,6 +465,27 @@ inherits_from_p (type1, type2)
   return 0;
 }
 
+/* Return a 1 iff TYPE1 is an enclosing context for TYPE2 */
+
+int
+enclosing_context_p (type1, type2)
+     tree type1, type2;
+{
+  if (!INNER_CLASS_TYPE_P (type2))
+    return 0;
+
+  for (type2 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2)));
+       type2; 
+       type2 = (INNER_CLASS_TYPE_P (type2) ?
+               TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2))) : NULL_TREE))
+    {
+      if (type2 == type1)
+       return 1;
+    }
+
+  return 0;
+}
+
 static void
 add_interface_do (basetype_vec, interface_class, i)
      tree basetype_vec, interface_class;
@@ -309,7 +508,6 @@ maybe_add_interface (this_class, interface_class)
      tree this_class, interface_class;
 {
   tree basetype_vec = TYPE_BINFO_BASETYPES (this_class);
-  tree interface_binfo = make_tree_vec (6);
   int i;
   int n = TREE_VEC_LENGTH (basetype_vec);
   for (i = 0; ; i++)
@@ -350,6 +548,7 @@ add_interface (this_class, interface_class)
   add_interface_do (basetype_vec, interface_class, i);
 }
 
+#if 0
 /* Return the address of a pointer to the first FUNCTION_DECL
    in the list (*LIST) whose DECL_NAME is NAME. */
 
@@ -362,8 +561,9 @@ find_named_method (list, name)
     list = &TREE_CHAIN (*list);
   return list;
 }
+#endif
 
-tree
+static tree
 build_java_method_type (fntype, this_class, access_flags)
      tree fntype;
      tree this_class;
@@ -374,6 +574,43 @@ build_java_method_type (fntype, this_class, access_flags)
   return build_method_type (CLASS_TO_HANDLE_TYPE (this_class), fntype);
 }
 
+static struct hash_entry *
+init_test_hash_newfunc (entry, table, string)
+     struct hash_entry *entry;
+     struct hash_table *table;
+     hash_table_key string ATTRIBUTE_UNUSED;
+{
+  struct init_test_hash_entry *ret = (struct init_test_hash_entry *) entry;
+  if (ret == NULL)
+    {
+      ret = ((struct init_test_hash_entry *)
+            hash_allocate (table, sizeof (struct init_test_hash_entry)));
+      if (ret == NULL)
+       return NULL;
+    }
+  ret->init_test_decl = 0;
+  return (struct hash_entry *) ret;
+}
+
+/* Hash table helpers. Also reused in find_applicable_accessible_methods_list
+   (parse.y). The hash of a tree node is it's pointer value,
+   comparison is direct. */
+
+unsigned long
+java_hash_hash_tree_node (k)
+     hash_table_key k;
+{
+  return (long) k;
+}
+
+boolean
+java_hash_compare_tree_node (k1, k2)
+     hash_table_key k1;
+     hash_table_key k2;
+{
+  return ((char*) k1 == (char*) k2);
+}
+
 tree
 add_method_1 (handle_class, access_flags, name, function_type)
      tree handle_class;
@@ -392,7 +629,12 @@ add_method_1 (handle_class, access_flags, name, function_type)
 
   DECL_LANG_SPECIFIC (fndecl)
     = (struct lang_decl *) permalloc (sizeof (struct lang_decl));
-  bzero (DECL_LANG_SPECIFIC (fndecl), sizeof (struct lang_decl));
+  bzero ((PTR) DECL_LANG_SPECIFIC (fndecl), sizeof (struct lang_decl));
+
+  /* Initialize the static initializer test table.  */
+  hash_table_init (&DECL_FUNCTION_INIT_TEST_TABLE (fndecl),
+                  init_test_hash_newfunc, java_hash_hash_tree_node, 
+                  java_hash_compare_tree_node);
 
   TREE_CHAIN (fndecl) = TYPE_METHODS (handle_class);
   TYPE_METHODS (handle_class) = fndecl;
@@ -400,10 +642,17 @@ add_method_1 (handle_class, access_flags, name, function_type)
 
   if (access_flags & ACC_PUBLIC) METHOD_PUBLIC (fndecl) = 1;
   if (access_flags & ACC_PROTECTED) METHOD_PROTECTED (fndecl) = 1;
-  if (access_flags & ACC_PRIVATE) METHOD_PRIVATE (fndecl) = 1;
-  if (access_flags & ACC_NATIVE) METHOD_NATIVE (fndecl) = 1;
-  if (access_flags & ACC_STATIC) METHOD_STATIC (fndecl) = 1;
-  if (access_flags & ACC_FINAL) METHOD_FINAL (fndecl) = 1;
+  if (access_flags & ACC_PRIVATE)
+    METHOD_PRIVATE (fndecl) = DECL_INLINE (fndecl) = 1;
+  if (access_flags & ACC_NATIVE)
+    {
+      METHOD_NATIVE (fndecl) = 1;
+      DECL_EXTERNAL (fndecl) = 1;
+    }
+  if (access_flags & ACC_STATIC) 
+    METHOD_STATIC (fndecl) = DECL_INLINE (fndecl) = 1;
+  if (access_flags & ACC_FINAL) 
+    METHOD_FINAL (fndecl) = DECL_INLINE (fndecl) = 1;
   if (access_flags & ACC_SYNCHRONIZED) METHOD_SYNCHRONIZED (fndecl) = 1;
   if (access_flags & ACC_ABSTRACT) METHOD_ABSTRACT (fndecl) = 1;
   if (access_flags & ACC_TRANSIENT) METHOD_TRANSIENT (fndecl) = 1;
@@ -422,8 +671,8 @@ add_method (this_class, access_flags, name, method_sig)
      tree method_sig;
 {
   tree handle_class = CLASS_TO_HANDLE_TYPE (this_class);
-  tree function_type, method_type, fndecl;
-  unsigned char *sig = (unsigned char*)IDENTIFIER_POINTER (method_sig);
+  tree function_type, fndecl;
+  const unsigned char *sig = (const unsigned char*)IDENTIFIER_POINTER (method_sig);
   push_obstacks (&permanent_obstack, &permanent_obstack);
   if (sig[0] != '(')
     fatal ("bad method signature");
@@ -484,6 +733,7 @@ set_constant_value (field, constant)
 
 /* Count the number of Unicode chars encoded in a given Ut8 string. */
 
+#if 0
 int
 strLengthUtf8 (str, len)
      char *str;
@@ -498,19 +748,20 @@ strLengthUtf8 (str, len)
   }
   return str_length;
 }
+#endif
 
 
 /* Calculate a hash value for a string encoded in Utf8 format.
  * This returns the same hash value as specified for java.lang.String.hashCode.
  */
 
-int32
+static int32
 hashUtf8String (str, len)
-     char *str;
+     const char *str;
      int len;
 {
-  register unsigned char* ptr = (unsigned char*) str;
-  register unsigned char *limit = ptr + len;
+  register const unsigned char* ptr = (const unsigned char*) str;
+  register const unsigned char *limit = ptr + len;
   int32 hash = 0;
   for (; ptr < limit;)
     {
@@ -528,11 +779,11 @@ tree
 build_utf8_ref (name)
      tree name;
 {
-  char* name_ptr = IDENTIFIER_POINTER(name);
+  const char * name_ptr = IDENTIFIER_POINTER(name);
   int name_len = IDENTIFIER_LENGTH(name);
   char buf[60];
   char *buf_ptr;
-  tree ctype, field, str_type, cinit, string;
+  tree ctype, field = NULL_TREE, str_type, cinit, string;
   static int utf8_count = 0;
   int name_hash;
   tree ref = IDENTIFIER_UTF8_REF (name);
@@ -556,16 +807,19 @@ build_utf8_ref (name)
   TREE_TYPE (string) = str_type;
   PUSH_FIELD_VALUE (cinit, "data", string);
   FINISH_RECORD_CONSTRUCTOR (cinit);
+  TREE_CONSTANT (cinit) = 1;
 
   /* Build a unique identifier based on buf. */
   sprintf(buf, "_Utf%d", ++utf8_count);
   buf_ptr = &buf[strlen (buf)];
+  if (name_len > 0 && name_ptr[0] >= '0' && name_ptr[0] <= '9')
+    *buf_ptr++ = '_';
   while (--name_len >= 0)
     {
-      char c = *name_ptr++;
+      unsigned char c = *name_ptr++;
       if (c & 0x80)
        continue;
-      if (!isalpha(c) && !isdigit(c))
+      if (!ISALPHA(c) && !ISDIGIT(c))
        c = '_';
       *buf_ptr++ = c;
       if (buf_ptr >= buf + 50)
@@ -579,6 +833,7 @@ build_utf8_ref (name)
   DECL_ARTIFICIAL (decl) = 1;
   DECL_IGNORED_P (decl) = 1;
   TREE_READONLY (decl) = 1;
+  TREE_THIS_VOLATILE (decl) = 0;
   DECL_INITIAL (decl) = cinit;
   TREE_CHAIN (decl) = utf8_decl_list;
   layout_decl (decl, 0);
@@ -617,6 +872,7 @@ build_class_ref (type)
              push_obstacks (&permanent_obstack, &permanent_obstack);
              decl = build_decl (VAR_DECL, decl_name, class_type_node);
              DECL_SIZE (decl) = TYPE_SIZE (class_type_node);
+             DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (class_type_node);
              TREE_STATIC (decl) = 1;
              TREE_PUBLIC (decl) = 1;
              DECL_IGNORED_P (decl) = 1;
@@ -631,8 +887,36 @@ build_class_ref (type)
        }
       else
        {
-         char *name;
+         const char *name;
          char buffer[25];
+         if (flag_emit_class_files)
+           {
+             const char *prim_class_name;
+             tree prim_class;
+             if (type == char_type_node)
+               prim_class_name = "java.lang.Character";
+             else if (type == boolean_type_node)
+               prim_class_name = "java.lang.Boolean";
+             else if (type == byte_type_node)
+               prim_class_name = "java.lang.Byte";
+             else if (type == short_type_node)
+               prim_class_name = "java.lang.Short";
+             else if (type == int_type_node)
+               prim_class_name = "java.lang.Integer";
+             else if (type == long_type_node)
+               prim_class_name = "java.lang.Long";
+             else if (type == float_type_node)
+                prim_class_name = "java.lang.Float";
+             else if (type == double_type_node)
+                prim_class_name = "java.lang.Double";
+             else if (type == void_type_node)
+                prim_class_name = "java.lang.Void";
+             else
+               fatal ("internal error - bad type to build_class_ref");
+             prim_class = lookup_class (get_identifier (prim_class_name));
+             return build (COMPONENT_REF, NULL_TREE,
+                           prim_class, TYPE_identifier_node);
+           }
          decl_name = TYPE_NAME (type);
          if (TREE_CODE (decl_name) == TYPE_DECL)
            decl_name = DECL_NAME (decl_name);
@@ -693,8 +977,7 @@ build_static_field_ref (fdecl)
   else
     {
       /* Compile as:
-       * *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr
-       */
+       * *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */
       static tree fields_ident = NULL_TREE;
       static tree info_ident = NULL_TREE;
       tree ref = build_class_ref (fclass);
@@ -765,6 +1048,8 @@ get_access_flags_from_decl (decl)
        access_flags |= ACC_INTERFACE;
       if (CLASS_ABSTRACT (decl))
        access_flags |= ACC_ABSTRACT;
+      if (CLASS_STATIC (decl))
+       access_flags |= ACC_STATIC;
       return access_flags;
     }
   if (TREE_CODE (decl) == FUNCTION_DECL)
@@ -792,51 +1077,54 @@ get_access_flags_from_decl (decl)
   abort ();
 }
 
-tree
-make_field_value (tree fdecl)
+static tree
+make_field_value (fdecl)
+  tree fdecl;
 {
-  tree finit, info;
-  int bsize, flags;
+  tree finit;
+  int flags;
   tree type = TREE_TYPE (fdecl);
   int resolved = is_compiled_class (type);
+
   START_RECORD_CONSTRUCTOR (finit, field_type_node);
   PUSH_FIELD_VALUE (finit, "name", build_utf8_ref (DECL_NAME (fdecl)));
   if (resolved)
     type = build_class_ref (type);
   else
-    type = build_utf8_ref (build_java_signature (type));
+    {
+      tree signature = build_java_signature (type);
+
+      type = build_utf8_ref (unmangle_classname 
+                            (IDENTIFIER_POINTER (signature),
+                             IDENTIFIER_LENGTH (signature)));
+    }
   PUSH_FIELD_VALUE (finit, "type", type);
+
   flags = get_access_flags_from_decl (fdecl);
   if (! resolved)
     flags |= 0x8000 /* FIELD_UNRESOLVED_FLAG */;
+
   PUSH_FIELD_VALUE (finit, "accflags", build_int_2 (flags, 0));
-  bsize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (fdecl))) / BITS_PER_UNIT;
-  PUSH_FIELD_VALUE (finit, "bsize", build_int_2 (bsize, 0));
-  if (FIELD_STATIC (fdecl))
-    {
-      tree cfield = TREE_CHAIN (TYPE_FIELDS(field_info_union_node));
-      tree faddr = build_address_of (build_static_field_ref (fdecl));
-      info = build (CONSTRUCTOR, field_info_union_node, NULL_TREE,
-                   build_tree_list (cfield, faddr));
-    }
-  else
-    {
-      int boffset
-       = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (fdecl)) / BITS_PER_UNIT;
-      info = build (CONSTRUCTOR, field_info_union_node, NULL_TREE,
-                   build_tree_list (TYPE_FIELDS(field_info_union_node),
-                                    build_int_2 (boffset, 0)));
-    }
-  PUSH_FIELD_VALUE (finit, "info", info);
+  PUSH_FIELD_VALUE (finit, "bsize", TYPE_SIZE_UNIT (TREE_TYPE (fdecl)));
+
+  PUSH_FIELD_VALUE
+    (finit, "info",
+     build (CONSTRUCTOR, field_info_union_node, NULL_TREE,
+           build_tree_list
+           ((FIELD_STATIC (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))
+             : byte_position (fdecl)))));
 
   FINISH_RECORD_CONSTRUCTOR (finit);
   return finit;
 }
 
-tree
-make_method_value (mdecl, this_class_addr)
+static tree
+make_method_value (mdecl)
      tree mdecl;
-     tree this_class_addr;
 {
   tree minit;
   tree code;
@@ -850,48 +1138,53 @@ make_method_value (mdecl, this_class_addr)
                    build_utf8_ref (DECL_CONSTRUCTOR_P (mdecl) ?
                                    init_identifier_node
                                    : DECL_NAME (mdecl)));
-  PUSH_FIELD_VALUE (minit, "signature",
-                   build_utf8_ref (build_java_signature (TREE_TYPE (mdecl))));
+  {
+    tree signature = build_java_signature (TREE_TYPE (mdecl));
+    PUSH_FIELD_VALUE (minit, "signature", 
+                     (build_utf8_ref 
+                      (unmangle_classname 
+                       (IDENTIFIER_POINTER(signature),
+                        IDENTIFIER_LENGTH(signature)))));
+  }
   PUSH_FIELD_VALUE (minit, "accflags", build_int_2 (accflags, 0));
   PUSH_FIELD_VALUE (minit, "ncode", code);
   FINISH_RECORD_CONSTRUCTOR (minit);
   return minit;
 }
 
-tree
+static tree
 get_dispatch_vector (type)
      tree type;
 {
   tree vtable = TYPE_VTABLE (type);
   if (vtable == NULL)
     {
-      int i;
+      HOST_WIDE_INT i;
       tree method;
       tree super = CLASSTYPE_SUPER (type);
-      int nvirtuals = TREE_INT_CST_LOW (TYPE_NVIRTUALS (type));
+      HOST_WIDE_INT nvirtuals = tree_low_cst (TYPE_NVIRTUALS (type), 0);
       vtable = make_tree_vec (nvirtuals);
       TYPE_VTABLE (type) = vtable;
       if (super != NULL_TREE)
        {
          tree super_vtable = get_dispatch_vector (super);
-         for ( i = TREE_INT_CST_LOW (TYPE_NVIRTUALS (super));  --i >= 0; )
+
+         for (i = tree_low_cst (TYPE_NVIRTUALS (super), 0); --i >= 0; )
            TREE_VEC_ELT (vtable, i) = TREE_VEC_ELT (super_vtable, i);
        }
+
       for (method = TYPE_METHODS (type);  method != NULL_TREE;
           method = TREE_CHAIN (method))
-       {
-         if (DECL_VINDEX (method) != NULL_TREE
-             && TREE_CODE (DECL_VINDEX (method)) == INTEGER_CST)
-           {
-             TREE_VEC_ELT (vtable, TREE_INT_CST_LOW (DECL_VINDEX (method)))
-               = method;
-           }
-       }
+       if (DECL_VINDEX (method) != NULL_TREE
+           && host_integerp (DECL_VINDEX (method), 0))
+         TREE_VEC_ELT (vtable, tree_low_cst (DECL_VINDEX (method), 0))
+           = method;
     }
+
   return vtable;
 }
 
-tree
+static tree
 get_dispatch_table (type, this_class_addr)
      tree type, this_class_addr;
 {
@@ -910,8 +1203,11 @@ get_dispatch_table (type, this_class_addr)
                        build1 (ADDR_EXPR, nativecode_ptr_type_node, method),
                        list);
     }
-  /* Dummy entry for compatibility with G++ -fvtable-thunks. */
-  list = tree_cons (integer_zero_node, null_pointer_node, list);
+  /* Dummy entry for compatibility with G++ -fvtable-thunks.  When
+     using the Boehm GC we sometimes stash a GC type descriptor
+     there.  */
+  list = tree_cons (integer_zero_node, get_boehm_type_descriptor (type),
+                   list);
   list = tree_cons (integer_zero_node, this_class_addr, list);
   return build (CONSTRUCTOR, build_prim_array_type (nativecode_ptr_type_node,
                                                    nvirtuals + 2),
@@ -957,9 +1253,16 @@ make_class_data (type)
          tree init = make_field_value (field);
          if (FIELD_STATIC (field))
            {
+             tree initial = DECL_INITIAL (field);
              static_field_count++;
              static_fields = tree_cons (NULL_TREE, init, static_fields);
+             /* If the initial value is a string constant,
+                prevent output_constant from trying to assemble the value. */
+             if (initial != NULL_TREE
+                 && TREE_TYPE (initial) == string_ptr_type_node)
+               DECL_INITIAL (field) = NULL_TREE;
              rest_of_decl_compilation (field, (char*) 0, 1, 1);
+             DECL_INITIAL (field) = initial;
            }
          else
            {
@@ -991,7 +1294,12 @@ make_class_data (type)
   for (method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (type));
        method != NULL_TREE; method = TREE_CHAIN (method))
     {
-      tree init = make_method_value (method, this_class_addr);
+      tree init;
+      if (METHOD_PRIVATE (method)
+         && ! flag_keep_inline_functions
+         && (flag_inline_functions || optimize))
+       continue;
+      init = make_method_value (method);
       method_count++;
       methods = tree_cons (NULL_TREE, init, methods);
     }
@@ -1005,7 +1313,7 @@ make_class_data (type)
   DECL_IGNORED_P (methods_decl) = 1;
   rest_of_decl_compilation (methods_decl, (char*) 0, 1, 0);
 
-  if (flag_assume_compiled
+  if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
       && ! CLASS_ABSTRACT (type_decl) && ! CLASS_INTERFACE (type_decl))
     {
       tree dtable = get_dispatch_table (type, this_class_addr);
@@ -1021,13 +1329,13 @@ make_class_data (type)
   super = CLASSTYPE_SUPER (type);
   if (super == NULL_TREE)
     super = null_pointer_node;
-  else if (flag_assume_compiled)
+  else if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl))))
     super = build_class_ref (super);
   else
     {
       int super_index = alloc_class_constant (super);
       super = build_int_2 (super_index, 0);
-      TREE_TYPE (super) == ptr_type_node;
+      TREE_TYPE (super) = ptr_type_node;
     }
 
   /* Build and emit the array of implemented interfaces. */
@@ -1047,13 +1355,13 @@ make_class_data (type)
          tree child = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), i);
          tree iclass = BINFO_TYPE (child);
          tree index;
-         if (flag_assume_compiled)
+         if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (iclass)))))
            index = build_class_ref (iclass);
          else
            {
                int int_index = alloc_class_constant (iclass);
                index = build_int_2 (int_index, 0);
-               TREE_TYPE (index) == ptr_type_node;
+               TREE_TYPE (index) = ptr_type_node;
            }
          init = tree_cons (NULL_TREE, index, init); 
        }
@@ -1069,28 +1377,25 @@ make_class_data (type)
   constant_pool_constructor = build_constants_constructor ();
 
   START_RECORD_CONSTRUCTOR (temp, object_type_node);
-#if 0
-  PUSH_FIELD_VALUE (temp, "dtable", NULL_TREE);
-#else
-  PUSH_FIELD_VALUE (temp, "dtable",
+  PUSH_FIELD_VALUE (temp, "vtable",
                    build1 (ADDR_EXPR, dtable_ptr_type, class_dtable_decl));
-#endif
-  PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node);
+  if (! flag_hash_synchronization)
+    PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node);
   FINISH_RECORD_CONSTRUCTOR (temp);
   START_RECORD_CONSTRUCTOR (cons, class_type_node);
   PUSH_SUPER_VALUE (cons, temp);
   PUSH_FIELD_VALUE (cons, "next", null_pointer_node);
-  PUSH_FIELD_VALUE (cons, "name",
-                   build_utf8_ref (build_internal_class_name (type)));
+  PUSH_FIELD_VALUE (cons, "name", build_utf8_ref (DECL_NAME (type_decl)));
   PUSH_FIELD_VALUE (cons, "accflags",
                    build_int_2 (get_access_flags_from_decl (type_decl), 0));
 
-  PUSH_FIELD_VALUE (cons, "superclass", super);
+  PUSH_FIELD_VALUE (cons, "superclass", 
+                   CLASS_INTERFACE (type_decl) ? null_pointer_node : super);
   PUSH_FIELD_VALUE (cons, "constants", constant_pool_constructor);
   PUSH_FIELD_VALUE (cons, "methods",
                    build1 (ADDR_EXPR, method_ptr_type_node, methods_decl));
   PUSH_FIELD_VALUE (cons, "method_count",  build_int_2 (method_count, 0));
-  PUSH_FIELD_VALUE (cons, "dtable_method_count", TYPE_NVIRTUALS (type));
+  PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type));
   PUSH_FIELD_VALUE (cons, "fields",
                    fields_decl == NULL_TREE ? null_pointer_node
                    : build1 (ADDR_EXPR, field_ptr_type_node, fields_decl));
@@ -1098,8 +1403,7 @@ make_class_data (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));
-  /* For now, we let Kaffe fill in the dtable.  */
-  PUSH_FIELD_VALUE (cons, "dtable",
+  PUSH_FIELD_VALUE (cons, "vtable",
                    dtable_decl == NULL_TREE ? null_pointer_node
                    : build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl));
   PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
@@ -1108,6 +1412,9 @@ make_class_data (type)
   PUSH_FIELD_VALUE (cons, "state", integer_zero_node);
 
   PUSH_FIELD_VALUE (cons, "thread", null_pointer_node);
+  PUSH_FIELD_VALUE (cons, "depth", integer_zero_node);
+  PUSH_FIELD_VALUE (cons, "ancestors", null_pointer_node);
+  PUSH_FIELD_VALUE (cons, "idt", null_pointer_node);
 
   FINISH_RECORD_CONSTRUCTOR (cons);
 
@@ -1115,6 +1422,55 @@ make_class_data (type)
   rest_of_decl_compilation (decl, (char*) 0, 1, 0);
 }
 
+void
+finish_class ()
+{
+  tree method;
+  tree type_methods = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (current_class));
+  int saw_native_method = 0;
+
+  /* Find out if we have any native methods.  We use this information
+     later.  */
+  for (method = type_methods;
+       method != NULL_TREE;
+       method = TREE_CHAIN (method))
+    {
+      if (METHOD_NATIVE (method))
+       {
+         saw_native_method = 1;
+         break;
+       }
+    }
+
+  /* Emit deferred inline methods. */  
+  for (method = type_methods; method != NULL_TREE; )
+    {
+      if (! TREE_ASM_WRITTEN (method) && DECL_SAVED_INSNS (method) != 0)
+       {
+         /* It's a deferred inline method.  Decide if we need to emit it. */
+         if (flag_keep_inline_functions
+             || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (method))
+             || ! METHOD_PRIVATE (method)
+             || saw_native_method)
+           {
+             temporary_allocation ();
+             output_inline_function (method);
+             permanent_allocation (1);
+             /* Scan the list again to see if there are any earlier
+                 methods to emit. */
+             method = type_methods;
+             continue;
+           }
+       }
+      method = TREE_CHAIN (method);
+    }
+
+  current_function_decl = NULL_TREE;
+  make_class_data (current_class);
+  register_class ();
+  rest_of_decl_compilation (TYPE_NAME (current_class), (char*) 0, 1, 0);
+}
+
 /* Return 2 if CLASS is compiled by this compilation job;
    return 1 if CLASS can otherwise be assumed to be compiled;
    return 0 if we cannot assume that CLASS is compiled.
@@ -1133,8 +1489,7 @@ is_compiled_class (class)
   if (class == current_class)
     return 2;
 
-  seen_in_zip = (TYPE_LANG_SPECIFIC (class) && TYPE_LANG_SPECIFIC (class)->jcf
-                && TYPE_LANG_SPECIFIC (class)->jcf->seen_in_zip);
+  seen_in_zip = (TYPE_JCF (class) && TYPE_JCF (class)->seen_in_zip);
   if (CLASS_FROM_CURRENTLY_COMPILED_SOURCE_P (class) || seen_in_zip)
     {
       /* The class was seen in the current ZIP file and will be
@@ -1150,10 +1505,15 @@ is_compiled_class (class)
       return 2;
     }
 
-  if (flag_assume_compiled)
+  if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class)))))
     {
       if (!CLASS_LOADED_P (class))
-       load_class (class, 1);
+       {
+         if (CLASS_FROM_SOURCE_P (class))
+           safe_layout_class (class);
+         else
+           load_class (class, 1);
+       }
       return 1;
     }
 
@@ -1162,14 +1522,11 @@ is_compiled_class (class)
 
 /* Append the mangled name of TYPE onto OBSTACK. */
 
-void
+static void
 append_gpp_mangled_type (obstack, type)
      struct obstack *obstack;
      tree type;
 {
-  char buf[8];
-  int len;
-  char *ptr;
   switch (TREE_CODE (type))
     {
       char code;
@@ -1213,7 +1570,7 @@ append_gpp_mangled_type (obstack, type)
        }
       else
        {
-         char *class_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+         const char *class_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
          append_gpp_mangled_classtype (obstack, class_name);
        }
       break;
@@ -1240,7 +1597,7 @@ mangle_class_field (class)
 
 /* Build the mangled (assembly-level) name of the static field FIELD. */
 
-tree
+static tree
 mangle_static_field (field)
      tree field;
 {
@@ -1309,6 +1666,9 @@ push_super_field (this_class, super_class)
      tree this_class, super_class;
 {
   tree base_decl;
+  /* Don't insert the field if we're just re-laying the class out. */ 
+  if (TYPE_FIELDS (this_class) && !DECL_NAME (TYPE_FIELDS (this_class)))
+    return;
   push_obstacks (&permanent_obstack, &permanent_obstack);
   base_decl = build_decl (FIELD_DECL, NULL_TREE, super_class);
   pop_obstacks ();
@@ -1316,41 +1676,93 @@ push_super_field (this_class, super_class)
   TREE_CHAIN (base_decl) = TYPE_FIELDS (this_class);
   TYPE_FIELDS (this_class) = base_decl;
   DECL_SIZE (base_decl) = TYPE_SIZE (super_class);
+  DECL_SIZE_UNIT (base_decl) = TYPE_SIZE_UNIT (super_class);
+}
+
+/* Handle the different manners we may have to lay out a super class.  */
+
+static tree
+maybe_layout_super_class (super_class, this_class)
+     tree super_class;
+     tree this_class;
+{
+  if (TREE_CODE (super_class) == RECORD_TYPE)
+    {
+      if (!CLASS_LOADED_P (super_class) 
+         && CLASS_FROM_SOURCE_P (super_class))
+       safe_layout_class (super_class);
+      if (!CLASS_LOADED_P (super_class))
+       load_class (super_class, 1);
+    }
+  /* We might have to layout the class before its dependency on
+     the super class gets resolved by java_complete_class  */
+  else if (TREE_CODE (super_class) == POINTER_TYPE)
+    {
+      if (TREE_TYPE (super_class) != NULL_TREE)
+       super_class = TREE_TYPE (super_class);
+      else
+       {
+         super_class = do_resolve_class (NULL_TREE, /* FIXME? */
+                                         super_class, NULL_TREE, this_class);
+         if (!super_class)
+           return NULL_TREE;   /* FIXME, NULL_TREE not checked by caller. */
+         super_class = TREE_TYPE (super_class);
+       }
+    }
+  if (!TYPE_SIZE (super_class))
+    safe_layout_class (super_class);
+
+  return super_class;
 }
 
 void
 layout_class (this_class)
      tree this_class;
 {
+  static tree list = NULL_TREE;
   tree super_class = CLASSTYPE_SUPER (this_class);
-  tree handle_type = CLASS_TO_HANDLE_TYPE (this_class);
-  tree method_decl, field;
-  tree dtable_count;
-  int i;
+  tree field;
+  
+  list = tree_cons (this_class, NULL_TREE, list);
+  if (CLASS_BEING_LAIDOUT (this_class))
+    {
+      char buffer [1024];
+      tree current;
+      
+      sprintf (buffer, " with `%s'",
+              IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))));
+      obstack_grow (&temporary_obstack, buffer, strlen (buffer));
+
+      for (current = TREE_CHAIN (list); current; 
+          current = TREE_CHAIN (current))
+       {
+         tree decl = TYPE_NAME (TREE_PURPOSE (current));
+         sprintf (buffer, "\n  which inherits from `%s' (%s:%d)",
+                  IDENTIFIER_POINTER (DECL_NAME (decl)),
+                  DECL_SOURCE_FILE (decl),
+                  DECL_SOURCE_LINE (decl));
+         obstack_grow (&temporary_obstack, buffer, strlen (buffer));
+       }
+      obstack_1grow (&temporary_obstack, '\0');
+      cyclic_inheritance_report = obstack_finish (&temporary_obstack);
+      TYPE_SIZE (this_class) = error_mark_node;
+      return;
+    }
+  CLASS_BEING_LAIDOUT (this_class) = 1;
 
   if (super_class)
     {
-      /* Class seen in source are now complete and can be layed out.
-        Once layed out, a class seen in the source has its
-        CLASS_LOADED_P flag set */
-      if (CLASS_FROM_SOURCE_P (super_class) && !CLASS_LOADED_P (super_class))
-       safe_layout_class (super_class);
-      if (! CLASS_LOADED_P (super_class))
-       load_class (super_class, 1);
+      super_class = maybe_layout_super_class (super_class, this_class);
       if (TREE_CODE (TYPE_SIZE (super_class)) == ERROR_MARK)
        {
          TYPE_SIZE (this_class) = error_mark_node;
+         CLASS_BEING_LAIDOUT (this_class) = 0;
+         list = TREE_CHAIN (list);
          return;
        }
-      dtable_count = TYPE_NVIRTUALS (super_class);
-
       if (TYPE_SIZE (this_class) == NULL_TREE)
        push_super_field (this_class, super_class);
     }
-  else
-    {
-      dtable_count = integer_zero_node;
-    }
 
   for (field = TYPE_FIELDS (this_class);
        field != NULL_TREE;  field = TREE_CHAIN (field))
@@ -1364,170 +1776,208 @@ layout_class (this_class)
 
   layout_type (this_class);
 
+  /* Convert the size back to an SI integer value */
+  TYPE_SIZE_UNIT (this_class) = 
+    fold (convert (int_type_node, TYPE_SIZE_UNIT (this_class)));
+
+  CLASS_BEING_LAIDOUT (this_class) = 0;
+  list = TREE_CHAIN (list);
+}
+
+void
+layout_class_methods (this_class)
+     tree this_class;
+{
+  tree method_decl, dtable_count;
+  tree super_class, handle_type;
+
+  if (TYPE_NVIRTUALS (this_class))
+    return;
+
+  push_obstacks (&permanent_obstack, &permanent_obstack);
+  super_class = CLASSTYPE_SUPER (this_class);
+  handle_type = CLASS_TO_HANDLE_TYPE (this_class);
+
+  if (super_class)
+    {
+      super_class = maybe_layout_super_class (super_class, this_class);
+      if (!TYPE_NVIRTUALS (super_class))
+       layout_class_methods (super_class);
+      dtable_count = TYPE_NVIRTUALS (super_class);
+    }
+  else
+    dtable_count = integer_zero_node;
+  
   TYPE_METHODS (handle_type) = nreverse (TYPE_METHODS (handle_type));
 
-  for (method_decl = TYPE_METHODS (handle_type), i = 0;
-       method_decl; method_decl = TREE_CHAIN (method_decl), i++)
+  for (method_decl = TYPE_METHODS (handle_type);
+       method_decl; method_decl = TREE_CHAIN (method_decl))
+    dtable_count = layout_class_method (this_class, super_class, 
+                                       method_decl, dtable_count);
+
+  TYPE_NVIRTUALS (this_class) = dtable_count;
+
+#ifdef JAVA_USE_HANDLES
+  layout_type (handle_type);
+#endif
+  pop_obstacks ();
+}
+
+/* Lay METHOD_DECL out, returning a possibly new value of
+   DTABLE_COUNT.  */
+
+tree
+layout_class_method (this_class, super_class, method_decl, dtable_count)
+     tree this_class, super_class, method_decl, dtable_count;
+{
+  const char *ptr;
+  char *asm_name;
+  tree arg, arglist, t;
+  int method_name_needs_escapes = 0;
+  tree method_name = DECL_NAME (method_decl);
+  int method_name_is_wfl = 
+    (TREE_CODE (method_name) == EXPR_WITH_FILE_LOCATION);
+  if (method_name_is_wfl)
+    method_name = java_get_real_method_name (method_decl);
+
+  if (!ID_INIT_P (method_name) && !ID_FINIT_P (method_name))
     {
-      char *ptr;
-      char buf[8];
-      char *asm_name;
-      tree method_name = DECL_NAME (method_decl);
-#if 1
-      /* Remove this once we no longer need old (Kaffe / JDK 1.0)  mangling. */
-      if (! flag_assume_compiled && METHOD_NATIVE (method_decl))
+      int encoded_len
+       = unicode_mangling_length (IDENTIFIER_POINTER (method_name), 
+                                  IDENTIFIER_LENGTH (method_name));
+      if (encoded_len > 0)
        {
-         for (ptr = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
-              *ptr; )
-           {
-             int ch = *ptr++;
-             if (ch == '.')
-               ch = '_';
-             obstack_1grow (&temporary_obstack, (char) ch);
-           }
-         obstack_1grow (&temporary_obstack, (char) '_');
-         if (method_name == init_identifier_node)
-           obstack_grow (&temporary_obstack, "INIT", 4);
-         else
-           obstack_grow (&temporary_obstack,
-                         IDENTIFIER_POINTER (method_name),
-                         IDENTIFIER_LENGTH (method_name));
+         method_name_needs_escapes = 1;
+         emit_unicode_mangled_name (&temporary_obstack,
+                                    IDENTIFIER_POINTER (method_name), 
+                                    IDENTIFIER_LENGTH (method_name));
        }
       else
-#endif
        {
-         int len;  tree arg, arglist, t;
-         int method_name_needs_escapes = 0;
-         if (method_name != init_identifier_node 
-             && method_name != finit_identifier_node)
+         obstack_grow (&temporary_obstack,
+                       IDENTIFIER_POINTER (method_name),
+                       IDENTIFIER_LENGTH (method_name));
+       }
+    }
+      
+  obstack_grow (&temporary_obstack, "__", 2);
+  if (ID_FINIT_P (method_name))
+    obstack_grow (&temporary_obstack, "finit", 5);
+  append_gpp_mangled_type (&temporary_obstack, this_class);
+  TREE_PUBLIC (method_decl) = 1;
+
+  t = TREE_TYPE (method_decl);
+  arglist = TYPE_ARG_TYPES (t);
+  if (TREE_CODE (t) == METHOD_TYPE)
+    arglist = TREE_CHAIN (arglist);
+  for (arg = arglist; arg != end_params_node;  )
+    {
+      tree a = arglist;
+      tree argtype = TREE_VALUE (arg);
+      int tindex = 1;
+      if (TREE_CODE (argtype) == POINTER_TYPE)
+       {
+         /* This is O(N**2).  Do we care?  Cfr gcc/cp/method.c. */
+         while (a != arg && argtype != TREE_VALUE (a))
+           a = TREE_CHAIN (a), tindex++;
+       }
+      else
+       a = arg;
+      if (a != arg)
+       {
+         char buf[12];
+         int nrepeats = 0;
+         do
            {
-             int encoded_len
-               = unicode_mangling_length (IDENTIFIER_POINTER (method_name), 
-                                          IDENTIFIER_LENGTH (method_name));
-             if (encoded_len > 0)
-               {
-                 method_name_needs_escapes = 1;
-                 emit_unicode_mangled_name (&temporary_obstack,
-                                            IDENTIFIER_POINTER (method_name), 
-                                            IDENTIFIER_LENGTH (method_name));
-               }
-             else
-               {
-                 obstack_grow (&temporary_obstack,
-                               IDENTIFIER_POINTER (method_name),
-                               IDENTIFIER_LENGTH (method_name));
-               }
+             arg = TREE_CHAIN (arg); nrepeats++;
            }
-
-         obstack_grow (&temporary_obstack, "__", 2);
-         if (method_name == finit_identifier_node)
-           obstack_grow (&temporary_obstack, "finit", 5);
-         append_gpp_mangled_type (&temporary_obstack, this_class);
-         TREE_PUBLIC (method_decl) = 1;
-
-         t = TREE_TYPE (method_decl);
-         arglist = TYPE_ARG_TYPES (t);
-         if (TREE_CODE (t) == METHOD_TYPE)
-           arglist = TREE_CHAIN (arglist);
-         for (arg = arglist; arg != NULL_TREE;  )
+         while (arg != end_params_node && argtype == TREE_VALUE (arg));
+         if (nrepeats > 1)
            {
-             tree a = arglist;
-             tree argtype = TREE_VALUE (arg);
-             int tindex = 1;
-             if (TREE_CODE (argtype) == POINTER_TYPE)
-               {
-                 /* This is O(N**2).  Do we care?  Cfr gcc/cp/method.c. */
-                 while (a != arg && argtype != TREE_VALUE (a))
-                   a = TREE_CHAIN (a), tindex++;
-               }
-             else
-               a = arg;
-             if (a != arg)
-               {
-                 char buf[12];
-                 int nrepeats = 0;
-                 do
-                   {
-                     arg = TREE_CHAIN (arg); nrepeats++;
-                   }
-                 while (arg != NULL_TREE && argtype == TREE_VALUE (arg));
-                 if (nrepeats > 1)
-                   {
-                     obstack_1grow (&temporary_obstack, 'N');
-                     sprintf (buf, "%d", nrepeats);
-                     obstack_grow (&temporary_obstack, buf, strlen (buf));
-                     if (nrepeats > 9)
-                       obstack_1grow (&temporary_obstack, '_');
-                   }
-                 else
-                   obstack_1grow (&temporary_obstack, 'T');
-                 sprintf (buf, "%d", tindex);
-                 obstack_grow (&temporary_obstack, buf, strlen (buf));
-                 if (tindex > 9)
-                   obstack_1grow (&temporary_obstack, '_');
-               }
-             else
-               {
-                 append_gpp_mangled_type (&temporary_obstack, argtype);
-                 arg = TREE_CHAIN (arg);
-               }
+             obstack_1grow (&temporary_obstack, 'N');
+             sprintf (buf, "%d", nrepeats);
+             obstack_grow (&temporary_obstack, buf, strlen (buf));
+             if (nrepeats > 9)
+               obstack_1grow (&temporary_obstack, '_');
            }
-         if (method_name_needs_escapes)
-           obstack_1grow (&temporary_obstack, 'U');
+         else
+           obstack_1grow (&temporary_obstack, 'T');
+         sprintf (buf, "%d", tindex);
+         obstack_grow (&temporary_obstack, buf, strlen (buf));
+         if (tindex > 9)
+           obstack_1grow (&temporary_obstack, '_');
        }
-      obstack_1grow (&temporary_obstack, '\0');
-      asm_name = obstack_finish (&temporary_obstack);
-      DECL_ASSEMBLER_NAME (method_decl) = get_identifier (asm_name);
-      if (! METHOD_ABSTRACT (method_decl))
-       make_function_rtl (method_decl);
-      obstack_free (&temporary_obstack, asm_name);
-
-      if (method_name == init_identifier_node)
+      else
        {
-         char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
-         for (ptr = p; *ptr; )
-           {
-             if (*ptr++ == '.')
-               p = ptr;
-           }
-         DECL_NAME (method_decl) = get_identifier (p);
-         DECL_CONSTRUCTOR_P (method_decl) = 1;
+         append_gpp_mangled_type (&temporary_obstack, argtype);
+         arg = TREE_CHAIN (arg);
        }
-      else if (! METHOD_STATIC (method_decl) && !DECL_ARTIFICIAL (method_decl))
+    }
+  if (method_name_needs_escapes)
+    obstack_1grow (&temporary_obstack, 'U');
+
+  obstack_1grow (&temporary_obstack, '\0');
+  asm_name = obstack_finish (&temporary_obstack);
+  DECL_ASSEMBLER_NAME (method_decl) = get_identifier (asm_name);
+  /* We don't generate a RTL for the method if it's abstract, or if
+     it's an interface method that isn't clinit. */
+  if (! METHOD_ABSTRACT (method_decl) 
+      || (CLASS_INTERFACE (TYPE_NAME (this_class)) 
+         && (DECL_CLINIT_P (method_decl))))
+    make_function_rtl (method_decl);
+  obstack_free (&temporary_obstack, asm_name);
+
+  if (ID_INIT_P (method_name))
+    {
+      const char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
+      for (ptr = p; *ptr; )
        {
-         tree method_sig = build_java_argument_signature (TREE_TYPE (method_decl));
-         tree super_method = lookup_argument_method (super_class, method_name,
+         if (*ptr++ == '.')
+           p = ptr;
+       }
+      if (method_name_is_wfl)
+       EXPR_WFL_NODE (DECL_NAME (method_decl)) = get_identifier (p);
+      else
+       DECL_NAME (method_decl) = get_identifier (p);
+      DECL_CONSTRUCTOR_P (method_decl) = 1;
+      build_java_argument_signature (TREE_TYPE (method_decl));
+    }
+  else if (! METHOD_STATIC (method_decl) && !DECL_ARTIFICIAL (method_decl))
+    {
+      tree method_sig = 
+       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)
-           {
-             DECL_VINDEX (method_decl) = DECL_VINDEX (super_method);
-             if (DECL_VINDEX (method_decl) == NULL_TREE)
-               error_with_decl (method_decl,
-                        "non-static method '%s' overrides static method");
+      if (super_method != NULL_TREE && ! METHOD_PRIVATE (super_method))
+       {
+         DECL_VINDEX (method_decl) = DECL_VINDEX (super_method);
+         if (DECL_VINDEX (method_decl) == NULL_TREE 
+             && !CLASS_FROM_SOURCE_P (this_class))
+           error_with_decl (method_decl,
+                            "non-static method '%s' overrides static method");
 #if 0
-             else if (TREE_TYPE (TREE_TYPE (method_decl))
-                      != TREE_TYPE (TREE_TYPE (super_method)))
-               {
-                 error_with_decl (method_decl,
-                                "Method `%s' redefined with different return type");  
-                 error_with_decl (super_method,
-                                "Overridden decl is here");
-               }
-#endif
-           }
-         else if (! METHOD_FINAL (method_decl)
-                  && ! CLASS_FINAL (TYPE_NAME (this_class)))
+         else if (TREE_TYPE (TREE_TYPE (method_decl))
+                  != TREE_TYPE (TREE_TYPE (super_method)))
            {
-             DECL_VINDEX (method_decl) = dtable_count;
-             dtable_count = build_int_2 (1+TREE_INT_CST_LOW (dtable_count), 0);
+             error_with_decl (method_decl,
+                              "Method `%s' redefined with different return type");  
+             error_with_decl (super_method,
+                              "Overridden decl is here");
            }
+#endif
+       }
+      else if (! METHOD_FINAL (method_decl)
+              && ! METHOD_PRIVATE (method_decl)
+              && ! CLASS_FINAL (TYPE_NAME (this_class))
+              && dtable_count)
+       {
+         DECL_VINDEX (method_decl) = dtable_count;
+         dtable_count = fold (build (PLUS_EXPR, integer_type_node,
+                                     dtable_count, integer_one_node));
        }
     }
-  TYPE_NVIRTUALS (this_class) = dtable_count;
 
-#ifdef JAVA_USE_HANDLES
-  layout_type (handle_type);
-#endif
+  return dtable_count;
 }
 
 static tree registered_class = NULL_TREE;
@@ -1554,15 +2004,12 @@ register_class ()
 void
 emit_register_classes ()
 {
-  tree decl = getdecls ();
-
-  extern tree get_file_function_name PROTO((int));
+  extern tree get_file_function_name PARAMS ((int));
   tree init_name = get_file_function_name ('I');
-  tree init_type = build_function_type (void_type_node, NULL_TREE);
+  tree init_type = build_function_type (void_type_node, end_params_node);
   tree init_decl;
   tree t;
 
-  start_sequence ();
   init_decl = build_decl (FUNCTION_DECL, init_name, init_type);
   DECL_ASSEMBLER_NAME (init_decl) = init_name;
   TREE_STATIC (init_decl) = 1;
@@ -1583,7 +2030,6 @@ emit_register_classes ()
   poplevel (1, 0, 1);
   { 
     /* Force generation, even with -O3 or deeper. Gross hack. FIXME */
-    extern int flag_inline_functions;
     int saved_flag = flag_inline_functions;
     flag_inline_functions = 0; 
     rest_of_compilation (init_decl);