Cache strings shared with Binaryen

This commit is contained in:
dcode 2019-01-27 02:08:04 +01:00
parent 918a40eb7d
commit 2fe228ff00

View File

@ -386,13 +386,12 @@ export class Module {
result: NativeType, result: NativeType,
paramTypes: NativeType[] | null paramTypes: NativeType[] | null
): FunctionRef { ): FunctionRef {
var cStr = allocString(name); var cStr = this.allocStringCached(name);
var cArr = allocI32Array(paramTypes); var cArr = allocI32Array(paramTypes);
try { try {
return _BinaryenAddFunctionType(this.ref, cStr, result, cArr, paramTypes ? paramTypes.length : 0); return _BinaryenAddFunctionType(this.ref, cStr, result, cArr, paramTypes ? paramTypes.length : 0);
} finally { } finally {
memory.free(cArr); memory.free(cArr);
memory.free(cStr);
} }
} }
@ -409,12 +408,8 @@ export class Module {
} }
removeFunctionType(name: string): void { removeFunctionType(name: string): void {
var cStr = allocString(name); var cStr = this.allocStringCached(name);
try { _BinaryenRemoveFunctionType(this.ref, cStr);
_BinaryenRemoveFunctionType(this.ref, cStr);
} finally {
memory.free(cStr);
}
} }
// constants // constants
@ -465,13 +460,12 @@ export class Module {
name: string | null = null, name: string | null = null,
operands: ExpressionRef[] | null = null operands: ExpressionRef[] | null = null
): ExpressionRef { ): ExpressionRef {
var cStr = allocString(name); var cStr = this.allocStringCached(name);
var cArr = allocPtrArray(operands); var cArr = allocPtrArray(operands);
try { try {
return _BinaryenHost(this.ref, op, cStr, cArr, operands ? (<ExpressionRef[]>operands).length : 0); return _BinaryenHost(this.ref, op, cStr, cArr, operands ? (<ExpressionRef[]>operands).length : 0);
} finally { } finally {
memory.free(cArr); memory.free(cArr);
memory.free(cStr);
} }
} }
@ -493,12 +487,8 @@ export class Module {
name: string, name: string,
type: NativeType type: NativeType
): ExpressionRef { ): ExpressionRef {
var cStr = allocString(name); var cStr = this.allocStringCached(name);
try { return _BinaryenGetGlobal(this.ref, cStr, type);
return _BinaryenGetGlobal(this.ref, cStr, type);
} finally {
memory.free(cStr);
}
} }
createLoad( createLoad(
@ -591,12 +581,8 @@ export class Module {
name: string, name: string,
value: ExpressionRef value: ExpressionRef
): ExpressionRef { ): ExpressionRef {
var cStr = allocString(name); var cStr = this.allocStringCached(name);
try { return _BinaryenSetGlobal(this.ref, cStr, value);
return _BinaryenSetGlobal(this.ref, cStr, value);
} finally {
memory.free(cStr);
}
} }
createBlock( createBlock(
@ -604,13 +590,12 @@ export class Module {
children: ExpressionRef[], children: ExpressionRef[],
type: NativeType = NativeType.None type: NativeType = NativeType.None
): ExpressionRef { ): ExpressionRef {
var cStr = allocString(label); var cStr = this.allocStringCached(label);
var cArr = allocPtrArray(children); var cArr = allocPtrArray(children);
try { try {
return _BinaryenBlock(this.ref, cStr, cArr, children.length, type); return _BinaryenBlock(this.ref, cStr, cArr, children.length, type);
} finally { } finally {
memory.free(cArr); memory.free(cArr);
memory.free(cStr);
} }
} }
@ -619,12 +604,8 @@ export class Module {
condition: ExpressionRef = 0, condition: ExpressionRef = 0,
value: ExpressionRef = 0 value: ExpressionRef = 0
): ExpressionRef { ): ExpressionRef {
var cStr = allocString(label); var cStr = this.allocStringCached(label);
try { return _BinaryenBreak(this.ref, cStr, condition, value);
return _BinaryenBreak(this.ref, cStr, condition, value);
} finally {
memory.free(cStr);
}
} }
createDrop( createDrop(
@ -637,12 +618,8 @@ export class Module {
label: string | null, label: string | null,
body: ExpressionRef body: ExpressionRef
): ExpressionRef { ): ExpressionRef {
var cStr = allocString(label); var cStr = this.allocStringCached(label);
try { return _BinaryenLoop(this.ref, cStr, body);
return _BinaryenLoop(this.ref, cStr, body);
} finally {
memory.free(cStr);
}
} }
createIf( createIf(
@ -680,16 +657,14 @@ export class Module {
var numNames = names.length; var numNames = names.length;
var strs = new Array<usize>(numNames); var strs = new Array<usize>(numNames);
for (let i = 0; i < numNames; ++i) { for (let i = 0; i < numNames; ++i) {
strs[i] = allocString(names[i]); strs[i] = this.allocStringCached(names[i]);
} }
var cArr = allocI32Array(strs); var cArr = allocI32Array(strs);
var cStr = allocString(defaultName); var cStr = this.allocStringCached(defaultName);
try { try {
return _BinaryenSwitch(this.ref, cArr, numNames, cStr, condition, value); return _BinaryenSwitch(this.ref, cArr, numNames, cStr, condition, value);
} finally { } finally {
memory.free(cStr);
memory.free(cArr); memory.free(cArr);
for (let i = numNames - 1; i >= 0; --i) memory.free(strs[i]);
} }
} }
@ -698,13 +673,12 @@ export class Module {
operands: ExpressionRef[] | null, operands: ExpressionRef[] | null,
returnType: NativeType returnType: NativeType
): ExpressionRef { ): ExpressionRef {
var cStr = allocString(target); var cStr = this.allocStringCached(target);
var cArr = allocPtrArray(operands); var cArr = allocPtrArray(operands);
try { try {
return _BinaryenCall(this.ref, cStr, cArr, operands && operands.length || 0, returnType); return _BinaryenCall(this.ref, cStr, cArr, operands && operands.length || 0, returnType);
} finally { } finally {
memory.free(cArr); memory.free(cArr);
memory.free(cStr);
} }
} }
@ -713,12 +687,11 @@ export class Module {
operands: ExpressionRef[] | null, operands: ExpressionRef[] | null,
typeName: string typeName: string
): ExpressionRef { ): ExpressionRef {
var cStr = this.allocStringCached(typeName);
var cArr = allocPtrArray(operands); var cArr = allocPtrArray(operands);
var cStr = allocString(typeName);
try { try {
return _BinaryenCallIndirect(this.ref, index, cArr, operands && operands.length || 0, cStr); return _BinaryenCallIndirect(this.ref, index, cArr, operands && operands.length || 0, cStr);
} finally { } finally {
memory.free(cStr);
memory.free(cArr); memory.free(cArr);
} }
} }
@ -735,23 +708,15 @@ export class Module {
mutable: bool, mutable: bool,
initializer: ExpressionRef initializer: ExpressionRef
): GlobalRef { ): GlobalRef {
var cStr = allocString(name); var cStr = this.allocStringCached(name);
try { return _BinaryenAddGlobal(this.ref, cStr, type, mutable ? 1 : 0, initializer);
return _BinaryenAddGlobal(this.ref, cStr, type, mutable ? 1 : 0, initializer);
} finally {
memory.free(cStr);
}
} }
removeGlobal( removeGlobal(
name: string name: string
): void { ): void {
var cStr = allocString(name); var cStr = this.allocStringCached(name);
try { _BinaryenRemoveGlobal(this.ref, cStr);
_BinaryenRemoveGlobal(this.ref, cStr);
} finally {
memory.free(cStr);
}
} }
addFunction( addFunction(
@ -760,32 +725,25 @@ export class Module {
varTypes: NativeType[] | null, varTypes: NativeType[] | null,
body: ExpressionRef body: ExpressionRef
): FunctionRef { ): FunctionRef {
var cStr = allocString(name); var cStr = this.allocStringCached(name);
var cArr = allocI32Array(varTypes); var cArr = allocI32Array(varTypes);
try { try {
return _BinaryenAddFunction(this.ref, cStr, type, cArr, varTypes ? varTypes.length : 0, body); return _BinaryenAddFunction(this.ref, cStr, type, cArr, varTypes ? varTypes.length : 0, body);
} finally { } finally {
memory.free(cArr); memory.free(cArr);
memory.free(cStr);
} }
} }
removeFunction(name: string): void { removeFunction(name: string): void {
var cStr = allocString(name); var cStr = this.allocStringCached(name);
try { _BinaryenRemoveFunction(this.ref, cStr);
_BinaryenRemoveFunction(this.ref, cStr);
} finally {
memory.free(cStr);
}
} }
private cachedTemporaryName: usize = 0;
private hasTemporaryFunction: bool = false; private hasTemporaryFunction: bool = false;
addTemporaryFunction(result: NativeType, paramTypes: NativeType[] | null, body: ExpressionRef): FunctionRef { addTemporaryFunction(result: NativeType, paramTypes: NativeType[] | null, body: ExpressionRef): FunctionRef {
this.hasTemporaryFunction = assert(!this.hasTemporaryFunction); this.hasTemporaryFunction = assert(!this.hasTemporaryFunction);
var tempName = this.cachedTemporaryName; var tempName = this.allocStringCached("");
if (!tempName) this.cachedTemporaryName = tempName = allocString(""); // works because strings are interned
var cArr = allocI32Array(paramTypes); var cArr = allocI32Array(paramTypes);
try { try {
let typeRef = _BinaryenAddFunctionType(this.ref, tempName, result, cArr, paramTypes ? paramTypes.length : 0); let typeRef = _BinaryenAddFunctionType(this.ref, tempName, result, cArr, paramTypes ? paramTypes.length : 0);
@ -797,7 +755,7 @@ export class Module {
removeTemporaryFunction(): void { removeTemporaryFunction(): void {
this.hasTemporaryFunction = !assert(this.hasTemporaryFunction); this.hasTemporaryFunction = !assert(this.hasTemporaryFunction);
var tempName = assert(this.cachedTemporaryName); var tempName = this.allocStringCached("");
_BinaryenRemoveFunction(this.ref, tempName); _BinaryenRemoveFunction(this.ref, tempName);
_BinaryenRemoveFunctionType(this.ref, tempName); _BinaryenRemoveFunctionType(this.ref, tempName);
} }
@ -806,65 +764,41 @@ export class Module {
internalName: string, internalName: string,
externalName: string externalName: string
): ExportRef { ): ExportRef {
var cStr1 = allocString(internalName); var cStr1 = this.allocStringCached(internalName);
var cStr2 = allocString(externalName); var cStr2 = this.allocStringCached(externalName);
try { return _BinaryenAddFunctionExport(this.ref, cStr1, cStr2);
return _BinaryenAddFunctionExport(this.ref, cStr1, cStr2);
} finally {
memory.free(cStr2);
memory.free(cStr1);
}
} }
addTableExport( addTableExport(
internalName: string, internalName: string,
externalName: string externalName: string
): ExportRef { ): ExportRef {
var cStr1 = allocString(internalName); var cStr1 = this.allocStringCached(internalName);
var cStr2 = allocString(externalName); var cStr2 = this.allocStringCached(externalName);
try { return _BinaryenAddTableExport(this.ref, cStr1, cStr2);
return _BinaryenAddTableExport(this.ref, cStr1, cStr2);
} finally {
memory.free(cStr2);
memory.free(cStr1);
}
} }
addMemoryExport( addMemoryExport(
internalName: string, internalName: string,
externalName: string externalName: string
): ExportRef { ): ExportRef {
var cStr1 = allocString(internalName); var cStr1 = this.allocStringCached(internalName);
var cStr2 = allocString(externalName); var cStr2 = this.allocStringCached(externalName);
try { return _BinaryenAddMemoryExport(this.ref, cStr1, cStr2);
return _BinaryenAddMemoryExport(this.ref, cStr1, cStr2);
} finally {
memory.free(cStr2);
memory.free(cStr1);
}
} }
addGlobalExport( addGlobalExport(
internalName: string, internalName: string,
externalName: string externalName: string
): ExportRef { ): ExportRef {
var cStr1 = allocString(internalName); var cStr1 = this.allocStringCached(internalName);
var cStr2 = allocString(externalName); var cStr2 = this.allocStringCached(externalName);
try { return _BinaryenAddGlobalExport(this.ref, cStr1, cStr2);
return _BinaryenAddGlobalExport(this.ref, cStr1, cStr2);
} finally {
memory.free(cStr2);
memory.free(cStr1);
}
} }
removeExport(externalName: string): void { removeExport(externalName: string): void {
var cStr = allocString(externalName); var cStr = this.allocStringCached(externalName);
try { _BinaryenRemoveExport(this.ref, cStr);
_BinaryenRemoveExport(this.ref, cStr);
} finally {
memory.free(cStr);
}
} }
addFunctionImport( addFunctionImport(
@ -873,16 +807,10 @@ export class Module {
externalBaseName: string, externalBaseName: string,
functionType: FunctionTypeRef functionType: FunctionTypeRef
): ImportRef { ): ImportRef {
var cStr1 = allocString(internalName); var cStr1 = this.allocStringCached(internalName);
var cStr2 = allocString(externalModuleName); var cStr2 = this.allocStringCached(externalModuleName);
var cStr3 = allocString(externalBaseName); var cStr3 = this.allocStringCached(externalBaseName);
try { return _BinaryenAddFunctionImport(this.ref, cStr1, cStr2, cStr3, functionType);
return _BinaryenAddFunctionImport(this.ref, cStr1, cStr2, cStr3, functionType);
} finally {
memory.free(cStr3);
memory.free(cStr2);
memory.free(cStr1);
}
} }
addTableImport( addTableImport(
@ -890,16 +818,10 @@ export class Module {
externalModuleName: string, externalModuleName: string,
externalBaseName: string externalBaseName: string
): ImportRef { ): ImportRef {
var cStr1 = allocString(internalName); var cStr1 = this.allocStringCached(internalName);
var cStr2 = allocString(externalModuleName); var cStr2 = this.allocStringCached(externalModuleName);
var cStr3 = allocString(externalBaseName); var cStr3 = this.allocStringCached(externalBaseName);
try { return _BinaryenAddTableImport(this.ref, cStr1, cStr2, cStr3);
return _BinaryenAddTableImport(this.ref, cStr1, cStr2, cStr3);
} finally {
memory.free(cStr3);
memory.free(cStr2);
memory.free(cStr1);
}
} }
addMemoryImport( addMemoryImport(
@ -908,16 +830,10 @@ export class Module {
externalBaseName: string, externalBaseName: string,
shared: bool = false, shared: bool = false,
): ImportRef { ): ImportRef {
var cStr1 = allocString(internalName); var cStr1 = this.allocStringCached(internalName);
var cStr2 = allocString(externalModuleName); var cStr2 = this.allocStringCached(externalModuleName);
var cStr3 = allocString(externalBaseName); var cStr3 = this.allocStringCached(externalBaseName);
try { return _BinaryenAddMemoryImport(this.ref, cStr1, cStr2, cStr3, shared);
return _BinaryenAddMemoryImport(this.ref, cStr1, cStr2, cStr3, shared);
} finally {
memory.free(cStr3);
memory.free(cStr2);
memory.free(cStr1);
}
} }
addGlobalImport( addGlobalImport(
@ -926,16 +842,10 @@ export class Module {
externalBaseName: string, externalBaseName: string,
globalType: NativeType globalType: NativeType
): ImportRef { ): ImportRef {
var cStr1 = allocString(internalName); var cStr1 = this.allocStringCached(internalName);
var cStr2 = allocString(externalModuleName); var cStr2 = this.allocStringCached(externalModuleName);
var cStr3 = allocString(externalBaseName); var cStr3 = this.allocStringCached(externalBaseName);
try { return _BinaryenAddGlobalImport(this.ref, cStr1, cStr2, cStr3, globalType);
return _BinaryenAddGlobalImport(this.ref, cStr1, cStr2, cStr3, globalType);
} finally {
memory.free(cStr3);
memory.free(cStr2);
memory.free(cStr1);
}
} }
/** Unlimited memory constant. */ /** Unlimited memory constant. */
@ -949,7 +859,7 @@ export class Module {
exportName: string | null = null, exportName: string | null = null,
shared: bool = false shared: bool = false
): void { ): void {
var cStr = allocString(exportName); var cStr = this.allocStringCached(exportName);
var k = segments.length; var k = segments.length;
var segs = new Array<usize>(k); var segs = new Array<usize>(k);
var offs = new Array<ExpressionRef>(k); var offs = new Array<ExpressionRef>(k);
@ -973,7 +883,6 @@ export class Module {
memory.free(cArr2); memory.free(cArr2);
memory.free(cArr1); memory.free(cArr1);
for (let i = k - 1; i >= 0; --i) memory.free(segs[i]); for (let i = k - 1; i >= 0; --i) memory.free(segs[i]);
memory.free(cStr);
} }
} }
@ -985,14 +894,13 @@ export class Module {
var numNames = funcs.length; var numNames = funcs.length;
var names = new Array<usize>(numNames); var names = new Array<usize>(numNames);
for (let i = 0; i < numNames; ++i) { for (let i = 0; i < numNames; ++i) {
names[i] = allocString(funcs[i]); names[i] = this.allocStringCached(funcs[i]);
} }
var cArr = allocI32Array(names); var cArr = allocI32Array(names);
try { try {
_BinaryenSetFunctionTable(this.ref, initial, maximum, cArr, numNames); _BinaryenSetFunctionTable(this.ref, initial, maximum, cArr, numNames);
} finally { } finally {
memory.free(cArr); memory.free(cArr);
for (let i = numNames; i >= 0; --i) memory.free(names[i]);
} }
} }
@ -1047,7 +955,6 @@ export class Module {
} }
} }
private cachedPrecomputeName: usize = 0; // for free'ing
private cachedPrecomputeNames: usize = 0; private cachedPrecomputeNames: usize = 0;
precomputeExpression(expr: ExpressionRef): ExpressionRef { precomputeExpression(expr: ExpressionRef): ExpressionRef {
@ -1064,9 +971,7 @@ export class Module {
var func = this.addTemporaryFunction(type, null, expr); var func = this.addTemporaryFunction(type, null, expr);
var names = this.cachedPrecomputeNames; var names = this.cachedPrecomputeNames;
if (!names) { if (!names) {
let name = allocString("precompute"); this.cachedPrecomputeNames = names = allocI32Array([ this.allocStringCached("precompute") ]);
this.cachedPrecomputeName = name;
this.cachedPrecomputeNames = names = allocI32Array([ name ]);
} }
_BinaryenFunctionRunPasses(func, this.ref, names, 1); _BinaryenFunctionRunPasses(func, this.ref, names, 1);
expr = _BinaryenFunctionGetBody(func); expr = _BinaryenFunctionGetBody(func);
@ -1116,12 +1021,23 @@ export class Module {
throw new Error("not implemented"); // JS glue overrides this throw new Error("not implemented"); // JS glue overrides this
} }
private cachedStrings: Map<string,usize> = new Map();
private allocStringCached(str: string | null): usize {
if (str == null) return 0;
if (cachedStrings.has(str)) return <usize>cachedStrings.get(str);
var ptr = allocString(str);
cachedStrings.set(str, ptr);
return ptr;
}
dispose(): void { dispose(): void {
assert(this.ref); assert(this.ref);
for (let ptr of this.cachedStrings.values()) memory.free(ptr);
this.cachedStrings = new Map();
memory.free(this.cachedByValue); memory.free(this.cachedByValue);
memory.free(this.cachedTemporaryName);
memory.free(this.cachedPrecomputeName);
memory.free(this.cachedPrecomputeNames); memory.free(this.cachedPrecomputeNames);
this.cachedPrecomputeNames = 0;
_BinaryenModuleDispose(this.ref); _BinaryenModuleDispose(this.ref);
this.ref = 0; this.ref = 0;
} }
@ -1593,8 +1509,11 @@ function stringLengthUTF8(str: string): usize {
return len; return len;
} }
var cachedStrings = new Map<string | null,usize>();
function allocString(str: string | null): usize { function allocString(str: string | null): usize {
if (str == null) return 0; if (str == null) return 0;
if (cachedStrings.has(str)) return <usize>cachedStrings.get(str);
var ptr = memory.allocate(stringLengthUTF8(str) + 1); var ptr = memory.allocate(stringLengthUTF8(str) + 1);
// the following is based on Emscripten's stringToUTF8Array // the following is based on Emscripten's stringToUTF8Array
var idx = ptr; var idx = ptr;
@ -1633,6 +1552,7 @@ function allocString(str: string | null): usize {
} }
} }
store<u8>(idx, 0); store<u8>(idx, 0);
cachedStrings.set(str, ptr);
return ptr; return ptr;
} }