aboutsummaryrefslogtreecommitdiff
path: root/libjava
diff options
context:
space:
mode:
authorAndrew Haley <aph@redhat.com>2003-10-24 09:29:43 +0000
committerAndrew Haley <aph@gcc.gnu.org>2003-10-24 09:29:43 +0000
commit904715853c40f9a27b492794a6db817ea89a553a (patch)
tree8c726fb42c811bb6652ba1a759bae78c2c8d9378 /libjava
parentc769a35d59f282465c1a344617bf04d595e8c477 (diff)
downloadgcc-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 'libjava')
-rw-r--r--libjava/ChangeLog26
-rw-r--r--libjava/defineclass.cc2
-rw-r--r--libjava/exception.cc28
-rw-r--r--libjava/include/java-interp.h31
-rw-r--r--libjava/java/lang/Class.h10
-rw-r--r--libjava/java/lang/natClass.cc65
-rw-r--r--libjava/resolve.cc10
7 files changed, 149 insertions, 23 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 742e94b..72b4d6c 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -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
diff --git a/libjava/defineclass.cc b/libjava/defineclass.cc
index 4cd4f4f..2e8b4d9 100644
--- a/libjava/defineclass.cc
+++ b/libjava/defineclass.cc
@@ -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))
{
diff --git a/libjava/exception.cc b/libjava/exception.cc
index 9647d44..088d482 100644
--- a/libjava/exception.cc
+++ b/libjava/exception.cc
@@ -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;
diff --git a/libjava/include/java-interp.h b/libjava/include/java-interp.h
index c801274..94acfae 100644
--- a/libjava/include/java-interp.h
+++ b/libjava/include/java-interp.h
@@ -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)
{
diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h
index cdfdd7d..01761af 100644
--- a/libjava/java/lang/Class.h
+++ b/libjava/java/lang/Class.h
@@ -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.
diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc
index c9b7014..2d80ce2 100644
--- a/libjava/java/lang/natClass.cc
+++ b/libjava/java/lang/natClass.cc
@@ -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);
diff --git a/libjava/resolve.cc b/libjava/resolve.cc
index ce1af8d..d71e125 100644
--- a/libjava/resolve.cc
+++ b/libjava/resolve.cc
@@ -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;
+ }
}
}