Adding fixed-size heaps as an experimental compile-time option.

This commit is contained in:
Alex Shinn 2015-04-25 22:24:56 +09:00
parent b3bc13443b
commit 24a880ad28
4 changed files with 30 additions and 11 deletions

23
gc.c
View file

@ -467,7 +467,7 @@ sexp sexp_gc (sexp ctx, size_t *sum_freed) {
return res; return res;
} }
sexp_heap sexp_make_heap (size_t size, size_t max_size) { sexp_heap sexp_make_heap (size_t size, size_t max_size, size_t chunk_size) {
sexp_free_list free, next; sexp_free_list free, next;
sexp_heap h; sexp_heap h;
#if SEXP_USE_MMAP_GC #if SEXP_USE_MMAP_GC
@ -479,6 +479,7 @@ sexp_heap sexp_make_heap (size_t size, size_t max_size) {
if (! h) return NULL; if (! h) return NULL;
h->size = size; h->size = size;
h->max_size = max_size; h->max_size = max_size;
h->chunk_size = chunk_size;
h->data = (char*) sexp_heap_align(sizeof(h->data)+(sexp_uint_t)&(h->data)); h->data = (char*) sexp_heap_align(sizeof(h->data)+(sexp_uint_t)&(h->data));
free = h->free_list = (sexp_free_list) h->data; free = h->free_list = (sexp_free_list) h->data;
h->next = NULL; h->next = NULL;
@ -498,20 +499,24 @@ sexp_heap sexp_make_heap (size_t size, size_t max_size) {
return h; return h;
} }
int sexp_grow_heap (sexp ctx, size_t size) { int sexp_grow_heap (sexp ctx, size_t size, size_t chunk_size) {
size_t cur_size, new_size; size_t cur_size, new_size;
sexp_heap h = sexp_heap_last(sexp_context_heap(ctx)); sexp_heap h = sexp_heap_last(sexp_context_heap(ctx));
cur_size = h->size; cur_size = h->size;
new_size = sexp_heap_align(((cur_size > size) ? cur_size : size) * 2); new_size = sexp_heap_align(((cur_size > size) ? cur_size : size) * 2);
h->next = sexp_make_heap(new_size, h->max_size); h->next = sexp_make_heap(new_size, h->max_size, chunk_size);
return (h->next != NULL); return (h->next != NULL);
} }
void* sexp_try_alloc (sexp ctx, size_t size) { void* sexp_try_alloc (sexp ctx, size_t size) {
sexp_free_list ls1, ls2, ls3; sexp_free_list ls1, ls2, ls3;
sexp_heap h; sexp_heap h;
for (h=sexp_context_heap(ctx); h; h=h->next) for (h=sexp_context_heap(ctx); h; h=h->next) {
for (ls1=h->free_list, ls2=ls1->next; ls2; ls1=ls2, ls2=ls2->next) #if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
if (h->chunk_size && h->chunk_size != size)
continue;
#endif
for (ls1=h->free_list, ls2=ls1->next; ls2; ls1=ls2, ls2=ls2->next) {
if (ls2->size >= size) { if (ls2->size >= size) {
#if SEXP_USE_DEBUG_GC #if SEXP_USE_DEBUG_GC
ls3 = (sexp_free_list) sexp_heap_end(h); ls3 = (sexp_free_list) sexp_heap_end(h);
@ -531,6 +536,8 @@ void* sexp_try_alloc (sexp ctx, size_t size) {
memset((void*)ls2, 0, size); memset((void*)ls2, 0, size);
return ls2; return ls2;
} }
}
}
return NULL; return NULL;
} }
@ -547,7 +554,7 @@ void* sexp_alloc (sexp ctx, size_t size) {
|| ((total_size > sum_freed) || ((total_size > sum_freed)
&& (total_size - sum_freed) > (total_size*SEXP_GROW_HEAP_RATIO))) && (total_size - sum_freed) > (total_size*SEXP_GROW_HEAP_RATIO)))
&& ((!h->max_size) || (total_size < h->max_size))) && ((!h->max_size) || (total_size < h->max_size)))
sexp_grow_heap(ctx, size); sexp_grow_heap(ctx, size, 0);
res = sexp_try_alloc(ctx, size); res = sexp_try_alloc(ctx, size);
if (! res) { if (! res) {
res = sexp_global(ctx, SEXP_G_OOM_ERROR); res = sexp_global(ctx, SEXP_G_OOM_ERROR);
@ -703,7 +710,7 @@ sexp sexp_copy_context (sexp ctx, sexp dst, sexp flags) {
if (from->next) { if (from->next) {
return sexp_user_exception(ctx, NULL, "can't copy a non-contiguous heap", ctx); return sexp_user_exception(ctx, NULL, "can't copy a non-contiguous heap", ctx);
} else if (! dst || sexp_not(dst)) { } else if (! dst || sexp_not(dst)) {
to = sexp_make_heap(from->size, from->max_size); to = sexp_make_heap(from->size, from->max_size, from->chunk_size);
if (!to) return sexp_global(ctx, SEXP_G_OOM_ERROR); if (!to) return sexp_global(ctx, SEXP_G_OOM_ERROR);
dst = (sexp) ((char*)ctx + ((char*)to - (char*)from)); dst = (sexp) ((char*)ctx + ((char*)to - (char*)from));
} else if (! sexp_contextp(dst)) { } else if (! sexp_contextp(dst)) {
@ -731,7 +738,7 @@ void sexp_gc_init (void) {
sexp_uint_t size = sexp_heap_align(SEXP_INITIAL_HEAP_SIZE); sexp_uint_t size = sexp_heap_align(SEXP_INITIAL_HEAP_SIZE);
#endif #endif
#if SEXP_USE_GLOBAL_HEAP #if SEXP_USE_GLOBAL_HEAP
sexp_global_heap = sexp_make_heap(size, SEXP_MAXIMUM_HEAP_SIZE); sexp_global_heap = sexp_make_heap(size, SEXP_MAXIMUM_HEAP_SIZE, 0);
#endif #endif
#if SEXP_USE_CONSERVATIVE_GC #if SEXP_USE_CONSERVATIVE_GC
/* the +32 is a hack, but this is just for debugging anyway */ /* the +32 is a hack, but this is just for debugging anyway */

View file

@ -67,6 +67,9 @@
/* uncomment this to disable weak references */ /* uncomment this to disable weak references */
/* #define SEXP_USE_WEAK_REFERENCES 0 */ /* #define SEXP_USE_WEAK_REFERENCES 0 */
/* uncomment this to enable heap regions for fixed-size chunks */
/* #define SEXP_USE_FIXED_CHUNK_SIZE_HEAPS 1 */
/* uncomment this to just malloc manually instead of any GC */ /* uncomment this to just malloc manually instead of any GC */
/* Mostly for debugging purposes, this is the no GC option. */ /* Mostly for debugging purposes, this is the no GC option. */
/* You can use just the read/write API and */ /* You can use just the read/write API and */
@ -356,6 +359,10 @@
#define SEXP_USE_WEAK_REFERENCES ! SEXP_USE_NO_FEATURES #define SEXP_USE_WEAK_REFERENCES ! SEXP_USE_NO_FEATURES
#endif #endif
#ifndef SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
#define SEXP_USE_FIXED_CHUNK_SIZE_HEAPS 0
#endif
#ifndef SEXP_USE_MALLOC #ifndef SEXP_USE_MALLOC
#define SEXP_USE_MALLOC 0 #define SEXP_USE_MALLOC 0
#endif #endif

View file

@ -279,7 +279,7 @@ struct sexp_free_list_t {
typedef struct sexp_heap_t *sexp_heap; typedef struct sexp_heap_t *sexp_heap;
struct sexp_heap_t { struct sexp_heap_t {
sexp_uint_t size, max_size; sexp_uint_t size, max_size, chunk_size;
sexp_free_list free_list; sexp_free_list free_list;
sexp_heap next; sexp_heap next;
/* note this must be aligned on a proper heap boundary, */ /* note this must be aligned on a proper heap boundary, */
@ -1518,7 +1518,8 @@ SEXP_API void sexp_maybe_unblock_port (sexp ctx, sexp in);
#if ! SEXP_USE_BOEHM && ! SEXP_USE_MALLOC #if ! SEXP_USE_BOEHM && ! SEXP_USE_MALLOC
SEXP_API void sexp_gc_init (void); SEXP_API void sexp_gc_init (void);
SEXP_API sexp_heap sexp_make_heap (size_t size, size_t max_size); SEXP_API int sexp_grow_heap (sexp ctx, size_t size, size_t chunk_size);
SEXP_API sexp_heap sexp_make_heap (size_t size, size_t max_size, size_t chunk_size);
SEXP_API void sexp_mark (sexp ctx, sexp x); SEXP_API void sexp_mark (sexp ctx, sexp x);
SEXP_API sexp sexp_sweep (sexp ctx, size_t *sum_freed_ptr); SEXP_API sexp sexp_sweep (sexp ctx, size_t *sum_freed_ptr);
SEXP_API sexp sexp_finalize (sexp ctx); SEXP_API sexp sexp_finalize (sexp ctx);

6
sexp.c
View file

@ -444,7 +444,7 @@ sexp sexp_bootstrap_context (sexp_uint_t size, sexp_uint_t max_size) {
sexp_heap heap; sexp_heap heap;
struct sexp_struct dummy_ctx; struct sexp_struct dummy_ctx;
if (size < SEXP_MINIMUM_HEAP_SIZE) size = SEXP_INITIAL_HEAP_SIZE; if (size < SEXP_MINIMUM_HEAP_SIZE) size = SEXP_INITIAL_HEAP_SIZE;
heap = sexp_make_heap(sexp_heap_align(size), sexp_heap_align(max_size)); heap = sexp_make_heap(sexp_heap_align(size), sexp_heap_align(max_size), 0);
if (!heap) return 0; if (!heap) return 0;
sexp_pointer_tag(&dummy_ctx) = SEXP_CONTEXT; sexp_pointer_tag(&dummy_ctx) = SEXP_CONTEXT;
sexp_context_saves(&dummy_ctx) = NULL; sexp_context_saves(&dummy_ctx) = NULL;
@ -454,6 +454,10 @@ sexp sexp_bootstrap_context (sexp_uint_t size, sexp_uint_t max_size) {
sexp_free_heap(heap); sexp_free_heap(heap);
} else { } else {
sexp_context_heap(ctx) = heap; sexp_context_heap(ctx) = heap;
#if SEXP_USE_FIXED_CHUNK_SIZE_HEAPS
heap->chunk_size = 1<<(4+SEXP_64_BIT);
sexp_grow_heap(ctx, sexp_heap_align(size), 0);
#endif
} }
return ctx; return ctx;
} }