jcf-parse.c (java_parse_file): Write otable and atable.
authorAndrew Haley <aph@redhat.com>
Wed, 1 Oct 2003 16:22:13 +0000 (16:22 +0000)
committerAndrew Haley <aph@gcc.gnu.org>
Wed, 1 Oct 2003 16:22:13 +0000 (16:22 +0000)
2003-10-01  Andrew Haley  <aph@redhat.com>

        * jcf-parse.c (java_parse_file): Write otable and atable.
        * java-tree.h (atable_methods): New.
        (atable_decl): New.
        (atable_syms_decl): New.
        (enum java_tree_index): Add JTI_ATABLE_METHODS, JTI_ATABLE_DECL,
        JTI_ATABLE_SYMS_DECL.  Rename JTI_METHOD_SYMBOL* to JTI_SYMBOL*.
        (symbol_*type): Rename method_symbol* to symbol*type.
        (emit_offset_symbol_table): Delete.
        (emit_symbol_table): New.
        (get_symbol_table_index): New.
        (atable_type): New.
        * expr.c (build_field_ref): Handle flag_indirect_dispatch.
        (build_known_method_ref): Likewise.
        (get_symbol_table_index): Rename from get_offset_table_index.
        Parameterize to allow re-use by differing types of symbol table.
        (build_invokevirtual): Pass table to get_offset_table_index.
        * decl.c (java_init_decl_processing): Push types and decls for
        atable and atable_syyms.
        * class.c (build_static_field_ref): Handle flag_indirect_dispatch.
        (make_class_data): Add new fields atable and atable_syms.
        (emit_symbol_table): Rename from emit_offset_symbol_table.
        Parameterize to allow re-use by different types of symbol table.
        (build_symbol_entry): Renamed from build_method_symbols_entry.

2003-10-01  Andrew Haley  <aph@redhat.com>

        * java/lang/natClass.cc (initializeClass): Check for otable and
        atable.
        (_Jv_LinkOffsetTable): Check for existence of atable.  Rewrite
        loops using for().  Search superinterfaces.  Check for fields as
        well as methods.  Initialize atable as well as otable: check for
        static methods as well as virtual methods.
        * java/lang/Class.h (struct _Jv_AddressTable): New.
        (atable): New.
        (atable_syms): New.
        * include/jvm.h (_Jv_equalUtf8Consts): constify.
        * prims.cc (_Jv_equalUtf8Consts): constify.

From-SVN: r71979

12 files changed:
gcc/java/ChangeLog
gcc/java/class.c
gcc/java/decl.c
gcc/java/expr.c
gcc/java/java-tree.h
gcc/java/jcf-parse.c
libjava/ChangeLog
libjava/include/jvm.h
libjava/java/lang/Class.h
libjava/java/lang/natClass.cc
libjava/java/util/LinkedList.java
libjava/prims.cc

index bf5da8c9ec9767dcb8defc44e1da1c55b225cc5e..ee3a016ba7d0b2067bb1b2e26ce1b5c736f7668f 100644 (file)
@@ -1,3 +1,29 @@
+2003-10-01  Andrew Haley  <aph@redhat.com>
+
+       * jcf-parse.c (java_parse_file): Write otable and atable.
+       * java-tree.h (atable_methods): New.
+       (atable_decl): New.
+       (atable_syms_decl): New.
+       (enum java_tree_index): Add JTI_ATABLE_METHODS, JTI_ATABLE_DECL,
+       JTI_ATABLE_SYMS_DECL.  Rename JTI_METHOD_SYMBOL* to JTI_SYMBOL*.
+       (symbol_*type): Rename method_symbol* to symbol*type.   
+       (emit_offset_symbol_table): Delete.
+       (emit_symbol_table): New.
+       (get_symbol_table_index): New.
+       (atable_type): New.
+       * expr.c (build_field_ref): Handle flag_indirect_dispatch.
+       (build_known_method_ref): Likewise.
+       (get_symbol_table_index): Rename from get_offset_table_index.
+       Parameterize to allow re-use by differing types of symbol table.
+       (build_invokevirtual): Pass table to get_offset_table_index.
+       * decl.c (java_init_decl_processing): Push types and decls for
+       atable and atable_syyms.
+       * class.c (build_static_field_ref): Handle flag_indirect_dispatch.
+       (make_class_data): Add new fields atable and atable_syms.
+       (emit_symbol_table): Rename from emit_offset_symbol_table.
+       Parameterize to allow re-use by different types of symbol table.
+       (build_symbol_entry): Renamed from build_method_symbols_entry.
+       
 2003-09-30  Roger Sayle  <roger@eyesopen.com>
 
        * jcf-write.c (generate_bytecode_insns): Implement evaluate-once
index 552a4f458620f4bd86e17341b521f6dbde32c763..d64db51fbd373c7188e1d7c31810f4fb94ed9e44 100644 (file)
@@ -59,7 +59,7 @@ static void add_interface_do (tree, tree, int);
 static tree maybe_layout_super_class (tree, tree);
 static void add_miranda_methods (tree, tree);
 static int assume_compiled (const char *);
-static tree build_method_symbols_entry (tree);
+static tree build_symbol_entry (tree);
 
 static GTY(()) rtx registerClass_libfunc;
 
@@ -925,7 +925,8 @@ build_static_field_ref (tree fdecl)
      However, currently sometimes gcj is too eager and will end up
      returning the field itself, leading to an incorrect external
      reference being generated.  */
