tree-inline.c (remap_block): All local class initialization flags go in the outermost...
authorAndrew Haley <aph@redhat.com>
Mon, 14 Oct 2002 18:12:12 +0000 (18:12 +0000)
committerAndrew Haley <aph@gcc.gnu.org>
Mon, 14 Oct 2002 18:12:12 +0000 (18:12 +0000)
2002-10-14  Andrew Haley  <aph@redhat.com>

        * tree-inline.c (remap_block): All local class initialization
        flags go in the outermost scope.
        (expand_call_inline): Call java_inlining_map_static_initializers.
        (expand_call_inline): Call java_inlining_merge_static_initializers.
        * java/lang.c (merge_init_test_initialization): New.
        (java_inlining_merge_static_initializers): New.
        (inline_init_test_initialization): New.
        (java_inlining_map_static_initializers): New.

        * tree-inline.c (expand_call_inline): Convert retvar to expected
        type.

From-SVN: r58129

gcc/ChangeLog
gcc/java/ChangeLog
gcc/java/lang.c
gcc/tree-inline.c

index 0f5f1e0..0312c09 100644 (file)
@@ -1,3 +1,17 @@
+2002-10-14  Andrew Haley  <aph@redhat.com>
+
+       * tree-inline.c (remap_block): All local class initialization
+       flags go in the outermost scope.
+       (expand_call_inline): Call java_inlining_map_static_initializers.
+       (expand_call_inline): Call java_inlining_merge_static_initializers.
+       * java/lang.c (merge_init_test_initialization): New.
+       (java_inlining_merge_static_initializers): New.
+       (inline_init_test_initialization): New.
+       (java_inlining_map_static_initializers): New.
+
+       * tree-inline.c (expand_call_inline): Convert retvar to expected
+       type.
+
 2002-10-14  Graham Stott  <graham.stott@btinternet.com>
 
        * stmt.c (decl_conflicts_with_clobbers_p): Add REG_P check.
index 5c22fe9..307d225 100644 (file)
@@ -1,3 +1,14 @@
+2002-10-14  Andrew Haley  <aph@redhat.com>
+
+       * tree-inline.c (remap_block): All local class initialization
+       flags go in the outermost scope.
+       (expand_call_inline): Call java_inlining_map_static_initializers.
+       (expand_call_inline): Call java_inlining_merge_static_initializers.
+       * java/lang.c (merge_init_test_initialization): New.
+       (java_inlining_merge_static_initializers): New.
+       (inline_init_test_initialization): New.
+       (java_inlining_map_static_initializers): New.
+
 2002-10-11  Mark Wielaard  <mark@klomp.org>
 
        * gcj.texi (Compatibility): Add Limitations and Extensions section.
index 706b4f1..6f19961 100644 (file)
@@ -41,6 +41,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc.  */
 #include "ggc.h"
 #include "diagnostic.h"
 #include "tree-inline.h"
