  #define header(x)                   *(word *x)
  #define imm_type(x)                 (((x) >> 3) & 0xff)
  #define imm_val(x)                  ((x) >> 12)
-+#define hdrsize(x)                  ((word) (((word)x) >> SPOS))
++#define hdrsize(x)                  ((((word)x) >> SPOS) & 0xffff)
  #define immediatep(x)               (((word)x)&2)
  #define allocp(x)                   (!immediatep(x))
  #define rawp(hdr)                   ((hdr)&RAWBIT)

- 
-    /* clear blank regs */
-    while(acc < NR) { R[acc++] = INULL; }
-@@ -923,6 +936,7 @@ word vm(word *ob, word *args) {
-    acc = 2; /* boot always calls with 2 args*/
- 
- apply: /* apply something at ob to values in regs, or maybe switch context */

- #define OCLOSE(proctype)            { word size = *ip++, tmp; word *ob; allocate(size, ob); tmp = R[*ip++]; tmp = ((word *) tmp)[*ip++]; *ob = make_header(size, proctype); ob[1] = tmp; tmp = 2; while(tmp != size) { ob[tmp++] = R[*ip++]; } R[*ip++] = (word) ob; }
- #define CLOSE1(proctype)            { word size = *ip++, tmp; word *ob; allocate(size, ob); tmp = R[1]; tmp = ((word *) tmp)[*ip++]; *ob = make_header(size, proctype); ob[1] = tmp; tmp = 2; while(tmp != size) { ob[tmp++] = R[*ip++]; } R[*ip++] = (word) ob; }
- #define EXEC switch(op&63) { \
-@@ -125,7 +129,7 @@ typedef unsigned long in_addr_t;
-       case 58: goto op58; case 59: goto op59; case 60: goto op60; case 61: goto op61; case 62: goto op62; case 63: goto op63; \
-    }
- 
--/* Globals and Prototypes */
-+/*** Globals and Prototypes ***/
- 
- /* memstart <= genstart <= memend */
- static word *genstart;
-@@ -148,7 +152,8 @@ char *getenv(const char *name);
- DIR *opendir(const char *name);
- DIR *fdopendir(int fd);
- 
--/* Garbage Collector, based on "Efficient Garbage Compaction Algorithm" by Johannes Martin (1982) */
-+
-+/*** Garbage Collector, based on "Efficient Garbage Compaction Algorithm" by Johannes Martin (1982) ***/
- 
- static __inline__ void rev(word pos) {
-    word val = V(pos);
-@@ -168,7 +173,7 @@ static __inline__ word *chase(word *pos) {
-    return pos;
- }
- 
--static void marks(word *pos, word *end) {
-+static void mark(word *pos, word *end) {
-    while (pos != end) {
-       word val = *pos;
-       if (allocp(val) && val >= ((word) genstart)) { 
-@@ -245,8 +250,9 @@ int adjust_heap(int cells) {
-    word *old = memstart;
-    word nwords = memend - memstart + MEMPAD; /* MEMPAD is after memend */
-    word new_words = nwords + cells;
--   if (!usegc) /* only run when the vm is running (temp) */
-+   if (!usegc) { /* only run when the vm is running (temp) */
-       return 0;
-+   }
-    if (seccompp) /* realloc is not allowed within seccomp */
-       return 0;
-    memstart = realloc(memstart, new_words*W);
-@@ -265,20 +271,54 @@ int adjust_heap(int cells) {
-    }
- }
- 
-+/* memstart                                      end
-+    v                                            v
-+   [hdr f1 ... fn] [hdr ...] ... [hdr f1 .. fm]  
-+   should work at any point in program operation when run for fp
-+ */
-+void check_heap(word *fp) {
-+	word *pos = memstart;
-+	while (pos < fp) {
-+		word h = *pos;
-+		int s = hdrsize(h); /* <- looking for potential sign issues in type promotion */
-+		if (!headerp(h))
-+			fprintf(stderr, "DEBUG: object has a non-header first field\n");
-+		if (s < 0 || s > 0xffff)
-+			fprintf(stderr, "DEBUG: object has a bad size \n");
-+		if (rawp(h)) {
-+			pos += s;
-+		} else {
-+			s--; pos++; /* skip header */
-+			while(s--) {
-+				word f = *pos++;
-+				if (immediatep(f)) 
-+					continue;
-+				if ((word) f > (word) pos) 
-+					fprintf(stderr, "DEBUG: up-pointer in heap\n");
-+				if (!headerp(V(f)))
-+					fprintf(stderr, "DEBUG: pointer to non-header\n");
-+			}
-+		}
-+   }
-+   if (pos != fp)
-+      fprintf(stderr, "DEBUG: heap didn't end exactly where it should have\n");
-+}
-+
- /* input desired allocation size and root object, 
-    return a pointer to the same object after compaction, resizing, possible heap relocation etc */
- static word *gc(int size, word *regs) {
-    word *root;
-    word *realend = memend;
-    int nfree, nused;
--   fp = regs + imm_val(*regs);
-+   fp = regs + hdrsize(*regs);
-+	check_heap(fp); /* pre GC heap integrity check */
-    root = fp+1;
-    *root = (word) regs;
--   fflush(stdout);
-    memend = fp;
--   marks(root, fp);
-+   mark(root, fp);
-    fp = compact();
-    regs = (word *) *root;
-+	check_heap(regs + hdrsize(*regs)); /* post GC heap integrity check */
-    memend = realend;
-    nfree = (word)memend - (word)regs;
-    nused = (word)regs - (word)genstart; 
-@@ -291,7 +331,7 @@ static word *gc(int size, word *regs) {
-       nfree -= size*W + MEMPAD;   /* how much really could be snipped off */
-       if (nfree < (heapsize / 20) || nfree < 0) {
-          /* increase heap size if less than 5% is free by ~10% of heap size (growth usually implies more growth) */
