From 9181f2d4cebb6c76671de81c7019f12214a8fc14 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sat, 17 Nov 2018 15:30:38 +0100 Subject: [PATCH] runtime: add "end of heap" to detect out of memory This can be used in the future to trigger garbage collection. For now, it provides a more useful error message in case the heap is completely filled up. --- src/runtime/arch_avr.go | 8 +++++++- src/runtime/arch_tinygoarm.go | 8 +++++++- src/runtime/arch_wasm.go | 7 ++++++- src/runtime/gc_dumb.go | 3 +++ src/runtime/runtime_unix.go | 5 ++++- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/runtime/arch_avr.go b/src/runtime/arch_avr.go index 778ae4d7..38e75732 100644 --- a/src/runtime/arch_avr.go +++ b/src/runtime/arch_avr.go @@ -14,7 +14,13 @@ const TargetBits = 8 //go:extern _heap_start var heapStartSymbol unsafe.Pointer -var heapStart = uintptr(unsafe.Pointer(&heapStartSymbol)) +//go:extern _heap_end +var heapEndSymbol unsafe.Pointer + +var ( + heapStart = uintptr(unsafe.Pointer(&heapStartSymbol)) + heapEnd = uintptr(unsafe.Pointer(&heapEndSymbol)) +) // Align on a word boundary. func align(ptr uintptr) uintptr { diff --git a/src/runtime/arch_tinygoarm.go b/src/runtime/arch_tinygoarm.go index cb8feed0..ed286f6f 100644 --- a/src/runtime/arch_tinygoarm.go +++ b/src/runtime/arch_tinygoarm.go @@ -14,7 +14,13 @@ const TargetBits = 32 //go:extern _heap_start var heapStartSymbol unsafe.Pointer -var heapStart = uintptr(unsafe.Pointer(&heapStartSymbol)) +//go:extern _heap_end +var heapEndSymbol unsafe.Pointer + +var ( + heapStart = uintptr(unsafe.Pointer(&heapStartSymbol)) + heapEnd = uintptr(unsafe.Pointer(&heapEndSymbol)) +) // Align on word boundary. func align(ptr uintptr) uintptr { diff --git a/src/runtime/arch_wasm.go b/src/runtime/arch_wasm.go index e893f889..00f97895 100644 --- a/src/runtime/arch_wasm.go +++ b/src/runtime/arch_wasm.go @@ -14,7 +14,12 @@ const TargetBits = 32 //go:extern __heap_base var heapStartSymbol unsafe.Pointer -var heapStart = uintptr(unsafe.Pointer(&heapStartSymbol)) +var ( + heapStart = uintptr(unsafe.Pointer(&heapStartSymbol)) + heapEnd = (heapStart + wasmPageSize - 1) & (wasmPageSize - 1) // conservative guess: one page of heap memory +) + +const wasmPageSize = 64 * 1024 // Align on word boundary. func align(ptr uintptr) uintptr { diff --git a/src/runtime/gc_dumb.go b/src/runtime/gc_dumb.go index 34fbfda3..92527364 100644 --- a/src/runtime/gc_dumb.go +++ b/src/runtime/gc_dumb.go @@ -20,6 +20,9 @@ func alloc(size uintptr) unsafe.Pointer { size = align(size) addr := heapptr heapptr += size + if heapptr >= heapEnd { + runtimePanic("out of memory") + } for i := uintptr(0); i < uintptr(size); i += 4 { ptr := (*uint32)(unsafe.Pointer(addr + i)) *ptr = 0 diff --git a/src/runtime/runtime_unix.go b/src/runtime/runtime_unix.go index 9a3a761c..aa9c15ac 100644 --- a/src/runtime/runtime_unix.go +++ b/src/runtime/runtime_unix.go @@ -14,7 +14,10 @@ func _Cfunc_clock_gettime(clk_id uint, ts *timespec) const heapSize = 1 * 1024 * 1024 // 1MB to start -var heapStart = uintptr(_Cfunc_malloc(heapSize)) +var ( + heapStart = uintptr(_Cfunc_malloc(heapSize)) + heapEnd = heapStart + heapSize +) type timeUnit int64