Black Lives Matter. Support the Equal Justice Initiative.

Source file src/runtime/mem_js.go

Documentation: runtime

     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  //go:build js && wasm
     6  // +build js,wasm
     7  
     8  package runtime
     9  
    10  import (
    11  	"unsafe"
    12  )
    13  
    14  // Don't split the stack as this function may be invoked without a valid G,
    15  // which prevents us from allocating more stack.
    16  //go:nosplit
    17  func sysAlloc(n uintptr, sysStat *sysMemStat) unsafe.Pointer {
    18  	p := sysReserve(nil, n)
    19  	sysMap(p, n, sysStat)
    20  	return p
    21  }
    22  
    23  func sysUnused(v unsafe.Pointer, n uintptr) {
    24  }
    25  
    26  func sysUsed(v unsafe.Pointer, n uintptr) {
    27  }
    28  
    29  func sysHugePage(v unsafe.Pointer, n uintptr) {
    30  }
    31  
    32  // Don't split the stack as this function may be invoked without a valid G,
    33  // which prevents us from allocating more stack.
    34  //go:nosplit
    35  func sysFree(v unsafe.Pointer, n uintptr, sysStat *sysMemStat) {
    36  	sysStat.add(-int64(n))
    37  }
    38  
    39  func sysFault(v unsafe.Pointer, n uintptr) {
    40  }
    41  
    42  var reserveEnd uintptr
    43  
    44  func sysReserve(v unsafe.Pointer, n uintptr) unsafe.Pointer {
    45  	// 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
    46  
    47  	if v != nil {
    48  		// The address space of WebAssembly's linear memory is contiguous,
    49  		// so requesting specific addresses is not supported. We could use
    50  		// a different address, but then mheap.sysAlloc discards the result
    51  		// right away and we don't reuse chunks passed to sysFree.
    52  		return nil
    53  	}
    54  
    55  	// Round up the initial reserveEnd to 64 KiB so that
    56  	// reservations are always aligned to the page size.
    57  	initReserveEnd := alignUp(lastmoduledatap.end, physPageSize)
    58  	if reserveEnd < initReserveEnd {
    59  		reserveEnd = initReserveEnd
    60  	}
    61  	v = unsafe.Pointer(reserveEnd)
    62  	reserveEnd += alignUp(n, physPageSize)
    63  
    64  	current := currentMemory()
    65  	// reserveEnd is always at a page boundary.
    66  	needed := int32(reserveEnd / physPageSize)
    67  	if current < needed {
    68  		if growMemory(needed-current) == -1 {
    69  			return nil
    70  		}
    71  		resetMemoryDataView()
    72  	}
    73  
    74  	return v
    75  }
    76  
    77  func currentMemory() int32
    78  func growMemory(pages int32) int32
    79  
    80  // resetMemoryDataView signals the JS front-end that WebAssembly's memory.grow instruction has been used.
    81  // This allows the front-end to replace the old DataView object with a new one.
    82  func resetMemoryDataView()
    83  
    84  func sysMap(v unsafe.Pointer, n uintptr, sysStat *sysMemStat) {
    85  	sysStat.add(int64(n))
    86  }
    87  

View as plain text