on master help sign in
detach heap from vm struct
commit9631f80c70a649d764fd4d55c30f60bec59f60d1 authorSam T <sta.cs.vsu@gmail.com> dateWed 13 Mar 2013, 17:11 (14 years ago) parent9841e2a
6 files changed+90−39
rts/Makefile+2−2 rts/idris_gc.c+16−15 rts/idris_heap.c+31 rts/idris_heap.h+20 rts/idris_rts.c+16−15 rts/idris_rts.h+5−7
rts/Makefile+2−2
@@ -1,7 +1,7 @@
11include ../config.mk
22
3−OBJS = idris_rts.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
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_heap.h idris_gc.h idris_gmp.h idris_stdfgn.h idris_bitstring.h
55CFLAGS = -O2 -Wall
66ifneq ($(GMP_INCLUDE_DIR),)
77 CFLAGS += -isystem $(GMP_INCLUDE_DIR)
rts/idris_gc.c+16−15
@@ -55,9 +55,9 @@ VAL copy(VM* vm, VAL x) {
5555void cheney(VM *vm) {
5656 int i;
5757 int ar;
58− char* scan = vm->heap;
58+ char* scan = vm->heap.heap;
5959
60− while(scan < vm->heap_next) {
60+ while(scan < vm->heap.next) {
6161 size_t inc = *((size_t*)scan);
6262 VAL heap_item = (VAL)(scan+sizeof(size_t));
6363 // If it's a CON, copy its arguments
@@ -76,19 +76,20 @@ void cheney(VM *vm) {
7676 }
7777 scan += inc;
7878 }
79− assert(scan == vm->heap_next);
79+ assert(scan == vm->heap.next);
8080}
8181
8282void idris_gc(VM* vm) {
8383 // printf("Collecting\n");
8484
85− char* newheap = malloc(vm -> heap_size);
86− char* oldheap = vm -> heap;
87− if (vm->oldheap != NULL) free(vm->oldheap);
85+ char* newheap = malloc(vm->heap.size);
86+ char* oldheap = vm->heap.heap;
87+ if (vm->heap.old != NULL)
88+ free(vm->heap.old);
8889
89− vm->heap = newheap;
90− vm->heap_next = newheap;
91− vm->heap_end = newheap + vm->heap_size;
90+ vm->heap.heap = newheap;
91+ vm->heap.next = newheap;
92+ vm->heap.end = newheap + vm->heap.size;
9293
9394 vm->collections++;
9495
@@ -111,10 +112,10 @@ void idris_gc(VM* vm) {
111112 // After reallocation, if we've still more than half filled the new heap, grow the heap
112113 // for next time.
113114
114− if ((vm->heap_next - vm->heap) > vm->heap_size >> 1) {
115− vm->heap_size += vm->heap_growth;
115+ if ((vm->heap.next - vm->heap.heap) > vm->heap.size >> 1) {
116+ vm->heap.size += vm->heap.growth;
116117 }
117− vm->oldheap = oldheap;
118+ vm->heap.old = oldheap;
118119
119120 // gcInfo(vm, 0);
120121}
@@ -123,8 +124,8 @@ void idris_gcInfo(VM* vm, int doGC) {
123124 printf("\nStack: %p %p\n", vm->valstack, vm->valstack_top);
124125 printf("Total allocations: %d\n", vm->allocations);
125126 printf("GCs: %d\n", vm->collections);
126− printf("Final heap size %d\n", (int)(vm->heap_size));
127− printf("Final heap use %d\n", (int)(vm->heap_next - vm->heap));
127+ printf("Final heap size %d\n", (int)(vm->heap.size));
128+ printf("Final heap use %d\n", (int)(vm->heap.next - vm->heap.heap));
128129 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));
130131}
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 @@
1010#include "idris_gc.h"
1111#include "idris_bitstring.h"
1212
13+
1314VM* init_vm(int stack_size, size_t heap_size,
1415 int max_threads, // not implemented yet
1516 int argc, char* argv[]) {
@@ -26,14 +27,12 @@ VM* init_vm(int stack_size, size_t heap_size,
2627 vm->floatstack = floatstack;
2728 vm->floatstack_ptr = floatstack;
2829 vm->stack_max = valstack + stack_size;
29− vm->heap = malloc(heap_size);
30− vm->oldheap = NULL;
31− vm->heap_next = vm->heap;
32− vm->heap_end = vm->heap + heap_size;
33− vm->heap_size = heap_size;
30+
31+ alloc_heap(&(vm->heap), heap_size);
32+
3433 vm->collections = 0;
3534 vm->allocations = 0;
36− vm->heap_growth = heap_size;
35+
3736 vm->ret = NULL;
3837 vm->reg1 = NULL;
3938
@@ -68,9 +67,11 @@ void terminate(VM* vm) {
6867 free(vm->valstack);
6968 free(vm->intstack);
7069 free(vm->floatstack);
71− free(vm->heap);
70+
71+ free_heap(&(vm->heap));
72+
7273 free(vm->argv);
73− if (vm->oldheap != NULL) { free(vm->oldheap); }
74+
7475 pthread_mutex_destroy(&(vm -> inbox_lock));
7576 pthread_mutex_destroy(&(vm -> inbox_block));
7677 pthread_cond_destroy(&(vm -> inbox_waiting));
@@ -78,7 +79,7 @@ void terminate(VM* vm) {
7879}
7980
8081void 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)) {
8283 idris_gc(vm);
8384 }
8485
@@ -106,11 +107,11 @@ void* allocate(VM* vm, size_t size, int outerlock) {
106107 if ((size & 7)!=0) {
107108 size = 8 + ((size >> 3) << 3);
108109 }
109− if (vm -> heap_next + size < vm -> heap_end) {
110+ if (vm -> heap.next + size < vm -> heap.end) {
110111 vm->allocations += size + sizeof(size_t);
111− void* ptr = (void*)(vm->heap_next + sizeof(size_t));
112− *((size_t*)(vm->heap_next)) = size + sizeof(size_t);
113− vm -> heap_next += size + sizeof(size_t);
112+ void* ptr = (void*)(vm->heap.next + sizeof(size_t));
113+ *((size_t*)(vm->heap.next)) = size + sizeof(size_t);
114+ vm -> heap.next += size + sizeof(size_t);
114115 memset(ptr, 0, size);
115116 if (lock) { // not message passing
116117 pthread_mutex_unlock(&vm->alloc_lock);
@@ -208,7 +209,7 @@ void dumpStack(VM* vm) {
208209 for (root = vm->valstack; root < vm->valstack_top; ++root, ++i) {
209210 printf("%d: ", i);
210211 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"); }
212213 printf("\n");
213214 }
214215 printf("RET: ");
@@ -406,7 +407,7 @@ void* runThread(void* arg) {
406407}
407408
408409void* 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,
410411 callvm->max_threads,
411412 0, NULL);
412413 vm->processes=1; // since it can send and receive messages
rts/idris_rts.h+5−7
@@ -9,6 +9,8 @@
99#include <pthread.h>
1010#include <stdint.h>
1111
12+#include "idris_heap.h"
13+
1214// Closures
1315
1416typedef enum {
@@ -47,12 +49,10 @@ typedef struct {
4749 VAL* valstack_base;
4850 int* intstack_ptr;
4951 double* floatstack_ptr;
50− char* heap;
51− char* oldheap;
52− char* heap_next;
53− char* heap_end;
5452 VAL* stack_max;
55−
53+
54+ Heap heap;
55+
5656 pthread_mutex_t inbox_lock;
5757 pthread_mutex_t inbox_block;
5858 pthread_mutex_t alloc_lock;
@@ -70,8 +70,6 @@ typedef struct {
7070 int argc;
7171 VAL* argv; // command line arguments
7272
73− size_t heap_size;
74− size_t heap_growth;
7573 int allocations;
7674 int collections;
7775 VAL ret;