Source file src/runtime/mem_js.go

     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  
     7  package runtime
     8  
     9  import (
    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  //
    16  //go:nosplit
    17  func sysAllocOS(n uintptr) unsafe.Pointer {
    18  	p := sysReserveOS(nil, n)
    19  	sysMapOS(p, n)
    20  	return p
    21  }
    22  
    23  func sysUnusedOS(v unsafe.Pointer, n uintptr) {
    24  }
    25  
    26  func sysUsedOS(v unsafe.Pointer, n uintptr) {
    27  }
    28  
    29  func sysHugePageOS(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  //
    35  //go:nosplit
    36  func sysFreeOS(v unsafe.Pointer, n uintptr) {
    37  }
    38  
    39  func sysFaultOS(v unsafe.Pointer, n uintptr) {
    40  }
    41  
    42  var reserveEnd uintptr
    43  
    44  func sysReserveOS(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 sysMapOS(v unsafe.Pointer, n uintptr) {
    85  }
    86  

View as plain text