-  if (is_compiled
+  if ((is_compiled 
+       && (! flag_indirect_dispatch || current_class == fclass))
       || (FIELD_FINAL (fdecl) && DECL_INITIAL (fdecl) != NULL_TREE
          && (JSTRING_TYPE_P (TREE_TYPE (fdecl))
              || JNUMERIC_TYPE_P (TREE_TYPE (fdecl)))
@@ -939,7 +940,18 @@ build_static_field_ref (tree fdecl)
        }
       return fdecl;
     }
-  else
+
+  if (flag_indirect_dispatch)
+    {
+      tree table_index 
+       = build_int_2 (get_symbol_table_index (fdecl, &atable_methods), 0);
+      tree field_address
+       = build (ARRAY_REF, build_pointer_type (TREE_TYPE (fdecl)), 
+                atable_decl, table_index);
+      return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl), 
+                          field_address));
+    }
+  else  
     {
       /* Compile as:
        * *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */
@@ -1500,7 +1512,6 @@ make_class_data (tree type)
                      : build (PLUS_EXPR, dtable_ptr_type,
                               build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl),
                               dtable_start_offset));
-  
   if (otable_methods == NULL_TREE)
     {
       PUSH_FIELD_VALUE (cons, "otable", null_pointer_node);
@@ -1511,9 +1522,25 @@ make_class_data (tree type)
       PUSH_FIELD_VALUE (cons, "otable",
                        build1 (ADDR_EXPR, otable_ptr_type, otable_decl));
       PUSH_FIELD_VALUE (cons, "otable_syms",
-                       build1 (ADDR_EXPR, method_symbols_array_ptr_type,
+                       build1 (ADDR_EXPR, symbols_array_ptr_type,
                                otable_syms_decl));
+      TREE_CONSTANT (otable_decl) = 1;
+    }
+  if (atable_methods == NULL_TREE)
+    {
+      PUSH_FIELD_VALUE (cons, "atable", null_pointer_node);
+      PUSH_FIELD_VALUE (cons, "atable_syms", null_pointer_node);
     }
+  else
+    {
+      PUSH_FIELD_VALUE (cons, "atable",
+                       build1 (ADDR_EXPR, atable_ptr_type, atable_decl));
+      PUSH_FIELD_VALUE (cons, "atable_syms",
+                       build1 (ADDR_EXPR, symbols_array_ptr_type,
+                               atable_syms_decl));
+      TREE_CONSTANT (atable_decl) = 1;
+    }
+
   PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
   PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "interface_count", build_int_2 (interface_len, 0));
@@ -2098,58 +2125,59 @@ emit_register_classes (void)
     }
 }
 
-/* Make a method_symbol_type (_Jv_MethodSymbol) node for METHOD. */
+/* Make a symbol_type (_Jv_MethodSymbol) node for DECL. */
 
 static tree
-build_method_symbols_entry (tree method)
+build_symbol_entry (tree decl)
 {
-  tree clname, name, signature, method_symbol;
+  tree clname, name, signature, sym;
   
-  clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (method))));
-  name = build_utf8_ref (DECL_NAME (method));
-  signature = build_java_signature (TREE_TYPE (method));
+  clname = build_utf8_ref (DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))));
+  name = build_utf8_ref (DECL_NAME (decl));
+  signature = build_java_signature (TREE_TYPE (decl));
   signature = build_utf8_ref (unmangle_classname 
                              (IDENTIFIER_POINTER (signature),
                               IDENTIFIER_LENGTH (signature)));
 
-  START_RECORD_CONSTRUCTOR (method_symbol, method_symbol_type);
-  PUSH_FIELD_VALUE (method_symbol, "clname", clname);
-  PUSH_FIELD_VALUE (method_symbol, "name", name);
-  PUSH_FIELD_VALUE (method_symbol, "signature", signature);
-  FINISH_RECORD_CONSTRUCTOR (method_symbol);
-  TREE_CONSTANT (method_symbol) = 1;
+  START_RECORD_CONSTRUCTOR (sym, symbol_type);
+  PUSH_FIELD_VALUE (sym, "clname", clname);
+  PUSH_FIELD_VALUE (sym, "name", name);
+  PUSH_FIELD_VALUE (sym, "signature", signature);
+  FINISH_RECORD_CONSTRUCTOR (sym);
+  TREE_CONSTANT (sym) = 1;
 
-  return method_symbol;
+  return sym;
 } 
 
-/* Emit the offset symbols table for indirect virtual dispatch. */
+/* Emit a symbol table: used by -findirect-dispatch.  */
 
-void
-emit_offset_symbol_table (void)
+tree
+emit_symbol_table (tree name, tree the_table, tree decl_list, tree the_syms_decl, 
+                         tree the_array_element_type)
 {
   tree method_list, method, table, list, null_symbol;
-  tree otable_bound, otable_array_type;
+  tree table_size, the_array_type;
   int index;
   
-  /* Only emit an offset table if this translation unit actually made virtual 
-     calls. */
-  if (otable_methods == NULL_TREE)
-    return;
+  /* Only emit a table if this translation unit actually made any
+     references via it. */
+  if (decl_list == NULL_TREE)
+    return the_table;
 
   /* Build a list of _Jv_MethodSymbols for each entry in otable_methods. */
   index = 0;
-  method_list = otable_methods;
+  method_list = decl_list;
   list = NULL_TREE;  
   while (method_list != NULL_TREE)
     {
       method = TREE_VALUE (method_list);
-      list = tree_cons (NULL_TREE, build_method_symbols_entry (method), list);
+      list = tree_cons (NULL_TREE, build_symbol_entry (method), list);
       method_list = TREE_CHAIN (method_list);
       index++;
     }
 
   /* Terminate the list with a "null" entry. */
-  START_RECORD_CONSTRUCTOR (null_symbol, method_symbol_type);
+  START_RECORD_CONSTRUCTOR (null_symbol, symbol_type);
   PUSH_FIELD_VALUE (null_symbol, "clname", null_pointer_node);
   PUSH_FIELD_VALUE (null_symbol, "name", null_pointer_node);
   PUSH_FIELD_VALUE (null_symbol, "signature", null_pointer_node);
@@ -2159,24 +2187,26 @@ emit_offset_symbol_table (void)
 
   /* Put the list in the right order and make it a constructor. */
   list = nreverse (list);
-  table = build_constructor (method_symbols_array_type, list);  
+  table = build_constructor (symbols_array_type, list);  
 
   /* Make it the initial value for otable_syms and emit the decl. */
-  DECL_INITIAL (otable_syms_decl) = table;
-  DECL_ARTIFICIAL (otable_syms_decl) = 1;
-  DECL_IGNORED_P (otable_syms_decl) = 1;
-  rest_of_decl_compilation (otable_syms_decl, NULL, 1, 0);
+  DECL_INITIAL (the_syms_decl) = table;
+  DECL_ARTIFICIAL (the_syms_decl) = 1;
+  DECL_IGNORED_P (the_syms_decl) = 1;
+  rest_of_decl_compilation (the_syms_decl, NULL, 1, 0);
   
-  /* Now that its size is known, redefine otable as an uninitialized static 
-     array of INDEX + 1 integers. The extra entry is used by the runtime 
-     to track whether the otable has been initialized. */
-  otable_bound = build_index_type (build_int_2 (index, 0));
-  otable_array_type = build_array_type (integer_type_node, otable_bound);
-  otable_decl = build_decl (VAR_DECL, get_identifier ("otable"), 
-                           otable_array_type);
-  TREE_STATIC (otable_decl) = 1;
-  TREE_READONLY (otable_decl) = 1;  
-  rest_of_decl_compilation (otable_decl, NULL, 1, 0);
+  /* Now that its size is known, redefine the table as an
+     uninitialized static array of INDEX + 1 elements. The extra entry
+     is used by the runtime to track whether the table has been
+     initialized. */
+  table_size = build_index_type (build_int_2 (index, 0));
+  the_array_type = build_array_type (the_array_element_type, table_size);
+  the_table = build_decl (VAR_DECL, name, the_array_type);
+  TREE_STATIC (the_table) = 1;
+  TREE_READONLY (the_table) = 1;  
+  rest_of_decl_compilation (the_table, NULL, 1, 0);
+
+  return the_table;
 }
 
 void
index 4e413de897d1db5ebffe486f032551928d98f7fe..8355431be583be3b5a93844d6a0c1e5c0a35939b 100644 (file)
@@ -621,32 +621,46 @@ java_init_decl_processing (void)
                                  one_elt_array_domain_type);
   TYPE_NONALIASED_COMPONENT (otable_type) = 1;
   otable_ptr_type = build_pointer_type (otable_type);
+  atable_type = build_array_type (ptr_type_node, 
+                                 one_elt_array_domain_type);
+  TYPE_NONALIASED_COMPONENT (atable_type) = 1;
+  atable_ptr_type = build_pointer_type (atable_type);
 
-  method_symbol_type = make_node (RECORD_TYPE);
-  PUSH_FIELD (method_symbol_type, field, "clname", utf8const_ptr_type);
-  PUSH_FIELD (method_symbol_type, field, "name", utf8const_ptr_type);
-  PUSH_FIELD (method_symbol_type, field, "signature", utf8const_ptr_type);
-  FINISH_RECORD (method_symbol_type);
+  symbol_type = make_node (RECORD_TYPE);
+  PUSH_FIELD (symbol_type, field, "clname", utf8const_ptr_type);
+  PUSH_FIELD (symbol_type, field, "name", utf8const_ptr_type);
+  PUSH_FIELD (symbol_type, field, "signature", utf8const_ptr_type);
+  FINISH_RECORD (symbol_type);
 
-  method_symbols_array_type = build_array_type (method_symbol_type, 
-                                               one_elt_array_domain_type);
-  method_symbols_array_ptr_type = build_pointer_type 
-                                 (method_symbols_array_type);
+  symbols_array_type = build_array_type (symbol_type, 
+                                        one_elt_array_domain_type);
+  symbols_array_ptr_type = build_pointer_type (symbols_array_type);
 
   if (flag_indirect_dispatch)
     {
-      otable_decl = build_decl (VAR_DECL, get_identifier ("otable"),
-                               otable_type);
+      otable_decl = build_decl (VAR_DECL, get_identifier ("otable"), otable_type);
       DECL_EXTERNAL (otable_decl) = 1;
       TREE_STATIC (otable_decl) = 1;
       TREE_READONLY (otable_decl) = 1;
-      pushdecl (otable_decl);
-  
+      TREE_CONSTANT (otable_decl) = 1;
+      pushdecl (otable_decl);  
       otable_syms_decl = build_decl (VAR_DECL, get_identifier ("otable_syms"), 
-                                    method_symbols_array_type);
+                                    symbols_array_type);
       TREE_STATIC (otable_syms_decl) = 1;
       TREE_CONSTANT (otable_syms_decl) = 1;
       pushdecl (otable_syms_decl);
