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 /libjava | |
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 'libjava')
-rw-r--r-- | libjava/ChangeLog | 26 | ||||
-rw-r--r-- | libjava/defineclass.cc | 2 | ||||
-rw-r--r-- | libjava/exception.cc | 28 | ||||
-rw-r--r-- | libjava/include/java-interp.h | 31 | ||||
-rw-r--r-- | libjava/java/lang/Class.h | 10 | ||||
-rw-r--r-- | libjava/java/lang/natClass.cc | 65 | ||||
-rw-r--r-- | libjava/resolve.cc | 10 |
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; + } } } |