more loader updates

This commit is contained in:
dcode 2019-05-24 20:31:52 +02:00
parent 7cd04b65ef
commit a6896d7bc2
12 changed files with 225 additions and 141 deletions

View File

@ -61,32 +61,19 @@ Instances are automatically populated with useful utility:
A 64-bit float view on the memory. A 64-bit float view on the memory.
* **newString**(str: `string`): `number`<br /> * **newString**(str: `string`): `number`<br />
Allocates a new string in the module's memory and returns its pointer.<sup>2</sup> Allocates a new string in the module's memory and returns its retained pointer. When done with the string, make sure to `Module#__release` it.
* **getString**(ptr: `number`): `string`<br /> * **getString**(ptr: `number`): `string`<br />
Gets a string from the module's memory by its pointer. Reads a string from the module's memory by its pointer.
* **newArray**(view: `TypedArray`, length?: `number`, unsafe?: `boolean`): `number`<br /> * **newArray**(id: `number`, values: `number[]`): `number`<br />
Copies a typed array into the module's memory and returns its pointer.<sup>2</sup> Allocates a new array in the module's memory and returns its retained pointer.
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 relevant value is an `export const INT32ARRAY_ID = idof<Int32Array>()`. When done with the array, make sure to `Module#__release` it.
* **newArray**(ctor: `TypedArrayConstructor`, length: `number`, unsafe?: `boolean`): `number`<br /> * **getArray**(ptr: `number`): `number[]`<br />
Creates a typed array in the module's memory and returns its pointer.<sup>2</sup> Gets the values of an array in the module's memory by its pointer.
* **getArray**(ctor: `TypedArrayConstructor`, ptr: `number`): `TypedArray`<br /> <sup>1</sup> This feature has not yet landed in any VM as of this writing.
Gets a view on a typed array in the module's memory by its pointer.
* **freeArray**(ptr: `number`): `void`<br />
Frees a typed array in the module's memory. Must not be accessed anymore afterwards.
* **getFunction**(ptr: `number`): `function`<br />
Gets a function by its pointer.
* **newFunction**(fn: `function`): `number`<br />
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.
<sup>1</sup> This feature has not yet landed in any VM as of this writing.<br />
<sup>2</sup> Requires that memory utilities have been exported through `export { memory }` within the entry file.
Examples Examples
-------- --------
@ -141,7 +128,11 @@ Strings and arrays cannot yet flow in and out of WebAssembly naturally, hence it
var str = "Hello world!"; var str = "Hello world!";
var ptr = module.newString(str); var ptr = module.newString(str);
// ... do something with ptr, i.e. call a WebAssembly export ... // do something with ptr, i.e. call a WebAssembly export
...
// when done, allow the runtime to collect it
module.__release(ptr);
``` ```
Similarly, when a string or array is returned from a WebAssembly function, a reference (pointer) is received on the JS side and the `getString` and `getArray` helpers can be used to obtain their values: Similarly, when a string or array is returned from a WebAssembly function, a reference (pointer) is received on the JS side and the `getString` and `getArray` helpers can be used to obtain their values:

View File

@ -1,18 +1,32 @@
"use strict"; "use strict";
/** Relative header `id` offset. */ // Runtime header offsets
const ID_OFFSET = -8; const ID_OFFSET = -8;
/** Relative header `size` offset. */
const SIZE_OFFSET = -4; const SIZE_OFFSET = -4;
/** Unique runtime id of an `ArrayBuffer`. */ // Runtime ids
const ARRAYBUFFER_ID = 0; const ARRAYBUFFER_ID = 0;
/** Unique runtime id of a `String`. */
const STRING_ID = 1; const STRING_ID = 1;
const ARRAYBUFFERVIEW_ID = 2;
/** Whether BigInt arrays are supported. */ // Runtime type information
const SUPPORTS_BIGINT = typeof BigUint64Array !== "undefined"; const ARRAY = 1 << 0;
/** Unique symbol for memoized 'this'. */ const SET = 1 << 1;
const MAP = 1 << 2;
const VAL_ALIGN = 1 << 4;
const VAL_NULLABLE = 1 << 9;
const VAL_MANAGED = 1 << 10;
const KEY_ALIGN = 1 << 11;
const KEY_NULLABLE = 1 << 16;
const KEY_MANAGED = 1 << 17;
// ArrayBufferView layout
const ABV_BUFFER_OFFSET = 0;
const ABV_DATASTART_OFFSET = 4;
const ABV_DATALENGTH_OFFSET = 8;
const ABV_SIZE = 12;
const BIGINT = typeof BigUint64Array !== "undefined";
const THIS = Symbol(); 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. */
@ -61,11 +75,10 @@ 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 alloc = rawExports["__alloc"];
var free = rawExports["__free"];
var setargc = rawExports["__setargc"] || function() {};
var memory_fill = rawExports["memory.fill"];
var table = rawExports.table; var table = rawExports.table;
var alloc = rawExports["__alloc"];
var retain = rawExports["__retain"];
var rtti = rawExports["__rtti"] | 0;
// 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;
@ -81,7 +94,7 @@ function postInstantiate(baseModule, instance) {
U16 = new Uint16Array(buffer); U16 = new Uint16Array(buffer);
I32 = new Int32Array(buffer); I32 = new Int32Array(buffer);
U32 = new Uint32Array(buffer); U32 = new Uint32Array(buffer);
if (SUPPORTS_BIGINT) { if (BIGINT) {
I64 = new BigInt64Array(buffer); I64 = new BigInt64Array(buffer);
U64 = new BigUint64Array(buffer); U64 = new BigUint64Array(buffer);
} }
@ -91,107 +104,95 @@ function postInstantiate(baseModule, instance) {
} }
checkMem(); checkMem();
/** Allocates a new string in the module's memory and returns its pointer. */ /** Gets the runtime type info for the given id. */
function getInfo(id) {
const count = U32[rtti >>> 2];
if ((id >>>= 0) >= count) throw Error("invalid id: " + id);
return U32[(rtti + 4 >>> 2) + id * 2];
}
/** Gets the runtime base id for the given id. */
function getBase(id) {
const count = U32[rtti >>> 2];
if ((id >>>= 0) >= count) throw Error("invalid id: " + id);
return U32[(rtti + 4 >>> 2) + id * 2 + 1];
}
/** Gets the runtime alignment of a collection's values or keys. */
function getAlign(which, info) {
return 31 - Math.clz32((info / which) & 31);
}
/** Allocates a new string in the module's memory and returns its retained pointer. */
function newString(str) { function newString(str) {
var length = str.length; const length = str.length;
var ptr = alloc(length << 1, STRING_ID); const ptr = alloc(length << 1, STRING_ID);
checkMem(); checkMem();
for (let i = 0, j = ptr >>> 1; i < length; ++i) U16[j + i] = str.charCodeAt(i); for (let i = 0, j = ptr >>> 1; i < length; ++i) U16[j + i] = str.charCodeAt(i);
return ptr; return retain(ptr);
} }
baseModule.newString = newString; baseModule.newString = newString;
/** Gets a string from the module's memory by its pointer. */ /** Reads a string from the module's memory by its pointer. */
function getString(ptr) { function getString(ptr) {
checkMem(); checkMem();
const id = U32[ptr + ID_OFFSET >>> 2];
if (id !== STRING_ID) throw Error("not a string: " + ptr);
return getStringImpl(U32, U16, ptr); return getStringImpl(U32, U16, ptr);
} }
baseModule.getString = getString; baseModule.getString = getString;
// function computeBufferSize(byteLength) { /** Allocates a new array in the module's memory and returns its retained pointer. */
// const HEADER_SIZE = 8; function newArray(id, values) {
// return 1 << (32 - Math.clz32(byteLength + HEADER_SIZE - 1)); const info = getInfo(id);
// } if (!(info & ARRAY)) throw Error("not an array: " + id + " @ " + info);
const align = getAlign(VAL_ALIGN, info);
const length = values.length;
const buf = alloc(length << align, ARRAYBUFFER_ID);
const arr = alloc(ABV_SIZE, id);
checkMem();
U32[arr + ABV_BUFFER_OFFSET >>> 2] = retain(buf);
U32[arr + ABV_DATASTART_OFFSET >>> 2] = buf;
U32[arr + ABV_DATALENGTH_OFFSET >>> 2] = length << align;
var view;
switch (align) {
case 0: view = U8; break;
case 1: view = U16; break;
case 2: view = U32; break;
case 3: view = U64; break;
default: throw Error("unsupported align: " + align);
}
for (let i = 0; i < length; ++i) view[(buf >> align) + i] = values[i];
if (info & VAL_MANAGED) for (let i = 0; i < length; ++i) retain(values[i]);
return retain(arr);
}
// /** Creates a new typed array in the module's memory and returns its pointer. */ baseModule.newArray = newArray;
// 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 = alloc(12); // TypedArray header
// var buf = alloc(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(buffer, 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;
// }
// baseModule.newArray = newArray; /** Gets the values of an array in the module's memory by its pointer. */
function getArray(arr) {
checkMem();
const id = U32[arr + ID_OFFSET >>> 2];
const info = getInfo(id);
if (!(info & ARRAY)) throw Error("not an array: " + id);
const align = getAlign(VAL_ALIGN, info);
var buf = U32[arr + ABV_DATASTART_OFFSET >>> 2];
const length = U32[buf + SIZE_OFFSET >>> 2] >>> align;
var view;
switch (align) {
// TODO: signedness/floats
case 0: view = U8; break;
case 1: view = U16; break;
case 2: view = U32; break;
case 3: view = U64; break;
default: throw Error("unsupported align: " + align);
}
return Array.from(view.slice(buf >>>= align, buf + length));
}
// /** Gets a view on a typed array in the module's memory by its pointer. */ baseModule.getArray = getArray;
// 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(buffer, buf + 8 + byteOffset, (byteLength - byteOffset) / elementSize);
// }
// baseModule.getArray = getArray;
// /** Frees a typed array in the module's memory. Must not be accessed anymore afterwards. */
// function freeArray(ptr) {
// checkMem();
// var buf = U32[ptr >>> 2];
// free(buf);
// free(ptr);
// }
// baseModule.freeArray = freeArray;
// /**
// * 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.
// */
// function newFunction(fn) {
// if (typeof fn.original === "function") fn = fn.original;
// var index = table.length;
// table.grow(1);
// table.set(index, fn);
// return index;
// }
// baseModule.newFunction = newFunction;
// /** Gets a function by its pointer. */
// function getFunction(ptr) {
// return wrapFunction(table.get(ptr), setargc);
// }
// 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;

