Skip to content

Store primitive GC arrays as raw byte buffers - #9051

Open
brendandahl wants to merge 1 commit into
WebAssembly:mainfrom
brendandahl:bytes-1-arrays
Open

Store primitive GC arrays as raw byte buffers#9051
brendandahl wants to merge 1 commit into
WebAssembly:mainfrom
brendandahl:bytes-1-arrays

Conversation

@brendandahl

Copy link
Copy Markdown
Collaborator

GCData previously represented all allocations using a vector of Literals. Storing numeric array elements this way introduces unnecessary memory overhead and prevents efficient byte-level operations.

Represent primitive numeric GC arrays using a raw byte buffer in GCData while preserving Literals storage for reference arrays and structs.

@brendandahl
brendandahl requested a review from a team as a code owner August 27, 2026 21:53
@brendandahl
brendandahl requested review from kripken and removed request for a team August 27, 2026 21:53
@brendandahl

Copy link
Copy Markdown
Collaborator Author

This PR ends up causing quite a bit of churn, but it makes implementing multibyte load/stores from numeric arrays pretty easy compared to my original PR. This PR should also use less memory for numeric arrays and be faster for most operations on them. In some follow up PRs, we could also move strings into the vectors to make them more efficient.

I also explored a few other ways of implementing this:

  1. Put all GC values in a byte array and do our own layout. This is probably the biggest change, and it seems relatively complex to handle all the alignment. Probably closer to what most runtimes do and would be the most efficient though.
  2. Subclass GCData for literal and numeric arrays. Less churn but we'll then have virtual dispatch overhead.
  3. Use two separate fields in GCData for Literals and bytes. This looks very similar to this PR, but seems a bit more error prone.

If anyone thinks we should just land my other PR or has other thoughts on how to do this let me know.

@brendandahl
brendandahl requested a review from tlively August 27, 2026 22:03
Comment thread src/wasm/literal.cpp
isNull() || isData() ||
(type.isRef() && (type.getHeapType().isMaybeShared(HeapType::ext) ||
type.getHeapType().isMaybeShared(HeapType::string) ||
type.getHeapType().isMaybeShared(HeapType::any) ||

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'm confused. Does this PR change how strings are implemented, and not just numeric arrays? If not, why is this code changing?

Comment thread src/literal.h

static void writeField(void* p, const Field& field, Literal value);
static Literal
readField(const void* p, const Field& field, bool signed_ = false);

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.

What is p in these? Perhaps add a comment?

Comment thread src/wasm/literal.cpp

uint8_t buf[16];
value.getBits(buf);
memcpy(p, buf, field.getByteSize());

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.

Perhaps assert that the byte size is less than 16 from two lines ago? Some day we may get larger types...

GCData previously represented all allocations using a vector of
Literals. Storing numeric array elements this way introduces
unnecessary memory overhead and prevents efficient byte-level
operations.

Represent primitive numeric GC arrays using a raw byte buffer in GCData
while preserving Literals storage for reference arrays and structs.
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