mirror of
https://github.com/golang/go
synced 2024-11-13 12:30:21 -07:00
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 <mknyszek@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
6a49f81edc
commit
4510586f93
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user