[introduce dedicated array allocation routine. clean up jgc garbage collector
John Meacham <john@repetae.net>**20120221011655
 Ignore-this: b8e153205aeaf94af76a97b0ee9aa895
] hunk ./rts/rts/constants.h 6
-#define SLAB_FLAG_NONE      0
+#define SLAB_FLAG_NONE         0
hunk ./rts/rts/constants.h 9
-#define SLAB_FLAG_FINALIZER 1
+#define SLAB_FLAG_FINALIZER    1
hunk ./rts/rts/constants.h 13
-#define SLAB_FLAG_FREE      2
+#define SLAB_FLAG_FREE         2
hunk ./rts/rts/constants.h 17
-#define SLAB_FLAG_DELAY     4
+#define SLAB_FLAG_DELAY        4
+
+// A global finalizer exists for this slab
+#define SLAB_GLOBAL_FINALIZER  8
+
+// slab is a monolith, should be 'free'd when done with and not returned to
+// cache.
+#define SLAB_MONOLITH          16
+
+// virtual flags are never set in a cache but are used internally to keep track
+// of things.
+
+// virtual flag to indicate location is a value
+#define SLAB_VIRTUAL_VALUE    256
+
+// virtual flag to indicate location has a special intererpretation.
+#define SLAB_VIRTUAL_SPECIAL  512
+
+// virtual flag to indication location is a constant.
+#define SLAB_VIRTUAL_CONSTANT 1024
hunk ./rts/rts/gc.h 15
-void jhc_alloc_print_stats(void);
hunk ./rts/rts/gc_jgc.c 14
+        SLIST_HEAD(,s_block) monolithic_blocks;
hunk ./rts/rts/gc_jgc.c 46
+        void (*init_fn)(void *);
+        void (*fini_fn)(void *);
+#if _JHC_PROFILE
+        unsigned allocations;
+#endif
hunk ./rts/rts/gc_jgc.c 55
-static unsigned number_gcs;             // number of garbage collections
-static unsigned number_allocs;          // number of allocations since last garbage collection
+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 59
-#define gc_frame0(gc,n,...) void *ptrs[n] = { __VA_ARGS__ }; for(int i = 0; i < n; i++) gc[i] = (sptr_t)ptrs[i]; gc_t sgc = gc;  gc_t gc = sgc + n;
-#define gc_frame1(gc,p1) gc[0] = (sptr_t)p1; gc_t sgc = gc;  gc_t gc = sgc + 1;
-#define gc_frame2(gc,p1,p2) gc[0] = (sptr_t)p1; gc[1] = (sptr_t)p2; gc_t sgc = gc;  gc_t gc = sgc + 2;
hunk ./rts/rts/gc_jgc.c 225
-void jhc_alloc_print_stats(void) { }
+// 7 to share caches with the first 7 tuples
+#define GC_STATIC_ARRAY_NUM 256
+
+static struct s_cache *static_array_caches[GC_STATIC_ARRAY_NUM];
hunk ./rts/rts/gc_jgc.c 244
+        for (int i = 0; i < GC_STATIC_ARRAY_NUM; i++) {
+                find_cache(&static_array_caches[i], arena, i + 1, i + 1);
+        }
hunk ./rts/rts/gc_jgc.c 251
-        if(JHC_STATUS) {
+        if(_JHC_PROFILE || JHC_STATUS) {
hunk ./rts/rts/gc_jgc.c 276
+// Allocate an array of count garbage collectable locations in the garbage collected heap
+void *
+gc_array_alloc(gc_t gc, unsigned count)
+{
+        if (!count)
+               return NULL;
+        if (count <= GC_STATIC_ARRAY_NUM)
+                return (wptr_t)s_alloc(gc,static_array_caches[count - 1]);
+        //if (count < GC_MAX_BLOCK_ENTRIES)
+                return s_alloc(gc, find_cache(NULL, arena, count, count));
+        abort();
+}
+
hunk ./rts/rts/gc_jgc.c 370
+        struct s_block *pg = SLIST_FIRST(&arena->monolithic_blocks);
+        SLIST_INIT(&arena->monolithic_blocks);
+        while (pg) {
+                if(BIT_IS_SET(pg->used, 0)) {
+                        SLIST_INSERT_HEAD(&arena->monolithic_blocks, pg, link);
+                        pg = SLIST_NEXT(pg,link);
+                }
+                else  {
+                        void *ptr = pg;
+                        pg = SLIST_NEXT(pg,link);
+                        free(ptr);
+                }
+        }
hunk ./rts/rts/gc_jgc.c 385
-
hunk ./rts/rts/gc_jgc.c 395
-                struct s_block *pg = SLIST_FIRST(&sc->blocks);
+                pg = SLIST_FIRST(&sc->blocks);
hunk ./rts/rts/gc_jgc.c 406
+                                // Add full blockes to the cache's full block list.
hunk ./rts/rts/gc_jgc.c 409
+                                // Return completely free block to arena free block list.
hunk ./rts/rts/gc_jgc.c 411
-                                VALGRIND_MAKE_MEM_NOACCESS((char *)pg + sizeof(struct s_block), BLOCK_SIZE - sizeof(struct s_block));
+                                VALGRIND_MAKE_MEM_NOACCESS((char *)pg + sizeof(struct s_block),
+                                                           BLOCK_SIZE - sizeof(struct s_block));
hunk ./rts/rts/gc_jgc.c 454
+#if _JHC_PROFILE
+       sc->allocations++;
+#endif
hunk ./rts/rts/gc_jgc.c 463
-                        VALGRIND_MAKE_MEM_UNDEFINED((char *)pg->used,BITARRAY_SIZE_IN_BYTES(sc->num_entries));
+                        VALGRIND_MAKE_MEM_UNDEFINED((char *)pg->used,
+                                                    BITARRAY_SIZE_IN_BYTES(sc->num_entries));
hunk ./rts/rts/gc_jgc.c 466
-                        VALGRIND_MAKE_MEM_DEFINED((char *)pg->used,BITARRAY_SIZE_IN_BYTES(sc->num_entries));
+                        VALGRIND_MAKE_MEM_DEFINED((char *)pg->used,
+                                                  BITARRAY_SIZE_IN_BYTES(sc->num_entries));
hunk ./rts/rts/gc_jgc.c 499
+        memset(sc,0,sizeof(*sc));
hunk ./rts/rts/gc_jgc.c 506
-        //sc->num_entries = (8*excess) / (8*size*sizeof(uintptr_t) + 1);
-        sc->pi.color = (sizeof(struct s_block) + BITARRAY_SIZE_IN_BYTES(sc->num_entries) + sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
+        sc->pi.color = (sizeof(struct s_block) + BITARRAY_SIZE_IN_BYTES(sc->num_entries) +
+                        sizeof(uintptr_t) - 1) / sizeof(uintptr_t);
hunk ./rts/rts/gc_jgc.c 511
-        //print_cache(sc);
hunk ./rts/rts/gc_jgc.c 531
-// set a used bit. returns true if the
-// tagged node should be scanned by the GC.
-// this happens when the used bit was not previously set
-// and the node contains internal pointers.
+// Set a used bit. returns true if the tagged node should be scanned by the GC.
+// this happens when the used bit was not previously set and the node contains
+// internal pointers.
hunk ./rts/rts/gc_jgc.c 550
-find_cache(struct s_cache **rsc, struct s_arena *arena, unsigned short size, unsigned short num_ptrs)
+find_cache(struct s_cache **rsc, struct s_arena *arena,
+           unsigned short size, unsigned short num_ptrs)
hunk ./rts/rts/gc_jgc.c 573
+        SLIST_INIT(&arena->monolithic_blocks);
hunk ./rts/rts/gc_jgc.c 582
-        fprintf(stderr, "num_entries: %i\n",(int)sc->num_entries);
-//        printf("  entries: %i words\n",(int)(sc->num_entries*sc->pi.size));
-        fprintf(stderr, "  header: %lu bytes\n", sizeof(struct s_block) + BITARRAY_SIZE_IN_BYTES(sc->num_entries));
-        fprintf(stderr, "  size: %i words\n",(int)sc->pi.size);
-//        printf("  color: %i words\n",(int)sc->pi.color);
-        fprintf(stderr, "  nptrs: %i words\n",(int)sc->pi.num_ptrs);
-//        printf("  end: %i bytes\n",(int)(sc->pi.color+ sc->num_entries*sc->pi.size)*sizeof(uintptr_t));
+        fprintf(stderr, "num_entries: %i with %lu bytes of header\n",
+                (int)sc->num_entries, sizeof(struct s_block) +
+                BITARRAY_SIZE_IN_BYTES(sc->num_entries));
+        fprintf(stderr, "  size: %i words %i ptrs\n",
+                (int)sc->pi.size,(int)sc->pi.num_ptrs);
+#if _JHC_PROFILE
+        fprintf(stderr, "  allocations: %lu\n", (unsigned long)sc->allocations);
+#endif
+        if(SLIST_EMPTY(&sc->blocks) && SLIST_EMPTY(&sc->full_blocks))
+                return;
+        fprintf(stderr, "  blocks:\n");
hunk ./rts/rts/gc_jgc.c 595
-        SLIST_FOREACH(pg,&sc->blocks,link) {
-            fprintf(stderr, "%20p %9i %9i %c\n", pg, pg->num_free, pg->next_free, 'P');
-        }
-        fprintf(stderr, "  full_blocks:\n");
-        SLIST_FOREACH(pg,&sc->full_blocks,link) {
-            fprintf(stderr, "%20p %9i %9i %c\n", pg, pg->num_free, pg->next_free, 'F');
-        }
+        SLIST_FOREACH(pg,&sc->blocks,link)
+                fprintf(stderr, "%20p %9i %9i %c\n", pg, pg->num_free, pg->next_free, 'P');
+        SLIST_FOREACH(pg,&sc->full_blocks,link)
+                fprintf(stderr, "%20p %9i %9i %c\n", pg, pg->num_free, pg->next_free, 'F');
hunk ./rts/rts/gc_jgc.h 14
-#define S_BLOCK(val) ((struct s_block *)((uintptr_t)(val) & ~ (BLOCK_SIZE - 1)))
+#define S_BLOCK(val) ((struct s_block *)((uintptr_t)(val) & ~(BLOCK_SIZE - 1)))
hunk ./rts/rts/gc_jgc.h 30
+void *gc_array_alloc(gc_t gc, unsigned count);
hunk ./rts/rts/gc_jgc.h 35
+#define gc_frame1(gc,p1) gc[0] = (sptr_t)p1; gc_t sgc = gc;  gc_t gc = sgc + 1;
+#define gc_frame2(gc,p1,p2) gc[0] = (sptr_t)p1; gc[1] = (sptr_t)p2; \
+                                    gc_t sgc = gc;  gc_t gc = sgc + 2;
hunk ./rts/rts/gc_none.c 14
-void jhc_alloc_print_stats(void) { }
hunk ./rts/rts/gc_none.c 26
-void jhc_alloc_fini(void) {}
hunk ./rts/rts/gc_none.c 28
-jhc_alloc_print_stats(void) {
-        fprintf(stderr, "Memory Allocated: %u bytes\n", (JHC_MEM_CHUNK_SIZE*(mem_chunks)) + mem_offset);
-        print_alloc_size_stats();
+jhc_alloc_fini(void) {
+        if(_JHC_PROFILE) {
+                fprintf(stderr, "Memory Allocated: %u bytes\n", (JHC_MEM_CHUNK_SIZE*(mem_chunks)) + mem_offset);
+                print_alloc_size_stats();
+        }
hunk ./rts/rts/profile.c 80
-        jhc_alloc_print_stats();
hunk ./rts/rts/profile.c 92
-#if _JHC_PROFILE
+#if _JHC_PROFILE && _JHC_GC != _JHC_GC_JGC
hunk ./src/C/FromGrin2.hs 609
-    (malloc,tmp) <- jhc_malloc_ptrs  (operator "*" (sizeof sptr_t) c') =:: ptrType sptr_t
+    (malloc,tmp) <- jhc_malloc_ptrs c' =:: ptrType sptr_t
hunk ./src/C/FromGrin2.hs 931
-jhc_malloc_ptrs sz | fopts FO.Jgc =  functionCall (name "gc_alloc") [v_gc,nullPtr,tbsize sz, tbsize sz]
-jhc_malloc_ptrs sz = functionCall (name "jhc_malloc") [sz]
+jhc_malloc_ptrs sz | fopts FO.Jgc =  functionCall (name "gc_array_alloc") [v_gc, sz]
+jhc_malloc_ptrs sz = functionCall (name "jhc_malloc") [sizeof sptr_t *# sz]
hunk ./src/C/Generate.hs 6
+    (*#),
+    (+#),
hunk ./src/C/Generate.hs 685
+
hunk ./src/C/Generate.hs 688
+
+x *# y = operator "*" (toExpression x) (toExpression y)
+x +# y = operator "+" (toExpression x) (toExpression y)