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]

gcj patch: class initialization optimization



This patch is an implementation of the optimization described in this
note:

http://sourceware.cygnus.com/ml/java-discuss/1999-q3/msg00124.html


2000-02-13  Anthony Green  <green@cygnus.com>

	* class.c (init_test_hash_newfunc): New function.
	(decl_hash): New function.
	(decl_compare): New function.
	* decl.c (emit_init_test_initialization): New function.
	(complete_start_java_method): Traverse the init test hashtable,
	calling emit_init_test_initialization.
	(always_initialize_class_p): Define.
	* expr.c (build_class_init): Use initialization tests when
	emitting class initialization code.
	(always_initialize_class_p): Declare.
	* jcf-parse.c (parse_class_file): Set always_initialize_class_p to
	1.
	* java-tree.h: Include hash.h.
	(DECL_FUNCTION_INIT_TEST_TABLE): Define.
	(struct lang_decl): Add init_test_table field.
	(init_test_hash_entry): Define.

Index: gcc/java/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/class.c,v
retrieving revision 1.53
diff -u -r1.53 class.c
--- class.c	2000/01/21 20:57:00	1.53
+++ class.c	2000/02/14 08:16:50
@@ -389,7 +389,7 @@
       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;
@@ -548,6 +548,40 @@
   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;
+}
+
+static unsigned long
+decl_hash (k)
+     hash_table_key k;
+{
+  return (long) k;
+}
+
+static boolean
+decl_compare (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;
@@ -567,6 +601,11 @@
   DECL_LANG_SPECIFIC (fndecl)
     = (struct lang_decl *) permalloc (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, decl_hash,
+		   decl_compare);
 
   TREE_CHAIN (fndecl) = TYPE_METHODS (handle_class);
   TYPE_METHODS (handle_class) = fndecl;
Index: gcc/java/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/decl.c,v
retrieving revision 1.46
diff -u -r1.46 decl.c
--- decl.c	2000/02/09 20:38:02	1.46
+++ decl.c	2000/02/14 08:16:51
@@ -48,6 +48,10 @@
 static tree push_promoted_type PARAMS ((const char *, tree));
 static struct binding_level *make_binding_level PARAMS ((void));
 
+/* Set to non-zero value in order to emit class initilization code
+   before static field references.  */
+extern int always_initialize_class_p;
+
 #ifndef INT_TYPE_SIZE
 #define INT_TYPE_SIZE BITS_PER_WORD
 #endif
@@ -1623,6 +1627,24 @@
   return (DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, restype));
 }
 
+
+/* Called for every element in DECL_FUNCTION_INIT_TEST_TABLE in order
+   to emit initialization code for each test flag.  */
+   
+static boolean
+emit_init_test_initialization (entry, key)
+  struct hash_entry *entry;
+  hash_table_key key;
+{
+  struct init_test_hash_entry *ite = (struct init_test_hash_entry *) entry;
+  expand_decl (ite->init_test_decl);
+
+  expand_expr_stmt (build (MODIFY_EXPR, boolean_type_node, 
+			   ite->init_test_decl, boolean_false_node));
+
+  return true;
+}
+
 void
 complete_start_java_method (fndecl)
   tree fndecl;
@@ -1634,6 +1656,11 @@
 
       /* Set up parameters and prepare for return, for the function.  */
       expand_function_start (fndecl, 0);
