From: Cherry Mui Date: Mon, 21 Oct 2024 17:01:56 +0000 (-0400) Subject: runtime: (re)use unused linear memory on Wasm X-Git-Tag: go1.24rc1~648 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=4510586f930b49a142f991c51d960a3afc18e667;p=gostls13.git runtime: (re)use unused linear memory on Wasm CL 476717 adopted the memory management mechanism on Plan 9 to manage Wasm's linear memory. But the Plan 9 code uses global variable bloc and blocMax to keep track of the runtime's and the OS's sense of break, whereas the Wasm sbrk function doesn't use those global variables, and directly goes to grow the linear memory instead. This causes that if there is any unused portion at the end of the linear memory, the runtime doesn't use it. This CL fixes it, adopts the same mechanism as the Plan 9 code. In particular, the runtime is not aware of any unused initial memory at startup. Therefore, (most of) the extra initial memory set by the linker are not actually used. This CL fixes this as well. For #69018. Change-Id: I2ea6a138310627eda5f19a1c76b1e1327362e5f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/621635 Reviewed-by: Michael Knyszek LUCI-TryBot-Result: Go LUCI --- diff --git a/src/runtime/mem_sbrk.go b/src/runtime/mem_sbrk.go index dc0a764a2c..1f0b9bf1d7 100644 --- a/src/runtime/mem_sbrk.go +++ b/src/runtime/mem_sbrk.go @@ -10,8 +10,28 @@ import "unsafe" const memDebug = false -var bloc uintptr -var blocMax uintptr +// Memory management on sbrk systems (including the linear memory +// on Wasm). + +// bloc is the runtime's sense of the break, which can go up or +// down. blocMax is the system's break, also the high water mark +// of bloc. The runtime uses memory up to bloc. The memory +// between bloc and blocMax is allocated by the OS but not used +// by the runtime. +// +// When the runtime needs to grow the heap address range, it +// increases bloc. When it needs to grow beyond blocMax, it calls +// the system sbrk to allocate more memory (and therefore +// increase blocMax). +// +// When the runtime frees memory at the end of the address space, +// it decreases bloc, but does not reduces the system break (as +// the OS doesn't support it). When the runtime frees memory in +// the middle of the address space, the memory goes to a free +// list. + +var bloc uintptr // The runtime's sense of break. Can go up or down. +var blocMax uintptr // The break of the OS. Only increase. var memlock mutex type memHdr struct { diff --git a/src/runtime/mem_wasm.go b/src/runtime/mem_wasm.go index d9d32705bb..76de88ac3c 100644 --- a/src/runtime/mem_wasm.go +++ b/src/runtime/mem_wasm.go @@ -7,14 +7,21 @@ package runtime import "unsafe" func sbrk(n uintptr) unsafe.Pointer { - grow := divRoundUp(n, physPageSize) - size := growMemory(int32(grow)) - if size < 0 { - return nil + bl := bloc + n = memRound(n) + if bl+n > blocMax { + grow := (bl + n - blocMax) / physPageSize + size := growMemory(int32(grow)) + if size < 0 { + return nil + } + resetMemoryDataView() + blocMax = bl + n } - resetMemoryDataView() - return unsafe.Pointer(uintptr(size) * physPageSize) + bloc += n + return unsafe.Pointer(bl) } // Implemented in src/runtime/sys_wasm.s func growMemory(pages int32) int32 +func currentMemory() int32 diff --git a/src/runtime/os_wasm.go b/src/runtime/os_wasm.go index 15bc3131f1..8046caf45e 100644 --- a/src/runtime/os_wasm.go +++ b/src/runtime/os_wasm.go @@ -13,6 +13,7 @@ func osinit() { // https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances physPageSize = 64 * 1024 initBloc() + blocMax = uintptr(currentMemory()) * physPageSize // record the initial linear memory size ncpu = 1 getg().m.procid = 2 } diff --git a/src/runtime/sys_wasm.s b/src/runtime/sys_wasm.s index 1e73adadd5..b7965ec3fa 100644 --- a/src/runtime/sys_wasm.s +++ b/src/runtime/sys_wasm.s @@ -86,6 +86,12 @@ TEXT runtime·exitThread(SB), NOSPLIT, $0-0 TEXT runtime·osyield(SB), NOSPLIT, $0-0 UNDEF +TEXT runtime·currentMemory(SB), NOSPLIT, $0 + Get SP + CurrentMemory + I32Store ret+0(FP) + RET + TEXT runtime·growMemory(SB), NOSPLIT, $0 Get SP I32Load pages+0(FP)