Commit 4009bb7d by Alexandre Petit-Bianco Committed by Alexandre Petit-Bianco

check-init.c (flags.h): Include

2001-08-08  Alexandre Petit-Bianco  <apbianco@redhat.com>

	* check-init.c (flags.h): Include
	(check_init): Don't report uninitialized static class
	initialization flags, don't free bit index when doing static class
	initialization optimization.
	(check_for_initialization): Return type changed to `unsigned int.'
	(attach_initialized_static_class): New function.
	* class.c (add_method_1): Create the initialized static class
	table if necessary.
	(finish_class): Always emit deferred inline methods.
	* decl.c (emit_init_test_initialization): Moved to expr.c
	(complete_start_java_method): Don't traverse
	DECL_FUNCTION_INIT_TEST_TABLE.
	(lang_mark_tree): Mark hash tables in function decls.
	* expr.c (emit_init_test_initialization): Moved from decl.c.
	(build_class_init): Create LAG_DECL_SPECIFIC for the static class
	initialization flag, set DECL_CONTEXT and
	LOCAL_CLASS_INITIALIZATION_FLAG.
	(java_lang_expand_expr): Emit initialization code for static class
	initialized flags when entering block, if necessary.
	* gcj.texi (-fno-optimize-static-class-initialization): Documented.
	* java-tree.h (flag_optimize_sci): New global variable declaration.
	(DECL_FUNCTION_INITIALIZED_CLASS_TABLE): New macro.
	(DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND): Likewise.
	(LOCAL_FINAL_P): Fixed typo in comment.
	(FINAL_VARIABLE_P): Likewise.
	(LOCAL_CLASS_INITIALIZATIO_FLAG): New macro.
	(LOCAL_CLASS_INITIALIZATIO_FLAG_P): Likewise.
	(struct lang_decl): New fields `ict', `smic' and `cif.'
	(check_for_initialization): New returned value for global.
	(attach_initialized_static_class): New global function.
	(STATIC_CLASS_INIT_OPT_P): New macro.
	* lang-options.h (-fno-optimize-static-class-initialization): New flag.
	* lang.c (java_decode_option): Handle
	`-fno-optimize-static-class-initialization'
	* parse.y (start_complete_expand_method): New function.
	(java_expand_method_bodies): Likewise.
	(attach_init_test_initialization_flags): Likewise.
	(adjust_init_test_initialization): Likewise.
	(emit_test_initialization): Likewise.
	(java_complete_expand_methods): Nullify abstract and native method
	bodies.
	(java_complete_expand_method): New locals `fbody', `block_body'
	and `exception_copy.' Reorganized: directly return on empty method
	bodies, call `start_complete_expand_method', remember definitely
	initialized static class in function, don't expand method bodies.
	(java_expand_classes): Call `java_expand_method_bodies' before
	`finish_class' when compiling to native.
	(resolve_expression_name): Use `orig' after building outer class
	field access.
	(patch_invoke): Remember static method invokations.

(http://gcc.gnu.org/ml/gcc-patches/2001-08/msg00454.html)

From-SVN: r44733
parent 6351543d
2001-08-08 Alexandre Petit-Bianco <apbianco@redhat.com>
* check-init.c (flags.h): Include
(check_init): Don't report uninitialized static class
initialization flags, don't free bit index when doing static class
initialization optimization.
(check_for_initialization): Return type changed to `unsigned int.'
(attach_initialized_static_class): New function.
* class.c (add_method_1): Create the initialized static class
table if necessary.
(finish_class): Always emit deferred inline methods.
* decl.c (emit_init_test_initialization): Moved to expr.c
(complete_start_java_method): Don't traverse
DECL_FUNCTION_INIT_TEST_TABLE.
(lang_mark_tree): Mark hash tables in function decls.
* expr.c (emit_init_test_initialization): Moved from decl.c.
(build_class_init): Create LAG_DECL_SPECIFIC for the static class
initialization flag, set DECL_CONTEXT and
LOCAL_CLASS_INITIALIZATION_FLAG.
(java_lang_expand_expr): Emit initialization code for static class
initialized flags when entering block, if necessary.
* gcj.texi (-fno-optimize-static-class-initialization): Documented.
* java-tree.h (flag_optimize_sci): New global variable declaration.
(DECL_FUNCTION_INITIALIZED_CLASS_TABLE): New macro.
(DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND): Likewise.
(LOCAL_FINAL_P): Fixed typo in comment.
(FINAL_VARIABLE_P): Likewise.
(LOCAL_CLASS_INITIALIZATIO_FLAG): New macro.
(LOCAL_CLASS_INITIALIZATIO_FLAG_P): Likewise.
(struct lang_decl): New fields `ict', `smic' and `cif.'
(check_for_initialization): New returned value for global.
(attach_initialized_static_class): New global function.
(STATIC_CLASS_INIT_OPT_P): New macro.
* lang-options.h (-fno-optimize-static-class-initialization): New flag.
* lang.c (java_decode_option): Handle
`-fno-optimize-static-class-initialization'
* parse.y (start_complete_expand_method): New function.
(java_expand_method_bodies): Likewise.
(attach_init_test_initialization_flags): Likewise.
(adjust_init_test_initialization): Likewise.
(emit_test_initialization): Likewise.
(java_complete_expand_methods): Nullify abstract and native method
bodies.
(java_complete_expand_method): New locals `fbody', `block_body'
and `exception_copy.' Reorganized: directly return on empty method
bodies, call `start_complete_expand_method', remember definitely
initialized static class in function, don't expand method bodies.
(java_expand_classes): Call `java_expand_method_bodies' before
`finish_class' when compiling to native.
(resolve_expression_name): Use `orig' after building outer class
field access.
(patch_invoke): Remember static method invokations.
2001-08-06 Richard Henderson <rth@redhat.com>
* class.c (emit_register_classes): Pass a symbol_ref and priority
......
......@@ -25,6 +25,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "config.h"
#include "system.h"
#include "tree.h"
#include "flags.h" /* Needed for optimize. */
#include "java-tree.h"
#include "toplev.h" /* Needed for fatal. */
......@@ -370,7 +371,12 @@ check_init (exp, before)
if (! FIELD_STATIC (exp) && DECL_NAME (exp) != NULL_TREE)
{
int index = DECL_BIT_INDEX (exp);
if (index >= 0 && ! SET_P (before, index))
/* We don't want to report and mark as non initialized flags
the are, they will be marked initialized later on when
assigned to `true.' */
if ((STATIC_CLASS_INIT_OPT_P ()
&& ! LOCAL_CLASS_INITIALIZATION_FLAG_P (exp))
&& index >= 0 && ! SET_P (before, index))
{
parse_error_context
(wfl, "Variable `%s' may not have been initialized",
......@@ -398,8 +404,13 @@ check_init (exp, before)
if (index >= 0)
SET_BIT (before, index);
/* Minor optimization. See comment for start_current_locals. */
if (index >= start_current_locals
/* Minor optimization. See comment for start_current_locals.
If we're optimizing for class initialization, we keep
this information to check whether the variable is
definitely assigned when once we checked the whole
function. */
if (! STATIC_CLASS_INIT_OPT_P ()
&& index >= start_current_locals
&& index == num_current_locals - 1)
{
num_current_locals--;
......@@ -732,10 +743,35 @@ check_init (exp, before)
}
}
void
unsigned int
check_for_initialization (body)
tree body;
{
word before = 0;
check_init (body, &before);
return before;
}
/* Call for every element in DECL_FUNCTION_INITIALIZED_CLASS_TABLE of
a method to consider whether the type indirectly described by ENTRY
is definitly initialized and thus remembered as such. */
bool
attach_initialized_static_class (entry, ptr)
struct hash_entry *entry;
PTR ptr;
{
struct init_test_hash_entry *ite = (struct init_test_hash_entry *) entry;
tree fndecl = DECL_CONTEXT (ite->init_test_decl);
int index = DECL_BIT_INDEX (ite->init_test_decl);
/* If the initializer flag has been definitly assigned (not taking
into account its first mandatory assignment which has been
already added but escaped analysis.) */
if (fndecl && METHOD_STATIC (fndecl)
&& (DECL_INITIAL (ite->init_test_decl) == boolean_true_node
|| (index >= 0 && SET_P (((word *) ptr), index))))
hash_lookup (&DECL_FUNCTION_INITIALIZED_CLASS_TABLE (fndecl),
entry->key, TRUE, NULL);
return true;
}
......@@ -673,6 +673,18 @@ add_method_1 (handle_class, access_flags, name, function_type)
init_test_hash_newfunc, java_hash_hash_tree_node,
java_hash_compare_tree_node);
/* Initialize the initialized (static) class table. */
if (access_flags & ACC_STATIC)
hash_table_init (&DECL_FUNCTION_INITIALIZED_CLASS_TABLE (fndecl),
init_test_hash_newfunc, java_hash_hash_tree_node,
java_hash_compare_tree_node);
/* Initialize the static method invocation compound table */
if (STATIC_CLASS_INIT_OPT_P ())
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);
TYPE_METHODS (handle_class) = fndecl;
......@@ -1484,18 +1496,11 @@ finish_class ()
{
if (! TREE_ASM_WRITTEN (method) && DECL_SAVED_INSNS (method) != 0)
{
/* It's a deferred inline method. Decide if we need to emit it. */
if (flag_keep_inline_functions
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (method))
|| ! METHOD_PRIVATE (method)
|| saw_native_method)
{
output_inline_function (method);
/* Scan the list again to see if there are any earlier
methods to emit. */
method = type_methods;
continue;
}
output_inline_function (method);
/* Scan the list again to see if there are any earlier
methods to emit. */
method = type_methods;
continue;
}
method = TREE_CHAIN (method);
}
......
......@@ -49,8 +49,6 @@ static tree push_jvm_slot PARAMS ((int, tree));
static tree lookup_name_current_level PARAMS ((tree));
static tree push_promoted_type PARAMS ((const char *, tree));
static struct binding_level *make_binding_level PARAMS ((void));
static bool emit_init_test_initialization PARAMS ((struct hash_entry *,
hash_table_key));
static tree create_primitive_vtable PARAMS ((const char *));
static tree check_local_named_variable PARAMS ((tree, tree, int, int *));
static tree check_local_unnamed_variable PARAMS ((tree, tree, tree));
......@@ -1639,35 +1637,6 @@ build_result_decl (fndecl)
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 bool
emit_init_test_initialization (entry, key)
struct hash_entry *entry;
hash_table_key key ATTRIBUTE_UNUSED;
{
struct init_test_hash_entry *ite = (struct init_test_hash_entry *) entry;
tree klass = build_class_ref ((tree) entry->key);
expand_decl (ite->init_test_decl);
/* We initialize the class init check variable by looking at the
`state' field of the class to see if it is already initialized.
This makes things a bit faster if the class is already
initialized, which should be the common case. */
expand_expr_stmt
(build (MODIFY_EXPR, boolean_type_node,
ite->init_test_decl,
build (GE_EXPR, boolean_type_node,
build (COMPONENT_REF, byte_type_node,
build1 (INDIRECT_REF, class_type_node, klass),
lookup_field (&class_type_node,
get_identifier ("state"))),
build_int_2 (JV_STATE_DONE, 0))));
return true;
}
void
complete_start_java_method (fndecl)
tree fndecl;
......@@ -1679,11 +1648,6 @@ complete_start_java_method (fndecl)
/* 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);
}
#if 0
......@@ -1871,6 +1835,9 @@ lang_mark_tree (t)
ggc_mark_tree (ld->function_decl_body);
ggc_mark_tree (ld->called_constructor);
ggc_mark_tree (ld->inner_access);
ggc_mark_tree_hash_table (&ld->init_test_table);
ggc_mark_tree_hash_table (&ld->ict);
ggc_mark_tree_hash_table (&ld->smic);
}
}
else if (TYPE_P (t))
......
......@@ -82,6 +82,8 @@ static tree build_java_check_indexed_type PARAMS ((tree, tree));
static tree java_array_data_offset PARAMS ((tree));
static tree case_identity PARAMS ((tree, tree));
static unsigned char peek_opcode_at_pc PARAMS ((struct JCF *, int, int));
static bool emit_init_test_initialization PARAMS ((struct hash_entry *,
PTR ptr));
static tree operand_type[59];
extern struct obstack permanent_obstack;
......@@ -1710,10 +1712,20 @@ build_class_init (clas, expr)
TRUE, NULL);
if (ite->init_test_decl == 0)
ite->init_test_decl = build_decl (VAR_DECL, NULL_TREE,
boolean_type_node);
/* Tell the check-init code to ignore this decl. */
DECL_BIT_INDEX(ite->init_test_decl) = -1;
{
/* Build a declaration and mark it as a flag used to track
static class initializations. */
ite->init_test_decl = build_decl (VAR_DECL, NULL_TREE,
boolean_type_node);
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (ite->init_test_decl);
LOCAL_CLASS_INITIALIZATION_FLAG (ite->init_test_decl) = 1;
DECL_CONTEXT (ite->init_test_decl) = current_function_decl;
/* Tell the check-init code to ignore this decl when not
optimizing class initialization. */
if (!STATIC_CLASS_INIT_OPT_P ())
DECL_BIT_INDEX(ite->init_test_decl) = -1;
}
init = build (CALL_EXPR, void_type_node,
build_address_of (soft_initclass_node),
......@@ -2459,16 +2471,31 @@ java_lang_expand_expr (exp, target, tmode, modifier)
{
tree local;
tree body = BLOCK_EXPR_BODY (exp);
/* Set to 1 or more when we found a static class
initialization flag. */
int found_class_initialization_flag = 0;
pushlevel (2); /* 2 and above */
expand_start_bindings (0);
local = BLOCK_EXPR_DECLS (exp);
while (local)
{
tree next = TREE_CHAIN (local);
found_class_initialization_flag +=
LOCAL_CLASS_INITIALIZATION_FLAG_P (local);
layout_decl (local, 0);
expand_decl (pushdecl (local));
local = next;
}
/* Emit initialization code for test flags if we saw one. */
if (! always_initialize_class_p
&& current_function_decl
&& found_class_initialization_flag)
hash_traverse
(&DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl),
emit_init_test_initialization, NULL);
/* Avoid deep recursion for long block. */
while (TREE_CODE (body) == COMPOUND_EXPR)
{
......@@ -3335,3 +3362,37 @@ force_evaluation_order (node)
}
return node;
}
/* Called for every element in DECL_FUNCTION_INIT_TEST_TABLE of a
method in order to emit initialization code for each test flag. */
static bool
emit_init_test_initialization (entry, key)
struct hash_entry *entry;
hash_table_key key ATTRIBUTE_UNUSED;
{
struct init_test_hash_entry *ite = (struct init_test_hash_entry *) entry;
tree klass = build_class_ref ((tree) entry->key);
tree rhs;
/* If the DECL_INITIAL of the test flag is set to true, it
means that the class is already initialized the time it
is in use. */
if (DECL_INITIAL (ite->init_test_decl) == boolean_true_node)
rhs = boolean_true_node;
/* Otherwise, we initialize the class init check variable by looking
at the `state' field of the class to see if it is already
initialized. This makes things a bit faster if the class is
already initialized, which should be the common case. */
else
rhs = build (GE_EXPR, boolean_type_node,
build (COMPONENT_REF, byte_type_node,
build1 (INDIRECT_REF, class_type_node, klass),
lookup_field (&class_type_node,
get_identifier ("state"))),
build_int_2 (JV_STATE_DONE, 0));
expand_expr_stmt (build (MODIFY_EXPR, boolean_type_node,
ite->init_test_decl, rhs));
return true;
}
......@@ -356,6 +356,14 @@ compiling a class with native methods, and these methods are implemented
using JNI, then you must use @code{-fjni}. This option causes
@code{gcj} to generate stubs which will invoke the underlying JNI
methods.
@item -fno-optimize-static-class-initialization
When the optimization level is greather or equal to @code{-O2},
@code{gcj} will try to optimize the way calls into the runtime are made
to initialize static classes upon their first use (this optimization
isn't carried out if @code{-C} was specified.) When compiling to native
code, @code{-fno-optimize-static-class-initialization} will turn this
optimization off, regardless of the optimization level in use.
@end table
......
......@@ -186,6 +186,10 @@ extern int flag_hash_synchronization;
/* When non zero, generate checks for references to NULL. */
extern int flag_check_references;
/* Used through STATIC_CLASS_INIT_OPT_P to check whether static
initialization optimization should be performed. */
extern int flag_optimize_sci;
/* Encoding used for source files. */
extern const char *current_encoding;
......@@ -704,6 +708,16 @@ struct lang_identifier
class has been initialized in this function, and FALSE otherwise. */
#define DECL_FUNCTION_INIT_TEST_TABLE(DECL) \
(DECL_LANG_SPECIFIC(DECL)->init_test_table)
/* For each static function decl, itc contains a hash table whose
entries are keyed on class named that are definitively initialized
in DECL. */
#define DECL_FUNCTION_INITIALIZED_CLASS_TABLE(DECL) \
(DECL_LANG_SPECIFIC(DECL)->ict)
/* For each static function call, smic contains contains a hash table
whose entries are keyed on the compound statement that encapsulate
the invocation. */
#define DECL_FUNCTION_STATIC_METHOD_INVOCATION_COMPOUND(DECL) \
(DECL_LANG_SPECIFIC(DECL)->smic)
/* The Number of Artificial Parameters (NAP) DECL contains. this$<n>
is excluded, because sometimes created as a parameter before the
function decl exists. */
......@@ -815,11 +829,18 @@ struct lang_identifier
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->local_final)
/* True if NODE is a local final. */
#define LOCAL_FINAL_P(NODE) (DECL_LANG_SPECIFIC (NODE) && LOCAL_FINAL (NODE))
/* True if NODE is a final variable */
/* True if NODE is a final variable. */
#define FINAL_VARIABLE_P(NODE) (FIELD_FINAL (NODE) && !FIELD_STATIC (NODE))
/* True if NODE is a class final variable */
/* True if NODE is a class final variable. */
#define CLASS_FINAL_VARIABLE_P(NODE) \
(FIELD_FINAL (NODE) && FIELD_STATIC (NODE))
/* True if NODE is a class initialization flag. This macro accesses
the flag to read or set it. */
#define LOCAL_CLASS_INITIALIZATION_FLAG(NODE) \
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->cif)
/* True if NODE is a class initialization flag. */
#define LOCAL_CLASS_INITIALIZATION_FLAG_P(NODE) \
(DECL_LANG_SPECIFIC (NODE) && LOCAL_CLASS_INITIALIZATION_FLAG(NODE))
/* Create a DECL_LANG_SPECIFIC if necessary. */
#define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T) \
if (DECL_LANG_SPECIFIC (T) == NULL) \
......@@ -858,6 +879,8 @@ struct lang_decl
list of other constructor it calls */
struct hash_table init_test_table;
/* Class initialization test variables */
struct hash_table ict; /* Initialized (static) Class Table */
struct hash_table smic; /* Static method invocation compound */
tree inner_access; /* The identifier of the access method
used for invocation from inner classes */
int nap; /* Number of artificial parameters */
......@@ -888,6 +911,7 @@ struct lang_decl_var
int final_liic : 1; /* Final locally initialized in ctors */
int final_ierr : 1; /* Initialization error already detected */
int local_final : 1; /* True if the decl is a local final */
int cif : 1; /* True: decl is a class initialization flag */
};
/* Macro to access fields in `struct lang_type'. */
......@@ -1061,7 +1085,7 @@ extern void parse_error_context PARAMS ((tree cl, const char *, ...))
extern tree build_primtype_type_ref PARAMS ((const char *));
extern void finish_class PARAMS ((void));
extern void java_layout_seen_class_methods PARAMS ((void));
extern void check_for_initialization PARAMS ((tree));
extern unsigned int check_for_initialization PARAMS ((tree));
extern tree pushdecl_top_level PARAMS ((tree));
extern int alloc_class_constant PARAMS ((tree));
......@@ -1129,6 +1153,8 @@ extern tree get_boehm_type_descriptor PARAMS ((tree));
extern unsigned long java_hash_hash_tree_node PARAMS ((hash_table_key));
extern bool java_hash_compare_tree_node PARAMS ((hash_table_key,
hash_table_key));
extern bool attach_initialized_static_class PARAMS ((struct hash_entry *,
PTR));
extern void java_check_methods PARAMS ((tree));
extern void init_jcf_parse PARAMS((void));
extern void init_src_parse PARAMS((void));
......@@ -1559,6 +1585,10 @@ extern tree *type_map;
(inherits_from_p ((TYPE), runtime_exception_type_node) \
|| inherits_from_p ((TYPE), error_exception_type_node))
/* True when we can perform static class initialization optimization */
#define STATIC_CLASS_INIT_OPT_P() \
(flag_optimize_sci && (optimize >= 2) && ! flag_emit_class_files)
extern int java_error_count; \
/* Make the current function where this macro is invoked report error
......
......@@ -52,3 +52,5 @@ DEFINE_LANG_NAME ("Java")
N_("Warn if .class files are out of date") },
{ "-fforce-classes-archive-check",
N_("Always check for non gcj generated classes archives") },
{ "-fno-optimize-static-class-initialization",
N_("Never optimize static class initialization code") },
......@@ -146,6 +146,10 @@ int flag_extraneous_semicolon;
/* When non zero, always check for a non gcj generated classes archive. */
int flag_force_classes_archive_check;
/* When zero, don't optimize static class initialization. This flag shouldn't
be tested alone, use STATIC_CLASS_INITIALIZATION_OPTIMIZATION_P instead. */
int flag_optimize_sci = 1;
/* Table of language-dependent -f options.
STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE
......@@ -295,6 +299,15 @@ java_decode_option (argc, argv)
}
#undef ARG
#undef ARG
#define ARG "-fno-optimize-static-class-initialization"
if (strncmp (p, ARG, sizeof (ARG) - 1) == 0)
{
flag_optimize_sci = 0;
return 1;
}
#undef ARG
if (p[0] == '-' && p[1] == 'f')
{
/* Some kind of -f option.
......
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