fitzgen requested wasmtime-core-reviewers for a review on PR #12985.
fitzgen opened PR #12985 from fitzgen:const-eval-once to bytecodealliance:main:
Not each time they are referenced by e.g. an
array.new_eleminstruction.<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->
fitzgen requested cfallin for a review on PR #12985.
fitzgen submitted PR review.
fitzgen created PR review comment:
Ignore this, I just need to remove it. Forgot that
ValRaw's raw GC refs are raw GC refs.
cfallin submitted PR review:
LGTM!
cfallin created PR review comment:
would this make sense as a helper
ty.needs_gc_rooting()?
fitzgen submitted PR review.
fitzgen created PR review comment:
That's essentially what
is_vmgcref_type_and_not_i31is, but this allows us to avoid the type traversal at runtime, having done it at Wasm compile time already and saved the result inneeds_gc_rooting. I just didn't want to saveboolbecause it makes use-sites hard to understand what is happening.
fitzgen updated PR #12985.
fitzgen has enabled auto merge for PR #12985.
cfallin submitted PR review.
cfallin created PR review comment:
Sure, I guess I was thinking it'd be nice to package up the link from "is VMGCRef and not an i31" to "needs GC rooting" since you have the enum naming that concept (or maybe a ctor on
NeedsGcRootingotherwise that takes a ty) but no big deal either way.
fitzgen updated PR #12985.
fitzgen added PR #12985 Only const-eval passive element segments once to the merge queue.
fitzgen merged PR #12985.
fitzgen removed PR #12985 Only const-eval passive element segments once from the merge queue.
alexcrichton submitted PR review.
alexcrichton created PR review comment:
Or, put another way, should the tracing of instance-owned items move into here now? If not, could this be renamed to make it clear it's not a general purpose tracing function?
alexcrichton created PR review comment:
Could this be a
TryPrimaryMap<PassiveIndex, Option<...>>?
alexcrichton created PR review comment:
Could this be a method on
*const ValRawor something like that? It seems a bit sketchy to just cast away theValRaww.r.t endianness and such, as opposed to having a specific conversion which does something like&raw mut ...or similar.
alexcrichton created PR review comment:
Can this have a
passive_elements_muthelper like other field accessors in this file?
alexcrichton created PR review comment:
Perhaps a naive question: how come this isn't tracing tables or globals?
alexcrichton created PR review comment:
Although, actually, this seems pretty suspect. Here this is not
Pin<&mut ...>but below there's an accessor forPin<&mut ...>. Below thePinisn't actually doing anything I think because the internal type doesn't require pinning, and additionally I don't think that the type needs to be pinned? I'm a bit confused now...
fitzgen submitted PR review.
fitzgen created PR review comment:
Even better would be rebasing and landing #12621 and then using
TrySecondaryMaphere. Doesn't really seem better to me to replace one poor-man'sTrySecondaryMapwith a different poor-man'sTrySecondaryMap. Do you have objections to that?
alexcrichton submitted PR review.
alexcrichton created PR review comment:
Well #12621 is caught up, in my opinion at least, about the usage of secondary maps in the type registry where the use case isn't clear. Here, however, the usefulness is clear, but I don't think the map-like behavior of
SecondaryMapis useful here. Here for example it seems like this is created/mutated/accessed exactly like aPrimaryMapwhere there's always an entry-per-key.
fitzgen submitted PR review.
fitzgen created PR review comment:
Well #12621 is caught up, in my opinion at least, about the usage of secondary maps in the type registry where the use case isn't clear.
There is no reason that merging #12621 means we can't continue to evolve the
TypeRegistryrepresentation in #12662 IMO: they don't have to be bundled together as one all-or-nothing thing.Here for example it seems like this is created/mutated/accessed exactly like a
PrimaryMapwhere there's always an entry-per-key.I think this is a misunderstanding of
SecondaryMap: primary vs secondary isn't really about density per se (you can always doPrimaryMap<K, Option<V>>) but about defining an index space versus reusing an existing index space.In this example, the index space is defined by
wasmtime_environ::Module::passive_elements: PrimaryMap<PassiveElementIndex, _>, and invm::Instance::passive_elementswe are creating a side table to associate new data with that existing, already-defined index space. We aren't defining a new index space.By using
PrimaryMaphere again, we would be defining another index space but with the invariant that it actually must map 1:1 with the first index space (and in practice that invariant requires that we must insert into the newPrimaryMapin the exact same order as the firstPrimaryMap, for example). Although that invariant is relatively easy to maintain in this case, it is additional complexity and it is fairly subtle if you aren't familiar with all the moving parts already. On the other hand,SecondaryMapcompletely avoids that invariant, doesn't require inserting in order, and removes the complexity/subtlety.
fitzgen submitted PR review.
fitzgen created PR review comment:
If your reservations about #12621 are primarily about how we aren't "just" wrapping an inner type any more but implementing it "from scratch" on top of
Vec(which should probably beTryVecactually) then we could experiment a little bit and see if implementing it on top ofTryPrimaryMapinstead of[Try]Veccuts down on lines of code, something like this:pub struct TrySecondaryMap<K, V> where K: EntityRef, { inner: TryPrimaryMap<K, V>, default_value: V, phantom: PhantomData<fn(K) -> V>, } impl<K, V> Index<K> for SecondaryMap<K, V> where K: EntityRef, { type Output = V; fn index(&self, k: K) -> &V { self.get(k).unwrap_or(&self.default_value) } } impl<K, V> TrySecondaryMap<K, V> where K: EntityRef, { pub fn insert(&mut self, k: K, v: V) -> Result<Option<V>, OutOfMemory> where K: EntityRef, V: TryClone, { if let Some(old) = self.inner.get_mut(k) { Ok(Some(mem::replace(old, v))) } else { self.resize(k.index() + 1)?; self.elems[k] = v; Ok(None) } } // etc... }
Last updated: Apr 12 2026 at 23:10 UTC