jcf-parse.c (java_parse_file): Write otable and atable.

2003-10-01  Andrew Haley  <aph@redhat.com>

        * jcf-parse.c (java_parse_file): Write otable and atable.
        * java-tree.h (atable_methods): New.
        (atable_decl): New.
        (atable_syms_decl): New.
        (enum java_tree_index): Add JTI_ATABLE_METHODS, JTI_ATABLE_DECL,
        JTI_ATABLE_SYMS_DECL.  Rename JTI_METHOD_SYMBOL* to JTI_SYMBOL*.
        (symbol_*type): Rename method_symbol* to symbol*type.
        (emit_offset_symbol_table): Delete.
        (emit_symbol_table): New.
        (get_symbol_table_index): New.
        (atable_type): New.
        * expr.c (build_field_ref): Handle flag_indirect_dispatch.
        (build_known_method_ref): Likewise.
        (get_symbol_table_index): Rename from get_offset_table_index.
        Parameterize to allow re-use by differing types of symbol table.
        (build_invokevirtual): Pass table to get_offset_table_index.
        * decl.c (java_init_decl_processing): Push types and decls for
        atable and atable_syyms.
        * class.c (build_static_field_ref): Handle flag_indirect_dispatch.
        (make_class_data): Add new fields atable and atable_syms.
        (emit_symbol_table): Rename from emit_offset_symbol_table.
        Parameterize to allow re-use by different types of symbol table.
        (build_symbol_entry): Renamed from build_method_symbols_entry.

2003-10-01  Andrew Haley  <aph@redhat.com>

        * java/lang/natClass.cc (initializeClass): Check for otable and
        atable.
        (_Jv_LinkOffsetTable): Check for existence of atable.  Rewrite
        loops using for().  Search superinterfaces.  Check for fields as
        well as methods.  Initialize atable as well as otable: check for
        static methods as well as virtual methods.
        * java/lang/Class.h (struct _Jv_AddressTable): New.
        (atable): New.
        (atable_syms): New.
        * include/jvm.h (_Jv_equalUtf8Consts): constify.
        * prims.cc (_Jv_equalUtf8Consts): constify.

From-SVN: r71979
This commit is contained in:
Andrew Haley 2003-10-01 16:22:13 +00:00 committed by Andrew Haley
parent 530ce5517c
commit 9dfc2ec225
12 changed files with 474 additions and 153 deletions

View file

@ -125,6 +125,12 @@ struct _Jv_OffsetTable
jint offsets[];
};
struct _Jv_AddressTable
{
jint state;
void *addresses[];
};
#define JV_PRIMITIVE_VTABLE ((_Jv_VTable *) -1)
#define JV_CLASS(Obj) ((jclass) (*(_Jv_VTable **) Obj)->clas)
@ -324,7 +330,7 @@ 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_LinkSymbolTable (jclass);
friend void _Jv_LayoutVTableMethods (jclass klass);
friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *);
friend void _Jv_MakeVTable (jclass);
@ -404,6 +410,8 @@ private:
_Jv_OffsetTable *otable;
// Offset table symbols.
_Jv_MethodSymbol *otable_syms;
_Jv_AddressTable *atable;
_Jv_MethodSymbol *atable_syms;
// Interfaces implemented by this class.
jclass *interfaces;
// The class loader for this class.

View file