+
+      atable_decl = build_decl (VAR_DECL, get_identifier ("atable"), atable_type);
+      DECL_EXTERNAL (atable_decl) = 1;
+      TREE_STATIC (atable_decl) = 1;
+      TREE_READONLY (atable_decl) = 1;
+      TREE_CONSTANT (atable_decl) = 1;
+      pushdecl (atable_decl);  
+      atable_syms_decl = build_decl (VAR_DECL, get_identifier ("atable_syms"), 
+                                    symbols_array_type);
+      TREE_STATIC (atable_syms_decl) = 1;
+      TREE_CONSTANT (atable_syms_decl) = 1;
+      pushdecl (atable_syms_decl);
     }
   
   PUSH_FIELD (object_type_node, field, "vtable", dtable_ptr_type);
@@ -684,7 +698,10 @@ java_init_decl_processing (void)
   PUSH_FIELD (class_type_node, field, "vtable", dtable_ptr_type);
   PUSH_FIELD (class_type_node, field, "otable", otable_ptr_type);
   PUSH_FIELD (class_type_node, field, "otable_syms", 
-             method_symbols_array_ptr_type);
+             symbols_array_ptr_type);
+  PUSH_FIELD (class_type_node, field, "atable", atable_ptr_type);
+  PUSH_FIELD (class_type_node, field, "atable_syms", 
+             symbols_array_ptr_type);
   PUSH_FIELD (class_type_node, field, "interfaces",
              build_pointer_type (class_ptr_type));
   PUSH_FIELD (class_type_node, field, "loader", ptr_type_node);
index 994a8c52ed3e6ca93bc00a0fb28c6de982b455e3..2c9ac09e7358bd55e9302cb4df95948af2a0496a 100644 (file)
@@ -84,7 +84,6 @@ static tree build_java_check_indexed_type (tree, tree);
 static tree case_identity (tree, tree); 
 static unsigned char peek_opcode_at_pc (struct JCF *, int, int);
 static int emit_init_test_initialization (void **entry, void * ptr);
-static int get_offset_table_index (tree);
 
 static GTY(()) tree operand_type[59];
 
@@ -1510,6 +1509,25 @@ build_field_ref (tree self_value, tree self_class, tree name)
       tree base_type = promote_type (base_class);
       if (base_type != TREE_TYPE (self_value))
        self_value = fold (build1 (NOP_EXPR, base_type, self_value));
