@@ -22,10 +22,12 @@ VM* init_vm(int stack_size, size_t heap_size) {
2222 vm -> floatstack_ptr = floatstack;
2323 vm -> stack_max = stack_size;
2424 vm -> heap = malloc(heap_size);
25+ vm -> oldheap = NULL;
2526 vm -> heap_next = vm -> heap;
2627 vm -> heap_end = vm -> heap + heap_size;
2728 vm -> heap_size = heap_size;
2829 vm -> collections = 0;
30+ vm -> allocations = 0;
2931 vm -> heap_growth = heap_size;
3032 vm -> ret = NULL;
3133 return vm;
@@ -35,6 +37,7 @@ void* allocate(VM* vm, size_t size) {
3537 if ((size & 7)!=0) {
3638 size = 8 + ((size >> 3) << 3);
3739 }
40+ vm->allocations += size+sizeof(size_t)*2;
3841 if (vm -> heap_next + size < vm -> heap_end) {
3942 void* ptr = (void*)(((size_t*)(vm->heap_next))+2);
4043 *((size_t*)(vm->heap_next)) = size+sizeof(size_t)*2;
@@ -48,12 +51,13 @@ void* allocate(VM* vm, size_t size) {
4851
4952void* allocCon(VM* vm, int arity) {
5053 Closure* cl = allocate(vm, sizeof(ClosureType) +
51− sizeof(con));
54+ sizeof(con) + sizeof(VAL)*arity);
5255 cl -> ty = CON;
5356 if (arity == 0) {
5457 cl -> info.c.args = NULL;
5558 } else {
56− cl -> info.c.args = allocate(vm, sizeof(VAL)*arity);
59+ cl -> info.c.args = (void*)((char*)cl + sizeof(ClosureType)
60+ + sizeof(con));
5761 }
5862 return (void*)cl;
5963}
@@ -66,9 +70,10 @@ VAL MKFLOAT(VM* vm, double val) {
6670}
6771
6872VAL MKSTR(VM* vm, char* str) {
69− Closure* cl = allocate(vm, sizeof(ClosureType) + sizeof(char*));
73+ Closure* cl = allocate(vm, sizeof(ClosureType) + sizeof(char*) +
74+ sizeof(char)*strlen(str)+1);
7075 cl -> ty = STRING;
71− cl -> info.str = allocate(vm, sizeof(char)*strlen(str)+1);
76+ cl -> info.str = (char*)cl + sizeof(ClosureType) + sizeof(char*);
7277 strcpy(cl -> info.str, str);
7378 return cl;
7479}
@@ -133,9 +138,9 @@ void dumpVal(VAL v) {
133138}
134139
135140VAL idris_castIntStr(VM* vm, VAL i) {
136− Closure* cl = allocate(vm, sizeof(ClosureType) + sizeof(char*));
141+ Closure* cl = allocate(vm, sizeof(ClosureType) + sizeof(char*) + sizeof(char)*16);
137142 cl -> ty = STRING;
138− cl -> info.str = allocate(vm, sizeof(char)*16);
143+ cl -> info.str = (char*)cl + sizeof(ClosureType) + sizeof(char*);
139144 sprintf(cl -> info.str, "%ld", GETINT(i));
140145 return cl;
141146}
@@ -147,9 +152,9 @@ VAL idris_castStrInt(VM* vm, VAL i) {
147152}
148153
149154VAL idris_castFloatStr(VM* vm, VAL i) {
150− Closure* cl = allocate(vm, sizeof(ClosureType) + sizeof(char*));
155+ Closure* cl = allocate(vm, sizeof(ClosureType) + sizeof(char*) + sizeof(char)*32);
151156 cl -> ty = STRING;
152− cl -> info.str = allocate(vm, sizeof(char)*32);
157+ cl -> info.str = (char*)cl + sizeof(ClosureType) + sizeof(char*);
153158 sprintf(cl -> info.str, "%g", GETFLOAT(i));
154159 return cl;
155160}
@@ -161,10 +166,15 @@ VAL idris_castStrFloat(VM* vm, VAL i) {
161166VAL idris_concat(VM* vm, VAL l, VAL r) {
162167 char *ls = GETSTR(l);
163168 char *rs = GETSTR(r);
169+ Closure* cl = allocate(vm, sizeof(ClosureType) + sizeof(char*) +
170+ strlen(ls) + strlen(rs) + 1);
171+ // Oops! problem if the second allocate triggers a gc because cl has
172+ // to be a root. Fix by allocating all in one go.
164173
165− Closure* cl = allocate(vm, sizeof(ClosureType) + sizeof(char*));
174+ // Also note that l/r may be in from space, so don't delete after collection,
175+ // rather, delete just before the next collection.
166176 cl -> ty = STRING;
167− cl -> info.str = allocate(vm, sizeof(char)*(strlen(ls)+strlen(rs)+1));
177+ cl -> info.str = (char*)cl + sizeof(ClosureType) + sizeof(char*);
168178 strcpy(cl -> info.str, ls);
169179 strcat(cl -> info.str, rs);
170180 return cl;