Bug 1442544 - wasm: Drop offset guard reservation from 2GiB to 32MiB. r=jseward
authorRyan Hunt <rhunt@eqrion.net>
Thu, 16 Jun 2022 12:17:40 +0000
changeset 621128 b8931400a46227f747fb0b392d9698786fa6a8b4
parent 621127 30e72f02feba35758bbd83d477c72ee3b289a9c4
child 621129 7721733f56552638ad416e9dd2795bd4777e6a26
push id39861
push usernfay@mozilla.com
push dateFri, 17 Jun 2022 09:39:07 +0000
treeherdermozilla-central@213305a52f15 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjseward
bugs1442544
milestone103.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1442544 - wasm: Drop offset guard reservation from 2GiB to 32MiB. r=jseward We can use large v-mem reservations to omit bounds checks for 32-bit wasm code. This requires at least 4GiB to catch any possibly dynamic index given to a wasm memory access instruction. Memory accesses also can contain a static 'offset' immediate which is to be added to the dynamic index to get the effective address. To handle those, we reserve 'offset' guard pages after the 4GiB main region. Any offset that is larger than the offset guard region forces the access to have a bounds check. Our current reservation is 2GiB, which is unreasonably large. After profiling our internal wasm-corpus, the largest offset found was ~20MiB with most being <1MiB. 32MiB should therefore be more than enough and reduce our vmem reservations by 33%. Differential Revision: https://phabricator.services.mozilla.com/D149168
js/src/wasm/WasmMemory.h
--- a/js/src/wasm/WasmMemory.h
+++ b/js/src/wasm/WasmMemory.h
@@ -164,25 +164,38 @@ extern uint64_t RoundUpToNextValidBounds
 
 // Return the next higher valid immediate for arm.
 extern uint64_t RoundUpToNextValidARMImmediate(uint64_t i);
 
 #ifdef WASM_SUPPORTS_HUGE_MEMORY
 // On WASM_SUPPORTS_HUGE_MEMORY platforms, every asm.js or WebAssembly 32-bit
 // memory unconditionally allocates a huge region of virtual memory of size
 // wasm::HugeMappedSize. This allows all memory resizing to work without
-// reallocation and provides enough guard space for all offsets to be folded
+// reallocation and provides enough guard space for most offsets to be folded
 // into memory accesses.  See "Linear memory addresses and bounds checking" in
 // wasm/WasmMemory.cpp for more information.
 
+// Reserve 4GiB to support any i32 index.
 static const uint64_t HugeIndexRange = uint64_t(UINT32_MAX) + 1;
-static const uint64_t HugeOffsetGuardLimit = uint64_t(INT32_MAX) + 1;
+// Reserve 32MiB to support most offset immediates. Any immediate that is over
+// this will require a bounds check to be emitted. 32MiB was chosen to
+// generously cover the max offset immediate, 20MiB, found in a corpus of wasm
+// modules.
+static const uint64_t HugeOffsetGuardLimit = 1 << 25;
+// Reserve a wasm page (64KiB) to support slop on unaligned accesses.
 static const uint64_t HugeUnalignedGuardPage = PageSize;
+
+// Compute the total memory reservation.
 static const uint64_t HugeMappedSize =
     HugeIndexRange + HugeOffsetGuardLimit + HugeUnalignedGuardPage;
+
+// Try to keep the memory reservation aligned to the wasm page size. This
+// ensures that it's aligned to the system page size.
+static_assert(HugeMappedSize % PageSize == 0);
+
 #endif
 
 // The size of the guard page for non huge-memories.
 static const size_t GuardSize = PageSize;
 
 }  // namespace wasm
 }  // namespace js