Skip to content

Rework loop statement compilation / general cleanup #1046

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Jan 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions bin/asinit
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ console.log([
" TypeScript configuration inheriting recommended AssemblyScript settings.",
"",
colors.cyan(" ./assembly/index.ts"),
" Exemplary entry file being compiled to WebAssembly to get you started.",
" Example entry file being compiled to WebAssembly to get you started.",
"",
colors.cyan(" ./build"),
" Build artifact directory where compiled WebAssembly files are stored.",
Expand All @@ -65,7 +65,7 @@ console.log([
" Main file loading the WebAssembly module and exporting its exports.",
"",
colors.cyan(" ./tests/index.js"),
" Exemplary test to check that your module is indeed working.",
" Example test to check that your module is indeed working.",
"",
colors.cyan(" ./package.json"),
" Package info containing the necessary commands to compile to WebAssembly.",
Expand Down Expand Up @@ -122,7 +122,7 @@ rl.question(colors.white("Do you want to proceed?") + " [Y/n] ", answer => {
" ^ The optimized WebAssembly module using default optimization settings.",
" You can change the optimization settings in '" + colors.cyan("package.json")+ "'.",
"",
"To run the exemplary tests, do:",
"To run the tests, do:",
"",
colors.white(" npm test"),
"",
Expand Down
50 changes: 33 additions & 17 deletions lib/loader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,35 +43,25 @@ Besides demangling classes exported from your entry file to a handy object struc
```

* **__getString**(ptr: `number`): `string`<br />
Reads (copies) the value of a string from the module's memory.
Copies a string's value from the module's memory.

```ts
var str = module.__getString(ptr);
...
```

* **__allocArray**(id: `number`, values: `number[]`): `number`<br />
Allocates a new array in the module's memory and returns a reference (pointer) to it.
Automatically retains interior pointers. The `id` is the unique runtime id of the respective array class. If you are using `Int32Array` for example, the best way to know the id is an `export const INT32ARRAY_ID = idof<Int32Array>()`. When done with the array, make sure to release it.

```ts
var ptr = module.__retain(module.__allocArray(module.INT32ARRAY, [1, 2, 3]));
...
module.__release(ptr);
```
* **__getArrayBuffer**(ptr: `number`): `ArrayBuffer`<br />
Copies an ArrayBuffer's value from the module's memory.

* **__getArray**(ptr: `number`): `number[]`<br />
Reads (copies) the values of an array from the module's memory.
Copies an array's values from the module's memory. Infers the array type from RTTI.

```ts
var arr = module.__getArray(ptr);
...
```

* **__getArrayView**(ptr: `number`): `TypedArray`<br />
Gets a view on the values of an array in the module's memory. This differs from `__getArray` in that the data isn't copied but remains *live* in both directions. That's faster but also unsafe because if the array grows or becomes released, the view will no longer represent the correct memory region and modifying its values in this state will most likely corrupt memory. Use, but use with care.

If the type of the array is known beforehand, the following even faster and even more unsafe helpers can be used that don't do any type checking:
If the type of the array is known beforehand, the following slightly faster helpers that don't infer the type can be used:

**__getInt8Array**(ptr: `number`): `Int8Array`<br />
**__getUint8Array**(ptr: `number`): `Uint8Array`<br />
Expand All @@ -85,8 +75,24 @@ Besides demangling classes exported from your entry file to a handy object struc
**__getFloat32Array**(ptr: `number`): `Float32Array`<br />
**__getFloat64Array**(ptr: `number`): `Float64Array`

* **__getArrayBuffer**(ptr: `number`): `ArrayBuffer`<br />
Reads (copies) the data of an ArrayBuffer from the module's memory.
* **__getArrayView**(ptr: `number`): `TypedArray`<br />
Gets a live view on the values of an array in the module's memory. Infers the array type from RTTI.

This differs from `__getArray` in that the data isn't copied but remains *live* in both directions. That's faster but also unsafe because if the array grows or becomes released, the view will no longer represent the correct memory region and modifying its values in this state will most likely corrupt memory. Use, but use with care.

If the type of the array is known beforehand, the following slightly faster helpers that don't infer the type can be used:

**__getInt8ArrayView**(ptr: `number`): `Int8Array`<br />
**__getUint8ArrayView**(ptr: `number`): `Uint8Array`<br />
**__getUint8ClampedArrayView**(ptr: `number`): `Uint8ClampedArray`<br />
**__getInt16ArrayView**(ptr: `number`): `Int16Array`<br />
**__getUint16ArrayView**(ptr: `number`): `Uint16Array`<br />
**__getInt32ArrayView**(ptr: `number`): `Int32Array`<br />
**__getUint32ArrayView**(ptr: `number`): `Uint32Array`<br />
**__getInt64ArrayView**(ptr: `number`): `BigInt64Array`<br />
**__getUint64ArrayView**(ptr: `number`): `BigUint64Array`<br />
**__getFloat32ArrayView**(ptr: `number`): `Float32Array`<br />
**__getFloat64ArrayView**(ptr: `number`): `Float64Array`

* **__retain**(ptr: `number`): `number`<br />
Retains a reference to a managed object externally, making sure that it doesn't become collected prematurely. Returns the pointer.
Expand All @@ -107,6 +113,16 @@ Besides demangling classes exported from your entry file to a handy object struc
module.__release(ptr);
```

* **__allocArray**(id: `number`, values: `number[]`): `number`<br />
Allocates a new array in the module's memory and returns a reference (pointer) to it.
Automatically retains interior pointers. The `id` is the unique runtime id of the respective array class. If you are using `Int32Array` for example, the best way to know the id is an `export const INT32ARRAY_ID = idof<Int32Array>()`. When done with the array, make sure to release it.

```ts
var ptr = module.__retain(module.__allocArray(module.INT32ARRAY, [1, 2, 3]));
...
module.__release(ptr);
```

* **__instanceof**(ptr: `number`, baseId: `number`): `boolean`<br />
Tests whether an object is an instance of the class represented by the specified base id.

Expand Down
60 changes: 30 additions & 30 deletions lib/loader/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,66 +22,66 @@ interface ASUtil {
/** Allocates a new array in the module's memory and returns a reference (pointer) to it. */
__allocArray(id: number, values: ArrayLike<number>): number;

/** Reads (copies) the value of a string from the module's memory. */
/** Copies a string's value from the module's memory. */
__getString(ptr: number): string;
/** Reads (copies) the values of an array from the module's memory. */
__getArray(ptr: number): number[];
/** Gets a view on the values of an array in the module's memory. */
__getArrayView(ptr: number): ArrayBufferView;
/** Copies an ArrayBuffer's value from the module's memory. */
__getArrayBuffer(ptr: number): ArrayBuffer;

/** Reads (copies) the values of Int8Array from the module's memory. */
/** Copies an array's values from the module's memory. Infers the array type from RTTI. */
__getArray(ptr: number): number[];
/** Copies an Int8Array's values from the module's memory. */
__getInt8Array(ptr: number): Int8Array;
/** Reads (copies) the values of Uint8Array from the module's memory. */
/** Copies an Uint8Array's values from the module's memory. */
__getUint8Array(ptr: number): Uint8Array;
/** Reads (copies) the values of Uint8Array from the module's memory. */
/** Copies an Uint8ClampedArray's values from the module's memory. */
__getUint8ClampedArray(ptr: number): Uint8ClampedArray;
/** Reads (copies) the values of Int16Array from the module's memory. */
/** Copies an Int16Array's values from the module's memory. */
__getInt16Array(ptr: number): Int16Array;
/** Reads (copies) the values of Uint16Array from the module's memory. */
/** Copies an Uint16Array's values from the module's memory. */
__getUint16Array(ptr: number): Uint16Array;
/** Reads (copies) the values of Int32Array from the module's memory. */
/** Copies an Int32Array's values from the module's memory. */
__getInt32Array(ptr: number): Int32Array;
/** Reads (copies) the values of Uint32Array from the module's memory. */
/** Copies an Uint32Array's values from the module's memory. */
__getUint32Array(ptr: number): Uint32Array;
/** Reads (copies) the values of Int32Array from the module's memory. */
/** Copies an Int32Array's values from the module's memory. */
__getInt64Array?(ptr: number): BigInt64Array;
/** Reads (copies) the values of Uint32Array from the module's memory. */
/** Copies an Uint32Array's values from the module's memory. */
__getUint64Array?(ptr: number): BigUint64Array;
/** Reads (copies) the values of Float32Array from the module's memory. */
/** Copies a Float32Array's values from the module's memory. */
__getFloat32Array(ptr: number): Float32Array;
/** Reads (copies) the values of Float64Array from the module's memory. */
/** Copies a Float64Array's values from the module's memory. */
__getFloat64Array(ptr: number): Float64Array;

/** Reads the values of Int8Array from the module's memory. */
/** Gets a live view on an array's values in the module's memory. Infers the array type from RTTI. */
__getArrayView(ptr: number): ArrayBufferView;
/** Gets a live view on an Int8Array's values in the module's memory. */
__getInt8ArrayView(ptr: number): Int8Array;
/** Reads the values of Uint8Array from the module's memory. */
/** Gets a live view on an Uint8Array's values in the module's memory. */
__getUint8ArrayView(ptr: number): Uint8Array;
/** Reads the values of Uint8Array from the module's memory. */
/** Gets a live view on an Uint8ClampedArray's values in the module's memory. */
__getUint8ClampedArrayView(ptr: number): Uint8ClampedArray;
/** Reads the values of Int16Array from the module's memory. */
/** Gets a live view on an Int16Array's values in the module's memory. */
__getInt16ArrayView(ptr: number): Int16Array;
/** Reads the values of Uint16Array from the module's memory. */
/** Gets a live view on an Uint16Array's values in the module's memory. */
__getUint16ArrayView(ptr: number): Uint16Array;
/** Reads the values of Int32Array from the module's memory. */
/** Gets a live view on an Int32Array's values in the module's memory. */
__getInt32ArrayView(ptr: number): Int32Array;
/** Reads the values of Uint32Array from the module's memory. */
/** Gets a live view on an Uint32Array's values in the module's memory. */
__getUint32ArrayView(ptr: number): Uint32Array;
/** Reads the values of Int32Array from the module's memory. */
/** Gets a live view on an Int32Array's values in the module's memory. */
__getInt64ArrayView?(ptr: number): BigInt64Array;
/** Reads the values of Uint32Array from the module's memory. */
/** Gets a live view on an Uint32Array's values in the module's memory. */
__getUint64ArrayView?(ptr: number): BigUint64Array;
/** Reads the values of Float32Array from the module's memory. */
/** Gets a live view on a Float32Array's values in the module's memory. */
__getFloat32ArrayView(ptr: number): Float32Array;
/** Reads the values of Float64Array from the module's memory. */
/** Gets a live view on a Float64Array's values in the module's memory. */
__getFloat64ArrayView(ptr: number): Float64Array;

/** Reads (copies) the data of an ArrayBuffer from the module's memory. */
__getArrayBuffer(ptr: number): ArrayBuffer;
/** Retains a reference to a managed object externally, making sure that it doesn't become collected prematurely. Returns the pointer. */
__retain(ptr: number): number;
/** Releases a previously retained reference to a managed object, allowing the runtime to collect it once its reference count reaches zero. */
__release(ptr: number): void;
/** Resets base pointer to initial offset. Uses only for stub runtime. */
/** Forcefully resets the heap to its initial offset, effectively clearing dynamic memory. Stub runtime only. */
__reset?(): void;
/** Allocates an instance of the class represented by the specified id. */
__alloc(size: number, id: number): number;
Expand Down
39 changes: 15 additions & 24 deletions lib/loader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ function postInstantiate(baseModule, instance) {

baseModule.__allocArray = __allocArray;

/** Gets a view on the values of an array in the module's memory. */
/** Gets a live view on an array's values in the module's memory. Infers the array type from RTTI. */
function __getArrayView(arr) {
const U32 = new Uint32Array(memory.buffer);
const id = U32[arr + ID_OFFSET >>> 2];
Expand All @@ -197,7 +197,7 @@ function postInstantiate(baseModule, instance) {

baseModule.__getArrayView = __getArrayView;

/** Reads (copies) the values of an array from the module's memory. */
/** Copies an array's values from the module's memory. Infers the array type from RTTI. */
function __getArray(arr) {
const input = __getArrayView(arr);
const len = input.length;
Expand All @@ -208,7 +208,7 @@ function postInstantiate(baseModule, instance) {

baseModule.__getArray = __getArray;

/** Reads (copies) the data of an ArrayBuffer from the module's memory. */
/** Copies an ArrayBuffer's value from the module's memory. */
function __getArrayBuffer(ptr) {
const buffer = memory.buffer;
const length = new Uint32Array(buffer)[ptr + SIZE_OFFSET >>> 2];
Expand All @@ -217,50 +217,41 @@ function postInstantiate(baseModule, instance) {

baseModule.__getArrayBuffer = __getArrayBuffer;

/** Copies a typed array's values from the module's memory. */
function getTypedArray(Type, alignLog2, ptr) {
return new Type(getTypedArrayView(Type, alignLog2, ptr));
}

/** Gets a live view on a typed array's values in the module's memory. */
function getTypedArrayView(Type, alignLog2, ptr) {
const buffer = memory.buffer;
const U32 = new Uint32Array(buffer);
const bufPtr = U32[ptr + ARRAYBUFFERVIEW_DATASTART_OFFSET >>> 2];
return new Type(buffer, bufPtr, U32[bufPtr + SIZE_OFFSET >>> 2] >>> alignLog2);
}

function getTypedArray(Type, alignLog2, ptr) {
return new Type(getTypedArrayView(Type, alignLog2, ptr));
}

/** Gets a view on the values of a known-to-be Int8Array in the module's memory. */
baseModule.__getInt8Array = getTypedArray.bind(null, Int8Array, 0);
baseModule.__getInt8ArrayView = getTypedArrayView.bind(null, Int8Array, 0);
/** Gets a view on the values of a known-to-be Uint8Array in the module's memory. */
baseModule.__getUint8Array = getTypedArray.bind(null, Uint8Array, 0);
baseModule.__getUint8ArrayView = getTypedArrayView.bind(null, Uint8Array, 0);
/** Gets a view on the values of a known-to-be Uint8ClampedArray in the module's memory. */
baseModule.__getUint8ClampedArray = getTypedArray.bind(null, Uint8ClampedArray, 0);
baseModule.__getUint8ClampedArrayView = getTypedArrayView.bind(null, Uint8ClampedArray, 0);
/** Gets a view on the values of a known-to-be Int16Array in the module's memory. */
baseModule.__getInt16Array = getTypedArray.bind(null, Int16Array, 1);
baseModule.__getInt16ArrayView = getTypedArrayView.bind(null, Int16Array, 1);
/** Gets a view on the values of a known-to-be Uint16Array in the module's memory. */
baseModule.__getUint16Array = getTypedArray.bind(null, Uint16Array, 1);
baseModule.__getUint16ArrayView = getTypedArrayView.bind(null, Uint16Array, 1);
/** Gets a view on the values of a known-to-be Int32Array in the module's memory. */
baseModule.__getInt32Array = getTypedArray.bind(null, Int32Array, 2);
baseModule.__getInt32ArrayView = getTypedArrayView.bind(null, Int32Array, 2);
/** Gets a view on the values of a known-to-be Uint32Array in the module's memory. */
baseModule.__getUint32Array = getTypedArray.bind(null, Uint32Array, 2);
baseModule.__getUint32ArrayView = getTypedArrayView.bind(null, Uint32Array, 2);
if (BIGINT) {
/** Gets a view on the values of a known-to-be-Int64Array in the module's memory. */
baseModule.__getInt64Array = getTypedArray.bind(null, BigInt64Array, 3);
baseModule.__getInt64ArrayView = getTypedArrayView.bind(null, BigInt64Array, 3);
/** Gets a view on the values of a known-to-be-Uint64Array in the module's memory. */
baseModule.__getUint64Array = getTypedArray.bind(null, BigUint64Array, 3);
baseModule.__getUint64ArrayView = getTypedArrayView.bind(null, BigUint64Array, 3);
}
/** Gets a view on the values of a known-to-be Float32Array in the module's memory. */
baseModule.__getFloat32Array = getTypedArray.bind(null, Float32Array, 2);
baseModule.__getFloat32ArrayView = getTypedArrayView.bind(null, Float32Array, 2);
/** Gets a view on the values of a known-to-be Float64Array in the module's memory. */
baseModule.__getFloat64Array = getTypedArray.bind(null, Float64Array, 3);
baseModule.__getFloat64ArrayView = getTypedArrayView.bind(null, Float64Array, 3);

Expand All @@ -286,9 +277,9 @@ function postInstantiate(baseModule, instance) {
}

/** Wraps a WebAssembly function while also taking care of variable arguments. */
function wrapFunction(fn, setargc) {
function wrapFunction(fn, argumentsLength) {
var wrap = (...args) => {
setargc(args.length);
if (argumentsLength) argumentsLength.value = args.length;
return fn(...args);
}
wrap.original = fn;
Expand Down Expand Up @@ -351,7 +342,7 @@ exports.instantiateStreaming = instantiateStreaming;
/** Demangles an AssemblyScript module's exports to a friendly object structure. */
function demangle(exports, baseModule) {
var module = baseModule ? Object.create(baseModule) : {};
var setargc = exports["__setargc"] || function() {};
var argumentsLength = exports["__argumentsLength"];
function hasOwnProperty(elem, prop) {
return Object.prototype.hasOwnProperty.call(elem, prop);
}
Expand Down Expand Up @@ -401,11 +392,11 @@ function demangle(exports, baseModule) {
}
} else {
if (name === 'constructor') {
curr[name] = wrapFunction(elem, setargc);
curr[name] = wrapFunction(elem, argumentsLength);
} else { // for methods
Object.defineProperty(curr, name, {
value: function (...args) {
setargc(args.length);
if (argumentsLength) argumentsLength.value = args.length;
return elem(this[THIS], ...args);
}
});
Expand All @@ -421,7 +412,7 @@ function demangle(exports, baseModule) {
});
}
} else if (typeof elem === "function") {
curr[name] = wrapFunction(elem, setargc);
curr[name] = wrapFunction(elem, argumentsLength);
} else {
curr[name] = elem;
}
Expand Down
Binary file modified lib/loader/tests/build/untouched.wasm
Binary file not shown.
Loading