on master help sign in
Add String offsets to VM
9418fe0Edwin Brady
rts/idris_gc.c+8−1
@@ -24,6 +24,9 @@ VAL copy(VM* vm, VAL x) {
24 case STRING:
24 case STRING:
25 cl = MKSTRc(vm, x->info.str);
25 cl = MKSTRc(vm, x->info.str);
26 break;
26 break;
27+ case STROFFSET:
28+ cl = MKSTROFFc(vm, x->info.str_offset);
29+ break;
27 case BIGINT:
30 case BIGINT:
28 cl = MKBIGMc(vm, x->info.ptr);
31 cl = MKBIGMc(vm, x->info.ptr);
29 break;
32 break;
@@ -60,7 +63,7 @@ void cheney(VM *vm) {
60 while(scan < vm->heap.next) {
63 while(scan < vm->heap.next) {
61 size_t inc = *((size_t*)scan);
64 size_t inc = *((size_t*)scan);
62 VAL heap_item = (VAL)(scan+sizeof(size_t));
65 VAL heap_item = (VAL)(scan+sizeof(size_t));
63− // If it's a CON, copy its arguments
66+ // If it's a CON or STROFFSET, copy its arguments
64 switch(GETTY(heap_item)) {
67 switch(GETTY(heap_item)) {
65 case CON:
68 case CON:
66 ar = ARITY(heap_item);
69 ar = ARITY(heap_item);
@@ -71,6 +74,10 @@ void cheney(VM *vm) {
71 heap_item->info.c.args[i] = newptr;
74 heap_item->info.c.args[i] = newptr;
72 }
75 }
73 break;
76 break;
77+ case STROFFSET:
78+ heap_item->info.str_offset->str
79+ = copy(vm, heap_item->info.str_offset->str);
80+ break;
74 default: // Nothing to copy
81 default: // Nothing to copy
75 break;
82 break;
76 }
83 }
rts/idris_rts.c+44−1
@@ -84,6 +84,10 @@ void idris_doneAlloc(VM* vm) {
84 }
84 }
85}
85}
86
86
87+int space(VM* vm, size_t size) {
88+ return (vm->heap.next + size + sizeof(size_t) < vm->heap.end);
89+}
90+
87void* allocate(VM* vm, size_t size, int outerlock) {
91void* allocate(VM* vm, size_t size, int outerlock) {
88// return malloc(size);
92// return malloc(size);
89 int lock = vm->processes > 0 && !outerlock;
93 int lock = vm->processes > 0 && !outerlock;
@@ -161,6 +165,12 @@ VAL MKSTR(VM* vm, const char* str) {
161 return cl;
165 return cl;
162}
166}
163
167
168+char* GETSTROFF(VAL stroff) {
169+ // Assume STROFF
170+ StrOffset* root = stroff->info.str_offset;
171+ return (root->str->info.str + root->offset);
172+}
173+
164VAL MKPTR(VM* vm, void* ptr) {
174VAL MKPTR(VM* vm, void* ptr) {
165 Closure* cl = allocate(vm, sizeof(Closure), 0);
175 Closure* cl = allocate(vm, sizeof(Closure), 0);
166 SETTY(cl, PTR);
176 SETTY(cl, PTR);
@@ -397,8 +407,41 @@ VAL idris_strHead(VM* vm, VAL str) {
397 return MKINT((i_int)(GETSTR(str)[0]));
407 return MKINT((i_int)(GETSTR(str)[0]));
398}
408}
399
409
410+VAL MKSTROFFc(VM* vm, StrOffset* off) {
411+ Closure* cl = allocate(vm, sizeof(Closure) + sizeof(StrOffset), 1);
412+ SETTY(cl, STROFFSET);
413+ cl->info.str_offset = (StrOffset*)((char*)cl + sizeof(Closure));
414+
415+ cl->info.str_offset->str = off->str;
416+ cl->info.str_offset->offset = off->offset;
417+
418+ return cl;
419+}
420+
400VAL idris_strTail(VM* vm, VAL str) {
421VAL idris_strTail(VM* vm, VAL str) {
422+ // If there's no room, just copy the string, or we'll have a problem after
423+ // gc moves str
424+ if (space(vm, sizeof(Closure) + sizeof(StrOffset))) {
425+ Closure* cl = allocate(vm, sizeof(Closure) + sizeof(StrOffset), 0);
426+ SETTY(cl, STROFFSET);
427+ cl->info.str_offset = (StrOffset*)((char*)cl + sizeof(Closure));
428+
429+ int offset = 0;
430+ VAL root = str;
431+
432+ while(root!=NULL && !ISSTR(root)) { // find the root, carry on.
433+ // In theory, at most one step here!
434+ offset += root->info.str_offset->offset;
435+ root = root->info.str_offset->str;
436+ }
437+
438+ cl->info.str_offset->str = root;
439+ cl->info.str_offset->offset = offset+1;
440+
441+ return cl;
442+ } else {
401− return MKSTR(vm, GETSTR(str)+1);
443+ return MKSTR(vm, GETSTR(str)+1);
444+ }
402}
445}
403
446
404VAL idris_strCons(VM* vm, VAL x, VAL xs) {
447VAL idris_strCons(VM* vm, VAL x, VAL xs) {
rts/idris_rts.h+13−2
@@ -15,7 +15,8 @@
15// Closures
15// Closures
16
16
17typedef enum {
17typedef enum {
18+ CON, INT, BIGINT, FLOAT, STRING, STROFFSET,
18− CON, INT, BIGINT, FLOAT, STRING, BITS8, BITS16, BITS32, BITS64, UNIT, PTR, FWD
19+ BITS8, BITS16, BITS32, BITS64, UNIT, PTR, FWD
19} ClosureType;
20} ClosureType;
20
21
21typedef struct Closure *VAL;
22typedef struct Closure *VAL;
@@ -25,6 +26,11 @@ typedef struct {
25 VAL args[];
26 VAL args[];
26} con;
27} con;
27
28
29+typedef struct {
30+ VAL str;
31+ int offset;
32+} StrOffset;
33+
28typedef struct Closure {
34typedef struct Closure {
29// Use top 16 bits of ty for saying which heap value is in
35// Use top 16 bits of ty for saying which heap value is in
30// Bottom 16 bits for closure type
36// Bottom 16 bits for closure type
@@ -34,6 +40,7 @@ typedef struct Closure {
34 int i;
40 int i;
35 double f;
41 double f;
36 char* str;
42 char* str;
43+ StrOffset* str_offset;
37 void* ptr;
44 void* ptr;
38 uint8_t bits8;
45 uint8_t bits8;
39 uint16_t bits16;
46 uint16_t bits16;
@@ -92,7 +99,7 @@ typedef void(*func)(VM*, VAL*);
92
99
93// Retrieving values
100// Retrieving values
94
101
95−#define GETSTR(x) (((VAL)(x))->info.str)
102+#define GETSTR(x) (ISSTR(x) ? (((VAL)(x))->info.str) : GETSTROFF(x))
96#define GETPTR(x) (((VAL)(x))->info.ptr)
103#define GETPTR(x) (((VAL)(x))->info.ptr)
97#define GETFLOAT(x) (((VAL)(x))->info.f)
104#define GETFLOAT(x) (((VAL)(x))->info.f)
98
105
@@ -119,6 +126,7 @@ typedef intptr_t i_int;
119#define MKINT(x) ((void*)((x)<<1)+1)
126#define MKINT(x) ((void*)((x)<<1)+1)
120#define GETINT(x) ((i_int)(x)>>1)
127#define GETINT(x) ((i_int)(x)>>1)
121#define ISINT(x) ((((i_int)x)&1) == 1)
128#define ISINT(x) ((((i_int)x)&1) == 1)
129+#define ISSTR(x) (((VAL)(x))->ty == STRING)
122
130
123#define INTOP(op,x,y) MKINT((i_int)((((i_int)x)>>1) op (((i_int)y)>>1)))
131#define INTOP(op,x,y) MKINT((i_int)((((i_int)x)>>1) op (((i_int)y)>>1)))
124#define UINTOP(op,x,y) MKINT((i_int)((((uintptr_t)x)>>1) op (((uintptr_t)y)>>1)))
132#define UINTOP(op,x,y) MKINT((i_int)((((uintptr_t)x)>>1) op (((uintptr_t)y)>>1)))
@@ -151,9 +159,12 @@ VAL MKB64(VM* vm, uint64_t b);
151
159
152// following versions don't take a lock when allocating
160// following versions don't take a lock when allocating
153VAL MKFLOATc(VM* vm, double val);
161VAL MKFLOATc(VM* vm, double val);
162+VAL MKSTROFFc(VM* vm, StrOffset* off);
154VAL MKSTRc(VM* vm, char* str);
163VAL MKSTRc(VM* vm, char* str);
155VAL MKPTRc(VM* vm, void* ptr);
164VAL MKPTRc(VM* vm, void* ptr);
156
165
166+char* GETSTROFF(VAL stroff);
167+
157// #define SETTAG(x, a) (x)->info.c.tag = (a)
168// #define SETTAG(x, a) (x)->info.c.tag = (a)
158#define SETARG(x, i, a) ((x)->info.c.args)[i] = ((VAL)(a))
169#define SETARG(x, i, a) ((x)->info.c.args)[i] = ((VAL)(a))
159#define GETARG(x, i) ((x)->info.c.args)[i]
170#define GETARG(x, i) ((x)->info.c.args)[i]