AssemblyScript / assemblyscript

A TypeScript-like language for WebAssembly.
https://www.assemblyscript.org
Apache License 2.0
16.94k stars 664 forks source link

GC assertion using "big" WebAssembly.Memory object #1746

Closed vincent-tr closed 3 years ago

vincent-tr commented 3 years ago

I'm trying to provide a fixed-sized WebAssembly.Memory object, with the larger possible size. I'm expecting to be able to pass an object with 2GB memory, but it seems to fail with object > 1GB.

Here is my use case:

test.ts

export function hello(): string[] {
  const array: string[] = [];
  array.push('hello');
  array.push('world');
  return array;
}

compiled with: ./node_modules/.bin/asc --importMemory test -o test.wasm

main.js

const fs = require("fs");
const loader = require("@assemblyscript/loader");

const KB = 1024;
const MB = KB * 1024;
const GB = MB * 1024;
const PAGE_SIZE = 64 * KB;

main();

async function main() {
  // const pages = (2 * GB) / PAGE_SIZE; -> FAIL
  // const pages = 16385; -> FAIL
  // const pages = 16384; // -> OK, corresponds to 1GB

  console.log(pages, "pages");
  console.log((pages * PAGE_SIZE) / GB, "GB");

  const memory = new WebAssembly.Memory({ initial: pages, maximum: pages });
  const binary = fs.readFileSync("test.wasm");

  const { exports } = await loader.instantiate(binary, { env: { memory } });

  exports.hello();
}

launched with: node main

Got this error if using config > 1GB

Error: abort:  at ~lib/rt/tlsf.ts:239:14
    at abort (/Users/vincent/workspace/stoic/sandbox/as-memory-size/node_modules/@assemblyscript/loader/umd/index.js:78:13)
    at <anonymous>:wasm-function[22]:0x66c
    at <anonymous>:wasm-function[23]:0x8ac
    at <anonymous>:wasm-function[24]:0x9b2
    at <anonymous>:wasm-function[37]:0xf61
    at <anonymous>:wasm-function[41]:0x114b
    at <anonymous>:wasm-function[44]:0x1bd6
    at <anonymous>:wasm-function[60]:0x1f2b
    at hello (<anonymous>:wasm-function[59]:0x1ec1)
    at Object.curr.<computed> [as hello] (/Users/vincent/workspace/stoic/sandbox/as-memory-size/node_modules/@assemblyscript/loader/umd/index.js:502:20)

Note that it seems to be related to the size of the GC area itself: if I use memoryBase = 1GB, it works with a memory object of 2GB.

dcodeIO commented 3 years ago

Good find, thanks! Indeed looks like adding a region of memory that is larger than 1GB + 4B (max. size of a single TLSF block is 1GB - 4B, plus two 4B headers overhead) is missing to split the region prior to inserting it somewhere around here.