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:
parent
1870a43b3e
commit
e207dbea74
4 changed files with 59 additions and 12 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue