mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-19 18:01:31 +00:00
directize
This commit is contained in:
117
src/builtins.ts
117
src/builtins.ts
@ -135,6 +135,7 @@ export namespace BuiltinSymbols {
|
||||
export const changetype = "~lib/builtins/changetype";
|
||||
export const assert = "~lib/builtins/assert";
|
||||
export const unchecked = "~lib/builtins/unchecked";
|
||||
export const call_direct = "~lib/builtins/call_direct";
|
||||
export const call_indirect = "~lib/builtins/call_indirect";
|
||||
export const instantiate = "~lib/builtins/instantiate";
|
||||
|
||||
@ -477,14 +478,17 @@ export namespace BuiltinSymbols {
|
||||
export const memory_reset = "~lib/memory/memory.reset";
|
||||
|
||||
// std/runtime.ts
|
||||
export const classId = "~lib/runtime/classId";
|
||||
export const iterateRoots = "~lib/runtime/iterateRoots";
|
||||
export const runtime_id = "~lib/runtime/__runtime_id";
|
||||
export const runtime_allocate = "~lib/runtime/runtime.allocate";
|
||||
export const runtime_reallocate = "~lib/runtime/runtime.reallocate";
|
||||
export const runtime_register = "~lib/runtime/runtime.register";
|
||||
export const runtime_discard = "~lib/runtime/runtime.discard";
|
||||
export const runtime_makeArray = "~lib/runtime/runtime.makeArray";
|
||||
|
||||
// std/gc.ts
|
||||
export const gc_mark_roots = "~lib/gc/__gc_mark_roots";
|
||||
export const gc_mark_members = "~lib/gc/__gc_mark_members";
|
||||
|
||||
// std/typedarray.ts
|
||||
export const Int8Array = "~lib/typedarray/Int8Array";
|
||||
export const Uint8Array = "~lib/typedarray/Uint8Array";
|
||||
@ -532,6 +536,8 @@ export function compileCall(
|
||||
// below, but rather done to make this file easier to work with. If there was a general rule it'd
|
||||
// most likely be "three or more instructions that only differ in their actual opcode".
|
||||
|
||||
var directize = false;
|
||||
|
||||
switch (prototype.internalName) {
|
||||
|
||||
// === Static type evaluation =================================================================
|
||||
@ -2337,6 +2343,7 @@ export function compileCall(
|
||||
if (!alreadyUnchecked) flow.unset(FlowFlags.UNCHECKED_CONTEXT);
|
||||
return expr;
|
||||
}
|
||||
case BuiltinSymbols.call_direct: directize = true;
|
||||
case BuiltinSymbols.call_indirect: { // call_indirect<T?>(target: Function | u32, ...args: *[]) -> T
|
||||
if (
|
||||
checkTypeOptional(typeArguments, reportNode, compiler, true) |
|
||||
@ -2370,14 +2377,21 @@ export function compileCall(
|
||||
let typeRef = module.getFunctionTypeBySignature(nativeReturnType, nativeParamTypes);
|
||||
if (!typeRef) typeRef = module.addFunctionType(typeName, nativeReturnType, nativeParamTypes);
|
||||
compiler.currentType = returnType;
|
||||
// if the index expression is precomputable to a constant value, emit a direct call
|
||||
if (getExpressionId(arg0 = module.precomputeExpression(arg0)) == ExpressionId.Const) {
|
||||
assert(getExpressionType(arg0) == NativeType.I32);
|
||||
let index = getConstValueI32(arg0);
|
||||
let functionTable = compiler.functionTable;
|
||||
if (index >= 0 && index < functionTable.length) {
|
||||
return module.createCall(functionTable[index], operandExprs, nativeReturnType);
|
||||
if (directize) {
|
||||
// if the index expression is precomputable to a constant value, emit a direct call
|
||||
if (getExpressionId(arg0 = module.precomputeExpression(arg0)) == ExpressionId.Const) {
|
||||
assert(getExpressionType(arg0) == NativeType.I32);
|
||||
let index = getConstValueI32(arg0);
|
||||
let functionTable = compiler.functionTable;
|
||||
if (index >= 0 && index < functionTable.length) {
|
||||
return module.createCall(functionTable[index], operandExprs, nativeReturnType);
|
||||
}
|
||||
}
|
||||
compiler.error(
|
||||
DiagnosticCode.Operation_not_supported,
|
||||
operands[0].range
|
||||
);
|
||||
return module.createUnreachable();
|
||||
}
|
||||
// of course this can easily result in a 'RuntimeError: function signature mismatch' trap and
|
||||
// thus must be used with care. it exists because it *might* be useful in specific scenarios.
|
||||
@ -3624,7 +3638,7 @@ export function compileCall(
|
||||
|
||||
// === Internal runtime =======================================================================
|
||||
|
||||
case BuiltinSymbols.classId: {
|
||||
case BuiltinSymbols.runtime_id: {
|
||||
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
|
||||
compiler.currentType = Type.u32;
|
||||
if (!type) return module.createUnreachable();
|
||||
@ -3636,38 +3650,21 @@ export function compileCall(
|
||||
);
|
||||
return module.createUnreachable();
|
||||
}
|
||||
let classId = classReference.ensureClassId(compiler); // involves compile steps
|
||||
let id = classReference.ensureId(compiler); // involves compile steps
|
||||
compiler.currentType = Type.u32;
|
||||
return module.createI32(classId);
|
||||
return module.createI32(id);
|
||||
}
|
||||
case BuiltinSymbols.iterateRoots: {
|
||||
case BuiltinSymbols.gc_mark_roots: {
|
||||
if (
|
||||
checkTypeAbsent(typeArguments, reportNode, prototype) |
|
||||
checkArgsRequired(operands, 1, reportNode, compiler)
|
||||
checkArgsRequired(operands, 0, reportNode, compiler)
|
||||
) {
|
||||
compiler.currentType = Type.void;
|
||||
return module.createUnreachable();
|
||||
}
|
||||
let expr = compiler.compileExpressionRetainType(operands[0], Type.u32, WrapMode.NONE);
|
||||
let type = compiler.currentType;
|
||||
let signatureReference = type.signatureReference;
|
||||
if (
|
||||
!type.is(TypeFlags.REFERENCE) ||
|
||||
!signatureReference ||
|
||||
signatureReference.parameterTypes.length != 1 ||
|
||||
signatureReference.parameterTypes[0] != compiler.options.usizeType
|
||||
) {
|
||||
compiler.error(
|
||||
DiagnosticCode.Type_0_is_not_assignable_to_type_1,
|
||||
reportNode.range, type.toString(), "(ref: usize) => void"
|
||||
);
|
||||
compiler.currentType = Type.void;
|
||||
return module.createUnreachable();
|
||||
}
|
||||
// just emit a call even if the function doesn't yet exist
|
||||
compiler.needsIterateRoots = true;
|
||||
compiler.needsTraverse = true;
|
||||
compiler.currentType = Type.void;
|
||||
return module.createCall("~iterateRoots", [ expr ], NativeType.None);
|
||||
return module.createCall(BuiltinSymbols.gc_mark_roots, null, NativeType.None);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4052,13 +4049,15 @@ export function compileAbort(
|
||||
]);
|
||||
}
|
||||
|
||||
/** Compiles the iterateRoots function if required. */
|
||||
export function compileIterateRoots(compiler: Compiler): void {
|
||||
/** Compiles the mark_roots function if required. */
|
||||
export function compileMarkRoots(compiler: Compiler): void {
|
||||
var module = compiler.module;
|
||||
var exprs = new Array<ExpressionRef>();
|
||||
var typeName = Signature.makeSignatureString([ Type.i32 ], Type.void);
|
||||
var typeRef = compiler.ensureFunctionType([ Type.i32 ], Type.void);
|
||||
var typeRef = compiler.ensureFunctionType(null, Type.void);
|
||||
var nativeSizeType = compiler.options.nativeSizeType;
|
||||
var markRef = assert(compiler.program.markRef);
|
||||
|
||||
compiler.compileFunction(markRef);
|
||||
|
||||
for (let element of compiler.program.elementsByName.values()) {
|
||||
if (element.kind != ElementKind.GLOBAL) continue;
|
||||
@ -4073,43 +4072,51 @@ export function compileIterateRoots(compiler: Compiler): void {
|
||||
let value = global.constantIntegerValue;
|
||||
if (i64_low(value) || i64_high(value)) {
|
||||
exprs.push(
|
||||
module.createCallIndirect(
|
||||
module.createGetLocal(0, NativeType.I32),
|
||||
[
|
||||
compiler.options.isWasm64
|
||||
? module.createI64(i64_low(value), i64_high(value))
|
||||
: module.createI32(i64_low(value))
|
||||
],
|
||||
typeName
|
||||
)
|
||||
module.createCall(markRef.internalName, [
|
||||
compiler.options.isWasm64
|
||||
? module.createI64(i64_low(value), i64_high(value))
|
||||
: module.createI32(i64_low(value))
|
||||
], NativeType.None)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
exprs.push(
|
||||
module.createIf(
|
||||
module.createTeeLocal(
|
||||
1,
|
||||
0,
|
||||
module.createGetGlobal(global.internalName, nativeSizeType)
|
||||
),
|
||||
module.createCallIndirect(
|
||||
module.createGetLocal(0, NativeType.I32),
|
||||
[
|
||||
module.createGetLocal(1, nativeSizeType)
|
||||
],
|
||||
typeName
|
||||
)
|
||||
module.createCall(markRef.internalName, [
|
||||
module.createGetLocal(0, nativeSizeType)
|
||||
], NativeType.None)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
module.addFunction("~iterateRoots", typeRef, [ nativeSizeType ],
|
||||
module.addFunction(BuiltinSymbols.gc_mark_roots, typeRef, [ nativeSizeType ],
|
||||
exprs.length
|
||||
? module.createBlock(null, exprs)
|
||||
: module.createNop()
|
||||
);
|
||||
}
|
||||
|
||||
// TODO
|
||||
export function compileMarkMembers(compiler: Compiler): void {
|
||||
var module = compiler.module;
|
||||
var ftype = compiler.ensureFunctionType(null, Type.void);
|
||||
|
||||
var names = new Array<string>();
|
||||
var current = module.createSwitch(names, "invalid", module.createGetLocal(0, NativeType.I32));
|
||||
|
||||
module.addFunction(BuiltinSymbols.gc_mark_members, ftype, [], module.createBlock(null, [
|
||||
module.createBlock("invalid", [
|
||||
current
|
||||
]),
|
||||
module.createUnreachable()
|
||||
]));
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
/** Evaluates the constant type of a type argument *or* expression. */
|
||||
|
@ -6,7 +6,7 @@
|
||||
import {
|
||||
compileCall as compileBuiltinCall,
|
||||
compileAbort,
|
||||
compileIterateRoots,
|
||||
compileMarkRoots,
|
||||
BuiltinSymbols
|
||||
} from "./builtins";
|
||||
|
||||
@ -309,8 +309,8 @@ export class Compiler extends DiagnosticEmitter {
|
||||
argcVar: GlobalRef = 0;
|
||||
/** Argument count helper setter. */
|
||||
argcSet: FunctionRef = 0;
|
||||
/** Indicates whether the iterateRoots function must be generated. */
|
||||
needsIterateRoots: bool = false;
|
||||
/** Indicates whether the traverseRoots function must be generated. */
|
||||
needsTraverse: bool = false;
|
||||
|
||||
/** Compiles a {@link Program} to a {@link Module} using the specified options. */
|
||||
static compile(program: Program, options: Options | null = null): Module {
|
||||
@ -444,7 +444,10 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
|
||||
// set up gc
|
||||
if (this.needsIterateRoots) compileIterateRoots(this);
|
||||
if (this.needsTraverse) {
|
||||
compileMarkRoots(this);
|
||||
// compileMarkMembers(this);
|
||||
}
|
||||
|
||||
// expose module capabilities
|
||||
var capabilities = Capability.NONE;
|
||||
@ -1409,7 +1412,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
} else {
|
||||
let length = stringValue.length;
|
||||
let buffer = new Uint8Array(rtHeaderSize + (length << 1));
|
||||
program.writeRuntimeHeader(buffer, 0, stringInstance.ensureClassId(this), length << 1);
|
||||
program.writeRuntimeHeader(buffer, 0, stringInstance.ensureId(this), length << 1);
|
||||
for (let i = 0; i < length; ++i) {
|
||||
writeI16(stringValue.charCodeAt(i), buffer, rtHeaderSize + (i << 1));
|
||||
}
|
||||
@ -1435,7 +1438,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var runtimeHeaderSize = program.runtimeHeaderSize;
|
||||
|
||||
var buf = new Uint8Array(runtimeHeaderSize + byteLength);
|
||||
program.writeRuntimeHeader(buf, 0, bufferInstance.ensureClassId(this), byteLength);
|
||||
program.writeRuntimeHeader(buf, 0, bufferInstance.ensureId(this), byteLength);
|
||||
var pos = runtimeHeaderSize;
|
||||
var nativeType = elementType.toNativeType();
|
||||
switch (nativeType) {
|
||||
@ -1522,7 +1525,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
var arrayLength = i32(bufferLength / elementType.byteSize);
|
||||
|
||||
var buf = new Uint8Array(runtimeHeaderSize + arrayInstanceSize);
|
||||
program.writeRuntimeHeader(buf, 0, arrayInstance.ensureClassId(this), arrayInstanceSize);
|
||||
program.writeRuntimeHeader(buf, 0, arrayInstance.ensureId(this), arrayInstanceSize);
|
||||
|
||||
var bufferAddress32 = i64_low(bufferSegment.offset) + runtimeHeaderSize;
|
||||
assert(!program.options.isWasm64); // TODO
|
||||
@ -5950,6 +5953,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
// create the trampoline element
|
||||
var trampolineSignature = new Signature(originalParameterTypes, commonReturnType, commonThisType);
|
||||
trampolineSignature.requiredParameters = maxArguments;
|
||||
trampolineSignature.parameterNames = originalSignature.parameterNames;
|
||||
trampoline = new Function(
|
||||
original.name + "|trampoline",
|
||||
original.prototype,
|
||||
@ -6122,12 +6126,15 @@ export class Compiler extends DiagnosticEmitter {
|
||||
)
|
||||
)
|
||||
) { // inline into the call
|
||||
let previousFlow = this.currentFlow;
|
||||
this.currentFlow = instance.flow;
|
||||
operands.push(this.compileExpression(
|
||||
<Expression>parameterNodes[i].initializer,
|
||||
parameterTypes[i],
|
||||
ConversionKind.IMPLICIT,
|
||||
WrapMode.NONE
|
||||
));
|
||||
this.currentFlow = previousFlow;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -6821,7 +6828,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
// makeArray(length, classId, alignLog2, staticBuffer)
|
||||
let expr = this.makeCallDirect(assert(program.makeArrayInstance), [
|
||||
module.createI32(length),
|
||||
module.createI32(arrayInstance.ensureClassId(this)),
|
||||
module.createI32(arrayInstance.ensureId(this)),
|
||||
program.options.isWasm64
|
||||
? module.createI64(elementType.alignLog2)
|
||||
: module.createI32(elementType.alignLog2),
|
||||
@ -6855,7 +6862,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
module.createSetLocal(tempThis.index,
|
||||
this.makeCallDirect(makeArrayInstance, [
|
||||
module.createI32(length),
|
||||
module.createI32(arrayInstance.ensureClassId(this)),
|
||||
module.createI32(arrayInstance.ensureId(this)),
|
||||
program.options.isWasm64
|
||||
? module.createI64(elementType.alignLog2)
|
||||
: module.createI32(elementType.alignLog2),
|
||||
@ -8116,7 +8123,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
? module.createI64(classInstance.currentMemoryOffset)
|
||||
: module.createI32(classInstance.currentMemoryOffset)
|
||||
], reportNode),
|
||||
module.createI32(classInstance.ensureClassId(this))
|
||||
module.createI32(classInstance.ensureId(this))
|
||||
], reportNode);
|
||||
}
|
||||
}
|
||||
@ -8321,7 +8328,7 @@ export class Compiler extends DiagnosticEmitter {
|
||||
module.createBreak(label,
|
||||
module.createBinary(BinaryOp.EqI32, // classId == class.id
|
||||
module.createTeeLocal(idTemp.index, idExpr),
|
||||
module.createI32(classInstance.ensureClassId(this))
|
||||
module.createI32(classInstance.ensureId(this))
|
||||
),
|
||||
module.createI32(1) // ? true
|
||||
)
|
||||
@ -8337,24 +8344,24 @@ export class Compiler extends DiagnosticEmitter {
|
||||
return module.createBlock(label, conditions, NativeType.I32);
|
||||
}
|
||||
|
||||
/** Reserves the function index / class id for the following `makeIterate` operation. */
|
||||
makeIterateReserve(classInstance: Class): u32 {
|
||||
/** Reserves the function index / class id for the following `makeTraverse` operation. */
|
||||
makeTraverseReserve(classInstance: Class): u32 {
|
||||
var functionTable = this.functionTable;
|
||||
var functionIndex = functionTable.length;
|
||||
functionTable.push(classInstance.iterateName);
|
||||
functionTable.push(classInstance.internalName + "~traverse");
|
||||
return functionIndex;
|
||||
}
|
||||
|
||||
/** Makes the managed iteration function of the specified class. */
|
||||
makeIterate(classInstance: Class, functionIndex: i32): void {
|
||||
/** Makes the managed traversal function of the specified class. */
|
||||
makeTraverse(classInstance: Class, functionIndex: i32): void {
|
||||
var program = this.program;
|
||||
assert(classInstance.type.isManaged(program));
|
||||
|
||||
// check if the class implements a custom iteration function (only valid for library elements)
|
||||
var members = classInstance.members;
|
||||
if (classInstance.isDeclaredInLibrary) {
|
||||
if (members !== null && members.has("__iterate")) {
|
||||
let iterPrototype = members.get("__iterate")!;
|
||||
if (members !== null && members.has("__traverse")) {
|
||||
let iterPrototype = members.get("__traverse")!;
|
||||
assert(iterPrototype.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
let iterInstance = assert(program.resolver.resolveFunction(<FunctionPrototype>iterPrototype, null));
|
||||
assert(iterInstance.is(CommonFlags.PRIVATE | CommonFlags.INSTANCE));
|
||||
@ -8362,10 +8369,9 @@ export class Compiler extends DiagnosticEmitter {
|
||||
assert(!iterInstance.isAny(CommonFlags.AMBIENT | CommonFlags.VIRTUAL));
|
||||
let signature = iterInstance.signature;
|
||||
let parameterTypes = signature.parameterTypes;
|
||||
assert(parameterTypes.length == 1);
|
||||
assert(parameterTypes[0].signatureReference);
|
||||
assert(parameterTypes.length == 0);
|
||||
assert(signature.returnType == Type.void);
|
||||
iterInstance.internalName = classInstance.iterateName;
|
||||
iterInstance.internalName = classInstance.internalName + "~traverse";
|
||||
assert(this.compileFunction(iterInstance));
|
||||
this.ensureFunctionTableEntry(iterInstance);
|
||||
return;
|
||||
@ -8394,29 +8400,28 @@ export class Compiler extends DiagnosticEmitter {
|
||||
|
||||
// remember the function index so we don't recurse infinitely
|
||||
var functionTable = this.functionTable;
|
||||
var functionName = classInstance.iterateName;
|
||||
var functionName = classInstance.internalName + "~traverse";
|
||||
assert(functionIndex < functionTable.length);
|
||||
assert(functionTable[functionIndex] == functionName);
|
||||
|
||||
var fnSig = Signature.makeSignatureString([ usizeType ], Type.void);
|
||||
this.ensureFunctionType([ usizeType ], Type.void);
|
||||
|
||||
// if the class extends a base class, call its hook first
|
||||
var baseInstance = classInstance.base;
|
||||
if (baseInstance) {
|
||||
let baseType = baseInstance.type;
|
||||
let baseClassId = baseInstance.ensureClassId(this);
|
||||
let baseClassId = baseInstance.ensureId(this);
|
||||
assert(baseType.isManaged(program));
|
||||
body.push(
|
||||
// BASECLASS~iterate.call(this, fn)
|
||||
// BASECLASS~traverse.call(this)
|
||||
module.createCall(functionTable[baseClassId], [
|
||||
module.createGetLocal(0, nativeSizeType),
|
||||
module.createGetLocal(1, NativeType.I32)
|
||||
module.createGetLocal(0, nativeSizeType)
|
||||
], NativeType.None)
|
||||
);
|
||||
}
|
||||
|
||||
// iterate references assigned to own fields
|
||||
var markRef = assert(program.markRef);
|
||||
var hasRefFields = false;
|
||||
|
||||
// traverse references assigned to own fields
|
||||
if (members) {
|
||||
for (let member of members.values()) {
|
||||
if (member.kind == ElementKind.FIELD) {
|
||||
@ -8424,13 +8429,14 @@ export class Compiler extends DiagnosticEmitter {
|
||||
let fieldType = (<Field>member).type;
|
||||
if (fieldType.isManaged(program)) {
|
||||
let fieldClass = fieldType.classReference!;
|
||||
let fieldClassId = fieldClass.ensureClassId(this);
|
||||
let fieldClassId = fieldClass.ensureId(this);
|
||||
let fieldOffset = (<Field>member).memoryOffset;
|
||||
assert(fieldOffset >= 0);
|
||||
hasRefFields = true;
|
||||
body.push(
|
||||
// if ($2 = value) { fn($2); FIELDCLASS~iterate($2, fn); }
|
||||
// if ($1 = value) FIELDCLASS~traverse($1)
|
||||
module.createIf(
|
||||
module.createTeeLocal(2,
|
||||
module.createTeeLocal(1,
|
||||
module.createLoad(
|
||||
nativeSizeSize,
|
||||
false,
|
||||
@ -8440,15 +8446,11 @@ export class Compiler extends DiagnosticEmitter {
|
||||
)
|
||||
),
|
||||
module.createBlock(null, [
|
||||
module.createCallIndirect(
|
||||
module.createGetLocal(1, NativeType.I32),
|
||||
[
|
||||
module.createGetLocal(2, nativeSizeType)
|
||||
], fnSig
|
||||
),
|
||||
module.createCall(markRef.internalName, [
|
||||
module.createGetLocal(1, nativeSizeType)
|
||||
], NativeType.None),
|
||||
module.createCall(functionTable[fieldClassId], [
|
||||
module.createGetLocal(2, nativeSizeType),
|
||||
module.createGetLocal(1, NativeType.I32)
|
||||
module.createGetLocal(1, nativeSizeType)
|
||||
], NativeType.None)
|
||||
])
|
||||
)
|
||||
@ -8459,10 +8461,12 @@ export class Compiler extends DiagnosticEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
if (hasRefFields) this.compileFunction(markRef);
|
||||
|
||||
// add the function to the module and return its table index
|
||||
module.addFunction(
|
||||
functionName,
|
||||
this.ensureFunctionType([ Type.u32 ], Type.void, options.usizeType),
|
||||
this.ensureFunctionType(null, Type.void, options.usizeType),
|
||||
members ? [ nativeSizeType ] : null,
|
||||
module.createBlock(null, body)
|
||||
);
|
||||
|
@ -389,6 +389,8 @@ export class Program extends DiagnosticEmitter {
|
||||
retainRef: Function | null = null;
|
||||
/** Reference release implementation, if present: `__ref_release(ref: usize): void` */
|
||||
releaseRef: Function | null = null;
|
||||
/** Reference mark implementation, if present: `__ref_mark(ref: usize): void` */
|
||||
markRef: Function | null = null;
|
||||
|
||||
/** Next class id. */
|
||||
nextClassId: u32 = 1;
|
||||
@ -861,6 +863,9 @@ export class Program extends DiagnosticEmitter {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.unlinkRef = this.resolver.resolveFunction(<FunctionPrototype>element, null);
|
||||
}
|
||||
element = assert(this.lookupGlobal("__ref_mark"));
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
this.markRef = this.resolver.resolveFunction(<FunctionPrototype>element, null);
|
||||
this.collectorKind = CollectorKind.TRACING;
|
||||
} else if (element = this.lookupGlobal("__ref_retain")) {
|
||||
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
|
||||
@ -3012,7 +3017,7 @@ export class Class extends TypedElement {
|
||||
private _id: u32 = 0;
|
||||
|
||||
/** Ensures that this class has an id. */
|
||||
ensureClassId(compiler: Compiler): i32 {
|
||||
ensureId(compiler: Compiler): i32 {
|
||||
var id = this._id;
|
||||
if (!id) {
|
||||
assert(!this.hasDecorator(DecoratorFlags.UNMANAGED));
|
||||
@ -3022,8 +3027,8 @@ export class Class extends TypedElement {
|
||||
// class's id so it can call the id directly, which avoids to generate
|
||||
// a helper function with a big switch mapping ids to function indexes.
|
||||
// here: might be called recursively in makeIterate, so reserve the id.
|
||||
this._id = id = compiler.makeIterateReserve(this);
|
||||
compiler.makeIterate(this, id);
|
||||
this._id = id = compiler.makeTraverseReserve(this);
|
||||
compiler.makeTraverse(this, id);
|
||||
} else {
|
||||
// counting GC or none just increments without any iterate functions
|
||||
this._id = id = program.nextClassId++;
|
||||
@ -3053,11 +3058,6 @@ export class Class extends TypedElement {
|
||||
);
|
||||
}
|
||||
|
||||
/** Gets the name of this class's GC iteration function. */
|
||||
get iterateName(): string {
|
||||
return this.internalName + "~iterate";
|
||||
}
|
||||
|
||||
/** Constructs a new class. */
|
||||
constructor(
|
||||
/** Name incl. type parameters, i.e. `Foo<i32>`. */
|
||||
|
Reference in New Issue
Block a user