]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: (re)use unused linear memory on Wasm
authorCherry Mui <cherryyz@google.com>
Mon, 21 Oct 2024 17:01:56 +0000 (13:01 -0400)
committerCherry Mui <cherryyz@google.com>
Mon, 21 Oct 2024 21:52:53 +0000 (21:52 +0000)
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 <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/runtime/mem_sbrk.go
src/runtime/mem_wasm.go
src/runtime/os_wasm.go
src/runtime/sys_wasm.s

index dc0a764a2cac86f0c9ce9d6b46880e0ee1be3efe..1f0b9bf1d78a6f825d9afe123ead6909fdc4d75c 100644 (file)
@@ -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 {
index d9d32705bb6a068cef4d93ea5658f4c1f9955c79..76de88ac3cd4aa883548ebbd56cf563e0d2913d8 100644 (file)
@@ -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
index 15bc3131f117c9fc3f592916e7835992cc1de379..8046caf45ef133edc2c14b4d2be57089535a549f 100644 (file)
@@ -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
 }
index 1e73adadd56aa78bf25b35b14104cba3d175d8fc..b7965ec3fa4138454e6a2fd843e80abec19c065f 100644 (file)
@@ -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)