static array stuff

This commit is contained in:
dcode
2019-03-15 13:13:48 +01:00
parent 968b0321a0
commit 058dc8d4fa
77 changed files with 5634 additions and 4657 deletions

View File

@ -4153,17 +4153,17 @@ function compileTypedArrayGet(
WrapMode.NONE
));
if (getExpressionId(dynamicOffset) == ExpressionId.Const) {
constantOffset = getConstValueI32(dynamicOffset);
constantOffset = getConstValueI32(dynamicOffset) * type.byteSize;
dynamicOffset = 0;
} else if (getExpressionId(dynamicOffset) == ExpressionId.Binary) {
if (getBinaryOp(dynamicOffset) == BinaryOp.AddI32) {
let left = getBinaryLeft(dynamicOffset);
let right = getBinaryRight(dynamicOffset);
if (getExpressionId(left) == ExpressionId.Const) {
constantOffset = getConstValueI32(left);
constantOffset = getConstValueI32(left) * type.byteSize;
dynamicOffset = right;
} else if (getExpressionId(right) == ExpressionId.Const) {
constantOffset = getConstValueI32(right);
constantOffset = getConstValueI32(right) * type.byteSize;
dynamicOffset = left;
}
}

View File

@ -183,10 +183,9 @@ export namespace LibrarySymbols {
export const ALLOCATE = "ALLOCATE";
export const REALLOCATE = "REALLOCATE";
export const DISCARD = "DISCARD";
// gc
export const gc = "gc";
export const register = "register";
export const link = "link";
export const REGISTER = "REGISTER";
export const LINK = "LINK";
export const WRAPARRAY = "WRAPARRAY";
// other
export const length = "length";
export const byteLength = "byteLength";

View File

@ -6693,27 +6693,43 @@ export class Compiler extends DiagnosticEmitter {
}
var arrayPrototype = assert(this.program.arrayPrototype);
var arrayInstance = assert(this.resolver.resolveClass(
<ClassPrototype>arrayPrototype,
[ elementType ],
makeMap()
));
var arrayInstance = assert(this.resolver.resolveClass(arrayPrototype, [ elementType ]));
var arrayType = arrayInstance.type;
// make a static buffer if possible
// if the array is static, make a static arraybuffer segment and wrap it with an array
if (isStatic) {
// let bufferPtr = this.ensureStaticArrayBuffer(elementType, constantValues);
// TODO: runtime.alloc the array header and make it use a copy of the static buffer
let arrayBufferInstance = assert(this.program.arrayBufferInstance);
let wrapArrayPrototype = assert(this.program.wrapArrayPrototype);
let wrapArrayInstance = this.resolver.resolveFunction(wrapArrayPrototype, [ elementType ]);
if (!wrapArrayInstance) {
this.currentType = arrayType;
return module.createUnreachable();
}
let previousFlow = this.currentFlow;
let tempLocal = previousFlow.getTempLocal(arrayBufferInstance.type, false);
let flow = Flow.createInline(previousFlow.parentFunction, wrapArrayInstance);
flow.addScopedAlias("buffer", arrayBufferInstance.type, tempLocal.index);
this.currentFlow = flow;
let body = this.compileFunctionBody(wrapArrayInstance);
body.unshift(
module.createSetLocal(tempLocal.index,
this.ensureStaticArrayBuffer(elementType, constantValues)
)
);
previousFlow.freeTempLocal(tempLocal);
this.currentFlow = previousFlow;
this.currentType = arrayType;
return module.createBlock(flow.inlineReturnLabel, body, this.options.nativeSizeType);
}
// and compile an explicit instantiation
this.currentType = arrayType;
// otherwise compile an explicit instantiation with indexed sets
var setter = arrayInstance.lookupOverload(OperatorKind.INDEXED_SET, true);
if (!setter) {
this.error(
DiagnosticCode.Index_signature_in_type_0_only_permits_reading,
reportNode.range, arrayInstance.internalName
);
this.currentType = arrayType;
return module.createUnreachable();
}
var nativeArrayType = arrayType.toNativeType();
@ -7945,41 +7961,46 @@ export class Compiler extends DiagnosticEmitter {
var module = this.module;
var options = this.options;
var nativeSizeType = options.nativeSizeType;
var classType = classInstance.type;
// ALLOCATE(payloadSize)
// ALLOCATE(payloadSize: usize) -> usize
var allocateInstance = assert(program.allocateInstance);
if (!this.compileFunction(allocateInstance)) return module.createUnreachable();
var alloc = module.createCall(
allocateInstance.internalName, [
options.isWasm64
? module.createI64(classInstance.currentMemoryOffset)
: module.createI32(classInstance.currentMemoryOffset)
// module.createI32(
// ensureGCHook(this, classInstance)
// )
],
nativeSizeType
);
// REGISTER<T>(ref, classId)
if (program.gcImplemented) {
let registerInstance = assert(program.gcRegisterInstance);
if (!this.compileFunction(registerInstance)) return module.createUnreachable();
let tempLocal = this.currentFlow.getAndFreeTempLocal(classInstance.type, false);
alloc = module.createBlock(null, [
module.createCall(
registerInstance.internalName, [
module.createTeeLocal(tempLocal.index, alloc),
module.createI32(classInstance.id)
],
NativeType.None
),
module.createGetLocal(tempLocal.index, nativeSizeType)
], nativeSizeType);
if (!this.compileFunction(allocateInstance)) {
this.currentType = classInstance.type;
return module.createUnreachable();
}
this.currentType = classInstance.type;
return alloc;
// REGISTER<T>(ref: usize) -> usize
var registerPrototype = assert(program.registerPrototype);
var registerInstance = this.resolver.resolveFunction(registerPrototype, [ classType ]);
if (!registerInstance) {
this.currentType = classType;
return module.createUnreachable();
}
// REGISTER<T>(ALLOCATE(sizeof<T>()))
var previousFlow = this.currentFlow;
var tempLocal = previousFlow.getTempLocal(classType, false);
var flow = Flow.createInline(previousFlow.parentFunction, registerInstance);
flow.addScopedAlias("ref", this.options.usizeType, tempLocal.index);
this.currentFlow = flow;
var body = this.compileFunctionBody(registerInstance);
body.unshift(
module.createSetLocal(tempLocal.index,
module.createCall(
allocateInstance.internalName, [
options.isWasm64
? module.createI64(classInstance.currentMemoryOffset)
: module.createI32(classInstance.currentMemoryOffset)
],
nativeSizeType
)
)
);
previousFlow.freeTempLocal(tempLocal);
this.currentFlow = previousFlow;
this.currentType = classType;
return module.createBlock(flow.inlineReturnLabel, body, nativeSizeType);
}
/** Makes the initializers for a class's fields. */

View File

@ -179,7 +179,7 @@ export class Flow {
return flow;
}
/** Creates an inline flow within `currentFunction`. */
/** Creates an inline flow within `parentFunction`. */
static createInline(parentFunction: Function, inlineFunction: Function): Flow {
var flow = Flow.create(parentFunction);
flow.set(FlowFlags.INLINE_CONTEXT);

View File

@ -349,6 +349,12 @@ export class Program extends DiagnosticEmitter {
reallocateInstance: Function | null = null;
/** Runtime discard function. */
discardInstance: Function | null = null;
/** Runtime register function. */
registerPrototype: FunctionPrototype | null = null;
/** Runtime link function. */
linkPrototype: FunctionPrototype | null = null;
/** Runtime wrap array function. */
wrapArrayPrototype: FunctionPrototype | null = null;
/** Next class id. */
nextClassId: u32 = 1;
@ -357,18 +363,10 @@ export class Program extends DiagnosticEmitter {
/** Whether a garbage collector is present or not. */
get gcImplemented(): bool {
return this.gcRegisterInstance !== null;
return this.lookupGlobal("__gc_register") !== null;
}
/** Garbage collector register function called when an object becomes managed. */
gcRegisterInstance: Function | null = null;
/** Garbage collector link function called when a managed object is referenced from a parent. */
gcLinkInstance: Function | null = null;
/** Garbage collector mark function called to on reachable managed objects. */
gcMarkInstance: Function | null = null;
/** Size of a managed object header. */
gcHeaderSize: u32 = 0;
/** Offset of the GC hook. */
gcHookOffset: u32 = 0;
gcMarkInstance: Function | null = null; // FIXME
/** Constructs a new program, optionally inheriting parser diagnostics. */
constructor(
@ -805,6 +803,18 @@ export class Program extends DiagnosticEmitter {
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
this.discardInstance = this.resolver.resolveFunction(<FunctionPrototype>element, null);
}
if (element = this.lookupGlobal(LibrarySymbols.REGISTER)) {
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
this.registerPrototype = <FunctionPrototype>element;
}
if (element = this.lookupGlobal(LibrarySymbols.LINK)) {
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
this.linkPrototype = <FunctionPrototype>element;
}
if (element = this.lookupGlobal(LibrarySymbols.WRAPARRAY)) {
assert(element.kind == ElementKind.FUNCTION_PROTOTYPE);
this.wrapArrayPrototype = <FunctionPrototype>element;
}
}
// mark module exports, i.e. to apply proper wrapping behavior on the boundaries