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> 2003-12-25 Andrew Pinski <pinskia@physics.uc.edu>
* parse.y (catch_clause_parameter): Fix typo. * parse.y (catch_clause_parameter): Fix typo.
......
/* Functions related to building classes and their related objects. /* Functions related to building classes and their related objects.
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. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -42,6 +42,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ ...@@ -42,6 +42,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "ggc.h" #include "ggc.h"
#include "stdio.h" #include "stdio.h"
#include "target.h" #include "target.h"
#include "except.h"
/* DOS brain-damage */ /* DOS brain-damage */
#ifndef O_BINARY #ifndef O_BINARY
...@@ -304,6 +305,83 @@ unmangle_classname (const char *name, int name_length) ...@@ -304,6 +305,83 @@ unmangle_classname (const char *name, int name_length)
return to_return; return to_return;
} }
/* Given a class, create the DECLs for all its associated indirect dispatch tables. */
void
gen_indirect_dispatch_tables (tree type)
{
const char *typename = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
{
tree field = NULL;
char *buf = alloca (strlen (typename) + strlen ("_catch_classes_"));
tree catch_class_type = make_node (RECORD_TYPE);
sprintf (buf, "_catch_classes_%s", typename);
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);
TYPE_CTABLE_DECL (type)
= build_decl (VAR_DECL, get_identifier (buf),
build_array_type (catch_class_type, 0));
DECL_EXTERNAL (TYPE_CTABLE_DECL (type)) = 1;
TREE_STATIC (TYPE_CTABLE_DECL (type)) = 1;
TREE_READONLY (TYPE_CTABLE_DECL (type)) = 1;
TREE_CONSTANT (TYPE_CTABLE_DECL (type)) = 1;
DECL_IGNORED_P (TYPE_CTABLE_DECL (type)) = 1;
pushdecl (TYPE_CTABLE_DECL (type));
}
if (flag_indirect_dispatch)
{
{
char *buf = alloca (strlen (typename) + strlen ("_otable_syms_"));
sprintf (buf, "_otable_%s", typename);
TYPE_OTABLE_DECL (type) =
build_decl (VAR_DECL, get_identifier (buf), otable_type);
DECL_EXTERNAL (TYPE_OTABLE_DECL (type)) = 1;
TREE_STATIC (TYPE_OTABLE_DECL (type)) = 1;
TREE_READONLY (TYPE_OTABLE_DECL (type)) = 1;
TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1;
DECL_IGNORED_P (TYPE_OTABLE_DECL (type)) = 1;
pushdecl (TYPE_OTABLE_DECL (type));
sprintf (buf, "_otable_syms_%s", typename);
TYPE_OTABLE_SYMS_DECL (type) =
build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);
TREE_STATIC (TYPE_OTABLE_SYMS_DECL (type)) = 1;
TREE_CONSTANT (TYPE_OTABLE_SYMS_DECL (type)) = 1;
DECL_IGNORED_P(TYPE_OTABLE_SYMS_DECL (type)) = 1;
pushdecl (TYPE_OTABLE_SYMS_DECL (type));
}
{
char *buf = alloca (strlen (typename) + strlen ("_atable_syms_"));
tree decl;
sprintf (buf, "_atable_%s", typename);
TYPE_ATABLE_DECL (type) = decl =
build_decl (VAR_DECL, get_identifier (buf), atable_type);
DECL_EXTERNAL (decl) = 1;
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
TREE_CONSTANT (decl) = 1;
DECL_IGNORED_P (decl) = 1;
/* Mark the atable as belonging to this class. */
pushdecl (decl);
MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
DECL_OWNER (decl) = type;
sprintf (buf, "_atable_syms_%s", typename);
TYPE_ATABLE_SYMS_DECL (type) =
build_decl (VAR_DECL, get_identifier (buf), symbols_array_type);
TREE_STATIC (TYPE_ATABLE_SYMS_DECL (type)) = 1;
TREE_CONSTANT (TYPE_ATABLE_SYMS_DECL (type)) = 1;
DECL_IGNORED_P (TYPE_ATABLE_SYMS_DECL (type)) = 1;
pushdecl (TYPE_ATABLE_SYMS_DECL (type));
}
}
}
tree tree
push_class (tree class_type, tree class_name) push_class (tree class_type, tree class_name)
{ {
...@@ -835,8 +913,13 @@ build_class_ref (tree type) ...@@ -835,8 +913,13 @@ build_class_ref (tree type)
if (TREE_CODE (type) == POINTER_TYPE) if (TREE_CODE (type) == POINTER_TYPE)
type = TREE_TYPE (type); type = TREE_TYPE (type);
if (flag_indirect_dispatch /* FIXME: we really want an indirect reference to our
&& type != current_class superclass. However, libgcj assumes that a superclass
pointer always points directly to a class. As a workaround
we always emit this hard superclass reference. */
if (flag_indirect_dispatch
&& type != output_class
&& type != CLASSTYPE_SUPER (output_class)
&& TREE_CODE (type) == RECORD_TYPE) && TREE_CODE (type) == RECORD_TYPE)
return build_indirect_class_ref (type); return build_indirect_class_ref (type);
...@@ -957,10 +1040,11 @@ build_static_field_ref (tree fdecl) ...@@ -957,10 +1040,11 @@ build_static_field_ref (tree fdecl)
if (flag_indirect_dispatch) if (flag_indirect_dispatch)
{ {
tree table_index tree table_index
= build_int_2 (get_symbol_table_index (fdecl, &atable_methods), 0); = build_int_2 (get_symbol_table_index
(fdecl, &TYPE_ATABLE_METHODS (output_class)), 0);
tree field_address tree field_address
= build (ARRAY_REF, build_pointer_type (TREE_TYPE (fdecl)), = build (ARRAY_REF, build_pointer_type (TREE_TYPE (fdecl)),
atable_decl, table_index); TYPE_ATABLE_DECL (output_class), table_index);
return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl), return fold (build1 (INDIRECT_REF, TREE_TYPE (fdecl),
field_address)); field_address));
} }
...@@ -1435,8 +1519,10 @@ make_class_data (tree type) ...@@ -1435,8 +1519,10 @@ make_class_data (tree type)
super = CLASSTYPE_SUPER (type); super = CLASSTYPE_SUPER (type);
if (super == NULL_TREE) if (super == NULL_TREE)
super = null_pointer_node; super = null_pointer_node;
else if (! flag_indirect_dispatch else if (/* FIXME: we should also test for (!
&& assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl))) flag_indirect_dispatch) here, but libgcj can't cope with
a symbolic reference a superclass in the class data. */
assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl)))
&& assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (super))))) && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (super)))))
super = build_class_ref (super); super = build_class_ref (super);
else else
...@@ -1463,13 +1549,15 @@ make_class_data (tree type) ...@@ -1463,13 +1549,15 @@ make_class_data (tree type)
tree child = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), i); tree child = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), i);
tree iclass = BINFO_TYPE (child); tree iclass = BINFO_TYPE (child);
tree index; tree index;
if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (iclass))))) if (! flag_indirect_dispatch
&& (assume_compiled
(IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (iclass))))))
index = build_class_ref (iclass); index = build_class_ref (iclass);
else else
{ {
int int_index = alloc_class_constant (iclass); int int_index = alloc_class_constant (iclass);
index = build_int_2 (int_index, 0); index = build_int_2 (int_index, 0);
TREE_TYPE (index) = ptr_type_node; TREE_TYPE (index) = ptr_type_node;
} }
init = tree_cons (NULL_TREE, index, init); init = tree_cons (NULL_TREE, index, init);
} }
...@@ -1483,6 +1571,23 @@ make_class_data (tree type) ...@@ -1483,6 +1571,23 @@ make_class_data (tree type)
constant_pool_constructor = build_constants_constructor (); constant_pool_constructor = build_constants_constructor ();
if (flag_indirect_dispatch)
{
TYPE_OTABLE_DECL (type)
= emit_symbol_table
(DECL_NAME (TYPE_OTABLE_DECL (type)),
TYPE_OTABLE_DECL (type), TYPE_OTABLE_METHODS (type),
TYPE_OTABLE_SYMS_DECL (type), integer_type_node);
TYPE_ATABLE_DECL (type)
= emit_symbol_table
(DECL_NAME (TYPE_ATABLE_DECL (type)),
TYPE_ATABLE_DECL (type), TYPE_ATABLE_METHODS (type),
TYPE_ATABLE_SYMS_DECL (type), ptr_type_node);
}
TYPE_CTABLE_DECL (type) = emit_catch_table (type);
START_RECORD_CONSTRUCTOR (temp, object_type_node); START_RECORD_CONSTRUCTOR (temp, object_type_node);
PUSH_FIELD_VALUE (temp, "vtable", PUSH_FIELD_VALUE (temp, "vtable",
build (PLUS_EXPR, dtable_ptr_type, build (PLUS_EXPR, dtable_ptr_type,
...@@ -1526,7 +1631,7 @@ make_class_data (tree type) ...@@ -1526,7 +1631,7 @@ make_class_data (tree type)
: build (PLUS_EXPR, dtable_ptr_type, : build (PLUS_EXPR, dtable_ptr_type,
build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl), build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl),
dtable_start_offset)); dtable_start_offset));
if (otable_methods == NULL_TREE) if (TYPE_OTABLE_METHODS (type) == NULL_TREE)
{ {
PUSH_FIELD_VALUE (cons, "otable", null_pointer_node); PUSH_FIELD_VALUE (cons, "otable", null_pointer_node);
PUSH_FIELD_VALUE (cons, "otable_syms", null_pointer_node); PUSH_FIELD_VALUE (cons, "otable_syms", null_pointer_node);
...@@ -1534,13 +1639,13 @@ make_class_data (tree type) ...@@ -1534,13 +1639,13 @@ make_class_data (tree type)
else else
{ {
PUSH_FIELD_VALUE (cons, "otable", PUSH_FIELD_VALUE (cons, "otable",
build1 (ADDR_EXPR, otable_ptr_type, otable_decl)); build1 (ADDR_EXPR, otable_ptr_type, TYPE_OTABLE_DECL (type)));
PUSH_FIELD_VALUE (cons, "otable_syms", PUSH_FIELD_VALUE (cons, "otable_syms",
build1 (ADDR_EXPR, symbols_array_ptr_type, build1 (ADDR_EXPR, symbols_array_ptr_type,
otable_syms_decl)); TYPE_OTABLE_SYMS_DECL (type)));
TREE_CONSTANT (otable_decl) = 1; TREE_CONSTANT (TYPE_OTABLE_DECL (type)) = 1;
} }
if (atable_methods == NULL_TREE) if (TYPE_ATABLE_METHODS(type) == NULL_TREE)
{ {
PUSH_FIELD_VALUE (cons, "atable", null_pointer_node); PUSH_FIELD_VALUE (cons, "atable", null_pointer_node);
PUSH_FIELD_VALUE (cons, "atable_syms", null_pointer_node); PUSH_FIELD_VALUE (cons, "atable_syms", null_pointer_node);
...@@ -1548,15 +1653,15 @@ make_class_data (tree type) ...@@ -1548,15 +1653,15 @@ make_class_data (tree type)
else else
{ {
PUSH_FIELD_VALUE (cons, "atable", PUSH_FIELD_VALUE (cons, "atable",
build1 (ADDR_EXPR, atable_ptr_type, atable_decl)); build1 (ADDR_EXPR, atable_ptr_type, TYPE_ATABLE_DECL (type)));
PUSH_FIELD_VALUE (cons, "atable_syms", PUSH_FIELD_VALUE (cons, "atable_syms",
build1 (ADDR_EXPR, symbols_array_ptr_type, build1 (ADDR_EXPR, symbols_array_ptr_type,
atable_syms_decl)); TYPE_ATABLE_SYMS_DECL (type)));
TREE_CONSTANT (atable_decl) = 1; TREE_CONSTANT (TYPE_ATABLE_DECL (type)) = 1;
} }
PUSH_FIELD_VALUE (cons, "catch_classes", PUSH_FIELD_VALUE (cons, "catch_classes",
build1 (ADDR_EXPR, ptr_type_node, ctable_decl)); build1 (ADDR_EXPR, ptr_type_node, TYPE_CTABLE_DECL (type)));
PUSH_FIELD_VALUE (cons, "interfaces", interfaces); PUSH_FIELD_VALUE (cons, "interfaces", interfaces);
PUSH_FIELD_VALUE (cons, "loader", null_pointer_node); PUSH_FIELD_VALUE (cons, "loader", null_pointer_node);
PUSH_FIELD_VALUE (cons, "interface_count", build_int_2 (interface_len, 0)); PUSH_FIELD_VALUE (cons, "interface_count", build_int_2 (interface_len, 0));
...@@ -1616,6 +1721,8 @@ finish_class (void) ...@@ -1616,6 +1721,8 @@ finish_class (void)
method = TREE_CHAIN (method); method = TREE_CHAIN (method);
} }
java_expand_catch_classes (current_class);
current_function_decl = NULL_TREE; current_function_decl = NULL_TREE;
make_class_data (current_class); make_class_data (current_class);
register_class (); register_class ();
...@@ -2231,7 +2338,7 @@ tree ...@@ -2231,7 +2338,7 @@ tree
make_catch_class_record (tree catch_class, tree classname) make_catch_class_record (tree catch_class, tree classname)
{ {
tree entry; tree entry;
tree type = TREE_TYPE (TREE_TYPE (ctable_decl)); tree type = TREE_TYPE (TREE_TYPE (TYPE_CTABLE_DECL (output_class)));
START_RECORD_CONSTRUCTOR (entry, type); START_RECORD_CONSTRUCTOR (entry, type);
PUSH_FIELD_VALUE (entry, "address", catch_class); PUSH_FIELD_VALUE (entry, "address", catch_class);
PUSH_FIELD_VALUE (entry, "classname", classname); PUSH_FIELD_VALUE (entry, "classname", classname);
...@@ -2241,29 +2348,35 @@ make_catch_class_record (tree catch_class, tree classname) ...@@ -2241,29 +2348,35 @@ make_catch_class_record (tree catch_class, tree classname)
/* Generate the list of Throwable classes that are caught by exception /* Generate the list of Throwable classes that are caught by exception
handlers in this compilation. */ handlers in this class. */
void tree
emit_catch_table (void) emit_catch_table (tree this_class)
{ {
tree table, table_size, array_type; tree table, table_size, array_type;
catch_classes TYPE_CATCH_CLASSES (this_class) =
= tree_cons (NULL, tree_cons (NULL,
make_catch_class_record (null_pointer_node, null_pointer_node), make_catch_class_record (null_pointer_node, null_pointer_node),
catch_classes); TYPE_CATCH_CLASSES (this_class));
catch_classes = nreverse (catch_classes); TYPE_CATCH_CLASSES (this_class) = nreverse (TYPE_CATCH_CLASSES (this_class));
catch_classes TYPE_CATCH_CLASSES (this_class) =
= tree_cons (NULL, tree_cons (NULL,
make_catch_class_record (null_pointer_node, null_pointer_node), make_catch_class_record (null_pointer_node, null_pointer_node),
catch_classes); TYPE_CATCH_CLASSES (this_class));
table_size = build_index_type (build_int_2 (list_length (catch_classes), 0)); table_size =
build_index_type (build_int_2
(list_length (TYPE_CATCH_CLASSES (this_class)), 0));
array_type array_type
= build_array_type (TREE_TYPE (TREE_TYPE (ctable_decl)), table_size); = build_array_type (TREE_TYPE (TREE_TYPE (TYPE_CTABLE_DECL (this_class))),
table = build_decl (VAR_DECL, DECL_NAME (ctable_decl), array_type); table_size);
DECL_INITIAL (table) = build_constructor (array_type, catch_classes); table =
build_decl (VAR_DECL, DECL_NAME (TYPE_CTABLE_DECL (this_class)), array_type);
DECL_INITIAL (table) =
build_constructor (array_type, TYPE_CATCH_CLASSES (this_class));
TREE_STATIC (table) = 1; TREE_STATIC (table) = 1;
TREE_READONLY (table) = 1; TREE_READONLY (table) = 1;
DECL_IGNORED_P (table) = 1;
rest_of_decl_compilation (table, NULL, 1, 0); rest_of_decl_compilation (table, NULL, 1, 0);
ctable_decl = table; return table;
} }
......
/* Handle the constant pool of the Java(TM) Virtual Machine. /* 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. This file is part of GCC.
...@@ -351,7 +351,7 @@ cpool_for_class (tree class) ...@@ -351,7 +351,7 @@ cpool_for_class (tree class)
int int
alloc_name_constant (int tag, tree name) 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); return find_tree_constant (outgoing_cpool, tag, name);
} }
...@@ -393,19 +393,19 @@ build_constant_data_ref (void) ...@@ -393,19 +393,19 @@ build_constant_data_ref (void)
{ {
tree cpool_data_ref = NULL_TREE; tree cpool_data_ref = NULL_TREE;
if (TYPE_CPOOL_DATA_REF (current_class)) if (TYPE_CPOOL_DATA_REF (output_class))
cpool_data_ref = TYPE_CPOOL_DATA_REF (current_class); cpool_data_ref = TYPE_CPOOL_DATA_REF (output_class);
if (cpool_data_ref == NULL_TREE) if (cpool_data_ref == NULL_TREE)
{ {
tree decl; 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, decl = build_decl (VAR_DECL, decl_name,
build_array_type (ptr_type_node, build_array_type (ptr_type_node,
one_elt_array_domain_type)); one_elt_array_domain_type));
TREE_STATIC (decl) = 1; TREE_STATIC (decl) = 1;
make_decl_rtl (decl, NULL); 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); = build1 (ADDR_EXPR, ptr_type_node, decl);
} }
return cpool_data_ref; return cpool_data_ref;
......
/* Process declarations and variables for the GNU compiler for the /* Process declarations and variables for the GNU compiler for the
Java(TM) language. 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. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -64,10 +64,6 @@ tree java_lang_cloneable_identifier_node; ...@@ -64,10 +64,6 @@ tree java_lang_cloneable_identifier_node;
/* Name of the Serializable class. */ /* Name of the Serializable class. */
tree java_io_serializable_identifier_node; 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. /* 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, it is the index of a local variable.
if index >= max_locals, then index-max_locals is a stack slot. if index >= max_locals, then index-max_locals is a stack slot.
...@@ -389,6 +385,13 @@ create_primitive_vtable (const char *name) ...@@ -389,6 +385,13 @@ create_primitive_vtable (const char *name)
return r; return r;
} }
static tree
do_nothing (tree t)
{
return t;
}
void void
java_init_decl_processing (void) java_init_decl_processing (void)
{ {
...@@ -538,6 +541,28 @@ java_init_decl_processing (void) ...@@ -538,6 +541,28 @@ java_init_decl_processing (void)
float_array_vtable = create_primitive_vtable ("float"); float_array_vtable = create_primitive_vtable ("float");
double_array_vtable = create_primitive_vtable ("double"); 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 /* As you're adding items here, please update the code right after
this section, so that the filename containing the source code of this section, so that the filename containing the source code of
the pre-defined class gets registered correctly. */ the pre-defined class gets registered correctly. */
...@@ -595,12 +620,6 @@ java_init_decl_processing (void) ...@@ -595,12 +620,6 @@ java_init_decl_processing (void)
/* for lack of a better place to put this stub call */ /* for lack of a better place to put this stub call */
init_expr_processing(); 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); constants_type_node = make_node (RECORD_TYPE);
PUSH_FIELD (constants_type_node, field, "size", unsigned_int_type_node); PUSH_FIELD (constants_type_node, field, "size", unsigned_int_type_node);
PUSH_FIELD (constants_type_node, field, "tags", ptr_type_node); PUSH_FIELD (constants_type_node, field, "tags", ptr_type_node);
...@@ -613,69 +632,10 @@ java_init_decl_processing (void) ...@@ -613,69 +632,10 @@ java_init_decl_processing (void)
dtable_type = make_node (RECORD_TYPE); dtable_type = make_node (RECORD_TYPE);
dtable_ptr_type = build_pointer_type (dtable_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, otable_type = build_array_type (integer_type_node,
one_elt_array_domain_type); one_elt_array_domain_type);
TYPE_NONALIASED_COMPONENT (otable_type) = 1; TYPE_NONALIASED_COMPONENT (otable_type) = 1;
otable_ptr_type = build_pointer_type (otable_type); 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); PUSH_FIELD (object_type_node, field, "vtable", dtable_ptr_type);
/* This isn't exactly true, but it is what we have in the source. /* This isn't exactly true, but it is what we have in the source.
...@@ -945,12 +905,12 @@ java_init_decl_processing (void) ...@@ -945,12 +905,12 @@ java_init_decl_processing (void)
eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
? "__gcj_personality_sj0" ? "__gcj_personality_sj0"
: "__gcj_personality_v0"); : "__gcj_personality_v0");
lang_eh_runtime_type = prepare_eh_table_type;
lang_eh_runtime_type = do_nothing;
init_jcf_parse (); init_jcf_parse ();
initialize_builtins (); initialize_builtins ();
soft_fmod_node = built_in_decls[BUILT_IN_FMOD]; soft_fmod_node = built_in_decls[BUILT_IN_FMOD];
#if 0 #if 0
soft_fmodf_node = built_in_decls[BUILT_IN_FMODF]; soft_fmodf_node = built_in_decls[BUILT_IN_FMODF];
...@@ -1860,6 +1820,7 @@ java_expand_body (tree fndecl) ...@@ -1860,6 +1820,7 @@ java_expand_body (tree fndecl)
current_function_decl = fndecl; current_function_decl = fndecl;
input_location = DECL_SOURCE_LOCATION (fndecl); input_location = DECL_SOURCE_LOCATION (fndecl);
output_class = DECL_CONTEXT (current_function_decl);
current_class = DECL_CONTEXT (fndecl); current_class = DECL_CONTEXT (fndecl);
timevar_push (TV_EXPAND); timevar_push (TV_EXPAND);
......
/* Handle exceptions for GNU compiler for the Java(TM) language. /* 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. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -312,6 +312,7 @@ tree ...@@ -312,6 +312,7 @@ tree
prepare_eh_table_type (tree type) prepare_eh_table_type (tree type)
{ {
tree exp; tree exp;
tree *slot;
const char *name; const char *name;
char *buf; char *buf;
tree decl; tree decl;
...@@ -324,8 +325,16 @@ prepare_eh_table_type (tree type) ...@@ -324,8 +325,16 @@ prepare_eh_table_type (tree type)
* rewritten to point to the appropriate class. */ * rewritten to point to the appropriate class. */
if (type == NULL_TREE) if (type == NULL_TREE)
exp = NULL_TREE; return NULL_TREE;
else if (is_compiled_class (type) && !flag_indirect_dispatch)
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))); name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
buf = alloca (strlen (name) + 5); buf = alloca (strlen (name) + 5);
...@@ -339,8 +348,6 @@ prepare_eh_table_type (tree type) ...@@ -339,8 +348,6 @@ prepare_eh_table_type (tree type)
DECL_INITIAL (decl) = build_class_ref (type); DECL_INITIAL (decl) = build_class_ref (type);
layout_decl (decl, 0); layout_decl (decl, 0);
pushdecl (decl); 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); exp = build1 (ADDR_EXPR, ptr_type_node, decl);
} }
else else
...@@ -357,14 +364,37 @@ prepare_eh_table_type (tree type) ...@@ -357,14 +364,37 @@ prepare_eh_table_type (tree type)
TREE_THIS_VOLATILE (decl) = 0; TREE_THIS_VOLATILE (decl) = 0;
layout_decl (decl, 0); layout_decl (decl, 0);
pushdecl (decl); 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); 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; 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 /* Build a reference to the jthrowable object being carried in the
exception header. */ exception header. */
...@@ -404,7 +434,7 @@ expand_end_java_handler (struct eh_range *range) ...@@ -404,7 +434,7 @@ expand_end_java_handler (struct eh_range *range)
if (type == NULL) if (type == NULL)
type = throwable_type_node; type = throwable_type_node;
expand_start_catch (type); expand_start_catch (prepare_eh_table_type (type));
expand_goto (TREE_VALUE (handler)); expand_goto (TREE_VALUE (handler));
expand_end_catch (); expand_end_catch ();
} }
......
/* Process expressions for the GNU compiler for the Java(TM) language. /* 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. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -1511,17 +1511,18 @@ build_field_ref (tree self_value, tree self_class, tree name) ...@@ -1511,17 +1511,18 @@ build_field_ref (tree self_value, tree self_class, tree name)
if (base_type != TREE_TYPE (self_value)) if (base_type != TREE_TYPE (self_value))
self_value = fold (build1 (NOP_EXPR, base_type, self_value)); self_value = fold (build1 (NOP_EXPR, base_type, self_value));
if (flag_indirect_dispatch if (flag_indirect_dispatch
&& current_class != self_class) && output_class != self_class)
/* FIXME: current_class != self_class is not exactly the right /* FIXME: output_class != self_class is not exactly the right
test. What we really want to know is whether self_class is 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. */ we can make a direct reference. */
{ {
tree otable_index tree otable_index =
= build_int_2 build_int_2 (get_symbol_table_index
(get_symbol_table_index (field_decl, &otable_methods), 0); (field_decl, &TYPE_OTABLE_METHODS (output_class)), 0);
tree field_offset = build (ARRAY_REF, integer_type_node, otable_decl, tree field_offset =
otable_index); build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class),
otable_index);
tree address tree address
= fold (build (PLUS_EXPR, = fold (build (PLUS_EXPR,
build_pointer_type (TREE_TYPE (field_decl)), build_pointer_type (TREE_TYPE (field_decl)),
...@@ -1771,10 +1772,12 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED, ...@@ -1771,10 +1772,12 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED,
} }
else else
{ {
tree table_index = build_int_2 (get_symbol_table_index tree table_index =
(method, &atable_methods), 0); build_int_2 (get_symbol_table_index
func = build (ARRAY_REF, method_ptr_type_node, atable_decl, (method, &TYPE_ATABLE_METHODS (output_class)), 0);
table_index); func =
build (ARRAY_REF, method_ptr_type_node,
TYPE_ATABLE_DECL (output_class), table_index);
} }
} }
else else
...@@ -1893,8 +1896,10 @@ build_invokevirtual (tree dtable, tree method) ...@@ -1893,8 +1896,10 @@ build_invokevirtual (tree dtable, tree method)
if (flag_indirect_dispatch) if (flag_indirect_dispatch)
{ {
otable_index otable_index
= build_int_2 (get_symbol_table_index (method, &otable_methods), 0); = build_int_2 (get_symbol_table_index
method_index = build (ARRAY_REF, integer_type_node, otable_decl, (method, &TYPE_OTABLE_METHODS (output_class)), 0);
method_index = build (ARRAY_REF, integer_type_node,
TYPE_OTABLE_DECL (output_class),
otable_index); otable_index);
} }
else else
...@@ -1957,9 +1962,12 @@ build_invokeinterface (tree dtable, tree method) ...@@ -1957,9 +1962,12 @@ build_invokeinterface (tree dtable, tree method)
if (flag_indirect_dispatch) if (flag_indirect_dispatch)
{ {
otable_index otable_index =
= build_int_2 (get_symbol_table_index (method, &otable_methods), 0); build_int_2 (get_symbol_table_index
idx = build (ARRAY_REF, integer_type_node, otable_decl, otable_index); (method, &TYPE_OTABLE_METHODS (output_class)), 0);
idx =
build (ARRAY_REF, integer_type_node, TYPE_OTABLE_DECL (output_class),
otable_index);
} }
else else
{ {
...@@ -2605,7 +2613,7 @@ java_expand_expr (tree exp, rtx target, enum machine_mode tmode, ...@@ -2605,7 +2613,7 @@ java_expand_expr (tree exp, rtx target, enum machine_mode tmode,
tree decl = BLOCK_EXPR_DECLS (catch); tree decl = BLOCK_EXPR_DECLS (catch);
tree type = (decl ? TREE_TYPE (TREE_TYPE (decl)) : NULL_TREE); 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_expr_stmt (TREE_OPERAND (current, 0));
expand_end_catch (); expand_end_catch ();
} }
......
/* Definitions for parsing and type checking for the GNU compiler for /* Definitions for parsing and type checking for the GNU compiler for
the Java(TM) language. 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. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -134,10 +134,17 @@ extern int compiling_from_source; ...@@ -134,10 +134,17 @@ extern int compiling_from_source;
#define main_class \ #define main_class \
java_global_trees[JTI_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 \ #define current_class \
java_global_trees[JTI_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. */ /* List of all class DECLs seen so far. */
#define all_class_list \ #define all_class_list \
java_global_trees[JTI_ALL_CLASS_LIST] java_global_trees[JTI_ALL_CLASS_LIST]
...@@ -147,27 +154,13 @@ extern int compiling_from_source; ...@@ -147,27 +154,13 @@ extern int compiling_from_source;
/* List of virtual decls referred to by this translation unit, used to /* List of virtual decls referred to by this translation unit, used to
generate virtual method offset symbol table. */ 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 virtual offset table. This is emitted as uninitialized data of
the required length, and filled out at run time during class the required length, and filled out at run time during class
linking. */ 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 virtual offset symbol table. Used by the runtime to fill out
the otable. */ 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; extern int flag_emit_class_files;
...@@ -244,6 +237,10 @@ extern const char *current_encoding; ...@@ -244,6 +237,10 @@ extern const char *current_encoding;
/* The Java .class file that provides main_class; the main input file. */ /* The Java .class file that provides main_class; the main input file. */
extern GTY(()) struct JCF * current_jcf; 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; typedef struct CPool constant_pool;
#define CONSTANT_ResolvedFlag 16 #define CONSTANT_ResolvedFlag 16
...@@ -413,20 +410,10 @@ enum java_tree_index ...@@ -413,20 +410,10 @@ enum java_tree_index
JTI_MAIN_CLASS, JTI_MAIN_CLASS,
JTI_CURRENT_CLASS, JTI_CURRENT_CLASS,
JTI_OUTPUT_CLASS,
JTI_ALL_CLASS_LIST, JTI_ALL_CLASS_LIST,
JTI_ALL_CLASS_FILENAME, 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_PREDEF_FILENAMES,
JTI_MAX JTI_MAX
...@@ -923,6 +910,9 @@ union lang_tree_node ...@@ -923,6 +910,9 @@ union lang_tree_node
/* The original WFL of a final variable. */ /* The original WFL of a final variable. */
#define DECL_FIELD_FINAL_WFL(NODE) \ #define DECL_FIELD_FINAL_WFL(NODE) \
(DECL_LANG_SPECIFIC(NODE)->u.v.wfl) (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. */ /* True if NODE is a local variable final. */
#define LOCAL_FINAL_P(NODE) (DECL_LANG_SPECIFIC (NODE) && DECL_FINAL (NODE)) #define LOCAL_FINAL_P(NODE) (DECL_LANG_SPECIFIC (NODE) && DECL_FINAL (NODE))
/* True if NODE is a final field. */ /* True if NODE is a final field. */
...@@ -1022,6 +1012,7 @@ struct lang_decl_var GTY(()) ...@@ -1022,6 +1012,7 @@ struct lang_decl_var GTY(())
tree slot_chain; tree slot_chain;
tree am; /* Access method for this field (1.1) */ tree am; /* Access method for this field (1.1) */
tree wfl; /* Original wfl */ tree wfl; /* Original wfl */
tree owner;
unsigned int final_iud : 1; /* Final initialized upon declaration */ unsigned int final_iud : 1; /* Final initialized upon declaration */
unsigned int cif : 1; /* True: decl is a class initialization flag */ unsigned int cif : 1; /* True: decl is a class initialization flag */
unsigned int freed; /* Decl is no longer in scope. */ unsigned int freed; /* Decl is no longer in scope. */
...@@ -1070,6 +1061,19 @@ struct lang_decl GTY(()) ...@@ -1070,6 +1061,19 @@ struct lang_decl GTY(())
#define TYPE_STRICTFP(T) (TYPE_LANG_SPECIFIC(T)->strictfp) #define TYPE_STRICTFP(T) (TYPE_LANG_SPECIFIC(T)->strictfp)
#define TYPE_USES_ASSERTIONS(T) (TYPE_LANG_SPECIFIC(T)->assertions) #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(()) struct lang_type GTY(())
{ {
tree signature; tree signature;
...@@ -1086,6 +1090,21 @@ struct lang_type GTY(()) ...@@ -1086,6 +1090,21 @@ struct lang_type GTY(())
tree package_list; /* List of package names, progressive */ tree package_list; /* List of package names, progressive */
tree import_list; /* Imported types, in the CU of this class */ tree import_list; /* Imported types, in the CU of this class */
tree import_demand_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 pic:1; /* Private Inner Class. */
unsigned poic:1; /* Protected Inner Class. */ unsigned poic:1; /* Protected Inner Class. */
unsigned strictfp:1; /* `strictfp' class. */ unsigned strictfp:1; /* `strictfp' class. */
...@@ -1200,6 +1219,7 @@ extern tree build_instanceof (tree, tree); ...@@ -1200,6 +1219,7 @@ extern tree build_instanceof (tree, tree);
extern tree create_label_decl (tree); extern tree create_label_decl (tree);
extern void push_labeled_block (tree); extern void push_labeled_block (tree);
extern tree prepare_eh_table_type (tree); extern tree prepare_eh_table_type (tree);
extern void java_expand_catch_classes (tree);
extern tree build_exception_object_ref (tree); extern tree build_exception_object_ref (tree);
extern tree generate_name (void); extern tree generate_name (void);
extern void pop_labeled_block (void); extern void pop_labeled_block (void);
...@@ -1322,7 +1342,9 @@ extern void java_expand_body (tree); ...@@ -1322,7 +1342,9 @@ extern void java_expand_body (tree);
extern int get_symbol_table_index (tree, tree *); extern int get_symbol_table_index (tree, tree *);
extern tree make_catch_class_record (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) #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
......
/* Parser for Java(TM) .class files. /* 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. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -72,10 +72,6 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ ...@@ -72,10 +72,6 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
extern struct obstack temporary_obstack; 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]; static GTY(()) tree parse_roots[3];
/* The FIELD_DECL for the current field. */ /* The FIELD_DECL for the current field. */
...@@ -153,7 +149,7 @@ set_source_filename (JCF *jcf, int index) ...@@ -153,7 +149,7 @@ set_source_filename (JCF *jcf, int index)
#define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \ #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
{ tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \ { 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);} set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);}
#define HANDLE_CLASS_INTERFACE(INDEX) \ #define HANDLE_CLASS_INTERFACE(INDEX) \
...@@ -509,7 +505,7 @@ read_class (tree name) ...@@ -509,7 +505,7 @@ read_class (tree name)
wfl_operator = build_expr_wfl (NULL_TREE, NULL, 0, 0); wfl_operator = build_expr_wfl (NULL_TREE, NULL, 0, 0);
EXPR_WFL_FILENAME_NODE (wfl_operator) = file; EXPR_WFL_FILENAME_NODE (wfl_operator) = file;
input_filename = ggc_strdup (filename); input_filename = ggc_strdup (filename);
current_class = NULL_TREE; output_class = current_class = NULL_TREE;
current_function_decl = NULL_TREE; current_function_decl = NULL_TREE;
if (!HAS_BEEN_ALREADY_PARSED_P (file)) if (!HAS_BEEN_ALREADY_PARSED_P (file))
{ {
...@@ -531,7 +527,7 @@ read_class (tree name) ...@@ -531,7 +527,7 @@ read_class (tree name)
{ {
java_parser_context_save_global (); java_parser_context_save_global ();
java_push_parser_context (); java_push_parser_context ();
current_class = class; output_class = current_class = class;
input_filename = current_jcf->filename; input_filename = current_jcf->filename;
if (JCF_SEEN_IN_ZIP (current_jcf)) if (JCF_SEEN_IN_ZIP (current_jcf))
read_zip_member(current_jcf, read_zip_member(current_jcf,
...@@ -549,7 +545,7 @@ read_class (tree name) ...@@ -549,7 +545,7 @@ read_class (tree name)
load_inner_classes (class); load_inner_classes (class);
} }
current_class = save_current_class; output_class = current_class = save_current_class;
input_location = save_location; input_location = save_location;
current_jcf = save_current_jcf; current_jcf = save_current_jcf;
return 1; return 1;
...@@ -709,6 +705,8 @@ parse_class_file (void) ...@@ -709,6 +705,8 @@ parse_class_file (void)
compiling from class files. */ compiling from class files. */
always_initialize_class_p = 1; always_initialize_class_p = 1;
gen_indirect_dispatch_tables (current_class);
java_mark_class_local (current_class); java_mark_class_local (current_class);
for (method = TYPE_METHODS (current_class); for (method = TYPE_METHODS (current_class);
...@@ -1099,7 +1097,7 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED) ...@@ -1099,7 +1097,7 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
input_filename = IDENTIFIER_POINTER (TREE_VALUE (node)); input_filename = IDENTIFIER_POINTER (TREE_VALUE (node));
if (CLASS_FILE_P (node)) if (CLASS_FILE_P (node))
{ {
current_class = TREE_PURPOSE (node); output_class = current_class = TREE_PURPOSE (node);
current_jcf = TYPE_JCF (current_class); current_jcf = TYPE_JCF (current_class);
layout_class (current_class); layout_class (current_class);
load_inner_classes (current_class); load_inner_classes (current_class);
...@@ -1119,18 +1117,6 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED) ...@@ -1119,18 +1117,6 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
/* Emit the .jcf section. */ /* Emit the .jcf section. */
emit_register_classes (); 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 (); write_resource_constructor ();
...@@ -1201,7 +1187,7 @@ parse_zip_file_entries (void) ...@@ -1201,7 +1187,7 @@ parse_zip_file_entries (void)
class = lookup_class (get_identifier (class_name)); class = lookup_class (get_identifier (class_name));
FREE (class_name); FREE (class_name);
current_jcf = TYPE_JCF (class); current_jcf = TYPE_JCF (class);
current_class = class; output_class = current_class = class;
if (! CLASS_LOADED_P (class)) if (! CLASS_LOADED_P (class))
{ {
......
/* Java(TM) language-specific utility routines. /* 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. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -464,6 +464,11 @@ java_init (void) ...@@ -464,6 +464,11 @@ java_init (void)
if (flag_inline_functions) if (flag_inline_functions)
flag_inline_trees = 1; 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 /* Force minimum function alignment if g++ uses the least significant
bit of function pointers to store the virtual bit. This is required bit of function pointers to store the virtual bit. This is required
to keep vtables compatible. */ to keep vtables compatible. */
...@@ -967,11 +972,9 @@ inline_init_test_initialization (void **entry, void *x) ...@@ -967,11 +972,9 @@ inline_init_test_initialization (void **entry, void *x)
(DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), ite->key); (DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), ite->key);
if (! h) if (! h)
return true; return true;
splay_tree_insert (decl_map, splay_tree_insert (decl_map,
(splay_tree_key) ite->value, (splay_tree_key) ite->value,
(splay_tree_value) h); (splay_tree_value) h);
return true; return true;
} }
...@@ -1102,7 +1105,7 @@ java_dump_tree (void *dump_info, tree t) ...@@ -1102,7 +1105,7 @@ java_dump_tree (void *dump_info, tree t)
static bool static bool
java_decl_ok_for_sibcall (tree decl) 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 /* Used by estimate_num_insns. Estimate number of instructions seen
...@@ -1228,7 +1231,7 @@ java_start_inlining (tree fn) ...@@ -1228,7 +1231,7 @@ java_start_inlining (tree fn)
static tree static tree
java_get_callee_fndecl (tree call_expr) java_get_callee_fndecl (tree call_expr)
{ {
tree method, table, element; tree method, table, element, atable_methods;
HOST_WIDE_INT index; HOST_WIDE_INT index;
...@@ -1239,10 +1242,14 @@ java_get_callee_fndecl (tree call_expr) ...@@ -1239,10 +1242,14 @@ java_get_callee_fndecl (tree call_expr)
if (TREE_CODE (method) != ARRAY_REF) if (TREE_CODE (method) != ARRAY_REF)
return NULL; return NULL;
table = TREE_OPERAND (method, 0); 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; 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. */ /* FIXME: Replace this for loop with a hash table lookup. */
for (element = atable_methods; element; element = TREE_CHAIN (element)) for (element = atable_methods; element; element = TREE_CHAIN (element))
{ {
...@@ -1257,7 +1264,7 @@ java_get_callee_fndecl (tree call_expr) ...@@ -1257,7 +1264,7 @@ java_get_callee_fndecl (tree call_expr)
} }
--index; --index;
} }
return NULL; return NULL;
} }
......
/* Source code parsing and tree node generation for the GNU compiler /* Source code parsing and tree node generation for the GNU compiler
for the Java(TM) language. 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. Free Software Foundation, Inc.
Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com) Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
...@@ -5451,7 +5451,7 @@ java_fix_constructors (void) ...@@ -5451,7 +5451,7 @@ java_fix_constructors (void)
if (CLASS_INTERFACE (TYPE_NAME (class_type))) if (CLASS_INTERFACE (TYPE_NAME (class_type)))
continue; continue;
current_class = class_type; output_class = current_class = class_type;
for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl)) for (decl = TYPE_METHODS (class_type); decl; decl = TREE_CHAIN (decl))
{ {
if (DECL_CONSTRUCTOR_P (decl)) if (DECL_CONSTRUCTOR_P (decl))
...@@ -7575,7 +7575,7 @@ java_reorder_fields (void) ...@@ -7575,7 +7575,7 @@ java_reorder_fields (void)
for (current = gclass_list; current; current = TREE_CHAIN (current)) 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) if (current_class == stop_reordering)
break; break;
...@@ -7632,7 +7632,7 @@ java_layout_classes (void) ...@@ -7632,7 +7632,7 @@ java_layout_classes (void)
for (current = gclass_list; current; current = TREE_CHAIN (current)) 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); layout_class (current_class);
/* Error reported by the caller */ /* Error reported by the caller */
...@@ -7696,7 +7696,7 @@ java_complete_expand_methods (tree class_decl) ...@@ -7696,7 +7696,7 @@ java_complete_expand_methods (tree class_decl)
{ {
tree clinit, decl, first_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 /* 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 not. If we do need it, we pre-expand the static fields so they're
...@@ -9017,6 +9017,15 @@ java_expand_classes (void) ...@@ -9017,6 +9017,15 @@ java_expand_classes (void)
for (cur_ctxp = ctxp_for_generation; cur_ctxp; cur_ctxp = cur_ctxp->next) 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; ctxp = cur_ctxp;
input_filename = ctxp->filename; input_filename = ctxp->filename;
lang_init_source (2); /* Error msgs have method prototypes */ lang_init_source (2); /* Error msgs have method prototypes */
...@@ -9025,7 +9034,6 @@ java_expand_classes (void) ...@@ -9025,7 +9034,6 @@ java_expand_classes (void)
} }
input_filename = main_input_filename; input_filename = main_input_filename;
/* Find anonymous classes and expand their constructor. This extra pass is /* Find anonymous classes and expand their constructor. This extra pass is
necessary because the constructor itself is only generated when the necessary because the constructor itself is only generated when the
method in which it is defined is expanded. */ method in which it is defined is expanded. */
...@@ -9035,7 +9043,7 @@ java_expand_classes (void) ...@@ -9035,7 +9043,7 @@ java_expand_classes (void)
ctxp = cur_ctxp; ctxp = cur_ctxp;
for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) 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)) if (ANONYMOUS_CLASS_P (current_class))
{ {
tree d; tree d;
...@@ -9063,7 +9071,7 @@ java_expand_classes (void) ...@@ -9063,7 +9071,7 @@ java_expand_classes (void)
for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
{ {
tree d; 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)) for (d = TYPE_METHODS (current_class); d; d = TREE_CHAIN (d))
{ {
if (DECL_RESULT (d) == NULL_TREE) if (DECL_RESULT (d) == NULL_TREE)
...@@ -9094,7 +9102,7 @@ java_expand_classes (void) ...@@ -9094,7 +9102,7 @@ java_expand_classes (void)
for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
{ {
tree d; 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)) for (d = TYPE_METHODS (current_class); d; d = TREE_CHAIN (d))
{ {
if (DECL_RESULT (d) == NULL_TREE) if (DECL_RESULT (d) == NULL_TREE)
...@@ -9159,7 +9167,7 @@ java_expand_classes (void) ...@@ -9159,7 +9167,7 @@ java_expand_classes (void)
current; current;
current = TREE_CHAIN (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) if (flag_emit_class_files)
write_classfile (current_class); write_classfile (current_class);
if (flag_emit_xref) if (flag_emit_xref)
...@@ -9180,7 +9188,7 @@ java_finish_classes (void) ...@@ -9180,7 +9188,7 @@ java_finish_classes (void)
ctxp = cur_ctxp; ctxp = cur_ctxp;
for (current = ctxp->class_list; current; current = TREE_CHAIN (current)) for (current = ctxp->class_list; current; current = TREE_CHAIN (current))
{ {
current_class = TREE_TYPE (current); output_class = current_class = TREE_TYPE (current);
finish_class (); 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