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


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

Java: PR12755: Resolving static methods and classes is not thread safe


This is a big reorganization of indirect dispatch.

The killer problem was that the previous code was far to eager; it
resolved all the references made by every class even if some of them
would never be used.  This code is much less aggressive, but it is
somewhat less efficient because classes no longer share dispatch
tables.  It is correct, though.

Tested w/ full bootstrap, no regressions.

This patch makes possible a bunch of libgcj changes that will allow
12755 to be closed.

Andrew.

2004-01-05  Andrew Haley  <aph@redhat.com>

	PR java/12755:
	* parse.y (java_fix_constructors):  Set output_class.
	(java_reorder_fields): Likewise.
	(java_layout_classes): Likewise.
	(java_expand_classes): Generate indirect dispatch tables.
	(java_expand_classes): Set output_class.
	(java_finish_classes): Likewise.
	* lang.c (java_init): Turn on always_initialize_class_p if we're
	using indirect dis[atch.
	(java_decl_ok_for_sibcall): Use output_class, not current_class.
	(java_get_callee_fndecl): Use class local atable.
	* jcf-parse.c 
	(always_initialize_class_p): Decl moved to java-tree.h.
	(HANDLE_CLASS_INFO): Set output_class.
	(read_class): Likewise.
	(parse_class_file): Call gen_indirect_dispatch_tables.
	(parse_zip_file_entries): Set output_class.
	(java_parse_file): Set output_class.  Don't emit symbol tables.
	* java-tree.h (output_class): New.
	Remove global declarations for otable, atable, and ctable.
	(always_initialize_class_p): moved here from decl.c.
	(DECL_OWNER): New.
	(TYPE_ATABLE_METHODS, TYPE_ATABLE_SYMS_DECL, TYPE_ATABLE_DECL,
	TYPE_OTABLE_METHODS, TYPE_OTABLE_SYMS_DECL, TYPE_OTABLE_DECL,
	TYPE_CTABLE_DECL, TYPE_CATCH_CLASSES): New.
	(struct lang_type): Add otable_methods, otable_decl,
	otable_syms_decl, atable_methods, atable_decl, atable_syms_decl,
	ctable_decl, catch_classes, type_to_runtime_map.
	* expr.c (build_field_ref): Make otable, atable, and ctable class
	local rather than global.
	(build_known_method_ref): Likewise.
	(build_invokeinterface): Likewise.
	(java_expand_expr): Pass runtime type (rather than actual type) to
	expand_start_catch.
	* except.c (prepare_eh_table_type): Create TYPE_TO_RUNTIME_MAP for
	this class.  Look up each class in that map to delete duplicates.
	(expand_end_java_handler): Pass runtime type (rather than actual
	type) to expand_start_catch.
	* decl.c: (always_initialize_class_p): Decl moved to java-tree.h.
	(do_nothing): New.
	(java_init_decl_processing): Rearrange things.  Remove global
	declarations of otable, atable, and ctable.
	(java_init_decl_processing): Make lang_eh_runtime_type do_nothing.
	(java_expand_body): Set output_class.
	* constants.c (build_constant_data_ref): Use output_class, not
	current_class.
	(alloc_name_constant): Likewise.
	* class.c (gen_indirect_dispatch_tables): New.
	(build_class_ref): Generate hard reference to superclass, even if
	using indirect dispatch.
	(build_static_field_ref): Use class local atable.
	(make_class_data): Generate hard reference to superclass, even if
	using indirect dispatch.
	Generate symbolic references to interfaces when using indirect
	dispatch.
	(make_class_data): Emit otable, atable, and ctable.
	Make otable, atable, and ctable class local rather than global.
	(emit_catch_table): Make otable, atable, and ctable class local
	rather than global.
		
Index: java/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.174
diff -p -2 -c -r1.174 class.c
*** java/class.c	20 Dec 2003 15:38:27 -0000	1.174
--- java/class.c	6 Jan 2004 11:11:04 -0000
*************** The Free Software Foundation is independ
*** 43,46 ****
--- 43,47 ----
  #include "stdio.h"
  #include "target.h"
+ #include "except.h"
  
  /* DOS brain-damage */
*************** unmangle_classname (const char *name, in
*** 305,308 ****
--- 306,386 ----
  }
  
+ 
+ /* Given a class, create the DECLs for all its associated indirect dispatch tables.  */
+ void
+ gen_indirect_dispatch_tables (tree type)
+ {
+   const char *typename = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+   {  
+     tree field = NULL;
+     char *buf = alloca (strlen (typename) + strlen ("_catch_classes_"));
+     tree catch_class_type = make_node (RECORD_TYPE);
+ 
+     sprintf (buf, "_catch_classes_%s", typename);
+     PUSH_FIELD (catch_class_type, field, "address", utf8const_ptr_type);
+     PUSH_FIELD (catch_class_type, field, "classname", ptr_type_node);
+     FINISH_RECORD (catch_class_type);
+     
+     TYPE_CTABLE_DECL (type) 
+       = build_decl (VAR_DECL, get_identifier (buf),
+ 		    build_array_type (catch_class_type, 0));
+     DECL_EXTERNAL (TYPE_CTABLE_DECL (type)) = 1;
+     TREE_STATIC (TYPE_CTABLE_DECL (type)) = 1;
+     TREE_READONLY (TYPE_CTABLE_DECL (type)) = 1;
+     TREE_CONSTANT (TYPE_CTABLE_DECL (type)) = 1;
+     DECL_IGNORED_P (TYPE_CTABLE_DECL (type)) = 1;
+     pushdecl (TYPE_CTABLE_DECL (type));  
+   }
+ 
+   if (flag_indirect_dispatch)
+     {
+       {
+ 	char *buf = alloca (strlen (typename) + strlen ("_otable_syms_"));
+ 
+ 	sprintf (buf, "_otable_%s", typename);
+ 	TYPE_OTABLE_DECL (type) = 
+ 	  build_decl (VAR_DECL, get_identifier (buf), otable_type);
+ 	DECL_EXTERNAL (TYPE_OTABLE_DECL (type)) = 1;
+ 	TREE_STATIC (TYPE_OTABLE_DECL (type)) = 1;
+ 	TREE_READONLY (TYPE_OTABLE_DECL (type)) = 1;
+ 	TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1;
+ 	DECL_IGNORED_P (TYPE_OTABLE_DECL (type)) = 1;
+ 	pushdecl (TYPE_OTABLE_DECL (type));  
+ 	sprintf (buf, "_otable_syms_%s", typename);
+ 	TYPE_OTABLE_SYMS_DECL (type) = 
+ 	  build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);
+ 	TREE_STATIC (TYPE_OTABLE_SYMS_DECL (type)) = 1;
+ 	TREE_CONSTANT (TYPE_OTABLE_SYMS_DECL (type)) = 1;
+ 	DECL_IGNORED_P(TYPE_OTABLE_SYMS_DECL (type)) = 1;
+ 	pushdecl (TYPE_OTABLE_SYMS_DECL (type));
+       }
+ 
+       {
+ 	char *buf = alloca (strlen (typename) + strlen ("_atable_syms_"));
+ 	tree decl;
+ 
+ 	sprintf (buf, "_atable_%s", typename);
+ 	TYPE_ATABLE_DECL (type) = decl =
+ 	  build_decl (VAR_DECL, get_identifier (buf), atable_type);
+ 	DECL_EXTERNAL (decl) = 1;
+ 	TREE_STATIC (decl) = 1;
+ 	TREE_READONLY (decl) = 1;
+ 	TREE_CONSTANT (decl) = 1;
+ 	DECL_IGNORED_P (decl) = 1;
+ 	/* Mark the atable as belonging to this class.  */
+ 	pushdecl (decl);  
+ 	MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
+ 	DECL_OWNER (decl) = type;
+ 	sprintf (buf, "_atable_syms_%s", typename);
+ 	TYPE_ATABLE_SYMS_DECL (type) = 
+ 	  build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);
+ 	TREE_STATIC (TYPE_ATABLE_SYMS_DECL (type)) = 1;
+ 	TREE_CONSTANT (TYPE_ATABLE_SYMS_DECL (type)) = 1;
+ 	DECL_IGNORED_P (TYPE_ATABLE_SYMS_DECL (type)) = 1;
+ 	pushdecl (TYPE_ATABLE_SYMS_DECL (type));
+       }
+     }
+ }
+ 
  tree
  push_class (tree class_type, tree class_name)