View File

@ -58,3 +58,5 @@ export function calladd(fn: (a: i32, b: i32) => i32, a: i32, b: i32): i32 {
export function dotrace(num: f64): void { export function dotrace(num: f64): void {
trace("The answer is", 1, num); trace("The answer is", 1, num);
} }
export const INT32ARRAY_ID = idof<Int32Array>();

View File

@ -33,17 +33,19 @@ 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(module.INT32ARRAY_ID, 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(Array.from(module.getArray(ptr)), arr);
// should be able to free and reuse the space of an internal typed array // should be able to release no longer needed references
// module.freeArray(ptr); module.__release(ptr);
// var ptr2 = module.newArray(new Int32Array(arr)); try {
// assert.strictEqual(ptr, ptr2); module.__release(ptr);
assert(false);
} catch (e) {};
// 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);

View File

@ -4160,7 +4160,8 @@ export function compileRTTI(compiler: Compiler): void {
var data = new Uint8Array(size); var data = new Uint8Array(size);
writeI32(count, data, 0); writeI32(count, data, 0);
var off = 4; var off = 4;
var arrayPrototype = program.arrayPrototype; var abvInstance = program.arrayBufferViewInstance;
var abvPrototype = abvInstance.prototype;
var setPrototype = program.setPrototype; var setPrototype = program.setPrototype;
var mapPrototype = program.mapPrototype; var mapPrototype = program.mapPrototype;
var lastId = 0; var lastId = 0;
@ -4168,17 +4169,16 @@ export function compileRTTI(compiler: Compiler): void {
assert(id == lastId++); assert(id == lastId++);
let flags: TypeinfoFlags = 0; let flags: TypeinfoFlags = 0;
if (instance.isAcyclic) flags |= TypeinfoFlags.ACYCLIC; if (instance.isAcyclic) flags |= TypeinfoFlags.ACYCLIC;
if (instance.prototype.extends(arrayPrototype)) { if (instance !== abvInstance && instance.extends(abvPrototype)) {
let typeArguments = assert(instance.getTypeArgumentsTo(arrayPrototype)); let valueType = instance.getArrayValueType();
assert(typeArguments.length == 1);
flags |= TypeinfoFlags.ARRAY; flags |= TypeinfoFlags.ARRAY;
flags |= TypeinfoFlags.VALUE_ALIGN_0 * typeToRuntimeFlags(typeArguments[0]); flags |= TypeinfoFlags.VALUE_ALIGN_0 * typeToRuntimeFlags(valueType);
} else if (instance.prototype.extends(setPrototype)) { } else if (instance.extends(setPrototype)) {
let typeArguments = assert(instance.getTypeArgumentsTo(setPrototype)); let typeArguments = assert(instance.getTypeArgumentsTo(setPrototype));
assert(typeArguments.length == 1); assert(typeArguments.length == 1);
flags |= TypeinfoFlags.SET; flags |= TypeinfoFlags.SET;
flags |= TypeinfoFlags.VALUE_ALIGN_0 * typeToRuntimeFlags(typeArguments[0]); flags |= TypeinfoFlags.VALUE_ALIGN_0 * typeToRuntimeFlags(typeArguments[0]);
} else if (instance.prototype.extends(mapPrototype)) { } else if (instance.extends(mapPrototype)) {
let typeArguments = assert(instance.getTypeArgumentsTo(mapPrototype)); let typeArguments = assert(instance.getTypeArgumentsTo(mapPrototype));
assert(typeArguments.length == 2); assert(typeArguments.length == 2);
flags |= TypeinfoFlags.MAP; flags |= TypeinfoFlags.MAP;

View File

@ -178,6 +178,17 @@ export namespace CommonSymbols {
export const ArrayBuffer = "ArrayBuffer"; export const ArrayBuffer = "ArrayBuffer";
export const Math = "Math"; export const Math = "Math";
export const Mathf = "Mathf"; export const Mathf = "Mathf";
export const Int8Array = "Int8Array";
export const Int16Array = "Int16Array";
export const Int32Array = "Int32Array";
export const Int64Array = "Int64Array";
export const Uint8Array = "Uint8Array";
export const Uint8ClampedArray = "Uint8ClampedArray";
export const Uint16Array = "Uint16Array";
export const Uint32Array = "Uint32Array";
export const Uint64Array = "Uint64Array";
export const Float32Array = "Float32Array";
export const Float64Array = "Float64Array";
// runtime // runtime
export const abort = "abort"; export const abort = "abort";
export const pow = "pow"; export const pow = "pow";

View File

@ -356,6 +356,28 @@ export class Program extends DiagnosticEmitter {
mapPrototype: ClassPrototype; mapPrototype: ClassPrototype;
/** Fixed array prototype reference. */ /** Fixed array prototype reference. */
fixedArrayPrototype: ClassPrototype; fixedArrayPrototype: ClassPrototype;
/** Int8Array prototype. */
i8ArrayPrototype: ClassPrototype;
/** Int16Array prototype. */
i16ArrayPrototype: ClassPrototype;
/** Int32Array prototype. */
i32ArrayPrototype: ClassPrototype;
/** Int64Array prototype. */
i64ArrayPrototype: ClassPrototype;
/** Uint8Array prototype. */
u8ArrayPrototype: ClassPrototype;
/** Uint8ClampedArray prototype. */
u8ClampedArrayPrototype: ClassPrototype;
/** Uint16Array prototype. */
u16ArrayPrototype: ClassPrototype;
/** Uint32Array prototype. */
u32ArrayPrototype: ClassPrototype;
/** Uint64Array prototype. */
u64ArrayPrototype: ClassPrototype;
/** Float32Array prototype. */
f32ArrayPrototype: ClassPrototype;
/** Float64Array prototype. */
f64ArrayPrototype: ClassPrototype;
/** String instance reference. */ /** String instance reference. */
stringInstance: Class; stringInstance: Class;
/** Abort function reference, if present. */ /** Abort function reference, if present. */
@ -734,12 +756,14 @@ export class Program extends DiagnosticEmitter {
} }
} }
// register ArrayBuffer (id=0) and String (id=1) // register ArrayBuffer (id=0), String (id=1), ArrayBufferView (id=2)
assert(this.nextClassId == 0); assert(this.nextClassId == 0);
this.arrayBufferInstance = this.requireClass(CommonSymbols.ArrayBuffer); this.arrayBufferInstance = this.requireClass(CommonSymbols.ArrayBuffer);
assert(this.arrayBufferInstance.id == 0); assert(this.arrayBufferInstance.id == 0);
this.stringInstance = this.requireClass(CommonSymbols.String); this.stringInstance = this.requireClass(CommonSymbols.String);
assert(this.stringInstance.id == 1); assert(this.stringInstance.id == 1);
this.arrayBufferViewInstance = this.requireClass(CommonSymbols.ArrayBufferView);
assert(this.arrayBufferViewInstance.id == 2);
// register classes backing basic types // register classes backing basic types
this.registerNativeTypeClass(TypeKind.I8, CommonSymbols.I8); this.registerNativeTypeClass(TypeKind.I8, CommonSymbols.I8);
@ -757,6 +781,19 @@ export class Program extends DiagnosticEmitter {
this.registerNativeTypeClass(TypeKind.F64, CommonSymbols.F64); this.registerNativeTypeClass(TypeKind.F64, CommonSymbols.F64);
if (options.hasFeature(Feature.SIMD)) this.registerNativeTypeClass(TypeKind.V128, CommonSymbols.V128); if (options.hasFeature(Feature.SIMD)) this.registerNativeTypeClass(TypeKind.V128, CommonSymbols.V128);
// register views but don't instantiate them yet
this.i8ArrayPrototype = <ClassPrototype>this.require(CommonSymbols.Int8Array, ElementKind.CLASS_PROTOTYPE);
this.i16ArrayPrototype = <ClassPrototype>this.require(CommonSymbols.Int16Array, ElementKind.CLASS_PROTOTYPE);
this.i32ArrayPrototype = <ClassPrototype>this.require(CommonSymbols.Int32Array, ElementKind.CLASS_PROTOTYPE);
this.i64ArrayPrototype = <ClassPrototype>this.require(CommonSymbols.Int64Array, ElementKind.CLASS_PROTOTYPE);
this.u8ArrayPrototype = <ClassPrototype>this.require(CommonSymbols.Uint8Array, ElementKind.CLASS_PROTOTYPE);
this.u8ClampedArrayPrototype = <ClassPrototype>this.require(CommonSymbols.Uint8ClampedArray, ElementKind.CLASS_PROTOTYPE);
this.u16ArrayPrototype = <ClassPrototype>this.require(CommonSymbols.Uint16Array, ElementKind.CLASS_PROTOTYPE);
this.u32ArrayPrototype = <ClassPrototype>this.require(CommonSymbols.Uint32Array, ElementKind.CLASS_PROTOTYPE);
this.u64ArrayPrototype = <ClassPrototype>this.require(CommonSymbols.Uint64Array, ElementKind.CLASS_PROTOTYPE);
this.f32ArrayPrototype = <ClassPrototype>this.require(CommonSymbols.Float32Array, ElementKind.CLASS_PROTOTYPE);
this.f64ArrayPrototype = <ClassPrototype>this.require(CommonSymbols.Float64Array, ElementKind.CLASS_PROTOTYPE);
// resolve base prototypes of derived classes // resolve base prototypes of derived classes
var resolver = this.resolver; var resolver = this.resolver;
for (let i = 0, k = queuedExtends.length; i < k; ++i) { for (let i = 0, k = queuedExtends.length; i < k; ++i) {
@ -813,7 +850,6 @@ export class Program extends DiagnosticEmitter {
} }
// register stdlib components // register stdlib components
this.arrayBufferViewInstance = this.requireClass(CommonSymbols.ArrayBufferView);
this.arrayPrototype = <ClassPrototype>this.require(CommonSymbols.Array, ElementKind.CLASS_PROTOTYPE); this.arrayPrototype = <ClassPrototype>this.require(CommonSymbols.Array, ElementKind.CLASS_PROTOTYPE);
this.fixedArrayPrototype = <ClassPrototype>this.require(CommonSymbols.FixedArray, ElementKind.CLASS_PROTOTYPE); this.fixedArrayPrototype = <ClassPrototype>this.require(CommonSymbols.FixedArray, ElementKind.CLASS_PROTOTYPE);
this.setPrototype = <ClassPrototype>this.require(CommonSymbols.Set, ElementKind.CLASS_PROTOTYPE); this.setPrototype = <ClassPrototype>this.require(CommonSymbols.Set, ElementKind.CLASS_PROTOTYPE);
@ -3200,6 +3236,32 @@ export class Class extends TypedElement {
return null; return null;
} }
/** Gets the value type of an array. Must be an array. */
getArrayValueType(): Type {
var current: Class = this;
var program = this.program;
var abvInstance = program.arrayBufferViewInstance;
while (current.base !== abvInstance) {
current = assert(current.base);
}
switch (current.prototype) {
case program.i8ArrayPrototype: return Type.i8;
case program.i16ArrayPrototype: return Type.i16;
case program.i32ArrayPrototype: return Type.i32;
case program.i64ArrayPrototype: return Type.i64;
case program.u8ArrayPrototype:
case program.u8ClampedArrayPrototype: return Type.u8;
case program.u16ArrayPrototype: return Type.u16;
case program.u32ArrayPrototype: return Type.u32;
case program.u64ArrayPrototype: return Type.u64;
case program.f32ArrayPrototype: return Type.f32;
case program.f64ArrayPrototype: return Type.f64;
case program.arrayPrototype: return assert(this.getTypeArgumentsTo(program.arrayPrototype))[0];
default: assert(false);
}
return Type.void;
}
/** Tests if this class is inherently acyclic. */ /** Tests if this class is inherently acyclic. */
get isAcyclic(): bool { get isAcyclic(): bool {
var acyclic = this._acyclic; var acyclic = this._acyclic;

View File

@ -1,3 +1,3 @@
export { __alloc, __realloc, __free } from "rt/tlsf"; export { __alloc } from "rt/tlsf";
export { __retain, __release, __collect } from "rt/pure"; export { __retain, __release, __collect } from "rt/pure";
export { __instanceof, __typeinfo } from "rt"; export { RTTI_BASE as __rtti } from "rt";

View File

@ -1,2 +1,2 @@
export { __alloc, __realloc, __free, __retain, __release, __collect } from "rt/stub"; export { __alloc, __retain, __release, __collect } from "rt/stub";
export { __instanceof, __typeinfo } from "rt"; export { RTTI_BASE as __rtti } from "rt";

View File

@ -1,2 +1,5 @@
import { ArrayBufferView } from "arraybuffer";
assert(idof<ArrayBuffer>() == 0); assert(idof<ArrayBuffer>() == 0);
assert(idof<String>() == 1); assert(idof<String>() == 1);
assert(idof<ArrayBufferView>() == 2);

View File

@ -16,7 +16,7 @@
if if
i32.const 0 i32.const 0
i32.const 24 i32.const 24
i32.const 1 i32.const 3
i32.const 0 i32.const 0
call $~lib/builtins/abort call $~lib/builtins/abort
unreachable unreachable
@ -28,7 +28,19 @@
if if
i32.const 0 i32.const 0
i32.const 24 i32.const 24
i32.const 4
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 2 i32.const 2
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 5
i32.const 0 i32.const 0
call $~lib/builtins/abort call $~lib/builtins/abort
unreachable unreachable