diff --git a/std/assembly/rt/README.md b/std/assembly/rt/README.md index c930576e..1fb78f57 100644 --- a/std/assembly/rt/README.md +++ b/std/assembly/rt/README.md @@ -4,3 +4,30 @@ The AssemblyScript Runtime The runtime provides the functionality necessary to dynamically allocate and deallocate memory of objects, arrays and buffers, as well as keep track of references that are no longer used. It is based on [the TLSF memory manager](./tlsf.ts) and [a pure reference counting garbage collector](./pure.ts). + +Interface +--------- + +* **__rt_allocate**(size: `usize`, id: `u32` = 0): `usize`
+ Dynamically allocates a chunk of memory of at least the specified size and returns its address. + Alignment is guaranteed to be 16 bytes to fit up to v128 values naturally. + +* **__rt_free**(ref: `usize`): `void`
+ Frees a dynamically allocated chunk of memory by its address. + +* **__rt_retain**(ref: `usize`): `void`
+ Retains a reference. + +* **__rt_release**(ref: `usize`): `void`
+ Releases a reference. + +* **__rt_collect**(): `void`
+ Forces a full garbage collection cycle. + +* **__rt_typeinfo**(id: `u32`): `void`
+ Obtains the runtime type information for objects of the kind represented by the specified id. + +Stub +---- + +The fully functional yet minimal [stub implementation](./stub.ts) provides dynamic memory allocation only but doesn't include sophisticated support to deallocate objects. Useful for prototyping or very short-lived programs with hardly any memory footprint. diff --git a/std/assembly/rt/common.ts b/std/assembly/rt/common.ts index e8062635..97af07d6 100644 --- a/std/assembly/rt/common.ts +++ b/std/assembly/rt/common.ts @@ -11,3 +11,29 @@ // @ts-ignore: decorator @inline export const DEBUG = true; + +/** Common block structure. */ +@unmanaged export class CommonBlock { + /** Memory manager info. */ + mmInfo: usize; // WASM64 might need adaption + /** Garbage collector info. */ + gcInfo: u32; + /** Runtime class id. */ + rtId: u32; + /** Runtime object size. */ + rtSize: u32; +} + +/////////////////////////////////// Type information interface //////////////////////////////////// + +import { RTTI_BASE } from "../runtime"; +import { RTTIData } from "../common/rtti"; + +// @ts-ignore: decorator +@global @unsafe +function __rt_typeinfo(id: u32): u32 { + var ptr: usize = RTTI_BASE; + return !id || id > load(ptr) + ? unreachable() + : changetype(ptr + id * offsetof()).flags; +} diff --git a/std/assembly/rt/index.ts b/std/assembly/rt/index.ts index cdd95244..a37cf887 100644 --- a/std/assembly/rt/index.ts +++ b/std/assembly/rt/index.ts @@ -1,52 +1,56 @@ import { AL_MASK, DEBUG } from "./common"; -import { ROOT, Block, BLOCK_OVERHEAD, initializeRoot, allocateBlock, reallocateBlock, freeBlock } from "./tlsf"; -import { increment, decrement, collectCycles } from "./pure"; //////////////////////////////////// Memory manager interface ///////////////////////////////////// +import { ROOT, Block, BLOCK_OVERHEAD, initializeRoot, allocateBlock, reallocateBlock, freeBlock } from "./tlsf"; + // @ts-ignore: decorator @global @unsafe -function __mm_allocate(size: usize): usize { +function __rt_allocate(size: usize, id: u32): usize { var root = ROOT; if (!root) { initializeRoot(); root = ROOT; } - return changetype(allocateBlock(root, size)) + BLOCK_OVERHEAD; + var block = allocateBlock(root, size); + block.rtId = id; + return changetype(block) + BLOCK_OVERHEAD; } // @ts-ignore: decorator @global @unsafe -function __mm_reallocate(data: usize, size: usize): usize { +function __rt_reallocate(ref: usize, size: usize): usize { if (DEBUG) assert(ROOT); // must be initialized - assert(data != 0 && !(data & AL_MASK)); // must exist and be aligned - return changetype(reallocateBlock(ROOT, changetype(data - BLOCK_OVERHEAD), size)) + BLOCK_OVERHEAD; + assert(ref != 0 && !(ref & AL_MASK)); // must exist and be aligned + return changetype(reallocateBlock(ROOT, changetype(ref - BLOCK_OVERHEAD), size)) + BLOCK_OVERHEAD; } // @ts-ignore: decorator @global @unsafe -function __mm_free(data: usize): void { +function __rt_free(ref: usize): void { if (DEBUG) assert(ROOT); // must be initialized - assert(data != 0 && !(data & AL_MASK)); // must exist and be aligned - freeBlock(ROOT, changetype(data - BLOCK_OVERHEAD)); + assert(ref != 0 && !(ref & AL_MASK)); // must exist and be aligned + freeBlock(ROOT, changetype(ref - BLOCK_OVERHEAD)); } /////////////////////////////////// Garbage collector interface /////////////////////////////////// +import { increment, decrement, collectCycles } from "./pure"; + // @ts-ignore: decorator @global @unsafe -function __gc_retain(ref: usize): void { +function __rt_retain(ref: usize): void { if (ref) increment(changetype(ref - BLOCK_OVERHEAD)); } // @ts-ignore: decorator @global @unsafe -function __gc_release(ref: usize): void { +function __rt_release(ref: usize): void { if (ref) decrement(changetype(ref - BLOCK_OVERHEAD)); } // @ts-ignore: decorator @global @unsafe -function __gc_collect(): void { +function __rt_collect(): void { collectCycles(); } diff --git a/std/assembly/rt/stub.ts b/std/assembly/rt/stub.ts new file mode 100644 index 00000000..da02be77 --- /dev/null +++ b/std/assembly/rt/stub.ts @@ -0,0 +1,77 @@ +import { AL_MASK, CommonBlock } from "./common"; + +// @ts-ignore: decorator +@inline +const BLOCK_OVERHEAD = offsetof(); + +// @ts-ignore: decorator +@inline +const BLOCK_MAXSIZE: usize = (1 << 30) - BLOCK_OVERHEAD; // match TLSF + +// @ts-ignore: decorator +@lazy +var startOffset: usize = (HEAP_BASE + AL_MASK) & ~AL_MASK; + +// @ts-ignore: decorator +@lazy +var offset: usize = startOffset; + +//////////////////////////////////// Memory manager interface ///////////////////////////////////// + +// @ts-ignore: decorator +@unsafe @global +function __rt_allocate(size: usize, id: u32): usize { + if (size > BLOCK_MAXSIZE) unreachable(); + var ptr = offset + BLOCK_OVERHEAD; + var newPtr = (ptr + max(size, 1) + AL_MASK) & ~AL_MASK; + var pagesBefore = memory.size(); + if (newPtr > pagesBefore << 16) { + let pagesNeeded = ((newPtr - ptr + 0xffff) & ~0xffff) >>> 16; + let pagesWanted = max(pagesBefore, pagesNeeded); // double memory + if (memory.grow(pagesWanted) < 0) { + if (memory.grow(pagesNeeded) < 0) unreachable(); // out of memory + } + } + offset = newPtr; + var block = changetype(ptr - BLOCK_OVERHEAD); + block.rtId = id; + block.rtSize = size; + return ptr; +} + +// @ts-ignore: decorator +@unsafe @global +function __rt_reallocate(ref: usize, size: usize): usize { + var block = changetype(ref - BLOCK_OVERHEAD); + var newRef = __rt_allocate(size, block.rtId); + memory.copy(newRef, ref, block.rtSize); + return newRef; +} + +// @ts-ignore: decorator +@unsafe @global +function __rt_free(ref: usize): void { +} + +// @ts-ignore: decorator +@unsafe @global +function __rt_reset(): void { // special + offset = startOffset; +} + +/////////////////////////////////// Garbage collector interface /////////////////////////////////// + +// @ts-ignore: decorator +@global @unsafe +function __rt_retain(ref: usize): void { +} + +// @ts-ignore: decorator +@global @unsafe +function __rt_release(ref: usize): void { +} + +// @ts-ignore: decorator +@global @unsafe +function __rt_collect(): void { +} diff --git a/std/assembly/rt/tlsf.ts b/std/assembly/rt/tlsf.ts index 8b9bfbea..518908a2 100644 --- a/std/assembly/rt/tlsf.ts +++ b/std/assembly/rt/tlsf.ts @@ -1,4 +1,4 @@ -import { AL_BITS, AL_SIZE, AL_MASK, DEBUG } from "./common"; +import { AL_BITS, AL_SIZE, AL_MASK, DEBUG, CommonBlock } from "./common"; /////////////////////// The TLSF (Two-Level Segregate Fit) memory allocator /////////////////////// // see: http://www.gii.upv.es/tlsf/ @@ -69,16 +69,7 @@ import { AL_BITS, AL_SIZE, AL_MASK, DEBUG } from "./common"; // │ if free: back ▲ │ ◄─┘ // └───────────────────────────────────────────────────────────────┘ payload ┘ >= MIN SIZE // F: FREE, L: LEFTFREE -@unmanaged export class Block { - - /** Memory manager info. */ - mmInfo: usize; // WASM64 might need adaption - /** Garbage collector info. */ - gcInfo: u32; - /** Runtime class id. */ - rtId: u32; - /** Runtime object size. */ - rtSize: u32; +@unmanaged export class Block extends CommonBlock { /** Previous free block, if any. Only valid if free, otherwise part of payload. */ prev: Block | null; diff --git a/tests/allocators/asrt/assembly/index.ts b/tests/allocators/rt/assembly/index.ts similarity index 84% rename from tests/allocators/asrt/assembly/index.ts rename to tests/allocators/rt/assembly/index.ts index f2af0bf0..07ddc5a5 100644 --- a/tests/allocators/asrt/assembly/index.ts +++ b/tests/allocators/rt/assembly/index.ts @@ -3,10 +3,10 @@ import { memory as builtin_memory } from "memory"; export namespace memory { export function allocate(size: usize): usize { - return __mm_allocate(size); + return __rt_allocate(size, 0); } export function free(ptr: usize): void { - __mm_free(ptr); + __rt_free(ptr); } export function fill(dst: usize, c: u8, n: usize): void { builtin_memory.fill(dst, c, n); diff --git a/tests/allocators/asrt/assembly/tsconfig.json b/tests/allocators/rt/assembly/tsconfig.json similarity index 100% rename from tests/allocators/asrt/assembly/tsconfig.json rename to tests/allocators/rt/assembly/tsconfig.json diff --git a/tests/allocators/asrt/optimized.wat b/tests/allocators/rt/optimized.wat similarity index 96% rename from tests/allocators/asrt/optimized.wat rename to tests/allocators/rt/optimized.wat index 40afeeef..7b5eb5ce 100644 --- a/tests/allocators/asrt/optimized.wat +++ b/tests/allocators/rt/optimized.wat @@ -1,8 +1,8 @@ (module (type $FUNCSIG$ii (func (param i32) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$v (func)) (type $FUNCSIG$vii (func (param i32 i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$viiii (func (param i32 i32 i32 i32))) (type $FUNCSIG$viii (func (param i32 i32 i32))) (type $FUNCSIG$vi (func (param i32))) @@ -497,7 +497,7 @@ if i32.const 0 i32.const 24 - i32.const 436 + i32.const 427 i32.const 29 call $~lib/builtins/abort unreachable @@ -758,7 +758,7 @@ call $~lib/rt/tlsf/prepareBlock local.get $2 ) - (func $assembly/index/memory.allocate (; 10 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) + (func $~lib/rt/index/__rt_allocate (; 10 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) (local $1 i32) global.get $~lib/rt/tlsf/ROOT local.tee $1 @@ -770,10 +770,18 @@ end local.get $0 call $~lib/rt/tlsf/allocateBlock + local.tee $0 + i32.const 0 + i32.store offset=8 + local.get $0 i32.const 16 i32.add ) - (func $assembly/index/memory.free (; 11 ;) (type $FUNCSIG$vi) (param $0 i32) + (func $assembly/index/memory.allocate (; 11 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) + local.get $0 + call $~lib/rt/index/__rt_allocate + ) + (func $assembly/index/memory.free (; 12 ;) (type $FUNCSIG$vi) (param $0 i32) local.get $0 i32.const 16 i32.sub @@ -787,7 +795,7 @@ local.get $0 call $~lib/rt/tlsf/insertBlock ) - (func $~lib/memory/memory.fill (; 12 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) + (func $~lib/memory/memory.fill (; 13 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i64) (local $4 i32) block $~lib/util/memory/memset|inlined.0 @@ -1017,13 +1025,13 @@ end end ) - (func $assembly/index/memory.fill (; 13 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) + (func $assembly/index/memory.fill (; 14 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) local.get $0 local.get $1 local.get $2 call $~lib/memory/memory.fill ) - (func $null (; 14 ;) (type $FUNCSIG$v) + (func $null (; 15 ;) (type $FUNCSIG$v) nop ) ) diff --git a/tests/allocators/asrt/package.json b/tests/allocators/rt/package.json similarity index 100% rename from tests/allocators/asrt/package.json rename to tests/allocators/rt/package.json diff --git a/tests/allocators/asrt/untouched.wat b/tests/allocators/rt/untouched.wat similarity index 97% rename from tests/allocators/asrt/untouched.wat rename to tests/allocators/rt/untouched.wat index 5e0390d1..1667756b 100644 --- a/tests/allocators/asrt/untouched.wat +++ b/tests/allocators/rt/untouched.wat @@ -1,10 +1,10 @@ (module (type $FUNCSIG$ii (func (param i32) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$v (func)) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$viiii (func (param i32 i32 i32 i32))) (type $FUNCSIG$vii (func (param i32 i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$viii (func (param i32 i32 i32))) (type $FUNCSIG$vi (func (param i32))) (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) @@ -41,7 +41,7 @@ if i32.const 0 i32.const 24 - i32.const 265 + i32.const 256 i32.const 13 call $~lib/builtins/abort unreachable @@ -66,7 +66,7 @@ if i32.const 0 i32.const 24 - i32.const 267 + i32.const 258 i32.const 13 call $~lib/builtins/abort unreachable @@ -118,7 +118,7 @@ if i32.const 0 i32.const 24 - i32.const 280 + i32.const 271 i32.const 13 call $~lib/builtins/abort unreachable @@ -256,7 +256,7 @@ if i32.const 0 i32.const 24 - i32.const 193 + i32.const 184 i32.const 13 call $~lib/builtins/abort unreachable @@ -271,7 +271,7 @@ if i32.const 0 i32.const 24 - i32.const 195 + i32.const 186 i32.const 13 call $~lib/builtins/abort unreachable @@ -370,7 +370,7 @@ if i32.const 0 i32.const 24 - i32.const 216 + i32.const 207 i32.const 15 call $~lib/builtins/abort unreachable @@ -433,7 +433,7 @@ if i32.const 0 i32.const 24 - i32.const 231 + i32.const 222 i32.const 13 call $~lib/builtins/abort unreachable @@ -449,7 +449,7 @@ if i32.const 0 i32.const 24 - i32.const 232 + i32.const 223 i32.const 13 call $~lib/builtins/abort unreachable @@ -506,7 +506,7 @@ if i32.const 0 i32.const 24 - i32.const 248 + i32.const 239 i32.const 13 call $~lib/builtins/abort unreachable @@ -629,7 +629,7 @@ if i32.const 0 i32.const 24 - i32.const 374 + i32.const 365 i32.const 4 call $~lib/builtins/abort unreachable @@ -654,7 +654,7 @@ if i32.const 0 i32.const 24 - i32.const 384 + i32.const 375 i32.const 15 call $~lib/builtins/abort unreachable @@ -685,7 +685,7 @@ if i32.const 0 i32.const 24 - i32.const 396 + i32.const 387 i32.const 4 call $~lib/builtins/abort unreachable @@ -918,7 +918,7 @@ if i32.const 0 i32.const 24 - i32.const 436 + i32.const 427 i32.const 29 call $~lib/builtins/abort unreachable @@ -1012,7 +1012,7 @@ if i32.const 0 i32.const 24 - i32.const 326 + i32.const 317 i32.const 13 call $~lib/builtins/abort unreachable @@ -1077,7 +1077,7 @@ if i32.const 0 i32.const 24 - i32.const 339 + i32.const 330 i32.const 17 call $~lib/builtins/abort unreachable @@ -1195,7 +1195,7 @@ if i32.const 0 i32.const 24 - i32.const 353 + i32.const 344 i32.const 13 call $~lib/builtins/abort unreachable @@ -1306,7 +1306,7 @@ if i32.const 0 i32.const 24 - i32.const 466 + i32.const 457 i32.const 15 call $~lib/builtins/abort unreachable @@ -1324,7 +1324,7 @@ if i32.const 0 i32.const 24 - i32.const 468 + i32.const 459 i32.const 13 call $~lib/builtins/abort unreachable @@ -1347,26 +1347,33 @@ call $~lib/rt/tlsf/prepareBlock local.get $3 ) - (func $~lib/rt/index/__mm_allocate (; 10 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) - (local $1 i32) + (func $~lib/rt/index/__rt_allocate (; 10 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) global.get $~lib/rt/tlsf/ROOT - local.set $1 - local.get $1 + local.set $2 + local.get $2 i32.eqz if call $~lib/rt/tlsf/initializeRoot global.get $~lib/rt/tlsf/ROOT - local.set $1 + local.set $2 end - local.get $1 + local.get $2 local.get $0 call $~lib/rt/tlsf/allocateBlock + local.set $3 + local.get $3 + local.get $1 + i32.store offset=8 + local.get $3 i32.const 16 i32.add ) (func $assembly/index/memory.allocate (; 11 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) local.get $0 - call $~lib/rt/index/__mm_allocate + i32.const 0 + call $~lib/rt/index/__rt_allocate ) (func $~lib/rt/tlsf/freeBlock (; 12 ;) (type $FUNCSIG$vii) (param $0 i32) (param $1 i32) (local $2 i32) @@ -1381,7 +1388,7 @@ if i32.const 0 i32.const 24 - i32.const 519 + i32.const 510 i32.const 2 call $~lib/builtins/abort unreachable @@ -1395,13 +1402,13 @@ local.get $1 call $~lib/rt/tlsf/insertBlock ) - (func $~lib/rt/index/__mm_free (; 13 ;) (type $FUNCSIG$vi) (param $0 i32) + (func $~lib/rt/index/__rt_free (; 13 ;) (type $FUNCSIG$vi) (param $0 i32) global.get $~lib/rt/tlsf/ROOT i32.eqz if i32.const 0 i32.const 72 - i32.const 29 + i32.const 31 i32.const 13 call $~lib/builtins/abort unreachable @@ -1421,7 +1428,7 @@ if i32.const 0 i32.const 72 - i32.const 30 + i32.const 32 i32.const 2 call $~lib/builtins/abort unreachable @@ -1434,7 +1441,7 @@ ) (func $assembly/index/memory.free (; 14 ;) (type $FUNCSIG$vi) (param $0 i32) local.get $0 - call $~lib/rt/index/__mm_free + call $~lib/rt/index/__rt_free ) (func $~lib/memory/memory.fill (; 15 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) (local $3 i32) diff --git a/tests/runtime/assembly/index.ts b/tests/runtime/assembly/index.ts index e10336b7..18f2db53 100644 --- a/tests/runtime/assembly/index.ts +++ b/tests/runtime/assembly/index.ts @@ -1,12 +1,13 @@ import "rt"; export { - __mm_allocate, - __mm_reallocate, - __mm_free, - __gc_retain, - __gc_release, - __gc_collect + __rt_allocate, + __rt_reallocate, + __rt_free, + __rt_retain, + __rt_release, + __rt_collect, + __rt_typeinfo }; @start export function main(): void {} diff --git a/tests/runtime/index.html b/tests/runtime/index.html index d029c223..f7f8b46c 100644 --- a/tests/runtime/index.html +++ b/tests/runtime/index.html @@ -28,8 +28,8 @@ fetch("untouched.wasm").then(result => ).then(result => { exports = result.instance.exports; U32 = new Uint32Array(exports.memory.buffer); - var first = exports.__mm_allocate(255); - exports.__mm_free(first); + var first = exports.__rt_allocate(255); + exports.__rt_free(first); ROOT = first - 17; while (!U32[ROOT >> 2]) --ROOT; // find tail ROOT -= (1 + FL_BITS + HL_SIZE) << 2; @@ -113,7 +113,7 @@ function update() { } function allocate(size) { - var ptr = exports.__mm_allocate(size); + var ptr = exports.__rt_allocate(size); if (!ptr) { alert("should not happen"); return; @@ -127,7 +127,7 @@ function allocate(size) { var er = document.createElement("button"); er.innerText = "realloc"; er.onclick = function() { - ptr = exports.__mm_reallocate(ptr, es.value >>> 0); + ptr = exports.__rt_reallocate(ptr, es.value >>> 0); update(); }; el.appendChild(er); @@ -136,7 +136,7 @@ function allocate(size) { ef.className = "free"; el.appendChild(ef); ef.onclick = function() { - exports.__mm_free(ptr); + exports.__rt_free(ptr); document.getElementById("segs").removeChild(el); update(); }; diff --git a/tests/runtime/optimized.wat b/tests/runtime/optimized.wat index f35cbe3e..fb233542 100644 --- a/tests/runtime/optimized.wat +++ b/tests/runtime/optimized.wat @@ -1,9 +1,9 @@ (module (type $FUNCSIG$v (func)) - (type $FUNCSIG$ii (func (param i32) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$vii (func (param i32 i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$viiii (func (param i32 i32 i32 i32))) (type $FUNCSIG$viii (func (param i32 i32 i32))) (type $FUNCSIG$vi (func (param i32))) @@ -13,18 +13,20 @@ (data (i32.const 24) "~\00l\00i\00b\00/\00r\00t\00/\00t\00l\00s\00f\00.\00t\00s") (data (i32.const 56) "\10\00\00\00\1c") (data (i32.const 72) "~\00l\00i\00b\00/\00m\00e\00m\00o\00r\00y\00.\00t\00s") + (data (i32.const 104) "\10\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08") (global $~lib/started (mut i32) (i32.const 0)) (global $~lib/rt/tlsf/ROOT (mut i32) (i32.const 0)) (global $~lib/rt/pure/CUR (mut i32) (i32.const 0)) (global $~lib/rt/pure/ROOTS (mut i32) (i32.const 0)) (export "memory" (memory $0)) (export "main" (func $assembly/index/main)) - (export "__mm_allocate" (func $~lib/rt/index/__mm_allocate)) - (export "__mm_reallocate" (func $~lib/rt/index/__mm_reallocate)) - (export "__mm_free" (func $~lib/rt/index/__mm_free)) - (export "__gc_retain" (func $~lib/rt/index/__gc_retain)) - (export "__gc_release" (func $~lib/rt/index/__gc_release)) - (export "__gc_collect" (func $~lib/rt/index/__gc_collect)) + (export "__rt_allocate" (func $~lib/rt/index/__rt_allocate)) + (export "__rt_reallocate" (func $~lib/rt/index/__rt_reallocate)) + (export "__rt_free" (func $~lib/rt/index/__rt_free)) + (export "__rt_retain" (func $~lib/rt/index/__rt_retain)) + (export "__rt_release" (func $~lib/rt/index/__rt_release)) + (export "__rt_collect" (func $~lib/rt/index/__rt_collect)) + (export "__rt_typeinfo" (func $~lib/rt/common/__rt_typeinfo)) (func $assembly/index/main (; 1 ;) (type $FUNCSIG$v) global.get $~lib/started i32.eqz @@ -416,7 +418,7 @@ (local $1 i32) (local $2 i32) (local $3 i32) - i32.const 112 + i32.const 240 local.tee $3 i32.const 67107 i32.add @@ -515,7 +517,7 @@ if i32.const 0 i32.const 24 - i32.const 436 + i32.const 427 i32.const 29 call $~lib/builtins/abort unreachable @@ -776,18 +778,22 @@ call $~lib/rt/tlsf/prepareBlock local.get $2 ) - (func $~lib/rt/index/__mm_allocate (; 11 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) - (local $1 i32) + (func $~lib/rt/index/__rt_allocate (; 11 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) global.get $~lib/rt/tlsf/ROOT - local.tee $1 + local.tee $2 if (result i32) - local.get $1 + local.get $2 else call $~lib/rt/tlsf/initializeRoot global.get $~lib/rt/tlsf/ROOT end local.get $0 call $~lib/rt/tlsf/allocateBlock + local.tee $0 + local.get $1 + i32.store offset=8 + local.get $0 i32.const 16 i32.add ) @@ -1067,7 +1073,7 @@ call $~lib/rt/tlsf/insertBlock local.get $3 ) - (func $~lib/rt/index/__mm_reallocate (; 14 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) + (func $~lib/rt/index/__rt_reallocate (; 14 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) global.get $~lib/rt/tlsf/ROOT local.get $0 i32.const 16 @@ -1088,14 +1094,14 @@ local.get $1 call $~lib/rt/tlsf/insertBlock ) - (func $~lib/rt/index/__mm_free (; 16 ;) (type $FUNCSIG$vi) (param $0 i32) + (func $~lib/rt/index/__rt_free (; 16 ;) (type $FUNCSIG$vi) (param $0 i32) global.get $~lib/rt/tlsf/ROOT local.get $0 i32.const 16 i32.sub call $~lib/rt/tlsf/freeBlock ) - (func $~lib/rt/index/__gc_retain (; 17 ;) (type $FUNCSIG$vi) (param $0 i32) + (func $~lib/rt/index/__rt_retain (; 17 ;) (type $FUNCSIG$vi) (param $0 i32) local.get $0 if local.get $0 @@ -1109,7 +1115,7 @@ i32.store offset=4 end ) - (func $~lib/rt/index/__gc_release (; 18 ;) (type $FUNCSIG$vi) (param $0 i32) + (func $~lib/rt/index/__rt_release (; 18 ;) (type $FUNCSIG$vi) (param $0 i32) local.get $0 if local.get $0 @@ -1327,10 +1333,34 @@ local.get $5 global.set $~lib/rt/pure/CUR ) - (func $~lib/rt/index/__gc_collect (; 23 ;) (type $FUNCSIG$v) + (func $~lib/rt/index/__rt_collect (; 23 ;) (type $FUNCSIG$v) call $~lib/rt/pure/collectCycles ) - (func $start (; 24 ;) (type $FUNCSIG$v) + (func $~lib/rt/common/__rt_typeinfo (; 24 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) + (local $1 i32) + i32.const 104 + local.set $1 + local.get $0 + if (result i32) + local.get $0 + local.get $1 + i32.load + i32.gt_u + else + i32.const 1 + end + if (result i32) + unreachable + else + local.get $1 + local.get $0 + i32.const 3 + i32.shl + i32.add + i32.load + end + ) + (func $start (; 25 ;) (type $FUNCSIG$v) nop ) ) diff --git a/tests/runtime/untouched.wasm b/tests/runtime/untouched.wasm index b84c7aa0..e6bc7cdd 100644 Binary files a/tests/runtime/untouched.wasm and b/tests/runtime/untouched.wasm differ diff --git a/tests/runtime/untouched.wat b/tests/runtime/untouched.wat index e3f74648..267a1056 100644 --- a/tests/runtime/untouched.wat +++ b/tests/runtime/untouched.wat @@ -1,10 +1,10 @@ (module (type $FUNCSIG$v (func)) - (type $FUNCSIG$ii (func (param i32) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$viiii (func (param i32 i32 i32 i32))) (type $FUNCSIG$vii (func (param i32 i32))) - (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$viii (func (param i32 i32 i32))) (type $FUNCSIG$vi (func (param i32))) (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) @@ -13,6 +13,7 @@ (data (i32.const 56) "\10\00\00\00 \00\00\00\00\00\00\00\00\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00i\00n\00d\00e\00x\00.\00t\00s\00") (data (i32.const 104) "\10\00\00\00\1e\00\00\00\00\00\00\00\00\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00p\00u\00r\00e\00.\00t\00s\00") (data (i32.const 152) "\10\00\00\00\1c\00\00\00\00\00\00\00\00\00\00\00~\00l\00i\00b\00/\00m\00e\00m\00o\00r\00y\00.\00t\00s\00") + (data (i32.const 200) "\10\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00") (table $0 1 funcref) (elem (i32.const 0) $null) (global $~lib/rt/pure/ACYCLIC_FLAG i32 (i32.const 0)) @@ -21,15 +22,17 @@ (global $~lib/rt/pure/CUR (mut i32) (i32.const 0)) (global $~lib/rt/pure/END (mut i32) (i32.const 0)) (global $~lib/rt/pure/ROOTS (mut i32) (i32.const 0)) - (global $~lib/memory/HEAP_BASE i32 (i32.const 196)) + (global $~lib/runtime/RTTI_BASE i32 (i32.const 200)) + (global $~lib/memory/HEAP_BASE i32 (i32.const 336)) (export "memory" (memory $0)) (export "main" (func $assembly/index/main)) - (export "__mm_allocate" (func $~lib/rt/index/__mm_allocate)) - (export "__mm_reallocate" (func $~lib/rt/index/__mm_reallocate)) - (export "__mm_free" (func $~lib/rt/index/__mm_free)) - (export "__gc_retain" (func $~lib/rt/index/__gc_retain)) - (export "__gc_release" (func $~lib/rt/index/__gc_release)) - (export "__gc_collect" (func $~lib/rt/index/__gc_collect)) + (export "__rt_allocate" (func $~lib/rt/index/__rt_allocate)) + (export "__rt_reallocate" (func $~lib/rt/index/__rt_reallocate)) + (export "__rt_free" (func $~lib/rt/index/__rt_free)) + (export "__rt_retain" (func $~lib/rt/index/__rt_retain)) + (export "__rt_release" (func $~lib/rt/index/__rt_release)) + (export "__rt_collect" (func $~lib/rt/index/__rt_collect)) + (export "__rt_typeinfo" (func $~lib/rt/common/__rt_typeinfo)) (func $assembly/index/main (; 1 ;) (type $FUNCSIG$v) global.get $~lib/started i32.eqz @@ -60,7 +63,7 @@ if i32.const 0 i32.const 24 - i32.const 265 + i32.const 256 i32.const 13 call $~lib/builtins/abort unreachable @@ -85,7 +88,7 @@ if i32.const 0 i32.const 24 - i32.const 267 + i32.const 258 i32.const 13 call $~lib/builtins/abort unreachable @@ -137,7 +140,7 @@ if i32.const 0 i32.const 24 - i32.const 280 + i32.const 271 i32.const 13 call $~lib/builtins/abort unreachable @@ -275,7 +278,7 @@ if i32.const 0 i32.const 24 - i32.const 193 + i32.const 184 i32.const 13 call $~lib/builtins/abort unreachable @@ -290,7 +293,7 @@ if i32.const 0 i32.const 24 - i32.const 195 + i32.const 186 i32.const 13 call $~lib/builtins/abort unreachable @@ -389,7 +392,7 @@ if i32.const 0 i32.const 24 - i32.const 216 + i32.const 207 i32.const 15 call $~lib/builtins/abort unreachable @@ -452,7 +455,7 @@ if i32.const 0 i32.const 24 - i32.const 231 + i32.const 222 i32.const 13 call $~lib/builtins/abort unreachable @@ -468,7 +471,7 @@ if i32.const 0 i32.const 24 - i32.const 232 + i32.const 223 i32.const 13 call $~lib/builtins/abort unreachable @@ -525,7 +528,7 @@ if i32.const 0 i32.const 24 - i32.const 248 + i32.const 239 i32.const 13 call $~lib/builtins/abort unreachable @@ -648,7 +651,7 @@ if i32.const 0 i32.const 24 - i32.const 374 + i32.const 365 i32.const 4 call $~lib/builtins/abort unreachable @@ -673,7 +676,7 @@ if i32.const 0 i32.const 24 - i32.const 384 + i32.const 375 i32.const 15 call $~lib/builtins/abort unreachable @@ -704,7 +707,7 @@ if i32.const 0 i32.const 24 - i32.const 396 + i32.const 387 i32.const 4 call $~lib/builtins/abort unreachable @@ -937,7 +940,7 @@ if i32.const 0 i32.const 24 - i32.const 436 + i32.const 427 i32.const 29 call $~lib/builtins/abort unreachable @@ -1031,7 +1034,7 @@ if i32.const 0 i32.const 24 - i32.const 326 + i32.const 317 i32.const 13 call $~lib/builtins/abort unreachable @@ -1096,7 +1099,7 @@ if i32.const 0 i32.const 24 - i32.const 339 + i32.const 330 i32.const 17 call $~lib/builtins/abort unreachable @@ -1214,7 +1217,7 @@ if i32.const 0 i32.const 24 - i32.const 353 + i32.const 344 i32.const 13 call $~lib/builtins/abort unreachable @@ -1325,7 +1328,7 @@ if i32.const 0 i32.const 24 - i32.const 466 + i32.const 457 i32.const 15 call $~lib/builtins/abort unreachable @@ -1343,7 +1346,7 @@ if i32.const 0 i32.const 24 - i32.const 468 + i32.const 459 i32.const 13 call $~lib/builtins/abort unreachable @@ -1366,20 +1369,26 @@ call $~lib/rt/tlsf/prepareBlock local.get $3 ) - (func $~lib/rt/index/__mm_allocate (; 11 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) - (local $1 i32) + (func $~lib/rt/index/__rt_allocate (; 11 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) global.get $~lib/rt/tlsf/ROOT - local.set $1 - local.get $1 + local.set $2 + local.get $2 i32.eqz if call $~lib/rt/tlsf/initializeRoot global.get $~lib/rt/tlsf/ROOT - local.set $1 + local.set $2 end - local.get $1 + local.get $2 local.get $0 call $~lib/rt/tlsf/allocateBlock + local.set $3 + local.get $3 + local.get $1 + i32.store offset=8 + local.get $3 i32.const 16 i32.add ) @@ -1613,7 +1622,7 @@ if i32.const 0 i32.const 24 - i32.const 481 + i32.const 472 i32.const 13 call $~lib/builtins/abort unreachable @@ -1727,13 +1736,13 @@ call $~lib/rt/tlsf/insertBlock local.get $8 ) - (func $~lib/rt/index/__mm_reallocate (; 14 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) + (func $~lib/rt/index/__rt_reallocate (; 14 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) global.get $~lib/rt/tlsf/ROOT i32.eqz if i32.const 0 i32.const 72 - i32.const 21 + i32.const 23 i32.const 13 call $~lib/builtins/abort unreachable @@ -1753,7 +1762,7 @@ if i32.const 0 i32.const 72 - i32.const 22 + i32.const 24 i32.const 2 call $~lib/builtins/abort unreachable @@ -1780,7 +1789,7 @@ if i32.const 0 i32.const 24 - i32.const 519 + i32.const 510 i32.const 2 call $~lib/builtins/abort unreachable @@ -1794,13 +1803,13 @@ local.get $1 call $~lib/rt/tlsf/insertBlock ) - (func $~lib/rt/index/__mm_free (; 16 ;) (type $FUNCSIG$vi) (param $0 i32) + (func $~lib/rt/index/__rt_free (; 16 ;) (type $FUNCSIG$vi) (param $0 i32) global.get $~lib/rt/tlsf/ROOT i32.eqz if i32.const 0 i32.const 72 - i32.const 29 + i32.const 31 i32.const 13 call $~lib/builtins/abort unreachable @@ -1820,7 +1829,7 @@ if i32.const 0 i32.const 72 - i32.const 30 + i32.const 32 i32.const 2 call $~lib/builtins/abort unreachable @@ -1864,7 +1873,7 @@ i32.add i32.store offset=4 ) - (func $~lib/rt/index/__gc_retain (; 18 ;) (type $FUNCSIG$vi) (param $0 i32) + (func $~lib/rt/index/__rt_retain (; 18 ;) (type $FUNCSIG$vi) (param $0 i32) local.get $0 if local.get $0 @@ -2037,7 +2046,7 @@ end end ) - (func $~lib/rt/index/__gc_release (; 25 ;) (type $FUNCSIG$vi) (param $0 i32) + (func $~lib/rt/index/__rt_release (; 25 ;) (type $FUNCSIG$vi) (param $0 i32) local.get $0 if local.get $0 @@ -2300,11 +2309,36 @@ local.get $0 global.set $~lib/rt/pure/CUR ) - (func $~lib/rt/index/__gc_collect (; 31 ;) (type $FUNCSIG$v) + (func $~lib/rt/index/__rt_collect (; 31 ;) (type $FUNCSIG$v) call $~lib/rt/pure/collectCycles ) - (func $start (; 32 ;) (type $FUNCSIG$v) + (func $~lib/rt/common/__rt_typeinfo (; 32 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/runtime/RTTI_BASE + local.set $1 + local.get $0 + i32.eqz + if (result i32) + i32.const 1 + else + local.get $0 + local.get $1 + i32.load + i32.gt_u + end + if (result i32) + unreachable + else + local.get $1 + local.get $0 + i32.const 8 + i32.mul + i32.add + i32.load + end ) - (func $null (; 33 ;) (type $FUNCSIG$v) + (func $start (; 33 ;) (type $FUNCSIG$v) + ) + (func $null (; 34 ;) (type $FUNCSIG$v) ) )