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> 2001-08-06 Richard Henderson <rth@redhat.com>
* class.c (emit_register_classes): Pass a symbol_ref and priority * 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. */ ...@@ -25,6 +25,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
#include "tree.h" #include "tree.h"
#include "flags.h" /* Needed for optimize. */
#include "java-tree.h" #include "java-tree.h"
#include "toplev.h" /* Needed for fatal. */ #include "toplev.h" /* Needed for fatal. */
...@@ -370,7 +371,12 @@ check_init (exp, before) ...@@ -370,7 +371,12 @@ check_init (exp, before)
if (! FIELD_STATIC (exp) && DECL_NAME (exp) != NULL_TREE) if (! FIELD_STATIC (exp) && DECL_NAME (exp) != NULL_TREE)
{ {
int index = DECL_BIT_INDEX (exp); 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 parse_error_context
(wfl, "Variable `%s' may not have been initialized", (wfl, "Variable `%s' may not have been initialized",
...@@ -398,8 +404,13 @@ check_init (exp, before) ...@@ -398,8 +404,13 @@ check_init (exp, before)
if (index >= 0) if (index >= 0)
SET_BIT (before, index); SET_BIT (before, index);
/* Minor optimization. See comment for start_current_locals. */ /* Minor optimization. See comment for start_current_locals.
if (index >= 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) && index == num_current_locals - 1)
{ {
num_current_locals--; num_current_locals--;
...@@ -732,10 +743,35 @@ check_init (exp, before) ...@@ -732,10 +743,35 @@ check_init (exp, before)
} }
} }
void unsigned int
check_for_initialization (body) check_for_initialization (body)
tree body; tree body;
{ {
word before = 0; word before = 0;
check_init (body, &before); 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) ...@@ -673,6 +673,18 @@ 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 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); TREE_CHAIN (fndecl) = TYPE_METHODS (handle_class);
TYPE_METHODS (handle_class) = fndecl; TYPE_METHODS (handle_class) = fndecl;
...@@ -1484,18 +1496,11 @@ finish_class () ...@@ -1484,18 +1496,11 @@ finish_class ()
{ {
if (! TREE_ASM_WRITTEN (method) && DECL_SAVED_INSNS (method) != 0) if (! TREE_ASM_WRITTEN (method) && DECL_SAVED_INSNS (method) != 0)
{ {
/* It's a deferred inline method. Decide if we need to emit it. */ output_inline_function (method);
if (flag_keep_inline_functions /* Scan the list again to see if there are any earlier
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (method)) methods to emit. */
|| ! METHOD_PRIVATE (method) method = type_methods;
|| saw_native_method) 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); method = TREE_CHAIN (method);
} }
......
...@@ -49,8 +49,6 @@ static tree push_jvm_slot PARAMS ((int, tree)); ...@@ -49,8 +49,6 @@ static tree push_jvm_slot PARAMS ((int, tree));
static tree lookup_name_current_level PARAMS ((tree)); static tree lookup_name_current_level PARAMS ((tree));
static tree push_promoted_type PARAMS ((const char *, tree)); static tree push_promoted_type PARAMS ((const char *, tree));
static struct binding_level *make_binding_level PARAMS ((void)); 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 create_primitive_vtable PARAMS ((const char *));
static tree check_local_named_variable PARAMS ((tree, tree, int, int *)); static tree check_local_named_variable PARAMS ((tree, tree, int, int *));
static tree check_local_unnamed_variable PARAMS ((tree, tree, tree)); static tree check_local_unnamed_variable PARAMS ((tree, tree, tree));
...@@ -1639,35 +1637,6 @@ build_result_decl (fndecl) ...@@ -1639,35 +1637,6 @@ build_result_decl (fndecl)
return (DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, restype)); 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 void
complete_start_java_method (fndecl) complete_start_java_method (fndecl)
tree fndecl; tree fndecl;
...@@ -1679,11 +1648,6 @@ complete_start_java_method (fndecl) ...@@ -1679,11 +1648,6 @@ complete_start_java_method (fndecl)
/* Set up parameters and prepare for return, for the function. */ /* Set up parameters and prepare for return, for the function. */
expand_function_start (fndecl, 0); 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 #if 0
...@@ -1871,6 +1835,9 @@ lang_mark_tree (t) ...@@ -1871,6 +1835,9 @@ lang_mark_tree (t)
ggc_mark_tree (ld->function_decl_body); ggc_mark_tree (ld->function_decl_body);
ggc_mark_tree (ld->called_constructor); ggc_mark_tree (ld->called_constructor);
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->ict);
ggc_mark_tree_hash_table (&ld->smic);
} }
} }
else if (TYPE_P (t)) else if (TYPE_P (t))
......
...@@ -82,6 +82,8 @@ static tree build_java_check_indexed_type PARAMS ((tree, tree)); ...@@ -82,6 +82,8 @@ static tree build_java_check_indexed_type PARAMS ((tree, tree));
static tree java_array_data_offset PARAMS ((tree)); static tree java_array_data_offset PARAMS ((tree));
static tree case_identity PARAMS ((tree, tree)); static tree case_identity PARAMS ((tree, tree));
static unsigned char peek_opcode_at_pc PARAMS ((struct JCF *, int, int)); 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]; static tree operand_type[59];
extern struct obstack permanent_obstack; extern struct obstack permanent_obstack;
...@@ -1710,10 +1712,20 @@ build_class_init (clas, expr) ...@@ -1710,10 +1712,20 @@ build_class_init (clas, expr)
TRUE, NULL); TRUE, NULL);
if (ite->init_test_decl == 0) if (ite->init_test_decl == 0)
ite->init_test_decl = build_decl (VAR_DECL, NULL_TREE, {
boolean_type_node); /* Build a declaration and mark it as a flag used to track
/* Tell the check-init code to ignore this decl. */ static class initializations. */
DECL_BIT_INDEX(ite->init_test_decl) = -1; 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, init = build (CALL_EXPR, void_type_node,
build_address_of (soft_initclass_node), build_address_of (soft_initclass_node),
...@@ -2459,16 +2471,31 @@ java_lang_expand_expr (exp, target, tmode, modifier) ...@@ -2459,16 +2471,31 @@ java_lang_expand_expr (exp, target, tmode, modifier)
{ {
tree local; tree local;
tree body = BLOCK_EXPR_BODY (exp); 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 */ pushlevel (2); /* 2 and above */
expand_start_bindings (0); expand_start_bindings (0);
local = BLOCK_EXPR_DECLS (exp); local = BLOCK_EXPR_DECLS (exp);
while (local) while (local)
{ {
tree next = TREE_CHAIN (local); tree next = TREE_CHAIN (local);
found_class_initialization_flag +=
LOCAL_CLASS_INITIALIZATION_FLAG_P (local);
layout_decl (local, 0); layout_decl (local, 0);
expand_decl (pushdecl (local)); expand_decl (pushdecl (local));
local = next; 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. */ /* Avoid deep recursion for long block. */
while (TREE_CODE (body) == COMPOUND_EXPR) while (TREE_CODE (body) == COMPOUND_EXPR)
{ {
...@@ -3335,3 +3362,37 @@ force_evaluation_order (node) ...@@ -3335,3 +3362,37 @@ force_evaluation_order (node)
} }
return 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 ...@@ -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 using JNI, then you must use @code{-fjni}. This option causes
@code{gcj} to generate stubs which will invoke the underlying JNI @code{gcj} to generate stubs which will invoke the underlying JNI
methods. 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 @end table
......
...@@ -186,6 +186,10 @@ extern int flag_hash_synchronization; ...@@ -186,6 +186,10 @@ extern int flag_hash_synchronization;
/* When non zero, generate checks for references to NULL. */ /* When non zero, generate checks for references to NULL. */
extern int flag_check_references; 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. */ /* Encoding used for source files. */
extern const char *current_encoding; extern const char *current_encoding;
...@@ -704,6 +708,16 @@ struct lang_identifier ...@@ -704,6 +708,16 @@ 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)
/* 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> /* The Number of Artificial Parameters (NAP) DECL contains. this$<n>
is excluded, because sometimes created as a parameter before the is excluded, because sometimes created as a parameter before the
function decl exists. */ function decl exists. */
...@@ -815,11 +829,18 @@ struct lang_identifier ...@@ -815,11 +829,18 @@ struct lang_identifier
(((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->local_final) (((struct lang_decl_var*)DECL_LANG_SPECIFIC(NODE))->local_final)
/* True if NODE is a local final. */ /* True if NODE is a local final. */
#define LOCAL_FINAL_P(NODE) (DECL_LANG_SPECIFIC (NODE) && LOCAL_FINAL (NODE)) #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)) #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) \ #define CLASS_FINAL_VARIABLE_P(NODE) \
(FIELD_FINAL (NODE) && FIELD_STATIC (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. */ /* Create a DECL_LANG_SPECIFIC if necessary. */
#define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T) \ #define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T) \
if (DECL_LANG_SPECIFIC (T) == NULL) \ if (DECL_LANG_SPECIFIC (T) == NULL) \
...@@ -858,6 +879,8 @@ struct lang_decl ...@@ -858,6 +879,8 @@ struct lang_decl
list of other constructor it calls */ list of other constructor it calls */
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 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 */
...@@ -888,6 +911,7 @@ struct lang_decl_var ...@@ -888,6 +911,7 @@ struct lang_decl_var
int final_liic : 1; /* Final locally initialized in ctors */ int final_liic : 1; /* Final locally initialized in ctors */
int final_ierr : 1; /* Initialization error already detected */ int final_ierr : 1; /* Initialization error already detected */
int local_final : 1; /* True if the decl is a local final */ 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'. */ /* Macro to access fields in `struct lang_type'. */
...@@ -1061,7 +1085,7 @@ extern void parse_error_context PARAMS ((tree cl, const char *, ...)) ...@@ -1061,7 +1085,7 @@ extern void parse_error_context PARAMS ((tree cl, const char *, ...))
extern tree build_primtype_type_ref PARAMS ((const char *)); extern tree build_primtype_type_ref PARAMS ((const char *));
extern void finish_class PARAMS ((void)); extern void finish_class PARAMS ((void));
extern void java_layout_seen_class_methods 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 tree pushdecl_top_level PARAMS ((tree));
extern int alloc_class_constant PARAMS ((tree)); extern int alloc_class_constant PARAMS ((tree));
...@@ -1129,6 +1153,8 @@ extern tree get_boehm_type_descriptor 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 unsigned long java_hash_hash_tree_node PARAMS ((hash_table_key));
extern bool java_hash_compare_tree_node PARAMS ((hash_table_key, extern bool java_hash_compare_tree_node PARAMS ((hash_table_key,
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 java_check_methods PARAMS ((tree));
extern void init_jcf_parse PARAMS((void)); extern void init_jcf_parse PARAMS((void));
extern void init_src_parse PARAMS((void)); extern void init_src_parse PARAMS((void));
...@@ -1559,6 +1585,10 @@ extern tree *type_map; ...@@ -1559,6 +1585,10 @@ extern tree *type_map;
(inherits_from_p ((TYPE), runtime_exception_type_node) \ (inherits_from_p ((TYPE), runtime_exception_type_node) \
|| inherits_from_p ((TYPE), error_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; \ extern int java_error_count; \
/* Make the current function where this macro is invoked report error /* Make the current function where this macro is invoked report error
......
...@@ -52,3 +52,5 @@ DEFINE_LANG_NAME ("Java") ...@@ -52,3 +52,5 @@ DEFINE_LANG_NAME ("Java")
N_("Warn if .class files are out of date") }, N_("Warn if .class files are out of date") },
{ "-fforce-classes-archive-check", { "-fforce-classes-archive-check",
N_("Always check for non gcj generated classes archives") }, 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; ...@@ -146,6 +146,10 @@ int flag_extraneous_semicolon;
/* When non zero, always check for a non gcj generated classes archive. */ /* When non zero, always check for a non gcj generated classes archive. */
int flag_force_classes_archive_check; 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. /* Table of language-dependent -f options.
STRING is the option name. VARIABLE is the address of the variable. STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE ON_VALUE is the value to store in VARIABLE
...@@ -295,6 +299,15 @@ java_decode_option (argc, argv) ...@@ -295,6 +299,15 @@ java_decode_option (argc, argv)
} }
#undef ARG #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') if (p[0] == '-' && p[1] == 'f')
{ {
/* Some kind of -f option. /* 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