Skip to content

Add a MakeSharedObjects pass - #8953

Open
tlively wants to merge 4 commits into
WebAssembly:mainfrom
tlively:make-shared
Open

Add a MakeSharedObjects pass#8953
tlively wants to merge 4 commits into
WebAssembly:mainfrom
tlively:make-shared

Conversation

@tlively

@tlively tlively commented Jul 29, 2026

Copy link
Copy Markdown
Member

This pass makes all functions unshared and all structs and arrays shared. It avoids validation errors from storing unshared function references in shared structs and arrays by replacing all function references with i31 references holding indices into a function table. Indirect calls and casts are updated to extract their function reference from the table.

This new pass will make it easier to convert unshared Wasm GC programs to run on the shared heap for testing purposes. It will also lower shared functions emitted by toolchains to allow them to run on prototypes that do not support shared functions.

This pass makes all functions unshared and all structs and arrays shared. It avoids validation errors from storing unshared function references in shared structs and arrays by replacing all function references with i31 references holding indices into a function table. Indirect calls and casts are updated to extract their function reference from the table.

This new pass will make it easier to convert unshared Wasm GC programs to run on the shared heap for testing purposes. It will also lower shared functions emitted by toolchains to allow them to run on prototypes that do not support shared functions.
@tlively
tlively requested a review from a team as a code owner July 29, 2026 21:08
@tlively
tlively requested review from kripken and removed request for a team July 29, 2026 21:08
@tlively

tlively commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

Looks like there's a determinism bug with the type renaming when multiple types get merged. Will look into that tomorrow.

std::vector<Name> funcs;
std::unordered_map<Name, Index> funcIndices;

Type funcref = Type(HeapTypes::func, Nullable);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pass could use a toplevel comment (what the pass does) and these properties as well (how does the pass achieve its goal using the table and so forth).

Comment thread src/wasm-traversal.h
walk(segment->offset);
}
for (auto* expr : segment->data) {
for (auto*& expr : segment->data) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So replaceCurrent can replace the top-level expressions. Otherwise it would replace an on-stack copy of the expressions.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Then do we not also need this on line 176?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the argument there is already a reference to the value that we would want replaceCurrent to replace.

Comment thread src/wasm-type.h
(exact == Exact && !heapType.isBasic() ? ExactMask : 0)) {
assert(!(heapType.getID() &
(TupleMask | NullMask | (heapType.isBasic() ? 0 : ExactMask))));
assert(!heapType.isBasic() || exact == Inexact);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why relax this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The when we map old function types to i31, the general type updating code tries to update the heap type but keep exactness. There would be other ways to solve this, but this seemed simple enough.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up reverting this and checking whether the new type is basic before trying to make it exact.

Comment thread src/wasm-type.h Outdated
if (auto super = type.getDeclaredSuperType()) {
setSubType(i, map(*super));
if (auto mapped = map(*super); !mapped.isBasic()) {
setSubType(i, map(*super));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
setSubType(i, map(*super));
setSubType(i, mapped);

Or is there some reason not to?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, that's an oversight.

Comment thread src/wasm-type.h Outdated
if (auto desc = type.getDescriptorType()) {
setDescriptor(i, map(*desc));
if (auto mapped = map(*desc); !mapped.isBasic()) {
setDescriptor(i, map(*desc));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment? I assume this can happen if both of a descriptor-described pair are mapped to a basic type?

@tlively
tlively requested a review from kripken July 30, 2026 04:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants