on master help sign in
detach heap from vm struct
9631f80Sam T
rts/Makefile+2−2
@@ -1,7 +1,7 @@
1include ../config.mk
1include ../config.mk
2
2
3−OBJS = idris_rts.o idris_gc.o idris_gmp.o idris_stdfgn.o idris_bitstring.o
3+OBJS = idris_rts.o idris_heap.o idris_gc.o idris_gmp.o idris_stdfgn.o idris_bitstring.o
4−HDRS = idris_rts.h idris_gc.h idris_gmp.h idris_stdfgn.h idris_bitstring.h
4+HDRS = idris_rts.h idris_heap.h idris_gc.h idris_gmp.h idris_stdfgn.h idris_bitstring.h
5CFLAGS = -O2 -Wall
5CFLAGS = -O2 -Wall
6ifneq ($(GMP_INCLUDE_DIR),)
6ifneq ($(GMP_INCLUDE_DIR),)
7 CFLAGS += -isystem $(GMP_INCLUDE_DIR)
7 CFLAGS += -isystem $(GMP_INCLUDE_DIR)
rts/idris_gc.c+16−15
@@ -55,9 +55,9 @@ VAL copy(VM* vm, VAL x) {
55void cheney(VM *vm) {
55void cheney(VM *vm) {
56 int i;
56 int i;
57 int ar;
57 int ar;
58− char* scan = vm->heap;
58+ char* scan = vm->heap.heap;
59
59
60− while(scan < vm->heap_next) {
60+ while(scan < vm->heap.next) {
61 size_t inc = *((size_t*)scan);
61 size_t inc = *((size_t*)scan);
62 VAL heap_item = (VAL)(scan+sizeof(size_t));
62 VAL heap_item = (VAL)(scan+sizeof(size_t));
63 // If it's a CON, copy its arguments
63 // If it's a CON, copy its arguments
@@ -76,19 +76,20 @@ void cheney(VM *vm) {
76 }
76 }
77 scan += inc;
77 scan += inc;
78 }
78 }
79− assert(scan == vm->heap_next);
79+ assert(scan == vm->heap.next);
80}
80}
81
81
82void idris_gc(VM* vm) {
82void idris_gc(VM* vm) {
83 // printf("Collecting\n");
83 // printf("Collecting\n");
84
84
85− char* newheap = malloc(vm -> heap_size);
85+ char* newheap = malloc(vm->heap.size);
86− char* oldheap = vm -> heap;
86+ char* oldheap = vm->heap.heap;
87− if (vm->oldheap != NULL) free(vm->oldheap);
87+ if (vm->heap.old != NULL)
88+ free(vm->heap.old);
88
89
89− vm->heap = newheap;
90+ vm->heap.heap = newheap;
90− vm->heap_next = newheap;
91+ vm->heap.next = newheap;
91− vm->heap_end = newheap + vm->heap_size;
92+ vm->heap.end = newheap + vm->heap.size;
92
93
93 vm->collections++;
94 vm->collections++;
94
95
@@ -111,10 +112,10 @@ void idris_gc(VM* vm) {
111 // After reallocation, if we've still more than half filled the new heap, grow the heap
112 // After reallocation, if we've still more than half filled the new heap, grow the heap
112 // for next time.
113 // for next time.
113
114
114− if ((vm->heap_next - vm->heap) > vm->heap_size >> 1) {
115+ if ((vm->heap.next - vm->heap.heap) > vm->heap.size >> 1) {
115− vm->heap_size += vm->heap_growth;
116+ vm->heap.size += vm->heap.growth;
116 }
117 }
117− vm->oldheap = oldheap;
118+ vm->heap.old = oldheap;
118
119
119 // gcInfo(vm, 0);
120 // gcInfo(vm, 0);
120}
121}
@@ -123,8 +124,8 @@ void idris_gcInfo(VM* vm, int doGC) {
123 printf("\nStack: %p %p\n", vm->valstack, vm->valstack_top);
124 printf("\nStack: %p %p\n", vm->valstack, vm->valstack_top);
124 printf("Total allocations: %d\n", vm->allocations);
125 printf("Total allocations: %d\n", vm->allocations);
125 printf("GCs: %d\n", vm->collections);
126 printf("GCs: %d\n", vm->collections);
126− printf("Final heap size %d\n", (int)(vm->heap_size));
127+ printf("Final heap size %d\n", (int)(vm->heap.size));
127− printf("Final heap use %d\n", (int)(vm->heap_next - vm->heap));
128+ printf("Final heap use %d\n", (int)(vm->heap.next - vm->heap.heap));
128 if (doGC) { idris_gc(vm); }
129 if (doGC) { idris_gc(vm); }
129− printf("Final heap use after GC %d\n", (int)(vm->heap_next - vm->heap));
130+ printf("Final heap use after GC %d\n", (int)(vm->heap.next - vm->heap.heap));
130}
131}
rts/idris_heap.cnew file+31
@@ -0,0 +1,31 @@
1+#include "idris_heap.h"
2+
3+#include <stdlib.h>
4+#include <stddef.h>
5+#include <stdio.h>
6+
7+void alloc_heap(Heap * h, size_t heap_size)
8+{
9+ char * mem = malloc(heap_size);
10+ if (mem == NULL) {
11+ fprintf(stderr, "Unable to allocate heap. Requested %d bytes.\n", heap_size);
12+ exit(EXIT_FAILURE);
13+ }
14+
15+ h->heap = mem;
16+ h->next = h->heap;
17+ h->end = h->heap + heap_size;
18+
19+ h->size = heap_size;
20+ h->growth = heap_size;
21+
22+ h->old = NULL;
23+}
24+
25+void free_heap(Heap * h) {
26+ free(h->heap);
27+
28+ if (h->old != NULL) {
29+ free(h->old);
30+ }
31+}
rts/idris_heap.hnew file+20
@@ -0,0 +1,20 @@
1+#ifndef _IDRIS_HEAP_H
2+#define _IDRIS_HEAP_H
3+
4+#include <stddef.h>
5+
6+typedef struct {
7+ char* next; // Next allocated chunk. Should always (heap <= next < end).
8+ char* heap; // Point to bottom of heap
9+ char* end; // Point to top of heap
10+ size_t size; // Size of _next_ heap. Size of current heap is /end - heap/.
11+ size_t growth; // Quantity of heap growth in bytes. TODO: should it be constant?
12+
13+ char* old;
14+ // TODO heap usage
15+} Heap;
16+
17+void alloc_heap(Heap * heap, size_t heap_size);
18+void free_heap(Heap * heap);
19+
20+#endif
rts/idris_rts.c+16−15
@@ -10,6 +10,7 @@
10#include "idris_gc.h"
10#include "idris_gc.h"
11#include "idris_bitstring.h"
11#include "idris_bitstring.h"
12
12
13+
13VM* init_vm(int stack_size, size_t heap_size,
14VM* init_vm(int stack_size, size_t heap_size,
14 int max_threads, // not implemented yet
15 int max_threads, // not implemented yet
15 int argc, char* argv[]) {
16 int argc, char* argv[]) {
@@ -26,14 +27,12 @@ VM* init_vm(int stack_size, size_t heap_size,
26 vm->floatstack = floatstack;
27 vm->floatstack = floatstack;
27 vm->floatstack_ptr = floatstack;
28 vm->floatstack_ptr = floatstack;
28 vm->stack_max = valstack + stack_size;
29 vm->stack_max = valstack + stack_size;
30+
29− vm->heap = malloc(heap_size);
31+ alloc_heap(&(vm->heap), heap_size);
30− vm->oldheap = NULL;
32+
31− vm->heap_next = vm->heap;
32− vm->heap_end = vm->heap + heap_size;
33− vm->heap_size = heap_size;
34 vm->collections = 0;
33 vm->collections = 0;
35 vm->allocations = 0;
34 vm->allocations = 0;
36− vm->heap_growth = heap_size;
35+
37 vm->ret = NULL;
36 vm->ret = NULL;
38 vm->reg1 = NULL;
37 vm->reg1 = NULL;
39
38
@@ -68,9 +67,11 @@ void terminate(VM* vm) {
68 free(vm->valstack);
67 free(vm->valstack);
69 free(vm->intstack);
68 free(vm->intstack);
70 free(vm->floatstack);
69 free(vm->floatstack);
70+
71− free(vm->heap);
71+ free_heap(&(vm->heap));
72+
72 free(vm->argv);
73 free(vm->argv);
73− if (vm->oldheap != NULL) { free(vm->oldheap); }
74+
74 pthread_mutex_destroy(&(vm -> inbox_lock));
75 pthread_mutex_destroy(&(vm -> inbox_lock));
75 pthread_mutex_destroy(&(vm -> inbox_block));
76 pthread_mutex_destroy(&(vm -> inbox_block));
76 pthread_cond_destroy(&(vm -> inbox_waiting));
77 pthread_cond_destroy(&(vm -> inbox_waiting));
@@ -78,7 +79,7 @@ void terminate(VM* vm) {
78}
79}
79
80
80void idris_requireAlloc(VM* vm, size_t size) {
81void idris_requireAlloc(VM* vm, size_t size) {
81− if (!(vm -> heap_next + size < vm -> heap_end)) {
82+ if (!(vm->heap.next + size < vm->heap.end)) {
82 idris_gc(vm);
83 idris_gc(vm);
83 }
84 }
84
85
@@ -106,11 +107,11 @@ void* allocate(VM* vm, size_t size, int outerlock) {
106 if ((size & 7)!=0) {
107 if ((size & 7)!=0) {
107 size = 8 + ((size >> 3) << 3);
108 size = 8 + ((size >> 3) << 3);
108 }
109 }
109− if (vm -> heap_next + size < vm -> heap_end) {
110+ if (vm -> heap.next + size < vm -> heap.end) {
110 vm->allocations += size + sizeof(size_t);
111 vm->allocations += size + sizeof(size_t);
111− void* ptr = (void*)(vm->heap_next + sizeof(size_t));
112+ void* ptr = (void*)(vm->heap.next + sizeof(size_t));
112− *((size_t*)(vm->heap_next)) = size + sizeof(size_t);
113+ *((size_t*)(vm->heap.next)) = size + sizeof(size_t);
113− vm -> heap_next += size + sizeof(size_t);
114+ vm -> heap.next += size + sizeof(size_t);
114 memset(ptr, 0, size);
115 memset(ptr, 0, size);
115 if (lock) { // not message passing
116 if (lock) { // not message passing
116 pthread_mutex_unlock(&vm->alloc_lock);
117 pthread_mutex_unlock(&vm->alloc_lock);
@@ -208,7 +209,7 @@ void dumpStack(VM* vm) {
208 for (root = vm->valstack; root < vm->valstack_top; ++root, ++i) {
209 for (root = vm->valstack; root < vm->valstack_top; ++root, ++i) {
209 printf("%d: ", i);
210 printf("%d: ", i);
210 dumpVal(*root);
211 dumpVal(*root);
211− if (*root >= (VAL)(vm->heap) && *root < (VAL)(vm->heap_end)) { printf("OK"); }
212+ if (*root >= (VAL)(vm->heap.heap) && *root < (VAL)(vm->heap.end)) { printf("OK"); }
212 printf("\n");
213 printf("\n");
213 }
214 }
214 printf("RET: ");
215 printf("RET: ");
@@ -406,7 +407,7 @@ void* runThread(void* arg) {
406}
407}
407
408
408void* vmThread(VM* callvm, func f, VAL arg) {
409void* vmThread(VM* callvm, func f, VAL arg) {
409− VM* vm = init_vm(callvm->stack_max - callvm->valstack, callvm->heap_size,
410+ VM* vm = init_vm(callvm->stack_max - callvm->valstack, callvm->heap.size,
410 callvm->max_threads,
411 callvm->max_threads,
411 0, NULL);
412 0, NULL);
412 vm->processes=1; // since it can send and receive messages
413 vm->processes=1; // since it can send and receive messages
rts/idris_rts.h+5−7
@@ -9,6 +9,8 @@
9#include <pthread.h>
9#include <pthread.h>
10#include <stdint.h>
10#include <stdint.h>
11
11
12+#include "idris_heap.h"
13+
12// Closures
14// Closures
13
15
14typedef enum {
16typedef enum {
@@ -47,12 +49,10 @@ typedef struct {
47 VAL* valstack_base;
49 VAL* valstack_base;
48 int* intstack_ptr;
50 int* intstack_ptr;
49 double* floatstack_ptr;
51 double* floatstack_ptr;
50− char* heap;
51− char* oldheap;
52− char* heap_next;
53− char* heap_end;
54 VAL* stack_max;
52 VAL* stack_max;
55−
53+
54+ Heap heap;
55+
56 pthread_mutex_t inbox_lock;
56 pthread_mutex_t inbox_lock;
57 pthread_mutex_t inbox_block;
57 pthread_mutex_t inbox_block;
58 pthread_mutex_t alloc_lock;
58 pthread_mutex_t alloc_lock;
@@ -70,8 +70,6 @@ typedef struct {
70 int argc;
70 int argc;
71 VAL* argv; // command line arguments
71 VAL* argv; // command line arguments
72
72
73− size_t heap_size;
74− size_t heap_growth;
75 int allocations;
73 int allocations;
76 int collections;
74 int collections;
77 VAL ret;
75 VAL ret;