1// Copyright 2018 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// +build js,wasm 6 7package runtime 8 9import ( 10 "unsafe" 11) 12 13// Don't split the stack as this function may be invoked without a valid G, 14// which prevents us from allocating more stack. 15//go:nosplit 16func sysAlloc(n uintptr, sysStat *uint64) unsafe.Pointer { 17 p := sysReserve(nil, n) 18 sysMap(p, n, sysStat) 19 return p 20} 21 22func sysUnused(v unsafe.Pointer, n uintptr) { 23} 24 25func sysUsed(v unsafe.Pointer, n uintptr) { 26} 27 28func sysHugePage(v unsafe.Pointer, n uintptr) { 29} 30 31// Don't split the stack as this function may be invoked without a valid G, 32// which prevents us from allocating more stack. 33//go:nosplit 34func sysFree(v unsafe.Pointer, n uintptr, sysStat *uint64) { 35 mSysStatDec(sysStat, n) 36} 37 38func sysFault(v unsafe.Pointer, n uintptr) { 39} 40 41var reserveEnd uintptr 42 43func sysReserve(v unsafe.Pointer, n uintptr) unsafe.Pointer { 44 // TODO(neelance): maybe unify with mem_plan9.go, depending on how https://github.com/WebAssembly/design/blob/master/FutureFeatures.md#finer-grained-control-over-memory turns out 45 46 if v != nil { 47 // The address space of WebAssembly's linear memory is contiguous, 48 // so requesting specific addresses is not supported. We could use 49 // a different address, but then mheap.sysAlloc discards the result 50 // right away and we don't reuse chunks passed to sysFree. 51 return nil 52 } 53 54 // Round up the initial reserveEnd to 64 KiB so that 55 // reservations are always aligned to the page size. 56 initReserveEnd := alignUp(lastmoduledatap.end, physPageSize) 57 if reserveEnd < initReserveEnd { 58 reserveEnd = initReserveEnd 59 } 60 v = unsafe.Pointer(reserveEnd) 61 reserveEnd += alignUp(n, physPageSize) 62 63 current := currentMemory() 64 // reserveEnd is always at a page boundary. 65 needed := int32(reserveEnd / physPageSize) 66 if current < needed { 67 if growMemory(needed-current) == -1 { 68 return nil 69 } 70 resetMemoryDataView() 71 } 72 73 return v 74} 75 76func currentMemory() int32 77func growMemory(pages int32) int32 78 79// resetMemoryDataView signals the JS front-end that WebAssembly's memory.grow instruction has been used. 80// This allows the front-end to replace the old DataView object with a new one. 81func resetMemoryDataView() 82 83func sysMap(v unsafe.Pointer, n uintptr, sysStat *uint64) { 84 mSysStatInc(sysStat, n) 85} 86