From c7bb1fa15bf70045a1dc7e3256fa63aa70245620 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Mon, 23 Jun 2025 14:38:55 +0100 Subject: [PATCH] [emval] Simplify dynamic invoker creation. NFC --- src/lib/libembind.js | 6 +-- src/lib/libembind_gen.js | 6 +-- src/lib/libembind_shared.js | 2 +- src/lib/libemval.js | 53 +++++++++++---------------- test/code_size/embind_hello_wasm.json | 8 ++-- test/code_size/embind_val_wasm.json | 8 ++-- 6 files changed, 36 insertions(+), 47 deletions(-) diff --git a/src/lib/libembind.js b/src/lib/libembind.js index b46f447ffbed8..e76f744a525a6 100644 --- a/src/lib/libembind.js +++ b/src/lib/libembind.js @@ -668,7 +668,7 @@ var LibraryEmbind = { // TODO: Remove this completely once all function invokers are being dynamically generated. var needsDestructorStack = usesDestructorStack(argTypes); - var returns = (argTypes[0].name !== 'void'); + var returns = !argTypes[0].isVoid; var expectedArgCount = argCount - 2; #if ASSERTIONS @@ -766,8 +766,8 @@ var LibraryEmbind = { var invokerFn = InvokerFunctions[signature](...closureArgs); #else - let [args, invokerFnBody] = createJsInvoker(argTypes, isClassMethodFunc, returns, isAsync); - var invokerFn = new Function(...args, invokerFnBody)(...closureArgs); + let invokerFactory = createJsInvoker(argTypes, isClassMethodFunc, returns, isAsync); + var invokerFn = invokerFactory(...closureArgs); #endif #endif return createNamedFunction(humanName, invokerFn); diff --git a/src/lib/libembind_gen.js b/src/lib/libembind_gen.js index 4b6f2c9f7b42f..519130b2d2863 100644 --- a/src/lib/libembind_gen.js +++ b/src/lib/libembind_gen.js @@ -134,13 +134,13 @@ var LibraryEmbind = { for (const argType of this.argumentTypes) { argTypes.push(this.convertToEmbindType(argType.type)); } - const signature = createJsInvokerSignature(argTypes, !!this.thisType, this.returnType.name !== 'void', this.isAsync) + const signature = createJsInvokerSignature(argTypes, !!this.thisType, !this.returnType.isVoid, this.isAsync) if (emittedFunctions.has(signature)) { return; } emittedFunctions.add(signature); - let [args, body] = createJsInvoker(argTypes, !!this.thisType, this.returnType.name !== 'void', this.isAsync); - out.push(`'${signature}': function(${args.join(',')}) {\n${body}},`); + let invokerFactory = createJsInvoker(argTypes, !!this.thisType, !this.returnType.isVoid, this.isAsync); + out.push(`'${signature}': ${invokerFactory},`); } }, $PointerDefinition: class { diff --git a/src/lib/libembind_shared.js b/src/lib/libembind_shared.js index a9ffea81027f9..fcc4fe1a672c4 100644 --- a/src/lib/libembind_shared.js +++ b/src/lib/libembind_shared.js @@ -293,7 +293,7 @@ var LibraryEmbindShared = { args1.push('checkArgCount', 'minArgs', 'maxArgs'); invokerFnBody = `if (arguments.length !== ${args1.length}){ throw new Error(humanName + "Expected ${args1.length} closure arguments " + arguments.length + " given."); }\n${invokerFnBody}`; #endif - return [args1, invokerFnBody]; + return new Function(args1, invokerFnBody); } }; diff --git a/src/lib/libemval.js b/src/lib/libemval.js index 2c5abc4221ccb..9537680cfb837 100644 --- a/src/lib/libemval.js +++ b/src/lib/libemval.js @@ -297,52 +297,41 @@ var LibraryEmVal = { return emval_returnValue(toReturnWire, destructorsRef, rv); }; #else - var functionBody = - `return function (handle, methodName, destructorsRef, args) {\n`; - - var offset = 0; - var argsList = []; // 'arg0, arg1, arg2, ... , argN' - var params = ['toValue']; - var args = [Emval.toValue]; - for (var i = 0; i < argCount; ++i) { - argsList.push(`arg${i}`); - params.push(`argFromPtr${i}`); - args.push(argFromPtr[i]); - functionBody += - ` var arg${i} = argFromPtr${i}(args${offset ? '+' + offset : ''});\n`; - offset += GenericWireTypeSize; - } - var invoker; + var captures = {'toValue': Emval.toValue}; + var args = argFromPtr.map((argFromPtr, i) => { + var captureName = `argFromPtr${i}`; + captures[captureName] = argFromPtr; + return `${captureName}(args${i ? '+' + i * GenericWireTypeSize : ''})`; + }); + var functionBody; switch (kind){ case {{{ cDefs['internal::EM_INVOKER_KIND::FUNCTION'] }}}: - invoker = 'toValue(handle)'; + functionBody = 'toValue(handle)'; break; case {{{ cDefs['internal::EM_INVOKER_KIND::CONSTRUCTOR'] }}}: - invoker = 'new (toValue(handle))'; + functionBody = 'new (toValue(handle))'; break; case {{{ cDefs['internal::EM_INVOKER_KIND::CAST'] }}}: - invoker = ''; + functionBody = ''; break; case {{{ cDefs['internal::EM_INVOKER_KIND::METHOD'] }}}: - params.push('getStringOrSymbol'); - args.push(getStringOrSymbol); - invoker = 'toValue(handle)[getStringOrSymbol(methodName)]'; + captures['getStringOrSymbol'] = getStringOrSymbol; + functionBody = 'toValue(handle)[getStringOrSymbol(methodName)]'; break; } - functionBody += - ` var rv = ${invoker}(${argsList.join(', ')});\n`; + functionBody += `(${args})`; if (!retType.isVoid) { - params.push('toReturnWire', 'emval_returnValue'); - args.push(toReturnWire, emval_returnValue); - functionBody += - ' return emval_returnValue(toReturnWire, destructorsRef, rv);\n'; + captures['toReturnWire'] = toReturnWire; + captures['emval_returnValue'] = emval_returnValue; + functionBody = `return emval_returnValue(toReturnWire, destructorsRef, ${functionBody})`; } - functionBody += - "};\n"; + functionBody = `return function (handle, methodName, destructorsRef, args) { +${functionBody} +}`; - var invokerFunction = new Function(...params, functionBody)(...args); + var invokerFunction = new Function(Object.keys(captures), functionBody)(...Object.values(captures)); #endif - var functionName = `methodCaller<(${argTypes.map(t => t.name).join(', ')}) => ${retType.name}>`; + var functionName = `methodCaller<(${argTypes.map(t => t.name)}) => ${retType.name}>`; return emval_addMethodCaller(createNamedFunction(functionName, invokerFunction)); }, diff --git a/test/code_size/embind_hello_wasm.json b/test/code_size/embind_hello_wasm.json index a9884cc49d60f..0cdcec6352a1c 100644 --- a/test/code_size/embind_hello_wasm.json +++ b/test/code_size/embind_hello_wasm.json @@ -1,10 +1,10 @@ { "a.html": 552, "a.html.gz": 380, - "a.js": 7266, - "a.js.gz": 3321, + "a.js": 7255, + "a.js.gz": 3318, "a.wasm": 7300, "a.wasm.gz": 3348, - "total": 15118, - "total_gz": 7049 + "total": 15107, + "total_gz": 7046 } diff --git a/test/code_size/embind_val_wasm.json b/test/code_size/embind_val_wasm.json index dd1c00e7322f8..e604a3d847ed5 100644 --- a/test/code_size/embind_val_wasm.json +++ b/test/code_size/embind_val_wasm.json @@ -1,10 +1,10 @@ { "a.html": 552, "a.html.gz": 380, - "a.js": 5367, - "a.js.gz": 2540, + "a.js": 5356, + "a.js.gz": 2531, "a.wasm": 9101, "a.wasm.gz": 4698, - "total": 15020, - "total_gz": 7618 + "total": 15009, + "total_gz": 7609 }