on master help sign in
Blindly implement the C heap in the RTS.
commit1daf2213777b2d39103773a08bc6d6aa19a550e0 authorMatus Tejiscak <ziman@functor.sk> dateThu 21 Jan 2016, 18:13 (11 years ago) parent374b18e
5 files changed+127−1
rts/idris_gc.c+7 rts/idris_heap.c+68 rts/idris_heap.h+24 rts/idris_rts.c+23 rts/idris_rts.h+5−1
rts/idris_gc.c+7
@@ -60,6 +60,10 @@ VAL copy(VM* vm, VAL x) {
6060 memcpy(cl, x, size);
6161 }
6262 break;
63+ case CDATA:
64+ cl = MKCDATAc(vm, x->info.c_heap_item);
65+ c_heap_mark_item(x->info.c_heap_item);
66+ break;
6367 default:
6468 break;
6569 }
@@ -135,6 +139,9 @@ void idris_gc(VM* vm) {
135139
136140 STATS_LEAVE_GC(vm->stats, vm->heap.size, vm->heap.next - vm->heap.heap)
137141 HEAP_CHECK(vm)
142+
143+ // finally, sweep the C heap
144+ c_heap_sweep(&vm->c_heap);
138145}
139146
140147void idris_gcInfo(VM* vm, int doGC) {
rts/idris_heap.c+68
@@ -5,6 +5,74 @@
55#include <stddef.h>
66#include <stdio.h>
77
8+CHeapItem * c_heap_create_item(void * data, CDataFinalizer_t * finalizer)
9+{
10+ CHeapItem * item = (CHeapItem *) malloc(sizeof(CHeapItem));
11+
12+ item->data = data;
13+ item->finalizer = finalizer;
14+ item->is_inserted = false;
15+ item->is_used = false;
16+ item->next = NULL;
17+
18+ return item;
19+}
20+
21+void c_heap_insert(CHeap * heap, CHeapItem * item)
22+{
23+ item->next = heap->first;
24+ heap->first = item;
25+}
26+
27+void c_heap_mark_item(CHeapItem * item)
28+{
29+ item->is_used = true;
30+}
31+
32+static void c_heap_free_item(CHeapItem * item)
33+{
34+ item->finalizer(item->data);
35+ free(item);
36+}
37+
38+void c_heap_sweep(CHeap * heap)
39+{
40+ CHeapItem ** prev_next = &heap->first;
41+ CHeapItem * p = heap->first;
42+ while (p != NULL)
43+ {
44+ if (p->is_used)
45+ {
46+ p->is_used = false;
47+ prev_next = &p->next;
48+ p = p->next;
49+ }
50+ else
51+ {
52+ CHeapItem * unused_item = p;
53+ p = p->next;
54+
55+ *prev_next = unused_item->next;
56+ c_heap_free_item(unused_item);
57+ }
58+ }
59+}
60+
61+void c_heap_init(CHeap * heap)
62+{
63+ heap->first = NULL;
64+}
65+
66+void c_heap_free(CHeap * heap)
67+{
68+ CHeapItem * p = heap->first;
69+ while (p != NULL)
70+ {
71+ CHeapItem * q = p;
72+ p = p->next;
73+ c_heap_free_item(q);
74+ }
75+}
876
977/* Used for initializing the heap. */
1078void alloc_heap(Heap * h, size_t heap_size, size_t growth, char * old)
rts/idris_heap.h+24
@@ -1,8 +1,32 @@
11#ifndef _IDRIS_HEAP_H
22#define _IDRIS_HEAP_H
33
4+#include <stdbool.h>
45#include <stddef.h>
56
7+typedef void CDataFinalizer_t(void *);
8+
9+typedef struct CHeapItem {
10+ void * data;
11+ CDataFinalizer_t * finalizer; // responsible for freeing the passed pointer, too
12+ bool is_used;
13+ bool is_inserted;
14+ struct CHeapItem * next;
15+} CHeapItem;
16+
17+typedef struct CHeap {
18+ CHeapItem * first;
19+} CHeap;
20+
21+void c_heap_init(CHeap * c_heap);
22+void c_heap_free(CHeap * c_heap);
23+void c_heap_insert(CHeap * c_heap, CHeapItem * item);
24+void c_heap_mark_item(CHeapItem * item);
25+void c_heap_sweep(CHeap * c_heap);
26+
27+// this is the function to use in C binding code
28+CHeapItem * c_heap_create_item(void * data, CDataFinalizer_t * finalizer);
29+
630typedef struct {
731 char* next; // Next allocated chunk. Should always (heap <= next < end).
832 char* heap; // Point to bottom of heap
rts/idris_rts.c+23
@@ -35,6 +35,8 @@ VM* init_vm(int stack_size, size_t heap_size,
3535
3636 alloc_heap(&(vm->heap), heap_size, heap_size, NULL);
3737
38+ c_heap_init(&vm->c_heap);
39+
3840 vm->ret = NULL;
3941 vm->reg1 = NULL;
4042#ifdef HAS_PTHREAD
@@ -108,6 +110,7 @@ Stats terminate(VM* vm) {
108110#endif
109111 free(vm->valstack);
110112 free_heap(&(vm->heap));
113+ c_heap_free(&(vm->c_heap));
111114#ifdef HAS_PTHREAD
112115 pthread_mutex_destroy(&(vm -> inbox_lock));
113116 pthread_mutex_destroy(&(vm -> inbox_block));
@@ -264,6 +267,26 @@ char* GETSTROFF(VAL stroff) {
264267 return (root->str->info.str + root->offset);
265268}
266269
270+VAL MKCDATA(VM* vm, CHeapItem * item) {
271+ Closure* cl = allocate(sizeof(Closure), 0);
272+ SETTY(cl, CDATA);
273+ if (!item->is_inserted)
274+ {
275+ c_heap_insert(&vm->c_heap, item);
276+ }
277+ return cl;
278+}
279+
280+VAL MKCDATAc(VM* vm, CHeapItem * item) {
281+ Closure* cl = allocate(sizeof(Closure), 1);
282+ SETTY(cl, CDATA);
283+ if (!item->is_inserted)
284+ {
285+ c_heap_insert(&vm->c_heap, item);
286+ }
287+ return cl;
288+}
289+
267290VAL MKPTR(VM* vm, void* ptr) {
268291 Closure* cl = allocate(sizeof(Closure), 0);
269292 SETTY(cl, PTR);
rts/idris_rts.h+5−1
@@ -27,7 +27,7 @@
2727typedef enum {
2828 CON, INT, BIGINT, FLOAT, STRING, STROFFSET,
2929 BITS8, BITS16, BITS32, BITS64, UNIT, PTR, FWD,
30− MANAGEDPTR, RAWDATA
30+ MANAGEDPTR, RAWDATA, CDATA
3131} ClosureType;
3232
3333typedef struct Closure *VAL;
@@ -67,6 +67,7 @@ typedef struct Closure {
6767 uint32_t bits32;
6868 uint64_t bits64;
6969 ManagedPtr* mptr;
70+ CHeapItem* c_heap_item;
7071 size_t size;
7172 } info;
7273} Closure;
@@ -90,6 +91,7 @@ struct VM_t {
9091 VAL* valstack_base;
9192 VAL* stack_max;
9293
94+ CHeap c_heap;
9395 Heap heap;
9496#ifdef HAS_PTHREAD
9597 pthread_mutex_t inbox_lock;
@@ -207,6 +209,7 @@ VAL MKB8(VM* vm, uint8_t b);
207209VAL MKB16(VM* vm, uint16_t b);
208210VAL MKB32(VM* vm, uint32_t b);
209211VAL MKB64(VM* vm, uint64_t b);
212+VAL MKCDATA(VM* vm, CHeapItem * item);
210213
211214// following versions don't take a lock when allocating
212215VAL MKFLOATc(VM* vm, double val);
@@ -214,6 +217,7 @@ VAL MKSTROFFc(VM* vm, StrOffset* off);
214217VAL MKSTRc(VM* vm, char* str);
215218VAL MKPTRc(VM* vm, void* ptr);
216219VAL MKMPTRc(VM* vm, void* ptr, size_t size);
220+VAL MKCDATAc(VM* vm, CHeapItem * item);
217221
218222char* GETSTROFF(VAL stroff);
219223