Commit 5412ef6b by Per Bothner Committed by Per Bothner

Restore support for static class initialization optimization.

From-SVN: r47735
parent c1bf99a2
2001-12-05 Per Bothner <per@bothner.com>
Restore support for static class initialization optimization.
* java-tree.h (STATIC_CLASS_INIT_OPT_P): Re-enable.
* check-init.c (check_int): At end of BLOCK handle initialization
blocks, which used to be done in java_complete_expand_method but did
not handle the case where check_for_initialization might allocate
more than a word of bits.
* decl.c (lang_make_tree): The smic field is now a tree.
* expr.c (build_class_init): Set DECL_FUNCTION_INIT_TEST_CLASS field.
* java-tree.h (DECL_FUNCTION_INIT_TEST_TABLE): New macro.
* parse.y (emit_test_initialization): Combine hash_lookup calls.
* java-tree.h (DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND):
Change from a hash table to a list.
(struct_lang_decl): Change field 'smic' to match.
* class.c (add_method_1): Initialize
DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND to null list.
* parse.y (adjust_init_test_initialization): Removed - inlined into -
(java_expand_method_bodies): -here, since 'smic' is now a list.
(patch_invoke): Add to 'smic' list, instead of hash_lookup.
* check-init.c (WORD_SIZE): Use BITS_PER_UNIT.
* class.c (java_hash_compare_tree_node): Fix casts.
2001-12-04 Per Bothner <per@bothner.com> 2001-12-04 Per Bothner <per@bothner.com>
* check-init.c: Handle definite unassignment to finals in addition * check-init.c: Handle definite unassignment to finals in addition
......
...@@ -96,7 +96,7 @@ static tree wfl; ...@@ -96,7 +96,7 @@ static tree wfl;
#define INTERSECT(DST, SRC1, SRC2) \ #define INTERSECT(DST, SRC1, SRC2) \
INTERSECTN (DST, SRC1, SRC2, num_current_words) INTERSECTN (DST, SRC1, SRC2, num_current_words)
#define WORD_SIZE ((unsigned int)(sizeof(word) * 8)) #define WORD_SIZE ((unsigned int)(sizeof(word) * BITS_PER_UNIT))
static void check_bool_init PARAMS ((tree, words, words, words)); static void check_bool_init PARAMS ((tree, words, words, words));
static void check_init PARAMS ((tree, words)); static void check_init PARAMS ((tree, words));
...@@ -595,6 +595,24 @@ check_init (exp, before) ...@@ -595,6 +595,24 @@ check_init (exp, before)
SET_UNASSIGNED (tmp, i); SET_UNASSIGNED (tmp, i);
} }
check_init (BLOCK_EXPR_BODY (exp), tmp); check_init (BLOCK_EXPR_BODY (exp), tmp);
/* Re-set DECL_BIT_INDEX since it is also DECL_POINTER_ALIAS_SET. */
for (decl = BLOCK_EXPR_DECLS (exp);
decl != NULL_TREE; decl = TREE_CHAIN (decl))
{
if (LOCAL_CLASS_INITIALIZATION_FLAG_P (decl))
{
int index = DECL_BIT_INDEX (decl);
tree fndecl = DECL_CONTEXT (decl);
if (fndecl && METHOD_STATIC (fndecl)
&& (DECL_INITIAL (decl) == boolean_true_node
|| (index >= 0 && ASSIGNED_P (tmp, index))))
hash_lookup (&DECL_FUNCTION_INITIALIZED_CLASS_TABLE (fndecl),
DECL_FUNCTION_INIT_TEST_CLASS(decl), TRUE, NULL);
}
DECL_BIT_INDEX (decl) = -1;
}
num_current_locals = start_current_locals; num_current_locals = start_current_locals;
start_current_locals = save_start_current_locals; start_current_locals = save_start_current_locals;
if (tmp != before) if (tmp != before)
...@@ -603,13 +621,6 @@ check_init (exp, before) ...@@ -603,13 +621,6 @@ check_init (exp, before)
COPY (before, tmp); COPY (before, tmp);
FREE_WORDS (tmp); FREE_WORDS (tmp);
} }
/* Re-set DECL_BIT_INDEX since it is also DECL_POINTER_ALIAS_SET. */
for (decl = BLOCK_EXPR_DECLS (exp);
decl != NULL_TREE; decl = TREE_CHAIN (decl))
{
DECL_BIT_INDEX (decl) = -1;
}
} }
break; break;
case LOOP_EXPR: case LOOP_EXPR:
......
...@@ -656,7 +656,7 @@ java_hash_compare_tree_node (k1, k2) ...@@ -656,7 +656,7 @@ java_hash_compare_tree_node (k1, k2)
hash_table_key k1; hash_table_key k1;
hash_table_key k2; hash_table_key k2;
{ {
return ((char*) k1 == (char*) k2); return ((tree) k1 == (tree) k2);
} }
tree tree
...@@ -688,11 +688,8 @@ add_method_1 (handle_class, access_flags, name, function_type) ...@@ -688,11 +688,8 @@ add_method_1 (handle_class, access_flags, name, function_type)
init_test_hash_newfunc, java_hash_hash_tree_node, init_test_hash_newfunc, java_hash_hash_tree_node,
java_hash_compare_tree_node); java_hash_compare_tree_node);
/* Initialize the static method invocation compound table */ /* Initialize the static method invocation compound list */
if (STATIC_CLASS_INIT_OPT_P ()) DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl) = NULL_TREE;
hash_table_init (&DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl),
init_test_hash_newfunc, java_hash_hash_tree_node,
java_hash_compare_tree_node);
TREE_CHAIN (fndecl) = TYPE_METHODS (handle_class); TREE_CHAIN (fndecl) = TYPE_METHODS (handle_class);
TYPE_METHODS (handle_class) = fndecl; TYPE_METHODS (handle_class) = fndecl;
......
...@@ -1847,7 +1847,7 @@ lang_mark_tree (t) ...@@ -1847,7 +1847,7 @@ lang_mark_tree (t)
ggc_mark_tree (ld->inner_access); ggc_mark_tree (ld->inner_access);
ggc_mark_tree_hash_table (&ld->init_test_table); ggc_mark_tree_hash_table (&ld->init_test_table);
ggc_mark_tree_hash_table (&ld->ict); ggc_mark_tree_hash_table (&ld->ict);
ggc_mark_tree_hash_table (&ld->smic); ggc_mark_tree (ld->smic);
} }
} }
else if (TYPE_P (t)) else if (TYPE_P (t))
......
...@@ -1729,7 +1729,7 @@ build_class_init (clas, expr) ...@@ -1729,7 +1729,7 @@ build_class_init (clas, expr)
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (ite->init_test_decl); MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (ite->init_test_decl);
LOCAL_CLASS_INITIALIZATION_FLAG (ite->init_test_decl) = 1; LOCAL_CLASS_INITIALIZATION_FLAG (ite->init_test_decl) = 1;
DECL_CONTEXT (ite->init_test_decl) = current_function_decl; DECL_CONTEXT (ite->init_test_decl) = current_function_decl;
DECL_FUNCTION_INIT_TEST_CLASS (ite->init_test_decl) = clas;
/* Tell the check-init code to ignore this decl when not /* Tell the check-init code to ignore this decl when not
optimizing class initialization. */ optimizing class initialization. */
if (!STATIC_CLASS_INIT_OPT_P ()) if (!STATIC_CLASS_INIT_OPT_P ())
......
...@@ -726,14 +726,17 @@ struct lang_identifier ...@@ -726,14 +726,17 @@ struct lang_identifier
class has been initialized in this function, and FALSE otherwise. */ class has been initialized in this function, and FALSE otherwise. */
#define DECL_FUNCTION_INIT_TEST_TABLE(DECL) \ #define DECL_FUNCTION_INIT_TEST_TABLE(DECL) \
(DECL_LANG_SPECIFIC(DECL)->init_test_table) (DECL_LANG_SPECIFIC(DECL)->init_test_table)
/* If LOCAL_CLASS_INITIALIZATION_FLAG_P(decl), give class it initializes. */
#define DECL_FUNCTION_INIT_TEST_CLASS(DECL) \
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(DECL))->slot_chain)
/* For each static function decl, itc contains a hash table whose /* For each static function decl, itc contains a hash table whose
entries are keyed on class named that are definitively initialized entries are keyed on class named that are definitively initialized
in DECL. */ in DECL. */
#define DECL_FUNCTION_INITIALIZED_CLASS_TABLE(DECL) \ #define DECL_FUNCTION_INITIALIZED_CLASS_TABLE(DECL) \
(DECL_LANG_SPECIFIC(DECL)->ict) (DECL_LANG_SPECIFIC(DECL)->ict)
/* For each static function call, smic contains contains a hash table /* A list of all the static method calls in the method DECL (if optimizing).
whose entries are keyed on the compound statement that encapsulate Actually each TREE_VALUE points to a COMPONT_EXPR that wraps the
the invocation. */ invoation so we can later patch it. */
#define DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND(DECL) \ #define DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND(DECL) \
(DECL_LANG_SPECIFIC(DECL)->smic) (DECL_LANG_SPECIFIC(DECL)->smic)
/* The Number of Artificial Parameters (NAP) DECL contains. this$<n> /* The Number of Artificial Parameters (NAP) DECL contains. this$<n>
...@@ -888,7 +891,7 @@ struct lang_decl ...@@ -888,7 +891,7 @@ struct lang_decl
struct hash_table init_test_table; struct hash_table init_test_table;
/* Class initialization test variables */ /* Class initialization test variables */
struct hash_table ict; /* Initialized (static) Class Table */ struct hash_table ict; /* Initialized (static) Class Table */
struct hash_table smic; /* Static method invocation compound */ tree smic; /* Static method invocation compound */
tree inner_access; /* The identifier of the access method tree inner_access; /* The identifier of the access method
used for invocation from inner classes */ used for invocation from inner classes */
int nap; /* Number of artificial parameters */ int nap; /* Number of artificial parameters */
...@@ -1604,8 +1607,7 @@ extern tree *type_map; ...@@ -1604,8 +1607,7 @@ extern tree *type_map;
/* True when we can perform static class initialization optimization */ /* True when we can perform static class initialization optimization */
#define STATIC_CLASS_INIT_OPT_P() \ #define STATIC_CLASS_INIT_OPT_P() \
0 /* ??? Temporarily turn off this optimization -PB */ (flag_optimize_sci && (optimize >= 2) && ! flag_emit_class_files)
/* (flag_optimize_sci && (optimize >= 2) && ! flag_emit_class_files)*/
extern int java_error_count; extern int java_error_count;
......
...@@ -335,8 +335,6 @@ static tree maybe_build_class_init_for_field PARAMS ((tree, tree)); ...@@ -335,8 +335,6 @@ static tree maybe_build_class_init_for_field PARAMS ((tree, tree));
static bool attach_init_test_initialization_flags PARAMS ((struct hash_entry *, static bool attach_init_test_initialization_flags PARAMS ((struct hash_entry *,
PTR)); PTR));
static bool adjust_init_test_initialization PARAMS ((struct hash_entry *,
PTR));
static bool emit_test_initialization PARAMS ((struct hash_entry *, PTR)); static bool emit_test_initialization PARAMS ((struct hash_entry *, PTR));
/* Number of error found so far. */ /* Number of error found so far. */
...@@ -8017,21 +8015,16 @@ java_complete_expand_method (mdecl) ...@@ -8017,21 +8015,16 @@ java_complete_expand_method (mdecl)
static variables and see whether they're definitively static variables and see whether they're definitively
assigned, in which case the type is remembered as assigned, in which case the type is remembered as
definitively initialized in MDECL. */ definitively initialized in MDECL. */
/* FIXME this doesn't work state is too short.
if (STATIC_CLASS_INIT_OPT_P ()) if (STATIC_CLASS_INIT_OPT_P ())
{ {
hash_traverse (&DECL_FUNCTION_INIT_TEST_TABLE (mdecl), /* Always register the context as properly initialized in
attach_initialized_static_class, (PTR)&state);
/ * Always register the context as properly initialized in
MDECL. This used with caution helps removing extra MDECL. This used with caution helps removing extra
initialization of self. * / initialization of self. */
if (METHOD_STATIC (mdecl)) if (METHOD_STATIC (mdecl))
hash_lookup (&DECL_FUNCTION_INITIALIZED_CLASS_TABLE (mdecl), hash_lookup (&DECL_FUNCTION_INITIALIZED_CLASS_TABLE (mdecl),
(hash_table_key) DECL_CONTEXT (mdecl), (hash_table_key) DECL_CONTEXT (mdecl),
TRUE, NULL); TRUE, NULL);
} }
*/
} }
ctxp->explicit_constructor_p = 0; ctxp->explicit_constructor_p = 0;
} }
...@@ -8081,8 +8074,32 @@ java_expand_method_bodies (class) ...@@ -8081,8 +8074,32 @@ java_expand_method_bodies (class)
initialization based on which classes invoked static methods initialization based on which classes invoked static methods
are definitely initializing. This should be flagged. */ are definitely initializing. This should be flagged. */
if (STATIC_CLASS_INIT_OPT_P ()) if (STATIC_CLASS_INIT_OPT_P ())
hash_traverse (&DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (decl), {
adjust_init_test_initialization, NULL); tree list = DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (decl);
for (; list != NULL_TREE; list = TREE_CHAIN (list))
{
/* Executed for each statement calling a static function.
LIST is a TREE_LIST whose PURPOSE is the called function
and VALUE is a compound whose second operand can be patched
with static class initialization flag assignments. */
tree called_method = TREE_PURPOSE (list);
tree compound = TREE_VALUE (list);
tree assignment_compound_list
= build_tree_list (called_method, NULL);
/* For each class definitely initialized in
CALLED_METHOD, fill ASSIGNMENT_COMPOUND with
assignment to the class initialization flag. */
hash_traverse (&DECL_FUNCTION_INITIALIZED_CLASS_TABLE (called_method),
emit_test_initialization,
assignment_compound_list);
if (TREE_VALUE (assignment_compound_list))
TREE_OPERAND (compound, 1)
= TREE_VALUE (assignment_compound_list);
}
}
/* Prepare the function for RTL expansion */ /* Prepare the function for RTL expansion */
start_complete_expand_method (decl); start_complete_expand_method (decl);
...@@ -10691,10 +10708,10 @@ patch_invoke (patch, method, args) ...@@ -10691,10 +10708,10 @@ patch_invoke (patch, method, args)
tree type = TREE_TYPE (patch); tree type = TREE_TYPE (patch);
patch = build (COMPOUND_EXPR, type, save, empty_stmt_node); patch = build (COMPOUND_EXPR, type, save, empty_stmt_node);
list = build_tree_list (method, patch); list = tree_cons (method, patch,
DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl));
hash_lookup (&DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl), DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND (fndecl) = list;
(const hash_table_key) list, TRUE, NULL);
patch = build (COMPOUND_EXPR, type, patch, save); patch = build (COMPOUND_EXPR, type, patch, save);
} }
...@@ -15974,32 +15991,6 @@ attach_init_test_initialization_flags (entry, ptr) ...@@ -15974,32 +15991,6 @@ attach_init_test_initialization_flags (entry, ptr)
return true; return true;
} }
/* This function is called for each statement calling a static
function. ENTRY is a TREE_LIST whose PURPOSE is the called
function and VALUE is a compound whose second operand can be
patched with static class initialization flag assignments. */
static bool
adjust_init_test_initialization (entry, info)
struct hash_entry *entry;
PTR info ATTRIBUTE_UNUSED;
{
tree list = (tree)(entry->key);
tree called_method = TREE_PURPOSE (list);
tree compound = TREE_VALUE (list);
tree assignment_compound_list = build_tree_list (called_method, NULL);
/* For each class definitely initialized in CALLED_METHOD, fill
ASSIGNMENT_COMPOUND with assignment to the class initialization flag. */
hash_traverse (&DECL_FUNCTION_INITIALIZED_CLASS_TABLE (called_method),
emit_test_initialization, assignment_compound_list);
if (TREE_VALUE (assignment_compound_list))
TREE_OPERAND (compound, 1) = TREE_VALUE (assignment_compound_list);
return true;
}
/* This function is called for each classes that is known definitely /* This function is called for each classes that is known definitely
assigned when a given static method was called. This function assigned when a given static method was called. This function
augments a compound expression (INFO) storing all assignment to augments a compound expression (INFO) storing all assignment to
...@@ -16016,21 +16007,15 @@ emit_test_initialization (entry, info) ...@@ -16016,21 +16007,15 @@ emit_test_initialization (entry, info)
struct init_test_hash_entry *ite = (struct init_test_hash_entry *) struct init_test_hash_entry *ite = (struct init_test_hash_entry *)
hash_lookup (&DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), hash_lookup (&DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl),
entry->key, FALSE, NULL); entry->key,
current_function_decl != TREE_PURPOSE (l), NULL);
/* If we haven't found a flag and we're dealing with self registered /* If we haven't found a flag and we're dealing with self registered
with current_function_decl, then don't do anything. Self is with current_function_decl, then don't do anything. Self is
always added as definitely initialized but this information is always added as definitely initialized but this information is
valid only if used outside the current function. */ valid only if used outside the current function. */
if (! ite) if (! ite)
{ return true;
if (current_function_decl != TREE_PURPOSE (l))
ite = (struct init_test_hash_entry *)
hash_lookup (&DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl),
entry->key, TRUE, NULL);
else
return true;
}
/* If we don't have a variable, create one and install it. */ /* If we don't have a variable, create one and install it. */
if (! ite->init_test_decl) if (! ite->init_test_decl)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment