on master help sign in
Avoid indirection for strings and take advantage of the 8 bytes in the union to reduce allocation size
9904389Jorge Acereda
rts/idris_gc.c+2−3
@@ -41,7 +41,7 @@ VAL copy(VM* vm, VAL x) {
41 cl = MKPTRc(vm, GETPTR(x));
41 cl = MKPTRc(vm, GETPTR(x));
42 break;
42 break;
43 case CT_MANAGEDPTR:
43 case CT_MANAGEDPTR:
44− cl = MKMPTRc(vm, x->info.managed_ptr, x->sz);
44+ cl = MKMPTRc(vm, x->info.mptr, x->sz);
45 break;
45 break;
46 case CT_BITS8:
46 case CT_BITS8:
47 cl = idris_b8CopyForGC(vm, x);
47 cl = idris_b8CopyForGC(vm, x);
@@ -107,8 +107,7 @@ void cheney(VM *vm) {
107 heap_item->info.ptr = copy(vm, (VAL)(GETPTR(heap_item)));
107 heap_item->info.ptr = copy(vm, (VAL)(GETPTR(heap_item)));
108 break;
108 break;
109 case CT_STROFFSET:
109 case CT_STROFFSET:
110− heap_item->info.str_offset
111− = copy(vm, heap_item->info.str_offset);
110+ heap_item->info.str_offset = copy(vm, heap_item->info.str_offset);
112 break;
111 break;
113 default: // Nothing to copy
112 default: // Nothing to copy
114 break;
113 break;
rts/idris_rts.c+21−21
@@ -222,9 +222,8 @@ void* allocate(size_t size, int outerlock) {
222 VM* vm = global_vm;
222 VM* vm = global_vm;
223#endif
223#endif
224
224
225− if ((size & 7)!=0) {
225+ size += 7;
226− size = 8 + ((size >> 3) << 3);
226+ size &= ~7;
227− }
228
227
229 size_t chunk_size = size + sizeof(size_t);
228 size_t chunk_size = size + sizeof(size_t);
230
229
@@ -260,10 +259,14 @@ void* allocate(size_t size, int outerlock) {
260
259
261}
260}
262
261
262+static size_t szMax(ssize_t a, ssize_t b) {
263+ return a > b? a : b;
264+}
265+
263static Closure * allocStr(size_t len, int outer) {
266static Closure * allocStr(size_t len, int outer) {
267+ size_t sz = szMax(len + 1 - 8, 0);
264− Closure * cl = allocate(sizeof(*cl) + len + 1, outer);
268+ Closure * cl = allocate(sizeof(*cl) + sz, outer);
265 SETTY(cl, CT_STRING);
269 SETTY(cl, CT_STRING);
266− cl->info.str = cl->data;
267 cl->sz = len;
270 cl->sz = len;
268 return cl;
271 return cl;
269}
272}
@@ -290,16 +293,13 @@ VAL MKFLOAT(VM* vm, double val) {
290
293
291VAL MKSTRlen(VM* vm, const char * str, size_t len) {
294VAL MKSTRlen(VM* vm, const char * str, size_t len) {
292 Closure* cl = allocStr(len, 0);
295 Closure* cl = allocStr(len, 0);
293− if (str) {
294− memcpy(cl->info.str, str, len);
296+ memcpy(cl->info.str, str, len);
295− } else {
296− cl->info.str = NULL;
297+ cl->flag = str == NULL;
297− }
298 return cl;
298 return cl;
299}
299}
300
300
301VAL MKSTR(VM* vm, const char* str) {
301VAL MKSTR(VM* vm, const char* str) {
302− return MKSTRlen(vm, str, str? strlen(str) : ~0);
302+ return MKSTRlen(vm, str, str? strlen(str) : 0);
303}
303}
304
304
305char* GETSTROFF(VAL stroff) {
305char* GETSTROFF(VAL stroff) {
@@ -339,7 +339,7 @@ VAL MKPTR(VM* vm, void* ptr) {
339VAL MKMPTR(VM* vm, void* ptr, size_t size) {
339VAL MKMPTR(VM* vm, void* ptr, size_t size) {
340 Closure* cl = allocate(sizeof(Closure) + size, 0);
340 Closure* cl = allocate(sizeof(Closure) + size, 0);
341 SETTY(cl, CT_MANAGEDPTR);
341 SETTY(cl, CT_MANAGEDPTR);
342− memcpy(cl->info.managed_ptr, ptr, size);
342+ memcpy(cl->info.mptr, ptr, size);
343 cl->sz = size;
343 cl->sz = size;
344 return cl;
344 return cl;
345}
345}
@@ -351,7 +351,7 @@ VAL MKFLOATc(VM* vm, double val) {
351 return cl;
351 return cl;
352}
352}
353
353
354−VAL MKSTRclen(VM* vm, char* str, int len) {
354+VAL MKSTRclen(VM* vm, char* str, size_t len) {
355 Closure* cl = allocStr(len, 1);
355 Closure* cl = allocStr(len, 1);
356 memcpy(cl->info.str, str, len);
356 memcpy(cl->info.str, str, len);
357 return cl;
357 return cl;
@@ -371,7 +371,7 @@ VAL MKPTRc(VM* vm, void* ptr) {
371VAL MKMPTRc(VM* vm, void* ptr, size_t size) {
371VAL MKMPTRc(VM* vm, void* ptr, size_t size) {
372 Closure* cl = allocate(sizeof(Closure) + size, 1);
372 Closure* cl = allocate(sizeof(Closure) + size, 1);
373 SETTY(cl, CT_MANAGEDPTR);
373 SETTY(cl, CT_MANAGEDPTR);
374− memcpy(cl->info.managed_ptr, ptr, size);
374+ memcpy(cl->info.mptr, ptr, size);
375 cl->sz = size;
375 cl->sz = size;
376 return cl;
376 return cl;
377}
377}
@@ -567,8 +567,8 @@ VAL idris_castStrFloat(VM* vm, VAL i) {
567VAL idris_concat(VM* vm, VAL l, VAL r) {
567VAL idris_concat(VM* vm, VAL l, VAL r) {
568 char *rs = GETSTR(r);
568 char *rs = GETSTR(r);
569 char *ls = GETSTR(l);
569 char *ls = GETSTR(l);
570− int llen = GETSTRLEN(l);
570+ size_t llen = GETSTRLEN(l);
571− int rlen = GETSTRLEN(r);
571+ size_t rlen = GETSTRLEN(r);
572
572
573 Closure* cl = allocStr(llen + rlen, 0);
573 Closure* cl = allocStr(llen + rlen, 0);
574 memcpy(cl->info.str, ls, llen);
574 memcpy(cl->info.str, ls, llen);
@@ -677,7 +677,7 @@ VAL idris_strTail(VM* vm, VAL str) {
677VAL idris_strCons(VM* vm, VAL x, VAL xs) {
677VAL idris_strCons(VM* vm, VAL x, VAL xs) {
678 char *xstr = GETSTR(xs);
678 char *xstr = GETSTR(xs);
679 int xval = GETINT(x);
679 int xval = GETINT(x);
680− int xlen = GETSTRLEN(xs);
680+ size_t xlen = GETSTRLEN(xs);
681
681
682 if (xval < 0x80) { // ASCII char
682 if (xval < 0x80) { // ASCII char
683 Closure* cl = allocStr(xlen + 1, 0);
683 Closure* cl = allocStr(xlen + 1, 0);
@@ -702,8 +702,8 @@ VAL idris_strIndex(VM* vm, VAL str, VAL i) {
702}
702}
703
703
704VAL idris_substr(VM* vm, VAL offset, VAL length, VAL str) {
704VAL idris_substr(VM* vm, VAL offset, VAL length, VAL str) {
705− int offset_val = GETINT(offset);
705+ size_t offset_val = GETINT(offset);
706− int length_val = GETINT(length);
706+ size_t length_val = GETINT(length);
707 char* str_val = GETSTR(str);
707 char* str_val = GETSTR(str);
708
708
709 // If the substring is a suffix, use idris_strShift to avoid reallocating
709 // If the substring is a suffix, use idris_strShift to avoid reallocating
@@ -723,7 +723,7 @@ VAL idris_substr(VM* vm, VAL offset, VAL length, VAL str) {
723
723
724VAL idris_strRev(VM* vm, VAL str) {
724VAL idris_strRev(VM* vm, VAL str) {
725 char *xstr = GETSTR(str);
725 char *xstr = GETSTR(str);
726− int xlen = GETSTRLEN(str);
726+ size_t xlen = GETSTRLEN(str);
727
727
728 Closure* cl = allocStr(xlen, 0);
728 Closure* cl = allocStr(xlen, 0);
729 idris_utf8_rev(xstr, cl->info.str);
729 idris_utf8_rev(xstr, cl->info.str);
@@ -893,7 +893,7 @@ VAL doCopyTo(VM* vm, VAL x) {
893 cl = MKPTRc(vm, x->info.ptr);
893 cl = MKPTRc(vm, x->info.ptr);
894 break;
894 break;
895 case CT_MANAGEDPTR:
895 case CT_MANAGEDPTR:
896− cl = MKMPTRc(vm, x->info.managed_ptr, x->sz);
896+ cl = MKMPTRc(vm, x->info.mptr, x->sz);
897 break;
897 break;
898 case CT_CDATA:
898 case CT_CDATA:
899 cl = MKCDATAc(vm, x->info.c_heap_item);
899 cl = MKCDATAc(vm, x->info.c_heap_item);
rts/idris_rts.h+13−8
@@ -34,7 +34,9 @@ typedef struct Closure *VAL;
34
34
35typedef struct Closure {
35typedef struct Closure {
36 uint64_t ty:8;
36 uint64_t ty:8;
37+// True for null strings. Might be useful at some point for other types.
38+ uint64_t flag:1;
37− uint64_t sz:56;
39+ uint64_t sz:55;
38 union {
40 union {
39// A constructor, consisting of a tag (encoded in the sz field),
41// A constructor, consisting of a tag (encoded in the sz field),
40// an arity (encoded in 8 bits in the sz field), and arguments
42// an arity (encoded in 8 bits in the sz field), and arguments
@@ -47,15 +49,14 @@ typedef struct Closure {
47 double f;
49 double f;
48 VAL str_offset;
50 VAL str_offset;
49 void * ptr;
51 void * ptr;
50− char * str;
52+ char str[0];
51 uint8_t bits8;
53 uint8_t bits8;
52 uint16_t bits16;
54 uint16_t bits16;
53 uint32_t bits32;
55 uint32_t bits32;
54 uint64_t bits64;
56 uint64_t bits64;
55− char managed_ptr[0]; // A foreign pointer, managed by the idris GC
57+ char mptr[0]; // A foreign pointer, managed by the idris GC
56 CHeapItem* c_heap_item;
58 CHeapItem* c_heap_item;
57 } info;
59 } info;
58− char data[0];
59} Closure;
60} Closure;
60
61
61struct VM;
62struct VM;
@@ -165,10 +166,14 @@ typedef void(*func)(VM*, VAL*);
165#define REG1 (vm->reg1)
166#define REG1 (vm->reg1)
166
167
167// Retrieving values
168// Retrieving values
168−#define GETSTR(x) (ISSTR(x) ? (((VAL)(x))->info.str) : GETSTROFF(x))
169+static inline char * getstr(VAL x) {
170+ return x->flag? NULL : x->info.str;
171+}
172+
173+#define GETSTR(x) (ISSTR(x) ? getstr((VAL)(x)) : GETSTROFF(x))
169−#define GETSTRLEN(x) (ISSTR(x) ? (((VAL)(x))->sz) : GETSTROFFLEN(x))
174+#define GETSTRLEN(x) (ISSTR(x) ? ((VAL)(x))->sz : GETSTROFFLEN(x))
170#define GETPTR(x) (((VAL)(x))->info.ptr)
175#define GETPTR(x) (((VAL)(x))->info.ptr)
171−#define GETMPTR(x) (((VAL)(x))->info.managed_ptr)
176+#define GETMPTR(x) (((VAL)(x))->info.mptr)
172#define GETFLOAT(x) (((VAL)(x))->info.f)
177#define GETFLOAT(x) (((VAL)(x))->info.f)
173#define GETCDATA(x) (((VAL)(x))->info.c_heap_item)
178#define GETCDATA(x) (((VAL)(x))->info.c_heap_item)
174
179
@@ -245,7 +250,7 @@ VAL MKCDATA(VM* vm, CHeapItem * item);
245VAL MKFLOATc(VM* vm, double val);
250VAL MKFLOATc(VM* vm, double val);
246VAL MKSTROFFc(VM* vm, VAL off);
251VAL MKSTROFFc(VM* vm, VAL off);
247VAL MKSTRc(VM* vm, char* str);
252VAL MKSTRc(VM* vm, char* str);
248−VAL MKSTRclen(VM* vm, char* str, int len);
253+VAL MKSTRclen(VM* vm, char* str, size_t len);
249VAL MKPTRc(VM* vm, void* ptr);
254VAL MKPTRc(VM* vm, void* ptr);
250VAL MKMPTRc(VM* vm, void* ptr, size_t size);
255VAL MKMPTRc(VM* vm, void* ptr, size_t size);
251VAL MKCDATAc(VM* vm, CHeapItem * item);
256VAL MKCDATAc(VM* vm, CHeapItem * item);