+      if (flag_indirect_dispatch
+         && current_class != self_class)
+       /* FIXME: current_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 current_class.  If it is,
+          we can make a direct reference.  */
+       {
+         tree otable_index 
+           = build_int_2 
+           (get_symbol_table_index (field_decl, &otable_methods), 0);
+         tree field_offset = build (ARRAY_REF, integer_type_node, otable_decl, 
+                                    otable_index);
+         tree address 
+           = fold (build (PLUS_EXPR, 
+                          build_pointer_type (TREE_TYPE (field_decl)),
+                          self_value, field_offset));
+         return fold (build1 (INDIRECT_REF, TREE_TYPE (field_decl), address));
+       }
+
       self_value = build_java_indirect_ref (TREE_TYPE (TREE_TYPE (self_value)),
                                            self_value, check);
       return fold (build (COMPONENT_REF, TREE_TYPE (field_decl),
@@ -1744,8 +1762,19 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED,
   tree func;
   if (is_compiled_class (self_type))
     {
-      make_decl_rtl (method, NULL);
-      func = build1 (ADDR_EXPR, method_ptr_type_node, method);
+      if (!flag_indirect_dispatch
+         || (!TREE_PUBLIC (method) && DECL_CONTEXT (method)))
+       {
+         make_decl_rtl (method, NULL);
+         func = build1 (ADDR_EXPR, method_ptr_type_node, method);
+       }
+      else
+       {
+         tree table_index = build_int_2 (get_symbol_table_index 
+                                         (method, &atable_methods), 0);
+         func = build (ARRAY_REF,  method_ptr_type_node, atable_decl, 
+                       table_index);
+       }
     }
   else
     {
@@ -1816,27 +1845,29 @@ invoke_build_dtable (int is_invoke_interface, tree arg_list)
   return dtable;
 }
 
-/* Determine the index in the virtual offset table (otable) for a call to
-   METHOD. If this method has not been seen before, it will be added to the 
-   otable_methods. If it has, the existing otable slot will be reused. */
+/* Determine the index in SYMBOL_TABLE for a reference to the decl
+   T. If this decl has not been seen before, it will be added to the
+   otable_methods. If it has, the existing table slot will be
+   reused. */
 
-static int
-get_offset_table_index (tree method)
+int
+get_symbol_table_index (tree t, tree *symbol_table)
 {
   int i = 1;
   tree method_list;
-  
-  if (otable_methods == NULL_TREE)
+
+  if (*symbol_table == NULL_TREE)
     {
-      otable_methods = build_tree_list (method, method);
+      *symbol_table = build_tree_list (t, t);
       return 1;
     }
   
-  method_list = otable_methods;
+  method_list = *symbol_table;
   
   while (1)
     {
-      if (TREE_VALUE (method_list) == method)
+      tree value = TREE_VALUE (method_list);
+      if (value == t)
         return i;
       i++;
       if (TREE_CHAIN (method_list) == NULL_TREE)
@@ -1845,7 +1876,7 @@ get_offset_table_index (tree method)
         method_list = TREE_CHAIN (method_list);
     }
 
-  TREE_CHAIN (method_list) = build_tree_list (method, method);
+  TREE_CHAIN (method_list) = build_tree_list (t, t);
   return i;
 }
 
@@ -1860,7 +1891,8 @@ build_invokevirtual (tree dtable, tree method)
 
   if (flag_indirect_dispatch)
     {
-      otable_index = build_int_2 (get_offset_table_index (method), 0);
+      otable_index 
+       = build_int_2 (get_symbol_table_index (method, &otable_methods), 0);
       method_index = build (ARRAY_REF, integer_type_node, otable_decl, 
                            otable_index);
     }
@@ -1924,7 +1956,8 @@ build_invokeinterface (tree dtable, tree method)
   
   if (flag_indirect_dispatch)
     {
-      otable_index = build_int_2 (get_offset_table_index (method), 0);
+      otable_index 
+       = build_int_2 (get_symbol_table_index (method, &otable_methods), 0);
       idx = build (ARRAY_REF, integer_type_node, otable_decl, otable_index);
     }
   else
index 8f524284c486867d81b33d21e273f339303a5af8..42f99b57e95c71eb6eceff3a84b6584f92b8d0b2 100644 (file)
@@ -146,17 +146,26 @@ extern int compiling_from_source;
 /* List of all class filenames seen so far.  */
 #define all_class_filename java_global_trees [JTI_ALL_CLASS_FILENAME]
 
-/* List of virtual method decls called in this translation unit, used to 
-   generate virtual method offset symbol table. */
+/* List of virtual decls referred to by this translation unit, used to
+   generate virtual method offset symbol table.  */
 #define otable_methods java_global_trees [JTI_OTABLE_METHODS]
+/* List of static decls referred to by this translation unit, used to
+   generate virtual method offset symbol table.  */
+#define atable_methods java_global_trees [JTI_ATABLE_METHODS]
 
-/* The virtual method offset table. This is emitted as uninitialized data of 
-   the required length, and filled out at run time during class linking. */
+/* The virtual offset table.  This is emitted as uninitialized data of
+   the required length, and filled out at run time during class
+   linking. */
 #define otable_decl java_global_trees [JTI_OTABLE_DECL]
+/* The static address table.  */
+#define atable_decl java_global_trees [JTI_ATABLE_DECL]
 
-/* The virtual method offset symbol table. Used by the runtime to fill out the
-   otable. */
+/* The virtual offset symbol table. Used by the runtime to fill out
+   the otable. */
 #define otable_syms_decl java_global_trees [JTI_OTABLE_SYMS_DECL]
+/* The static symbol table. Used by the runtime to fill out the
+   otable. */
+#define atable_syms_decl java_global_trees [JTI_ATABLE_SYMS_DECL]
 
 extern int flag_emit_class_files;
 
@@ -364,9 +373,11 @@ enum java_tree_index
   JTI_METHOD_PTR_TYPE_NODE,
   JTI_OTABLE_TYPE,
   JTI_OTABLE_PTR_TYPE,
-  JTI_METHOD_SYMBOL_TYPE,
-  JTI_METHOD_SYMBOLS_ARRAY_TYPE,
-  JTI_METHOD_SYMBOLS_ARRAY_PTR_TYPE,
+  JTI_ATABLE_TYPE,
+  JTI_ATABLE_PTR_TYPE,
+  JTI_SYMBOL_TYPE,
+  JTI_SYMBOLS_ARRAY_TYPE,
+  JTI_SYMBOLS_ARRAY_PTR_TYPE,
 
   JTI_END_PARAMS_NODE,
 
@@ -409,6 +420,10 @@ enum java_tree_index
   JTI_OTABLE_DECL,
   JTI_OTABLE_SYMS_DECL,
 
+  JTI_ATABLE_METHODS,
+  JTI_ATABLE_DECL,
+  JTI_ATABLE_SYMS_DECL,
+
   JTI_PREDEF_FILENAMES,
 
   JTI_MAX
@@ -602,14 +617,18 @@ extern GTY(()) tree java_global_trees[JTI_MAX];
   java_global_trees[JTI_METHOD_PTR_TYPE_NODE]
 #define otable_type \
   java_global_trees[JTI_OTABLE_TYPE]
+#define atable_type \
+  java_global_trees[JTI_ATABLE_TYPE]
 #define otable_ptr_type \
   java_global_trees[JTI_OTABLE_PTR_TYPE]
-#define method_symbol_type \
-  java_global_trees[JTI_METHOD_SYMBOL_TYPE]
-#define method_symbols_array_type \
-  java_global_trees[JTI_METHOD_SYMBOLS_ARRAY_TYPE]
-#define method_symbols_array_ptr_type \
-  java_global_trees[JTI_METHOD_SYMBOLS_ARRAY_PTR_TYPE]
+#define atable_ptr_type \
+  java_global_trees[JTI_ATABLE_PTR_TYPE]
+#define symbol_type \
+  java_global_trees[JTI_SYMBOL_TYPE]
+#define symbols_array_type \
+  java_global_trees[JTI_SYMBOLS_ARRAY_TYPE]
+#define symbols_array_ptr_type \
+  java_global_trees[JTI_SYMBOLS_ARRAY_PTR_TYPE]
 
 #define end_params_node \
   java_global_trees[JTI_END_PARAMS_NODE]
@@ -1199,7 +1218,7 @@ extern void make_class_data (tree);
 extern void register_class (void);
 extern int alloc_name_constant (int, tree);
 extern void emit_register_classes (void);
-extern void emit_offset_symbol_table (void);
+extern tree emit_symbol_table (tree, tree, tree, tree, tree);
 extern void lang_init_source (int);
 extern void write_classfile (tree);
 extern char *print_int_node (tree);
@@ -1299,6 +1318,7 @@ extern void init_resource_processing (void);
 extern void start_complete_expand_method (tree);
 extern void java_expand_body (tree);
 
+extern int get_symbol_table_index (tree, tree *);
 
 #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
 
@@ -1658,11 +1678,11 @@ extern tree *type_map;
 /* Append a field initializer to CONS for a field with the given VALUE.
    NAME is a char* string used for error checking;
    the initializer must be specified in order. */
-#define PUSH_FIELD_VALUE(CONS, NAME, VALUE) {\
-  tree field = TREE_CHAIN(CONS);\
-  if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)), NAME) != 0) abort();\
-  CONSTRUCTOR_ELTS(CONS) = tree_cons (field, VALUE, CONSTRUCTOR_ELTS(CONS));\
-  TREE_CHAIN(CONS) = TREE_CHAIN (field); }
+  #define PUSH_FIELD_VALUE(CONS, NAME, VALUE) {\
+    tree field = TREE_CHAIN(CONS);\
+    if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)), NAME) != 0) abort();\
+    CONSTRUCTOR_ELTS(CONS) = tree_cons (field, VALUE, CONSTRUCTOR_ELTS(CONS));\
+    TREE_CHAIN(CONS) = TREE_CHAIN (field); }
 
 /* Finish creating a record CONSTRUCTOR CONS. */
 #define FINISH_RECORD_CONSTRUCTOR(CONS) \
