Commit e207dbea by Tom Tromey Committed by Tom Tromey

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
parent 1870a43b
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> 2005-02-18 Anthony Green <green@redhat.com>
* NEWS: Draft of libgcj NEWS for 4.0. * NEWS: Draft of libgcj NEWS for 4.0.
......
...@@ -278,6 +278,7 @@ private: ...@@ -278,6 +278,7 @@ private:
public: public:
static bool has_field_p (jclass, _Jv_Utf8Const *);
static void print_class_loaded (jclass); static void print_class_loaded (jclass);
static void resolve_class_ref (jclass, jclass *); static void resolve_class_ref (jclass, jclass *);
static void wait_for_state(jclass, int); static void wait_for_state(jclass, int);
......
...@@ -131,6 +131,18 @@ _Jv_Linker::find_field_helper (jclass search, _Jv_Utf8Const *name, ...@@ -131,6 +131,18 @@ _Jv_Linker::find_field_helper (jclass search, _Jv_Utf8Const *name,
return NULL; 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. // Find a field.
// KLASS is the class that is requesting the field. // KLASS is the class that is requesting the field.
// OWNER is the class in which the field should be found. // OWNER is the class in which the field should be found.
......
// verify.cc - verify bytecode // 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. This file is part of libgcj.
...@@ -751,6 +751,20 @@ private: ...@@ -751,6 +751,20 @@ private:
return klass->compatible(k.klass, verifier); 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 bool isvoid () const
{ {
return key == void_type; return key == void_type;
...@@ -1963,7 +1977,9 @@ private: ...@@ -1963,7 +1977,9 @@ private:
} }
// Return field's type, compute class' type if requested. // 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; _Jv_Utf8Const *name, *field_type;
type ct = handle_field_or_method (index, type ct = handle_field_or_method (index,
...@@ -1971,9 +1987,25 @@ private: ...@@ -1971,9 +1987,25 @@ private:
&name, &field_type); &name, &field_type);
if (class_type) if (class_type)
*class_type = ct; *class_type = ct;
type result;
if (field_type->first() == '[' || field_type->first() == 'L') if (field_type->first() == '[' || field_type->first() == 'L')
return type (field_type, this); result = type (field_type, this);
return get_type_val_for_signature (field_type->first()); 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, type check_method_constant (int index, bool is_interface,
...@@ -2783,15 +2815,8 @@ private: ...@@ -2783,15 +2815,8 @@ private:
case op_putfield: case op_putfield:
{ {
type klass; type klass;
type field = check_field_constant (get_ushort (), &klass); type field = check_field_constant (get_ushort (), &klass, true);
pop_type (field); 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); pop_type (klass);
} }
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment