java-except.h (struct eh_range.handler): Remove unused field.

2005-04-18  Andrew Haley  <aph@redhat.com>

        * java-except.h (struct eh_range.handler): Remove unused field.
        (handle_nested_ranges): Remove function declaration.
        (sanity_check_exception_range): Add function declaration.
        * verify.c (verify_jvm_instructions): Remove call to
        handle_nested_ranges.
        * verify-glue.c (verify_jvm_instructions_new): Call
        sanity_check_exception_range.
        * except.c (link_handler, eh_range_freelist, link_handler,
        handle_nested_ranges): Remove.
        (add_handler): Rewrite.
        (sanity_check_exception_range): New function.
        (print_ranges): New function.

From-SVN: r98395
This commit is contained in:
Andrew Haley 2005-04-19 09:52:21 +00:00 committed by Andrew Haley
parent 8a5691f87d
commit d393cb7237
5 changed files with 210 additions and 150 deletions

View File

@ -1,3 +1,18 @@
2005-04-18 Andrew Haley <aph@redhat.com>
* java-except.h (struct eh_range.handler): Remove unused field.
(handle_nested_ranges): Remove function declaration.
(sanity_check_exception_range): Add function declaration.
* verify.c (verify_jvm_instructions): Remove call to
handle_nested_ranges.
* verify-glue.c (verify_jvm_instructions_new): Call
sanity_check_exception_range.
* except.c (link_handler, eh_range_freelist, link_handler,
handle_nested_ranges): Remove.
(add_handler): Rewrite.
(sanity_check_exception_range): New function.
(print_ranges): New function.
2005-04-13 Julian Brown <julian@codesourcery.com>
* decl.c (finish_method): Give methods once-only linkage.

View File

@ -1,5 +1,5 @@
/* Handle exceptions for GNU compiler for the Java(TM) language.
Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004
Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GCC.
@ -42,7 +42,6 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
static void expand_start_java_handler (struct eh_range *);
static struct eh_range *find_handler_in_range (int, struct eh_range *,
struct eh_range *);
static void link_handler (struct eh_range *, struct eh_range *);
static void check_start_handlers (struct eh_range *, int);
static void free_eh_ranges (struct eh_range *range);
@ -50,8 +49,6 @@ struct eh_range *current_method_handlers;
struct eh_range *current_try_block = NULL;
struct eh_range *eh_range_freelist = NULL;
/* These variables are used to speed up find_handler. */
static int cache_range_start, cache_range_end;
@ -62,12 +59,60 @@ static struct eh_range *cache_next_child;
struct eh_range whole_range;
/* Check the invariants of the structure we're using to contain
exception regions. Either returns true or fails an assertion
check. */
bool
sanity_check_exception_range (struct eh_range *range)
{
struct eh_range *ptr = range->first_child;
for (; ptr; ptr = ptr->next_sibling)
{
gcc_assert (ptr->outer == range
&& ptr->end_pc > ptr->start_pc);
if (ptr->next_sibling)
gcc_assert (ptr->next_sibling->start_pc >= ptr->end_pc);
gcc_assert (ptr->start_pc >= ptr->outer->start_pc
&& ptr->end_pc <= ptr->outer->end_pc);
(void) sanity_check_exception_range (ptr);
}
return true;
}
#if defined(DEBUG_JAVA_BINDING_LEVELS)
extern int binding_depth;
extern int is_class_level;
extern int current_pc;
extern void indent ();
extern int binding_depth;
extern void indent (void);
static void
print_ranges (struct eh_range *range)
{
if (! range)
return;
struct eh_range *child = range->first_child;
indent ();
fprintf (stderr, "handler pc %d --> %d ", range->start_pc, range->end_pc);
tree handler = range->handlers;
for ( ; handler != NULL_TREE; handler = TREE_CHAIN (handler))
{
tree type = TREE_PURPOSE (handler);
if (type == NULL)
type = throwable_type_node;
fprintf (stderr, " type=%s ", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
}
fprintf (stderr, "\n");
int saved = binding_depth;
binding_depth++;
print_ranges (child);
binding_depth = saved;
print_ranges (range->next_sibling);
}
#endif
/* Search for the most specific eh_range containing PC.
@ -117,114 +162,6 @@ find_handler (int pc)
return find_handler_in_range (pc, h, cache_next_child);
}
/* Recursive helper routine for check_nested_ranges. */
static void
link_handler (struct eh_range *range, struct eh_range *outer)
{
struct eh_range **ptr;
if (range->start_pc == outer->start_pc && range->end_pc == outer->end_pc)
{
outer->handlers = chainon (outer->handlers, range->handlers);
return;
}
/* If the new range completely encloses the `outer' range, then insert it
between the outer range and its parent. */
if (range->start_pc <= outer->start_pc && range->end_pc >= outer->end_pc)
{
range->outer = outer->outer;
range->next_sibling = NULL;
range->first_child = outer;
{
struct eh_range *p = outer;
struct eh_range **pr = &(outer->outer->first_child);
while (*pr != outer)
pr = &(*pr)->next_sibling;
*pr = range;
while (p)
{
p->outer = range;
p = p->next_sibling;
}
}
return;
}
/* Handle overlapping ranges by splitting the new range. */
if (range->start_pc < outer->start_pc || range->end_pc > outer->end_pc)
{
struct eh_range *h = xmalloc (sizeof (struct eh_range));
if (range->start_pc < outer->start_pc)
{
h->start_pc = range->start_pc;
h->end_pc = outer->start_pc;
range->start_pc = outer->start_pc;
}
else
{
h->start_pc = outer->end_pc;
h->end_pc = range->end_pc;
range->end_pc = outer->end_pc;
}
h->first_child = NULL;
h->outer = NULL;
h->handlers = build_tree_list (TREE_PURPOSE (range->handlers),
TREE_VALUE (range->handlers));
h->next_sibling = NULL;
h->expanded = 0;
h->stmt = NULL;
/* Restart both from the top to avoid having to make this
function smart about reentrancy. */
link_handler (h, &whole_range);
link_handler (range, &whole_range);
return;
}
ptr = &outer->first_child;
for (;; ptr = &(*ptr)->next_sibling)
{
if (*ptr == NULL || range->end_pc <= (*ptr)->start_pc)
{
range->next_sibling = *ptr;
range->first_child = NULL;
range->outer = outer;
*ptr = range;
return;
}
else if (range->start_pc < (*ptr)->end_pc)
{
link_handler (range, *ptr);
return;
}
/* end_pc > (*ptr)->start_pc && start_pc >= (*ptr)->end_pc. */
}
}
/* The first pass of exception range processing (calling add_handler)
constructs a linked list of exception ranges. We turn this into
the data structure expected by the rest of the code, and also
ensure that exception ranges are properly nested. */
void
handle_nested_ranges (void)
{
struct eh_range *ptr, *next;
ptr = whole_range.first_child;
whole_range.first_child = NULL;
for (; ptr; ptr = next)
{
next = ptr->next_sibling;
ptr->next_sibling = NULL;
link_handler (ptr, &whole_range);
}
}
/* Free RANGE as well as its children and siblings. */
static void
free_eh_ranges (struct eh_range *range)
{
@ -252,55 +189,166 @@ method_init_exceptions (void)
cache_range_start = 0xFFFFFF;
}
/* Add an exception range. If we already have an exception range
which has the same handler and label, and the new range overlaps
that one, then we simply extend the existing range. Some bytecode
obfuscators generate seemingly nonoverlapping exception ranges
which, when coalesced, do in fact nest correctly.
This constructs an ordinary linked list which check_nested_ranges()
later turns into the data structure we actually want.
We expect the input to come in order of increasing START_PC. This
function doesn't attempt to detect the case where two previously
added disjoint ranges could be coalesced by a new range; that is
what the sorting counteracts. */
/* Split an exception range into two at PC. The sub-ranges that
belong to the range are split and distributed between the two new
ranges. */
void
add_handler (int start_pc, int end_pc, tree handler, tree type)
static void
split_range (struct eh_range *range, int pc)
{
struct eh_range *ptr, *prev = NULL, *h;
struct eh_range *ptr;
struct eh_range **first_child, **second_child;
struct eh_range *h;
for (ptr = whole_range.first_child; ptr; ptr = ptr->next_sibling)
/* First, split all the sub-ranges. */
for (ptr = range->first_child; ptr; ptr = ptr->next_sibling)
{
if (start_pc >= ptr->start_pc
&& start_pc <= ptr->end_pc
&& TREE_PURPOSE (ptr->handlers) == type
&& TREE_VALUE (ptr->handlers) == handler)
if (pc > ptr->start_pc
&& pc < ptr->end_pc)
{
/* Already found an overlapping range, so coalesce. */
ptr->end_pc = MAX (ptr->end_pc, end_pc);
return;
split_range (ptr, pc);
}
prev = ptr;
}
/* Create a new range. */
h = xmalloc (sizeof (struct eh_range));
h->start_pc = pc;
h->end_pc = range->end_pc;
h->next_sibling = range->next_sibling;
range->next_sibling = h;
range->end_pc = pc;
h->handlers = build_tree_list (TREE_PURPOSE (range->handlers),
TREE_VALUE (range->handlers));
h->next_sibling = NULL;
h->expanded = 0;
h->stmt = NULL;
h->outer = range->outer;
h->first_child = NULL;
ptr = range->first_child;
first_child = &range->first_child;
second_child = &h->first_child;
/* Distribute the sub-ranges bewteen the two new ranges. */
for (ptr = range->first_child; ptr; ptr = ptr->next_sibling)
{
if (ptr->start_pc < pc)
{
*first_child = ptr;
ptr->outer = range;
first_child = &ptr->next_sibling;
}
else
{
*second_child = ptr;
ptr->outer = h;
second_child = &ptr->next_sibling;
}
}
*first_child = NULL;
*second_child = NULL;
}
/* Add an exception range.
There are some missed optimization opportunities here. For
example, some bytecode obfuscators generate seemingly
nonoverlapping exception ranges which, when coalesced, do in fact
nest correctly. We could merge these, but we'd have to fix up all
the enclosed regions first and perhaps create a new range anyway if
it overlapped existing ranges.
Also, we don't attempt to detect the case where two previously
added disjoint ranges could be coalesced by a new range. */
void
add_handler (int start_pc, int end_pc, tree handler, tree type)
{
struct eh_range *ptr, *h;
struct eh_range **first_child, **prev;
/* First, split all the existing ranges that we need to enclose. */
for (ptr = whole_range.first_child; ptr; ptr = ptr->next_sibling)
{
if (start_pc > ptr->start_pc
&& start_pc < ptr->end_pc)
{
split_range (ptr, start_pc);
}
if (end_pc > ptr->start_pc
&& end_pc < ptr->end_pc)
{
split_range (ptr, end_pc);
}
if (ptr->start_pc >= end_pc)
break;
}
/* Create the new range. */
h = xmalloc (sizeof (struct eh_range));
first_child = &h->first_child;
h->start_pc = start_pc;
h->end_pc = end_pc;
h->first_child = NULL;
h->outer = NULL;
h->outer = NULL_EH_RANGE;
h->handlers = build_tree_list (type, handler);
h->next_sibling = NULL;
h->expanded = 0;
h->stmt = NULL;
if (prev == NULL)
whole_range.first_child = h;
else
prev->next_sibling = h;
}
/* Find every range at the top level that will be a sub-range of the
range we're inserting and make it so. */
{
struct eh_range **prev = &whole_range.first_child;
for (ptr = *prev; ptr;)
{
struct eh_range *next = ptr->next_sibling;
if (ptr->start_pc >= end_pc)
break;
if (ptr->start_pc < start_pc)
{
prev = &ptr->next_sibling;
}
else if (ptr->start_pc >= start_pc
&& ptr->start_pc < end_pc)
{
*prev = next;
*first_child = ptr;
first_child = &ptr->next_sibling;
ptr->outer = h;
ptr->next_sibling = NULL;
}
ptr = next;
}
}
/* Find the right place to insert the new range. */
prev = &whole_range.first_child;
for (ptr = *prev; ptr; prev = &ptr->next_sibling, ptr = ptr->next_sibling)
{
gcc_assert (ptr->outer == NULL_EH_RANGE);
if (ptr->start_pc >= start_pc)
break;
}
/* And insert it there. */
*prev = h;
if (ptr)
{
h->next_sibling = ptr;
h->outer = ptr->outer;
}
}
/* if there are any handlers for this range, issue start of region */
static void
expand_start_java_handler (struct eh_range *range)

View File

@ -54,8 +54,6 @@ struct eh_range
/* The TRY_CATCH_EXPR for this EH range. */
tree stmt;
tree handler;
};
/* A dummy range that represents the entire method. */
@ -67,5 +65,5 @@ extern struct eh_range * find_handler (int);
extern void method_init_exceptions (void);
extern void maybe_start_try (int, int);
extern void add_handler (int, int, tree, tree);
extern void handle_nested_ranges (void);
extern void expand_end_java_handler (struct eh_range *);
extern bool sanity_check_exception_range (struct eh_range *);

View File

@ -487,7 +487,7 @@ verify_jvm_instructions_new (JCF *jcf, const unsigned char *byte_ops,
instruction_bits[handler_pc] |= BCODE_EXCEPTION_TARGET;
}
handle_nested_ranges ();
gcc_assert (sanity_check_exception_range (&whole_range));
method.method = current_function_decl;
method.signature = build_java_signature (TREE_TYPE (current_function_decl));

View File

@ -491,7 +491,6 @@ verify_jvm_instructions (JCF* jcf, const unsigned char *byte_ops, long length)
}
free (starts);
handle_nested_ranges ();
for (PC = 0;;)
{