index 4abd6ceac6efbc2ef58b2600a6a51aebabb93c08..de4b213a6c68bc83bbff00a81c6b94cd30668bb4 100644 (file)
@@ -1127,7 +1127,16 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
       /* Emit the .jcf section.  */
       emit_register_classes ();
       if (flag_indirect_dispatch)
-       emit_offset_symbol_table ();
+       {
+         otable_decl 
+           = emit_symbol_table 
+           (get_identifier ("otable"), 
+            otable_decl, otable_methods, otable_syms_decl, integer_type_node);
+         atable_decl 
+           = emit_symbol_table 
+           (get_identifier ("atable"), 
+            atable_decl, atable_methods, atable_syms_decl, ptr_type_node);
+       }
     }
 
   write_resource_constructor ();
index d12987a7227d9898c58a7fce363659946d1f4e69..a86041acd2d44a2193d3d155a936a84f29b0676e 100644 (file)
@@ -1,3 +1,17 @@
+2003-10-01  Andrew Haley  <aph@redhat.com>
+
+       * java/lang/natClass.cc (initializeClass): Check for otable and
+       atable.
+       (_Jv_LinkOffsetTable): Check for existence of atable.  Rewrite
+       loops using for().  Search superinterfaces.  Check for fields as
+       well as methods.  Initialize atable as well as otable: check for
+       static methods as well as virtual methods.
+       * java/lang/Class.h (struct _Jv_AddressTable): New.
+       (atable): New.
+       (atable_syms): New.
+       * include/jvm.h (_Jv_equalUtf8Consts): constify.
+       * prims.cc (_Jv_equalUtf8Consts): constify.
+
 2003-09-29  Tom Tromey  <tromey@redhat.com>
 
        PR libgcj/10596:
index ed6c61ec50dec16648755a428b7ef6f7e792c97e..b28f61a0e970c635fc6e66fdb270441e14bbe4ca 100644 (file)
@@ -145,7 +145,7 @@ extern int _Jv_strLengthUtf8(char* str, int len);
 typedef struct _Jv_Utf8Const Utf8Const;
 _Jv_Utf8Const *_Jv_makeUtf8Const (char *s, int len);
 _Jv_Utf8Const *_Jv_makeUtf8Const (jstring string);
-extern jboolean _Jv_equalUtf8Consts (_Jv_Utf8Const *, _Jv_Utf8Const *);
+extern jboolean _Jv_equalUtf8Consts (const _Jv_Utf8Const *, const _Jv_Utf8Const *);
 extern jboolean _Jv_equal (_Jv_Utf8Const *, jstring, jint);
 extern jboolean _Jv_equaln (_Jv_Utf8Const *, jstring, jint);
 
index 7fe96d0a01fd63fd5dbbe14166ebd0eb855ce6a7..7572c6cfdb2920566d8c79d17762d4f1138b1d60 100644 (file)
@@ -125,6 +125,12 @@ struct _Jv_OffsetTable
   jint offsets[];
 };
 
+struct _Jv_AddressTable
+{
+  jint state;
+  void *addresses[];
+};
+
 #define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
 
 #define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
@@ -324,7 +330,7 @@ private:
   friend jstring _Jv_GetMethodString(jclass, _Jv_Utf8Const *);
   friend jshort _Jv_AppendPartialITable (jclass, jclass, void **, jshort);
   friend jshort _Jv_FindIIndex (jclass *, jshort *, jshort);
-  friend void _Jv_LinkOffsetTable (jclass);
+  friend void _Jv_LinkSymbolTable (jclass);
   friend void _Jv_LayoutVTableMethods (jclass klass);
   friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
   friend void _Jv_MakeVTable (jclass);
@@ -404,6 +410,8 @@ private:
   _Jv_OffsetTable *otable;
   // Offset table symbols.
   _Jv_MethodSymbol *otable_syms;
+  _Jv_AddressTable *atable;
+  _Jv_MethodSymbol *atable_syms;
   // Interfaces implemented by this class.
   jclass *interfaces;
   // The class loader for this class.
index 551a5312fe56f59ea15285fad4f546159fc7c29a..aa5867fc8711db8916e2c9c41ab8b226205d7e7a 100644 (file)
@@ -36,6 +36,7 @@ details.  */
 #include <java/lang/IllegalAccessError.h>
 #include <java/lang/IllegalArgumentException.h>
 #include <java/lang/IncompatibleClassChangeError.h>
+#include <java/lang/NoSuchFieldError.h>
 #include <java/lang/ArrayIndexOutOfBoundsException.h>
 #include <java/lang/InstantiationException.h>
 #include <java/lang/NoClassDefFoundError.h>
