swig/Source/DOH/Doh/memory.c
Dave Beazley d72c7beb9d Major cleanup of comments
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@128 626c5289-ae23-0410-ae9c-e8d60b6d4f22
2000-01-20 05:45:58 +00:00

411 lines
10 KiB
C

/* -----------------------------------------------------------------------------
* memory.c
*
* This file implements all of DOH's memory management including allocation
* of objects, checking of objects, and garbage collection.
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
*
* Copyright (C) 1999-2000. The University of Chicago
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
static char cvsroot[] = "$Header$";
#include "dohint.h"
#ifndef DOH_POOL_SIZE
#define DOH_POOL_SIZE 128000
#endif
#ifndef DOH_MAX_FRAG
#define DOH_MAX_FRAG 1024
#endif
#ifndef DOH_MAX_SCOPES
#define DOH_MAX_SCOPES 256
#endif
static int _DohMemoryCurrent = 0;
static int _DohMemoryHigh = 0;
static int _PoolSize = DOH_POOL_SIZE;
DOH *DohNone = 0; /* The DOH None object */
typedef struct fragment {
char *ptr; /* Pointer to fragment */
int len; /* Length of fragment */
struct fragment *next; /* Next fragment */
} Fragment;
static Fragment *FreeFragments[DOH_MAX_FRAG];
typedef struct pool {
char *ptr; /* Start of pool */
int len; /* Length of pool */
int current; /* Current position for next allocation */
struct pool *next; /* Next pool */
} Pool;
static Pool *Pools = 0;
static int pools_initialized = 0;
static DohBase *scopes[DOH_MAX_SCOPES];
static int nscopes = 0;
/* ----------------------------------------------------------------------
* CreatePool()
*
* Create a new memory pool
* ---------------------------------------------------------------------- */
static Pool *
CreatePool(int size) {
Pool *p = 0;
char *c;
c = (char *) DohMalloc(size);
if (!c) return 0;
p = (Pool *) DohMalloc(sizeof(Pool));
p->ptr = c;
p->len = size;
p->current = 0;
p->next = 0;
return p;
}
/* ----------------------------------------------------------------------
* InitPools()
*
* Initialize the memory allocator
* ---------------------------------------------------------------------- */
static void
InitPools() {
int i;
if (pools_initialized) return;
for (i = 0; i < DOH_MAX_FRAG; i++) {
FreeFragments[i] = 0;
}
Pools = CreatePool(_PoolSize); /* Create initial pool */
pools_initialized = 1;
for (i = 0; i < DOH_MAX_SCOPES; i++) {
scopes[i] = 0;
}
DohNewScope(); /* Initialize the scope system */
DohNone = NewVoid(0,0);
DohIntern(DohNone);
}
/* ----------------------------------------------------------------------
* DohCheck()
*
* Returns 1 if an arbitrary pointer is a DOH object. This determination
* is made according to the pointer value only.
* ---------------------------------------------------------------------- */
int
DohCheck(DOH *ptr) {
Pool *p = Pools;
char *cptr = (char *) ptr;
while (p) {
if ((cptr >= p->ptr) && (cptr < p->ptr+p->current)) return 1;
p = p->next;
}
return 0;
}
/* ----------------------------------------------------------------------
* DohObjFreeCheck()
*
* Checks to see if an object was already deleted. Useful when tracking
* down nasty double-free problems.
* ---------------------------------------------------------------------- */
int
DohObjFreeCheck(DOH *ptr) {
int i;
Fragment *f;
char *cptr = (char *) ptr;
for (i = 0; i < DOH_MAX_FRAG; i++) {
f = FreeFragments[i];
while (f) {
if (f->ptr == cptr) return 1;
f = f->next;
}
}
return 0;
}
/* ----------------------------------------------------------------------
* DohNewScope()
*
* Create a new scope in which objects will be placed. Returns a scope
* identifier.
* ---------------------------------------------------------------------- */
int
DohNewScope() {
assert(nscopes < DOH_MAX_SCOPES);
if (!pools_initialized) InitPools();
scopes[nscopes] = 0;
nscopes++;
return nscopes - 1;
}
/* ----------------------------------------------------------------------
* DohDelScope()
*
* Deletes a scope.
* ---------------------------------------------------------------------- */
void
DohDelScope(int s) {
int ns;
DohBase *b, *b1;
ns = s;
assert((s >= 0) && (s < nscopes));
s = nscopes - 1;
while (s >= ns) {
b = scopes[s];
b1 = 0;
while (b) {
if (s <= b->scope) {
if (!(b->flags & DOH_FLAG_DELSCOPE)) {
Delete(b);
b->flags = b->flags | DOH_FLAG_DELSCOPE;
}
}
b1 = b;
b = (DohBase *) (b->nextptr);
}
if (ns > 0) { /* Add objects to highest non-deleted scope */
if (b1) {
b1->nextptr = (DOH *) scopes[ns-1];
scopes[ns-1] = (DohBase *) scopes[s];
}
}
scopes[s] = 0;
s--;
}
nscopes = ns;
}
/* ----------------------------------------------------------------------
* real_objfree()
*
* This is the function that actually frees an object. Invoked by the
* garbage collector.
* ---------------------------------------------------------------------- */
static void
real_objfree(DOH *ptr) {
DohBase *b;
Fragment *f;
b = (DohBase *) ptr;
if (!b->objinfo) {
DohTrace(DOH_MEMORY,"DohObjFree. %x not properly defined. No objinfo structure.\n", ptr);
return; /* Improperly initialized object. leak some more */
}
f = (Fragment *) DohMalloc(sizeof(Fragment));
f->ptr = (char *) ptr;
f->len = (b->objinfo->objsize + 7) & ~0x07;
f->next = FreeFragments[f->len];
FreeFragments[f->len] = f;
}
/* ----------------------------------------------------------------------
* DohGarbageCollect()
*
* This walks through all of the scopes and does garbage collection.
*
* 1. Objects with refcount <= 0 are released.
* 2. The scopes data structures are rebuilt and compacted.
* ---------------------------------------------------------------------- */
void
DohGarbageCollect() {
int s;
DohBase *b, *b1;
int ndeleted = 1;
DohTrace(DOH_MEMORY,"Garbage collecting.\n");
while (ndeleted) {
ndeleted = 0;
s = nscopes - 1;
while (s >= 0) {
b = scopes[s];
b1 = 0;
while (b) {
if ((b->refcount <= 0)) {
if (b1) {
b1->nextptr = b->nextptr;
} else {
scopes[s] = b->nextptr;
}
if (!(b->flags & DOH_FLAG_INTERN)) {
assert(!(b->flags & DOH_FLAG_GC));
real_objfree(b); /* Release the object */
b->flags = b->flags | DOH_FLAG_GC;
}
ndeleted++;
} else {
b1 = b;
}
b = (DohBase *) b->nextptr;
}
s--;
}
}
DohTrace(DOH_MEMORY,"Done garbage collecting.\n");
}
/* ----------------------------------------------------------------------
* DohObjMalloc()
*
* Allocate memory for a new object.
* ---------------------------------------------------------------------- */
void *
DohObjMalloc(size_t size) {
Pool *p;
Fragment *f;
void *ptr = 0;
int garbage_collected = 0;
if (size > DOH_MAX_FRAG) return 0;
if (!pools_initialized) InitPools();
/* adjust the size for double word alignment */
size = (size + 7) & ~0x07;
retry:
p = Pools;
f = FreeFragments[size];
if (f) {
ptr = (void *) f->ptr;
FreeFragments[size] = f->next;
DohFree(f);
DohInit(ptr);
if (nscopes) {
((DohBase *) ptr)->scope = nscopes-1;
((DohBase *) ptr)->nextptr = scopes[nscopes-1];
scopes[nscopes-1] = (DohBase *) ptr;
}
return ptr;
}
/* No free fragments. See if the pool is large enough */
if ((int) size < (p->len - p->current)) {
ptr = (void *) (p->ptr + p->current);
/* p->current = (p->current + size + 7) & ~0x3; */
p->current = p->current + size;
DohInit(ptr);
if (nscopes) {
((DohBase *) ptr)->scope = nscopes-1;
((DohBase *) ptr)->nextptr = scopes[nscopes-1];
scopes[nscopes-1] = (DohBase *) ptr;
}
return ptr;
}
if (!garbage_collected) {
garbage_collected = 1;
DohGarbageCollect();
goto retry;
}
/* Pool is not large enough. Create a new pool */
if (p->len - p->current > 0) {
f = (Fragment *) DohMalloc(sizeof(Fragment));
f->ptr = (p->ptr + p->current);
f->len = (p->len - p->current);
f->next = FreeFragments[f->len];
p->current = p->len;
FreeFragments[f->len] = f;
}
p = CreatePool(_PoolSize);
p->next = Pools;
Pools = p;
return DohObjMalloc(size);
}
/* ----------------------------------------------------------------------
* DohObjFree()
*
* Frees a DOH object. Doesn't do much with GC.
* ---------------------------------------------------------------------- */
void
DohObjFree(DOH *ptr) {
DohBase *b;
if (!DohCheck(ptr)) {
DohTrace(DOH_MEMORY,"DohObjFree. %x not a DOH object!\n", ptr);
return; /* Oh well. Guess we're leaky */
}
b = (DohBase *) ptr;
if (!b->objinfo) {
DohTrace(DOH_MEMORY,"DohObjFree. %x not properly defined. No objinfo structure.\n", ptr);
return; /* Improperly initialized object. leak some more */
}
}
/* -----------------------------------------------------------------------------
* DohMalloc()
*
* Wrapper around malloc() function. Records memory usage.
* ----------------------------------------------------------------------------- */
void *
DohMalloc(size_t nbytes) {
return (void *) malloc(nbytes);
}
/* -----------------------------------------------------------------------------
* DohRealloc()
*
* Wrapper around realloc() function.
* ----------------------------------------------------------------------------- */
void *
DohRealloc(void *ptr, size_t newsize) {
return (void *) realloc(ptr,newsize);
}
/* -----------------------------------------------------------------------------
* DohFree()
*
* Wrapper around free() function.
* ----------------------------------------------------------------------------- */
void
DohFree(void *ptr) {
free(ptr);
}
/* -----------------------------------------------------------------------------
* DohPoolSize()
*
* Change the size of the memory pools used by DOH
* ----------------------------------------------------------------------------- */
int
DohPoolSize(int poolsize) {
int ps;
ps = _PoolSize;
if (poolsize > 0) {
_PoolSize = poolsize;
}
return ps;
}