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:
parent
ed86a83d51
commit
861ef92859
13 changed files with 550 additions and 29 deletions
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue