-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Minimize lazy allocation of the GC store #11411
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
Minimize lazy allocation of the GC store #11411
Conversation
Subscribe to Label Actioncc @fitzgen
This issue or pull request has been labeled: "wasmtime:api", "wasmtime:ref-types"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
@fitzgen ok so turns out there were more places than expected that really do lazily allocate a GC store, notably dealing with i31ref and null references. Best I can think of for handling this is to either:
Do you have other ideas and/or a preference about how might be best to resolve this? |
We already bake in the assumption that Anyways, we have some of these checks in the Also, if we have a non- So I think that the impl StoreOpaque {
pub(crate) fn clone_gc_ref(&mut self, gc_ref: &GcRef) -> GcRef {
if gc_ref.is_i31() {
gc_ref.copy_i31()
} else {
self.gc_store
.as_mut()
.expect("non-null, non-i31 gc ref means we must have a gc store")
.clone_gc_ref(gc_ref)
}
} |
This commit is an effort to minimize the number of entrypoints which might lazily allocate a GC store. The is currently done through `StoreOpaque::gc_store_mut` but this method is very commonly used meaning that there are many many places to audit for lazily allocating a GC store. The reason that this needs an audit is that lazy allocation is an async operation right now that must be on a fiber and is something I'm looking to fix as part of bytecodealliance#11262. This commit performs a few refactorings to achieve this: * `gc_store_mut` is renamed to `ensure_gc_store`. This is intended to be an `async` function in the future and clearly demarcates where lazy allocation of a GC store is occurring. * `require_gc_store{,_mut}` is now added which is a pure accessor of the GC store with no lazy allocation. Most locations previously using `gc_store_mut` are updated to use this instead. Documentation is added to store methods to clearly indicate which ones are allocating and which ones should only be called in a context where allocation should already have happened.
Instead update `needs_gc_heap` with the tables that are added to a module and rely on instantiation to create the GC heap.
6cf17a3
to
527a7e1
Compare
Ok I think everything should be handled now. Mind taking another look @fitzgen? |
self.result.module.needs_gc_heap |= match table.ref_type.heap_type.top() { | ||
WasmHeapTopType::Extern | WasmHeapTopType::Exn | WasmHeapTopType::Any => { | ||
true | ||
} | ||
WasmHeapTopType::Func | WasmHeapTopType::Cont => false, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.result.module.needs_gc_heap |= match table.ref_type.heap_type.top() { | |
WasmHeapTopType::Extern | WasmHeapTopType::Exn | WasmHeapTopType::Any => { | |
true | |
} | |
WasmHeapTopType::Func | WasmHeapTopType::Cont => false, | |
}; | |
self.result.module.needs_gc_heap |= table | |
.ref_type | |
.is_vmgcref_type_and_points_to_object(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up going with is_vmgcref_type
since the method here is on wasmtime_environ
types and not wasmtime
types (therefore is_vmgcref_type_and_points_to_object
not naively available). I tried using is_vmgcref_type_not_i31
but due to the way table initialization works it requires the GC store to be present right now so I switched it to is_vmgcref_type
. Should be easy enough to fix in the future if we really want, but I figure it's not too important to be too optimal here and keeping the same code between the externref/exnref/anyref clauses is nice
} | ||
} | ||
|
||
/// This is a bit-packed version of | ||
/// | ||
/// ```ignore | ||
/// enema { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOL how did this sneak by????
This commit is an effort to minimize the number of entrypoints which might lazily allocate a GC store. The is currently done through
StoreOpaque::gc_store_mut
but this method is very commonly used meaning that there are many many places to audit for lazily allocating a GC store. The reason that this needs an audit is that lazy allocation is an async operation right now that must be on a fiber and is something I'm looking to fix as part of #11262.This commit performs a few refactorings to achieve this:
gc_store_mut
is renamed toensure_gc_store
. This is intended to be anasync
function in the future and clearly demarcates where lazy allocation of a GC store is occurring.require_gc_store{,_mut}
is now added which is a pure accessor of the GC store with no lazy allocation. Most locations previously usinggc_store_mut
are updated to use this instead.Documentation is added to store methods to clearly indicate which ones are allocating and which ones should only be called in a context where allocation should already have happened.