on master help sign in
Added a simple copying GC
commit30093190194fbae48e75feb8548041d2a52fd6de authorEdwin Brady <eb@cs.st-andrews.ac.uk> dateWed 5 Sep 2012, 13:23 (14 years ago) parent29ba32e
8 files changed+145−9
iif/testmap.iif+12−1 rts/Makefile+2−2 rts/idris_gc.c+90 rts/idris_gc.h+8 rts/idris_main.c+5 rts/idris_rts.c+18−2 rts/idris_rts.h+9−3 src/IRTS/LParser.hs+1−1
iif/testmap.iif+12−1
@@ -13,7 +13,18 @@ fun dumpList(xs) = case xs of {
1313 | Cons(y, ys) => %IntString(y) ++ ", " ++ dumpList(ys)
1414 }
1515
16+fun countFrom(x) = Cons(x, countFrom@(x+1))
17+
18+fun take(n, xs) = case n of {
19+ 0 => Nil
20+ | _ => case xs of {
21+ Nil => Nil
22+ | Cons(y, ys) => Cons(y, take(n-1, ys))
23+ }
24+ }
25+
1626fun double(x) = x + x
1727
1828fun main() = let mult = 2 in
19− %WriteString(dumpList(map(twice(\ x => x*mult), Cons(4, Cons(6, Nil)))))
29+ %WriteString(dumpList(map(twice(\ x => x*mult), take(1010, countFrom(10)))))
30+
rts/Makefile+2−2
@@ -1,5 +1,5 @@
1−OBJS = idris_rts.o
2−HDRS = idris_rts.h
1+OBJS = idris_rts.o idris_gc.o
2+HDRS = idris_rts.h idris_gc.h
33CFLAGS = -g
44
55LIBTARGET = libidris_rts.a
rts/idris_gc.cnew file+90
@@ -0,0 +1,90 @@
1+#include "idris_rts.h"
2+#include "idris_gc.h"
3+
4+VAL copy(VM* vm, VAL x) {
5+ int i;
6+ VAL* argptr;
7+ Closure* cl;
8+ if (x==NULL || ISINT(x)) {
9+ return x;
10+ }
11+ switch(x->ty) {
12+ case CON:
13+ cl = allocCon(vm, x->info.c.arity);
14+ cl->info.c.tag = x->info.c.tag;
15+ cl->info.c.arity = x->info.c.arity;
16+
17+ argptr = (VAL*)(cl->info.c.args);
18+ for(i = 0; i < x->info.c.arity; ++i) {
19+// *argptr = copy(vm, *((VAL*)(x->info.c.args)+i)); // recursive version
20+ *argptr = *((VAL*)(x->info.c.args)+i);
21+ argptr++;
22+ }
23+ break;
24+ case FLOAT:
25+ cl = MKFLOAT(vm, x->info.f);
26+ break;
27+ case STRING:
28+ cl = MKSTR(vm, x->info.str);
29+ break;
30+ case PTR:
31+ cl = MKPTR(vm, x->info.ptr);
32+ break;
33+ case FWD:
34+ cl = x->info.ptr;
35+ break;
36+ }
37+ x->ty = FWD;
38+ x->info.ptr = cl;
39+ return cl;
40+}
41+
42+void cheney(VM *vm) {
43+ VAL* argptr;
44+ int i;
45+ char* scan = vm->heap;
46+
47+ while(scan < vm->heap_next) {
48+ size_t inc = *((size_t*)scan);
49+ VAL heap_item = (VAL)(scan+sizeof(size_t)*2);
50+ // If it's a CON, copy its arguments
51+ switch(heap_item->ty) {
52+ case CON:
53+ argptr = (VAL*)(heap_item->info.c.args);
54+ for(i = 0; i < heap_item->info.c.arity; ++i) {
55+ *argptr = copy(vm, *argptr);
56+ argptr++;
57+ }
58+ break;
59+ }
60+ scan += inc;
61+ }
62+}
63+
64+void gc(VM* vm) {
65+ char* newheap = malloc(vm -> heap_size);
66+ char* oldheap = vm -> heap;
67+
68+ vm->heap = newheap;
69+ vm->heap_next = newheap;
70+ vm->heap_end = newheap + vm->heap_size;
71+
72+ vm->collections++;
73+
74+ VAL* root;
75+
76+ for(root = vm->valstack; root < vm->valstack_top; ++root) {
77+ *root = copy(vm, *root);
78+ }
79+ vm->ret = copy(vm, vm->ret);
80+ cheney(vm);
81+
82+ // After reallocation, if we've still more than half filled the new heap, grow the heap
83+ // for next time.
84+
85+ if ((vm->heap_next - vm->heap) > vm->heap_size >> 1) {
86+ vm->heap_size += vm->heap_growth;
87+ }
88+
89+ free(oldheap);
90+}
rts/idris_gc.hnew file+8
@@ -0,0 +1,8 @@
1+#ifndef _IDRISGC_H
2+#define _IDRISGC_H
3+
4+#include "idris_rts.h"
5+
6+void gc(VM* vm);
7+
8+#endif
rts/idris_main.c+5
@@ -4,5 +4,10 @@ int main(int argc, char* argv[]) {
44 _idris_main(vm, NULL);
55#ifdef IDRIS_DEBUG
66 printf("\nStack: %p %p\n", vm->valstack, vm->valstack_top);
7+ printf("GCs: %d\n", vm->collections);
8+ printf("Final heap size %d\n", (int)(vm->heap_size));
9+ printf("Final heap use %d\n", (int)(vm->heap_next - vm->heap));
10+ gc(vm);
11+ printf("Final heap use after GC %d\n", (int)(vm->heap_next - vm->heap));
712#endif
813}
rts/idris_rts.c+18−2
@@ -5,6 +5,7 @@
55#include <stdarg.h>
66
77#include "idris_rts.h"
8+#include "idris_gc.h"
89
910VM* init_vm(int stack_size, size_t heap_size) {
1011 VAL* valstack = malloc(stack_size*sizeof(VAL));
@@ -22,12 +23,27 @@ VM* init_vm(int stack_size, size_t heap_size) {
2223 vm -> stack_max = stack_size;
2324 vm -> heap = malloc(heap_size);
2425 vm -> heap_next = vm -> heap;
26+ vm -> heap_end = vm -> heap + heap_size;
27+ vm -> heap_size = heap_size;
28+ vm -> collections = 0;
29+ vm -> heap_growth = heap_size;
2530 vm -> ret = NULL;
2631 return vm;
2732}
2833
29−void* allocate(VM* vm, int size) {
30− return malloc(size); // TMP!
34+void* allocate(VM* vm, size_t size) {
35+ if ((size & 7)!=0) {
36+ size = 8 + ((size >> 3) << 3);
37+ }
38+ if (vm -> heap_next + size < vm -> heap_end) {
39+ void* ptr = (void*)(((size_t*)(vm->heap_next))+2);
40+ *((size_t*)(vm->heap_next)) = size+sizeof(size_t)*2;
41+ vm -> heap_next += size+sizeof(size_t)*2;
42+ return ptr;
43+ } else {
44+ gc(vm);
45+ return allocate(vm, size);
46+ }
3147}
3248
3349void* allocCon(VM* vm, int arity) {
rts/idris_rts.h+9−3
@@ -10,7 +10,7 @@
1010// Closures
1111
1212typedef enum {
13− CON, INT, FLOAT, STRING, UNIT, PTR
13+ CON, INT, FLOAT, STRING, UNIT, PTR, FWD
1414} ClosureType;
1515
1616typedef struct {
@@ -40,9 +40,13 @@ typedef struct {
4040 VAL* valstack_base;
4141 int* intstack_ptr;
4242 double* floatstack_ptr;
43− void* heap;
44− void* heap_next;
43+ char* heap;
44+ char* heap_next;
45+ char* heap_end;
4546 int stack_max;
47+ size_t heap_size;
48+ size_t heap_growth;
49+ int collections;
4650 VAL ret;
4751} VM;
4852
@@ -103,6 +107,7 @@ VAL MKCON(VM* vm, int tag, int arity, ...);
103107void PROJECT(VM* vm, VAL r, int loc, int arity);
104108void SLIDE(VM* vm, int args);
105109
110+void* allocCon(VM* vm, int arity);
106111void dumpVal(VAL r);
107112
108113// Casts
@@ -128,4 +133,5 @@ VAL idris_readStr(VM* vm, FILE* h);
128133
129134void stackOverflow();
130135
136+
131137#endif
src/IRTS/LParser.hs+1−1
@@ -52,7 +52,7 @@ fovm f = do defs <- parseFOVM f
5252 let defuns = defunctionalise nexttag ctxtIn
5353-- print defuns
5454 let checked = checkDefs defuns (toAlist defuns)
55− print checked
55+-- print checked
5656 case checked of
5757 OK c -> codegenC c "a.out" True ["math.h"] "" TRACE
5858 Error e -> fail $ show e