mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-20 18:26:40 +00:00
unify mem/ref interface
This commit is contained in:
21
std/assembly/allocator/README.md
Normal file
21
std/assembly/allocator/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
Memory manager interface
|
||||
========================
|
||||
|
||||
A memory manager for AssemblyScript must implement the following common and may implement any number of optional interfaces:
|
||||
|
||||
Common
|
||||
------
|
||||
|
||||
* **__mem_allocate**(size: `usize`): `usize`<br />
|
||||
Dynamically allocates a chunk of memory of at least the specified size and returns its address.
|
||||
Alignment must be guaranteed to be at least 8 bytes, but there are considerations to increase
|
||||
alignment to 16 bytes to fit SIMD v128 values.
|
||||
|
||||
* **__mem_free**(ref: `usize`): `void`<br />
|
||||
Frees a dynamically allocated chunk of memory by its address.
|
||||
|
||||
Optional
|
||||
--------
|
||||
|
||||
* **__mem_reset**(ref: `usize`, parentRef: `usize`)<br />
|
||||
Resets dynamic memory to its initial state. Used by the arena allocator.
|
@ -10,8 +10,8 @@ var startOffset: usize = (HEAP_BASE + AL_MASK) & ~AL_MASK;
|
||||
var offset: usize = startOffset;
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global @inline
|
||||
function __memory_allocate(size: usize): usize {
|
||||
@unsafe @global
|
||||
function __mem_allocate(size: usize): usize {
|
||||
if (size > MAX_SIZE_32) unreachable();
|
||||
var ptr = offset;
|
||||
var newPtr = (ptr + max<usize>(size, 1) + AL_MASK) & ~AL_MASK;
|
||||
@ -30,12 +30,12 @@ function __memory_allocate(size: usize): usize {
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global @inline
|
||||
function __memory_free(ptr: usize): void {
|
||||
@unsafe @global
|
||||
function __mem_free(ptr: usize): void {
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global @inline
|
||||
function __memory_reset(): void {
|
||||
@unsafe @global
|
||||
function __mem_reset(): void {
|
||||
offset = startOffset;
|
||||
}
|
||||
|
@ -7,13 +7,13 @@ declare function _malloc(size: usize): usize;
|
||||
declare function _free(ptr: usize): void;
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global @inline
|
||||
function __memory_allocate(size: usize): usize {
|
||||
@unsafe @global
|
||||
function __mem_allocate(size: usize): usize {
|
||||
return _malloc(size);
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global @inline
|
||||
function __memory_free(ptr: usize): void {
|
||||
@unsafe @global
|
||||
function __mem_free(ptr: usize): void {
|
||||
_free(ptr);
|
||||
}
|
||||
|
3
std/assembly/allocator/index.d.ts
vendored
Normal file
3
std/assembly/allocator/index.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
declare function __mem_allocate(size: usize): usize;
|
||||
declare function __mem_free(ref: usize): void;
|
||||
declare function __mem_reset(): void;
|
@ -7,13 +7,13 @@ declare function malloc(size: usize): usize;
|
||||
declare function free(ptr: usize): void;
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global @inline
|
||||
function __memory_allocate(size: usize): usize {
|
||||
@unsafe @global
|
||||
function __mem_allocate(size: usize): usize {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global @inline
|
||||
function __memory_free(ptr: usize): void {
|
||||
@unsafe @global
|
||||
function __mem_free(ptr: usize): void {
|
||||
free(ptr);
|
||||
}
|
||||
|
@ -428,8 +428,8 @@ var ROOT: Root = changetype<Root>(0);
|
||||
|
||||
/** Allocates a chunk of memory. */
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global @inline
|
||||
function __memory_allocate(size: usize): usize {
|
||||
@unsafe @global
|
||||
function __mem_allocate(size: usize): usize {
|
||||
// initialize if necessary
|
||||
var root = ROOT;
|
||||
if (!root) {
|
||||
@ -478,8 +478,8 @@ function __memory_allocate(size: usize): usize {
|
||||
|
||||
/** Frees the chunk of memory at the specified address. */
|
||||
// @ts-ignore: decorator
|
||||
@unsafe @global @inline
|
||||
function __memory_free(data: usize): void {
|
||||
@unsafe @global
|
||||
function __mem_free(data: usize): void {
|
||||
if (data) {
|
||||
let root = ROOT;
|
||||
if (root) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
Garbage collector interface
|
||||
===========================
|
||||
|
||||
A garbage collector for AssemblyScript must implement the common and either of the tracing or reference counting interfaces.
|
||||
A garbage collector for AssemblyScript must implement the following common and either the tracing or reference counting interfaces:
|
||||
|
||||
Common
|
||||
------
|
||||
|
@ -1,3 +1,5 @@
|
||||
/// <reference path="./allocator/index.d.ts" />
|
||||
|
||||
import { memcmp, memmove, memset } from "./util/memory";
|
||||
|
||||
// @ts-ignore: decorator
|
||||
@ -49,8 +51,7 @@ export namespace memory {
|
||||
// @ts-ignore: decorator
|
||||
@unsafe
|
||||
export function allocate(size: usize): usize {
|
||||
// @ts-ignore: stub
|
||||
if (isDefined(__memory_allocate)) return __memory_allocate(size);
|
||||
if (isDefined(__mem_allocate)) return __mem_allocate(size);
|
||||
else return <usize>unreachable();
|
||||
}
|
||||
|
||||
@ -58,8 +59,7 @@ export namespace memory {
|
||||
// @ts-ignore: decorator
|
||||
@unsafe
|
||||
export function free(ptr: usize): void {
|
||||
// @ts-ignore: stub
|
||||
if (isDefined(__memory_free)) __memory_free(ptr);
|
||||
if (isDefined(__mem_free)) __mem_free(ptr);
|
||||
else unreachable();
|
||||
}
|
||||
|
||||
@ -67,8 +67,7 @@ export namespace memory {
|
||||
// @ts-ignore: decorator
|
||||
@unsafe
|
||||
export function reset(): void {
|
||||
// @ts-ignore: stub
|
||||
if (isDefined(__memory_reset)) __memory_reset();
|
||||
if (isDefined(__mem_reset)) __mem_reset();
|
||||
else unreachable();
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
// The runtime provides a set of macros for dealing with common AssemblyScript internals, like
|
||||
// allocation, memory management in general, integration with a (potential) garbage collector
|
||||
// and interfaces to hard-wired data types like buffers and their views. Doing so ensures that
|
||||
// no matter which underlying implementation of a memory allocator or garbage collector is used,
|
||||
// as long as all runtime/managed objects adhere to the runtime conventions, it'll all play well
|
||||
// together. The compiler assumes that it can itself use the macros with the signatures declared
|
||||
// in this file, so changing anything here will most likely require changes to the compiler, too.
|
||||
// The runtime provides common functionality that links runtime interfaces for memory management
|
||||
// and garbage collection to the standard library, making sure it all plays well together. However,
|
||||
// most of the garbage collector interface must still be implemented explicitly in standard library
|
||||
// components, because common abstractions for both tracing and reference counting would result in
|
||||
// unnecessary overhead (e.g. tracing needs parent references while rc does not etc.).
|
||||
|
||||
import { AL_MASK, MAX_SIZE_32 } from "./util/allocator";
|
||||
import { HEAP_BASE, memory } from "./memory";
|
||||
|
Reference in New Issue
Block a user