commit 4c2e113134d42e178451726a11c1d789ac937813
parent c5c8110cd319bfa6da73e0b02de3c34588c2514a
Author: Jon Coppeard <jcoppeard@mozilla.com>
Date: Mon, 6 Oct 2025 09:51:10 +0000
Bug 1978645 - Part 1: Use buffer allocator for wasm struct outline data r=jseward
Differential Revision: https://phabricator.services.mozilla.com/D265783
Diffstat:
2 files changed, 38 insertions(+), 60 deletions(-)
diff --git a/js/src/wasm/WasmGcObject-inl.h b/js/src/wasm/WasmGcObject-inl.h
@@ -20,6 +20,19 @@
//=========================================================================
// WasmStructObject inlineable allocation methods
+// Maximum size of trailer block to allocate directly in the nursery.
+//
+// For objects that die in the nursery, direct nursery allocation is faster and
+// is better for cache locality. For objects that survive, direct nursery
+// allocation incurs the overhead of copying the data. This parameter should be
+// chosen to balance these based on the expected allocation sizes and tenuring
+// rates in workloads we care about.
+//
+// This is set to a lower value than the default (Nursery::MaxNurseryBufferSize)
+// because we tend to get higher tenuring rates in Wasm GC benchmarks.
+static constexpr size_t MaxNurseryTrailerSize = 256;
+static_assert(MaxNurseryTrailerSize < js::gc::ChunkSize);
+
namespace js {
/* static */
@@ -94,25 +107,19 @@ MOZ_ALWAYS_INLINE WasmStructObject* WasmStructObject::createStructOOL(
MOZ_ASSERT(inlineBytes == WasmStructObject_MaxInlineBytes);
MOZ_ASSERT(outlineBytes > 0);
- // Allocate the outline data area before allocating the object so that we can
- // infallibly initialize the outline data area.
- Nursery& nursery = cx->nursery();
- PointerAndUint7 outlineData =
- nursery.mallocedBlockCache().alloc(outlineBytes);
- if (MOZ_UNLIKELY(!outlineData.pointer())) {
- ReportOutOfMemory(cx);
- return nullptr;
- }
-
// See corresponding comment in WasmArrayObject::createArray.
Rooted<WasmStructObject*> structObj(cx);
structObj = (WasmStructObject*)cx->newCell<WasmGcObject>(
typeDefData->allocKind, initialHeap, typeDefData->clasp, allocSite);
if (MOZ_UNLIKELY(!structObj)) {
ReportOutOfMemory(cx);
- if (outlineData.pointer()) {
- nursery.mallocedBlockCache().free(outlineData);
- }
+ return nullptr;
+ }
+
+ uint8_t* outlineData = AllocateCellBuffer<uint8_t>(
+ cx, structObj, outlineBytes, MaxNurseryTrailerSize);
+ if (MOZ_UNLIKELY(!outlineData)) {
+ structObj->outlineData_ = nullptr;
return nullptr;
}
@@ -121,24 +128,10 @@ MOZ_ALWAYS_INLINE WasmStructObject* WasmStructObject::createStructOOL(
structObj->superTypeVector_ = typeDefData->superTypeVector;
// Initialize the outline data fields
- structObj->outlineData_ = (uint8_t*)outlineData.pointer();
+ structObj->outlineData_ = outlineData;
if constexpr (ZeroFields) {
memset(structObj->inlineData(), 0, inlineBytes);
- memset(outlineData.pointer(), 0, outlineBytes);
- }
-
- if (MOZ_LIKELY(js::gc::IsInsideNursery(structObj))) {
- // See corresponding comment in WasmArrayObject::createArrayNonEmpty.
- if (MOZ_UNLIKELY(!nursery.registerTrailer(outlineData, outlineBytes))) {
- nursery.mallocedBlockCache().free(outlineData);
- ReportOutOfMemory(cx);
- return nullptr;
- }
- } else {
- // See corresponding comment in WasmArrayObject::createArrayNonEmpty.
- MOZ_ASSERT(structObj->isTenured());
- AddCellMemory(structObj, outlineBytes + wasm::TrailerBlockOverhead,
- MemoryUse::WasmTrailerBlock);
+ memset(outlineData, 0, outlineBytes);
}
MOZ_ASSERT(typeDefData->clasp->shouldDelayMetadataBuilder());
diff --git a/js/src/wasm/WasmGcObject.cpp b/js/src/wasm/WasmGcObject.cpp
@@ -554,29 +554,16 @@ void WasmStructObject::obj_trace(JSTracer* trc, JSObject* object) {
reinterpret_cast<AnyRef*>(structObj.inlineData() + offset);
TraceManuallyBarrieredEdge(trc, fieldPtr, "wasm-struct-field");
}
- for (uint32_t offset : structType.outlineTraceOffsets_) {
- AnyRef* fieldPtr =
- reinterpret_cast<AnyRef*>(structObj.outlineData_ + offset);
- TraceManuallyBarrieredEdge(trc, fieldPtr, "wasm-struct-field");
- }
-}
-/* static */
-void WasmStructObject::obj_finalize(JS::GCContext* gcx, JSObject* object) {
- // See corresponding comments in WasmArrayObject::obj_finalize.
- WasmStructObject& structObj = object->as<WasmStructObject>();
if (structObj.outlineData_) {
- js_free(structObj.outlineData_);
- const TypeDef& typeDef = structObj.typeDef();
- MOZ_ASSERT(typeDef.isStructType());
- uint32_t totalBytes = typeDef.structType().size_;
- uint32_t inlineBytes, outlineBytes;
- WasmStructObject::getDataByteSizes(totalBytes, &inlineBytes, &outlineBytes);
- MOZ_ASSERT(inlineBytes == WasmStructObject_MaxInlineBytes);
- MOZ_ASSERT(outlineBytes > 0);
- gcx->removeCellMemory(&structObj, outlineBytes + TrailerBlockOverhead,
- MemoryUse::WasmTrailerBlock);
- structObj.outlineData_ = nullptr;
+ TraceBufferEdge(trc, &structObj, &structObj.outlineData_,
+ "WasmStructObject outline data");
+
+ for (uint32_t offset : structType.outlineTraceOffsets_) {
+ AnyRef* fieldPtr =
+ reinterpret_cast<AnyRef*>(structObj.outlineData_ + offset);
+ TraceManuallyBarrieredEdge(trc, fieldPtr, "wasm-struct-field");
+ }
}
}
@@ -593,9 +580,8 @@ size_t WasmStructObject::obj_moved(JSObject* obj, JSObject* old) {
WasmStructObject::getDataByteSizes(totalBytes, &inlineBytes, &outlineBytes);
MOZ_ASSERT(inlineBytes == WasmStructObject_MaxInlineBytes);
MOZ_ASSERT(outlineBytes > 0);
- nursery.trackTrailerOnPromotion(structObj.outlineData_, obj, outlineBytes,
- TrailerBlockOverhead,
- MemoryUse::WasmTrailerBlock);
+ nursery.maybeMoveBufferOnPromotion(&structObj.outlineData_, obj,
+ outlineBytes);
}
return 0;
@@ -627,11 +613,11 @@ static const JSClassOps WasmStructObjectOutlineClassOps = {
nullptr, /* delProperty */
nullptr, /* enumerate */
WasmGcObject::obj_newEnumerate,
- nullptr, /* resolve */
- nullptr, /* mayResolve */
- WasmStructObject::obj_finalize, /* finalize */
- nullptr, /* call */
- nullptr, /* construct */
+ nullptr, /* resolve */
+ nullptr, /* mayResolve */
+ nullptr, /* finalize */
+ nullptr, /* call */
+ nullptr, /* construct */
WasmStructObject::obj_trace,
};
static const ClassExtension WasmStructObjectOutlineClassExt = {
@@ -639,8 +625,7 @@ static const ClassExtension WasmStructObjectOutlineClassExt = {
};
const JSClass WasmStructObject::classOutline_ = {
"WasmStructObject",
- JSClass::NON_NATIVE | JSCLASS_DELAY_METADATA_BUILDER |
- JSCLASS_BACKGROUND_FINALIZE | JSCLASS_SKIP_NURSERY_FINALIZE,
+ JSClass::NON_NATIVE | JSCLASS_DELAY_METADATA_BUILDER,
&WasmStructObjectOutlineClassOps,
JS_NULL_CLASS_SPEC,
&WasmStructObjectOutlineClassExt,