1
0
mirror of https://github.com/fluencelabs/assemblyscript synced 2025-07-03 08:31:53 +00:00

Add initial newArray and getArray helpers to loader

Essentially creates an unmanaged typed array in memory that one can work with and free again respectively obtain from the AS side. No support for GC or generic arrays yet, and is likely to change substentially once WASM GC becomes a thing.
This commit is contained in:
dcodeIO
2018-09-18 15:17:44 +02:00
parent 16d1a833dd
commit 9c770d801e
11 changed files with 132 additions and 9 deletions

@ -17,6 +17,9 @@ function instantiate(module, imports) {
// Instantiate the module and obtain its (flat) exports
var instance = new WebAssembly.Instance(module, imports);
var exports = instance.exports;
var memory_allocate = exports["memory.allocate"];
var memory_fill = exports["memory.fill"];
var memory_free = exports["memory.free"];
// Provide views for all sorts of basic values
var mem, I8, U8, I16, U16, I32, U32, F32, F64, I64, U64;
@ -45,7 +48,7 @@ function instantiate(module, imports) {
/** Allocates a new string in the module's memory and returns its pointer. */
function newString(str) {
var dataLength = str.length;
var ptr = exports["memory.allocate"](4 + (dataLength << 1));
var ptr = memory_allocate(4 + (dataLength << 1));
var dataOffset = (4 + ptr) >>> 1;
checkMem();
U32[ptr >>> 2] = dataLength;
@ -71,6 +74,62 @@ function instantiate(module, imports) {
return parts.join("") + String.fromCharCode.apply(String, U16.subarray(dataOffset, dataOffset + dataRemain));
}
function computeBufferSize(byteLength) {
const HEADER_SIZE = 8;
return 1 << (32 - Math.clz32(byteLength + HEADER_SIZE - 1));
}
/** Creates a new typed array in the module's memory and returns its pointer. */
function newArray(view, length, unsafe) {
var ctor = view.constructor;
if (ctor === Function) { // TypedArray constructor created in memory
ctor = view;
view = null;
} else { // TypedArray instance copied into memory
if (length === undefined) length = view.length;
}
var elementSize = ctor.BYTES_PER_ELEMENT;
if (!elementSize) throw Error("not a typed array");
var byteLength = elementSize * length;
var ptr = memory_allocate(12); // TypedArray header
var buf = memory_allocate(computeBufferSize(byteLength)); // ArrayBuffer
checkMem();
U32[ ptr >>> 2] = buf; // .buffer
U32[(ptr + 4) >>> 2] = 0; // .byteOffset
U32[(ptr + 8) >>> 2] = byteLength; // .byteLength
U32[ buf >>> 2] = byteLength; // .byteLength
U32[(buf + 4) >>> 2] = 0; // 0
if (view) {
new ctor(mem, buf + 8, length).set(view);
if (view.length < length && !unsafe) {
let setLength = elementSize * view.length;
memory_fill(buf + 8 + setLength, 0, byteLength - setLength);
}
} else if (!unsafe) {
memory_fill(buf + 8, 0, byteLength);
}
return ptr;
}
/** Gets a view on a typed array in the module's memory by its pointer. */
function getArray(ctor, ptr) {
var elementSize = ctor.BYTES_PER_ELEMENT;
if (!elementSize) throw Error("not a typed array");
checkMem();
var buf = U32[ ptr >>> 2];
var byteOffset = U32[(ptr + 4) >>> 2];
var byteLength = U32[(ptr + 8) >>> 2];
return new ctor(mem, buf + 8 + byteOffset, (byteLength - byteOffset) / elementSize);
}
/** Frees a typed array in the module's memory. Must not be accessed anymore afterwards. */
function freeArray(ptr) {
checkMem();
var buf = U32[ptr >>> 2];
memory_free(buf);
memory_free(ptr);
}
// Demangle exports and provide the usual utility on the prototype
return demangle(exports, {
get I8() { checkMem(); return I8; },
@ -84,7 +143,10 @@ function instantiate(module, imports) {
get F32() { checkMem(); return F32; },
get F64() { checkMem(); return F64; },
newString,
getString
getString,
newArray,
getArray,
freeArray
});
}