Make sure all roots are iterated by delaying builtin generation; Cleanup

This commit is contained in:
dcodeIO
2018-07-20 20:32:25 +02:00
parent 41ad2f8a70
commit 2fa7d6678c
11 changed files with 411 additions and 871 deletions

View File

@ -2629,8 +2629,7 @@ export function compileCall(
// gc
case "gc.iterateRoots": {
// TOOD: make it so that this can only be called from a library file?
case "iterateRoots": {
if (typeArguments) {
compiler.error(
DiagnosticCode.Type_0_is_not_generic,
@ -2661,49 +2660,10 @@ export function compileCall(
);
return module.createUnreachable();
}
let exprs = new Array<ExpressionRef>();
for (let element of compiler.program.elementsLookup.values()) {
if (element.kind != ElementKind.GLOBAL) continue;
let global = <Global>element;
let classReference = global.type.classReference;
if (
global.is(CommonFlags.COMPILED) &&
classReference !== null &&
!classReference.hasDecorator(DecoratorFlags.UNMANAGED)
) {
if (global.is(CommonFlags.INLINED)) {
let value = global.constantIntegerValue;
exprs.push(
module.createCallIndirect(
expr,
[
compiler.options.isWasm64
? module.createI64(i64_low(value), i64_high(value))
: module.createI32(i64_low(value))
],
signatureReference.toSignatureString()
)
);
} else {
exprs.push(
module.createCallIndirect(
expr,
[
module.createGetGlobal(
global.internalName,
compiler.options.nativeSizeType
)
],
signatureReference.toSignatureString()
)
);
}
}
}
compiler.currentType = Type.void;
return exprs.length
? module.createBlock(null, exprs)
: module.createNop();
// just emit a call even if the function doesn't yet exist
compiler.needsIterateRoots = true;
return module.createCall("~iterateRoots", [ expr ], NativeType.None);
}
}
var expr = deferASMCall(compiler, prototype, operands, contextualType, reportNode);
@ -2977,3 +2937,54 @@ export function compileAbort(
module.createUnreachable()
]);
}
/** Compiles the iterateRoots function if requires. */
export function compileIterateRoots(compiler: Compiler): void {
var module = compiler.module;
var exprs = new Array<ExpressionRef>();
for (let element of compiler.program.elementsLookup.values()) {
if (element.kind != ElementKind.GLOBAL) continue;
let global = <Global>element;
let classReference = global.type.classReference;
if (
global.is(CommonFlags.COMPILED) &&
classReference !== null &&
!classReference.hasDecorator(DecoratorFlags.UNMANAGED)
) {
if (global.is(CommonFlags.INLINED)) {
let value = global.constantIntegerValue;
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))
],
"iv"
)
);
} else {
exprs.push(
module.createCallIndirect(
module.createGetLocal(0, NativeType.I32),
[
module.createGetGlobal(
global.internalName,
compiler.options.nativeSizeType
)
],
"iv"
)
);
}
}
}
var typeRef = compiler.ensureFunctionType([ Type.i32 ], Type.void);
module.addFunction("~iterateRoots", typeRef, [],
exprs.length
? module.createBlock(null, exprs)
: module.createNop()
);
}

View File

@ -5,8 +5,9 @@
import {
compileCall as compileBuiltinCall,
compileAllocate as compileBuiltinAllocate,
compileAbort as compileBuiltinAbort
compileAllocate,
compileAbort,
compileIterateRoots
} from "./builtins";
import {
@ -286,6 +287,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;
/** Compiles a {@link Program} to a {@link Module} using the specified options. */
static compile(program: Program, options: Options | null = null): Module {
@ -408,6 +411,9 @@ export class Compiler extends DiagnosticEmitter {
this.makeModuleExport(name, moduleExport.element);
}
// set up gc
if (this.needsIterateRoots) compileIterateRoots(this);
return module;
}
@ -974,7 +980,7 @@ export class Compiler extends DiagnosticEmitter {
}
/** Either reuses or creates the function type matching the specified signature. */
private ensureFunctionType(
ensureFunctionType(
parameterTypes: Type[] | null,
returnType: Type,
thisType: Type | null = null
@ -2022,7 +2028,7 @@ export class Compiler extends DiagnosticEmitter {
flow.set(FlowFlags.RETURNS);
// TODO: requires exception-handling spec.
return compileBuiltinAbort(this, null, statement);
return compileAbort(this, null, statement);
}
compileTryStatement(statement: TryStatement): ExpressionRef {
@ -6524,7 +6530,7 @@ export class Compiler extends DiagnosticEmitter {
// allocate a new instance first and assign 'this' to the temp. local
exprs[0] = module.createSetLocal(
tempLocal.index,
compileBuiltinAllocate(this, classReference, expression)
compileAllocate(this, classReference, expression)
);
// once all field values have been set, return 'this'
@ -7497,7 +7503,7 @@ export class Compiler extends DiagnosticEmitter {
var initializers = new Array<ExpressionRef>();
initializers.push(
module.createSetLocal(tempLocal.index,
compileBuiltinAllocate(this, classInstance, reportNode)
compileAllocate(this, classInstance, reportNode)
)
);