diff options
author | Andrew Haley <aph@redhat.com> | 2003-10-24 09:29:43 +0000 |
---|---|---|
committer | Andrew Haley <aph@gcc.gnu.org> | 2003-10-24 09:29:43 +0000 |
commit | 904715853c40f9a27b492794a6db817ea89a553a (patch) | |
tree | 8c726fb42c811bb6652ba1a759bae78c2c8d9378 /gcc/java | |
parent | c769a35d59f282465c1a344617bf04d595e8c477 (diff) | |
download | gcc-904715853c40f9a27b492794a6db817ea89a553a.zip gcc-904715853c40f9a27b492794a6db817ea89a553a.tar.gz gcc-904715853c40f9a27b492794a6db817ea89a553a.tar.bz2 |
lang.c (LANG_HOOKS_GET_CALLEE_FNDECL): New.
2003-10-22 Andrew Haley <aph@redhat.com>
* lang.c (LANG_HOOKS_GET_CALLEE_FNDECL): New.
(java_get_callee_fndecl): New.
* jcf-parse.c (java_parse_file): Call emit_catch_table().
* java-tree.h (ctable_decl): New.
(catch_classes): New.
(java_tree_index): Add JTI_CTABLE_DECL, JTI_CATCH_CLASSES.
* decl.c (java_init_decl_processing): Add catch_class_type.
Add ctable_decl.
Add catch_classes field.
* class.c (build_indirect_class_ref): Break out from
build_class_ref.
(make_field_value): Check flag_indirect_dispatch.
(make_class_data): Ditto.
Tidy uses of PUSH_FIELD_VALUE.
Add field catch_classes.
(make_catch_class_record): New.
* java-tree.h (PUSH_FIELD_VALUE): Tidy.
2003-10-22 Andrew Haley <aph@redhat.com>
* java/lang/natClass.cc (initializeClass): Call
_Jv_linkExceptionClassTable.
(_Jv_LinkSymbolTable): Call )_Jv_ThrowNoSuchMethodError. Call
_Jv_Defer_Resolution on a method whose ncode is NULL.
(_Jv_linkExceptionClassTable): New function.
(_Jv_LayoutVTableMethods): If superclass looks like a constant pool
entry, look it up.
* java/lang/Class.h (struct _Jv_CatchClass): New.
(_Jv_linkExceptionClassTable): New friend.
(_Jv_Defer_Resolution): New friend.
(class Class.catch_classes): New field.
* include/java-interp.h (Jv_Defer_Resolution): New method.
(_Jv_PrepareClass): Make a friend of _Jv_MethodBase.
(_Jv_MethodBase.deferred): New field.
(_Jv_Defer_Resolution): New function.
* resolve.cc (_Jv_PrepareClass): Resolve deferred handlers.
* exception.cc (get_ttype_entry): Change return type to void**.
(PERSONALITY_FUNCTION): Remove all code related to using a
Utf8Const* for a match type. Change match type to be a pointer to
a pointer, rather than a pointer to a Class.
* defineclass.cc (handleCodeAttribute): Initialize
method->deferred.
(handleMethodsEnd): Likewise.
From-SVN: r72886
Diffstat (limited to 'gcc/java')
-rw-r--r-- | gcc/java/ChangeLog | 25 | ||||
-rw-r--r-- | gcc/java/class.c | 83 | ||||
-rw-r--r-- | gcc/java/decl.c | 18 | ||||
-rw-r--r-- | gcc/java/except.c | 48 | ||||
-rw-r--r-- | gcc/java/java-tree.h | 26 | ||||
-rw-r--r-- | gcc/java/jcf-parse.c | 3 | ||||
-rw-r--r-- | gcc/java/lang.c | 45 |
7 files changed, 208 insertions, 40 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 16bb513..1458560 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,28 @@ +2003-10-22 Andrew Haley <aph@redhat.com> + + * lang.c (LANG_HOOKS_GET_CALLEE_FNDECL): New. + (java_get_callee_fndecl): New. + + * jcf-parse.c (java_parse_file): Call emit_catch_table(). + + * java-tree.h (ctable_decl): New. + (catch_classes): New. + (java_tree_index): Add JTI_CTABLE_DECL, JTI_CATCH_CLASSES. + + * decl.c (java_init_decl_processing): Add catch_class_type. + Add ctable_decl. + Add catch_classes field. + + * class.c (build_indirect_class_ref): Break out from + build_class_ref. + (make_field_value): Check flag_indirect_dispatch. + (make_class_data): Ditto. + Tidy uses of PUSH_FIELD_VALUE. + Add field catch_classes. + (make_catch_class_record): New. + + * java-tree.h (PUSH_FIELD_VALUE): Tidy. + 2003-10-22 Kazu Hirata <kazu@cs.umass.edu> * jcf-write.c: Follow spelling conventions. diff --git a/gcc/java/class.c b/gcc/java/class.c index 49e1a3d..2aacbd4 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -808,6 +808,20 @@ build_utf8_ref (tree name) return ref; } +/* Like build_class_ref, but instead of a direct reference generate a + pointer into the constant pool. */ + +static tree +build_indirect_class_ref (tree type) +{ + int index; + tree cl; + index = alloc_class_constant (type); + cl = build_ref_from_constant_pool (index); + TREE_TYPE (cl) = promote_type (class_ptr_type); + return cl; +} + /* Build a reference to the class TYPE. Also handles primitive types and array types. */ @@ -820,6 +834,12 @@ build_class_ref (tree type) tree ref, decl_name, decl; if (TREE_CODE (type) == POINTER_TYPE) type = TREE_TYPE (type); + + if (flag_indirect_dispatch + && type != current_class + && TREE_CODE (type) == RECORD_TYPE) + return build_indirect_class_ref (type); + if (TREE_CODE (type) == RECORD_TYPE) { if (TYPE_SIZE (type) == error_mark_node) @@ -902,14 +922,7 @@ build_class_ref (tree type) return ref; } else - { - int index; - tree cl; - index = alloc_class_constant (type); - cl = build_ref_from_constant_pool (index); - TREE_TYPE (cl) = promote_type (class_ptr_type); - return cl; - } + return build_indirect_class_ref (type); } tree @@ -1061,7 +1074,7 @@ make_field_value (tree fdecl) tree finit; int flags; tree type = TREE_TYPE (fdecl); - int resolved = is_compiled_class (type); + int resolved = is_compiled_class (type) && ! flag_indirect_dispatch; START_RECORD_CONSTRUCTOR (finit, field_type_node); PUSH_FIELD_VALUE (finit, "name", build_utf8_ref (DECL_NAME (fdecl))); @@ -1422,7 +1435,8 @@ make_class_data (tree type) super = CLASSTYPE_SUPER (type); if (super == NULL_TREE) super = null_pointer_node; - else if (assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl))) + else if (! flag_indirect_dispatch + && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (type_decl))) && assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (super))))) super = build_class_ref (super); else @@ -1492,7 +1506,7 @@ make_class_data (tree type) PUSH_FIELD_VALUE (cons, "method_count", build_int_2 (method_count, 0)); if (flag_indirect_dispatch) - PUSH_FIELD_VALUE (cons, "vtable_method_count", integer_minus_one_node) + PUSH_FIELD_VALUE (cons, "vtable_method_count", integer_minus_one_node); else PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type)); @@ -1505,7 +1519,7 @@ make_class_data (tree type) build_int_2 (static_field_count, 0)); if (flag_indirect_dispatch) - PUSH_FIELD_VALUE (cons, "vtable", null_pointer_node) + PUSH_FIELD_VALUE (cons, "vtable", null_pointer_node); else PUSH_FIELD_VALUE (cons, "vtable", dtable_decl == NULL_TREE ? null_pointer_node @@ -1540,7 +1554,9 @@ make_class_data (tree type) atable_syms_decl)); TREE_CONSTANT (atable_decl) = 1; } - + + PUSH_FIELD_VALUE (cons, "catch_classes", + build1 (ADDR_EXPR, ptr_type_node, ctable_decl)); PUSH_FIELD_VALUE (cons, "interfaces", interfaces); PUSH_FIELD_VALUE (cons, "loader", null_pointer_node); PUSH_FIELD_VALUE (cons, "interface_count", build_int_2 (interface_len, 0)); @@ -2210,6 +2226,47 @@ emit_symbol_table (tree name, tree the_table, tree decl_list, tree the_syms_decl return the_table; } +/* make an entry for the catch_classes list. */ +tree +make_catch_class_record (tree catch_class, tree classname) +{ + tree entry; + tree type = TREE_TYPE (TREE_TYPE (ctable_decl)); + START_RECORD_CONSTRUCTOR (entry, type); + PUSH_FIELD_VALUE (entry, "address", catch_class); + PUSH_FIELD_VALUE (entry, "classname", classname); + FINISH_RECORD_CONSTRUCTOR (entry); + return entry; +} + + +/* Generate the list of Throwable classes that are caught by exception + handlers in this compilation. */ +void +emit_catch_table (void) +{ + tree table, table_size, array_type; + catch_classes + = tree_cons (NULL, + make_catch_class_record (null_pointer_node, null_pointer_node), + catch_classes); + catch_classes = nreverse (catch_classes); + catch_classes + = tree_cons (NULL, + make_catch_class_record (null_pointer_node, null_pointer_node), + catch_classes); + table_size = build_index_type (build_int_2 (list_length (catch_classes), 0)); + array_type + = build_array_type (TREE_TYPE (TREE_TYPE (ctable_decl)), table_size); + table = build_decl (VAR_DECL, DECL_NAME (ctable_decl), array_type); + DECL_INITIAL (table) = build_constructor (array_type, catch_classes); + TREE_STATIC (table) = 1; + TREE_READONLY (table) = 1; + rest_of_decl_compilation (table, NULL, 1, 0); + ctable_decl = table; +} + + void init_class_processing (void) { diff --git a/gcc/java/decl.c b/gcc/java/decl.c index fa8c939..e23cb120 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -663,6 +663,23 @@ java_init_decl_processing (void) 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. There is an unresolved issue here, which is whether the vtable @@ -702,6 +719,7 @@ java_init_decl_processing (void) PUSH_FIELD (class_type_node, field, "atable", atable_ptr_type); PUSH_FIELD (class_type_node, field, "atable_syms", symbols_array_ptr_type); + PUSH_FIELD (class_type_node, field, "catch_classes", ptr_type_node); PUSH_FIELD (class_type_node, field, "interfaces", build_pointer_type (class_ptr_type)); PUSH_FIELD (class_type_node, field, "loader", ptr_type_node); diff --git a/gcc/java/except.c b/gcc/java/except.c index 6aeff65..dc97b42f 100644 --- a/gcc/java/except.c +++ b/gcc/java/except.c @@ -313,46 +313,52 @@ prepare_eh_table_type (tree type) { tree exp; - /* The "type" (metch_info) in a (Java) exception table is one: + /* The "type" (match_info) in a (Java) exception table is a pointer to: * a) NULL - meaning match any type in a try-finally. - * b) a pointer to a (compiled) class (low-order bit 0). - * c) a pointer to the Utf8Const name of the class, plus one - * (which yields a value with low-order bit 1). */ + * b) a pointer to a pointer to a class. + * c) a pointer to a pointer to a utf8_ref. The pointer is + * rewritten to point to the appropriate class. */ if (type == NULL_TREE) exp = NULL_TREE; - else if (is_compiled_class (type)) - exp = build_class_ref (type); + else if (is_compiled_class (type) && !flag_indirect_dispatch) + { + char buf[64]; + tree decl; + sprintf (buf, "%s_ref", + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)))); + decl = build_decl (VAR_DECL, get_identifier (buf), ptr_type_node); + TREE_STATIC (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (decl) = 1; + TREE_READONLY (decl) = 1; + TREE_THIS_VOLATILE (decl) = 0; + 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 { - tree ctype = make_node (RECORD_TYPE); - tree field = NULL_TREE; - tree cinit, decl; + tree decl; tree utf8_ref = build_utf8_ref (DECL_NAME (TYPE_NAME (type))); char buf[64]; sprintf (buf, "%s_ref", IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (utf8_ref, 0)))); - PUSH_FIELD (ctype, field, "dummy", ptr_type_node); - PUSH_FIELD (ctype, field, "utf8", utf8const_ptr_type); - FINISH_RECORD (ctype); - START_RECORD_CONSTRUCTOR (cinit, ctype); - PUSH_FIELD_VALUE (cinit, "dummy", - convert (ptr_type_node, integer_minus_one_node)); - PUSH_FIELD_VALUE (cinit, "utf8", utf8_ref); - FINISH_RECORD_CONSTRUCTOR (cinit); - TREE_CONSTANT (cinit) = 1; - decl = build_decl (VAR_DECL, get_identifier (buf), ctype); + decl = build_decl (VAR_DECL, get_identifier (buf), utf8const_ptr_type); TREE_STATIC (decl) = 1; DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; TREE_READONLY (decl) = 1; TREE_THIS_VOLATILE (decl) = 0; - DECL_INITIAL (decl) = cinit; 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 (ctype), 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); } return exp; } diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index 42f99b5..7b5a397 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -167,6 +167,9 @@ extern int compiling_from_source; 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_filelist_file; @@ -424,6 +427,9 @@ enum java_tree_index JTI_ATABLE_DECL, JTI_ATABLE_SYMS_DECL, + JTI_CTABLE_DECL, + JTI_CATCH_CLASSES, + JTI_PREDEF_FILENAMES, JTI_MAX @@ -629,6 +635,8 @@ extern GTY(()) tree java_global_trees[JTI_MAX]; java_global_trees[JTI_SYMBOLS_ARRAY_TYPE] #define symbols_array_ptr_type \ java_global_trees[JTI_SYMBOLS_ARRAY_PTR_TYPE] +#define class_refs_decl \ + Jjava_global_trees[TI_CLASS_REFS_DECL] #define end_params_node \ java_global_trees[JTI_END_PARAMS_NODE] @@ -1320,6 +1328,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); + #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL) /* Access flags etc for a method (a FUNCTION_DECL): */ @@ -1678,11 +1689,16 @@ extern tree *type_map; /* Append a field initializer to CONS for a field with the given VALUE. NAME is a char* string used for error checking; the initializer must be specified in order. */ - #define PUSH_FIELD_VALUE(CONS, NAME, VALUE) {\ - tree field = TREE_CHAIN(CONS);\ - if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)), NAME) != 0) abort();\ - CONSTRUCTOR_ELTS(CONS) = tree_cons (field, VALUE, CONSTRUCTOR_ELTS(CONS));\ - TREE_CHAIN(CONS) = TREE_CHAIN (field); } +#define PUSH_FIELD_VALUE(CONS, NAME, VALUE) \ +do \ +{ \ + tree field = TREE_CHAIN(CONS); \ + if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)), NAME) != 0) \ + abort(); \ + CONSTRUCTOR_ELTS(CONS) = tree_cons (field, VALUE, CONSTRUCTOR_ELTS(CONS)); \ + TREE_CHAIN(CONS) = TREE_CHAIN (field); \ +} \ +while (0) /* Finish creating a record CONSTRUCTOR CONS. */ #define FINISH_RECORD_CONSTRUCTOR(CONS) \ diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c index de4b213..7570f86 100644 --- a/gcc/java/jcf-parse.c +++ b/gcc/java/jcf-parse.c @@ -632,7 +632,7 @@ jcf_parse (JCF* jcf) if (CLASS_PARSED_P (current_class)) { /* FIXME - where was first time */ - fatal_error ("reading class %s for the second time from %s", + fatal_error (stderr, "READING CLASS %s for the second time from %s", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))), jcf->filename); } @@ -1137,6 +1137,7 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED) (get_identifier ("atable"), atable_decl, atable_methods, atable_syms_decl, ptr_type_node); } + emit_catch_table (); } write_resource_constructor (); diff --git a/gcc/java/lang.c b/gcc/java/lang.c index ee476b2..615d250 100644 --- a/gcc/java/lang.c +++ b/gcc/java/lang.c @@ -68,6 +68,7 @@ static void dump_compound_expr (dump_info_p, tree); static bool java_decl_ok_for_sibcall (tree); static int java_estimate_num_insns (tree); static int java_start_inlining (tree); +static tree java_get_callee_fndecl (tree); #ifndef TARGET_OBJECT_SUFFIX # define TARGET_OBJECT_SUFFIX ".o" @@ -263,6 +264,9 @@ struct language_function GTY(()) #undef LANG_HOOKS_DECL_OK_FOR_SIBCALL #define LANG_HOOKS_DECL_OK_FOR_SIBCALL java_decl_ok_for_sibcall +#undef LANG_HOOKS_GET_CALLEE_FNDECL +#define LANG_HOOKS_GET_CALLEE_FNDECL java_get_callee_fndecl + #undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION java_expand_body @@ -1205,4 +1209,45 @@ java_start_inlining (tree fn) return TREE_ASM_WRITTEN (fn) ? 1 : 0; } +/* Given a call_expr, try to figure out what its target might be. In + the case of an indirection via the atable, search for the decl. If + the decl is external, we return NULL. If we don't, the optimizer + will replace the indirection with a direct call, which undoes the + purpose of the atable indirection. */ +static tree +java_get_callee_fndecl (tree call_expr) +{ + tree method, table, element; + + HOST_WIDE_INT index; + + if (TREE_CODE (call_expr) != CALL_EXPR) + return NULL; + method = TREE_OPERAND (call_expr, 0); + STRIP_NOPS (method); + if (TREE_CODE (method) != ARRAY_REF) + return NULL; + table = TREE_OPERAND (method, 0); + if (table != atable_decl) + return NULL; + 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)) + { + if (index == 1) + { + tree purpose = TREE_PURPOSE (element); + if (TREE_CODE (purpose) == FUNCTION_DECL + && ! DECL_EXTERNAL (purpose)) + return purpose; + else + return NULL; + } + --index; + } + + return NULL; +} + #include "gt-java-lang.h" |