Store primitive GC arrays as raw byte buffers - #9051
Conversation
|
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:
If anyone thinks we should just land my other PR or has other thoughts on how to do this let me know. |
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.
131d1a1 to
dd3fbea
Compare
| struct GCData { | ||
| // The element or field values. | ||
| Literals values; | ||
| Type type; |
There was a problem hiding this comment.
Since the Literal pointing to this GCData already has the type, can we avoid storing it again here?
| return !gcData->getLiterals().empty() && | ||
| gcData->getLiterals()[0].type == Type::i32; |
There was a problem hiding this comment.
Does an externref literal ever have an empty literals array?
| for (Index i = 0; i < num; i++) { | ||
| VISIT(value, curr->values[i]) | ||
| data[i] = truncateForPacking(value.getSingleValue(), field); | ||
| GCData::writeField(&data[i * elemBytes], field, value.getSingleValue()); |
There was a problem hiding this comment.
Would it make sense to use data->setElement here and above?
| uint64_t val = 0; | ||
| for (unsigned b = 0; b < curr->bytes; ++b) { | ||
| val |= static_cast<uint64_t>(data->values[i + b].geti32()) << (b * 8); | ||
| val |= static_cast<uint64_t>(p[b]) << (b * 8); |
There was a problem hiding this comment.
Do we need this to handle v128 loads? Would it make sense to move the actual load into the switch so we can load the entire value at once?
| if (srcVal + lengthVal > srcData->getNumElements()) { | ||
| trap("oob"); | ||
| } | ||
| if (destData->isRawBytes() && srcData->isRawBytes()) { |
There was a problem hiding this comment.
Is this an optimization, or would the getElement/setElement path below not do the right thing?
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.