using namespace gcj;
-// When true, print debugging information about class loading.
-bool gcj::verbose_class_flag;
-
typedef unsigned int uaddr __attribute__ ((mode (pointer)));
template<typename T>
// 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.
+// Fill FOUND_CLASS with the address of the class in which the field
+// is actually declared.
// 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,
+ jclass *found_class,
_Jv_Utf8Const *field_name,
_Jv_Utf8Const *field_type_name)
{
if (field_type == NULL)
throw new java::lang::NoClassDefFoundError(field_name->toString());
- jclass found_class = 0;
_Jv_Field *the_field = find_field_helper (owner, field_name,
- field_type->name, &found_class);
+ field_type->name, found_class);
if (the_field == 0)
{
throw new java::lang::NoSuchFieldError (sb->toString());
}
- if (_Jv_CheckAccess (klass, found_class, the_field->flags))
+ if (_Jv_CheckAccess (klass, *found_class, the_field->flags))
{
// Note that the field returned by find_field_helper is always
// resolved. There's no point checking class loaders here,
= new java::lang::StringBuffer ();
sb->append(klass->getName());
sb->append(JvNewStringLatin1(": "));
- sb->append(found_class->getName());
+ sb->append((*found_class)->getName());
sb->append(JvNewStringLatin1("."));
sb->append(_Jv_NewStringUtf8Const (field_name));
throw new java::lang::IllegalAccessError(sb->toString());
_Jv_Utf8Const *field_name = pool->data[name_index].utf8;
_Jv_Utf8Const *field_type_name = pool->data[type_index].utf8;
- _Jv_Field *the_field = find_field (klass, owner, field_name,
+ jclass found_class = 0;
+ _Jv_Field *the_field = find_field (klass, owner,
+ &found_class,
+ field_name,
field_type_name);
-
+ if (owner != found_class)
+ _Jv_InitClass (found_class);
pool->data[index].field = the_field;
pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
}
}
// This is put in empty vtable slots.
-static void
-_Jv_abstractMethodError (void)
+void
+_Jv_ThrowAbstractMethodError ()
{
throw new java::lang::AbstractMethodError();
}
(_Jv_GetMethodString (klass, meth));
if ((meth->accflags & Modifier::ABSTRACT) != 0)
- itable[pos] = (void *) &_Jv_abstractMethodError;
+ itable[pos] = (void *) &_Jv_ThrowAbstractMethodError;
else
itable[pos] = meth->ncode;
}
// Try fields.
{
wait_for_state(target_class, JV_STATE_PREPARED);
- _Jv_Field *the_field = find_field (klass, target_class,
+ jclass found_class;
+ _Jv_Field *the_field = find_field (klass, target_class, &found_class,
sym.name, sym.signature);
if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
throw new java::lang::IncompatibleClassChangeError;
// Try fields.
{
wait_for_state(target_class, JV_STATE_PREPARED);
- _Jv_Field *the_field = find_field (klass, target_class,
+ jclass found_class;
+ _Jv_Field *the_field = find_field (klass, target_class, &found_class,
sym.name, sym.signature);
if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
klass->atable->addresses[index] = the_field->u.addr;
if ((meth->accflags & Modifier::ABSTRACT))
// FIXME: it might be nice to have a libffi trampoline here,
// so we could pass in the method name and other information.
- vtable->set_method(meth->index, (void *) &_Jv_abstractMethodError);
+ vtable->set_method(meth->index,
+ (void *) &_Jv_ThrowAbstractMethodError);
else
vtable->set_method(meth->index, meth->ncode);
}
void
_Jv_Linker::ensure_method_table_complete (jclass klass)
{
- if (klass->vtable != NULL || klass->isInterface())
+ if (klass->vtable != NULL)
return;
// We need our superclass to have its own Miranda methods installed.
- wait_for_state (klass->getSuperclass (), JV_STATE_LOADED);
+ if (! klass->isInterface())
+ wait_for_state (klass->getSuperclass (), JV_STATE_LOADED);
// A class might have so-called "Miranda methods". This is a method
// that is declared in an interface and not re-declared in an
if (cl1 == NULL || cl2 == NULL)
continue;
- if (! _Jv_IsAssignableFromSlow (cl2, cl1))
+ if (! _Jv_IsAssignableFromSlow (cl1, cl2))
{
jstring s = JvNewStringUTF ("Incompatible types: In class ");
s = s->concat (klass->getName());
if (codesource == NULL)
codesource = "<no code source>";
- // We use a somewhat bogus test for the ABI here.
char *abi;
if (_Jv_IsInterpretedClass (klass))
abi = "bytecode";
- else if (klass->state == JV_STATE_PRELOADING)
+ else if (_Jv_IsBinaryCompatibilityABI (klass))
abi = "BC-compiled";
else
abi = "pre-compiled";
if (state >= JV_STATE_LINKED && klass->state < JV_STATE_LINKED)
{
- verify_class (klass);
+ if (gcj::verifyClasses)
+ verify_class (klass);
ensure_class_linked (klass);
link_exception_table (klass);