summaryrefslogtreecommitdiff
path: root/libjava
diff options
context:
space:
mode:
authorbryce <bryce@138bc75d-0d04-0410-961f-82ee72b054a4>2001-12-15 08:31:49 +0000
committerbryce <bryce@138bc75d-0d04-0410-961f-82ee72b054a4>2001-12-15 08:31:49 +0000
commitbee0e6ed4aac405fc7e97f44c491966e086649ba (patch)
treea15d17366ad109cb78a0bc4f4aaf8e142550387d /libjava
parent9eba6a12358d924eec800f1f9b9fd4c398acd788 (diff)
downloadgcc-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/ChangeLog16
-rw-r--r--libjava/include/jvm.h6
-rw-r--r--libjava/java/lang/Class.h23
-rw-r--r--libjava/java/lang/natClass.cc193
-rw-r--r--libjava/java/lang/natClassLoader.cc7
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 ();
}