From 099cfdf933ab736ec5daa1e749b52617c00cfa0f Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Tue, 2 Sep 2025 06:04:24 +0200 Subject: [PATCH 1/7] Support WithMemoryCapacityFromMax --- internal/alloc/alloc_unix.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/internal/alloc/alloc_unix.go b/internal/alloc/alloc_unix.go index 157b5447..11107d2b 100644 --- a/internal/alloc/alloc_unix.go +++ b/internal/alloc/alloc_unix.go @@ -9,7 +9,7 @@ import ( "golang.org/x/sys/unix" ) -func NewMemory(_, max uint64) experimental.LinearMemory { +func NewMemory(cap, max uint64) experimental.LinearMemory { // Round up to the page size. rnd := uint64(unix.Getpagesize() - 1) max = (max + rnd) &^ rnd @@ -20,13 +20,19 @@ func NewMemory(_, max uint64) experimental.LinearMemory { max = math.MaxUint64 } + prot := unix.PROT_READ | unix.PROT_WRITE + if cap < max { + prot = unix.PROT_NONE + cap = 0 + } + // Reserve max bytes of address space, to ensure we won't need to move it. // A protected, private, anonymous mapping should not commit memory. - b, err := unix.Mmap(-1, 0, int(max), unix.PROT_NONE, unix.MAP_PRIVATE|unix.MAP_ANON) + b, err := unix.Mmap(-1, 0, int(max), prot, unix.MAP_PRIVATE|unix.MAP_ANON) if err != nil { panic(err) } - return &mmappedMemory{buf: b[:0]} + return &mmappedMemory{buf: b[:cap]} } // The slice covers the entire mmapped memory: From 28a9464c032ef64acd390c0f2c1ad9c70332a382 Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Tue, 2 Sep 2025 09:33:44 +0200 Subject: [PATCH 2/7] Windows. --- internal/alloc/alloc_windows.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/internal/alloc/alloc_windows.go b/internal/alloc/alloc_windows.go index 2d753e20..1698ded9 100644 --- a/internal/alloc/alloc_windows.go +++ b/internal/alloc/alloc_windows.go @@ -9,7 +9,7 @@ import ( "golang.org/x/sys/windows" ) -func NewMemory(_, max uint64) experimental.LinearMemory { +func NewMemory(cap, max uint64) experimental.LinearMemory { // Round up to the page size. rnd := uint64(windows.Getpagesize() - 1) max = (max + rnd) &^ rnd @@ -20,9 +20,15 @@ func NewMemory(_, max uint64) experimental.LinearMemory { max = math.MaxUint64 } + kind := windows.MEM_COMMIT + if cap < max { + kind = windows.MEM_RESERVE + cap = max + } + // Reserve max bytes of address space, to ensure we won't need to move it. // This does not commit memory. - r, err := windows.VirtualAlloc(0, uintptr(max), windows.MEM_RESERVE, windows.PAGE_READWRITE) + r, err := windows.VirtualAlloc(0, uintptr(max), kind, windows.PAGE_READWRITE) if err != nil { panic(err) } @@ -30,6 +36,7 @@ func NewMemory(_, max uint64) experimental.LinearMemory { mem := virtualMemory{addr: r} // SliceHeader, although deprecated, avoids a go vet warning. sh := (*reflect.SliceHeader)(unsafe.Pointer(&mem.buf)) + sh.Len = int(cap) sh.Cap = int(max) sh.Data = r return &mem From 686a91fda5f3edf29b826a1987084ce3d2a76068 Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Tue, 2 Sep 2025 10:33:17 +0200 Subject: [PATCH 3/7] Fix. --- internal/alloc/alloc_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/alloc/alloc_windows.go b/internal/alloc/alloc_windows.go index 1698ded9..e62d5ff0 100644 --- a/internal/alloc/alloc_windows.go +++ b/internal/alloc/alloc_windows.go @@ -28,7 +28,7 @@ func NewMemory(cap, max uint64) experimental.LinearMemory { // Reserve max bytes of address space, to ensure we won't need to move it. // This does not commit memory. - r, err := windows.VirtualAlloc(0, uintptr(max), kind, windows.PAGE_READWRITE) + r, err := windows.VirtualAlloc(0, uintptr(max), uint32(kind), windows.PAGE_READWRITE) if err != nil { panic(err) } From 886c80b5dcdf8924392aa1f2303654bad12e799f Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Tue, 2 Sep 2025 11:01:02 +0200 Subject: [PATCH 4/7] Fix. --- internal/alloc/alloc_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/alloc/alloc_windows.go b/internal/alloc/alloc_windows.go index e62d5ff0..3bbeb739 100644 --- a/internal/alloc/alloc_windows.go +++ b/internal/alloc/alloc_windows.go @@ -23,7 +23,7 @@ func NewMemory(cap, max uint64) experimental.LinearMemory { kind := windows.MEM_COMMIT if cap < max { kind = windows.MEM_RESERVE - cap = max + cap = 0 } // Reserve max bytes of address space, to ensure we won't need to move it. From 14c17ff0966dabe8dc9197bcaf9caa2ecd9ed966 Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Wed, 3 Sep 2025 08:35:09 +0200 Subject: [PATCH 5/7] Refactor. --- internal/alloc/alloc_unix.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/internal/alloc/alloc_unix.go b/internal/alloc/alloc_unix.go index 11107d2b..203d8471 100644 --- a/internal/alloc/alloc_unix.go +++ b/internal/alloc/alloc_unix.go @@ -12,27 +12,28 @@ import ( func NewMemory(cap, max uint64) experimental.LinearMemory { // Round up to the page size. rnd := uint64(unix.Getpagesize() - 1) - max = (max + rnd) &^ rnd + res := (max + rnd) &^ rnd - if max > math.MaxInt { - // This ensures int(max) overflows to a negative value, + if res > math.MaxInt { + // This ensures int(res) overflows to a negative value, // and unix.Mmap returns EINVAL. - max = math.MaxUint64 + res = math.MaxUint64 } + com := res prot := unix.PROT_READ | unix.PROT_WRITE - if cap < max { + if cap < max { // Commit memory only if cap=max. + com = 0 prot = unix.PROT_NONE - cap = 0 } - // Reserve max bytes of address space, to ensure we won't need to move it. + // Reserve res bytes of address space, to ensure we won't need to move it. // A protected, private, anonymous mapping should not commit memory. - b, err := unix.Mmap(-1, 0, int(max), prot, unix.MAP_PRIVATE|unix.MAP_ANON) + b, err := unix.Mmap(-1, 0, int(res), prot, unix.MAP_PRIVATE|unix.MAP_ANON) if err != nil { panic(err) } - return &mmappedMemory{buf: b[:cap]} + return &mmappedMemory{buf: b[:com]} } // The slice covers the entire mmapped memory: @@ -58,8 +59,7 @@ func (m *mmappedMemory) Reallocate(size uint64) []byte { return nil } - // Update committed memory. - m.buf = m.buf[:new] + m.buf = m.buf[:new] // Update committed memory. } // Limit returned capacity because bytes beyond // len(m.buf) have not yet been committed. From 32cfc8d8da67d10c03b0d89a3e383aebe78745c0 Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Wed, 3 Sep 2025 08:41:45 +0200 Subject: [PATCH 6/7] Refactor Windows. --- internal/alloc/alloc_windows.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/internal/alloc/alloc_windows.go b/internal/alloc/alloc_windows.go index 3bbeb739..3eab91e3 100644 --- a/internal/alloc/alloc_windows.go +++ b/internal/alloc/alloc_windows.go @@ -12,23 +12,23 @@ import ( func NewMemory(cap, max uint64) experimental.LinearMemory { // Round up to the page size. rnd := uint64(windows.Getpagesize() - 1) - max = (max + rnd) &^ rnd + res := (max + rnd) &^ rnd - if max > math.MaxInt { - // This ensures uintptr(max) overflows to a large value, + if res > math.MaxInt { + // This ensures uintptr(res) overflows to a large value, // and windows.VirtualAlloc returns an error. - max = math.MaxUint64 + res = math.MaxUint64 } + com := res kind := windows.MEM_COMMIT - if cap < max { + if cap < max { // Commit memory only if cap=max. + com = 0 kind = windows.MEM_RESERVE - cap = 0 } - // Reserve max bytes of address space, to ensure we won't need to move it. - // This does not commit memory. - r, err := windows.VirtualAlloc(0, uintptr(max), uint32(kind), windows.PAGE_READWRITE) + // Reserve res bytes of address space, to ensure we won't need to move it. + r, err := windows.VirtualAlloc(0, uintptr(res), uint32(kind), windows.PAGE_READWRITE) if err != nil { panic(err) } @@ -36,9 +36,9 @@ func NewMemory(cap, max uint64) experimental.LinearMemory { mem := virtualMemory{addr: r} // SliceHeader, although deprecated, avoids a go vet warning. sh := (*reflect.SliceHeader)(unsafe.Pointer(&mem.buf)) - sh.Len = int(cap) - sh.Cap = int(max) sh.Data = r + sh.Len = int(com) + sh.Cap = int(res) return &mem } From 4e5fbab3617267989cedf48dbbb5f93fa2c67961 Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Wed, 3 Sep 2025 09:00:07 +0200 Subject: [PATCH 7/7] Refactor. --- internal/alloc/alloc_windows.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/alloc/alloc_windows.go b/internal/alloc/alloc_windows.go index 3eab91e3..ef83f018 100644 --- a/internal/alloc/alloc_windows.go +++ b/internal/alloc/alloc_windows.go @@ -66,8 +66,7 @@ func (m *virtualMemory) Reallocate(size uint64) []byte { return nil } - // Update committed memory. - m.buf = m.buf[:new] + m.buf = m.buf[:new] // Update committed memory. } // Limit returned capacity because bytes beyond // len(m.buf) have not yet been committed.