pure-c/purec

Consider copying boxed integers and numbers

felixSchl opened this issue · 3 comments

Heap allocating boxes for integers, doubles, and chars seems very redundant when it should be cheaper to just copy around the box itself. This needs to be properly investigated.

I just found myself writing this FFI code:

PURS_FFI_FUNC_4(Control_Monad_ST_Internal_for, _lo, _hi, f, _, {
	int lo = purs_any_get_int(_lo);
	int hi = purs_any_get_int(_hi);
	for (int i = 0; i < hi; i++) {
		purs_any_app(purs_any_app(f, purs_any_int_new(i) /* ouch! */), NULL)
	}
	return NULL;
});

Actually, it should be possible to simply copy the purs_any_t everywhere and only take pointers to it for internal functions if needed. We can probably use a smaller type for the tag, making the cost of copying this thing around negligible (tag + union)?

I'd love feedback on this. I just set up the inlineCommonValues optimization pass and added as a first example inlining integer negation, but this optimization looks far from optimal:

https://github.com/pure-c/pure-c/blob/187fb7f54cbb890cfd276f72ab04186c067b92a9/src/Language/PureScript/CodeGen/C/Optimizer/Inliner.purs#L92-L104

https://github.com/pure-c/pure-c/blob/187fb7f54cbb890cfd276f72ab04186c067b92a9/runtime/purescript.h#L256

Essentially we have to dereference a pointer, allocate new heap memory, initialize it, and copy the now negated value over. A sizeof (purs_any_t) on my machine yields 24, whereas a pointer to one is only 8. I think we should stop heap allocating the boxes and just copy the structs around. It will also take pressure off the gc. At this point, however, it would have a large knock on effect into the existing libraries, so we should develop this on a branch and attempt to get it merged after we see #12 passing with the current approach, I'd say.

Closing this as not (realistically) actionable