diff options
author | bryce <bryce@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-12-15 08:31:49 +0000 |
---|---|---|
committer | bryce <bryce@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-12-15 08:31:49 +0000 |
commit | bee0e6ed4aac405fc7e97f44c491966e086649ba (patch) | |
tree | a15d17366ad109cb78a0bc4f4aaf8e142550387d /libjava | |
parent | 9eba6a12358d924eec800f1f9b9fd4c398acd788 (diff) | |
download | gcc-bee0e6ed4aac405fc7e97f44c491966e086649ba.tar.gz |
gcc/java:
* java-tree.h (otable_methods, otable_decl, otable_syms_decl,
otable_type, otable_ptr_type, method_symbol_type,
method_symbols_array_type, method_symbols_array_ptr_type): New
field/global tree definitions.
(flag_indirect_dispatch): New flag.
* decl.c (java_init_decl_processing): Initialize new otable and
otable_syms type nodes and decls. Add new field "index" to
method_type_node.
* class.c (build_method_symbols_entry): New function.
(make_method_value): Set "index" to to method's vtable index for
virtual methods when indirect-dispatch is not used.
(make_class_data): For indirect-dispatch, dont emit the dtable_decl,
and set vtable_method_count to -1. Set otable and otable_syms field
if indirect-dispatch is used and there was something to put in them.
(build_method_symbols_entry): New function.
(emit_offset_symbol_table): New function.
* expr.c (get_offset_table_index): New function.
(build_invokevirtual): Build array reference to otable at the index
returned by get_offset_table_index, and use the result as the vtable
offset.
(build_invokeinterface): Similar.
* jcf-parse.c (yyparse): If indirect-dispatch, call
emit_offset_symbol_table at the end of compilation, after all classes
have been generated.
* jvspec.c: Don't pass findirect-dispatch to jvgenmain.
* lang.c (flag_indirect_dispatch): Define.
(lang_f_options): Add indirect-dispatch flag.
libjava:
* include/jvm.h (_Jv_VTable::idx_to_offset): New method.
* java/lang/natClassLoader.cc (_Jv_PrepareCompiledClass): Call
_Jv_MakeVTable and _Jv_LinkOffsetTable if needed.
* java/lang/Class.h (_Jv_Method): Add "index" field.
(_Jv_MethodSymbol): New struct type.
(_Jv_LinkOffsetTable, _Jv_LayoutVTableMethods, _Jv_SetVTableEntries,
_Jv_MakeVTable): Friends.
(otable, otable_syms): New Class fields.
* java/lang/natClass.cc (_Jv_LinkOffsetTable): New function.
(isVirtualMethod): New static function.
(_Jv_LayoutVTableMethods): New function.
(_Jv_SetVTableEntries): New function.
(_Jv_MakeVTable): New function.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@48038 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava')
-rw-r--r-- | libjava/ChangeLog | 16 | ||||
-rw-r--r-- | libjava/include/jvm.h | 6 | ||||
-rw-r--r-- | libjava/java/lang/Class.h | 23 | ||||
-rw-r--r-- | libjava/java/lang/natClass.cc | 193 | ||||
-rw-r--r-- | libjava/java/lang/natClassLoader.cc | 7 |
5 files changed, 243 insertions, 2 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 3a3294cc366..39375cf8612 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,5 +1,21 @@ 2001-12-15 Bryce McKinlay <bryce@waitaki.otago.ac.nz> + * include/jvm.h (_Jv_VTable::idx_to_offset): New method. + * java/lang/natClassLoader.cc (_Jv_PrepareCompiledClass): Call + _Jv_MakeVTable and _Jv_LinkOffsetTable if needed. + * java/lang/Class.h (_Jv_Method): Add "index" field. + (_Jv_MethodSymbol): New struct type. + (_Jv_LinkOffsetTable, _Jv_LayoutVTableMethods, _Jv_SetVTableEntries, + _Jv_MakeVTable): Friends. + (otable, otable_syms): New Class fields. + * java/lang/natClass.cc (_Jv_LinkOffsetTable): New function. + (isVirtualMethod): New static function. + (_Jv_LayoutVTableMethods): New function. + (_Jv_SetVTableEntries): New function. + (_Jv_MakeVTable): New function. + +2001-12-15 Bryce McKinlay <bryce@waitaki.otago.ac.nz> + * java/util/BitSet.java (and): Fix off-by-one bug, don't skip part of the bitset. (andNot): Likewise. diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h index 57ba44fbfad..ada8e11a2e1 100644 --- a/libjava/include/jvm.h +++ b/libjava/include/jvm.h @@ -57,6 +57,12 @@ struct _Jv_VTable #endif static size_t vtable_elt_size() { return sizeof(vtable_elt); } + + // Given a method index, return byte offset from the vtable pointer. + static jint idx_to_offset (int index) + { + return (2 * sizeof (void *)) + (index * vtable_elt_size ()); + } static _Jv_VTable *new_vtable (int count); }; diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h index aac5f12dd26..20523912e58 100644 --- a/libjava/java/lang/Class.h +++ b/libjava/java/lang/Class.h @@ -70,6 +70,8 @@ struct _Jv_Method _Jv_Utf8Const *signature; // Access flags. _Jv_ushort accflags; + // Method's index in the vtable. + _Jv_ushort index; // Pointer to underlying function. void *ncode; // NULL-terminated list of exception class names; can be NULL if @@ -114,6 +116,19 @@ union _Jv_Self jclass self; }; +struct _Jv_MethodSymbol +{ + _Jv_Utf8Const *class_name; + _Jv_Utf8Const *name; + _Jv_Utf8Const *signature; +}; + +struct _Jv_OffsetTable +{ + jint state; + jint offsets[]; +}; + #define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1) #define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas) @@ -303,6 +318,10 @@ private: friend jstring _Jv_GetMethodString(jclass, _Jv_Utf8Const *); friend jshort _Jv_AppendPartialITable (jclass, jclass, void **, jshort); friend jshort _Jv_FindIIndex (jclass *, jshort *, jshort); + friend void _Jv_LinkOffsetTable (jclass); + friend void _Jv_LayoutVTableMethods (jclass klass); + friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *); + friend void _Jv_MakeVTable (jclass); // Return array class corresponding to element type KLASS, creating it if // necessary. @@ -367,6 +386,10 @@ private: jshort static_field_count; // The vtbl for all objects of this class. _Jv_VTable *vtable; + // Virtual method offset table. + _Jv_OffsetTable *otable; + // Offset table symbols. + _Jv_MethodSymbol *otable_syms; // 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 54289b34102..6dfe14bab71 100644 --- a/libjava/java/lang/natClass.cc +++ b/libjava/java/lang/natClass.cc @@ -692,7 +692,7 @@ java::lang::Class::initializeClass (void) _Jv_PrepareCompiledClass (this); } } - + if (state <= JV_STATE_LINKED) _Jv_PrepareConstantTimeTables (this); @@ -1422,3 +1422,194 @@ java::lang::Class::getProtectionDomain0 () { return protectionDomain; } + +// Functions for indirect dispatch (symbolic virtual method binding) support. + +// Resolve entries in the virtual method offset symbol table +// (klass->otable_syms). The vtable offset (in bytes) for each resolved method +// is placed at the corresponding position in the virtual method offset table +// (klass->otable). A single otable and otable_syms pair may be shared by many +// classes. +void +_Jv_LinkOffsetTable(jclass klass) +{ + //// FIXME: Need to lock the otable //// + + if (klass->otable == NULL + || klass->otable->state != 0) + return; + + klass->otable->state = 1; + + int index = 0; + _Jv_MethodSymbol sym = klass->otable_syms[0]; + + while (sym.name != NULL) + { + jclass target_class = _Jv_FindClass (sym.class_name, NULL); + _Jv_Method *meth = NULL; + + if (target_class != NULL) + if (target_class->isInterface()) + { + // FIXME: This does not yet fully conform to binary compatibility + // rules. It will break if a declaration is moved into a + // superinterface. + for (int i=0; i < target_class->method_count; i++) + { + meth = &target_class->methods[i]; + if (_Jv_equalUtf8Consts (sym.name, meth->name) + && _Jv_equalUtf8Consts (sym.signature, meth->signature)) + { + klass->otable->offsets[index] = i + 1; + break; + } + } + } + else + { + // If the target class does not have a vtable_method_count yet, + // then we can't tell the offsets for its methods, so we must lay + // it out now. + if (target_class->vtable_method_count == -1) + { + JvSynchronize sync (target_class); + _Jv_LayoutVTableMethods (target_class); + } + + meth = _Jv_LookupDeclaredMethod(target_class, sym.name, + sym.signature); + + if (meth != NULL) + { + klass->otable->offsets[index] = + _Jv_VTable::idx_to_offset (meth->index); + } + } + + if (meth == NULL) + // FIXME: This should be special index for ThrowNoSuchMethod(). + klass->otable->offsets[index] = -1; + + sym = klass->otable_syms[++index]; + } +} + +// Returns true if METH should get an entry in a VTable. +static bool +isVirtualMethod (_Jv_Method *meth) +{ + using namespace java::lang::reflect; + return (((meth->accflags & (Modifier::STATIC | Modifier::PRIVATE)) == 0) + && meth->name->data[0] != '<'); +} + +// Prepare virtual method declarations in KLASS, and any superclasses as +// required, by determining their vtable index, setting method->index, and +// finally setting the class's vtable_method_count. Must be called with the +// lock for KLASS held. +void +_Jv_LayoutVTableMethods (jclass klass) +{ + if (klass->vtable != NULL || klass->isInterface() + || klass->vtable_method_count != -1) + return; + + jclass superclass = klass->superclass; + + if (superclass != NULL && superclass->vtable_method_count == -1) + { + JvSynchronize sync (superclass); + _Jv_LayoutVTableMethods (superclass); + } + + int index = (superclass == NULL ? 0 : superclass->vtable_method_count); + + for (int i = 0; i < klass->method_count; ++i) + { + _Jv_Method *meth = &klass->methods[i]; + _Jv_Method *super_meth = NULL; + + if (!isVirtualMethod(meth)) + continue; + + if (superclass != NULL) + super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name, + meth->signature); + + if (super_meth) + meth->index = super_meth->index; + else + meth->index = index++; + } + + klass->vtable_method_count = index; +} + +// Set entries in VTABLE for virtual methods declared in KLASS. If KLASS has +// an immediate abstract parent, recursivly do its methods first. +void +_Jv_SetVTableEntries (jclass klass, _Jv_VTable *vtable) +{ + using namespace java::lang::reflect; + + jclass superclass = klass->getSuperclass(); + + if (superclass != NULL && (superclass->getModifiers() & Modifier::ABSTRACT)) + _Jv_SetVTableEntries (superclass, vtable); + + for (int i = klass->method_count - 1; i >= 0; i--) + { + _Jv_Method *meth = &klass->methods[i]; + if (!isVirtualMethod(meth)) + continue; + vtable->set_method(meth->index, meth->ncode); + } +} + +// Allocate and lay out the virtual method table for KLASS. This will also +// cause vtables to be generated for any non-abstract superclasses, and +// virtual method layout to occur for any abstract superclasses. Must be +// called with monitor lock for KLASS held. +void +_Jv_MakeVTable (jclass klass) +{ + using namespace java::lang::reflect; + + if (klass->vtable != NULL || klass->isInterface() + || (klass->accflags & Modifier::ABSTRACT)) + return; + + // out before we can create a vtable. + if (klass->vtable_method_count == -1) + _Jv_LayoutVTableMethods (klass); + + // Allocate the new vtable. + _Jv_VTable *vtable = _Jv_VTable::new_vtable (klass->vtable_method_count); + klass->vtable = vtable; + + // Copy the vtable of the closest non-abstract superclass. + jclass superclass = klass->superclass; + if (superclass != NULL) + { + while ((superclass->accflags & Modifier::ABSTRACT) != 0) + superclass = superclass->superclass; + + if (superclass->vtable == NULL) + { + JvSynchronize sync (superclass); + _Jv_MakeVTable (superclass); + } + + for (int i = 0; i < superclass->vtable_method_count; ++i) + vtable->set_method (i, superclass->vtable->get_method (i)); + } + + // Set the class pointer and GC descriptor. + vtable->clas = klass; + vtable->gc_descr = _Jv_BuildGCDescr (klass); + + // For each virtual declared in klass and any immediate abstract + // superclasses, set new vtable entry or override an old one. + _Jv_SetVTableEntries (klass, vtable); +} diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc index 59aca071ea2..ffe5b18fbe0 100644 --- a/libjava/java/lang/natClassLoader.cc +++ b/libjava/java/lang/natClassLoader.cc @@ -234,7 +234,6 @@ java::lang::ClassLoader::findLoadedClass (jstring name) return _Jv_FindClassInCache (_Jv_makeUtf8Const (name), this); } - /** This function does class-preparation for compiled classes. NOTE: It contains replicated functionality from _Jv_ResolvePoolEntry, and this is intentional, since that function @@ -309,6 +308,12 @@ _Jv_PrepareCompiledClass (jclass klass) } #endif /* INTERPRETER */ + if (klass->vtable == NULL) + _Jv_MakeVTable(klass); + + if (klass->otable != NULL && klass->otable->state == 0) + _Jv_LinkOffsetTable(klass); + klass->notifyAll (); } |