java-tree.h (otable_methods, [...]): New field/global tree definitions.

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.

From-SVN: r48038
This commit is contained in:
Bryce McKinlay 2001-12-15 08:31:49 +00:00 committed by Bryce McKinlay
parent ed86a83d51
commit 861ef92859
13 changed files with 550 additions and 29 deletions

View file

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