diff --git a/compileopts/config.go b/compileopts/config.go index d6979213..6e52c4ff 100644 --- a/compileopts/config.go +++ b/compileopts/config.go @@ -80,12 +80,7 @@ func (c *Config) GC() string { if c.Target.GC != "" { return c.Target.GC } - for _, tag := range c.Target.BuildTags { - if tag == "baremetal" || tag == "wasm" { - return "conservative" - } - } - return "extalloc" + return "conservative" } // NeedsStackObjects returns true if the compiler should insert stack objects diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go index 60110161..ac31b67d 100644 --- a/src/runtime/os_darwin.go +++ b/src/runtime/os_darwin.go @@ -3,3 +3,11 @@ package runtime const GOOS = "darwin" + +const ( + // See https://github.com/golang/go/blob/master/src/syscall/zerrors_darwin_amd64.go + flag_PROT_READ = 0x1 + flag_PROT_WRITE = 0x2 + flag_MAP_PRIVATE = 0x2 + flag_MAP_ANONYMOUS = 0x1000 // MAP_ANON +) diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index ab43c3a4..7613134e 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -3,3 +3,11 @@ package runtime const GOOS = "linux" + +const ( + // See https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/mman-common.h + flag_PROT_READ = 0x1 + flag_PROT_WRITE = 0x2 + flag_MAP_PRIVATE = 0x2 + flag_MAP_ANONYMOUS = 0x20 +) diff --git a/src/runtime/runtime_unix.go b/src/runtime/runtime_unix.go index 59a28682..584f0338 100644 --- a/src/runtime/runtime_unix.go +++ b/src/runtime/runtime_unix.go @@ -16,6 +16,9 @@ func usleep(usec uint) int //export malloc func malloc(size uintptr) unsafe.Pointer +//export mmap +func mmap(addr unsafe.Pointer, length, prot, flags, fd int, offset int) unsafe.Pointer + //export abort func abort() diff --git a/src/runtime/runtime_unix_heap.go b/src/runtime/runtime_unix_heap.go index 98ad8075..cee1f1e1 100644 --- a/src/runtime/runtime_unix_heap.go +++ b/src/runtime/runtime_unix_heap.go @@ -5,20 +5,33 @@ package runtime -const heapSize = 1 * 1024 * 1024 // 1MB to start +var heapSize uintptr = 128 * 1024 // small amount to start +const heapMaxSize = 1 * 1024 * 1024 * 1024 // 1GB for the entire heap var heapStart, heapEnd uintptr func preinit() { - heapStart = uintptr(malloc(heapSize)) + // Allocate a large chunk of virtual memory. Because it is virtual, it won't + // really be allocated in RAM. Memory will only be allocated when it is + // first touched. + addr := mmap(nil, heapMaxSize, flag_PROT_READ|flag_PROT_WRITE, flag_MAP_PRIVATE|flag_MAP_ANONYMOUS, -1, 0) + heapStart = uintptr(addr) heapEnd = heapStart + heapSize } // growHeap tries to grow the heap size. It returns true if it succeeds, false // otherwise. func growHeap() bool { - // At the moment, this is not possible. However it shouldn't be too - // difficult (at least on Linux) to allocate a large amount of virtual - // memory at startup that is then slowly used. - return false + if heapSize == heapMaxSize { + // Already at the max. If we run out of memory, we should consider + // increasing heapMaxSize on 64-bit systems. + return false + } + // Grow the heap size used by the program. + heapSize = (heapSize * 4 / 3) &^ 4095 // grow by around 33% + if heapSize > heapMaxSize { + heapSize = heapMaxSize + } + setHeapEnd(heapStart + heapSize) + return true }