+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
// 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.
// 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.
stack = NULL;
locals = NULL;
local_changed = NULL;
+ seen_subrs = NULL;
}
state (int max_stack, int max_locals)
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;
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;
}
delete[] locals;
if (local_changed)
_Jv_Free (local_changed);
+ clean_subrs ();
}
void *operator new[] (size_t bytes)
_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)
{
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'.
}
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.
}
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.