* verify.cc (handle_ret_insn): Check for subroutine merge here...
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 30 Jan 2002 22:20:23 +0000 (22:20 +0000)
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 30 Jan 2002 22:20:23 +0000 (22:20 +0000)
(state::merge): ... not here.
(subr_entry_info): New structure.
(entry_points): New field.
(~_Jv_BytecodeVerifier): Correctly free jsr_ptrs.  Free
entry_points.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@49344 138bc75d-0d04-0410-961f-82ee72b054a4

libjava/ChangeLog
libjava/verify.cc

index 9c1f1c0..044f724 100644 (file)
@@ -1,3 +1,12 @@
+2002-01-30  Tom Tromey  <tromey@redhat.com>
+
+       * verify.cc (handle_ret_insn): Check for subroutine merge here...
+       (state::merge): ... not here.
+       (subr_entry_info): New structure.
+       (entry_points): New field.
+       (~_Jv_BytecodeVerifier): Correctly free jsr_ptrs.  Free
+       entry_points.
+
 2002-01-29  Tom Tromey  <tromey@redhat.com>
 
        * java/awt/List.java (addNotify): Correctly check to see if peer
index 9100831..1035cda 100644 (file)
@@ -56,6 +56,7 @@ private:
   struct state;
   struct type;
   struct subr_info;
+  struct subr_entry_info;
   struct linked_utf8;
 
   // The current PC.
@@ -84,6 +85,11 @@ private:
   // of all calling `jsr's at at each jsr target.
   subr_info **jsr_ptrs;
 
+  // We keep a linked list of entries which map each `ret' instruction
+  // to its unique subroutine entry point.  We expect that there won't
+  // be many `ret' instructions, so a linked list is ok.
+  subr_entry_info *entry_points;
+
   // The current top of the stack, in terms of slots.
   int stacktop;
   // The current depth of the stack.  This will be larger than
@@ -273,6 +279,18 @@ private:
     subr_info *next;
   };
 
+  // This is used to keep track of which subroutine entry point
+  // corresponds to which `ret' instruction.
+  struct subr_entry_info
+  {
+    // PC of the subroutine entry point.
+    int pc;
+    // PC of the `ret' instruction.
+    int ret_pc;
+    // Link.
+    subr_entry_info *next;
+  };
+
   // The `type' class is used to represent a single type in the
   // verifier.
   struct type
@@ -886,9 +904,9 @@ private:
       if (this_type.isinitialized ())
        this_type = state_old->this_type;
 
-      // Merge subroutine states.  *THIS and *STATE_OLD must be in the
-      // same subroutine.  Also, recursive subroutine calls must be
-      // avoided.
+      // Merge subroutine states.  Here we just keep track of what
+      // subroutine we think we're in.  We only check for a merge
+      // (which is invalid) when we see a `ret'.
       if (subroutine == state_old->subroutine)
        {
          // Nothing.
@@ -898,11 +916,13 @@ private:
          subroutine = state_old->subroutine;
          changed = true;
        }
-      // If we're handling the result of an unmerged `ret', then we
-      // can't trust that it has the correct PC setting.  So in this
-      // case we ignore what might otherwise look like a merge error.
-      else if (! state_old->is_unmerged_ret_state (max_locals))
-       verifier->verify_fail ("subroutines merged");
+      else
+       {
+         // If the subroutines differ, indicate that the state
+         // changed.  This is needed to detect when subroutines have
+         // merged.
+         changed = true;
+       }
 
       // Merge stacks.
       if (state_old->stacktop != stacktop)
@@ -1329,6 +1349,24 @@ private:
     if (csub == 0)
       verify_fail ("no subroutine");
 
+    // Check to see if we've merged subroutines.
+    subr_entry_info *entry;
+    for (entry = entry_points; entry != NULL; entry = entry->next)
+      {
+       if (entry->ret_pc == start_PC)
+         break;
+      }
+    if (entry == NULL)
+      {
+       entry = (subr_entry_info *) _Jv_Malloc (sizeof (subr_entry_info));
+       entry->pc = csub;
+       entry->ret_pc = start_PC;
+       entry->next = entry_points;
+       entry_points = entry;
+      }
+    else if (entry->pc != csub)
+      verify_fail ("subroutines merged");
+
     for (subr_info *subr = jsr_ptrs[csub]; subr != NULL; subr = subr->next)
       {
        // Temporarily modify the current state so it looks like we're
@@ -2893,6 +2931,7 @@ public:
     flags = NULL;
     jsr_ptrs = NULL;
     utf8_list = NULL;
+    entry_points = NULL;
   }
 
   ~_Jv_BytecodeVerifier ()
@@ -2901,8 +2940,25 @@ public:
       _Jv_Free (states);
     if (flags)
       _Jv_Free (flags);
+
     if (jsr_ptrs)
-      _Jv_Free (jsr_ptrs);
+      {
+       for (int i = 0; i < current_method->code_length; ++i)
+         {
+           if (jsr_ptrs[i] != NULL)
+             {
+               subr_info *info = jsr_ptrs[i];
+               while (info != NULL)
+                 {
+                   subr_info *next = info->next;
+                   _Jv_Free (info);
+                   info = next;
+                 }
+             }
+         }
+       _Jv_Free (jsr_ptrs);
+      }
+
     while (utf8_list != NULL)
       {
        linked_utf8 *n = utf8_list->next;
@@ -2910,6 +2966,13 @@ public:
        _Jv_Free (utf8_list);
        utf8_list = n;
       }
+
+    while (entry_points != NULL)
+      {
+       subr_entry_info *next = entry_points->next;
+       _Jv_Free (entry_points);
+       entry_points = next;
+      }
   }
 };