OSDN Git Service

gcc:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Jun 2000 16:38:49 +0000 (16:38 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Jun 2000 16:38:49 +0000 (16:38 +0000)
  * 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

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@34429 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/exception.cc
gcc/eh-common.h
gcc/libgcc2.c

index 7a6fcc9..3f24d77 100644 (file)
@@ -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.
index 949f4c8..198ff67 100644 (file)
@@ -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
index 9263bfe..1ffd762 100644 (file)
@@ -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 **);
 
index 20adfd6..5303d6d 100644 (file)
@@ -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
index 822d84e..305d7f0 100644 (file)
@@ -3190,6 +3190,75 @@ eh_context_specific (void)
 }
 #endif /* __GTHREADS */
 \f
+/* 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);
+}
+\f
 /* Support routines for setjmp/longjmp exception handling.  */
 
 /* Calls to __sjthrow are generated by the compiler when an exception