-
-
Notifications
You must be signed in to change notification settings - Fork 669
Generalize runtime #1503
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generalize runtime #1503
Conversation
New MM header
New GC (full object) header
|
@willemneal can we check to see if this breaks aspect? |
Also, have me a chuckle. "minor changes." This looks like a really big deal. Thanks for the work. |
Speaking of breaking changes, this would be the beginning of multiple breaking changes in a row. This one breaks anything depending on memory layout or runtime APIs already (very likely also aspect), and replacing ARC with ITCM will remove |
Regarding breaking changes. Just wondering why __alloc / __realloc changed to __new / __renew? |
These do different things now. For instance, |
I see. It's just question about naming. What about use |
We can add wrappers (or forwarding builtins) for |
Could also be a builtin module maybe: // std/malloc.ts
export { __alloc as malloc, __realloc as realloc, __free as free }; // assembly/index.ts
import { malloc, realloc, free } from "malloc"; |
I like convensions with // gc stuffs
gc.alloc, gc.realloc, gc.collect
// memory stuffs
mm.alloc, mm.realloc, mm.free, mm.reset
// other memory utils
mm.fill, mm.copy, mm.repeat, mm.compare
// intrinsics (for compatibility with wasm)
memory.fill, memory.copy, memory.init etc |
What if we'd just rename
and make these available globally, but mark them Other than that I think it's fine to hide the GC details (except |
Also good variant. In this case it will be: // gc stuffs
gc.alloc, gc.realloc
// /memory stuffs
alloc, realloc, free, reset
// intrinsics
memory.fill, memory.copy, memory.init another alternative use "heap" namespace: heap.alloc, heap.realloc, heap.free, heap.reset I think in any case better use "alloc" instead "malloc" |
I like the |
also great advantage of "heap" namespace we could put into it |
First, I really like these changes. Would it be possible to be tagged on these sorts of changes more pre-emptively? |
Looking at this more, it becomes apparent that we'll need some sort of shadow stack after all, albeit only for managed objects. A tracing GC will run incrementally with the program and needs to know what's currently on the stack so it doesn't prematurely free what the current function, for instance calling function doSomethingManaged(): void {
var S = __stacksave(8);
S[-1] = __new(123);
S[-2] = __new(234);
gc.collect(); // must not free 123 and 234
__stackrestore(S);
} So far it looks like the compiler will be able to tell statically how much stack space to reserve, and only needs to insert |
One way to model a shadow stack like this could be:
Inside loops, the same stack slot is taken by the same allocation or function return within the loop, effectively keeping everything explicitly or implicitly kept alive by the function alive while the function is. Overhead is the memory for maintaining a stack, potentially with a well-predicted check that the stack isn't overflown, stores to the stack slots, and traversing the stack in addition to other roots when marking/sweeping. Overall doesn't look so bad. A typical function using managed objects might end up with say 10 stack slots for example, ~40 bytes stack space, and a solid maximum stack size might be one page (65536 bytes, ~1638 depth). |
Alternative: Only do GC work when the Wasm execution stack is fully unwound, i.e. when returning from a directly called export. // index.ts
var _depth = 0;
var _collect_called = false;
export function someExport(): void {
++_depth;
// code of someExport
if (!--_depth) {
if (_collect_called) doFullGc();
else doSomeGc();
}
} Does not require a shadow stack, but also isn't as granularly incremental anymore. Much easier to implement however, at hardly any runtime cost. @MaxGraey Wdyt? |
It seems it will be most of time is fully collected (stop the world mode). Not sure we need incremental collector in this case at all. I think we should investigate our efforts to approximated liveness-assisted GC but it required finish our IR first |
Nothing of this is optimal, I agree, and it seems that the best we can do is to make a forward decision, ideally with Wasm GC in mind, so we are not blocked on this forever. Would everyone be OK with me making that decision and taking the blame for it, so that we can otherwise go on? |
Going to merge this patch even without tracing along #1513, combining multiple breaking changes into one version, likely 0.17. |
Okay. It looks like this will be affecting as-pect user installs. Will have to work on this soon. Thanks for the changes! |
Minor changes.
__alloc
,__realloc
and__free
now essentially beingmalloc
,realloc
andfree
in C__alloc
does not take anid
argument anymore__alloc
for GC objects is now__new
(withid
argument)__realloc
for GC objects is now__renew
__realloc
and__free
are now exposed by the full/stub runtimes__allocArray
is now__newArray
__allocBuffer
is now__newBuffer
__allocString
is now__newString
gc.auto
has been removed due to unforeseen consequences with the execution stackheap
namespace providingalloc
,realloc
,free
andreset
(stub only)