commit f77375ba41acc4f5ea4ec581b1060a6dac5d888b
parent f49212e6d50613b3ce7f7aedac5c364a33d542ae
Author: Andy Wingo <wingo@igalia.com>
Date: Mon, 8 Dec 2025 16:02:52 +0000
Bug 1977854 - Add PageSize to array buffers. r=rhunt,bvisness
Also add an assert to bounds-check elimination for the time being.
Differential Revision: https://phabricator.services.mozilla.com/D257726
Diffstat:
5 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp
@@ -818,7 +818,7 @@ bool ArrayBufferObject::resizeImpl(JSContext* cx, const CallArgs& args) {
}
Pages newPages =
- Pages::fromByteLengthExact(newByteLength, wasm::PageSize::Standard);
+ Pages::fromByteLengthExact(newByteLength, obj->wasmPageSize());
MOZ_RELEASE_ASSERT(WasmArrayBufferSourceMaxPages(obj).isSome());
Rooted<ArrayBufferObject*> res(
cx,
@@ -1979,12 +1979,20 @@ AddressType ArrayBufferObject::wasmAddressType() const {
return wasm::AddressType::I32;
}
+wasm::PageSize ArrayBufferObject::wasmPageSize() const {
+ if (isWasm()) {
+ return contents().wasmBuffer()->pageSize();
+ }
+ MOZ_ASSERT(isPreparedForAsmJS());
+ return wasm::PageSize::Standard;
+}
+
Pages ArrayBufferObject::wasmPages() const {
if (isWasm()) {
return contents().wasmBuffer()->pages();
}
MOZ_ASSERT(isPreparedForAsmJS());
- return Pages::fromByteLengthExact(byteLength(), wasm::PageSize::Standard);
+ return Pages::fromByteLengthExact(byteLength(), wasmPageSize());
}
Pages ArrayBufferObject::wasmClampedMaxPages() const {
@@ -1992,7 +2000,7 @@ Pages ArrayBufferObject::wasmClampedMaxPages() const {
return contents().wasmBuffer()->clampedMaxPages();
}
MOZ_ASSERT(isPreparedForAsmJS());
- return Pages::fromByteLengthExact(byteLength(), wasm::PageSize::Standard);
+ return Pages::fromByteLengthExact(byteLength(), wasmPageSize());
}
Maybe<Pages> ArrayBufferObject::wasmSourceMaxPages() const {
@@ -2000,8 +2008,7 @@ Maybe<Pages> ArrayBufferObject::wasmSourceMaxPages() const {
return contents().wasmBuffer()->sourceMaxPages();
}
MOZ_ASSERT(isPreparedForAsmJS());
- return Some<Pages>(
- Pages::fromByteLengthExact(byteLength(), wasm::PageSize::Standard));
+ return Some<Pages>(Pages::fromByteLengthExact(byteLength(), wasmPageSize()));
}
size_t js::WasmArrayBufferMappedSize(const ArrayBufferObjectMaybeShared* buf) {
@@ -2018,6 +2025,13 @@ AddressType js::WasmArrayBufferAddressType(
}
return buf->as<SharedArrayBufferObject>().wasmAddressType();
}
+wasm::PageSize js::WasmArrayBufferPageSize(
+ const ArrayBufferObjectMaybeShared* buf) {
+ if (buf->is<ArrayBufferObject>()) {
+ return buf->as<ArrayBufferObject>().wasmPageSize();
+ }
+ return buf->as<SharedArrayBufferObject>().wasmPageSize();
+}
Pages js::WasmArrayBufferPages(const ArrayBufferObjectMaybeShared* buf) {
if (buf->is<ArrayBufferObject>()) {
return buf->as<ArrayBufferObject>().wasmPages();
@@ -2165,10 +2179,9 @@ ArrayBufferObject* ArrayBufferObject::wasmMovingGrowToPages(
Pages clampedMaxPages =
wasm::ClampedMaxPages(t, newPages, Nothing(), /* hugeMemory */ false);
- wasm::PageSize pageSize = wasm::PageSize::Standard;
WasmArrayRawBuffer* newRawBuf = WasmArrayRawBuffer::AllocateWasm(
- oldBuf->wasmAddressType(), pageSize, newPages, clampedMaxPages, Nothing(),
- Nothing());
+ oldBuf->wasmAddressType(), oldBuf->wasmPageSize(), newPages,
+ clampedMaxPages, Nothing(), Nothing());
if (!newRawBuf) {
return nullptr;
}
diff --git a/js/src/vm/ArrayBufferObject.h b/js/src/vm/ArrayBufferObject.h
@@ -135,6 +135,7 @@ class ArrayBufferObjectMaybeShared;
wasm::AddressType WasmArrayBufferAddressType(
const ArrayBufferObjectMaybeShared* buf);
+wasm::PageSize WasmArrayBufferPageSize(const ArrayBufferObjectMaybeShared* buf);
wasm::Pages WasmArrayBufferPages(const ArrayBufferObjectMaybeShared* buf);
wasm::Pages WasmArrayBufferClampedMaxPages(
const ArrayBufferObjectMaybeShared* buf);
@@ -159,6 +160,7 @@ class ArrayBufferObjectMaybeShared : public NativeObject {
wasm::AddressType wasmAddressType() const {
return WasmArrayBufferAddressType(this);
}
+ wasm::PageSize wasmPageSize() const { return WasmArrayBufferPageSize(this); }
wasm::Pages wasmPages() const { return WasmArrayBufferPages(this); }
wasm::Pages wasmClampedMaxPages() const {
return WasmArrayBufferClampedMaxPages(this);
@@ -634,6 +636,7 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared {
size_t wasmMappedSize() const;
wasm::AddressType wasmAddressType() const;
+ wasm::PageSize wasmPageSize() const;
wasm::Pages wasmPages() const;
wasm::Pages wasmClampedMaxPages() const;
mozilla::Maybe<wasm::Pages> wasmSourceMaxPages() const;
@@ -1061,7 +1064,7 @@ class WasmArrayRawBuffer {
size_t byteLength() const { return length_; }
wasm::Pages pages() const {
- return wasm::Pages::fromByteLengthExact(length_, wasm::PageSize::Standard);
+ return wasm::Pages::fromByteLengthExact(length_, pageSize());
}
/*
diff --git a/js/src/vm/SharedArrayObject.cpp b/js/src/vm/SharedArrayObject.cpp
@@ -133,7 +133,7 @@ WasmSharedArrayRawBuffer* WasmSharedArrayRawBuffer::AllocateWasm(
uint8_t* buffer = reinterpret_cast<uint8_t*>(p) + gc::SystemPageSize();
uint8_t* base = buffer - sizeof(WasmSharedArrayRawBuffer);
return new (base) WasmSharedArrayRawBuffer(
- buffer, length, addressType, clampedMaxPages,
+ buffer, length, addressType, pageSize, clampedMaxPages,
sourceMaxPages.valueOr(Pages::fromPageCount(0, pageSize)),
computedMappedSize);
}
@@ -432,7 +432,7 @@ bool SharedArrayBufferObject::growImpl(JSContext* cx, const CallArgs& args) {
}
Pages newPages =
- Pages::fromByteLengthExact(newByteLength, wasm::PageSize::Standard);
+ Pages::fromByteLengthExact(newByteLength, buffer->wasmPageSize());
return buffer->rawWasmBufferObject()->wasmGrowToPagesInPlace(
*lock, buffer->wasmAddressType(), newPages);
}
diff --git a/js/src/vm/SharedArrayObject.h b/js/src/vm/SharedArrayObject.h
@@ -127,6 +127,8 @@ class WasmSharedArrayRawBuffer : public SharedArrayRawBuffer {
Mutex growLock_ MOZ_UNANNOTATED;
// The address type of this buffer.
wasm::AddressType addressType_;
+ // The size of each wasm page in this buffer.
+ wasm::PageSize pageSize_;
// The maximum size of this buffer in wasm pages.
wasm::Pages clampedMaxPages_;
wasm::Pages sourceMaxPages_;
@@ -141,11 +143,12 @@ class WasmSharedArrayRawBuffer : public SharedArrayRawBuffer {
protected:
WasmSharedArrayRawBuffer(uint8_t* buffer, size_t length,
wasm::AddressType addressType,
- wasm::Pages clampedMaxPages,
+ wasm::PageSize pageSize, wasm::Pages clampedMaxPages,
wasm::Pages sourceMaxPages, size_t mappedSize)
: SharedArrayRawBuffer(WasmBuffer{}, buffer, length),
growLock_(mutexid::SharedArrayGrow),
addressType_(addressType),
+ pageSize_(pageSize),
clampedMaxPages_(clampedMaxPages),
sourceMaxPages_(sourceMaxPages),
mappedSize_(mappedSize) {}
@@ -183,9 +186,10 @@ class WasmSharedArrayRawBuffer : public SharedArrayRawBuffer {
}
wasm::AddressType wasmAddressType() const { return addressType_; }
+ wasm::PageSize wasmPageSize() const { return pageSize_; }
wasm::Pages volatileWasmPages() const {
- return wasm::Pages::fromByteLengthExact(length_, wasm::PageSize::Standard);
+ return wasm::Pages::fromByteLengthExact(length_, wasmPageSize());
}
wasm::Pages wasmClampedMaxPages() const { return clampedMaxPages_; }
@@ -371,6 +375,10 @@ class SharedArrayBufferObject : public ArrayBufferObjectMaybeShared {
return rawWasmBufferObject()->wasmAddressType();
}
+ wasm::PageSize wasmPageSize() const {
+ return rawWasmBufferObject()->wasmPageSize();
+ }
+
bool isWasm() const { return rawBufferObject()->isWasm(); }
bool isGrowable() const { return is<GrowableSharedArrayBufferObject>(); }
diff --git a/js/src/wasm/WasmBCMemory.cpp b/js/src/wasm/WasmBCMemory.cpp
@@ -371,6 +371,9 @@ template <typename RegAddressType>
void BaseCompiler::prepareMemoryAccess(MemoryAccessDesc* access,
AccessCheck* check, RegPtr instance,
RegAddressType ptr) {
+ MOZ_ASSERT(codeMeta_.memories[access->memoryIndex()].pageSize() ==
+ PageSize::Standard);
+
uint64_t offsetGuardLimit = GetMaxOffsetGuardLimit(
codeMeta_.hugeMemoryEnabled(access->memoryIndex()));