mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
c769a35d59
commit
904715853c
|
|
@ -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>
|
2003-10-22 Kazu Hirata <kazu@cs.umass.edu>
|
||||||
|
|
||||||
* jcf-write.c: Follow spelling conventions.
|
* jcf-write.c: Follow spelling conventions.
|
||||||
|
|
|
||||||
|
|
@ -808,6 +808,20 @@ build_utf8_ref (tree name)
|
||||||
return ref;
|
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.
|
/* Build a reference to the class TYPE.
|
||||||
Also handles primitive types and array types. */
|
Also handles primitive types and array types. */
|
||||||
|
|
||||||
|
|
@ -820,6 +834,12 @@ build_class_ref (tree type)
|
||||||
tree ref, decl_name, decl;
|
tree ref, decl_name, decl;
|
||||||
if (TREE_CODE (type) == POINTER_TYPE)
|
if (TREE_CODE (type) == POINTER_TYPE)
|
||||||
type = TREE_TYPE (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 (TREE_CODE (type) == RECORD_TYPE)
|
||||||
{
|
{
|
||||||
if (TYPE_SIZE (type) == error_mark_node)
|
if (TYPE_SIZE (type) == error_mark_node)
|
||||||
|
|
@ -902,14 +922,7 @@ build_class_ref (tree type)
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
return build_indirect_class_ref (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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tree
|
tree
|
||||||
|
|
@ -1061,7 +1074,7 @@ make_field_value (tree fdecl)
|
||||||
tree finit;
|
tree finit;
|
||||||
int flags;
|
int flags;
|
||||||
tree type = TREE_TYPE (fdecl);
|
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);
|
START_RECORD_CONSTRUCTOR (finit, field_type_node);
|
||||||
PUSH_FIELD_VALUE (finit, "name", build_utf8_ref (DECL_NAME (fdecl)));
|
PUSH_FIELD_VALUE (finit, "name", build_utf8_ref (DECL_NAME (fdecl)));
|
||||||
|
|
@ -1422,7 +1435,8 @@ 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 (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)))))
|
&& assume_compiled (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (super)))))
|
||||||
super = build_class_ref (super);
|
super = build_class_ref (super);
|
||||||
else
|
else
|
||||||
|
|
@ -1492,7 +1506,7 @@ make_class_data (tree type)
|
||||||
PUSH_FIELD_VALUE (cons, "method_count", build_int_2 (method_count, 0));
|
PUSH_FIELD_VALUE (cons, "method_count", build_int_2 (method_count, 0));
|
||||||
|
|
||||||
if (flag_indirect_dispatch)
|
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
|
else
|
||||||
PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type));
|
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));
|
build_int_2 (static_field_count, 0));
|
||||||
|
|
||||||
if (flag_indirect_dispatch)
|
if (flag_indirect_dispatch)
|
||||||
PUSH_FIELD_VALUE (cons, "vtable", null_pointer_node)
|
PUSH_FIELD_VALUE (cons, "vtable", null_pointer_node);
|
||||||
else
|
else
|
||||||
PUSH_FIELD_VALUE (cons, "vtable",
|
PUSH_FIELD_VALUE (cons, "vtable",
|
||||||
dtable_decl == NULL_TREE ? null_pointer_node
|
dtable_decl == NULL_TREE ? null_pointer_node
|
||||||
|
|
@ -1540,7 +1554,9 @@ make_class_data (tree type)
|
||||||
atable_syms_decl));
|
atable_syms_decl));
|
||||||
TREE_CONSTANT (atable_decl) = 1;
|
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, "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));
|
||||||
|
|
@ -2210,6 +2226,47 @@ emit_symbol_table (tree name, tree the_table, tree decl_list, tree the_syms_decl
|
||||||
return the_table;
|
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
|
void
|
||||||
init_class_processing (void)
|
init_class_processing (void)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -663,6 +663,23 @@ java_init_decl_processing (void)
|
||||||
pushdecl (atable_syms_decl);
|
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.
|
||||||
There is an unresolved issue here, which is whether the vtable
|
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", atable_ptr_type);
|
||||||
PUSH_FIELD (class_type_node, field, "atable_syms",
|
PUSH_FIELD (class_type_node, field, "atable_syms",
|
||||||
symbols_array_ptr_type);
|
symbols_array_ptr_type);
|
||||||
|
PUSH_FIELD (class_type_node, field, "catch_classes", ptr_type_node);
|
||||||
PUSH_FIELD (class_type_node, field, "interfaces",
|
PUSH_FIELD (class_type_node, field, "interfaces",
|
||||||
build_pointer_type (class_ptr_type));
|
build_pointer_type (class_ptr_type));
|
||||||
PUSH_FIELD (class_type_node, field, "loader", ptr_type_node);
|
PUSH_FIELD (class_type_node, field, "loader", ptr_type_node);
|
||||||
|
|
|
||||||
|
|
@ -313,46 +313,52 @@ prepare_eh_table_type (tree type)
|
||||||
{
|
{
|
||||||
tree exp;
|
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.
|
* a) NULL - meaning match any type in a try-finally.
|
||||||
* b) a pointer to a (compiled) class (low-order bit 0).
|
* b) a pointer to a pointer to a class.
|
||||||
* c) a pointer to the Utf8Const name of the class, plus one
|
* c) a pointer to a pointer to a utf8_ref. The pointer is
|
||||||
* (which yields a value with low-order bit 1). */
|
* rewritten to point to the appropriate class. */
|
||||||
|
|
||||||
if (type == NULL_TREE)
|
if (type == NULL_TREE)
|
||||||
exp = NULL_TREE;
|
exp = NULL_TREE;
|
||||||
else if (is_compiled_class (type))
|
else if (is_compiled_class (type) && !flag_indirect_dispatch)
|
||||||
exp = build_class_ref (type);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
tree ctype = make_node (RECORD_TYPE);
|
|
||||||
tree field = NULL_TREE;
|
|
||||||
tree cinit, decl;
|
|
||||||
tree utf8_ref = build_utf8_ref (DECL_NAME (TYPE_NAME (type)));
|
|
||||||
char buf[64];
|
char buf[64];
|
||||||
|
tree decl;
|
||||||
sprintf (buf, "%s_ref",
|
sprintf (buf, "%s_ref",
|
||||||
IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (utf8_ref, 0))));
|
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
|
||||||
PUSH_FIELD (ctype, field, "dummy", ptr_type_node);
|
decl = build_decl (VAR_DECL, get_identifier (buf), 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);
|
|
||||||
TREE_STATIC (decl) = 1;
|
TREE_STATIC (decl) = 1;
|
||||||
DECL_ARTIFICIAL (decl) = 1;
|
DECL_ARTIFICIAL (decl) = 1;
|
||||||
DECL_IGNORED_P (decl) = 1;
|
DECL_IGNORED_P (decl) = 1;
|
||||||
TREE_READONLY (decl) = 1;
|
TREE_READONLY (decl) = 1;
|
||||||
TREE_THIS_VOLATILE (decl) = 0;
|
TREE_THIS_VOLATILE (decl) = 0;
|
||||||
DECL_INITIAL (decl) = cinit;
|
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);
|
rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0);
|
||||||
make_decl_rtl (decl, (char*) 0);
|
make_decl_rtl (decl, (char*) 0);
|
||||||
exp = build1 (ADDR_EXPR, build_pointer_type (ctype), decl);
|
exp = build1 (ADDR_EXPR, ptr_type_node, decl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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))));
|
||||||
|
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;
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
return exp;
|
return exp;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,9 @@ extern int compiling_from_source;
|
||||||
otable. */
|
otable. */
|
||||||
#define atable_syms_decl java_global_trees [JTI_ATABLE_SYMS_DECL]
|
#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;
|
||||||
|
|
||||||
extern int flag_filelist_file;
|
extern int flag_filelist_file;
|
||||||
|
|
@ -424,6 +427,9 @@ enum java_tree_index
|
||||||
JTI_ATABLE_DECL,
|
JTI_ATABLE_DECL,
|
||||||
JTI_ATABLE_SYMS_DECL,
|
JTI_ATABLE_SYMS_DECL,
|
||||||
|
|
||||||
|
JTI_CTABLE_DECL,
|
||||||
|
JTI_CATCH_CLASSES,
|
||||||
|
|
||||||
JTI_PREDEF_FILENAMES,
|
JTI_PREDEF_FILENAMES,
|
||||||
|
|
||||||
JTI_MAX
|
JTI_MAX
|
||||||
|
|
@ -629,6 +635,8 @@ extern GTY(()) tree java_global_trees[JTI_MAX];
|
||||||
java_global_trees[JTI_SYMBOLS_ARRAY_TYPE]
|
java_global_trees[JTI_SYMBOLS_ARRAY_TYPE]
|
||||||
#define symbols_array_ptr_type \
|
#define symbols_array_ptr_type \
|
||||||
java_global_trees[JTI_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 \
|
#define end_params_node \
|
||||||
java_global_trees[JTI_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 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)
|
#define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
|
||||||
|
|
||||||
/* Access flags etc for a method (a FUNCTION_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.
|
/* Append a field initializer to CONS for a field with the given VALUE.
|
||||||
NAME is a char* string used for error checking;
|
NAME is a char* string used for error checking;
|
||||||
the initializer must be specified in order. */
|
the initializer must be specified in order. */
|
||||||
#define PUSH_FIELD_VALUE(CONS, NAME, VALUE) {\
|
#define PUSH_FIELD_VALUE(CONS, NAME, VALUE) \
|
||||||
tree field = TREE_CHAIN(CONS);\
|
do \
|
||||||
if (strcmp (IDENTIFIER_POINTER (DECL_NAME (field)), NAME) != 0) abort();\
|
{ \
|
||||||
CONSTRUCTOR_ELTS(CONS) = tree_cons (field, VALUE, CONSTRUCTOR_ELTS(CONS));\
|
tree field = TREE_CHAIN(CONS); \
|
||||||
TREE_CHAIN(CONS) = TREE_CHAIN (field); }
|
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. */
|
/* Finish creating a record CONSTRUCTOR CONS. */
|
||||||
#define FINISH_RECORD_CONSTRUCTOR(CONS) \
|
#define FINISH_RECORD_CONSTRUCTOR(CONS) \
|
||||||
|
|
|
||||||
|
|
@ -632,7 +632,7 @@ jcf_parse (JCF* jcf)
|
||||||
if (CLASS_PARSED_P (current_class))
|
if (CLASS_PARSED_P (current_class))
|
||||||
{
|
{
|
||||||
/* FIXME - where was first time */
|
/* 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))),
|
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))),
|
||||||
jcf->filename);
|
jcf->filename);
|
||||||
}
|
}
|
||||||
|
|
@ -1137,6 +1137,7 @@ java_parse_file (int set_yydebug ATTRIBUTE_UNUSED)
|
||||||
(get_identifier ("atable"),
|
(get_identifier ("atable"),
|
||||||
atable_decl, atable_methods, atable_syms_decl, ptr_type_node);
|
atable_decl, atable_methods, atable_syms_decl, ptr_type_node);
|
||||||
}
|
}
|
||||||
|
emit_catch_table ();
|
||||||
}
|
}
|
||||||
|
|
||||||
write_resource_constructor ();
|
write_resource_constructor ();
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ static void dump_compound_expr (dump_info_p, tree);
|
||||||
static bool java_decl_ok_for_sibcall (tree);
|
static bool java_decl_ok_for_sibcall (tree);
|
||||||
static int java_estimate_num_insns (tree);
|
static int java_estimate_num_insns (tree);
|
||||||
static int java_start_inlining (tree);
|
static int java_start_inlining (tree);
|
||||||
|
static tree java_get_callee_fndecl (tree);
|
||||||
|
|
||||||
#ifndef TARGET_OBJECT_SUFFIX
|
#ifndef TARGET_OBJECT_SUFFIX
|
||||||
# define TARGET_OBJECT_SUFFIX ".o"
|
# define TARGET_OBJECT_SUFFIX ".o"
|
||||||
|
|
@ -263,6 +264,9 @@ struct language_function GTY(())
|
||||||
#undef LANG_HOOKS_DECL_OK_FOR_SIBCALL
|
#undef LANG_HOOKS_DECL_OK_FOR_SIBCALL
|
||||||
#define LANG_HOOKS_DECL_OK_FOR_SIBCALL java_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
|
#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
|
||||||
#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION java_expand_body
|
#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;
|
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"
|
#include "gt-java-lang.h"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,29 @@
|
||||||
|
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.
|
||||||
|
|
||||||
2003-10-23 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
|
2003-10-23 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
|
||||||
|
|
||||||
* java/lang/natObject.cc (_Jv_ObjectCheckMonitor): Use
|
* java/lang/natObject.cc (_Jv_ObjectCheckMonitor): Use
|
||||||
|
|
|
||||||
|
|
@ -1270,6 +1270,7 @@ void _Jv_ClassReader::handleCodeAttribute
|
||||||
_Jv_InterpMethod *method =
|
_Jv_InterpMethod *method =
|
||||||
(_Jv_InterpMethod*) (_Jv_AllocBytes (size));
|
(_Jv_InterpMethod*) (_Jv_AllocBytes (size));
|
||||||
|
|
||||||
|
method->deferred = NULL;
|
||||||
method->max_stack = max_stack;
|
method->max_stack = max_stack;
|
||||||
method->max_locals = max_locals;
|
method->max_locals = max_locals;
|
||||||
method->code_length = code_length;
|
method->code_length = code_length;
|
||||||
|
|
@ -1328,6 +1329,7 @@ void _Jv_ClassReader::handleMethodsEnd ()
|
||||||
m->self = method;
|
m->self = method;
|
||||||
m->function = NULL;
|
m->function = NULL;
|
||||||
def->interpreted_methods[i] = m;
|
def->interpreted_methods[i] = m;
|
||||||
|
m->deferred = NULL;
|
||||||
|
|
||||||
if ((method->accflags & Modifier::STATIC))
|
if ((method->accflags & Modifier::STATIC))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,7 @@ parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static jclass
|
static void **
|
||||||
get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
|
get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
|
||||||
{
|
{
|
||||||
_Unwind_Ptr ptr;
|
_Unwind_Ptr ptr;
|
||||||
|
|
@ -169,7 +169,7 @@ get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
|
||||||
i *= size_of_encoded_value (info->ttype_encoding);
|
i *= size_of_encoded_value (info->ttype_encoding);
|
||||||
read_encoded_value (context, info->ttype_encoding, info->TType - i, &ptr);
|
read_encoded_value (context, info->ttype_encoding, info->TType - i, &ptr);
|
||||||
|
|
||||||
return reinterpret_cast<jclass>(ptr);
|
return reinterpret_cast<void **>(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -336,23 +336,15 @@ PERSONALITY_FUNCTION (int version,
|
||||||
{
|
{
|
||||||
// Positive filter values are handlers.
|
// Positive filter values are handlers.
|
||||||
|
|
||||||
jclass catch_type = get_ttype_entry (context, &info, ar_filter);
|
void **catch_word = get_ttype_entry (context, &info, ar_filter);
|
||||||
|
jclass catch_type = (jclass)*catch_word;
|
||||||
|
|
||||||
|
// FIXME: This line is a kludge to work around exception
|
||||||
|
// handlers written in C++, which don't yet use indirect
|
||||||
|
// dispatch.
|
||||||
|
if (catch_type == *(void **)&java::lang::Class::class$)
|
||||||
|
catch_type = (jclass)catch_word;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int __attribute__ ((mode (pointer))) dummy;
|
|
||||||
Utf8Const *utf8;
|
|
||||||
} utf8_hdr;
|
|
||||||
utf8_hdr *p = (utf8_hdr *)catch_type;
|
|
||||||
if (p->dummy == -1)
|
|
||||||
{
|
|
||||||
using namespace gnu::gcj::runtime;
|
|
||||||
java::lang::Class *klass
|
|
||||||
= StackTrace::getClass ((gnu::gcj::RawData *)ip);
|
|
||||||
java::lang::ClassLoader *loader
|
|
||||||
= klass ? klass->getClassLoaderInternal () : NULL;
|
|
||||||
catch_type = _Jv_FindClass (p->utf8, loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_Jv_IsInstanceOf (xh->value, catch_type))
|
if (_Jv_IsInstanceOf (xh->value, catch_type))
|
||||||
{
|
{
|
||||||
handler_switch_value = ar_filter;
|
handler_switch_value = ar_filter;
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,12 @@ protected:
|
||||||
// Size of raw arguments.
|
// Size of raw arguments.
|
||||||
_Jv_ushort args_raw_size;
|
_Jv_ushort args_raw_size;
|
||||||
|
|
||||||
|
// Chain of addresses to fill in. See _Jv_Defer_Resolution.
|
||||||
|
void *deferred;
|
||||||
|
|
||||||
|
friend void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **);
|
||||||
|
friend void _Jv_PrepareClass(jclass);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_Jv_Method *get_method ()
|
_Jv_Method *get_method ()
|
||||||
{
|
{
|
||||||
|
|
@ -167,8 +173,33 @@ class _Jv_InterpClass : public java::lang::Class
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
friend _Jv_MethodBase ** _Jv_GetFirstMethod (_Jv_InterpClass *klass);
|
friend _Jv_MethodBase ** _Jv_GetFirstMethod (_Jv_InterpClass *klass);
|
||||||
|
friend void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We have an interpreted class CL and we're trying to find the
|
||||||
|
// address of the ncode of a method METH. That interpreted class
|
||||||
|
// hasn't yet been prepared, so we defer fixups until they are ready.
|
||||||
|
// To do this, we create a chain of fixups that will be resolved by
|
||||||
|
// _Jv_PrepareClass.
|
||||||
|
extern inline void
|
||||||
|
_Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **address)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
_Jv_InterpClass *self = (_Jv_InterpClass *)cl;
|
||||||
|
for (i = 0; i < self->method_count; i++)
|
||||||
|
{
|
||||||
|
_Jv_Method *m = &self->methods[i];
|
||||||
|
if (m == meth)
|
||||||
|
{
|
||||||
|
_Jv_MethodBase *imeth = self->interpreted_methods[i];
|
||||||
|
*address = imeth->deferred;
|
||||||
|
imeth->deferred = address;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
extern inline _Jv_MethodBase **
|
extern inline _Jv_MethodBase **
|
||||||
_Jv_GetFirstMethod (_Jv_InterpClass *klass)
|
_Jv_GetFirstMethod (_Jv_InterpClass *klass)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,12 @@ struct _Jv_AddressTable
|
||||||
void *addresses[];
|
void *addresses[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _Jv_CatchClass
|
||||||
|
{
|
||||||
|
java::lang::Class **address;
|
||||||
|
_Jv_Utf8Const *classname;
|
||||||
|
};
|
||||||
|
|
||||||
#define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
|
#define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
|
||||||
|
|
||||||
#define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
|
#define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
|
||||||
|
|
@ -336,6 +342,7 @@ private:
|
||||||
friend void _Jv_LayoutVTableMethods (jclass klass);
|
friend void _Jv_LayoutVTableMethods (jclass klass);
|
||||||
friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
|
friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
|
||||||
friend void _Jv_MakeVTable (jclass);
|
friend void _Jv_MakeVTable (jclass);
|
||||||
|
friend void _Jv_linkExceptionClassTable (jclass);
|
||||||
|
|
||||||
friend jboolean _Jv_CheckAccess (jclass self_klass, jclass other_klass,
|
friend jboolean _Jv_CheckAccess (jclass self_klass, jclass other_klass,
|
||||||
jint flags);
|
jint flags);
|
||||||
|
|
@ -365,6 +372,8 @@ private:
|
||||||
friend void _Jv_PrepareClass (jclass);
|
friend void _Jv_PrepareClass (jclass);
|
||||||
friend void _Jv_PrepareMissingMethods (jclass base, jclass iface_class);
|
friend void _Jv_PrepareMissingMethods (jclass base, jclass iface_class);
|
||||||
|
|
||||||
|
friend void _Jv_Defer_Resolution (void *cl, _Jv_Method *meth, void **);
|
||||||
|
|
||||||
friend class _Jv_ClassReader;
|
friend class _Jv_ClassReader;
|
||||||
friend class _Jv_InterpClass;
|
friend class _Jv_InterpClass;
|
||||||
friend class _Jv_InterpMethod;
|
friend class _Jv_InterpMethod;
|
||||||
|
|
@ -414,6 +423,7 @@ private:
|
||||||
_Jv_MethodSymbol *otable_syms;
|
_Jv_MethodSymbol *otable_syms;
|
||||||
_Jv_AddressTable *atable;
|
_Jv_AddressTable *atable;
|
||||||
_Jv_MethodSymbol *atable_syms;
|
_Jv_MethodSymbol *atable_syms;
|
||||||
|
_Jv_CatchClass *catch_classes;
|
||||||
// Interfaces implemented by this class.
|
// Interfaces implemented by this class.
|
||||||
jclass *interfaces;
|
jclass *interfaces;
|
||||||
// The class loader for this class.
|
// The class loader for this class.
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ details. */
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#pragma implementation "Class.h"
|
#pragma implementation "Class.h"
|
||||||
|
|
||||||
|
|
@ -56,7 +57,7 @@ details. */
|
||||||
#include <gnu/gcj/RawData.h>
|
#include <gnu/gcj/RawData.h>
|
||||||
|
|
||||||
#include <java-cpool.h>
|
#include <java-cpool.h>
|
||||||
|
#include <java-interp.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace gcj;
|
using namespace gcj;
|
||||||
|
|
@ -796,6 +797,8 @@ java::lang::Class::initializeClass (void)
|
||||||
if (otable || atable)
|
if (otable || atable)
|
||||||
_Jv_LinkSymbolTable(this);
|
_Jv_LinkSymbolTable(this);
|
||||||
|
|
||||||
|
_Jv_linkExceptionClassTable (this);
|
||||||
|
|
||||||
// Steps 8, 9, 10, 11.
|
// Steps 8, 9, 10, 11.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -1541,14 +1544,18 @@ _Jv_LinkSymbolTable(jclass klass)
|
||||||
|
|
||||||
for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++)
|
for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++)
|
||||||
{
|
{
|
||||||
|
// FIXME: Why are we passing NULL as the class loader?
|
||||||
jclass target_class = _Jv_FindClass (sym.class_name, NULL);
|
jclass target_class = _Jv_FindClass (sym.class_name, NULL);
|
||||||
_Jv_Method *meth = NULL;
|
_Jv_Method *meth = NULL;
|
||||||
|
|
||||||
const _Jv_Utf8Const *signature = sym.signature;
|
const _Jv_Utf8Const *signature = sym.signature;
|
||||||
|
|
||||||
// FIXME: This should be special index for ThrowNoSuchMethod().
|
{
|
||||||
klass->otable->offsets[index] = -1;
|
static char *bounce = (char *)_Jv_ThrowNoSuchMethodError;
|
||||||
|
ptrdiff_t offset = (char *)(klass->vtable) - bounce;
|
||||||
|
klass->otable->offsets[index] = offset;
|
||||||
|
}
|
||||||
|
|
||||||
if (target_class == NULL)
|
if (target_class == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -1658,6 +1665,7 @@ _Jv_LinkSymbolTable(jclass klass)
|
||||||
|
|
||||||
for (index = 0; sym = klass->atable_syms[index], sym.name != NULL; index++)
|
for (index = 0; sym = klass->atable_syms[index], sym.name != NULL; index++)
|
||||||
{
|
{
|
||||||
|
// FIXME: Why are we passing NULL as the class loader?
|
||||||
jclass target_class = _Jv_FindClass (sym.class_name, NULL);
|
jclass target_class = _Jv_FindClass (sym.class_name, NULL);
|
||||||
_Jv_Method *meth = NULL;
|
_Jv_Method *meth = NULL;
|
||||||
const _Jv_Utf8Const *signature = sym.signature;
|
const _Jv_Utf8Const *signature = sym.signature;
|
||||||
|
|
@ -1687,7 +1695,13 @@ _Jv_LinkSymbolTable(jclass klass)
|
||||||
sym.signature);
|
sym.signature);
|
||||||
|
|
||||||
if (meth != NULL)
|
if (meth != NULL)
|
||||||
klass->atable->addresses[index] = meth->ncode;
|
{
|
||||||
|
if (meth->ncode) // Maybe abstract?
|
||||||
|
klass->atable->addresses[index] = meth->ncode;
|
||||||
|
else if (_Jv_IsInterpretedClass (target_class))
|
||||||
|
_Jv_Defer_Resolution (target_class, meth,
|
||||||
|
&klass->atable->addresses[index]);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
klass->atable->addresses[index] = (void *)_Jv_ThrowNoSuchMethodError;
|
klass->atable->addresses[index] = (void *)_Jv_ThrowNoSuchMethodError;
|
||||||
|
|
||||||
|
|
@ -1743,6 +1757,27 @@ _Jv_LinkSymbolTable(jclass klass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For each catch_record in the list of caught classes, fill in the
|
||||||
|
// address field.
|
||||||
|
void
|
||||||
|
_Jv_linkExceptionClassTable (jclass self)
|
||||||
|
{
|
||||||
|
struct _Jv_CatchClass *catch_record = self->catch_classes;
|
||||||
|
if (!catch_record || catch_record->classname)
|
||||||
|
return;
|
||||||
|
catch_record++;
|
||||||
|
while (catch_record->classname)
|
||||||
|
{
|
||||||
|
jclass target_class = _Jv_FindClass (catch_record->classname,
|
||||||
|
self->getClassLoaderInternal ());
|
||||||
|
*catch_record->address = target_class;
|
||||||
|
catch_record++;
|
||||||
|
}
|
||||||
|
self->catch_classes->classname = (_Jv_Utf8Const *)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Returns true if METH should get an entry in a VTable.
|
// Returns true if METH should get an entry in a VTable.
|
||||||
static jboolean
|
static jboolean
|
||||||
isVirtualMethod (_Jv_Method *meth)
|
isVirtualMethod (_Jv_Method *meth)
|
||||||
|
|
@ -1772,6 +1807,26 @@ _Jv_LayoutVTableMethods (jclass klass)
|
||||||
|
|
||||||
jclass superclass = klass->superclass;
|
jclass superclass = klass->superclass;
|
||||||
|
|
||||||
|
typedef unsigned int uaddr __attribute__ ((mode (pointer)));
|
||||||
|
|
||||||
|
// If superclass looks like a constant pool entry,
|
||||||
|
// resolve it now.
|
||||||
|
if ((uaddr)superclass < (uaddr)klass->constants.size)
|
||||||
|
{
|
||||||
|
if (klass->state < JV_STATE_LINKED)
|
||||||
|
{
|
||||||
|
_Jv_Utf8Const *name = klass->constants.data[(int)superclass].utf8;
|
||||||
|
superclass = _Jv_FindClass (name, klass->loader);
|
||||||
|
if (! superclass)
|
||||||
|
{
|
||||||
|
jstring str = _Jv_NewStringUTF (name->data);
|
||||||
|
throw new java::lang::NoClassDefFoundError (str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
superclass = klass->constants.data[(int)superclass].clazz;
|
||||||
|
}
|
||||||
|
|
||||||
if (superclass != NULL && superclass->vtable_method_count == -1)
|
if (superclass != NULL && superclass->vtable_method_count == -1)
|
||||||
{
|
{
|
||||||
JvSynchronize sync (superclass);
|
JvSynchronize sync (superclass);
|
||||||
|
|
|
||||||
|
|
@ -575,6 +575,16 @@ _Jv_PrepareClass(jclass klass)
|
||||||
_Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth);
|
_Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth);
|
||||||
_Jv_VerifyMethod (im);
|
_Jv_VerifyMethod (im);
|
||||||
clz->methods[i].ncode = im->ncode ();
|
clz->methods[i].ncode = im->ncode ();
|
||||||
|
|
||||||
|
// Resolve ctable entries pointing to this method. See
|
||||||
|
// _Jv_Defer_Resolution.
|
||||||
|
void **code = (void **)imeth->deferred;
|
||||||
|
while (code)
|
||||||
|
{
|
||||||
|
void **target = (void **)*code;
|
||||||
|
*code = clz->methods[i].ncode;
|
||||||
|
code = target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue