eh-common.h (EH_ALLOC_SIZE, [...]): New #defines.
gcc: * eh-common.h (EH_ALLOC_SIZE, EH_ALLOC_ALIGN): New #defines. (eh_context): Add alloc_mask and alloc_buffer emergency fallback space. * libgcc2.c (__eh_alloc): Moved from cp/exception.cc. Fallback on emergency eh_context buffer, if malloc fails. (__eh_free): Moved from cp/exception.cc. Release to emergency eh_context buffer, if appropriate. gcc/cp: * exception.cc: (__eh_alloc, __eh_free): Moved to libgcc2.c From-SVN: r34429
This commit is contained in:
parent
051ffad528
commit
103c63aeb9
5 changed files with 105 additions and 23 deletions
|
@ -1,3 +1,13 @@
|
|||
2000-06-06 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* eh-common.h (EH_ALLOC_SIZE, EH_ALLOC_ALIGN): New #defines.
|
||||
(eh_context): Add alloc_mask and alloc_buffer emergency fallback
|
||||
space.
|
||||
* libgcc2.c (__eh_alloc): Moved from cp/exception.cc. Fallback on
|
||||
emergency eh_context buffer, if malloc fails.
|
||||
(__eh_free): Moved from cp/exception.cc. Release to emergency
|
||||
eh_context buffer, if appropriate.
|
||||
|
||||
2000-06-06 Jason Merrill <jason@casey.soma.redhat.com>
|
||||
|
||||
* expr.c (store_expr): Fix typo.
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2000-06-06 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* exception.cc: (__eh_alloc, __eh_free): Moved to libgcc2.c
|
||||
|
||||
2000-06-05 Jason Merrill <jason@casey.soma.redhat.com>
|
||||
|
||||
* search.c (maybe_suppress_debug_info): Don't check
|
||||
|
|
|
@ -118,6 +118,10 @@ struct cp_eh_info
|
|||
|
||||
extern "C" cp_eh_info **__get_eh_info (); // actually void **
|
||||
|
||||
/* Exception allocate and free, defined in libgcc2. */
|
||||
extern "C" void *__eh_alloc(size_t);
|
||||
extern "C" void __eh_free();
|
||||
|
||||
/* Is P the type_info node for a pointer of some kind? */
|
||||
|
||||
extern bool __is_pointer (void *);
|
||||
|
@ -159,29 +163,6 @@ __start_cp_handler (void)
|
|||
return p;
|
||||
}
|
||||
|
||||
/* Allocate a buffer for a cp_eh_info and an exception object of size SIZE,
|
||||
and return a pointer to the beginning of the object's space. */
|
||||
|
||||
extern "C" void * malloc (size_t);
|
||||
extern "C" void *
|
||||
__eh_alloc (size_t size)
|
||||
{
|
||||
void *p = malloc (size);
|
||||
if (p == 0)
|
||||
terminate ();
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Free the memory for an cp_eh_info and associated exception, given
|
||||
a pointer to the cp_eh_info. */
|
||||
|
||||
extern "C" void free (void *);
|
||||
extern "C" void
|
||||
__eh_free (void *p)
|
||||
{
|
||||
free (p);
|
||||
}
|
||||
|
||||
extern "C" int __throw_type_match_rtti_2 (const void *, const void *,
|
||||
void *, void **);
|
||||
|
||||
|
|
|
@ -39,6 +39,20 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|||
The routine get_dynamic_handler_chain() also has a dependancy on
|
||||
the location of 'dynamic_handler_chain'. If its location is changed,
|
||||
that routine must be modified as well. */
|
||||
#ifndef EH_ALLOC_SIZE
|
||||
/* 192 bytes means the entire eh_context plus malloc overhead fits in 256
|
||||
bytes (assuming 8 byte pointers). 192 bytes gives an eh_info and object
|
||||
size limit of 96 bytes. This should be sufficient for throwing bad_alloc. */
|
||||
#define EH_ALLOC_SIZE 192
|
||||
#endif
|
||||
#ifndef EH_ALLOC_ALIGN
|
||||
/* We can't use BIGGEST_ALIGNMENT, because on some systems, that expands to
|
||||
a check on a compile time switch like
|
||||
'target_flags & MASK_ALIGN_DOUBLE ? 64 : 32'. There's no macro for
|
||||
'largest alignment for any code this compiler can build for', which is
|
||||
really what is needed. */
|
||||
#define EH_ALLOC_ALIGN 16
|
||||
#endif
|
||||
|
||||
struct eh_context
|
||||
{
|
||||
|
@ -48,6 +62,10 @@ struct eh_context
|
|||
void *info;
|
||||
/* This is used to remember where we threw for re-throws */
|
||||
void *table_index; /* address of exception table entry to rethrow from */
|
||||
/* emergency fallback space, if malloc fails during handling */
|
||||
char alloc_buffer[EH_ALLOC_SIZE]
|
||||
__attribute__((__aligned__(EH_ALLOC_ALIGN)));
|
||||
unsigned alloc_mask;
|
||||
};
|
||||
|
||||
#ifndef EH_TABLE_LOOKUP
|
||||
|
|
|
@ -3190,6 +3190,75 @@ eh_context_specific (void)
|
|||
}
|
||||
#endif /* __GTHREADS */
|
||||
|
||||
/* Support routines for alloc/free during exception handling */
|
||||
|
||||
/* __eh_alloc and __eh_free attempt allocation using malloc, but fall back to
|
||||
the small arena in the eh_context. This is needed because throwing an
|
||||
out-of-memory exception would fail otherwise. The emergency space is
|
||||
allocated in blocks of size EH_ALLOC_ALIGN, the
|
||||
minimum allocation being two blocks. A bitmask indicates which blocks
|
||||
have been allocated. To indicate the size of an allocation, the bit for
|
||||
the final block is not set. Hence each allocation is a run of 1s followed
|
||||
by a zero. */
|
||||
void *
|
||||
__eh_alloc (size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (!size)
|
||||
abort();
|
||||
p = malloc (size);
|
||||
if (p == 0)
|
||||
{
|
||||
struct eh_context *eh = __get_eh_context ();
|
||||
unsigned blocks = (size + EH_ALLOC_ALIGN - 1) / EH_ALLOC_ALIGN;
|
||||
unsigned real_mask = eh->alloc_mask | (eh->alloc_mask << 1);
|
||||
unsigned our_mask;
|
||||
unsigned ix;
|
||||
|
||||
if (blocks > EH_ALLOC_SIZE / EH_ALLOC_ALIGN)
|
||||
__terminate ();
|
||||
blocks += blocks == 1;
|
||||
our_mask = (1 << blocks) - 1;
|
||||
|
||||
for (ix = EH_ALLOC_SIZE / EH_ALLOC_ALIGN - blocks; ix; ix--)
|
||||
if (! ((real_mask >> ix) & our_mask))
|
||||
{
|
||||
/* found some space */
|
||||
p = &eh->alloc_buffer[ix * EH_ALLOC_ALIGN];
|
||||
eh->alloc_mask |= (our_mask >> 1) << ix;
|
||||
return p;
|
||||
}
|
||||
__terminate ();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Free the memory for an cp_eh_info and associated exception, given
|
||||
a pointer to the cp_eh_info. */
|
||||
void
|
||||
__eh_free (void *p)
|
||||
{
|
||||
struct eh_context *eh = __get_eh_context ();
|
||||
|
||||
ptrdiff_t diff = (char *)p - &eh->alloc_buffer[0];
|
||||
if (diff >= 0 && diff < EH_ALLOC_SIZE)
|
||||
{
|
||||
unsigned mask = eh->alloc_mask;
|
||||
unsigned bit = 1 << (diff / EH_ALLOC_ALIGN);
|
||||
|
||||
do
|
||||
{
|
||||
mask ^= bit;
|
||||
bit <<= 1;
|
||||
}
|
||||
while (mask & bit);
|
||||
eh->alloc_mask = mask;
|
||||
}
|
||||
else
|
||||
free (p);
|
||||
}
|
||||
|
||||
/* Support routines for setjmp/longjmp exception handling. */
|
||||
|
||||
/* Calls to __sjthrow are generated by the compiler when an exception
|
||||
|
|
Loading…
Add table
Reference in a new issue