summaryrefslogtreecommitdiff
path: root/gcc/alloc-pool.c
diff options
context:
space:
mode:
authorzlomek <zlomek@138bc75d-0d04-0410-961f-82ee72b054a4>2003-05-12 05:16:55 +0000
committerzlomek <zlomek@138bc75d-0d04-0410-961f-82ee72b054a4>2003-05-12 05:16:55 +0000
commita5f52a4548046ea51b00bd465af7d6e7b90c9ad3 (patch)
tree29d4dc1fdfe78b727f24ca1dd297d829aa75218f /gcc/alloc-pool.c
parent4d2aa485d66d731a3726186c5be15f869b5895f9 (diff)
downloadgcc-a5f52a4548046ea51b00bd465af7d6e7b90c9ad3.tar.gz
* alloc-pool.h (ALLOC_POOL_ID_TYPE): New type.
(struct alloc_pool_def): New element 'id'. * alloc-pool.c (fancy_abort): Extern function prototype. (abort): Macro which uses fancy_abort. (struct allocation_object_def): New structure. (ALLOCATION_OBJECT_PTR_FROM_USER_PTR): New macro. (USER_PTR_FROM_ALLOCATION_OBJECT_PTR): New macro. (last_id): New variable. (create_alloc_pool): Add the offset of u.data to size of element, increase and use last_id. (free_alloc_pool): Do the checking only when ENABLE_CHECKING. (pool_alloc): Likewise. Set ID for elements. (pool_free): Check whether the PTR was allocated from POOL. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@66711 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/alloc-pool.c')
-rw-r--r--gcc/alloc-pool.c91
1 files changed, 89 insertions, 2 deletions
diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c
index 2f5d04dab51..cb25b9ef061 100644
--- a/gcc/alloc-pool.c
+++ b/gcc/alloc-pool.c
@@ -1,5 +1,6 @@
/* Functions to support a pool of allocatable objects.
- Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2003
+ Free Software Foundation, Inc.
Contributed by Daniel Berlin <dan@cgsoftware.com>
This file is part of GCC.
@@ -23,9 +24,56 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "system.h"
#include "alloc-pool.h"
+/* Redefine abort to report an internal error w/o coredump, and
+ reporting the location of the error in the source file. This logic
+ is duplicated in rtl.h and tree.h because every file that needs the
+ special abort includes one or both. toplev.h gets too few files,
+ system.h gets too many. */
+
+extern void fancy_abort PARAMS ((const char *, int, const char *))
+ ATTRIBUTE_NORETURN;
+#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)
+
#define align_four(x) (((x+3) >> 2) << 2)
#define align_eight(x) (((x+7) >> 3) << 3)
+/* The internal allocation object. */
+typedef struct allocation_object_def
+{
+#ifdef ENABLE_CHECKING
+ /* The ID of alloc pool which the object was allocated from. */
+ ALLOC_POOL_ID_TYPE id;
+#endif
+
+ union
+ {
+ /* The data of the object. */
+ char data[1];
+
+ /* Because we want any type of data to be well aligned after the ID,
+ the following elements are here. They are never accessed so
+ the allocated object may be even smaller than this structure. */
+ char *align_p;
+ double align_d;
+ HOST_WIDEST_INT align_i;
+#ifdef HAVE_LONG_DOUBLE
+ long double align_ld;
+#endif
+ } u;
+} allocation_object;
+
+/* Convert a pointer to allocation_object from a pointer to user data. */
+#define ALLOCATION_OBJECT_PTR_FROM_USER_PTR(X) \
+ ((allocation_object *) (((char *) (X)) \
+ - offsetof (allocation_object, u.data)))
+
+/* Convert a pointer to user data from a pointer to allocation_object. */
+#define USER_PTR_FROM_ALLOCATION_OBJECT_PTR(X) \
+ ((void *) (((allocation_object *) (X))->u.data))
+
+/* Last used ID. */
+static ALLOC_POOL_ID_TYPE last_id;
+
/* Create a pool of things of size SIZE, with NUM in each block we
allocate. */
@@ -48,6 +96,11 @@ create_alloc_pool (name, size, num)
/* Now align the size to a multiple of 4. */
size = align_four (size);
+#ifdef ENABLE_CHECKING
+ /* Add the aligned size of ID. */
+ size += offsetof (allocation_object, u.data);
+#endif
+
/* Um, we can't really allocate 0 elements per block. */
if (num == 0)
abort ();
@@ -73,6 +126,16 @@ create_alloc_pool (name, size, num)
pool->blocks_allocated = 0;
pool->block_list = NULL;
+#ifdef ENABLE_CHECKING
+ /* Increase the last used ID and use it for this pool.
+ ID == 0 is used for free elements of pool so skip it. */
+ last_id++;
+ if (last_id == 0)
+ last_id++;
+
+ pool->id = last_id;
+#endif
+
return (pool);
}
@@ -83,8 +146,10 @@ free_alloc_pool (pool)
{
alloc_pool_list block, next_block;
+#ifdef ENABLE_CHECKING
if (!pool)
abort ();
+#endif
/* Free each block allocated to the pool. */
for (block = pool->block_list; block != NULL; block = next_block)
@@ -105,8 +170,10 @@ pool_alloc (pool)
alloc_pool_list header;
char *block;
+#ifdef ENABLE_CHECKING
if (!pool)
abort ();
+#endif
/* If there are no more free elements, make some more!. */
if (!pool->free_list)
@@ -126,7 +193,11 @@ pool_alloc (pool)
/* Now put the actual block pieces onto the free list. */
for (i = 0; i < pool->elts_per_block; i++, block += pool->elt_size)
{
- header = (alloc_pool_list) block;
+#ifdef ENABLE_CHECKING
+ /* Mark the element to be free. */
+ ((allocation_object *) block)->id = 0;
+#endif
+ header = (alloc_pool_list) USER_PTR_FROM_ALLOCATION_OBJECT_PTR (block);
header->next = pool->free_list;
pool->free_list = header;
}
@@ -141,6 +212,12 @@ pool_alloc (pool)
header = pool->free_list;
pool->free_list = header->next;
pool->elts_free--;
+
+#ifdef ENABLE_CHECKING
+ /* Set the ID for element. */
+ ALLOCATION_OBJECT_PTR_FROM_USER_PTR (header)->id = pool->id;
+#endif
+
return ((void *) header);
}
@@ -152,12 +229,22 @@ pool_free (pool, ptr)
{
alloc_pool_list header;
+#ifdef ENABLE_CHECKING
if (!ptr)
abort ();
+ /* Check whether the PTR was allocated from POOL. */
+ if (pool->id != ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id)
+ abort ();
+
+ /* Mark the element to be free. */
+ ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id = 0;
+#else
/* Check if we free more than we allocated, which is Bad (TM). */
if (pool->elts_free + 1 > pool->elts_allocated)
abort ();
+#endif
+
header = (alloc_pool_list) ptr;
header->next = pool->free_list;
pool->free_list = header;