@@ -790,7 +791,7 @@ java::lang::Class::initializeClass (void)
          so ensure internal tables are built.  */
       _Jv_PrepareConstantTimeTables (this);
       _Jv_MakeVTable(this);
-      _Jv_LinkOffsetTable(this);
+      _Jv_LinkSymbolTable(this);
 
       return;
     }
@@ -830,8 +831,8 @@ java::lang::Class::initializeClass (void)
   if (vtable == NULL)
     _Jv_MakeVTable(this);
 
-  if (otable != NULL && otable->state == 0)
-    _Jv_LinkOffsetTable(this);
+  if (otable || atable)
+    _Jv_LinkSymbolTable(this);
 
   // Steps 8, 9, 10, 11.
   try
@@ -1533,75 +1534,238 @@ java::lang::Class::getProtectionDomain0 ()
   return protectionDomain;
 }
 
-// Functions for indirect dispatch (symbolic virtual method binding) support.
+// Functions for indirect dispatch (symbolic virtual binding) support.
+
+// There are two tables, atable and otable.  atable is an array of
+// addresses, and otable is an array of offsets, and these are used
+// for static and virtual members respectively.
+
+// {a,o}table_syms is an array of _Jv_MethodSymbols.  Each such symbol
+// is a tuple of {classname, member name, signature}.
+// _Jv_LinkSymbolTable() scans these two arrays and fills in the
+// corresponding atable and otable with the addresses of static
+// members and the offsets of virtual members.
+
+// The offset (in bytes) for each resolved method or field is placed
+// at the corresponding position in the virtual method offset table
+// (klass->otable). 
+
+// The same otable and atable may be shared by many classes.
 
-// Resolve entries in the virtual method offset symbol table 
-// (klass->otable_syms). The vtable offset (in bytes) for each resolved method 
-// is placed at the corresponding position in the virtual method offset table 
-// (klass->otable). A single otable and otable_syms pair may be shared by many 
-// classes.
 void
