diff options
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/java/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/java/lang.c | 125 | ||||
-rw-r--r-- | gcc/tree-inline.c | 35 |
4 files changed, 175 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0f5f1e061c4..0312c09199d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 5c22fe92a2e..307d225e240 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -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. diff --git a/gcc/java/lang.c b/gcc/java/lang.c index 706b4f12776..6f19961f65c 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -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" diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index cf4754cad09..f0194ad0355 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -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. */ |