*************** build_class_ref (tree type)
*** 836,841 ****
  	type = TREE_TYPE (type);
  
!       if  (flag_indirect_dispatch 
! 	   && type != current_class
  	   && TREE_CODE (type) == RECORD_TYPE)
  	return build_indirect_class_ref (type);
--- 914,924 ----
  	type = TREE_TYPE (type);
  
!       /* FIXME: we really want an indirect reference to our
! 	 superclass.  However, libgcj assumes that a superclass
! 	 pointer always points directly to a class.  As a workaround
! 	 we always emit this hard superclass reference.  */
!       if  (flag_indirect_dispatch
! 	   && type != output_class
! 	   && type != CLASSTYPE_SUPER (output_class)
  	   && TREE_CODE (type) == RECORD_TYPE)
  	return build_indirect_class_ref (type);
*************** build_static_field_ref (tree fdecl)
*** 958,965 ****
      {
        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));
--- 1041,1049 ----
      {
        tree table_index 
! 	= build_int_2 (get_symbol_table_index 
! 		       (fdecl, &TYPE_ATABLE_METHODS (output_class)), 0);
        tree field_address
  	= build (ARRAY_REF, build_pointer_type (TREE_TYPE (fdecl)), 
! 		 TYPE_ATABLE_DECL (output_class), table_index);
        return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl), 
  			   field_address));
*************** make_class_data (tree type)
*** 1436,1441 ****
    if (super == NULL_TREE)
      super = null_pointer_node;
!   else if (! flag_indirect_dispatch
! 	   && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
  	   && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (super)))))
      super = build_class_ref (super);
--- 1520,1527 ----
    if (super == NULL_TREE)
      super = null_pointer_node;
!   else if (/* FIXME: we should also test for (!
! 	      flag_indirect_dispatch) here, but libgcj can't cope with
! 	      a symbolic reference a superclass in the class data.  */
! 	   assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
  	   && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (super)))))
      super = build_class_ref (super);
*************** make_class_data (tree type)
*** 1464,1474 ****
  	  tree iclass = BINFO_TYPE (child);
  	  tree index;
! 	  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;
  	    }
  	  init = tree_cons (NULL_TREE, index, init); 
--- 1550,1562 ----
  	  tree iclass = BINFO_TYPE (child);
  	  tree index;
! 	  if (! flag_indirect_dispatch
! 	      && (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;
  	    }
  	  init = tree_cons (NULL_TREE, index, init); 
*************** make_class_data (tree type)
*** 1484,1487 ****
--- 1572,1592 ----
    constant_pool_constructor = build_constants_constructor ();
  
+   if (flag_indirect_dispatch)
+     {
+       TYPE_OTABLE_DECL (type) 
+ 	= emit_symbol_table 
+ 	(DECL_NAME (TYPE_OTABLE_DECL (type)), 
+ 	 TYPE_OTABLE_DECL (type), TYPE_OTABLE_METHODS (type), 
+ 	 TYPE_OTABLE_SYMS_DECL (type), integer_type_node);
+        
+       TYPE_ATABLE_DECL (type) 
+ 	= emit_symbol_table 
+ 	(DECL_NAME (TYPE_ATABLE_DECL (type)), 
+ 	 TYPE_ATABLE_DECL (type), TYPE_ATABLE_METHODS (type), 
+ 	 TYPE_ATABLE_SYMS_DECL (type), ptr_type_node);
+     }
+   
+   TYPE_CTABLE_DECL (type) = emit_catch_table (type);
+ 
    START_RECORD_CONSTRUCTOR (temp, object_type_node);
    PUSH_FIELD_VALUE (temp, "vtable",
*************** make_class_data (tree type)
*** 1527,1531 ****
  			       build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl),
  			       dtable_start_offset));
!   if (otable_methods == NULL_TREE)
      {
        PUSH_FIELD_VALUE (cons, "otable", null_pointer_node);
--- 1632,1636 ----
  			       build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl),
  			       dtable_start_offset));
!   if (TYPE_OTABLE_METHODS (type) == NULL_TREE)
      {
        PUSH_FIELD_VALUE (cons, "otable", null_pointer_node);
*************** make_class_data (tree type)
*** 1535,1545 ****
      {
        PUSH_FIELD_VALUE (cons, "otable",
! 			build1 (ADDR_EXPR, otable_ptr_type, otable_decl));
        PUSH_FIELD_VALUE (cons, "otable_syms",
  			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);
--- 1640,1650 ----
      {
        PUSH_FIELD_VALUE (cons, "otable",
! 			build1 (ADDR_EXPR, otable_ptr_type, TYPE_OTABLE_DECL (type)));
        PUSH_FIELD_VALUE (cons, "otable_syms",
  			build1 (ADDR_EXPR, symbols_array_ptr_type,
! 				TYPE_OTABLE_SYMS_DECL (type)));
!       TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1;
!     } 
!   if (TYPE_ATABLE_METHODS(type) == NULL_TREE)
      {
        PUSH_FIELD_VALUE (cons, "atable", null_pointer_node);
*************** make_class_data (tree type)
*** 1549,1561 ****
      {
        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, "catch_classes",
! 		    build1 (ADDR_EXPR, ptr_type_node, ctable_decl)); 
    PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
    PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
--- 1654,1666 ----
      {
        PUSH_FIELD_VALUE (cons, "atable",
! 			build1 (ADDR_EXPR, atable_ptr_type, TYPE_ATABLE_DECL (type)));
        PUSH_FIELD_VALUE (cons, "atable_syms",
  			build1 (ADDR_EXPR, symbols_array_ptr_type,
! 				TYPE_ATABLE_SYMS_DECL (type)));
!       TREE_CONSTANT (TYPE_ATABLE_DECL (type)) = 1;
      }
   
    PUSH_FIELD_VALUE (cons, "catch_classes",
! 		    build1 (ADDR_EXPR, ptr_type_node, TYPE_CTABLE_DECL (type))); 
    PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
    PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
*************** finish_class (void)
*** 1617,1620 ****
--- 1722,1727 ----
      }
  
+   java_expand_catch_classes (current_class);
+ 
    current_function_decl = NULL_TREE;
    make_class_data (current_class);
*************** make_catch_class_record (tree catch_clas
*** 2232,2236 ****
  {
    tree entry;
!   tree type = TREE_TYPE (TREE_TYPE (ctable_decl));
    START_RECORD_CONSTRUCTOR (entry, type);
    PUSH_FIELD_VALUE (entry, "address", catch_class);
--- 2339,2343 ----
  {
    tree entry;
!   tree type = TREE_TYPE (TREE_TYPE (TYPE_CTABLE_DECL (output_class)));
    START_RECORD_CONSTRUCTOR (entry, type);
    PUSH_FIELD_VALUE (entry, "address", catch_class);
*************** make_catch_class_record (tree catch_clas
*** 2242,2268 ****
  
  /* Generate the list of Throwable classes that are caught by exception
!    handlers in this compilation.  */
! void 
! emit_catch_table (void)
  {
    tree table, table_size, array_type;
!   catch_classes 
!     = tree_cons (NULL, 
! 		 make_catch_class_record (null_pointer_node, null_pointer_node),
! 		 catch_classes);
!   catch_classes = nreverse (catch_classes);
!   catch_classes 
!     = tree_cons (NULL, 
! 		 make_catch_class_record (null_pointer_node, null_pointer_node),
! 		 catch_classes);
!   table_size = build_index_type (build_int_2 (list_length (catch_classes), 0));
    array_type 
!     = build_array_type (TREE_TYPE (TREE_TYPE (ctable_decl)), table_size);
!   table = build_decl (VAR_DECL, DECL_NAME (ctable_decl), array_type);
!   DECL_INITIAL (table) = build_constructor (array_type, catch_classes);
    TREE_STATIC (table) = 1;
    TREE_READONLY (table) = 1;  
    rest_of_decl_compilation (table, NULL, 1, 0);
!   ctable_decl = table;
  }
   
--- 2349,2381 ----
  
  /* Generate the list of Throwable classes that are caught by exception
!    handlers in this class.  */
! tree 
! emit_catch_table (tree this_class)
  {
    tree table, table_size, array_type;
!   TYPE_CATCH_CLASSES (this_class) =
!     tree_cons (NULL,
! 	       make_catch_class_record (null_pointer_node, null_pointer_node),
! 	       TYPE_CATCH_CLASSES (this_class));
!   TYPE_CATCH_CLASSES (this_class) = nreverse (TYPE_CATCH_CLASSES (this_class));
!   TYPE_CATCH_CLASSES (this_class) = 
!     tree_cons (NULL,
! 	       make_catch_class_record (null_pointer_node, null_pointer_node),
! 	       TYPE_CATCH_CLASSES (this_class));
!   table_size = 
!     build_index_type (build_int_2 
! 		      (list_length (TYPE_CATCH_CLASSES (this_class)), 0));
    array_type 
!     = build_array_type (TREE_TYPE (TREE_TYPE (TYPE_CTABLE_DECL (this_class))),
! 			table_size);
!   table = 
!     build_decl (VAR_DECL, DECL_NAME (TYPE_CTABLE_DECL (this_class)), array_type);
!   DECL_INITIAL (table) = 
!     build_constructor (array_type, TYPE_CATCH_CLASSES (this_class));
    TREE_STATIC (table) = 1;
    TREE_READONLY (table) = 1;  
+   DECL_IGNORED_P (table) = 1;
    rest_of_decl_compilation (table, NULL, 1, 0);
!   return table;
  }
   
Index: java/constants.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/constants.c,v
retrieving revision 1.32
diff -p -2 -c -r1.32 constants.c
*** java/constants.c	25 Nov 2003 17:32:54 -0000	1.32
--- java/constants.c	6 Jan 2004 11:11:05 -0000
*************** int
*** 352,356 ****
  alloc_name_constant (int tag, tree name)
  {
!   CPool *outgoing_cpool = cpool_for_class (current_class);
    return find_tree_constant (outgoing_cpool, tag, name);
  }
--- 352,356 ----
  alloc_name_constant (int tag, tree name)
  {
!   CPool *outgoing_cpool = cpool_for_class (output_class);
    return find_tree_constant (outgoing_cpool, tag, name);
  }
*************** build_constant_data_ref (void)
*** 394,404 ****
    tree cpool_data_ref = NULL_TREE;
  
!   if (TYPE_CPOOL_DATA_REF (current_class))
!     cpool_data_ref = TYPE_CPOOL_DATA_REF (current_class);
  
    if (cpool_data_ref == NULL_TREE)
      {
        tree decl;
!       tree decl_name = mangled_classname ("_CD_", current_class);
        decl = build_decl (VAR_DECL, decl_name,
  			 build_array_type (ptr_type_node,
--- 394,404 ----
    tree cpool_data_ref = NULL_TREE;
  
!   if (TYPE_CPOOL_DATA_REF (output_class))
!     cpool_data_ref = TYPE_CPOOL_DATA_REF (output_class);
  
    if (cpool_data_ref == NULL_TREE)
      {
        tree decl;
!       tree decl_name = mangled_classname ("_CD_", output_class);
        decl = build_decl (VAR_DECL, decl_name,
  			 build_array_type (ptr_type_node,
*************** build_constant_data_ref (void)
*** 406,410 ****
        TREE_STATIC (decl) = 1;
        make_decl_rtl (decl, NULL);
!       TYPE_CPOOL_DATA_REF (current_class) = cpool_data_ref
  	= build1 (ADDR_EXPR, ptr_type_node, decl);
      }
--- 406,410 ----
        TREE_STATIC (decl) = 1;
        make_decl_rtl (decl, NULL);
!       TYPE_CPOOL_DATA_REF (output_class) = cpool_data_ref
  	= build1 (ADDR_EXPR, ptr_type_node, decl);
      }
Index: java/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.174
diff -p -2 -c -r1.174 decl.c
*** java/decl.c	20 Dec 2003 15:38:27 -0000	1.174
--- java/decl.c	6 Jan 2004 11:11:05 -0000
*************** tree java_lang_cloneable_identifier_node
*** 65,72 ****
  tree java_io_serializable_identifier_node;
  
- /* Set to nonzero value in order to emit class initialization code
-    before static field references.  */
- extern int always_initialize_class_p;
- 
  /* The DECL_MAP is a mapping from (index, type) to a decl node.
     If index < max_locals, it is the index of a local variable.
--- 65,68 ----
*************** create_primitive_vtable (const char *nam
*** 390,393 ****
--- 386,396 ----
  }
  
+ static tree
+ do_nothing (tree t)
+ {
+   return t;
+ }
+ 
+ 
  void
  java_init_decl_processing (void)
*************** java_init_decl_processing (void)
*** 539,542 ****
--- 542,567 ----
    double_array_vtable = create_primitive_vtable ("double");
  
+   one_elt_array_domain_type = build_index_type (integer_one_node);
+   utf8const_type = make_node (RECORD_TYPE);
+   PUSH_FIELD (utf8const_type, field, "hash", unsigned_short_type_node);
+   PUSH_FIELD (utf8const_type, field, "length", unsigned_short_type_node);
+   FINISH_RECORD (utf8const_type);
+   utf8const_ptr_type = build_pointer_type (utf8const_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);
+ 
+   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);
+ 
+   symbols_array_type = build_array_type (symbol_type, 
+ 					 one_elt_array_domain_type);
+   symbols_array_ptr_type = build_pointer_type (symbols_array_type);
+ 
    /* As you're adding items here, please update the code right after
       this section, so that the filename containing the source code of
*************** java_init_decl_processing (void)
*** 596,605 ****
    init_expr_processing();
  
-   utf8const_type = make_node (RECORD_TYPE);
-   PUSH_FIELD (utf8const_type, field, "hash", unsigned_short_type_node);
-   PUSH_FIELD (utf8const_type, field, "length", unsigned_short_type_node);
-   FINISH_RECORD (utf8const_type);
-   utf8const_ptr_type = build_pointer_type (utf8const_type);
- 
    constants_type_node = make_node (RECORD_TYPE);
    PUSH_FIELD (constants_type_node, field, "size", unsigned_int_type_node);
--- 621,624 ----
*************** java_init_decl_processing (void)
*** 614,680 ****
    dtable_ptr_type = build_pointer_type (dtable_type);
  
-   one_elt_array_domain_type = build_index_type (integer_one_node);
    otable_type = build_array_type (integer_type_node, 
  				  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);
- 
-   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);
- 
-   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);
-       DECL_EXTERNAL (otable_decl) = 1;
-       TREE_STATIC (otable_decl) = 1;
-       TREE_READONLY (otable_decl) = 1;
-       TREE_CONSTANT (otable_decl) = 1;
-       pushdecl (otable_decl);  
-       otable_syms_decl = build_decl (VAR_DECL, get_identifier ("otable_syms"), 
- 				     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);
-     }
-   
-   {  
-     tree catch_class_type = make_node (RECORD_TYPE);
-     PUSH_FIELD (catch_class_type, field, "address", utf8const_ptr_type);
-     PUSH_FIELD (catch_class_type, field, "classname", ptr_type_node);
-     FINISH_RECORD (catch_class_type);
-     
-     ctable_decl 
-       = build_decl (VAR_DECL, get_identifier ("catch_classes"), 
- 		    build_array_type 
- 		    (catch_class_type, 0));
-     DECL_EXTERNAL (ctable_decl) = 1;
-     TREE_STATIC (ctable_decl) = 1;
-     TREE_READONLY (ctable_decl) = 1;
-     TREE_CONSTANT (ctable_decl) = 1;
-     pushdecl (ctable_decl);  
-   }
  
    PUSH_FIELD (object_type_node, field, "vtable", dtable_ptr_type);
--- 633,640 ----
*************** java_init_decl_processing (void)
*** 946,955 ****
                                               ? "__gcj_personality_sj0"
                                               : "__gcj_personality_v0");
!   lang_eh_runtime_type = prepare_eh_table_type;
  
    init_jcf_parse ();
      
    initialize_builtins ();
- 
    soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
  #if 0
--- 906,915 ----
                                               ? "__gcj_personality_sj0"
                                               : "__gcj_personality_v0");
! 
!   lang_eh_runtime_type = do_nothing;
  
    init_jcf_parse ();
      
    initialize_builtins ();
    soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
  #if 0
*************** java_expand_body (tree fndecl)
*** 1861,1864 ****
--- 1821,1825 ----
    current_function_decl = fndecl;
    input_location = DECL_SOURCE_LOCATION (fndecl);
+   output_class = DECL_CONTEXT (current_function_decl);
    current_class = DECL_CONTEXT (fndecl);
  
Index: java/except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/except.c,v
retrieving revision 1.41
diff -p -2 -c -r1.41 except.c
*** java/except.c	20 Nov 2003 03:34:59 -0000	1.41
--- java/except.c	6 Jan 2004 11:11:05 -0000
*************** prepare_eh_table_type (tree type)
*** 313,316 ****
--- 313,317 ----
  {
    tree exp;
+   tree *slot;
    const char *name;
    char *buf;
*************** prepare_eh_table_type (tree type)
*** 325,330 ****
  
    if (type == NULL_TREE)
!     exp = NULL_TREE;
!   else if (is_compiled_class (type) && !flag_indirect_dispatch)
      {
        name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
--- 326,339 ----
  
    if (type == NULL_TREE)
!     return NULL_TREE;
! 
!   if (TYPE_TO_RUNTIME_MAP (output_class) == NULL)
!     TYPE_TO_RUNTIME_MAP (output_class) = java_treetreehash_create (10, 1);
!   
!   slot = java_treetreehash_new (TYPE_TO_RUNTIME_MAP (output_class), type);
!   if (*slot != NULL)
!     return TREE_VALUE (*slot);
! 
!   if (is_compiled_class (type) && !flag_indirect_dispatch)
      {
        name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
*************** prepare_eh_table_type (tree type)
*** 340,345 ****
        layout_decl (decl, 0);
        pushdecl (decl);
-       rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0);
-       make_decl_rtl (decl, (char*) 0);
        exp = build1 (ADDR_EXPR, ptr_type_node, decl);
      }
--- 349,352 ----
*************** prepare_eh_table_type (tree type)
*** 358,369 ****
        layout_decl (decl, 0);
        pushdecl (decl);
-       rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0);
-       make_decl_rtl (decl, (char*) 0);
        exp = build1 (ADDR_EXPR, build_pointer_type (utf8const_ptr_type), decl);
!       catch_classes = tree_cons (NULL, make_catch_class_record (exp, utf8_ref), catch_classes);
      }
    return exp;
  }
  
  
  /* Build a reference to the jthrowable object being carried in the
--- 365,399 ----
        layout_decl (decl, 0);
        pushdecl (decl);
        exp = build1 (ADDR_EXPR, build_pointer_type (utf8const_ptr_type), decl);
!       TYPE_CATCH_CLASSES (output_class) = 
! 	tree_cons (NULL, make_catch_class_record (exp, utf8_ref), 
! 		   TYPE_CATCH_CLASSES (output_class));
      }
+ 
+   *slot = tree_cons (type, exp, NULL_TREE);
+ 
    return exp;
  }
  
+ static int
+ expand_catch_class (void **entry, void *x ATTRIBUTE_UNUSED)
+ {
+   struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry;
+   tree decl = TREE_OPERAND (TREE_VALUE ((tree)ite->value), 0);
+   rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0);
+   return true;
+ }
+   
+ /* For every class in the TYPE_TO_RUNTIME_MAP, expand the
+    corresponding object that is used by the runtime type matcher.  */
+ 
+ void
+ java_expand_catch_classes (tree this_class)
+ {
+   if (TYPE_TO_RUNTIME_MAP (this_class))
+     htab_traverse 
+       (TYPE_TO_RUNTIME_MAP (this_class),
+        expand_catch_class, NULL);
+ }
  
  /* Build a reference to the jthrowable object being carried in the
*************** expand_end_java_handler (struct eh_range
*** 405,409 ****
  	type = throwable_type_node;
  
!       expand_start_catch (type);
        expand_goto (TREE_VALUE (handler));
        expand_end_catch ();
--- 435,439 ----
  	type = throwable_type_node;
  
!       expand_start_catch (prepare_eh_table_type (type));
        expand_goto (TREE_VALUE (handler));
        expand_end_catch ();
Index: java/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/expr.c,v
retrieving revision 1.179
diff -p -2 -c -r1.179 expr.c
*** java/expr.c	20 Dec 2003 15:38:27 -0000	1.179
--- java/expr.c	6 Jan 2004 11:11:06 -0000
*************** build_field_ref (tree self_value, tree s
*** 1512,1526 ****
  	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, 
--- 1512,1527 ----
  	self_value = fold (build1 (NOP_EXPR, base_type, self_value));
        if (flag_indirect_dispatch
! 	  && output_class != self_class)
! 	/* FIXME: output_class != self_class is not exactly the right
  	   test.  What we really want to know is whether self_class is
! 	   in the same translation unit as output_class.  If it is,
  	   we can make a direct reference.  */
  	{
! 	  tree otable_index =
! 	    build_int_2 (get_symbol_table_index 
! 			 (field_decl, &TYPE_OTABLE_METHODS (output_class)), 0);
! 	  tree field_offset = 
! 	    build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class), 
! 		   otable_index);
  	  tree address 
  	    = fold (build (PLUS_EXPR, 
*************** build_known_method_ref (tree method, tre
*** 1772,1779 ****
        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);
  	}
      }
--- 1773,1782 ----
        else
  	{
! 	  tree table_index = 
! 	    build_int_2 (get_symbol_table_index 
! 			 (method, &TYPE_ATABLE_METHODS (output_class)), 0);
! 	  func = 
! 	    build (ARRAY_REF,  method_ptr_type_node, 
! 		   TYPE_ATABLE_DECL (output_class), table_index);
  	}
      }
*************** build_invokevirtual (tree dtable, tree m
*** 1894,1899 ****
      {
        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);
      }
--- 1897,1904 ----
      {
        otable_index 
! 	= build_int_2 (get_symbol_table_index 
! 		       (method, &TYPE_OTABLE_METHODS (output_class)), 0);
!       method_index = build (ARRAY_REF, integer_type_node, 
! 			    TYPE_OTABLE_DECL (output_class), 
  			    otable_index);
      }
*************** build_invokeinterface (tree dtable, tree
*** 1958,1964 ****
    if (flag_indirect_dispatch)
      {
!       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
--- 1963,1972 ----
    if (flag_indirect_dispatch)
      {
!       otable_index =
! 	build_int_2 (get_symbol_table_index 
! 		     (method, &TYPE_OTABLE_METHODS (output_class)), 0);
!       idx = 
! 	build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class),
! 	       otable_index);
      }
    else
*************** java_expand_expr (tree exp, rtx target, 
*** 2606,2610 ****
  	  tree type = (decl ? TREE_TYPE (TREE_TYPE (decl)) : NULL_TREE);
  
! 	  expand_start_catch (type);
  	  expand_expr_stmt (TREE_OPERAND (current, 0));
  	  expand_end_catch ();
--- 2614,2618 ----
  	  tree type = (decl ? TREE_TYPE (TREE_TYPE (decl)) : NULL_TREE);
  
! 	  expand_start_catch (prepare_eh_table_type (type));
  	  expand_expr_stmt (TREE_OPERAND (current, 0));
  	  expand_end_catch ();
Index: java/java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.191
diff -p -2 -c -r1.191 java-tree.h
*** java/java-tree.h	3 Dec 2003 07:04:18 -0000	1.191
--- java/java-tree.h	6 Jan 2004 11:11:07 -0000
*************** extern int compiling_from_source;
*** 135,142 ****
    java_global_trees[JTI_MAIN_CLASS]
  
! /* The class we are currently processing. */
  #define current_class \
    java_global_trees[JTI_CURRENT_CLASS]
  
  /* List of all class DECLs seen so far.  */
  #define all_class_list \
--- 135,149 ----
    java_global_trees[JTI_MAIN_CLASS]
  
! /* The class we use as the base for name resolution.  It's usually the
!    class we're generating code for but sometimes it points to an inner
!    class.  If you really want to know the class we're currently
!    generating code for, use output_class instead.  */
  #define current_class \
    java_global_trees[JTI_CURRENT_CLASS]
  
+ /* The class we are currently generating.  Really.  */
+ #define output_class \
+   java_global_trees[JTI_OUTPUT_CLASS]
+ 
  /* List of all class DECLs seen so far.  */
  #define all_class_list \
*************** extern int compiling_from_source;
*** 148,172 ****
  /* 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 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 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]
- 
- #define ctable_decl java_global_trees [JTI_CTABLE_DECL]
- #define catch_classes java_global_trees [JTI_CATCH_CLASSES]
  
  extern int flag_emit_class_files;
--- 155,165 ----
*************** extern const char *current_encoding;
*** 245,248 ****
--- 238,245 ----
  extern GTY(()) struct JCF * current_jcf;
  
+ /* Set to nonzero value in order to emit class initialization code
+    before static field references.  */
+ extern int always_initialize_class_p;
+ 
  typedef struct CPool constant_pool;
  
*************** enum java_tree_index
*** 414,431 ****
    JTI_MAIN_CLASS,
    JTI_CURRENT_CLASS,
    JTI_ALL_CLASS_LIST,
    JTI_ALL_CLASS_FILENAME,
  
-   JTI_OTABLE_METHODS,
-   JTI_OTABLE_DECL,
-   JTI_OTABLE_SYMS_DECL,
- 
-   JTI_ATABLE_METHODS,
-   JTI_ATABLE_DECL,
-   JTI_ATABLE_SYMS_DECL,
- 
-   JTI_CTABLE_DECL,
-   JTI_CATCH_CLASSES,
- 
    JTI_PREDEF_FILENAMES,
  
--- 411,418 ----
    JTI_MAIN_CLASS,
    JTI_CURRENT_CLASS,
+   JTI_OUTPUT_CLASS,
    JTI_ALL_CLASS_LIST,
    JTI_ALL_CLASS_FILENAME,
  
    JTI_PREDEF_FILENAMES,
  
*************** union lang_tree_node 
*** 924,927 ****
--- 911,917 ----
  #define DECL_FIELD_FINAL_WFL(NODE) \
    (DECL_LANG_SPECIFIC(NODE)->u.v.wfl)
+ /* The class that's the owner of a dynamic binding table.  */
+ #define DECL_OWNER(NODE) \
+   (DECL_LANG_SPECIFIC(NODE)->u.v.owner)
  /* True if NODE is a local variable final. */
  #define LOCAL_FINAL_P(NODE) (DECL_LANG_SPECIFIC (NODE) && DECL_FINAL (NODE))
*************** struct lang_decl_var GTY(())
*** 1023,1026 ****
--- 1013,1017 ----
    tree am;			/* Access method for this field (1.1) */
    tree wfl;			/* Original wfl */
+   tree owner;
    unsigned int final_iud : 1;	/* Final initialized upon declaration */
    unsigned int cif : 1;		/* True: decl is a class initialization flag */
*************** struct lang_decl GTY(())
*** 1071,1074 ****
--- 1062,1078 ----
  #define TYPE_USES_ASSERTIONS(T) (TYPE_LANG_SPECIFIC(T)->assertions)
  
+ #define TYPE_ATABLE_METHODS(T)   (TYPE_LANG_SPECIFIC(T)->atable_methods)
+ #define TYPE_ATABLE_SYMS_DECL(T) (TYPE_LANG_SPECIFIC(T)->atable_syms_decl)
+ #define TYPE_ATABLE_DECL(T)      (TYPE_LANG_SPECIFIC(T)->atable_decl)
+ 
+ #define TYPE_OTABLE_METHODS(T)   (TYPE_LANG_SPECIFIC(T)->otable_methods)
+ #define TYPE_OTABLE_SYMS_DECL(T) (TYPE_LANG_SPECIFIC(T)->otable_syms_decl)
+ #define TYPE_OTABLE_DECL(T)      (TYPE_LANG_SPECIFIC(T)->otable_decl)
+ 
+ #define TYPE_CTABLE_DECL(T)      (TYPE_LANG_SPECIFIC(T)->ctable_decl)
+ #define TYPE_CATCH_CLASSES(T)    (TYPE_LANG_SPECIFIC(T)->catch_classes)
+ 
+ #define TYPE_TO_RUNTIME_MAP(T)   (TYPE_LANG_SPECIFIC(T)->type_to_runtime_map)
+ 
  struct lang_type GTY(())
  {
*************** struct lang_type GTY(())
*** 1087,1090 ****
--- 1091,1109 ----
    tree import_list;		/* Imported types, in the CU of this class */
    tree import_demand_list;	/* Imported types, in the CU of this class */
+ 
+   tree otable_methods;          /* List of static decls referred to by this class.  */
+   tree otable_decl;		/* The static address table.  */
+   tree otable_syms_decl;
+ 
+   tree atable_methods;          /* List of static decls referred to by this class.  */
+   tree atable_decl;		/* The static address table.  */
+   tree atable_syms_decl;
+ 
+   tree ctable_decl;             /* The table of classes for the runtime type matcher.  */
+   tree catch_classes;
+ 
+   htab_t GTY ((param_is (struct treetreehash_entry))) type_to_runtime_map;   
+                                 /* The mapping of classes to exception region markers.  */
+ 
    unsigned pic:1;		/* Private Inner Class. */
    unsigned poic:1;		/* Protected Inner Class. */
*************** extern tree create_label_decl (tree);
*** 1201,1204 ****
--- 1220,1224 ----
  extern void push_labeled_block (tree);
  extern tree prepare_eh_table_type (tree);
+ extern void java_expand_catch_classes (tree);
  extern tree build_exception_object_ref (tree);
  extern tree generate_name (void);
*************** extern int get_symbol_table_index (tree,
*** 1323,1327 ****
  
  extern tree make_catch_class_record (tree, tree);
! extern void emit_catch_table (void);
  
  #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
--- 1343,1349 ----
  
  extern tree make_catch_class_record (tree, tree);
! extern tree emit_catch_table (tree);
! 
! extern void gen_indirect_dispatch_tables (tree type);
  
  #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
Index: java/jcf-parse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-parse.c,v
retrieving revision 1.155
diff -p -2 -c -r1.155 jcf-parse.c
*** java/jcf-parse.c	20 Dec 2003 15:38:27 -0000	1.155
--- java/jcf-parse.c	6 Jan 2004 11:11:07 -0000
*************** The Free Software Foundation is independ
*** 73,80 ****
  extern struct obstack temporary_obstack;
  
- /* Set to nonzero value in order to emit class initialization code
-    before static field references.  */
- extern int always_initialize_class_p;
- 
  static GTY(()) tree parse_roots[3];
  
--- 73,76 ----
*************** set_source_filename (JCF *jcf, int index
*** 154,158 ****
  #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
  { tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \
!   current_class = give_name_to_class (jcf, THIS); \
    set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);}
  
--- 150,154 ----
  #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
  { tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \
!   output_class = current_class = give_name_to_class (jcf, THIS); \
    set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);}
  
*************** read_class (tree name)
*** 510,514 ****
        EXPR_WFL_FILENAME_NODE (wfl_operator) = file;
        input_filename = ggc_strdup (filename);
!       current_class = NULL_TREE;
        current_function_decl = NULL_TREE;
        if (!HAS_BEEN_ALREADY_PARSED_P (file))
--- 506,510 ----
        EXPR_WFL_FILENAME_NODE (wfl_operator) = file;
        input_filename = ggc_strdup (filename);
!       output_class = current_class = NULL_TREE;
        current_function_decl = NULL_TREE;
        if (!HAS_BEEN_ALREADY_PARSED_P (file))
*************** read_class (tree name)
*** 532,536 ****
  	  java_parser_context_save_global ();
  	  java_push_parser_context ();
! 	  current_class = class;
  	  input_filename = current_jcf->filename;
  	  if (JCF_SEEN_IN_ZIP (current_jcf))
--- 528,532 ----
  	  java_parser_context_save_global ();
  	  java_push_parser_context ();
! 	  output_class = current_class = class;
  	  input_filename = current_jcf->filename;
  	  if (JCF_SEEN_IN_ZIP (current_jcf))
*************** read_class (tree name)
*** 550,554 ****
      }
  
!   current_class = save_current_class;
    input_location = save_location;
    current_jcf = save_current_jcf;
--- 546,550 ----
      }
  
!   output_class = current_class = save_current_class;
    input_location = save_location;
    current_jcf = save_current_jcf;
*************** parse_class_file (void)
*** 710,713 ****
--- 706,711 ----
    always_initialize_class_p = 1;
  
+   gen_indirect_dispatch_tables (current_class);
+ 
    java_mark_class_local (current_class);
  
*************** java_parse_file (int set_yydebug ATTRIBU
*** 1100,1104 ****
        if (CLASS_FILE_P (node))
  	{
! 	  current_class = TREE_PURPOSE (node);
  	  current_jcf = TYPE_JCF (current_class);
  	  layout_class (current_class);
--- 1098,1102 ----
        if (CLASS_FILE_P (node))
  	{
! 	  output_class = current_class = TREE_PURPOSE (node);
  	  current_jcf = TYPE_JCF (current_class);
  	  layout_class (current_class);
*************** java_parse_file (int set_yydebug ATTRIBU
*** 1120,1135 ****
        /* Emit the .jcf section.  */
        emit_register_classes ();
-       if (flag_indirect_dispatch)
- 	{
- 	  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);
- 	}
-       emit_catch_table ();
      }
  
--- 1118,1121 ----
*************** parse_zip_file_entries (void)
*** 1202,1206 ****
  	    FREE (class_name);
  	    current_jcf = TYPE_JCF (class);
! 	    current_class = class;
  
  	    if (! CLASS_LOADED_P (class))
--- 1188,1192 ----
  	    FREE (class_name);
  	    current_jcf = TYPE_JCF (class);
! 	    output_class = current_class = class;
  
  	    if (! CLASS_LOADED_P (class))
Index: java/lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lang.c,v
retrieving revision 1.147
diff -p -2 -c -r1.147 lang.c
*** java/lang.c	13 Nov 2003 01:25:24 -0000	1.147
--- java/lang.c	6 Jan 2004 11:11:07 -0000
*************** java_init (void)
*** 465,468 ****
--- 465,473 ----
      flag_inline_trees = 1;
  
+   /* FIXME: Indirect dispatch isn't yet compatible with static class
+      init optimization.  */
+   if (flag_indirect_dispatch)
+     always_initialize_class_p = true;
+ 
    /* Force minimum function alignment if g++ uses the least significant
       bit of function pointers to store the virtual bit. This is required
*************** inline_init_test_initialization (void **
*** 968,976 ****
    if (! h)
      return true;
- 
    splay_tree_insert (decl_map,
  		     (splay_tree_key) ite->value,
  		     (splay_tree_value) h);
- 
    return true;
  }
--- 973,979 ----
*************** static bool
*** 1103,1107 ****
  java_decl_ok_for_sibcall (tree decl)
  {
!   return decl != NULL && DECL_CONTEXT (decl) == current_class;
  }
  
--- 1106,1110 ----
  java_decl_ok_for_sibcall (tree decl)
  {
!   return decl != NULL && DECL_CONTEXT (decl) == output_class;
  }
  
*************** static tree
*** 1229,1233 ****
  java_get_callee_fndecl (tree call_expr)
  {
!   tree method, table, element;
  
    HOST_WIDE_INT index;
--- 1232,1236 ----
  java_get_callee_fndecl (tree call_expr)
  {
!   tree method, table, element, atable_methods;
  
    HOST_WIDE_INT index;
*************** java_get_callee_fndecl (tree call_expr)
*** 1240,1247 ****
      return NULL;
    table = TREE_OPERAND (method, 0);
!   if (table != atable_decl)
      return NULL;
-   index = TREE_INT_CST_LOW (TREE_OPERAND (method, 1));
  
    /* FIXME: Replace this for loop with a hash table lookup.  */
    for (element = atable_methods; element; element = TREE_CHAIN (element))
--- 1243,1254 ----
      return NULL;
    table = TREE_OPERAND (method, 0);
!   if (! DECL_LANG_SPECIFIC(table)
!       || !DECL_OWNER (table) 
!       || TYPE_ATABLE_DECL (DECL_OWNER (table)) != table)
      return NULL;
  
+   atable_methods = TYPE_ATABLE_METHODS (DECL_OWNER (table));
+   index = TREE_INT_CST_LOW (TREE_OPERAND (method, 1));
+   
    /* FIXME: Replace this for loop with a hash table lookup.  */
    for (element = atable_methods; element; element = TREE_CHAIN (element))
*************** java_get_callee_fndecl (tree call_expr)
*** 1258,1262 ****
        --index;
      }
!   
    return NULL;
  }
--- 1265,1269 ----
        --index;
      }
! 
    return NULL;
  }
Index: java/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.463
diff -p -2 -c -r1.463 parse.y
*** java/parse.y	25 Dec 2003 21:01:17 -0000	1.463
--- java/parse.y	6 Jan 2004 11:11:12 -0000
*************** java_fix_constructors (void)
*** 5452,5456 ****
  	continue;
  
!       current_class = class_type;
        for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
  	{
--- 5452,5456 ----
  	continue;
  
!       output_class = current_class = class_type;
        for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
  	{
*************** java_reorder_fields (void)
*** 7576,7580 ****
    for (current = gclass_list; current; current = TREE_CHAIN (current))
      {
!       current_class = TREE_TYPE (TREE_VALUE (current));
  
        if (current_class == stop_reordering)
--- 7576,7580 ----
    for (current = gclass_list; current; current = TREE_CHAIN (current))
      {
!       output_class = current_class = TREE_TYPE (TREE_VALUE (current));
  
        if (current_class == stop_reordering)
*************** java_layout_classes (void)
*** 7633,7637 ****
    for (current = gclass_list; current; current = TREE_CHAIN (current))
      {
!       current_class = TREE_TYPE (TREE_VALUE (current));
        layout_class (current_class);
  
--- 7633,7637 ----
    for (current = gclass_list; current; current = TREE_CHAIN (current))
      {
!       output_class = current_class = TREE_TYPE (TREE_VALUE (current));
        layout_class (current_class);
  
*************** java_complete_expand_methods (tree class
*** 7697,7701 ****
    tree clinit, decl, first_decl;
  
!   current_class = TREE_TYPE (class_decl);
  
    /* Pre-expand <clinit> to figure whether we really need it or
--- 7697,7701 ----
    tree clinit, decl, first_decl;
  
!   output_class = current_class = TREE_TYPE (class_decl);
  
    /* Pre-expand <clinit> to figure whether we really need it or
*************** java_expand_classes (void)
*** 9018,9021 ****
--- 9018,9030 ----
    for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
      {
+       tree current;
+       for (current = cur_ctxp->class_list; 
+ 	   current; 
+ 	   current = TREE_CHAIN (current))
+ 	gen_indirect_dispatch_tables (TREE_TYPE (current));
+     }
+   
+   for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
+     {
        ctxp = cur_ctxp;
        input_filename = ctxp->filename;
*************** java_expand_classes (void)
*** 9026,9030 ****
    input_filename = main_input_filename;
  
- 
    /* Find anonymous classes and expand their constructor. This extra pass is
       necessary because the constructor itself is only generated when the
--- 9035,9038 ----
*************** java_expand_classes (void)
*** 9036,9040 ****
        for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
  	{
! 	  current_class = TREE_TYPE (current);
  	  if (ANONYMOUS_CLASS_P (current_class))
  	    {
--- 9044,9048 ----
        for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
  	{
! 	  output_class = current_class = TREE_TYPE (current);
  	  if (ANONYMOUS_CLASS_P (current_class))
  	    {
*************** java_expand_classes (void)
*** 9064,9068 ****
  	{
  	  tree d;
! 	  current_class = TREE_TYPE (current);
  	  for (d = TYPE_METHODS (current_class); d; d = TREE_CHAIN (d))
  	    {
--- 9072,9076 ----
  	{
  	  tree d;
! 	  output_class = current_class = TREE_TYPE (current);
  	  for (d = TYPE_METHODS (current_class); d; d = TREE_CHAIN (d))
  	    {
*************** java_expand_classes (void)
*** 9095,9099 ****
  		{
  		  tree d;
! 		  current_class = TREE_TYPE (current);
  		  for (d = TYPE_METHODS (current_class); d; d = TREE_CHAIN (d))
  		    {
--- 9103,9107 ----
  		{
  		  tree d;
! 		  output_class = current_class = TREE_TYPE (current);
  		  for (d = TYPE_METHODS (current_class); d; d = TREE_CHAIN (d))
  		    {
*************** java_expand_classes (void)
*** 9160,9164 ****
  	   current = TREE_CHAIN (current))
  	{
! 	  current_class = TREE_TYPE (TREE_VALUE (current));
  	  if (flag_emit_class_files)
  	    write_classfile (current_class);
--- 9168,9172 ----
  	   current = TREE_CHAIN (current))
  	{
! 	  output_class = current_class = TREE_TYPE (TREE_VALUE (current));
  	  if (flag_emit_class_files)
  	    write_classfile (current_class);
*************** java_finish_classes (void)
*** 9181,9185 ****
        for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
  	{
! 	  current_class = TREE_TYPE (current);
  	  finish_class ();
  	}
--- 9189,9193 ----
        for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
  	{
! 	  output_class = current_class = TREE_TYPE (current);
  	  finish_class ();
  	}

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