From 6f2ffb37afce5c9abca45f7be9243f73e849a217 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 13 Feb 2003 23:48:39 +0000 Subject: [PATCH] verify.cc (state::seen_subrs): New field. * 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. From-SVN: r62878 --- libjava/ChangeLog | 11 +++++++++ libjava/verify.cc | 63 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/libjava/ChangeLog b/libjava/ChangeLog index cb8ea70e452..e53a2e7ff12 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,14 @@ +2003-02-13 Tom Tromey + + * 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 * java/io/InputStreamReader.java (getEncoding): Return null when diff --git a/libjava/verify.cc b/libjava/verify.cc index 238a3e926f1..a7b0ee2eb8b 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.