Commit b3de7ff3 by Tom Tromey Committed by Tom Tromey

verify.cc (handle_ret_insn): Check for subroutine merge here...

	* 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.

From-SVN: r49344
parent f2e7381d
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> 2002-01-29 Tom Tromey <tromey@redhat.com>
* java/awt/List.java (addNotify): Correctly check to see if peer * java/awt/List.java (addNotify): Correctly check to see if peer
......
...@@ -56,6 +56,7 @@ private: ...@@ -56,6 +56,7 @@ private:
struct state; struct state;
struct type; struct type;
struct subr_info; struct subr_info;
struct subr_entry_info;
struct linked_utf8; struct linked_utf8;
// The current PC. // The current PC.
...@@ -84,6 +85,11 @@ private: ...@@ -84,6 +85,11 @@ private:
// of all calling `jsr's at at each jsr target. // of all calling `jsr's at at each jsr target.
subr_info **jsr_ptrs; 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. // The current top of the stack, in terms of slots.
int stacktop; int stacktop;
// The current depth of the stack. This will be larger than // The current depth of the stack. This will be larger than
...@@ -273,6 +279,18 @@ private: ...@@ -273,6 +279,18 @@ private:
subr_info *next; 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 // The `type' class is used to represent a single type in the
// verifier. // verifier.
struct type struct type
...@@ -886,9 +904,9 @@ private: ...@@ -886,9 +904,9 @@ private:
if (this_type.isinitialized ()) if (this_type.isinitialized ())
this_type = state_old->this_type; this_type = state_old->this_type;
// Merge subroutine states. *THIS and *STATE_OLD must be in the // Merge subroutine states. Here we just keep track of what
// same subroutine. Also, recursive subroutine calls must be // subroutine we think we're in. We only check for a merge
// avoided. // (which is invalid) when we see a `ret'.
if (subroutine == state_old->subroutine) if (subroutine == state_old->subroutine)
{ {
// Nothing. // Nothing.
...@@ -898,11 +916,13 @@ private: ...@@ -898,11 +916,13 @@ private:
subroutine = state_old->subroutine; subroutine = state_old->subroutine;
changed = true; changed = true;
} }
// If we're handling the result of an unmerged `ret', then we else
// can't trust that it has the correct PC setting. So in this {
// case we ignore what might otherwise look like a merge error. // If the subroutines differ, indicate that the state
else if (! state_old->is_unmerged_ret_state (max_locals)) // changed. This is needed to detect when subroutines have
verifier->verify_fail ("subroutines merged"); // merged.
changed = true;
}
// Merge stacks. // Merge stacks.
if (state_old->stacktop != stacktop) if (state_old->stacktop != stacktop)
...@@ -1329,6 +1349,24 @@ private: ...@@ -1329,6 +1349,24 @@ private:
if (csub == 0) if (csub == 0)
verify_fail ("no subroutine"); 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) for (subr_info *subr = jsr_ptrs[csub]; subr != NULL; subr = subr->next)
{ {
// Temporarily modify the current state so it looks like we're // Temporarily modify the current state so it looks like we're
...@@ -2893,6 +2931,7 @@ public: ...@@ -2893,6 +2931,7 @@ public:
flags = NULL; flags = NULL;
jsr_ptrs = NULL; jsr_ptrs = NULL;
utf8_list = NULL; utf8_list = NULL;
entry_points = NULL;
} }
~_Jv_BytecodeVerifier () ~_Jv_BytecodeVerifier ()
...@@ -2901,8 +2940,25 @@ public: ...@@ -2901,8 +2940,25 @@ public:
_Jv_Free (states); _Jv_Free (states);
if (flags) if (flags)
_Jv_Free (flags); _Jv_Free (flags);
if (jsr_ptrs) if (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); _Jv_Free (jsr_ptrs);
}
while (utf8_list != NULL) while (utf8_list != NULL)
{ {
linked_utf8 *n = utf8_list->next; linked_utf8 *n = utf8_list->next;
...@@ -2910,6 +2966,13 @@ public: ...@@ -2910,6 +2966,13 @@ public:
_Jv_Free (utf8_list); _Jv_Free (utf8_list);
utf8_list = n; utf8_list = n;
} }
while (entry_points != NULL)
{
subr_entry_info *next = entry_points->next;
_Jv_Free (entry_points);
entry_points = next;
}
} }
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment