aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libjava/ChangeLog9
-rw-r--r--libjava/include/jvm.h1
-rw-r--r--libjava/link.cc12
-rw-r--r--libjava/verify.cc49
4 files changed, 59 insertions, 12 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 051484c..a81a389 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -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.
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index 235c8ed..61e426f 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -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);
diff --git a/libjava/link.cc b/libjava/link.cc
index 8dd809b..cfaa3cd 100644
--- a/libjava/link.cc
+++ b/libjava/link.cc
@@ -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.
diff --git a/libjava/verify.cc b/libjava/verify.cc
index 988b5aa..9df0316 100644
--- a/libjava/verify.cc
+++ b/libjava/verify.cc
@@ -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;