+
+      /* Emit initialization code for test flags.  */
+      if (! always_initialize_class_p)
+	hash_traverse (&DECL_FUNCTION_INIT_TEST_TABLE (fndecl),
+		       emit_init_test_initialization, 0);
     }
 
   /* Allocate further tree nodes temporarily during compilation
Index: gcc/java/expr.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/expr.c,v
retrieving revision 1.58
diff -u -r1.58 expr.c
--- expr.c	2000/02/09 14:08:44	1.58
+++ expr.c	2000/02/14 08:16:52
@@ -83,6 +83,10 @@
 static tree operand_type[59];
 extern struct obstack permanent_obstack;
 
+/* Set to non-zero value in order to emit class initilization code
+   before static field references.  */
+int always_initialize_class_p;
+
 void
 init_expr_processing()
 {
@@ -1476,14 +1480,46 @@
 build_class_init (clas, expr)
      tree clas, expr;
 {
-  tree init;
+  tree init, call;
+  struct init_test_hash_entry *ite;
   if (inherits_from_p (current_class, clas))
     return expr;
-  init = build (CALL_EXPR, void_type_node,
-		build_address_of (soft_initclass_node),
-		build_tree_list (NULL_TREE, build_class_ref (clas)),
-		NULL_TREE);
-  TREE_SIDE_EFFECTS (init) = 1;
+
+  if (always_initialize_class_p)
+    {
+      init = build (CALL_EXPR, void_type_node,
+		    build_address_of (soft_initclass_node),
+		    build_tree_list (NULL_TREE, build_class_ref (clas)),
+		    NULL_TREE);
+      TREE_SIDE_EFFECTS (init) = 1;
+    }
+  else
+    {
+      ite = (struct init_test_hash_entry *)
+	hash_lookup (&DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl),
+		     (const hash_table_key) clas,
+		     TRUE, NULL);
+      
+      if (ite->init_test_decl == 0)
+	ite->init_test_decl = build_decl (VAR_DECL, NULL_TREE, 
+					  boolean_type_node);
+      
+      init = build (CALL_EXPR, void_type_node,
+		    build_address_of (soft_initclass_node),
+		    build_tree_list (NULL_TREE, build_class_ref (clas)),
+		    NULL_TREE);
+      TREE_SIDE_EFFECTS (init) = 1;
+      call = build (COMPOUND_EXPR, TREE_TYPE (expr), init, 
+		    build (MODIFY_EXPR, boolean_type_node,
+			   ite->init_test_decl, boolean_true_node));
+      TREE_SIDE_EFFECTS (call) = 1;
+      init = build (COND_EXPR, void_type_node,
+		    build (EQ_EXPR, boolean_type_node, 
+			   ite->init_test_decl, boolean_false_node),
+		    call, integer_zero_node);
+      TREE_SIDE_EFFECTS (init) = 1;
+    }
+
   if (expr != NULL_TREE)
     {
       expr = build (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
Index: gcc/java/java-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/java-tree.h,v
retrieving revision 1.52
diff -u -r1.52 java-tree.h
--- java-tree.h	2000/02/09 14:08:44	1.52
+++ java-tree.h	2000/02/14 08:16:53
@@ -25,6 +25,8 @@
 
 /* Hacked by Per Bothner <bothner@cygnus.com> February 1996. */
 
+#include "hash.h"
+
 /* Java language-specific tree codes.  */
 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM,
 enum java_tree_code {
@@ -368,6 +370,12 @@
 /* How specific the function is (for method selection - Java source
    code front-end */
 #define DECL_SPECIFIC_COUNT(DECL) DECL_ARG_SLOT_COUNT(DECL)
+/* For each function decl, init_test_table contains a hash table whose
+   entries are keyed on class names, and whose values are local
+   boolean decls.  The variables are intended to be TRUE when the
+   class has been initialized in this function, and FALSE otherwise.  */
+#define DECL_FUNCTION_INIT_TEST_TABLE(DECL) \
+  (DECL_LANG_SPECIFIC(DECL)->init_test_table)
 
 /* In a LABEL_DECL, a TREE_VEC that saves the type_map at that point. */
 #define LABEL_TYPE_STATE(NODE) (DECL_INITIAL (NODE))
@@ -443,7 +451,17 @@
   tree function_decl_body;	/* Hold all function's statements */
   tree called_constructor;	/* When decl is a constructor, the
 				   list of other constructor it calls. */
+  struct hash_table init_test_table;
+                                /* Class initialization test variables.  */
 };
+
+/* init_test_table hash table entry structure.  */
+struct init_test_hash_entry
+{
+  struct hash_entry root;
+  tree init_test_decl;
+};
+
 
 /* DECL_LANG_SPECIFIC for VAR_DECL and PARM_DECL. */
 struct lang_decl_var
Index: gcc/java/jcf-parse.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/jcf-parse.c,v
retrieving revision 1.41
diff -u -r1.41 jcf-parse.c
--- jcf-parse.c	2000/01/21 20:57:00	1.41
+++ jcf-parse.c	2000/02/14 08:16:54
@@ -57,6 +57,10 @@
 extern struct obstack temporary_obstack;
 extern struct obstack permanent_obstack;
 
+/* Set to non-zero value in order to emit class initilization code
+   before static field references.  */
+extern int always_initialize_class_p;
+
 /* The class we are currently processing. */
 tree current_class = NULL_TREE;
 
@@ -656,6 +660,10 @@
   lineno = 0;
   debug_start_source_file (input_filename);
   init_outgoing_cpool ();
+
+  /* Currently we always have to emit calls to _Jv_InitClass when
+     compiling from class files.  */
+  always_initialize_class_p = 1;
 
   for ( method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (current_class));
 	method != NULL_TREE; method = TREE_CHAIN (method))

-- 
Anthony Green                                                        Red Hat
                                                       Sunnyvale, California

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