Skip to content

Commit

Permalink
Remove no longer used half of RTTI (#2555)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: RTTI at `__rtti_base` no longer contains base class ids and now is just type flags.
  • Loading branch information
dcodeIO authored Nov 10, 2022
1 parent 0fd4db2 commit a565d73
Show file tree
Hide file tree
Showing 163 changed files with 3,562 additions and 3,726 deletions.
2 changes: 0 additions & 2 deletions lib/loader/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ export interface ASUtil {
/** Gets a function from poiner which contain table's index. */
__getFunction(ptr: number): ((...args: unknown[]) => unknown) | null;

/** Tests whether a managed object is an instance of the class represented by the specified base id. */
__instanceof(ptr: number, baseId: number): boolean;
/** Allocates a new string in the module's memory and returns a reference (pointer) to it. */
__newString(str: string): number;
/** Allocates a new ArrayBuffer in the module's memory and returns a reference (pointer) to it. */
Expand Down
34 changes: 6 additions & 28 deletions lib/loader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,30 +102,23 @@ function postInstantiate(extendedExports, instance) {
const __unpin = exports.__unpin || F_NO_EXPORT_RUNTIME;
const __collect = exports.__collect || F_NO_EXPORT_RUNTIME;
const __rtti_base = exports.__rtti_base;
const getRttiCount = __rtti_base ? arr => arr[__rtti_base >>> 2] : F_NO_EXPORT_RUNTIME;
const getTypeinfoCount = __rtti_base ? arr => arr[__rtti_base >>> 2] : F_NO_EXPORT_RUNTIME;

extendedExports.__new = __new;
extendedExports.__pin = __pin;
extendedExports.__unpin = __unpin;
extendedExports.__collect = __collect;

/** Gets the runtime type info for the given id. */
function getRttInfo(id) {
function getTypeinfo(id) {
const U32 = new Uint32Array(memory.buffer);
if ((id >>>= 0) >= getRttiCount(U32)) throw Error(`invalid id: ${id}`);
return U32[(__rtti_base + 4 >>> 2) + (id << 1)];
if ((id >>>= 0) >= getTypeinfoCount(U32)) throw Error(`invalid id: ${id}`);
return U32[(__rtti_base + 4 >>> 2) + id];
}

/** Gets the runtime base id for the given id. */
function getRttBase(id) {
const U32 = new Uint32Array(memory.buffer);
if ((id >>>= 0) >= getRttiCount(U32)) throw Error(`invalid id: ${id}`);
return U32[(__rtti_base + 4 >>> 2) + (id << 1) + 1];
}

/** Gets and validate runtime type info for the given id for array like objects */
/** Gets and validates runtime type info for the given id for array like objects */
function getArrayInfo(id) {
const info = getRttInfo(id);
const info = getTypeinfo(id);
if (!(info & (ARRAYBUFFERVIEW | ARRAY | STATICARRAY))) throw Error(`not an array: ${id}, flags=${info}`);
return info;
}
Expand Down Expand Up @@ -320,21 +313,6 @@ function postInstantiate(extendedExports, instance) {
});
}

/** Tests whether an object is an instance of the class represented by the specified base id. */
function __instanceof(ptr, baseId) {
const U32 = new Uint32Array(memory.buffer);
let id = U32[ptr + ID_OFFSET >>> 2];
if (id <= getRttiCount(U32)) {
do {
if (id == baseId) return true;
id = getRttBase(id);
} while (id);
}
return false;
}

extendedExports.__instanceof = __instanceof;

// Pull basic exports to extendedExports so code in preInstantiate can use them
extendedExports.memory = extendedExports.memory || memory;
extendedExports.table = extendedExports.table || table;
Expand Down
Binary file modified lib/loader/tests/build/default.wasm
Binary file not shown.
Binary file modified lib/loader/tests/build/legacy.wasm
Binary file not shown.
16 changes: 0 additions & 16 deletions lib/loader/tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ function test(file) {
{
let arr = [1, 2, 3, 4, 5, 0x80000000 | 0];
let ref = exports.__newArray(exports.INT32ARRAY_ID, arr);
assert(exports.__instanceof(ref, exports.INT32ARRAY_ID));

// should be able to get the values of an array
assert.deepStrictEqual(exports.__getArray(ref), arr);
Expand All @@ -104,7 +103,6 @@ function test(file) {
{
let arr = [1, 2, 3, 4, 5, 0x80000000 | 0];
let ref = exports.__newArray(exports.STATICARRAYI32_ID, arr);
assert(exports.__instanceof(ref, exports.STATICARRAYI32_ID));

// should be able to get the values of an array
assert.deepStrictEqual(exports.__getArray(ref), arr);
Expand All @@ -120,17 +118,14 @@ function test(file) {
{
let arrU8Arr = new Uint8Array([0, 1, 2]);
let refU8Arr = module.__newUint8Array(arrU8Arr);
assert(module.__instanceof(refU8Arr, module.UINT8ARRAY_ID));
assert.deepStrictEqual(module.__getUint8Array(refU8Arr), arrU8Arr);
let arrU16Arr = new Uint16Array([0, 0x7FFF, 0xFFFF]);
let refU16Arr = module.__newUint16Array(arrU16Arr);
assert(module.__instanceof(refU16Arr, module.UINT16ARRAY_ID));
assert.deepStrictEqual(module.__getUint16Array(refU16Arr), arrU16Arr);
let arrI16Arr = new Int16Array([0, -1, -2]);
let refI16Arr = module.__newInt16Array(arrI16Arr);
assert(module.__instanceof(refI16Arr, module.INT16ARRAY_ID));
assert.deepStrictEqual(module.__getInt16Array(refI16Arr), arrI16Arr);
}
*/
Expand All @@ -140,7 +135,6 @@ function test(file) {
let values = [0, 255, 127];
let arr = new Uint8Array(values);
let ref = exports.__newArray(exports.UINT8ARRAY_ID, arr);
assert(exports.__instanceof(ref, exports.UINT8ARRAY_ID));
assert.deepStrictEqual(exports.__getUint8Array(ref), arr);
assert.deepStrictEqual(exports.__getUint8ArrayView(ref), arr);
assert.deepStrictEqual(exports.__getArray(ref), values);
Expand All @@ -150,7 +144,6 @@ function test(file) {
{
let arr = [0, 255, 127];
let ref = exports.__newArray(exports.STATICARRAYU8_ID, arr);
assert(exports.__instanceof(ref, exports.STATICARRAYU8_ID));
assert.deepStrictEqual(exports.__getArray(ref), arr);
}

Expand All @@ -159,7 +152,6 @@ function test(file) {
let values = [0, 0xFFFF, -0x00FF];
let arr = new Int16Array(values);
let ref = exports.__newArray(exports.INT16ARRAY_ID, arr);
assert(exports.__instanceof(ref, exports.INT16ARRAY_ID));
assert.deepStrictEqual(exports.__getInt16Array(ref), arr);
assert.deepStrictEqual(exports.__getInt16ArrayView(ref), arr);
assert.deepStrictEqual(exports.__getArray(ref), [0, -1, -255]);
Expand All @@ -169,7 +161,6 @@ function test(file) {
{
let arr = [0, 0xFFFF, -0x00FF];
let ref = exports.__newArray(exports.STATICARRAYI16_ID, arr);
assert(exports.__instanceof(ref, exports.STATICARRAYI16_ID));
assert.deepStrictEqual(exports.__getArray(ref), [0, -1, -255]);
}

Expand All @@ -178,7 +169,6 @@ function test(file) {
let values = [1, -1 >>> 0, 0x80000000];
let arr = new Uint32Array(values);
let ref = exports.__newArray(exports.UINT32ARRAY_ID, arr);
assert(exports.__instanceof(ref, exports.UINT32ARRAY_ID));
assert.deepStrictEqual(exports.__getUint32Array(ref), arr);
assert.deepStrictEqual(exports.__getUint32ArrayView(ref), arr);
assert.deepStrictEqual(exports.__getArray(ref), values);
Expand All @@ -188,7 +178,6 @@ function test(file) {
{
let arr = [1, -1 >>> 0, 0x80000000];
let ref = exports.__newArray(exports.STATICARRAYU32_ID, arr);
assert(exports.__instanceof(ref, exports.STATICARRAYU32_ID));
assert.deepStrictEqual(exports.__getArray(ref), arr);
}

Expand All @@ -197,7 +186,6 @@ function test(file) {
let values = [0.0, 1.5, 2.5];
let arr = new Float32Array(values);
let ref = exports.__newArray(exports.FLOAT32ARRAY_ID, arr);
assert(exports.__instanceof(ref, exports.FLOAT32ARRAY_ID));
assert.deepStrictEqual(exports.__getFloat32Array(ref), arr);
assert.deepStrictEqual(exports.__getFloat32ArrayView(ref), arr);
assert.deepStrictEqual(exports.__getArray(ref), values);
Expand All @@ -207,29 +195,25 @@ function test(file) {
{
let arr = [0.0, 1.5, 2.5];
let ref = exports.__newArray(exports.STATICARRAYF32_ID, arr);
assert(exports.__instanceof(ref, exports.STATICARRAYF32_ID));
assert.deepStrictEqual(exports.__getArray(ref), arr);
}

// should be able to create empty arrays
{
let ref = exports.__newArray(exports.ARRAYI32_ID);
assert(exports.__instanceof(ref, exports.ARRAYI32_ID));
assert.deepStrictEqual(exports.__getArray(ref), []);
}

// should be able to create arrays with capacity
{
let ref = exports.__newArray(exports.ARRAYI32_ID, 32);
assert(exports.__instanceof(ref, exports.ARRAYI32_ID));
assert.strictEqual(exports.__getArray(ref).length, 32);
}

// should be able to work with normal arrays
{
let arr = [1, 2, 3, 4, 5];
let ref = exports.__newArray(exports.ARRAYI32_ID, arr);
assert(exports.__instanceof(ref, exports.ARRAYI32_ID));
exports.changeLength(ref, 3);
assert.deepStrictEqual(exports.__getArray(ref), [1, 2, 3]);
}
Expand Down
39 changes: 7 additions & 32 deletions lib/loader/umd/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,31 +132,23 @@ var loader = (function(exports) {
const __collect = exports.__collect || F_NO_EXPORT_RUNTIME;

const __rtti_base = exports.__rtti_base;
const getRttiCount = __rtti_base ? arr => arr[__rtti_base >>> 2] : F_NO_EXPORT_RUNTIME;
const getTypeinfoCount = __rtti_base ? arr => arr[__rtti_base >>> 2] : F_NO_EXPORT_RUNTIME;
extendedExports.__new = __new;
extendedExports.__pin = __pin;
extendedExports.__unpin = __unpin;
extendedExports.__collect = __collect;
/** Gets the runtime type info for the given id. */

function getRttInfo(id) {
function getTypeinfo(id) {
const U32 = new Uint32Array(memory.buffer);
if ((id >>>= 0) >= getRttiCount(U32)) throw Error(`invalid id: ${id}`);
return U32[(__rtti_base + 4 >>> 2) + (id << 1)];
if ((id >>>= 0) >= getTypeinfoCount(U32)) throw Error(`invalid id: ${id}`);
return U32[(__rtti_base + 4 >>> 2) + id];
}
/** Gets the runtime base id for the given id. */


function getRttBase(id) {
const U32 = new Uint32Array(memory.buffer);
if ((id >>>= 0) >= getRttiCount(U32)) throw Error(`invalid id: ${id}`);
return U32[(__rtti_base + 4 >>> 2) + (id << 1) + 1];
}
/** Gets and validate runtime type info for the given id for array like objects */
/** Gets and validates runtime type info for the given id for array like objects */


function getArrayInfo(id) {
const info = getRttInfo(id);
const info = getTypeinfo(id);
if (!(info & (ARRAYBUFFERVIEW | ARRAY | STATICARRAY))) throw Error(`not an array: ${id}, flags=${info}`);
return info;
}
Expand Down Expand Up @@ -366,25 +358,8 @@ var loader = (function(exports) {
[BigUint64Array, BigInt64Array].forEach(ctor => {
attachTypedArrayFunctions(ctor, ctor.name.slice(3), 3);
});
}
/** Tests whether an object is an instance of the class represented by the specified base id. */


function __instanceof(ptr, baseId) {
const U32 = new Uint32Array(memory.buffer);
let id = U32[ptr + ID_OFFSET >>> 2];

if (id <= getRttiCount(U32)) {
do {
if (id == baseId) return true;
id = getRttBase(id);
} while (id);
}

return false;
}
} // Pull basic exports to extendedExports so code in preInstantiate can use them

extendedExports.__instanceof = __instanceof; // Pull basic exports to extendedExports so code in preInstantiate can use them

extendedExports.memory = extendedExports.memory || memory;
extendedExports.table = extendedExports.table || table; // Demangle exports and provide the usual utility on the prototype
Expand Down
4 changes: 1 addition & 3 deletions src/builtins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10399,7 +10399,7 @@ export function compileRTTI(compiler: Compiler): void {
let module = compiler.module;
let managedClasses = program.managedClasses;
let count = managedClasses.size;
let size = 4 + 8 * count;
let size = 4 + 4 * count; // count | TypeInfo*
let data = new Uint8Array(size);
writeI32(count, data, 0);
let off = 4;
Expand Down Expand Up @@ -10443,8 +10443,6 @@ export function compileRTTI(compiler: Compiler): void {
}
writeI32(flags, data, off); off += 4;
instance.rttiFlags = flags;
let base = instance.base;
writeI32(base ? base.id : 0, data, off); off += 4;
}
assert(off == size);
let usizeType = program.options.usizeType;
Expand Down
1 change: 0 additions & 1 deletion src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,6 @@ export namespace CommonNames {
export const renew = "__renew";
export const link = "__link";
export const collect = "__collect";
export const typeinfo = "__typeinfo";
export const visit = "__visit";
export const newBuffer = "__newBuffer";
export const newArray = "__newArray";
Expand Down
8 changes: 0 additions & 8 deletions src/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -729,14 +729,6 @@ export class Program extends DiagnosticEmitter {
}
private _visitInstance: Function | null = null;

/** Gets the runtime `__typeinfo(id: u32): RTTIFlags` instance. */
get typeinfoInstance(): Function {
let cached = this._typeinfoInstance;
if (!cached) this._typeinfoInstance = cached = this.requireFunction(CommonNames.typeinfo);
return cached;
}
private _typeinfoInstance: Function | null = null;

/** Gets the runtime `__newBuffer(size: usize, id: u32, data: usize = 0): usize` instance. */
get newBufferInstance(): Function {
let cached = this._newBufferInstance;
Expand Down
13 changes: 0 additions & 13 deletions std/assembly/rt.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Typeinfo, TypeinfoFlags } from "./shared/typeinfo";
import { E_INDEXOUTOFRANGE } from "./util/error";
import { OBJECT, TOTAL_OVERHEAD } from "./rt/common";
import { ArrayBufferView } from "./arraybuffer";

// @ts-ignore: decorator
Expand All @@ -23,18 +22,6 @@ export function __typeinfo(id: u32): TypeinfoFlags {
return changetype<Typeinfo>(ptr + sizeof<u32>() + id * offsetof<Typeinfo>()).flags;
}

// @ts-ignore: decorator
@unsafe
export function __instanceof(ptr: usize, classId: u32): bool { // keyword
let id = changetype<OBJECT>(ptr - TOTAL_OVERHEAD).rtId;
let rttiBase = __rtti_base;
if (id <= load<u32>(rttiBase)) {
do if (id == classId) return true;
while (id = changetype<Typeinfo>(rttiBase + sizeof<u32>() + id * offsetof<Typeinfo>()).base);
}
return false;
}

// @ts-ignore: decorator
@unsafe
export function __newBuffer(size: usize, id: u32, data: usize = 0): usize {
Expand Down
3 changes: 0 additions & 3 deletions std/assembly/rt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ Interface
* **__typeinfo**(id: `u32`): `RTTIFlags`<br />
Obtains the runtime type information for objects with the specified runtime id. Runtime type information is a set of flags indicating whether a type is managed, an array or similar, and what the relevant alignments when creating an instance externally are etc.

* **__instanceof**(ptr: `usize`, classId: `u32`): `bool`<br />
Tests if the object pointed to by `ptr` is an instance of the specified class id.

ITCMS / `--runtime incremental`
-----

Expand Down
1 change: 0 additions & 1 deletion std/assembly/rt/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ declare function __collect(): void;

// Runtime type info
declare function __typeinfo(id: u32): u32;
declare function __instanceof(ptr: usize, superId: u32): bool;

// Visitors
declare function __visit(ptr: usize, cookie: i32): void;
Expand Down
4 changes: 0 additions & 4 deletions std/assembly/shared/typeinfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
// │ count │
// ╞═══════════════════════════════════════════════════════════════╡ ┐
// │ Typeinfo#flags [id=0] │ id < count
// ├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┤
// │ Typeinfo#base [id=0] │
// ├───────────────────────────────────────────────────────────────┤
// │ ... │

Expand All @@ -17,8 +15,6 @@
export class Typeinfo {
/** Flags describing the shape of this class type. */
flags: TypeinfoFlags = TypeinfoFlags.NONE;
/** Base class id or `0` if none. */
base: u32 = 0;
}

/** Runtime type information flags. */
Expand Down
Loading

0 comments on commit a565d73

Please sign in to comment.