Another inliner patch
Adam Megacz
gcj@lists.megacz.com
Thu Oct 3 23:11:00 GMT 2002
Bah, I saw "inliner patch" and hoped that this had fixed PR 8063;
unfortunately it does not.
I'm also rewriting the PR since you need to do different things to
reproduce the fault depending on whether your compiler was built with
gcc 2.95 or 3.x. The new PR (which I will post here shortly) should
be reproducible by everyone.
- a
Andrew Haley <aph@redhat.com> writes:
> This testcase doesn't work correctly at -O3 because static
> initializers are not called from inlined methods:
>> // Test to make sure static initializers are called
>> class bar
> {
> public static int zog;
> public static int zag;
>> static
> {
> zog = 12;
> zag = 2;
> }
>> public bar() { }
> }
>> public class StaticConstructor
> {
> static int foo ()
> {
> return new bar().zog;
> }
>> public static void main(String args[])
> {
> System.out.println ("" + (foo() + bar.zag));
> }
> }
>> The patch to fix this is rather complicated.
>> Andrew.
>>> * 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.
>>> Index: tree-inline.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
> retrieving revision 1.31
> diff -c -2 -p -r1.31 tree-inline.c
> *** tree-inline.c 27 Sep 2002 12:48:04 -0000 1.31
> --- tree-inline.c 3 Oct 2002 15:42:36 -0000
> *************** remap_block (block, decls, id)
> *** 337,340 ****
> --- 337,357 ----
> 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);
> *************** expand_call_inline (tp, walk_subtrees, d
> *** 1181,1185 ****
> #else /* INLINER_FOR_JAVA */
> {
> ! tree new_body = copy_body (id);
> TREE_TYPE (new_body) = TREE_TYPE (TREE_TYPE (fn));
> BLOCK_EXPR_BODY (expr)
> --- 1198,1204 ----
> #else /* INLINER_FOR_JAVA */
> {
> ! 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)
> *************** expand_call_inline (tp, walk_subtrees, d
> *** 1222,1225 ****
> --- 1241,1246 ----
> = 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 */
>> Index: java/lang.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/java/lang.c,v
> retrieving revision 1.109
> diff -c -2 -p -r1.109 lang.c
> *** java/lang.c 21 Sep 2002 02:19:44 -0000 1.109
> --- java/lang.c 3 Oct 2002 15:42:37 -0000
> *************** The Free Software Foundation is independ
> *** 42,45 ****
> --- 42,46 ----
> #include "diagnostic.h"
> #include "tree-inline.h"
> + #include "splay-tree.h"
>> struct string_option
> *************** static int process_option_with_no PARAMS
> *** 63,75 ****
> const struct string_option *,
> int));
> ! static tree java_tree_inlining_walk_subtrees PARAMS ((tree *,
> ! int *,
> ! walk_tree_fn,
> ! void *,
> ! void *));
> static int java_unsafe_for_reeval PARAMS ((tree));
> static bool java_can_use_bit_fields_p PARAMS ((void));
>> -
> #ifndef TARGET_OBJECT_SUFFIX
> # define TARGET_OBJECT_SUFFIX ".o"
> --- 64,79 ----
> const struct string_option *,
> int));
> ! 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"
> *************** java_unsafe_for_reeval (t)
> *** 916,919 ****
> --- 920,1032 ----
>> 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);
> }
>>>
--
"Through your rags I see your vanity" -- Socrates
More information about the Java
mailing list