[add support for monolithic blocks that are plain malloced memory and can be big.
John Meacham <john@repetae.net>**20120221032043
 Ignore-this: 201ba4e67027f3336cfa5e984aefa89
] hunk ./rts/rts/gc_jgc.c 5
+#include "rts/constants.h"
hunk ./rts/rts/gc_jgc.c 17
+        unsigned number_gcs;    // number of garbage collections
+        unsigned number_allocs; // number of allocations since last garbage collection
hunk ./rts/rts/gc_jgc.c 27
-struct s_block_info {
-        unsigned char color;
-        unsigned char size;
-        unsigned char num_ptrs;
-        unsigned char flags;
-};
-
hunk ./rts/rts/gc_jgc.c 29
-        struct s_block_info pi;
-        unsigned short num_free;
-        unsigned short next_free;
+        unsigned char flags;  // defined in rts/constants.h
+        unsigned char color;  // offset in words to first entry.
+        union {
+                // A normal block.
+                struct {
+                        unsigned char num_ptrs;
+                        unsigned char size;
+                        unsigned short num_free;
+                        unsigned short next_free;
+                } pi;
+                // A monolithic block.
+                struct {
+                        unsigned num_ptrs;
+                } m;
+        } u;
hunk ./rts/rts/gc_jgc.c 51
-        struct s_block_info pi;
+        unsigned char color;
+        unsigned char size;
+        unsigned char num_ptrs;
+        unsigned char flags;
hunk ./rts/rts/gc_jgc.c 66
-static unsigned number_gcs;    // number of garbage collections
-static unsigned number_allocs; // number of allocations since last garbage collection
hunk ./rts/rts/gc_jgc.c 74
+static struct s_block *get_free_block(gc_t gc, struct s_arena *arena);
+static void *aligned_alloc(unsigned size);
hunk ./rts/rts/gc_jgc.c 133
-        VALGRIND_MAKE_MEM_DEFINED(s,(S_BLOCK(s))->pi.size * sizeof(uintptr_t));
+        VALGRIND_MAKE_MEM_DEFINED(s,(S_BLOCK(s))->u.pi.size * sizeof(uintptr_t));
hunk ./rts/rts/gc_jgc.c 142
-        number_gcs++;
+        arena->number_gcs++;
hunk ./rts/rts/gc_jgc.c 198
-                VALGRIND_MAKE_MEM_DEFINED(e,pg->pi.size * sizeof(uintptr_t));
+                if(!(pg->flags & SLAB_MONOLITH))
+                        VALGRIND_MAKE_MEM_DEFINED(e,pg->u.pi.size * sizeof(uintptr_t));
hunk ./rts/rts/gc_jgc.c 201
-
-                stack_check(&stack, pg->pi.num_ptrs);
-                for(int i = 0; i < pg->pi.num_ptrs; i++) {
+                unsigned num_ptrs = pg->flags & SLAB_MONOLITH ? pg->u.m.num_ptrs : pg->u.pi.num_ptrs;
+                stack_check(&stack, num_ptrs);
+                for(unsigned i = 0; i < num_ptrs; i++) {
hunk ./rts/rts/gc_jgc.c 223
-                        number_gcs,
-                        number_allocs,
+                        arena->number_gcs,
+                        arena->number_allocs,
hunk ./rts/rts/gc_jgc.c 232
-                number_allocs = 0;
+                arena->number_allocs = 0;
hunk ./rts/rts/gc_jgc.c 238
-#define GC_STATIC_ARRAY_NUM 256
+#define GC_STATIC_ARRAY_NUM 7
+#define GC_MAX_BLOCK_ENTRIES 100
hunk ./rts/rts/gc_jgc.c 241
-static struct s_cache *static_array_caches[GC_STATIC_ARRAY_NUM];
+static struct s_cache *array_caches[GC_STATIC_ARRAY_NUM];
+static struct s_cache *array_atomic_caches[GC_STATIC_ARRAY_NUM];
hunk ./rts/rts/gc_jgc.c 259
-                find_cache(&static_array_caches[i], arena, i + 1, i + 1);
+                find_cache(&array_caches[i], arena, i + 1, i + 1);
hunk ./rts/rts/gc_jgc.c 276
-void *
+heap_t A_STD
hunk ./rts/rts/gc_jgc.c 279
-        profile_push(&gc_alloc_time);
-        if (JHC_STATUS)
-                number_allocs++;
hunk ./rts/rts/gc_jgc.c 282
-        debugf("allocated: %p %i %i\n",(void *)e, count, nptrs);
-        profile_pop(&gc_alloc_time);
+        debugf("gc_alloc: %p %i %i\n",(void *)e, count, nptrs);
hunk ./rts/rts/gc_jgc.c 286
+static heap_t A_STD
+s_monoblock(struct s_arena *arena, unsigned size, unsigned nptrs) {
+        struct s_block *b = aligned_alloc(size * sizeof(uintptr_t));
+        b->flags = SLAB_MONOLITH;
+        b->color = (sizeof(struct s_block) + BITARRAY_SIZE_IN_BYTES(1) +
+                    sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
+        b->u.m.num_ptrs = nptrs;
+        SLIST_INSERT_HEAD(&arena->monolithic_blocks, b, link);
+        b->used[0] = 1;
+        return (void *)b + b->color*sizeof(uintptr_t);
+}
+
hunk ./rts/rts/gc_jgc.c 299
-void *
+heap_t A_STD
hunk ./rts/rts/gc_jgc.c 305
-                return (wptr_t)s_alloc(gc,static_array_caches[count - 1]);
-        //if (count < GC_MAX_BLOCK_ENTRIES)
+                return (wptr_t)s_alloc(gc,array_caches[count - 1]);
+        if (count < GC_MAX_BLOCK_ENTRIES)
hunk ./rts/rts/gc_jgc.c 308
+        return s_monoblock(arena, count, count);
hunk ./rts/rts/gc_jgc.c 332
-struct s_megablock *
-s_new_megablock(struct s_arena *arena)
-{
-        struct s_megablock *mb = malloc(sizeof(*mb));
+static void *
+aligned_alloc(unsigned size) {
+        void *base;
hunk ./rts/rts/gc_jgc.c 336
-        mb->base = _aligned_malloc(MEGABLOCK_SIZE, BLOCK_SIZE);
+        base = _aligned_malloc(MEGABLOCK_SIZE, BLOCK_SIZE);
hunk ./rts/rts/gc_jgc.c 339
-        mb->base = memalign(BLOCK_SIZE,MEGABLOCK_SIZE);
+        base = memalign(BLOCK_SIZE, MEGABLOCK_SIZE);
hunk ./rts/rts/gc_jgc.c 343
-        mb->base = valloc(MEGABLOCK_SIZE);
+        base = valloc(MEGABLOCK_SIZE);
hunk ./rts/rts/gc_jgc.c 346
-        int ret = posix_memalign(&mb->base,BLOCK_SIZE,MEGABLOCK_SIZE);
+        int ret = posix_memalign(&base,BLOCK_SIZE,MEGABLOCK_SIZE);
hunk ./rts/rts/gc_jgc.c 349
-                fprintf(stderr,"Unable to allocate memory for megablock\n");
+                fprintf(stderr,"Unable to allocate memory for aligned alloc: %u\n", size);
hunk ./rts/rts/gc_jgc.c 352
+        return base;
+}
+
+struct s_megablock *
+s_new_megablock(struct s_arena *arena)
+{
+        struct s_megablock *mb = malloc(sizeof(*mb));
+        mb->base = aligned_alloc(MEGABLOCK_SIZE);
hunk ./rts/rts/gc_jgc.c 361
-        //VALGRIND_FREELIKE_BLOCK(mb->base,0);
hunk ./rts/rts/gc_jgc.c 392
-                pg->num_free = 0;
+                pg->u.pi.num_free = 0;
hunk ./rts/rts/gc_jgc.c 434
-                        if(__predict_false(pg->num_free == 0)) {
+                        if(__predict_false(pg->u.pi.num_free == 0)) {
hunk ./rts/rts/gc_jgc.c 437
-                        } else if(__predict_true(pg->num_free == sc->num_entries)) {
+                        } else if(__predict_true(pg->u.pi.num_free == sc->num_entries)) {
hunk ./rts/rts/gc_jgc.c 445
-                                        free_best = pg->num_free;
+                                        free_best = pg->u.pi.num_free;
hunk ./rts/rts/gc_jgc.c 448
-                                        if(pg->num_free < free_best) {
+                                        if(pg->u.pi.num_free < free_best) {
hunk ./rts/rts/gc_jgc.c 451
-                                                free_best = pg->num_free;
+                                                free_best = pg->u.pi.num_free;
hunk ./rts/rts/gc_jgc.c 470
-        pg->num_free = num_entries;
+        pg->u.pi.num_free = num_entries;
hunk ./rts/rts/gc_jgc.c 480
-void * A_STD
+/*
+ * allocators
+ */
+
+heap_t A_STD
hunk ./rts/rts/gc_jgc.c 489
+       sc->arena->number_allocs++;
hunk ./rts/rts/gc_jgc.c 496
-                if(sc->num_entries != pg->num_free)
+                if(sc->num_entries != pg->u.pi.num_free)
hunk ./rts/rts/gc_jgc.c 503
-                pg->pi = sc->pi;
-                pg->next_free = 0;
+                pg->flags = sc->flags;
+                pg->color = sc->color;
+                pg->u.pi.num_ptrs = sc->num_ptrs;
+                pg->u.pi.size = sc->size;
+                pg->u.pi.next_free = 0;
hunk ./rts/rts/gc_jgc.c 509
-                if(sc->num_entries != pg->num_free)
+                if(sc->num_entries != pg->u.pi.num_free)
hunk ./rts/rts/gc_jgc.c 512
-                pg->num_free = sc->num_entries - 1;
-                return (uintptr_t *)pg + pg->pi.color;
+                pg->u.pi.num_free = sc->num_entries - 1;
+                return (uintptr_t *)pg + pg->color;
hunk ./rts/rts/gc_jgc.c 516
-                pg->num_free--;
-                unsigned next_free = pg->next_free;
+                pg->u.pi.num_free--;
+                unsigned next_free = pg->u.pi.next_free;
hunk ./rts/rts/gc_jgc.c 519
-                pg->next_free = next_free;
-                void *val = (uintptr_t *)pg + pg->pi.color + found*pg->pi.size;
-                if(__predict_false(0 == pg->num_free)) {
+                pg->u.pi.next_free = next_free;
+                void *val = (uintptr_t *)pg + pg->color + found*pg->u.pi.size;
+                if(__predict_false(0 == pg->u.pi.num_free)) {
hunk ./rts/rts/gc_jgc.c 538
-        sc->pi.size = size;
-        sc->pi.num_ptrs = num_ptrs;
-        sc->pi.flags = 0;
+        sc->size = size;
+        sc->num_ptrs = num_ptrs;
+        sc->flags = 0;
hunk ./rts/rts/gc_jgc.c 543
-        sc->pi.color = (sizeof(struct s_block) + BITARRAY_SIZE_IN_BYTES(sc->num_entries) +
+        sc->color = (sizeof(struct s_block) + BITARRAY_SIZE_IN_BYTES(sc->num_entries) +
hunk ./rts/rts/gc_jgc.c 555
+        struct s_block *pg;
+        SLIST_FOREACH(pg, &arena->monolithic_blocks, link)
+            pg->used[0] = 0;
hunk ./rts/rts/gc_jgc.c 560
-                struct s_block *pg = SLIST_FIRST(&sc->blocks);
-                struct s_block *fpg = SLIST_FIRST(&sc->full_blocks);
-                do {
-                        for(;pg;pg = SLIST_NEXT(pg,link))
-                                clear_block_used_bits(sc->num_entries,pg);
-                        pg = fpg;
-                        fpg = NULL;
-                }  while(pg);
+                SLIST_FOREACH(pg, &sc->blocks, link)
+                    clear_block_used_bits(sc->num_entries,pg);
+                SLIST_FOREACH(pg, &sc->full_blocks, link)
+                    clear_block_used_bits(sc->num_entries,pg);
hunk ./rts/rts/gc_jgc.c 576
-        unsigned int offset = ((uintptr_t *)val - (uintptr_t *)pg) - pg->pi.color;
-        if(__predict_true(BIT_IS_UNSET(pg->used,offset/pg->pi.size))) {
-                BIT_SET(pg->used,offset/pg->pi.size);
-                pg->num_free--;
-                return (bool)pg->pi.num_ptrs;
+        unsigned int offset = ((uintptr_t *)val - (uintptr_t *)pg) - pg->color;
+        if(__predict_true(BIT_IS_UNSET(pg->used,offset/pg->u.pi.size))) {
+                if (pg->flags & SLAB_MONOLITH) {
+                        pg->used[0] = 1;
+                        return (bool)pg->u.m.num_ptrs;
+
+                } else {
+                        BIT_SET(pg->used,offset/pg->u.pi.size);
+                        pg->u.pi.num_free--;
+                        return (bool)pg->u.pi.num_ptrs;
+                }
hunk ./rts/rts/gc_jgc.c 599
-                if(sc->pi.size == size && sc->pi.num_ptrs == num_ptrs)
+                if(sc->size == size && sc->num_ptrs == num_ptrs)
hunk ./rts/rts/gc_jgc.c 628
-                (int)sc->pi.size,(int)sc->pi.num_ptrs);
+                (int)sc->size,(int)sc->num_ptrs);
hunk ./rts/rts/gc_jgc.c 638
-                fprintf(stderr, "%20p %9i %9i %c\n", pg, pg->num_free, pg->next_free, 'P');
+            fprintf(stderr, "%20p %9i %9i %c\n", pg, pg->u.pi.num_free, pg->u.pi.next_free, 'P');
hunk ./rts/rts/gc_jgc.c 640
-                fprintf(stderr, "%20p %9i %9i %c\n", pg, pg->num_free, pg->next_free, 'F');
+            fprintf(stderr, "%20p %9i %9i %c\n", pg, pg->u.pi.num_free, pg->u.pi.next_free, 'F');
hunk ./rts/rts/gc_jgc.h 11
+typedef void* heap_t;  // a pointer into the GCed heap.
hunk ./rts/rts/gc_jgc.h 22
-void *s_alloc(gc_t gc, struct s_cache *sc) A_STD;
hunk ./rts/rts/gc_jgc.h 28
-void *(gc_alloc)(gc_t gc,struct s_cache **sc, unsigned count, unsigned nptrs);
hunk ./rts/rts/gc_jgc.h 29
-void *gc_array_alloc(gc_t gc, unsigned count);
+
+heap_t s_alloc(gc_t gc, struct s_cache *sc) A_STD;
+heap_t (gc_alloc)(gc_t gc,struct s_cache **sc, unsigned count, unsigned nptrs);
+heap_t gc_array_alloc(gc_t gc, unsigned count);
+heap_t gc_array_alloc_atomic(gc_t gc, unsigned count);