-_Jv_LinkOffsetTable(jclass klass)
+_Jv_LinkSymbolTable(jclass klass)
 {
-  //// FIXME: Need to lock the otable ////
+  //// FIXME: Need to lock the tables ////
   
+  int index = 0;
+  _Jv_MethodSymbol sym;
   if (klass->otable == NULL
       || klass->otable->state != 0)
-    return;
-  
+    goto atable;
+   
   klass->otable->state = 1;
 
-  int index = 0;
-  _Jv_MethodSymbol sym = klass->otable_syms[0];
-
-  while (sym.name != NULL)
+  for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++)
     {
       jclass target_class = _Jv_FindClass (sym.class_name, NULL);
       _Jv_Method *meth = NULL;            
+
+      const _Jv_Utf8Const *signature = sym.signature;
+
+      // FIXME: This should be special index for ThrowNoSuchMethod().
+      klass->otable->offsets[index] = -1;
       
-      if (target_class != NULL)
-       if (target_class->isInterface())
+      if (target_class == NULL)
+       continue;
+
+      if (target_class->isInterface())
+       {
+         // FIXME: This does not yet fully conform to binary compatibility
+         // rules. It will break if a declaration is moved into a 
+         // superinterface.
+         for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
+           {
+             for (int i=0; i < cls->method_count; i++)
+               {
+                 meth = &cls->methods[i];
+                 if (_Jv_equalUtf8Consts (sym.name, meth->name)
+                     && _Jv_equalUtf8Consts (signature, meth->signature))
+                   {
+                     klass->otable->offsets[index] = i + 1;
+                     goto found;
+                   }
+               }
+           
+           }
+       found:
+         continue;
+       }
+
+      // We're looking for a field or a method, and we can tell
+      // which is needed by looking at the signature.
+      if (signature->length >= 2
+         && signature->data[0] == '(')
+       {
+         // If the target class does not have a vtable_method_count yet, 
+         // then we can't tell the offsets for its methods, so we must lay 
+         // it out now.
+         if (target_class->vtable_method_count == -1)
+           {
+             JvSynchronize sync (target_class);
+             _Jv_LayoutVTableMethods (target_class);
+           }
+               
+         meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
+                                         sym.signature);
+               
+         if (meth != NULL)
+           {
+             klass->otable->offsets[index] = 
+               _Jv_VTable::idx_to_offset (meth->index);              
+           }
+
+         continue;
+       }
+
+      // try fields
+      {
+       _Jv_Field *the_field = NULL;
+
+       for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
          {
-           // FIXME: This does not yet fully conform to binary compatibility
-           // rules. It will break if a declaration is moved into a 
-           // superinterface.
-           for (int i=0; i < target_class->method_count; i++)
+           for (int i = 0; i < cls->field_count; i++)
              {
-               meth = &target_class->methods[i];
-               if (_Jv_equalUtf8Consts (sym.name, meth->name)
-                   && _Jv_equalUtf8Consts (sym.signature, meth->signature))
-                 {
-                   klass->otable->offsets[index] = i + 1;
-                   break;
-                 }
+               _Jv_Field *field = &cls->fields[i];
+               if (! _Jv_equalUtf8Consts (field->name, sym.name))
+                 continue;
+
+               // FIXME: What access checks should we perform here?
+//             if (_Jv_CheckAccess (klass, cls, field->flags))
+//               {
+
+               if (!field->isResolved ())
+                 _Jv_ResolveField (field, cls->loader);
+
+//             if (field_type != 0 && field->type != field_type)
+//               throw new java::lang::LinkageError
+//                 (JvNewStringLatin1 
+//                  ("field type mismatch with different loaders"));
+
+               the_field = field;
+               goto end_of_field_search;
              }
          }
-       else
+      end_of_field_search:
+       if (the_field != NULL)
          {
-           // If the target class does not have a vtable_method_count yet, 
-           // then we can't tell the offsets for its methods, so we must lay 
-           // it out now.
-           if (target_class->vtable_method_count == -1)
+           if (the_field->flags & 0x0008 /* Modifier::STATIC */)
+             {       
+               throw new java::lang::IncompatibleClassChangeError;
+             }
+           else
              {
-               JvSynchronize sync (target_class);
-               _Jv_LayoutVTableMethods (target_class);
+               klass->otable->offsets[index] = the_field->u.boffset;
              }
+         }
+       else
+         {
+           throw new java::lang::NoSuchFieldError
+             (_Jv_NewStringUtf8Const (sym.name));
+         }
+      }
+    }
+
+ atable:
+  if (klass->atable == NULL
+      || klass->atable->state != 0)
+    return;
+
+  klass->atable->state = 1;
+
+  for (index = 0; sym = klass->atable_syms[index], sym.name != NULL; index++)
+    {
+      jclass target_class = _Jv_FindClass (sym.class_name, NULL);
+      _Jv_Method *meth = NULL;            
+      const _Jv_Utf8Const *signature = sym.signature;
+
+      // ??? Setting this pointer to null will at least get us a
+      // NullPointerException
+      klass->atable->addresses[index] = NULL;
+      
+      if (target_class == NULL)
+       continue;
+      
+      // We're looking for a static field or a static method, and we
+      // can tell which is needed by looking at the signature.
+      if (signature->length >= 2
+         && signature->data[0] == '(')
+       {
+         // If the target class does not have a vtable_method_count yet, 
+         // then we can't tell the offsets for its methods, so we must lay 
+         // it out now.
+         if (target_class->vtable_method_count == -1)
+           {
+             JvSynchronize sync (target_class);
+             _Jv_LayoutVTableMethods (target_class);
+           }
+         
+         meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
+                                         sym.signature);
+         
+         if (meth != NULL)
+           klass->atable->addresses[index] = meth->ncode;
+         else
+           klass->atable->addresses[index] = (void *)_Jv_ThrowNoSuchMethodError;
 
-            meth = _Jv_LookupDeclaredMethod(target_class, sym.name, 
-                                           sym.signature);
+         continue;
+       }
+
+      // try fields
+      {
+       _Jv_Field *the_field = NULL;
 
-           if (meth != NULL)
+       for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
+         {
+           for (int i = 0; i < cls->field_count; i++)
              {
-               klass->otable->offsets[index] = 
-                 _Jv_VTable::idx_to_offset (meth->index);
+               _Jv_Field *field = &cls->fields[i];
+               if (! _Jv_equalUtf8Consts (field->name, sym.name))
+                 continue;
+
+               // FIXME: What access checks should we perform here?
+//             if (_Jv_CheckAccess (klass, cls, field->flags))
+//               {
+
+               if (!field->isResolved ())
+                 _Jv_ResolveField (field, cls->loader);
+               
+//             if (field_type != 0 && field->type != field_type)
+//               throw new java::lang::LinkageError
+//                 (JvNewStringLatin1 
+//                  ("field type mismatch with different loaders"));
+
+               the_field = field;
+               goto end_of_static_field_search;
              }
          }
-
-      if (meth == NULL)
-       // FIXME: This should be special index for ThrowNoSuchMethod().
-       klass->otable->offsets[index] = -1;
-
-      sym = klass->otable_syms[++index];
+      end_of_static_field_search:
+       if (the_field != NULL)
+         {
+           if (the_field->flags & 0x0008 /* Modifier::STATIC */)
+             {       
+               klass->atable->addresses[index] = the_field->u.addr;
+             }
+           else
+             {
+               throw new java::lang::IncompatibleClassChangeError;
+             }
+         }
+       else
+         {
+           throw new java::lang::NoSuchFieldError
+             (_Jv_NewStringUtf8Const (sym.name));
+         }
+      }
     }
 }
 
index c891f8230f086d2fdfa50cee05991ffe3022473d..2f21fb46735b48511b15005d70789b6eb475627b 100644 (file)
@@ -1,4 +1,4 @@
-/* LinkedList.java -- Linked list implementation of the List interface
+ /* LinkedList.java -- Linked list implementation of the List interface
    Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
index 8208995460e125f70ecbf11645fbd2b9fdf182c4..f15c24b796291332830f1f7b88ea24341a63672d 100644 (file)
@@ -165,10 +165,10 @@ SIGNAL_HANDLER (catch_fpe)
 \f
 
 jboolean
-_Jv_equalUtf8Consts (Utf8Const* a, Utf8Const *b)
+_Jv_equalUtf8Consts (const Utf8Const* a, const Utf8Const *b)
 {
   int len;
-  _Jv_ushort *aptr, *bptr;
+  const _Jv_ushort *aptr, *bptr;
   if (a == b)
     return true;
   if (a->hash != b->hash)
@@ -176,8 +176,8 @@ _Jv_equalUtf8Consts (Utf8Const* a, Utf8Const *b)
   len = a->length;
   if (b->length != len)
     return false;
-  aptr = (_Jv_ushort *)a->data;
-  bptr = (_Jv_ushort *)b->data;
+  aptr = (const _Jv_ushort *)a->data;
+  bptr = (const _Jv_ushort *)b->data;
   len = (len + 1) >> 1;
   while (--len >= 0)
     if (*aptr++ != *bptr++)