+#include "splay-tree.h"
 
 struct string_option
 {
@@ -62,15 +63,18 @@ static void java_print_error_function PARAMS ((diagnostic_context *,
 static int process_option_with_no PARAMS ((const char *,
                                           const struct string_option *,
                                           int));
-static tree java_tree_inlining_walk_subtrees  PARAMS ((tree *,
-                                                      int *,
-                                                      walk_tree_fn,
-                                                      void *,
-                                                      void *));
+static tree java_tree_inlining_walk_subtrees PARAMS ((tree *,
+                                                     int *,
+                                                     walk_tree_fn,
+                                                     void *,
+                                                     void *));
 static int java_unsafe_for_reeval PARAMS ((tree));
+static int merge_init_test_initialization PARAMS ((void * *, 
+                                                  void *));
+static int inline_init_test_initialization PARAMS ((void * *, 
+                                                   void *));
 static bool java_can_use_bit_fields_p PARAMS ((void));
 
-
 #ifndef TARGET_OBJECT_SUFFIX
 # define TARGET_OBJECT_SUFFIX ".o"
 #endif
@@ -928,4 +932,113 @@ java_unsafe_for_reeval (t)
   return -1;
 }
 
+/* Every call to a static constructor has an associated boolean
+   variable which is in the outermost scope of the calling method.
+   This variable is used to avoid multiple calls to the static
+   constructor for each class.  
+
+   It looks somthing like this:
+
+   foo ()
+   {
+      boolean dummy = OtherClass.is_initialized;
+  
+     ...
+  
+     if (! dummy)
+       OtherClass.initialize();
+
+     ... use OtherClass.data ...
+   }
+
+   Each of these boolean variables has an entry in the
+   DECL_FUNCTION_INIT_TEST_TABLE of a method.  When inlining a method
+   we must merge the DECL_FUNCTION_INIT_TEST_TABLE from the function
+   being linlined and create the boolean variables in the outermost
+   scope of the method being inlined into.  */
+
+/* Create a mapping from a boolean variable in a method being inlined
+   to one in the scope of the method being inlined into.  */
+
+static int
+merge_init_test_initialization (entry, x)
+     void * * entry;
+     void * x;
+{
+  struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry;
+  splay_tree decl_map = (splay_tree)x;
+  splay_tree_node n;
+  tree *init_test_decl;
+  
+  /* See if we have remapped this declaration.  If we haven't there's
+     a bug in the inliner.  */
+  n = splay_tree_lookup (decl_map, (splay_tree_key) ite->value);
+  if (! n)
+    abort ();
+
+  /* Create a new entry for the class and its remapped boolean
+     variable.  If we already have a mapping for this class we've
+     already initialized it, so don't overwrite the value.  */
+  init_test_decl = java_treetreehash_new
+    (DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), ite->key);
+  if (!*init_test_decl)
+    *init_test_decl = (tree)n->value;
+
+  return true;
+}
+
+/* Merge the DECL_FUNCTION_INIT_TEST_TABLE from the function we're
+   inlining.  */
+
+void
+java_inlining_merge_static_initializers (fn, decl_map)
+     tree fn;
+     void *decl_map;
+{
+  htab_traverse 
+    (DECL_FUNCTION_INIT_TEST_TABLE (fn),
+     merge_init_test_initialization, decl_map);
+}
+
+/* Lookup a DECL_FUNCTION_INIT_TEST_TABLE entry in the method we're
+   inlining into.  If we already have a corresponding entry in that
+   class we don't need to create another one, so we create a mapping
+   from the variable in the inlined class to the corresponding
+   pre-existing one.  */
+
+static int
+inline_init_test_initialization (entry, x)
+     void * * entry;
+     void * x;
+{
+  struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry;
+  splay_tree decl_map = (splay_tree)x;
+  
+  tree h = java_treetreehash_find 
+    (DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), ite->key);
+  if (! h)
+    return true;
+
+  splay_tree_insert (decl_map,
+                    (splay_tree_key) ite->value,
+                    (splay_tree_value) h);
+
+  return true;
+}
+
+/* Look up the boolean variables in the DECL_FUNCTION_INIT_TEST_TABLE
+   of a method being inlined.  For each hone, if we already have a
+   variable associated with the same class in the method being inlined
+   into, create a new mapping for it.  */
+
+void
+java_inlining_map_static_initializers (fn, decl_map)
+     tree fn;
+     void *decl_map;
+{
+  htab_traverse 
+    (DECL_FUNCTION_INIT_TEST_TABLE (fn),
+     inline_init_test_initialization, decl_map);
+}
+
 #include "gt-java-lang.h"
index cf4754c..f0194ad 100644 (file)
@@ -336,6 +336,23 @@ remap_block (block, decls, id)
     {
       tree new_var;
 
+      /* All local class initialization flags go in the outermost
+        scope.  */
+      if (LOCAL_CLASS_INITIALIZATION_FLAG_P (old_var))
+       {
+         /* We may already have one.  */
+         if (! splay_tree_lookup (id->decl_map, (splay_tree_key) old_var))
+           {
+             tree outermost_block;
+             new_var = remap_decl (old_var, id);
+             DECL_ABSTRACT_ORIGIN (new_var) = NULL;
+             outermost_block = DECL_SAVED_TREE (current_function_decl);
+             TREE_CHAIN (new_var) = BLOCK_VARS (outermost_block);
+             BLOCK_VARS (outermost_block) = new_var;
+           }
+         continue;
+       }
+
       /* Remap the variable.  */
       new_var = remap_decl (old_var, id);
       /* If we didn't remap this variable, so we can't mess with
@@ -1180,7 +1197,9 @@ expand_call_inline (tp, walk_subtrees, data)
   *inlined_body = copy_body (id);
 #else /* INLINER_FOR_JAVA */
   {
-    tree new_body = copy_body (id);
+    tree new_body;
+    java_inlining_map_static_initializers (fn, id->decl_map);
+    new_body = copy_body (id);
     TREE_TYPE (new_body) = TREE_TYPE (TREE_TYPE (fn));
     BLOCK_EXPR_BODY (expr)
       = add_stmt_to_compound (BLOCK_EXPR_BODY (expr), 
@@ -1218,9 +1237,17 @@ expand_call_inline (tp, walk_subtrees, data)
     = chainon (COMPOUND_BODY (stmt), scope_stmt);
 #else /* INLINER_FOR_JAVA */
   if (retvar)
-    BLOCK_EXPR_BODY (expr) 
-      = add_stmt_to_compound (BLOCK_EXPR_BODY (expr), 
-                             TREE_TYPE (retvar), retvar);
+    {
+      /* Mention the retvar.  If the return type of the function was
+        promoted, convert it back to the expected type.  */
+      if (TREE_TYPE (TREE_TYPE (fn)) != TREE_TYPE (retvar))
+       retvar = build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)), retvar);
+      BLOCK_EXPR_BODY (expr) 
+       = add_stmt_to_compound (BLOCK_EXPR_BODY (expr), 
+                               TREE_TYPE (retvar), retvar);
+    }
+  
+  java_inlining_merge_static_initializers (fn, id->decl_map);
 #endif /* INLINER_FOR_JAVA */
 
   /* Clean up.  */