re PR libgcj/18868 (Interface containing anonymous class breaks gij)

PR libgcj/18868:
	* include/jvm.h (_Jv_Linker::find_field): Declare.
	(_Jv_Linker::find_field_helper): Likewise.
	* link.cc (find_field_helper): New method.
	(find_field): Likewise.
	(resolve_pool_entry): Use it.  Throw NoSuchFieldError when field
	not found.
	(link_symbol_table): Use find_field.

From-SVN: r93151
This commit is contained in:
Tom Tromey 2005-01-10 19:21:46 +00:00 committed by Tom Tromey
parent 8a7f33c709
commit 0006c7b00d
3 changed files with 134 additions and 154 deletions

View File

@ -1,3 +1,14 @@
2005-01-10 Tom Tromey <tromey@redhat.com>
PR libgcj/18868:
* include/jvm.h (_Jv_Linker::find_field): Declare.
(_Jv_Linker::find_field_helper): Likewise.
* link.cc (find_field_helper): New method.
(find_field): Likewise.
(resolve_pool_entry): Use it. Throw NoSuchFieldError when field
not found.
(link_symbol_table): Use find_field.
2005-01-10 Michael Koch <konqueror@gmx.de>
PR libgcj/18014

View File

@ -1,6 +1,6 @@
// jvm.h - Header file for private implementation information. -*- c++ -*-
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
This file is part of libgcj.
@ -250,6 +250,9 @@ namespace gcj
class _Jv_Linker
{
private:
static _Jv_Field *find_field_helper(jclass, _Jv_Utf8Const *, jclass *);
static _Jv_Field *find_field(jclass, jclass, _Jv_Utf8Const *,
_Jv_Utf8Const *);
static void prepare_constant_time_tables(jclass);
static jshort get_interfaces(jclass, _Jv_ifaces *);
static void link_symbol_table(jclass);

View File

@ -1,6 +1,6 @@
// link.cc - Code for linking and resolving classes and pool entries.
/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation
This file is part of libgcj.
@ -94,6 +94,109 @@ _Jv_Linker::resolve_field (_Jv_Field *field, java::lang::ClassLoader *loader)
}
}
// A helper for find_field that knows how to recursively search
// superclasses and interfaces.
_Jv_Field *
_Jv_Linker::find_field_helper (jclass search, _Jv_Utf8Const *name,
jclass *declarer)
{
while (search)
{
// From 5.4.3.2. First search class itself.
for (int i = 0; i < search->field_count; ++i)
{
_Jv_Field *field = &search->fields[i];
if (_Jv_equalUtf8Consts (field->name, name))
{
*declarer = search;
return field;
}
}
// Next search direct interfaces.
for (int i = 0; i < search->interface_count; ++i)
{
_Jv_Field *result = find_field_helper (search->interfaces[i], name,
declarer);
if (result)
return result;
}
// Now search superclass.
search = search->superclass;
}
return NULL;
}
// Find a field.
// KLASS is the class that is requesting the field.
// OWNER is the class in which the field should be found.
// FIELD_TYPE_NAME is the type descriptor for the field.
// This function does the class loader type checks, and
// also access checks. Returns the field, or throws an
// exception on error.
_Jv_Field *
_Jv_Linker::find_field (jclass klass, jclass owner,
_Jv_Utf8Const *field_name,
_Jv_Utf8Const *field_type_name)
{
jclass field_type = 0;
if (owner->loader != klass->loader)
{
// FIXME: The implementation of this function
// (_Jv_FindClassFromSignature) will generate an instance of
// _Jv_Utf8Const for each call if the field type is a class name
// (Lxx.yy.Z;). This may be too expensive to do for each and
// every fieldref being resolved. For now, we fix the problem
// by only doing it when we have a loader different from the
// class declaring the field.
field_type = _Jv_FindClassFromSignature (field_type_name->chars(),
klass->loader);
}
jclass found_class = 0;
_Jv_Field *the_field = find_field_helper (owner, field_name, &found_class);
if (the_field == 0)
{
java::lang::StringBuffer *sb = new java::lang::StringBuffer();
sb->append(JvNewStringLatin1("field "));
sb->append(owner->getName());
sb->append(JvNewStringLatin1("."));
sb->append(_Jv_NewStringUTF(field_name->chars()));
sb->append(JvNewStringLatin1(" was not found."));
throw new java::lang::NoSuchFieldError (sb->toString());
}
if (_Jv_CheckAccess (klass, found_class, the_field->flags))
{
// Resolve the field using the class' own loader if necessary.
if (!the_field->isResolved ())
resolve_field (the_field, found_class->loader);
if (field_type != 0 && the_field->type != field_type)
throw new java::lang::LinkageError
(JvNewStringLatin1
("field type mismatch with different loaders"));
}
else
{
java::lang::StringBuffer *sb
= new java::lang::StringBuffer ();
sb->append(klass->getName());
sb->append(JvNewStringLatin1(": "));
sb->append(found_class->getName());
sb->append(JvNewStringLatin1("."));
sb->append(_Jv_NewStringUtf8Const (field_name));
throw new java::lang::IllegalAccessError(sb->toString());
}
return the_field;
}
_Jv_word
_Jv_Linker::resolve_pool_entry (jclass klass, int index)
{
@ -173,72 +276,8 @@ _Jv_Linker::resolve_pool_entry (jclass klass, int index)
_Jv_Utf8Const *field_name = pool->data[name_index].utf8;
_Jv_Utf8Const *field_type_name = pool->data[type_index].utf8;
// FIXME: The implementation of this function
// (_Jv_FindClassFromSignature) will generate an instance of
// _Jv_Utf8Const for each call if the field type is a class name
// (Lxx.yy.Z;). This may be too expensive to do for each and
// every fieldref being resolved. For now, we fix the problem by
// only doing it when we have a loader different from the class
// declaring the field.
jclass field_type = 0;
if (owner->loader != klass->loader)
field_type = _Jv_FindClassFromSignature (field_type_name->chars(),
klass->loader);
_Jv_Field* the_field = 0;
for (jclass cls = owner; cls != 0; cls = cls->getSuperclass ())
{
for (int i = 0; i < cls->field_count; i++)
{
_Jv_Field *field = &cls->fields[i];
if (! _Jv_equalUtf8Consts (field->name, field_name))
continue;
if (_Jv_CheckAccess (klass, cls, field->flags))
{
// Resolve the field using the class' own loader if
// necessary.
if (!field->isResolved ())
resolve_field (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;
}
else
{
java::lang::StringBuffer *sb
= new java::lang::StringBuffer ();
sb->append(klass->getName());
sb->append(JvNewStringLatin1(": "));
sb->append(cls->getName());
sb->append(JvNewStringLatin1("."));
sb->append(_Jv_NewStringUtf8Const (field_name));
throw new java::lang::IllegalAccessError(sb->toString());
}
}
}
end_of_field_search:
if (the_field == 0)
{
java::lang::StringBuffer *sb = new java::lang::StringBuffer();
sb->append(JvNewStringLatin1("field "));
sb->append(owner->getName());
sb->append(JvNewStringLatin1("."));
sb->append(_Jv_NewStringUTF(field_name->chars()));
sb->append(JvNewStringLatin1(" was not found."));
throw
new java::lang::IncompatibleClassChangeError (sb->toString());
}
_Jv_Field *the_field = find_field (klass, owner, field_name,
field_type_name);
pool->data[index].field = the_field;
pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
@ -296,7 +335,7 @@ _Jv_Linker::resolve_pool_entry (jclass klass, int index)
ifaces.list = (jclass *) _Jv_Malloc (ifaces.len
* sizeof (jclass *));
get_interfaces (owner, &ifaces);
get_interfaces (owner, &ifaces);
for (int i = 0; i < ifaces.count; i++)
{
@ -885,55 +924,15 @@ _Jv_Linker::link_symbol_table (jclass klass)
continue;
}
// try fields
// Try fields.
{
_Jv_Field *the_field = NULL;
wait_for_state(target_class, JV_STATE_PREPARED);
for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
{
for (int i = 0; i < cls->field_count; i++)
{
_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 ())
resolve_field (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;
if (debug_link)
fprintf (stderr, " offsets[%d] = %d (class %s@%p : %s)\n",
(int)index,
(int)field->u.boffset,
(const char*)cls->name->chars(),
cls,
(const char*)field->name->chars());
goto end_of_field_search;
}
}
end_of_field_search:
if (the_field != NULL)
{
if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
throw new java::lang::IncompatibleClassChangeError;
else
klass->otable->offsets[index] = the_field->u.boffset;
}
_Jv_Field *the_field = find_field (klass, target_class,
sym.name, sym.signature);
if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
throw new java::lang::IncompatibleClassChangeError;
else
{
throw new java::lang::NoSuchFieldError
(_Jv_NewStringUtf8Const (sym.name));
}
klass->otable->offsets[index] = the_field->u.boffset;
}
}
@ -1005,48 +1004,15 @@ _Jv_Linker::link_symbol_table (jclass klass)
continue;
}
// try fields
// Try fields.
{
_Jv_Field *the_field = NULL;
wait_for_state(target_class, JV_STATE_PREPARED);
for (jclass cls = target_class; cls != 0; cls = cls->getSuperclass ())
{
for (int i = 0; i < cls->field_count; i++)
{
_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 ())
resolve_field (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;
}
}
end_of_static_field_search:
if (the_field != NULL)
{
if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
klass->atable->addresses[index] = the_field->u.addr;
else
throw new java::lang::IncompatibleClassChangeError;
}
_Jv_Field *the_field = find_field (klass, target_class,
sym.name, sym.signature);
if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
klass->atable->addresses[index] = the_field->u.addr;
else
{
throw new java::lang::NoSuchFieldError
(_Jv_NewStringUtf8Const (sym.name));
}
throw new java::lang::IncompatibleClassChangeError;
}
}