re PR java/20056 ('verification failed: incompatible type on stack' with --indirect-dispatch)

PR java/20056:
	* include/jvm.h (_Jv_Linker::has_field_p): Declare.
	* link.cc (has_field_p): New function.
	* verify.cc (check_field_constant): Added 'putfield' argument.
	(verify_instructions_0): Updated.
	(type::equals): New method.

From-SVN: r95259
This commit is contained in:
Tom Tromey 2005-02-19 01:16:30 +00:00 committed by Tom Tromey
parent 1870a43b3e
commit e207dbea74
4 changed files with 59 additions and 12 deletions

View file

@ -1,3 +1,12 @@
2005-02-18 Tom Tromey <tromey@redhat.com>
PR java/20056:
* include/jvm.h (_Jv_Linker::has_field_p): Declare.
* link.cc (has_field_p): New function.
* verify.cc (check_field_constant): Added 'putfield' argument.
(verify_instructions_0): Updated.
(type::equals): New method.
2005-02-18 Anthony Green <green@redhat.com>
* NEWS: Draft of libgcj NEWS for 4.0.

View file

@ -278,6 +278,7 @@ private:
public:
static bool has_field_p (jclass, _Jv_Utf8Const *);
static void print_class_loaded (jclass);
static void resolve_class_ref (jclass, jclass *);
static void wait_for_state(jclass, int);

View file

@ -131,6 +131,18 @@ _Jv_Linker::find_field_helper (jclass search, _Jv_Utf8Const *name,
return NULL;
}
bool
_Jv_Linker::has_field_p (jclass search, _Jv_Utf8Const *field_name)
{
for (int i = 0; i < search->field_count; ++i)
{
_Jv_Field *field = &search->fields[i];
if (_Jv_equalUtf8Consts (field->name, field_name))
return true;
}
return false;
}
// Find a field.
// KLASS is the class that is requesting the field.
// OWNER is the class in which the field should be found.

View file

@ -1,6 +1,6 @@
// verify.cc - verify bytecode
/* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation
/* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
This file is part of libgcj.
@ -751,6 +751,20 @@ private:
return klass->compatible(k.klass, verifier);
}
bool equals (const type &other, _Jv_BytecodeVerifier *vfy)
{
// Only works for reference types.
if (key != reference_type
|| key != uninitialized_reference_type
|| other.key != reference_type
|| other.key != uninitialized_reference_type)
return false;
// Only for single-valued types.
if (klass->ref_next || other.klass->ref_next)
return false;
return klass->equals (other.klass, vfy);
}
bool isvoid () const
{
return key == void_type;
@ -1963,7 +1977,9 @@ private:
}
// Return field's type, compute class' type if requested.
type check_field_constant (int index, type *class_type = NULL)
// If PUTFIELD is true, use the special 'putfield' semantics.
type check_field_constant (int index, type *class_type = NULL,
bool putfield = false)
{
_Jv_Utf8Const *name, *field_type;
type ct = handle_field_or_method (index,
@ -1971,9 +1987,25 @@ private:
&name, &field_type);
if (class_type)
*class_type = ct;
type result;
if (field_type->first() == '[' || field_type->first() == 'L')
return type (field_type, this);
return get_type_val_for_signature (field_type->first());
result = type (field_type, this);
else
result = get_type_val_for_signature (field_type->first());
// We have an obscure special case here: we can use `putfield' on
// a field declared in this class, even if `this' has not yet been
// initialized.
if (putfield
&& ! current_state->this_type.isinitialized ()
&& current_state->this_type.pc == type::SELF
&& current_state->this_type.equals (ct, this)
// We don't look at the signature, figuring that if it is
// wrong we will fail during linking. FIXME?
&& _Jv_Linker::has_field_p (current_class, name))
class_type->set_uninitialized (type::SELF, this);
return result;
}
type check_method_constant (int index, bool is_interface,
@ -2783,15 +2815,8 @@ private:
case op_putfield:
{
type klass;
type field = check_field_constant (get_ushort (), &klass);
type field = check_field_constant (get_ushort (), &klass, true);
pop_type (field);
// We have an obscure special case here: we can use
// `putfield' on a field declared in this class, even if
// `this' has not yet been initialized.
if (! current_state->this_type.isinitialized ()
&& current_state->this_type.pc == type::SELF)
klass.set_uninitialized (type::SELF, this);
pop_type (klass);
}
break;