Skip to content

EMBIND_AOT should AOT method callers #24540

Open
@RReverser

Description

@RReverser

We have emval_methodCallers mechanism used for foo() and foo.call<...>(...) on emscripten::val instances here:

// Leave id 0 undefined. It's not a big deal, but might be confusing
// to have null be a valid method caller.
$emval_methodCallers: [undefined],
$emval_addMethodCaller__deps: ['$emval_methodCallers'],
$emval_addMethodCaller: (caller) => {
var id = emval_methodCallers.length;
emval_methodCallers.push(caller);
return id;
},
_emval_get_method_caller__deps: [
'$emval_addMethodCaller', '$emval_lookupTypes',
'$createNamedFunction', '$emval_returnValue',
],
_emval_get_method_caller: (argCount, argTypes, kind) => {
var GenericWireTypeSize = {{{ 2 * POINTER_SIZE }}};
var types = emval_lookupTypes(argCount, argTypes);
var retType = types.shift();
argCount--; // remove the shifted off return type
#if !DYNAMIC_EXECUTION
var argN = new Array(argCount);
var invokerFunction = (obj, func, destructorsRef, args) => {
var offset = 0;
for (var i = 0; i < argCount; ++i) {
argN[i] = types[i]['readValueFromPointer'](args + offset);
offset += GenericWireTypeSize;
}
var rv = kind === /* CONSTRUCTOR */ 1 ? Reflect.construct(func, argN) : func.apply(obj, argN);
return emval_returnValue(retType, destructorsRef, rv);
};
#else
var functionBody =
`return function (obj, func, destructorsRef, args) {\n`;
var offset = 0;
var argsList = []; // 'obj?, arg0, arg1, arg2, ... , argN'
if (kind === /* FUNCTION */ 0) {
argsList.push('obj');
}
var params = ['retType'];
var args = [retType];
for (var i = 0; i < argCount; ++i) {
argsList.push(`arg${i}`);
params.push(`argType${i}`);
args.push(types[i]);
functionBody +=
` var arg${i} = argType${i}.readValueFromPointer(args${offset ? '+' + offset : ''});\n`;
offset += GenericWireTypeSize;
}
var invoker = kind === /* CONSTRUCTOR */ 1 ? 'new func' : 'func.call';
functionBody +=
` var rv = ${invoker}(${argsList.join(', ')});\n`;
if (!retType.isVoid) {
params.push('emval_returnValue');
args.push(emval_returnValue);
functionBody +=
' return emval_returnValue(retType, destructorsRef, rv);\n';
}
functionBody +=
"};\n";
var invokerFunction = new Function(...params, functionBody)(...args);
#endif
var functionName = `methodCaller<(${types.map(t => t.name).join(', ')}) => ${retType.name}>`;
return emval_addMethodCaller(createNamedFunction(functionName, invokerFunction));
},

Right now it either constructs a JS function from strings on the fly, or uses a slower mechanism with looking up all the types on each invocation.

As far as I can tell, it should be fairly straightforward to add it to the EMBIND_AOT processing so that specialized function is generated during compile-time and then reused. cc @brendandahl

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions