From 169be8e5b123007a02adf3f742b2a200bd8f9e67 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 23 Aug 2021 17:27:40 +0000 Subject: [release-branch.go1.16] runtime: set iOS addr space to 40 bits with incremental pagealloc In iOS <14, the address space is strictly limited to 8 GiB, or 33 bits. As a result, the page allocator also assumes all heap memory lives in this region. This is especially necessary because the page allocator has a PROT_NONE mapping proportional to the size of the usable address space, so this keeps that mapping very small. However starting with iOS 14, this restriction is relaxed, and mmap may start returning addresses outside of the <14 range. Today this means that in iOS 14 and later, users experience an error in the page allocator when a heap arena is mapped outside of the old range. This change increases the ios/arm64 heapAddrBits to 40 while simultaneously making ios/arm64 use the 64-bit pagealloc implementation (with reservations and incremental mapping) to accommodate both iOS versions <14 and 14+. Once iOS <14 is deprecated, we can remove these exceptions and treat ios/arm64 like any other arm64 platform. This change also makes the BaseChunkIdx expression a little bit easier to read, while we're here. For #46860. Fixes #48115. Change-Id: I13865f799777739109585f14f1cc49d6d57e096b Reviewed-on: https://go-review.googlesource.com/c/go/+/344401 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui Reviewed-by: Austin Clements (cherry picked from commit af368da0b137116faba81ca249a8d964297e6e45) Reviewed-on: https://go-review.googlesource.com/c/go/+/369736 Run-TryBot: Dmitri Shuralyov --- src/runtime/export_test.go | 14 +++++++++++++- src/runtime/malloc.go | 20 +++++++++++++------- src/runtime/mgcscavenge_test.go | 5 ++++- src/runtime/mpagealloc_32bit.go | 8 +------- src/runtime/mpagealloc_64bit.go | 4 +--- src/runtime/mpagealloc_test.go | 9 +++++++-- src/runtime/mpagecache_test.go | 5 ++++- 7 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 22fef3134f..59f72ae709 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -1051,7 +1051,19 @@ func FreePageAlloc(pp *PageAlloc) { // // This should not be higher than 0x100*pallocChunkBytes to support // mips and mipsle, which only have 31-bit address spaces. -var BaseChunkIdx = ChunkIdx(chunkIndex(((0xc000*pageAlloc64Bit + 0x100*pageAlloc32Bit) * pallocChunkBytes) + arenaBaseOffset*sys.GoosAix)) +var BaseChunkIdx = func() ChunkIdx { + var prefix uintptr + if pageAlloc64Bit != 0 { + prefix = 0xc000 + } else { + prefix = 0x100 + } + baseAddr := prefix * pallocChunkBytes + if sys.GoosAix != 0 { + baseAddr += arenaBaseOffset + } + return ChunkIdx(chunkIndex(baseAddr)) +}() // PageBase returns an address given a chunk index and a page index // relative to that chunk. diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index f20ded5bf7..c57d8c617d 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -199,15 +199,21 @@ const ( // we further limit it to 31 bits. // // On ios/arm64, although 64-bit pointers are presumably - // available, pointers are truncated to 33 bits. Furthermore, - // only the top 4 GiB of the address space are actually available - // to the application, but we allow the whole 33 bits anyway for - // simplicity. - // TODO(mknyszek): Consider limiting it to 32 bits and using - // arenaBaseOffset to offset into the top 4 GiB. + // available, pointers are truncated to 33 bits in iOS <14. + // Furthermore, only the top 4 GiB of the address space are + // actually available to the application. In iOS >=14, more + // of the address space is available, and the OS can now + // provide addresses outside of those 33 bits. Pick 40 bits + // as a reasonable balance between address space usage by the + // page allocator, and flexibility for what mmap'd regions + // we'll accept for the heap. We can't just move to the full + // 48 bits because this uses too much address space for older + // iOS versions. + // TODO(mknyszek): Once iOS <14 is deprecated, promote ios/arm64 + // to a 48-bit address space like every other arm64 platform. // // WebAssembly currently has a limit of 4GB linear memory. - heapAddrBits = (_64bit*(1-sys.GoarchWasm)*(1-sys.GoosIos*sys.GoarchArm64))*48 + (1-_64bit+sys.GoarchWasm)*(32-(sys.GoarchMips+sys.GoarchMipsle)) + 33*sys.GoosIos*sys.GoarchArm64 + heapAddrBits = (_64bit*(1-sys.GoarchWasm)*(1-sys.GoosIos*sys.GoarchArm64))*48 + (1-_64bit+sys.GoarchWasm)*(32-(sys.GoarchMips+sys.GoarchMipsle)) + 40*sys.GoosIos*sys.GoarchArm64 // maxAlloc is the maximum size of an allocation. On 64-bit, // it's theoretically possible to allocate 1<