From ac2ca0deec2c464e6544831f4933fc4f04d9fa60 Mon Sep 17 00:00:00 2001
From: tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Thu, 13 Feb 2003 23:48:39 +0000
Subject: [PATCH] 	* verify.cc (state::seen_subrs): New field. 
 (state::state): Initialize it. 	(state::clean_subrs): New method. 
 (state::~state): Call it. 	(state::copy): Copy subroutine list. 
 (state::add_subr): New method. 	(state::merge): Only register a change
 if the current subroutine 	hasn't yet been noted.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@62878 138bc75d-0d04-0410-961f-82ee72b054a4
---
 libjava/ChangeLog | 11 +++++++++
 libjava/verify.cc | 63 +++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 69 insertions(+), 5 deletions(-)

diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index cb8ea70e4529..e53a2e7ff122 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,14 @@
+2003-02-13  Tom Tromey  <tromey@redhat.com>
+
+	* verify.cc (state::seen_subrs): New field.
+	(state::state): Initialize it.
+	(state::clean_subrs): New method.
+	(state::~state): Call it.
+	(state::copy): Copy subroutine list.
+	(state::add_subr): New method.
+	(state::merge): Only register a change if the current subroutine
+	hasn't yet been noted.
+
 2003-02-13  Mark Wielaard  <mark@klomp.org>
 
 	* java/io/InputStreamReader.java (getEncoding): Return null when
diff --git a/libjava/verify.cc b/libjava/verify.cc
index 238a3e926f1e..a7b0ee2eb8b2 100644
--- a/libjava/verify.cc
+++ b/libjava/verify.cc
@@ -1,6 +1,6 @@
 // defineclass.cc - defining a class from .class format.
 
-/* Copyright (C) 2001, 2002  Free Software Foundation
+/* Copyright (C) 2001, 2002, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -821,6 +821,12 @@ private:
     // assigns to locals[0] (overwriting `this') and then returns
     // without really initializing.
     type this_type;
+    // This is a list of all subroutines that have been seen at this
+    // point.  Ordinarily this is NULL; it is only allocated and used
+    // in relatively weird situations involving non-ret exit from a
+    // subroutine.  We have to keep track of this in this way to avoid
+    // endless recursion in these cases.
+    subr_info *seen_subrs;
 
     // INVALID marks a state which is not on the linked list of states
     // requiring reverification.
@@ -839,6 +845,7 @@ private:
       stack = NULL;
       locals = NULL;
       local_changed = NULL;
+      seen_subrs = NULL;
     }
 
     state (int max_stack, int max_locals)
@@ -851,6 +858,7 @@ private:
 	stack[i] = unsuitable_type;
       locals = new type[max_locals];
       local_changed = (bool *) _Jv_Malloc (sizeof (bool) * max_locals);
+      seen_subrs = NULL;
       for (int i = 0; i < max_locals; ++i)
 	{
 	  locals[i] = unsuitable_type;
@@ -866,6 +874,7 @@ private:
       stack = new type[max_stack];
       locals = new type[max_locals];
       local_changed = (bool *) _Jv_Malloc (sizeof (bool) * max_locals);
+      seen_subrs = NULL;
       copy (orig, max_stack, max_locals, ret_semantics);
       next = INVALID;
     }
@@ -878,6 +887,7 @@ private:
 	delete[] locals;
       if (local_changed)
 	_Jv_Free (local_changed);
+      clean_subrs ();
     }
 
     void *operator new[] (size_t bytes)
@@ -900,6 +910,17 @@ private:
       _Jv_Free (mem);
     }
 
+    void clean_subrs ()
+    {
+      subr_info *info = seen_subrs;
+      while (info != NULL)
+	{
+	  subr_info *next = info->next;
+	  _Jv_Free (info);
+	  info = next;
+	}
+    }
+
     void copy (const state *copy, int max_stack, int max_locals,
 	       bool ret_semantics = false)
     {
@@ -919,6 +940,16 @@ private:
 	    locals[i] = copy->locals[i];
 	  local_changed[i] = copy->local_changed[i];
 	}
+
+      clean_subrs ();
+      if (copy->seen_subrs)
+	{
+	  for (subr_info *info = seen_subrs; info != NULL; info = info->next)
+	    add_subr (info->pc);
+	}
+      else
+	seen_subrs = NULL;
+
       this_type = copy->this_type;
       // Don't modify `next'.
     }
@@ -945,6 +976,15 @@ private:
 	local_changed[i] = false;
     }
 
+    // Indicate that we've been in this this subroutine.
+    void add_subr (int pc)
+    {
+      subr_info *n = (subr_info *) _Jv_Malloc (sizeof (subr_info));
+      n->pc = pc;
+      n->next = seen_subrs;
+      seen_subrs = n;
+    }
+
     // Merge STATE_OLD into this state.  Destructively modifies this
     // state.  Returns true if the new state was in fact changed.
     // Will throw an exception if the states are not mergeable.
@@ -972,10 +1012,23 @@ private:
 	}
       else
 	{
-	  // If the subroutines differ, indicate that the state
-	  // changed.  This is needed to detect when subroutines have
-	  // merged.
-	  changed = true;
+	  // If the subroutines differ, and we haven't seen this
+	  // subroutine before, indicate that the state changed.  This
+	  // is needed to detect when subroutines have merged.
+	  bool found = false;
+	  for (subr_info *info = seen_subrs; info != NULL; info = info->next)
+	    {
+	      if (info->pc == state_old->subroutine)
+		{
+		  found = true;
+		  break;
+		}
+	    }
+	  if (! found)
+	    {
+	      add_subr (state_old->subroutine);
+	      changed = true;
+	    }
 	}
 
       // Merge stacks.  Special handling for NO_STACK case.
-- 
GitLab