X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmempool.c;h=dd351ccfe399a2e88c155d285e6e37c47bf5e1de;hb=94d44cb64a97e7252140bf7dd8e77071eda8480d;hp=b9c4bdd0050514a1f67b63b81a4699c8dbc5a187;hpb=5e99117394d535985237572998c34071334cdc6e;p=mono.git diff --git a/mono/metadata/mempool.c b/mono/metadata/mempool.c index b9c4bdd0050..dd351ccfe39 100644 --- a/mono/metadata/mempool.c +++ b/mono/metadata/mempool.c @@ -12,26 +12,33 @@ #include #include +#include -#include "jit.h" +#include "mempool.h" /* * MonoMemPool is for fast allocation of memory. We free * all memory when the pool is destroyed. */ -#if SIZEOF_VOID_P > SIZEOF_LONG -#define MEM_ALIGN SIZEOF_VOID_P -#else -#define MEM_ALIGN SIZEOF_LONG -#endif +#define MEM_ALIGN 8 #define MONO_MEMPOOL_PAGESIZE 8192 +#ifndef G_LIKELY +#define G_LIKELY(a) (a) +#define G_UNLIKELY(a) (a) +#endif + struct _MonoMemPool { MonoMemPool *next; gint rest; - gpointer pos; + guint8 *pos, *end; + guint32 size; + union { + double pad; /* to assure proper alignment */ + guint32 allocated; + } d; }; /** @@ -42,17 +49,18 @@ struct _MonoMemPool { MonoMemPool * mono_mempool_new () { - MonoMemPool *pool = g_malloc (MONO_MEMPOOL_PAGESIZE); + pool->next = NULL; - pool->pos = (gpointer)pool + sizeof (MonoMemPool); - pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool); + pool->pos = (char *)pool + sizeof (MonoMemPool); + pool->end = pool->pos + MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool); + pool->d.allocated = pool->size = MONO_MEMPOOL_PAGESIZE; return pool; } /** * mono_mempool_destroy: - * @pool: the momory pool to destroy + * @pool: the memory pool to destroy * * Free all memory associated with this pool. */ @@ -69,13 +77,66 @@ mono_mempool_destroy (MonoMemPool *pool) } } +/** + * mono_mempool_invalidate: + * @pool: the memory pool to invalidate + * + * Fill the memory associated with this pool to 0x2a (42). Useful for debugging. + */ +void +mono_mempool_invalidate (MonoMemPool *pool) +{ + MonoMemPool *p, *n; + + p = pool; + while (p) { + n = p->next; + memset (p, 42, p->size); + p = n; + } +} + +void +mono_mempool_empty (MonoMemPool *pool) +{ + pool->pos = (char *)pool + sizeof (MonoMemPool); + pool->end = pool->pos + MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool); +} + +/** + * mono_mempool_stats: + * @pool: the momory pool we need stats for + * + * Print a few stats about the mempool + */ +void +mono_mempool_stats (MonoMemPool *pool) +{ + MonoMemPool *p, *n; + int count = 0; + guint32 still_free = 0; + + p = pool; + while (p) { + still_free += p->end - p->pos; + n = p->next; + p = n; + count++; + } + if (pool) { + g_print ("Mempool %p stats:\n", pool); + g_print ("Total mem allocated: %d\n", pool->d.allocated); + g_print ("Num chunks: %d\n", count); + g_print ("Free memory: %d\n", still_free); + } +} + /** * mono_mempool_alloc: * @pool: the momory pool to destroy * @size: size of the momory block * - * Allocates a new block of memory in @pool. @size must - * be smaller than 256. + * Allocates a new block of memory in @pool. * * Returns: the address of a newly allocated memory block. */ @@ -83,25 +144,34 @@ gpointer mono_mempool_alloc (MonoMemPool *pool, guint size) { gpointer rval; - - g_assert (pool != NULL); - - /* we should also handle large blocks */ - g_assert (size < 4096); - + size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1); - if (pool->rest < size) { - MonoMemPool *np = g_malloc (MONO_MEMPOOL_PAGESIZE); - np->next = pool->next; - pool->next = np; - pool->pos = (gpointer)np + sizeof (MonoMemPool); - pool->rest = MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool); - } - rval = pool->pos; - pool->rest -= size; - pool->pos += size; + pool->pos = (char*)rval + size; + + if (G_UNLIKELY (pool->pos >= pool->end)) { + pool->pos -= size; + if (size >= 4096) { + MonoMemPool *np = g_malloc (sizeof (MonoMemPool) + size); + np->next = pool->next; + pool->next = np; + np->size = sizeof (MonoMemPool) + size; + pool->d.allocated += sizeof (MonoMemPool) + size; + return (char *)np + sizeof (MonoMemPool); + } else { + MonoMemPool *np = g_malloc (MONO_MEMPOOL_PAGESIZE); + np->next = pool->next; + pool->next = np; + pool->pos = (char *)np + sizeof (MonoMemPool); + np->size = MONO_MEMPOOL_PAGESIZE; + pool->end = pool->pos + MONO_MEMPOOL_PAGESIZE - sizeof (MonoMemPool); + pool->d.allocated += MONO_MEMPOOL_PAGESIZE; + + rval = pool->pos; + pool->pos += size; + } + } return rval; } @@ -114,8 +184,62 @@ mono_mempool_alloc (MonoMemPool *pool, guint size) gpointer mono_mempool_alloc0 (MonoMemPool *pool, guint size) { - gpointer rval = mono_mempool_alloc (pool, size); + gpointer rval; + + size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1); + + rval = pool->pos; + pool->pos = (char*)rval + size; + + if (G_UNLIKELY (pool->pos >= pool->end)) { + rval = mono_mempool_alloc (pool, size); + } + memset (rval, 0, size); return rval; } +/** + * mono_mempool_contains_addr: + * + * Determines whenever ADDR is inside the memory used by the mempool. + */ +gboolean +mono_mempool_contains_addr (MonoMemPool *pool, + gpointer addr) +{ + MonoMemPool *p; + + p = pool; + while (p) { + if (addr > (gpointer)p && addr <= (gpointer)((guint8*)p + p->size)) + return TRUE; + p = p->next; + } + + return FALSE; +} + +/** + * mono_mempool_strdup: + * + * Same as strdup, but allocates memory from the mempool. + * Returns: a pointer to the newly allocated string data inside the mempool. + */ +char* +mono_mempool_strdup (MonoMemPool *pool, + const char *s) +{ + int l; + char *res; + + if (s == NULL) + return NULL; + + l = strlen (s); + res = mono_mempool_alloc (pool, l + 1); + memcpy (res, s, l + 1); + + return res; +} +