| /* ----------------------------------------------------------------------------- |
| * This file is part of SWIG, which is licensed as a whole under version 3 |
| * (or any later version) of the GNU General Public License. Some additional |
| * terms also apply to certain portions of SWIG. The full details of the SWIG |
| * license and copyrights can be found in the LICENSE and COPYRIGHT files |
| * included with the SWIG source code as distributed by the SWIG developers |
| * and at http://www.swig.org/legal.html. |
| * |
| * memory.c |
| * |
| * This file implements all of DOH's memory management including allocation |
| * of objects and checking of objects. |
| * ----------------------------------------------------------------------------- */ |
| |
| #include "dohint.h" |
| |
| #ifndef DOH_POOL_SIZE |
| #define DOH_POOL_SIZE 16384 |
| #endif |
| |
| /* Checks stale DOH object use - will use a lot more memory as pool memory is not re-used. */ |
| /* |
| #define DOH_DEBUG_MEMORY_POOLS |
| */ |
| |
| static int PoolSize = DOH_POOL_SIZE; |
| |
| DOH *DohNone = 0; /* The DOH None object */ |
| |
| typedef struct pool { |
| DohBase *ptr; /* Start of pool */ |
| int len; /* Length of pool */ |
| int blen; /* Byte length of pool */ |
| int current; /* Current position for next allocation */ |
| char *pbeg; /* Beg of pool */ |
| char *pend; /* End of pool */ |
| struct pool *next; /* Next pool */ |
| } Pool; |
| |
| static DohBase *FreeList = 0; /* List of free objects */ |
| static Pool *Pools = 0; |
| static int pools_initialized = 0; |
| |
| /* ---------------------------------------------------------------------- |
| * CreatePool() - Create a new memory pool |
| * ---------------------------------------------------------------------- */ |
| |
| static void CreatePool() { |
| Pool *p = 0; |
| p = (Pool *) DohMalloc(sizeof(Pool)); |
| assert(p); |
| p->ptr = (DohBase *) DohMalloc(sizeof(DohBase) * PoolSize); |
| assert(p->ptr); |
| memset(p->ptr, 0, sizeof(DohBase) * PoolSize); |
| p->len = PoolSize; |
| p->blen = PoolSize * sizeof(DohBase); |
| p->current = 0; |
| p->pbeg = ((char *) p->ptr); |
| p->pend = p->pbeg + p->blen; |
| p->next = Pools; |
| Pools = p; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * InitPools() - Initialize the memory allocator |
| * ---------------------------------------------------------------------- */ |
| |
| static void InitPools() { |
| if (pools_initialized) |
| return; |
| CreatePool(); /* Create initial pool */ |
| pools_initialized = 1; |
| DohNone = NewVoid(0, 0); /* Create the None object */ |
| DohIntern(DohNone); |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * DohCheck() |
| * |
| * Returns 1 if an arbitrary pointer is a DOH object. |
| * ---------------------------------------------------------------------- */ |
| |
| int DohCheck(const DOH *ptr) { |
| Pool *p = Pools; |
| char *cptr = (char *) ptr; |
| while (p) { |
| if ((cptr >= p->pbeg) && (cptr < p->pend)) { |
| #ifdef DOH_DEBUG_MEMORY_POOLS |
| DohBase *b = (DohBase *) ptr; |
| int DOH_object_already_deleted = b->type == 0; |
| assert(!DOH_object_already_deleted); |
| #endif |
| return 1; |
| } |
| /* |
| pptr = (char *) p->ptr; |
| if ((cptr >= pptr) && (cptr < (pptr+(p->current*sizeof(DohBase))))) return 1; */ |
| p = p->next; |
| } |
| return 0; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * DohIntern() |
| * ----------------------------------------------------------------------------- */ |
| |
| void DohIntern(DOH *obj) { |
| DohBase *b = (DohBase *) obj; |
| b->flag_intern = 1; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * DohObjMalloc() |
| * |
| * Allocate memory for a new object. |
| * ---------------------------------------------------------------------- */ |
| |
| DOH *DohObjMalloc(DohObjInfo *type, void *data) { |
| DohBase *obj; |
| if (!pools_initialized) |
| InitPools(); |
| #ifndef DOH_DEBUG_MEMORY_POOLS |
| if (FreeList) { |
| obj = FreeList; |
| FreeList = (DohBase *) obj->data; |
| } else { |
| #endif |
| while (Pools->current == Pools->len) { |
| CreatePool(); |
| } |
| obj = Pools->ptr + Pools->current; |
| ++Pools->current; |
| #ifndef DOH_DEBUG_MEMORY_POOLS |
| } |
| #endif |
| obj->type = type; |
| obj->data = data; |
| obj->meta = 0; |
| obj->refcount = 1; |
| obj->flag_intern = 0; |
| obj->flag_marked = 0; |
| obj->flag_user = 0; |
| obj->flag_usermark = 0; |
| return (DOH *) obj; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * DohObjFree() - Free a DOH object |
| * ---------------------------------------------------------------------- */ |
| |
| void DohObjFree(DOH *ptr) { |
| DohBase *b, *meta; |
| b = (DohBase *) ptr; |
| if (b->flag_intern) |
| return; |
| meta = (DohBase *) b->meta; |
| b->data = (void *) FreeList; |
| b->meta = 0; |
| b->type = 0; |
| b->refcount = 0; |
| FreeList = b; |
| if (meta) { |
| Delete(meta); |
| } |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * DohMemoryDebug() |
| * |
| * Display memory usage statistics |
| * ---------------------------------------------------------------------- */ |
| |
| void DohMemoryDebug(void) { |
| extern DohObjInfo DohStringType; |
| extern DohObjInfo DohListType; |
| extern DohObjInfo DohHashType; |
| |
| Pool *p; |
| int totsize = 0; |
| int totused = 0; |
| int totfree = 0; |
| |
| int numstring = 0; |
| int numlist = 0; |
| int numhash = 0; |
| |
| printf("Memory statistics:\n\n"); |
| printf("Pools:\n"); |
| |
| p = Pools; |
| while (p) { |
| /* Calculate number of used, free items */ |
| int i; |
| int nused = 0, nfree = 0; |
| for (i = 0; i < p->len; i++) { |
| if (p->ptr[i].refcount <= 0) |
| nfree++; |
| else { |
| nused++; |
| if (p->ptr[i].type == &DohStringType) |
| numstring++; |
| else if (p->ptr[i].type == &DohListType) |
| numlist++; |
| else if (p->ptr[i].type == &DohHashType) |
| numhash++; |
| } |
| } |
| printf(" Pool %8p: size = %10d. used = %10d. free = %10d\n", (void *) p, p->len, nused, nfree); |
| totsize += p->len; |
| totused += nused; |
| totfree += nfree; |
| p = p->next; |
| } |
| printf("\n Total: size = %10d, used = %10d, free = %10d\n", totsize, totused, totfree); |
| |
| printf("\nObject types\n"); |
| printf(" Strings : %d\n", numstring); |
| printf(" Lists : %d\n", numlist); |
| printf(" Hashes : %d\n", numhash); |
| |
| #if 0 |
| p = Pools; |
| while (p) { |
| int i; |
| for (i = 0; i < p->len; i++) { |
| if (p->ptr[i].refcount > 0) { |
| if (p->ptr[i].type == &DohStringType) { |
| Printf(stdout, "%s\n", p->ptr + i); |
| } |
| } |
| } |
| p = p->next; |
| } |
| #endif |
| |
| } |