Commit 85194ee9 by Andrew Haley Committed by Andrew Haley

re PR java/12755 (Binary Compatibility: Resolving static methods and classes is not thread safe)

2004-01-09  Andrew Haley  <aph@redhat.com>

	PR java/12755:
	* parse.y (java_fix_constructors):  Set output_class.
	(java_reorder_fields): Likewise.
	(java_layout_classes): Likewise.
	(java_expand_classes): Generate indirect dispatch tables.
	(java_expand_classes): Set output_class.
	(java_finish_classes): Likewise.
	* lang.c (java_init): Turn on always_initialize_class_p if we're
	using indirect dis[atch.
	(java_decl_ok_for_sibcall): Use output_class, not current_class.
	(java_get_callee_fndecl): Use class local atable.
	* jcf-parse.c
	(always_initialize_class_p): Decl moved to java-tree.h.
	(HANDLE_CLASS_INFO): Set output_class.
	(read_class): Likewise.
	(parse_class_file): Call gen_indirect_dispatch_tables.
	(parse_zip_file_entries): Set output_class.
	(java_parse_file): Set output_class.  Don't emit symbol tables.
	* java-tree.h (output_class): New.
	Remove global declarations for otable, atable, and ctable.
	(always_initialize_class_p): moved here from decl.c.
	(DECL_OWNER): New.
	(TYPE_ATABLE_METHODS, TYPE_ATABLE_SYMS_DECL, TYPE_ATABLE_DECL,
	TYPE_OTABLE_METHODS, TYPE_OTABLE_SYMS_DECL, TYPE_OTABLE_DECL,
	TYPE_CTABLE_DECL, TYPE_CATCH_CLASSES): New.
	(struct lang_type): Add otable_methods, otable_decl,
	otable_syms_decl, atable_methods, atable_decl, atable_syms_decl,
	ctable_decl, catch_classes, type_to_runtime_map.
	* expr.c (build_field_ref): Make otable, atable, and ctable class
	local rather than global.
	(build_known_method_ref): Likewise.
	(build_invokeinterface): Likewise.
	(java_expand_expr): Pass runtime type (rather than actual type) to
	expand_start_catch.
	* except.c (prepare_eh_table_type): Create TYPE_TO_RUNTIME_MAP for
	this class.  Look up each class in that map to delete duplicates.
	(expand_end_java_handler): Pass runtime type (rather than actual
	type) to expand_start_catch.
	* decl.c: (always_initialize_class_p): Decl moved to java-tree.h.
	(do_nothing): New.
	(java_init_decl_processing): Rearrange things.  Remove global
	declarations of otable, atable, and ctable.
	(java_init_decl_processing): Make lang_eh_runtime_type do_nothing.
	(java_expand_body): Set output_class.
	* constants.c (build_constant_data_ref): Use output_class, not
	current_class.
	(alloc_name_constant): Likewise.
	* class.c (gen_indirect_dispatch_tables): New.
	(build_class_ref): Generate hard reference to superclass, even if
	using indirect dispatch.
	(build_static_field_ref): Use class local atable.
	(make_class_data): Generate hard reference to superclass, even if
	using indirect dispatch.
	Generate symbolic references to interfaces when using indirect
	dispatch.
	(make_class_data): Emit otable, atable, and ctable.
	Make otable, atable, and ctable class local rather than global.
	(emit_catch_table): Make otable, atable, and ctable class local
	rather than global.

From-SVN: r75590
parent 900a35c8
2004-01-09 Andrew Haley <aph@redhat.com>
PR java/12755:
* parse.y (java_fix_constructors): Set output_class.
(java_reorder_fields): Likewise.
(java_layout_classes): Likewise.
(java_expand_classes): Generate indirect dispatch tables.
(java_expand_classes): Set output_class.
(java_finish_classes): Likewise.
* lang.c (java_init): Turn on always_initialize_class_p if we're
using indirect dis[atch.
(java_decl_ok_for_sibcall): Use output_class, not current_class.
(java_get_callee_fndecl): Use class local atable.
* jcf-parse.c
(always_initialize_class_p): Decl moved to java-tree.h.
(HANDLE_CLASS_INFO): Set output_class.
(read_class): Likewise.
(parse_class_file): Call gen_indirect_dispatch_tables.
(parse_zip_file_entries): Set output_class.
(java_parse_file): Set output_class. Don't emit symbol tables.
* java-tree.h (output_class): New.
Remove global declarations for otable, atable, and ctable.
(always_initialize_class_p): moved here from decl.c.
(DECL_OWNER): New.
(TYPE_ATABLE_METHODS, TYPE_ATABLE_SYMS_DECL, TYPE_ATABLE_DECL,
TYPE_OTABLE_METHODS, TYPE_OTABLE_SYMS_DECL, TYPE_OTABLE_DECL,
TYPE_CTABLE_DECL, TYPE_CATCH_CLASSES): New.
(struct lang_type): Add otable_methods, otable_decl,
otable_syms_decl, atable_methods, atable_decl, atable_syms_decl,
ctable_decl, catch_classes, type_to_runtime_map.
* expr.c (build_field_ref): Make otable, atable, and ctable class
local rather than global.
(build_known_method_ref): Likewise.
(build_invokeinterface): Likewise.
(java_expand_expr): Pass runtime type (rather than actual type) to
expand_start_catch.
* except.c (prepare_eh_table_type): Create TYPE_TO_RUNTIME_MAP for
this class. Look up each class in that map to delete duplicates.
(expand_end_java_handler): Pass runtime type (rather than actual
type) to expand_start_catch.
* decl.c: (always_initialize_class_p): Decl moved to java-tree.h.
(do_nothing): New.
(java_init_decl_processing): Rearrange things. Remove global
declarations of otable, atable, and ctable.
(java_init_decl_processing): Make lang_eh_runtime_type do_nothing.
(java_expand_body): Set output_class.
* constants.c (build_constant_data_ref): Use output_class, not
current_class.
(alloc_name_constant): Likewise.
* class.c (gen_indirect_dispatch_tables): New.
(build_class_ref): Generate hard reference to superclass, even if
using indirect dispatch.
(build_static_field_ref): Use class local atable.
(make_class_data): Generate hard reference to superclass, even if
using indirect dispatch.
Generate symbolic references to interfaces when using indirect
dispatch.
(make_class_data): Emit otable, atable, and ctable.
Make otable, atable, and ctable class local rather than global.
(emit_catch_table): Make otable, atable, and ctable class local
rather than global.
2003-12-25 Andrew Pinski <pinskia@physics.uc.edu>
* parse.y (catch_clause_parameter): Fix typo.
......
/* Handle the constant pool of the Java(TM) Virtual Machine.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
......@@ -351,7 +351,7 @@ cpool_for_class (tree class)
int
alloc_name_constant (int tag, tree name)
{
CPool *outgoing_cpool = cpool_for_class (current_class);
CPool *outgoing_cpool = cpool_for_class (output_class);
return find_tree_constant (outgoing_cpool, tag, name);
}
......@@ -393,19 +393,19 @@ build_constant_data_ref (void)
{
tree cpool_data_ref = NULL_TREE;
if (TYPE_CPOOL_DATA_REF (current_class))
cpool_data_ref = TYPE_CPOOL_DATA_REF (current_class);
if (TYPE_CPOOL_DATA_REF (output_class))
cpool_data_ref = TYPE_CPOOL_DATA_REF (output_class);
if (cpool_data_ref == NULL_TREE)
{
tree decl;
tree decl_name = mangled_classname ("_CD_", current_class);
tree decl_name = mangled_classname ("_CD_", output_class);
decl = build_decl (VAR_DECL, decl_name,
build_array_type (ptr_type_node,
one_elt_array_domain_type));
TREE_STATIC (decl) = 1;
make_decl_rtl (decl, NULL);
TYPE_CPOOL_DATA_REF (current_class) = cpool_data_ref
TYPE_CPOOL_DATA_REF (output_class) = cpool_data_ref
= build1 (ADDR_EXPR, ptr_type_node, decl);
}
return cpool_data_ref;
......
/* Process declarations and variables for the GNU compiler for the
Java(TM) language.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GCC.
......@@ -64,10 +64,6 @@ tree java_lang_cloneable_identifier_node;
/* Name of the Serializable class. */
tree java_io_serializable_identifier_node;
/* Set to nonzero value in order to emit class initialization code
before static field references. */
extern int always_initialize_class_p;
/* The DECL_MAP is a mapping from (index, type) to a decl node.
If index < max_locals, it is the index of a local variable.
if index >= max_locals, then index-max_locals is a stack slot.
......@@ -389,6 +385,13 @@ create_primitive_vtable (const char *name)
return r;
}
static tree
do_nothing (tree t)
{
return t;
}
void
java_init_decl_processing (void)
{
......@@ -538,6 +541,28 @@ java_init_decl_processing (void)
float_array_vtable = create_primitive_vtable ("float");
double_array_vtable = create_primitive_vtable ("double");
one_elt_array_domain_type = build_index_type (integer_one_node);
utf8const_type = make_node (RECORD_TYPE);
PUSH_FIELD (utf8const_type, field, "hash", unsigned_short_type_node);
PUSH_FIELD (utf8const_type, field, "length", unsigned_short_type_node);
FINISH_RECORD (utf8const_type);
utf8const_ptr_type = build_pointer_type (utf8const_type);
atable_type = build_array_type (ptr_type_node,
one_elt_array_domain_type);
TYPE_NONALIASED_COMPONENT (atable_type) = 1;
atable_ptr_type = build_pointer_type (atable_type);
symbol_type = make_node (RECORD_TYPE);
PUSH_FIELD (symbol_type, field, "clname", utf8const_ptr_type);
PUSH_FIELD (symbol_type, field, "name", utf8const_ptr_type);
PUSH_FIELD (symbol_type, field, "signature", utf8const_ptr_type);
FINISH_RECORD (symbol_type);
symbols_array_type = build_array_type (symbol_type,
one_elt_array_domain_type);
symbols_array_ptr_type = build_pointer_type (symbols_array_type);
/* As you're adding items here, please update the code right after
this section, so that the filename containing the source code of
the pre-defined class gets registered correctly. */
......@@ -595,12 +620,6 @@ java_init_decl_processing (void)
/* for lack of a better place to put this stub call */
init_expr_processing();
utf8const_type = make_node (RECORD_TYPE);
PUSH_FIELD (utf8const_type, field, "hash", unsigned_short_type_node);
PUSH_FIELD (utf8const_type, field, "length", unsigned_short_type_node);
FINISH_RECORD (utf8const_type);
utf8const_ptr_type = build_pointer_type (utf8const_type);
constants_type_node = make_node (RECORD_TYPE);
PUSH_FIELD (constants_type_node, field, "size", unsigned_int_type_node);
PUSH_FIELD (constants_type_node, field, "tags", ptr_type_node);
......@@ -613,69 +632,10 @@ java_init_decl_processing (void)
dtable_type = make_node (RECORD_TYPE);
dtable_ptr_type = build_pointer_type (dtable_type);
one_elt_array_domain_type = build_index_type (integer_one_node);
otable_type = build_array_type (integer_type_node,
one_elt_array_domain_type);
TYPE_NONALIASED_COMPONENT (otable_type) = 1;
otable_ptr_type = build_pointer_type (otable_type);
atable_type = build_array_type (ptr_type_node,
one_elt_array_domain_type);
TYPE_NONALIASED_COMPONENT (atable_type) = 1;
atable_ptr_type = build_pointer_type (atable_type);
symbol_type = make_node (RECORD_TYPE);
PUSH_FIELD (symbol_type, field, "clname", utf8const_ptr_type);
PUSH_FIELD (symbol_type, field, "name", utf8const_ptr_type);
PUSH_FIELD (symbol_type, field, "signature", utf8const_ptr_type);
FINISH_RECORD (symbol_type);
symbols_array_type = build_array_type (symbol_type,
one_elt_array_domain_type);
symbols_array_ptr_type = build_pointer_type (symbols_array_type);
if (flag_indirect_dispatch)
{
otable_decl = build_decl (VAR_DECL, get_identifier ("otable"), otable_type);
DECL_EXTERNAL (otable_decl) = 1;
TREE_STATIC (otable_decl) = 1;
TREE_READONLY (otable_decl) = 1;
TREE_CONSTANT (otable_decl) = 1;
pushdecl (otable_decl);
otable_syms_decl = build_decl (VAR_DECL, get_identifier ("otable_syms"),
symbols_array_type);
TREE_STATIC (otable_syms_decl) = 1;
TREE_CONSTANT (otable_syms_decl) = 1;
pushdecl (otable_syms_decl);
atable_decl = build_decl (VAR_DECL, get_identifier ("atable"), atable_type);
DECL_EXTERNAL (atable_decl) = 1;
TREE_STATIC (atable_decl) = 1;
TREE_READONLY (atable_decl) = 1;
TREE_CONSTANT (atable_decl) = 1;
pushdecl (atable_decl);
atable_syms_decl = build_decl (VAR_DECL, get_identifier ("atable_syms"),
symbols_array_type);
TREE_STATIC (atable_syms_decl) = 1;
TREE_CONSTANT (atable_syms_decl) = 1;
pushdecl (atable_syms_decl);
}
{
tree catch_class_type = make_node (RECORD_TYPE);
PUSH_FIELD (catch_class_type, field, "address", utf8const_ptr_type);
PUSH_FIELD (catch_class_type, field, "classname", ptr_type_node);
FINISH_RECORD (catch_class_type);
ctable_decl
= build_decl (VAR_DECL, get_identifier ("catch_classes"),
build_array_type
(catch_class_type, 0));
DECL_EXTERNAL (ctable_decl) = 1;
TREE_STATIC (ctable_decl) = 1;
TREE_READONLY (ctable_decl) = 1;
TREE_CONSTANT (ctable_decl) = 1;
pushdecl (ctable_decl);
}
PUSH_FIELD (object_type_node, field, "vtable", dtable_ptr_type);
/* This isn't exactly true, but it is what we have in the source.
......@@ -945,12 +905,12 @@ java_init_decl_processing (void)
eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
? "__gcj_personality_sj0"
: "__gcj_personality_v0");
lang_eh_runtime_type = prepare_eh_table_type;
lang_eh_runtime_type = do_nothing;
init_jcf_parse ();
initialize_builtins ();
soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
#if 0
soft_fmodf_node = built_in_decls[BUILT_IN_FMODF];
......@@ -1860,6 +1820,7 @@ java_expand_body (tree fndecl)
current_function_decl = fndecl;
input_location = DECL_SOURCE_LOCATION (fndecl);
output_class = DECL_CONTEXT (current_function_decl);
current_class = DECL_CONTEXT (fndecl);
timevar_push (TV_EXPAND);
......
/* Handle exceptions for GNU compiler for the Java(TM) language.
Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003
Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GCC.
......@@ -312,6 +312,7 @@ tree
prepare_eh_table_type (tree type)
{
tree exp;
tree *slot;
const char *name;
char *buf;
tree decl;
......@@ -324,8 +325,16 @@ prepare_eh_table_type (tree type)
* rewritten to point to the appropriate class. */
if (type == NULL_TREE)
exp = NULL_TREE;
else if (is_compiled_class (type) && !flag_indirect_dispatch)
return NULL_TREE;
if (TYPE_TO_RUNTIME_MAP (output_class) == NULL)
TYPE_TO_RUNTIME_MAP (output_class) = java_treetreehash_create (10, 1);
slot = java_treetreehash_new (TYPE_TO_RUNTIME_MAP (output_class), type);
if (*slot != NULL)
return TREE_VALUE (*slot);
if (is_compiled_class (type) && !flag_indirect_dispatch)
{
name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
buf = alloca (strlen (name) + 5);
......@@ -339,8 +348,6 @@ prepare_eh_table_type (tree type)
DECL_INITIAL (decl) = build_class_ref (type);
layout_decl (decl, 0);
pushdecl (decl);
rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0);
make_decl_rtl (decl, (char*) 0);
exp = build1 (ADDR_EXPR, ptr_type_node, decl);
}
else
......@@ -357,14 +364,37 @@ prepare_eh_table_type (tree type)
TREE_THIS_VOLATILE (decl) = 0;
layout_decl (decl, 0);
pushdecl (decl);
rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0);
make_decl_rtl (decl, (char*) 0);
exp = build1 (ADDR_EXPR, build_pointer_type (utf8const_ptr_type), decl);
catch_classes = tree_cons (NULL, make_catch_class_record (exp, utf8_ref), catch_classes);
TYPE_CATCH_CLASSES (output_class) =
tree_cons (NULL, make_catch_class_record (exp, utf8_ref),
TYPE_CATCH_CLASSES (output_class));
}
*slot = tree_cons (type, exp, NULL_TREE);
return exp;
}
static int
expand_catch_class (void **entry, void *x ATTRIBUTE_UNUSED)
{
struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry;
tree decl = TREE_OPERAND (TREE_VALUE ((tree)ite->value), 0);
rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0);
return true;
}
/* For every class in the TYPE_TO_RUNTIME_MAP, expand the
corresponding object that is used by the runtime type matcher. */
void
java_expand_catch_classes (tree this_class)
{
if (TYPE_TO_RUNTIME_MAP (this_class))
htab_traverse
(TYPE_TO_RUNTIME_MAP (this_class),
expand_catch_class, NULL);
}
/* Build a reference to the jthrowable object being carried in the
exception header. */
......@@ -404,7 +434,7 @@ expand_end_java_handler (struct eh_range *range)
if (type == NULL)
type = throwable_type_node;
expand_start_catch (type);
expand_start_catch (prepare_eh_table_type (type));
expand_goto (TREE_VALUE (handler));
expand_end_catch ();
}
......
/* Process expressions for the GNU compiler for the Java(TM) language.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GCC.
......@@ -1511,17 +1511,18 @@ build_field_ref (tree self_value, tree self_class, tree name)
if (base_type != TREE_TYPE (self_value))
self_value = fold (build1 (NOP_EXPR, base_type, self_value));
if (flag_indirect_dispatch
&& current_class != self_class)
/* FIXME: current_class != self_class is not exactly the right
&& output_class != self_class)
/* FIXME: output_class != self_class is not exactly the right
test. What we really want to know is whether self_class is
in the same translation unit as current_class. If it is,
in the same translation unit as output_class. If it is,
we can make a direct reference. */
{
tree otable_index
= build_int_2
(get_symbol_table_index (field_decl, &otable_methods), 0);
tree field_offset = build (ARRAY_REF, integer_type_node, otable_decl,
otable_index);
tree otable_index =
build_int_2 (get_symbol_table_index
(field_decl, &TYPE_OTABLE_METHODS (output_class)), 0);
tree field_offset =
build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class),
otable_index);
tree address
= fold (build (PLUS_EXPR,
build_pointer_type (TREE_TYPE (field_decl)),
......@@ -1771,10 +1772,12 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED,
}
else
{
tree table_index = build_int_2 (get_symbol_table_index
(method, &atable_methods), 0);
func = build (ARRAY_REF, method_ptr_type_node, atable_decl,
table_index);
tree table_index =
build_int_2 (get_symbol_table_index
(method, &TYPE_ATABLE_METHODS (output_class)), 0);
func =
build (ARRAY_REF, method_ptr_type_node,
TYPE_ATABLE_DECL (output_class), table_index);
}
}
else
......@@ -1893,8 +1896,10 @@ build_invokevirtual (tree dtable, tree method)
if (flag_indirect_dispatch)
{
otable_index
= build_int_2 (get_symbol_table_index (method, &otable_methods), 0);
method_index = build (ARRAY_REF, integer_type_node, otable_decl,
= build_int_2 (get_symbol_table_index
(method, &TYPE_OTABLE_METHODS (output_class)), 0);
method_index = build (ARRAY_REF, integer_type_node,
TYPE_OTABLE_DECL (output_class),
otable_index);
}
else
......@@ -1957,9 +1962,12 @@ build_invokeinterface (tree dtable, tree method)
if (flag_indirect_dispatch)
{
otable_index
= build_int_2 (get_symbol_table_index (method, &otable_methods), 0);
idx = build (ARRAY_REF, integer_type_node, otable_decl, otable_index);
otable_index =
build_int_2 (get_symbol_table_index
(method, &TYPE_OTABLE_METHODS (output_class)), 0);
idx =
build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class),
otable_index);
}
else
{
......@@ -2605,7 +2613,7 @@ java_expand_expr (tree exp, rtx target, enum machine_mode tmode,
tree decl = BLOCK_EXPR_DECLS (catch);
tree type = (decl ? TREE_TYPE (TREE_TYPE (decl)) : NULL_TREE);
expand_start_catch (type);
expand_start_catch (prepare_eh_table_type (type));
expand_expr_stmt (TREE_OPERAND (current, 0));
expand_end_catch ();
}
......
/* Definitions for parsing and type checking for the GNU compiler for
the Java(TM) language.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GCC.
......@@ -134,10 +134,17 @@ extern int compiling_from_source;
#define main_class \
java_global_trees[JTI_MAIN_CLASS]
/* The class we are currently processing. */
/* The class we use as the base for name resolution. It's usually the
class we're generating code for but sometimes it points to an inner
class. If you really want to know the class we're currently
generating code for, use output_class instead. */
#define current_class \
java_global_trees[JTI_CURRENT_CLASS]
/* The class we are currently generating. Really. */
#define output_class \
java_global_trees[JTI_OUTPUT_CLASS]
/* List of all class DECLs seen so far. */
#define all_class_list \
java_global_trees[JTI_ALL_CLASS_LIST]
......@@ -147,27 +154,13 @@ extern int compiling_from_source;
/* List of virtual decls referred to by this translation unit, used to
generate virtual method offset symbol table. */
#define otable_methods java_global_trees [JTI_OTABLE_METHODS]
/* List of static decls referred to by this translation unit, used to
generate virtual method offset symbol table. */
#define atable_methods java_global_trees [JTI_ATABLE_METHODS]
/* The virtual offset table. This is emitted as uninitialized data of
the required length, and filled out at run time during class
linking. */
#define otable_decl java_global_trees [JTI_OTABLE_DECL]
/* The static address table. */
#define atable_decl java_global_trees [JTI_ATABLE_DECL]
/* The virtual offset symbol table. Used by the runtime to fill out
the otable. */
#define otable_syms_decl java_global_trees [JTI_OTABLE_SYMS_DECL]
/* The static symbol table. Used by the runtime to fill out the
otable. */
#define atable_syms_decl java_global_trees [JTI_ATABLE_SYMS_DECL]
#define ctable_decl java_global_trees [JTI_CTABLE_DECL]
#define catch_classes java_global_trees [JTI_CATCH_CLASSES]
extern int flag_emit_class_files;
......@@ -244,6 +237,10 @@ extern const char *current_encoding;
/* The Java .class file that provides main_class; the main input file. */
extern GTY(()) struct JCF * current_jcf;
/* Set to nonzero value in order to emit class initialization code
before static field references. */
extern int always_initialize_class_p;
typedef struct CPool constant_pool;
#define CONSTANT_ResolvedFlag 16
......@@ -413,20 +410,10 @@ enum java_tree_index
JTI_MAIN_CLASS,
JTI_CURRENT_CLASS,
JTI_OUTPUT_CLASS,
JTI_ALL_CLASS_LIST,
JTI_ALL_CLASS_FILENAME,
JTI_OTABLE_METHODS,
JTI_OTABLE_DECL,
JTI_OTABLE_SYMS_DECL,
JTI_ATABLE_METHODS,
JTI_ATABLE_DECL,
JTI_ATABLE_SYMS_DECL,
JTI_CTABLE_DECL,
JTI_CATCH_CLASSES,
JTI_PREDEF_FILENAMES,
JTI_MAX
......@@ -923,6 +910,9 @@ union lang_tree_node
/* The original WFL of a final variable. */
#define DECL_FIELD_FINAL_WFL(NODE) \
(DECL_LANG_SPECIFIC(NODE)->u.v.wfl)
/* The class that's the owner of a dynamic binding table. */
#define DECL_OWNER(NODE) \
(DECL_LANG_SPECIFIC(NODE)->u.v.owner)
/* True if NODE is a local variable final. */
#define LOCAL_FINAL_P(NODE) (DECL_LANG_SPECIFIC (NODE) && DECL_FINAL (NODE))
/* True if NODE is a final field. */
......@@ -1022,6 +1012,7 @@ struct lang_decl_var GTY(())
tree slot_chain;
tree am; /* Access method for this field (1.1) */
tree wfl; /* Original wfl */
tree owner;
unsigned int final_iud : 1; /* Final initialized upon declaration */
unsigned int cif : 1; /* True: decl is a class initialization flag */
unsigned int freed; /* Decl is no longer in scope. */
......@@ -1070,6 +1061,19 @@ struct lang_decl GTY(())
#define TYPE_STRICTFP(T) (TYPE_LANG_SPECIFIC(T)->strictfp)
#define TYPE_USES_ASSERTIONS(T) (TYPE_LANG_SPECIFIC(T)->assertions)
#define TYPE_ATABLE_METHODS(T) (TYPE_LANG_SPECIFIC(T)->atable_methods)
#define TYPE_ATABLE_SYMS_DECL(T) (TYPE_LANG_SPECIFIC(T)->atable_syms_decl)
#define TYPE_ATABLE_DECL(T) (TYPE_LANG_SPECIFIC(T)->atable_decl)
#define TYPE_OTABLE_METHODS(T) (TYPE_LANG_SPECIFIC(T)->otable_methods)
#define TYPE_OTABLE_SYMS_DECL(T) (TYPE_LANG_SPECIFIC(T)->otable_syms_decl)
#define TYPE_OTABLE_DECL(T) (TYPE_LANG_SPECIFIC(T)->otable_decl)
#define TYPE_CTABLE_DECL(T) (TYPE_LANG_SPECIFIC(T)->ctable_decl)
#define TYPE_CATCH_CLASSES(T) (TYPE_LANG_SPECIFIC(T)->catch_classes)
#define TYPE_TO_RUNTIME_MAP(T) (TYPE_LANG_SPECIFIC(T)->type_to_runtime_map)
struct lang_type GTY(())
{
tree signature;
......@@ -1086,6 +1090,21 @@ struct lang_type GTY(())
tree package_list; /* List of package names, progressive */
tree import_list; /* Imported types, in the CU of this class */
tree import_demand_list; /* Imported types, in the CU of this class */
tree otable_methods; /* List of static decls referred to by this class. */
tree otable_decl; /* The static address table. */
tree otable_syms_decl;
tree atable_methods; /* List of static decls referred to by this class. */
tree atable_decl; /* The static address table. */
tree atable_syms_decl;
tree ctable_decl; /* The table of classes for the runtime type matcher. */
tree catch_classes;
htab_t GTY ((param_is (struct treetreehash_entry))) type_to_runtime_map;
/* The mapping of classes to exception region markers. */
unsigned pic:1; /* Private Inner Class. */
unsigned poic:1; /* Protected Inner Class. */
unsigned strictfp:1; /* `strictfp' class. */
......@@ -1200,6 +1219,7 @@ extern tree build_instanceof (tree, tree);
extern tree create_label_decl (tree);
extern void push_labeled_block (tree);
extern tree prepare_eh_table_type (tree);
extern void java_expand_catch_classes (tree);
extern tree build_exception_object_ref (tree);
extern tree generate_name (void);
extern void pop_labeled_block (void);
......@@ -1322,7 +1342,9 @@ extern void java_expand_body (tree);
extern int get_symbol_table_index (tree, tree *);
extern tree make_catch_class_record (tree, tree);
extern void emit_catch_table (void);
extern tree emit_catch_table (tree);
extern void gen_indirect_dispatch_tables (tree type);
#define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
......
/* Parser for Java(TM) .class files.
Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003
Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GCC.
......@@ -72,10 +72,6 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
extern struct obstack temporary_obstack;
/* Set to nonzero value in order to emit class initialization code
before static field references. */
extern int always_initialize_class_p;
static GTY(()) tree parse_roots[3];
/* The FIELD_DECL for the current field. */
......@@ -153,7 +149,7 @@ set_source_filename (JCF *jcf, int index)
#define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
{ tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \
current_class = give_name_to_class (jcf, THIS); \
output_class = current_class = give_name_to_class (jcf, THIS); \
set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);}
#define HANDLE_CLASS_INTERFACE(INDEX) \
......@@ -509,7 +505,7 @@ read_class (tree name)
wfl_operator = build_expr_wfl (NULL_TREE, NULL, 0, 0);
EXPR_WFL_FILENAME_NODE (wfl_operator) = file;
input_filename = ggc_strdup (filename);
current_class = NULL_TREE;
output_class = current_class = NULL_TREE;
current_function_decl = NULL_TREE;
if (!HAS_BEEN_ALREADY_PARSED_P (file))
{
......@@ -531,7 +527,7 @@ read_class (tree name)
{
java_parser_context_save_global ();
java_push_parser_context ();
current_class = class;
output_class = current_class = class;
input_filename = current_jcf->filename;
if (JCF_SEEN_IN_ZIP (current_jcf))
read_zip_member(current_jcf,
......@@ -549,7 +545,7 @@ read_class (tree name)
load_inner_classes (class);
}
current_class = save_current_class;
output_class = current_class = save_current_class;
input_location = save_location;
current_jcf = save_current_jcf;
return 1;
......@@ -709,6 +705,8 @@ parse_class_file (void)
compiling from class files. */
always_initialize_class_p = 1;
gen_indirect_dispatch_tables (current_class);
java_mark_class_local (current_class);
for (method = TYPE_METHODS (current_class);
......@@ -1099,7 +1097,7 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
input_filename = IDENTIFIER_POINTER (TREE_VALUE (node));
if (CLASS_FILE_P (node))
{
current_class = TREE_PURPOSE (node);
output_class = current_class = TREE_PURPOSE (node);
current_jcf = TYPE_JCF (current_class);
layout_class (current_class);
load_inner_classes (current_class);
......@@ -1119,18 +1117,6 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
/* Emit the .jcf section. */
emit_register_classes ();
if (flag_indirect_dispatch)
{
otable_decl
= emit_symbol_table
(get_identifier ("otable"),
otable_decl, otable_methods, otable_syms_decl, integer_type_node);
atable_decl
= emit_symbol_table
(get_identifier ("atable"),
atable_decl, atable_methods, atable_syms_decl, ptr_type_node);
}
emit_catch_table ();
}
write_resource_constructor ();
......@@ -1201,7 +1187,7 @@ parse_zip_file_entries (void)
class = lookup_class (get_identifier (class_name));
FREE (class_name);
current_jcf = TYPE_JCF (class);
current_class = class;
output_class = current_class = class;
if (! CLASS_LOADED_P (class))
{
......
/* Java(TM) language-specific utility routines.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GCC.
......@@ -464,6 +464,11 @@ java_init (void)
if (flag_inline_functions)
flag_inline_trees = 1;
/* FIXME: Indirect dispatch isn't yet compatible with static class
init optimization. */
if (flag_indirect_dispatch)
always_initialize_class_p = true;
/* Force minimum function alignment if g++ uses the least significant
bit of function pointers to store the virtual bit. This is required
to keep vtables compatible. */
......@@ -967,11 +972,9 @@ inline_init_test_initialization (void **entry, void *x)
(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;
}
......@@ -1102,7 +1105,7 @@ java_dump_tree (void *dump_info, tree t)
static bool
java_decl_ok_for_sibcall (tree decl)
{
return decl != NULL && DECL_CONTEXT (decl) == current_class;
return decl != NULL && DECL_CONTEXT (decl) == output_class;
}
/* Used by estimate_num_insns. Estimate number of instructions seen
......@@ -1228,7 +1231,7 @@ java_start_inlining (tree fn)
static tree
java_get_callee_fndecl (tree call_expr)
{
tree method, table, element;
tree method, table, element, atable_methods;
HOST_WIDE_INT index;
......@@ -1239,10 +1242,14 @@ java_get_callee_fndecl (tree call_expr)
if (TREE_CODE (method) != ARRAY_REF)
return NULL;
table = TREE_OPERAND (method, 0);
if (table != atable_decl)
if (! DECL_LANG_SPECIFIC(table)
|| !DECL_OWNER (table)
|| TYPE_ATABLE_DECL (DECL_OWNER (table)) != table)
return NULL;
index = TREE_INT_CST_LOW (TREE_OPERAND (method, 1));
atable_methods = TYPE_ATABLE_METHODS (DECL_OWNER (table));
index = TREE_INT_CST_LOW (TREE_OPERAND (method, 1));
/* FIXME: Replace this for loop with a hash table lookup. */
for (element = atable_methods; element; element = TREE_CHAIN (element))
{
......@@ -1257,7 +1264,7 @@ java_get_callee_fndecl (tree call_expr)
}
--index;
}
return NULL;
}
......
/* Source code parsing and tree node generation for the GNU compiler
for the Java(TM) language.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
......@@ -5451,7 +5451,7 @@ java_fix_constructors (void)
if (CLASS_INTERFACE (TYPE_NAME (class_type)))
continue;
current_class = class_type;
output_class = current_class = class_type;
for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
{
if (DECL_CONSTRUCTOR_P (decl))
......@@ -7575,7 +7575,7 @@ java_reorder_fields (void)
for (current = gclass_list; current; current = TREE_CHAIN (current))
{
current_class = TREE_TYPE (TREE_VALUE (current));
output_class = current_class = TREE_TYPE (TREE_VALUE (current));
if (current_class == stop_reordering)
break;
......@@ -7632,7 +7632,7 @@ java_layout_classes (void)
for (current = gclass_list; current; current = TREE_CHAIN (current))
{
current_class = TREE_TYPE (TREE_VALUE (current));
output_class = current_class = TREE_TYPE (TREE_VALUE (current));
layout_class (current_class);
/* Error reported by the caller */
......@@ -7696,7 +7696,7 @@ java_complete_expand_methods (tree class_decl)
{
tree clinit, decl, first_decl;
current_class = TREE_TYPE (class_decl);
output_class = current_class = TREE_TYPE (class_decl);
/* Pre-expand <clinit> to figure whether we really need it or
not. If we do need it, we pre-expand the static fields so they're
......@@ -9017,6 +9017,15 @@ java_expand_classes (void)
for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
{
tree current;
for (current = cur_ctxp->class_list;
current;
current = TREE_CHAIN (current))
gen_indirect_dispatch_tables (TREE_TYPE (current));
}
for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next)
{
ctxp = cur_ctxp;
input_filename = ctxp->filename;
lang_init_source (2); /* Error msgs have method prototypes */
......@@ -9025,7 +9034,6 @@ java_expand_classes (void)
}
input_filename = main_input_filename;
/* Find anonymous classes and expand their constructor. This extra pass is
necessary because the constructor itself is only generated when the
method in which it is defined is expanded. */
......@@ -9035,7 +9043,7 @@ java_expand_classes (void)
ctxp = cur_ctxp;
for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
{
current_class = TREE_TYPE (current);
output_class = current_class = TREE_TYPE (current);
if (ANONYMOUS_CLASS_P (current_class))
{
tree d;
......@@ -9063,7 +9071,7 @@ java_expand_classes (void)
for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
{
tree d;
current_class = TREE_TYPE (current);
output_class = current_class = TREE_TYPE (current);
for (d = TYPE_METHODS (current_class); d; d = TREE_CHAIN (d))
{
if (DECL_RESULT (d) == NULL_TREE)
......@@ -9094,7 +9102,7 @@ java_expand_classes (void)
for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
{
tree d;
current_class = TREE_TYPE (current);
output_class = current_class = TREE_TYPE (current);
for (d = TYPE_METHODS (current_class); d; d = TREE_CHAIN (d))
{
if (DECL_RESULT (d) == NULL_TREE)
......@@ -9159,7 +9167,7 @@ java_expand_classes (void)
current;
current = TREE_CHAIN (current))
{
current_class = TREE_TYPE (TREE_VALUE (current));
output_class = current_class = TREE_TYPE (TREE_VALUE (current));
if (flag_emit_class_files)
write_classfile (current_class);
if (flag_emit_xref)
......@@ -9180,7 +9188,7 @@ java_finish_classes (void)
ctxp = cur_ctxp;
for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
{
current_class = TREE_TYPE (current);
output_class = current_class = TREE_TYPE (current);
finish_class ();
}
}
......
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