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