@ -36,6 +36,7 @@ details. */
#include <java/lang/IllegalAccessError.h>
#include <java/lang/IllegalArgumentException.h>
#include <java/lang/IncompatibleClassChangeError.h>
#include <java/lang/NoSuchFieldError.h>
#include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/InstantiationException.h>
#include <java/lang/NoClassDefFoundError.h>
@ -790,7 +791,7 @@ java::lang::Class::initializeClass (void)
so ensure internal tables are built. */
_Jv_PrepareConstantTimeTables (this);
_Jv_MakeVTable(this);
_Jv_LinkOffsetTable(this);
_Jv_LinkSymbolTable(this);
return;
}
@ -830,8 +831,8 @@ java::lang::Class::initializeClass (void)
if (vtable == NULL)
_Jv_MakeVTable(this);
if (otable != NULL && otable->state == 0)
_Jv_LinkOffsetTable(this);
if (otable || atable)
_Jv_LinkSymbolTable(this);
// Steps 8, 9, 10, 11.
try
@ -1533,75 +1534,238 @@ java::lang::Class::getProtectionDomain0 ()
return protectionDomain;
}
// Functions for indirect dispatch (symbolic virtual method binding) support.
// Functions for indirect dispatch (symbolic virtual binding) support.
// There are two tables, atable and otable. atable is an array of
// addresses, and otable is an array of offsets, and these are used
// for static and virtual members respectively.
// {a,o}table_syms is an array of _Jv_MethodSymbols. Each such symbol
// is a tuple of {classname, member name, signature}.
// _Jv_LinkSymbolTable() scans these two arrays and fills in the
// corresponding atable and otable with the addresses of static
// members and the offsets of virtual members.
// The offset (in bytes) for each resolved method or field is placed
// at the corresponding position in the virtual method offset table
// (klass->otable).
// The same otable and atable may be shared by many classes.
// 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)
_Jv_LinkSymbolTable(jclass klass)
{
//// FIXME: Need to lock the otable ////
//// FIXME: Need to lock the tables ////
int index = 0;
_Jv_MethodSymbol sym;
if (klass->otable == NULL
|| klass->otable->state != 0)
return;
goto atable;
klass->otable->state = 1;
int index = 0;
_Jv_MethodSymbol sym = klass->otable_syms[0];
while (sym.name != NULL)
for (index = 0; sym = klass->otable_syms[index], sym.name != NULL; index++)
{
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;
if (target_class != NULL)
if (target_class->isInterface())
if (target_class == NULL)
continue;
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 (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
{
for (int i=0; i < cls->method_count; i++)
{
meth = &cls->methods[i];
if (_Jv_equalUtf8Consts (sym.name, meth->name)
&& _Jv_equalUtf8Consts (signature, meth->signature))
{
klass->otable->offsets[index] = i + 1;
goto found;
}
}
}
found:
continue;
}
// We're looking for a field or a method, and we can tell
// which is needed by looking at the signature.
if (signature->length >= 2
&& signature->data[0] == '(')
{
// 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);
}
continue;
}
// try fields
{
_Jv_Field *the_field = NULL;
for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
{
// 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++)
for (int i = 0; i < cls->field_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;
}
_Jv_Field *field = &cls->fields[i];
if (! _Jv_equalUtf8Consts (field->name, sym.name))
continue;
// FIXME: What access checks should we perform here?
// if (_Jv_CheckAccess (klass, cls, field->flags))
// {
if (!field->isResolved ())
_Jv_ResolveField (field, cls->loader);
// if (field_type != 0 && field->type != field_type)
// throw new java::lang::LinkageError
// (JvNewStringLatin1
// ("field type mismatch with different loaders"));
the_field = field;
goto end_of_field_search;
}
}
end_of_field_search:
if (the_field != NULL)
{
if (the_field->flags & 0x0008 /* Modifier::STATIC */)
{
throw new java::lang::IncompatibleClassChangeError;
}
else
{
klass->otable->offsets[index] = the_field->u.boffset;
}
}
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);
}
throw new java::lang::NoSuchFieldError
(_Jv_NewStringUtf8Const (sym.name));
}
}
}
meth = _Jv_LookupDeclaredMethod(target_class, sym.name,
sym.signature);
atable:
if (klass->atable == NULL
|| klass->atable->state != 0)
return;
if (meth != NULL)
klass->atable->state = 1;
for (index = 0; sym = klass->atable_syms[index], sym.name != NULL; index++)
{
jclass target_class = _Jv_FindClass (sym.class_name, NULL);
_Jv_Method *meth = NULL;
const _Jv_Utf8Const *signature = sym.signature;
// ??? Setting this pointer to null will at least get us a
// NullPointerException
klass->atable->addresses[index] = NULL;
if (target_class == NULL)
continue;
// We're looking for a static field or a static method, and we
// can tell which is needed by looking at the signature.
if (signature->length >= 2
&& signature->data[0] == '(')
{
// 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->atable->addresses[index] = meth->ncode;
else
klass->atable->addresses[index] = (void *)_Jv_ThrowNoSuchMethodError;
continue;
}
// try fields
{
_Jv_Field *the_field = NULL;
for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
{
for (int i = 0; i < cls->field_count; i++)
{
klass->otable->offsets[index] =
_Jv_VTable::idx_to_offset (meth->index);
_Jv_Field *field = &cls->fields[i];
if (! _Jv_equalUtf8Consts (field->name, sym.name))
continue;
// FIXME: What access checks should we perform here?
// if (_Jv_CheckAccess (klass, cls, field->flags))
// {
if (!field->isResolved ())
_Jv_ResolveField (field, cls->loader);
// if (field_type != 0 && field->type != field_type)
// throw new java::lang::LinkageError
// (JvNewStringLatin1
// ("field type mismatch with different loaders"));
the_field = field;
goto end_of_static_field_search;
}
}
if (meth == NULL)
// FIXME: This should be special index for ThrowNoSuchMethod().
klass->otable->offsets[index] = -1;
sym = klass->otable_syms[++index];
end_of_static_field_search:
if (the_field != NULL)
{
if (the_field->flags & 0x0008 /* Modifier::STATIC */)
{
klass->atable->addresses[index] = the_field->u.addr;
}
else
{
throw new java::lang::IncompatibleClassChangeError;
}
}
else
{
throw new java::lang::NoSuchFieldError
(_Jv_NewStringUtf8Const (sym.name));
}
}
}
}