mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-05-01 09:52:19 +00:00
monkey-patch loader
This commit is contained in:
parent
71ea61e099
commit
81c212b208
@ -1,11 +1,15 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
/** Size of the runtime header, in bytes. */
|
/** Relative header `id` offset. */
|
||||||
const HEADER_SIZE = 16;
|
const ID_OFFSET = -8;
|
||||||
/** Runtime header offset of `classId`. */
|
/** Relative header `size` offset. */
|
||||||
const CLASSID_OFFSET = -HEADER_SIZE;
|
const SIZE_OFFSET = -4;
|
||||||
/** Runtime header offset of `payloadLength`. */
|
|
||||||
const PAYLOADLENGTH_OFFSET = -HEADER_SIZE + 4;
|
/** Unique runtime id of an `ArrayBuffer`. */
|
||||||
|
const ARRAYBUFFER_ID = 0;
|
||||||
|
/** Unique runtime id of a `String`. */
|
||||||
|
const STRING_ID = 1;
|
||||||
|
|
||||||
/** Whether BigInt arrays are supported. */
|
/** Whether BigInt arrays are supported. */
|
||||||
const SUPPORTS_BIGINT = typeof BigUint64Array !== "undefined";
|
const SUPPORTS_BIGINT = typeof BigUint64Array !== "undefined";
|
||||||
/** Unique symbol for memoized 'this'. */
|
/** Unique symbol for memoized 'this'. */
|
||||||
@ -13,19 +17,18 @@ const THIS = Symbol();
|
|||||||
|
|
||||||
/** Gets a string from an U32 and an U16 view on a memory. */
|
/** Gets a string from an U32 and an U16 view on a memory. */
|
||||||
function getStringImpl(U32, U16, ptr) {
|
function getStringImpl(U32, U16, ptr) {
|
||||||
var size32 = U32[(ptr + PAYLOADLENGTH_OFFSET) >>> 2];
|
var length = U32[(ptr + SIZE_OFFSET) >>> 2] >>> 1;
|
||||||
var offset16 = ptr >>> 1;
|
var offset = ptr >>> 1;
|
||||||
var remain32 = size32;
|
|
||||||
var parts = [];
|
var parts = [];
|
||||||
const chunkSize = 1024;
|
const chunkSize = 1024;
|
||||||
while (remain32 > chunkSize) {
|
while (length > chunkSize) {
|
||||||
let last = U16[offset16 + chunkSize - 1];
|
let last = U16[offset + chunkSize - 1];
|
||||||
let size = last >= 0xD800 && last < 0xDC00 ? chunkSize - 1 : chunkSize;
|
let size = last >= 0xD800 && last < 0xDC00 ? chunkSize - 1 : chunkSize;
|
||||||
let part = U16.subarray(offset16, offset16 += size);
|
let part = U16.subarray(offset, offset += size);
|
||||||
parts.push(String.fromCharCode.apply(String, part));
|
parts.push(String.fromCharCode.apply(String, part));
|
||||||
remain32 -= size;
|
length -= size;
|
||||||
}
|
}
|
||||||
return parts.join("") + String.fromCharCode.apply(String, U16.subarray(offset16, offset16 + remain32));
|
return parts.join("") + String.fromCharCode.apply(String, U16.subarray(offset, offset + length));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Prepares the base module prior to instantiation. */
|
/** Prepares the base module prior to instantiation. */
|
||||||
@ -58,11 +61,11 @@ function preInstantiate(imports) {
|
|||||||
function postInstantiate(baseModule, instance) {
|
function postInstantiate(baseModule, instance) {
|
||||||
var rawExports = instance.exports;
|
var rawExports = instance.exports;
|
||||||
var memory = rawExports.memory;
|
var memory = rawExports.memory;
|
||||||
var memory_allocate = rawExports["memory.allocate"];
|
var alloc = rawExports["__alloc"];
|
||||||
|
var free = rawExports["__free"];
|
||||||
|
var setargc = rawExports["__setargc"] || function() {};
|
||||||
var memory_fill = rawExports["memory.fill"];
|
var memory_fill = rawExports["memory.fill"];
|
||||||
var memory_free = rawExports["memory.free"];
|
|
||||||
var table = rawExports.table;
|
var table = rawExports.table;
|
||||||
var setargc = rawExports["$.setArgc"] || function() {};
|
|
||||||
|
|
||||||
// Provide views for all sorts of basic values
|
// Provide views for all sorts of basic values
|
||||||
var buffer, I8, U8, I16, U16, I32, U32, F32, F64, I64, U64;
|
var buffer, I8, U8, I16, U16, I32, U32, F32, F64, I64, U64;
|
||||||
@ -90,12 +93,10 @@ function postInstantiate(baseModule, instance) {
|
|||||||
|
|
||||||
/** Allocates a new string in the module's memory and returns its pointer. */
|
/** Allocates a new string in the module's memory and returns its pointer. */
|
||||||
function newString(str) {
|
function newString(str) {
|
||||||
var dataLength = str.length;
|
var length = str.length;
|
||||||
var ptr = memory_allocate(4 + (dataLength << 1));
|
var ptr = alloc(length << 1, STRING_ID);
|
||||||
var dataOffset = (4 + ptr) >>> 1;
|
|
||||||
checkMem();
|
checkMem();
|
||||||
U32[ptr >>> 2] = dataLength;
|
for (let i = 0, j = ptr >>> 1; i < length; ++i) U16[j + i] = str.charCodeAt(i);
|
||||||
for (let i = 0; i < dataLength; ++i) U16[dataOffset + i] = str.charCodeAt(i);
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,88 +110,88 @@ function postInstantiate(baseModule, instance) {
|
|||||||
|
|
||||||
baseModule.getString = getString;
|
baseModule.getString = getString;
|
||||||
|
|
||||||
function computeBufferSize(byteLength) {
|
// function computeBufferSize(byteLength) {
|
||||||
const HEADER_SIZE = 8;
|
// const HEADER_SIZE = 8;
|
||||||
return 1 << (32 - Math.clz32(byteLength + HEADER_SIZE - 1));
|
// return 1 << (32 - Math.clz32(byteLength + HEADER_SIZE - 1));
|
||||||
}
|
// }
|
||||||
|
|
||||||
/** Creates a new typed array in the module's memory and returns its pointer. */
|
// /** Creates a new typed array in the module's memory and returns its pointer. */
|
||||||
function newArray(view, length, unsafe) {
|
// function newArray(view, length, unsafe) {
|
||||||
var ctor = view.constructor;
|
// var ctor = view.constructor;
|
||||||
if (ctor === Function) { // TypedArray constructor created in memory
|
// if (ctor === Function) { // TypedArray constructor created in memory
|
||||||
ctor = view;
|
// ctor = view;
|
||||||
view = null;
|
// view = null;
|
||||||
} else { // TypedArray instance copied into memory
|
// } else { // TypedArray instance copied into memory
|
||||||
if (length === undefined) length = view.length;
|
// if (length === undefined) length = view.length;
|
||||||
}
|
// }
|
||||||
var elementSize = ctor.BYTES_PER_ELEMENT;
|
// var elementSize = ctor.BYTES_PER_ELEMENT;
|
||||||
if (!elementSize) throw Error("not a typed array");
|
// if (!elementSize) throw Error("not a typed array");
|
||||||
var byteLength = elementSize * length;
|
// var byteLength = elementSize * length;
|
||||||
var ptr = memory_allocate(12); // TypedArray header
|
// var ptr = alloc(12); // TypedArray header
|
||||||
var buf = memory_allocate(computeBufferSize(byteLength)); // ArrayBuffer
|
// var buf = alloc(computeBufferSize(byteLength)); // ArrayBuffer
|
||||||
checkMem();
|
// checkMem();
|
||||||
U32[ ptr >>> 2] = buf; // .buffer
|
// U32[ ptr >>> 2] = buf; // .buffer
|
||||||
U32[(ptr + 4) >>> 2] = 0; // .byteOffset
|
// U32[(ptr + 4) >>> 2] = 0; // .byteOffset
|
||||||
U32[(ptr + 8) >>> 2] = byteLength; // .byteLength
|
// U32[(ptr + 8) >>> 2] = byteLength; // .byteLength
|
||||||
U32[ buf >>> 2] = byteLength; // .byteLength
|
// U32[ buf >>> 2] = byteLength; // .byteLength
|
||||||
U32[(buf + 4) >>> 2] = 0; // 0
|
// U32[(buf + 4) >>> 2] = 0; // 0
|
||||||
if (view) {
|
// if (view) {
|
||||||
new ctor(buffer, buf + 8, length).set(view);
|
// new ctor(buffer, buf + 8, length).set(view);
|
||||||
if (view.length < length && !unsafe) {
|
// if (view.length < length && !unsafe) {
|
||||||
let setLength = elementSize * view.length;
|
// let setLength = elementSize * view.length;
|
||||||
memory_fill(buf + 8 + setLength, 0, byteLength - setLength);
|
// memory_fill(buf + 8 + setLength, 0, byteLength - setLength);
|
||||||
}
|
// }
|
||||||
} else if (!unsafe) {
|
// } else if (!unsafe) {
|
||||||
memory_fill(buf + 8, 0, byteLength);
|
// memory_fill(buf + 8, 0, byteLength);
|
||||||
}
|
// }
|
||||||
return ptr;
|
// return ptr;
|
||||||
}
|
// }
|
||||||
|
|
||||||
baseModule.newArray = newArray;
|
// baseModule.newArray = newArray;
|
||||||
|
|
||||||
/** Gets a view on a typed array in the module's memory by its pointer. */
|
// /** Gets a view on a typed array in the module's memory by its pointer. */
|
||||||
function getArray(ctor, ptr) {
|
// function getArray(ctor, ptr) {
|
||||||
var elementSize = ctor.BYTES_PER_ELEMENT;
|
// var elementSize = ctor.BYTES_PER_ELEMENT;
|
||||||
if (!elementSize) throw Error("not a typed array");
|
// if (!elementSize) throw Error("not a typed array");
|
||||||
checkMem();
|
// checkMem();
|
||||||
var buf = U32[ ptr >>> 2];
|
// var buf = U32[ ptr >>> 2];
|
||||||
var byteOffset = U32[(ptr + 4) >>> 2];
|
// var byteOffset = U32[(ptr + 4) >>> 2];
|
||||||
var byteLength = U32[(ptr + 8) >>> 2];
|
// var byteLength = U32[(ptr + 8) >>> 2];
|
||||||
return new ctor(buffer, buf + 8 + byteOffset, (byteLength - byteOffset) / elementSize);
|
// return new ctor(buffer, buf + 8 + byteOffset, (byteLength - byteOffset) / elementSize);
|
||||||
}
|
// }
|
||||||
|
|
||||||
baseModule.getArray = getArray;
|
// baseModule.getArray = getArray;
|
||||||
|
|
||||||
/** Frees a typed array in the module's memory. Must not be accessed anymore afterwards. */
|
// /** Frees a typed array in the module's memory. Must not be accessed anymore afterwards. */
|
||||||
function freeArray(ptr) {
|
// function freeArray(ptr) {
|
||||||
checkMem();
|
// checkMem();
|
||||||
var buf = U32[ptr >>> 2];
|
// var buf = U32[ptr >>> 2];
|
||||||
memory_free(buf);
|
// free(buf);
|
||||||
memory_free(ptr);
|
// free(ptr);
|
||||||
}
|
// }
|
||||||
|
|
||||||
baseModule.freeArray = freeArray;
|
// baseModule.freeArray = freeArray;
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Creates a new function in the module's table and returns its pointer. Note that only actual
|
// * Creates a new function in the module's table and returns its pointer. Note that only actual
|
||||||
* WebAssembly functions, i.e. as exported by the module, are supported.
|
// * WebAssembly functions, i.e. as exported by the module, are supported.
|
||||||
*/
|
// */
|
||||||
function newFunction(fn) {
|
// function newFunction(fn) {
|
||||||
if (typeof fn.original === "function") fn = fn.original;
|
// if (typeof fn.original === "function") fn = fn.original;
|
||||||
var index = table.length;
|
// var index = table.length;
|
||||||
table.grow(1);
|
// table.grow(1);
|
||||||
table.set(index, fn);
|
// table.set(index, fn);
|
||||||
return index;
|
// return index;
|
||||||
}
|
// }
|
||||||
|
|
||||||
baseModule.newFunction = newFunction;
|
// baseModule.newFunction = newFunction;
|
||||||
|
|
||||||
/** Gets a function by its pointer. */
|
// /** Gets a function by its pointer. */
|
||||||
function getFunction(ptr) {
|
// function getFunction(ptr) {
|
||||||
return wrapFunction(table.get(ptr), setargc);
|
// return wrapFunction(table.get(ptr), setargc);
|
||||||
}
|
// }
|
||||||
|
|
||||||
baseModule.getFunction = getFunction;
|
// baseModule.getFunction = getFunction;
|
||||||
|
|
||||||
// Pull basic exports to baseModule so code in preInstantiate can use them
|
// Pull basic exports to baseModule so code in preInstantiate can use them
|
||||||
baseModule.memory = baseModule.memory || memory;
|
baseModule.memory = baseModule.memory || memory;
|
||||||
@ -253,7 +254,7 @@ exports.instantiateStreaming = instantiateStreaming;
|
|||||||
/** Demangles an AssemblyScript module's exports to a friendly object structure. */
|
/** Demangles an AssemblyScript module's exports to a friendly object structure. */
|
||||||
function demangle(exports, baseModule) {
|
function demangle(exports, baseModule) {
|
||||||
var module = baseModule ? Object.create(baseModule) : {};
|
var module = baseModule ? Object.create(baseModule) : {};
|
||||||
var setargc = exports[".setargc"] || function() {};
|
var setargc = exports["__setargc"] || function() {};
|
||||||
function hasOwnProperty(elem, prop) {
|
function hasOwnProperty(elem, prop) {
|
||||||
return Object.prototype.hasOwnProperty.call(elem, prop);
|
return Object.prototype.hasOwnProperty.call(elem, prop);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import "allocator/tlsf";
|
|
||||||
|
|
||||||
export { memory };
|
export { memory };
|
||||||
|
|
||||||
export const COLOR: string = "red";
|
export const COLOR: string = "red";
|
||||||
@ -39,10 +37,6 @@ export class Car {
|
|||||||
this.doorsOpen = false;
|
this.doorsOpen = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose(): void {
|
|
||||||
memory.free(changetype<usize>(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sum(arr: Int32Array): i32 {
|
export function sum(arr: Int32Array): i32 {
|
||||||
|
Binary file not shown.
@ -21,7 +21,7 @@ assert(proto.F64 instanceof Float64Array);
|
|||||||
|
|
||||||
// should export memory
|
// should export memory
|
||||||
assert(module.memory instanceof WebAssembly.Memory);
|
assert(module.memory instanceof WebAssembly.Memory);
|
||||||
assert(typeof module.memory.free === "function");
|
assert(typeof module.memory.copy === "function");
|
||||||
|
|
||||||
// should be able to get an exported string
|
// should be able to get an exported string
|
||||||
assert.strictEqual(module.getString(module.COLOR), "red");
|
assert.strictEqual(module.getString(module.COLOR), "red");
|
||||||
@ -33,17 +33,17 @@ assert.strictEqual(module.getString(ptr), str);
|
|||||||
assert.strictEqual(module.strlen(ptr), str.length);
|
assert.strictEqual(module.strlen(ptr), str.length);
|
||||||
|
|
||||||
// should be able to allocate a typed array and sum up its values
|
// should be able to allocate a typed array and sum up its values
|
||||||
var arr = [1, 2, 3, 4, 5, 0x7fffffff];
|
// var arr = [1, 2, 3, 4, 5, 0x7fffffff];
|
||||||
ptr = module.newArray(new Int32Array(arr));
|
// ptr = module.newArray(new Int32Array(arr));
|
||||||
assert.strictEqual(module.sum(ptr), arr.reduce((a, b) => a + b, 0) | 0);
|
// assert.strictEqual(module.sum(ptr), arr.reduce((a, b) => a + b, 0) | 0);
|
||||||
|
|
||||||
// should be able to get a view on an internal typed array
|
// should be able to get a view on an internal typed array
|
||||||
assert.deepEqual(module.getArray(Int32Array, ptr), arr);
|
// assert.deepEqual(module.getArray(Int32Array, ptr), arr);
|
||||||
|
|
||||||
// should be able to free and reuse the space of an internal typed array
|
// should be able to free and reuse the space of an internal typed array
|
||||||
module.freeArray(ptr);
|
// module.freeArray(ptr);
|
||||||
var ptr2 = module.newArray(new Int32Array(arr));
|
// var ptr2 = module.newArray(new Int32Array(arr));
|
||||||
assert.strictEqual(ptr, ptr2);
|
// assert.strictEqual(ptr, ptr2);
|
||||||
|
|
||||||
// should be able to just call a function with variable arguments
|
// should be able to just call a function with variable arguments
|
||||||
assert.strictEqual(module.varadd(), 3);
|
assert.strictEqual(module.varadd(), 3);
|
||||||
@ -51,14 +51,14 @@ assert.strictEqual(module.varadd(2, 3), 5);
|
|||||||
assert.strictEqual(module.varadd(2), 4);
|
assert.strictEqual(module.varadd(2), 4);
|
||||||
|
|
||||||
// should be able to get a function from the table and just call it with variable arguments
|
// should be able to get a function from the table and just call it with variable arguments
|
||||||
var fn = module.getFunction(module.varadd_ptr);
|
// var fn = module.getFunction(module.varadd_ptr);
|
||||||
assert.strictEqual(fn(), 3);
|
// assert.strictEqual(fn(), 3);
|
||||||
assert.strictEqual(fn(2, 3), 5);
|
// assert.strictEqual(fn(2, 3), 5);
|
||||||
assert.strictEqual(fn(2), 4);
|
// assert.strictEqual(fn(2), 4);
|
||||||
|
|
||||||
// should be able to create a new function and call it from WASM
|
// should be able to create a new function and call it from WASM
|
||||||
ptr = module.newFunction(module.varadd);
|
// ptr = module.newFunction(module.varadd);
|
||||||
assert.strictEqual(module.calladd(ptr, 2, 3), 5);
|
// assert.strictEqual(module.calladd(ptr, 2, 3), 5);
|
||||||
|
|
||||||
// should be able to use a class
|
// should be able to use a class
|
||||||
var car = new module.Car(5);
|
var car = new module.Car(5);
|
||||||
|
@ -6489,7 +6489,7 @@ export class Compiler extends DiagnosticEmitter {
|
|||||||
module.createGetLocal(0, NativeType.I32)
|
module.createGetLocal(0, NativeType.I32)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
module.addFunctionExport(BuiltinSymbols.setargc, "$.setArgc");
|
module.addFunctionExport(BuiltinSymbols.setargc, "__setargc");
|
||||||
}
|
}
|
||||||
return BuiltinSymbols.setargc;
|
return BuiltinSymbols.setargc;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
(global $exports/vehicles.Car i32 (i32.const 4))
|
(global $exports/vehicles.Car i32 (i32.const 4))
|
||||||
(export "memory" (memory $0))
|
(export "memory" (memory $0))
|
||||||
(export "add" (func $exports/add))
|
(export "add" (func $exports/add))
|
||||||
(export "$.setArgc" (func $~lib/setargc))
|
(export "__setargc" (func $~lib/setargc))
|
||||||
(export "subOpt" (func $exports/subOpt|trampoline))
|
(export "subOpt" (func $exports/subOpt|trampoline))
|
||||||
(export "math.sub" (func $exports/subOpt))
|
(export "math.sub" (func $exports/subOpt))
|
||||||
(export "Animal.CAT" (global $exports/Animal.CAT))
|
(export "Animal.CAT" (global $exports/Animal.CAT))
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
(global $exports/vehicles.Car i32 (i32.const 4))
|
(global $exports/vehicles.Car i32 (i32.const 4))
|
||||||
(export "memory" (memory $0))
|
(export "memory" (memory $0))
|
||||||
(export "add" (func $exports/add))
|
(export "add" (func $exports/add))
|
||||||
(export "$.setArgc" (func $~lib/setargc))
|
(export "__setargc" (func $~lib/setargc))
|
||||||
(export "subOpt" (func $exports/subOpt|trampoline))
|
(export "subOpt" (func $exports/subOpt|trampoline))
|
||||||
(export "math.sub" (func $exports/math.sub))
|
(export "math.sub" (func $exports/math.sub))
|
||||||
(export "Animal.CAT" (global $exports/Animal.CAT))
|
(export "Animal.CAT" (global $exports/Animal.CAT))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user