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:
Andrew Haley 2003-10-24 09:29:43 +00:00 committed by Andrew Haley
parent c769a35d59
commit 904715853c
14 changed files with 360 additions and 66 deletions

View File

@ -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.

View File

@ -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)
{

View File

@ -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);

View File

@ -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
else if (is_compiled_class (type) && !flag_indirect_dispatch)
{
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];
tree decl;
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);
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) = cinit;
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, 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;
}

View File

@ -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) \

View File

@ -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 ();

View File

@ -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"

View File

@ -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>
* java/lang/natObject.cc (_Jv_ObjectCheckMonitor): Use

View File

@ -1270,6 +1270,7 @@ void _Jv_ClassReader::handleCodeAttribute
_Jv_InterpMethod *method =
(_Jv_InterpMethod*) (_Jv_AllocBytes (size));
method->deferred = NULL;
method->max_stack = max_stack;
method->max_locals = max_locals;
method->code_length = code_length;
@ -1328,6 +1329,7 @@ void _Jv_ClassReader::handleMethodsEnd ()
m->self = method;
m->function = NULL;
def->interpreted_methods[i] = m;
m->deferred = NULL;
if ((method->accflags & Modifier::STATIC))
{

View File

@ -161,7 +161,7 @@ parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
return p;
}
static jclass
static void **
get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
{
_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);
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.
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))
{
handler_switch_value = ar_filter;

View File

@ -88,6 +88,12 @@ protected:
// Size of raw arguments.
_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:
_Jv_Method *get_method ()
{
@ -167,8 +173,33 @@ class _Jv_InterpClass : public java::lang::Class
#endif
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 **
_Jv_GetFirstMethod (_Jv_InterpClass *klass)
{

View File

@ -131,6 +131,12 @@ struct _Jv_AddressTable
void *addresses[];
};
struct _Jv_CatchClass
{
java::lang::Class **address;
_Jv_Utf8Const *classname;
};
#define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
#define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
@ -336,6 +342,7 @@ private:
friend void _Jv_LayoutVTableMethods (jclass klass);
friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
friend void _Jv_MakeVTable (jclass);
friend void _Jv_linkExceptionClassTable (jclass);
friend jboolean _Jv_CheckAccess (jclass self_klass, jclass other_klass,
jint flags);
@ -365,6 +372,8 @@ private:
friend void _Jv_PrepareClass (jclass);
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_InterpClass;
friend class _Jv_InterpMethod;
@ -414,6 +423,7 @@ private:
_Jv_MethodSymbol *otable_syms;
_Jv_AddressTable *atable;
_Jv_MethodSymbol *atable_syms;
_Jv_CatchClass *catch_classes;
// Interfaces implemented by this class.
jclass *interfaces;
// The class loader for this class.

View File

@ -12,6 +12,7 @@ details. */
#include <limits.h>
#include <string.h>
#include <stddef.h>
#pragma implementation "Class.h"
@ -56,7 +57,7 @@ details. */
#include <gnu/gcj/RawData.h>
#include <java-cpool.h>
#include <java-interp.h>
using namespace gcj;
@ -796,6 +797,8 @@ java::lang::Class::initializeClass (void)
if (otable || atable)
_Jv_LinkSymbolTable(this);
_Jv_linkExceptionClassTable (this);
// Steps 8, 9, 10, 11.
try
{
@ -1541,14 +1544,18 @@ _Jv_LinkSymbolTable(jclass klass)
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);
_Jv_Method *meth = NULL;
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)
continue;
@ -1658,6 +1665,7 @@ _Jv_LinkSymbolTable(jclass klass)
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);
_Jv_Method *meth = NULL;
const _Jv_Utf8Const *signature = sym.signature;
@ -1687,7 +1695,13 @@ _Jv_LinkSymbolTable(jclass klass)
sym.signature);
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
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.
static jboolean
isVirtualMethod (_Jv_Method *meth)
@ -1772,6 +1807,26 @@ _Jv_LayoutVTableMethods (jclass klass)
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)
{
JvSynchronize sync (superclass);

View File

@ -575,6 +575,16 @@ _Jv_PrepareClass(jclass klass)
_Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth);
_Jv_VerifyMethod (im);
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;
}
}
}