re PR java/20056 ('verification failed: incompatible type on stack' with --indirect...
authorTom Tromey <tromey@redhat.com>
Sat, 19 Feb 2005 01:16:30 +0000 (01:16 +0000)
committerTom Tromey <tromey@gcc.gnu.org>
Sat, 19 Feb 2005 01:16:30 +0000 (01:16 +0000)
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

libjava/ChangeLog
libjava/include/jvm.h
libjava/link.cc
libjava/verify.cc

index 051484c35a5ad407717f29a6fd262d7ba1604460..a81a389ff19e422cbffe3831dc691b50575bd294 100644 (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.
index 235c8ed21cca5da1497349fcbd3fd38060acc71b..61e426f2e663c5fb3738dff6fe395e580b9de206 100644 (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);
index 8dd809b868787f6eee9adb87a38b6e0b8c95c96a..cfaa3cd363d6d3186cbff354d41b74a805f0c870 100644 (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.
index 988b5aab67ee6139a0d83a2ee383cb83e178cd33..9df031634fa6b33ab99d731fedc047f9227c8935 100644 (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;