diff --git a/Python/emscripten_trampoline.c b/Python/emscripten_trampoline.c index f51cd53896faf9..d7c74041e3187a 100644 --- a/Python/emscripten_trampoline.c +++ b/Python/emscripten_trampoline.c @@ -21,7 +21,7 @@ typedef int (*CountArgsFunc)(PyCFunctionWithKeywords func); EMSCRIPTEN_KEEPALIVE const int _PyEM_EMSCRIPTEN_COUNT_ARGS_OFFSET = offsetof(_PyRuntimeState, emscripten_count_args_function); EM_JS(CountArgsFunc, _PyEM_GetCountArgsPtr, (), { - return Module._PyEM_CountArgsPtr; // initialized below + return Module._PyEM_CountArgsPtr; // initialized below } // Binary module for the checks. It has to be done in web assembly because // clang/llvm have no support yet for the reference types yet. In fact, the wasm @@ -33,162 +33,162 @@ EM_JS(CountArgsFunc, _PyEM_GetCountArgsPtr, (), { // gets us the output we need. // // (module -// (type $type0 (func (param) (result i32))) -// (type $type1 (func (param i32) (result i32))) -// (type $type2 (func (param i32 i32) (result i32))) -// (type $type3 (func (param i32 i32 i32) (result i32))) -// (type $type4 (func (param i32 i32 i32 i32) (result i32))) -// (type $blocktype (func (param i32) (result))) -// (table $funcs (import "e" "t") 0 funcref) -// (export "f" (func $f)) -// (func $f (param $fptr i32) (result i32) -// (local $fref funcref) -// local.get $fptr -// table.get $funcs -// local.tee $fref -// ref.test $type4 -// (block $b (type $blocktype) -// i32.eqz -// br_if $b -// i32.const 4 -// return +// (type $type0 (func (param) (result i32))) +// (type $type1 (func (param i32) (result i32))) +// (type $type2 (func (param i32 i32) (result i32))) +// (type $type3 (func (param i32 i32 i32) (result i32))) +// (type $type4 (func (param i32 i32 i32 i32) (result i32))) +// (type $blocktype (func (param i32) (result))) +// (table $funcs (import "e" "t") 0 funcref) +// (export "f" (func $f)) +// (func $f (param $fptr i32) (result i32) +// (local $fref funcref) +// local.get $fptr +// table.get $funcs +// local.tee $fref +// ref.test $type4 +// (block $b (type $blocktype) +// i32.eqz +// br_if $b +// i32.const 4 +// return +// ) +// local.get $fref +// ref.test $type3 +// (block $b (type $blocktype) +// i32.eqz +// br_if $b +// i32.const 3 +// return +// ) +// local.get $fref +// ref.test $type2 +// (block $b (type $blocktype) +// i32.eqz +// br_if $b +// i32.const 2 +// return +// ) +// local.get $fref +// ref.test $type1 +// (block $b (type $blocktype) +// i32.eqz +// br_if $b +// i32.const 1 +// return +// ) +// local.get $fref +// ref.test $type0 +// (block $b (type $blocktype) +// i32.eqz +// br_if $b +// i32.const 0 +// return +// ) +// i32.const -1 // ) -// local.get $fref -// ref.test $type3 -// (block $b (type $blocktype) -// i32.eqz -// br_if $b -// i32.const 3 -// return -// ) -// local.get $fref -// ref.test $type2 -// (block $b (type $blocktype) -// i32.eqz -// br_if $b -// i32.const 2 -// return -// ) -// local.get $fref -// ref.test $type1 -// (block $b (type $blocktype) -// i32.eqz -// br_if $b -// i32.const 1 -// return -// ) -// local.get $fref -// ref.test $type0 -// (block $b (type $blocktype) -// i32.eqz -// br_if $b -// i32.const 0 -// return -// ) -// i32.const -1 -// ) // ) addOnPreRun(() => { - // Try to initialize countArgsFunc - const code = new Uint8Array([ - 0x00, 0x61, 0x73, 0x6d, // \0asm magic number - 0x01, 0x00, 0x00, 0x00, // version 1 - 0x01, 0x23, // Type section, body is 0x23 bytes - 0x06, // 6 entries - 0x60, 0x00, 0x01, 0x7f, // (type $type0 (func (param) (result i32))) - 0x60, 0x01, 0x7f, 0x01, 0x7f, // (type $type1 (func (param i32) (result i32))) - 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, // (type $type2 (func (param i32 i32) (result i32))) - 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, // (type $type3 (func (param i32 i32 i32) (result i32))) - 0x60, 0x04, 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, // (type $type4 (func (param i32 i32 i32 i32) (result i32))) - 0x60, 0x01, 0x7f, 0x00, // (type $blocktype (func (param i32) (result))) - 0x02, 0x09, // Import section, 0x9 byte body - 0x01, // 1 import (table $funcs (import "e" "t") 0 funcref) - 0x01, 0x65, // "e" - 0x01, 0x74, // "t" - 0x01, // importing a table - 0x70, // of entry type funcref - 0x00, 0x00, // table limits: no max, min of 0 - 0x03, 0x02, // Function section - 0x01, 0x01, // We're going to define one function of type 1 (func (param i32) (result i32)) - 0x07, 0x05, // export section - 0x01, // 1 export - 0x01, 0x66, // called "f" - 0x00, // a function - 0x00, // at index 0 + // Try to initialize countArgsFunc + const code = new Uint8Array([ + 0x00, 0x61, 0x73, 0x6d, // \0asm magic number + 0x01, 0x00, 0x00, 0x00, // version 1 + 0x01, 0x23, // Type section, body is 0x23 bytes + 0x06, // 6 entries + 0x60, 0x00, 0x01, 0x7f, // (type $type0 (func (param) (result i32))) + 0x60, 0x01, 0x7f, 0x01, 0x7f, // (type $type1 (func (param i32) (result i32))) + 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, // (type $type2 (func (param i32 i32) (result i32))) + 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, // (type $type3 (func (param i32 i32 i32) (result i32))) + 0x60, 0x04, 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, // (type $type4 (func (param i32 i32 i32 i32) (result i32))) + 0x60, 0x01, 0x7f, 0x00, // (type $blocktype (func (param i32) (result))) + 0x02, 0x09, // Import section, 0x9 byte body + 0x01, // 1 import (table $funcs (import "e" "t") 0 funcref) + 0x01, 0x65, // "e" + 0x01, 0x74, // "t" + 0x01, // importing a table + 0x70, // of entry type funcref + 0x00, 0x00, // table limits: no max, min of 0 + 0x03, 0x02, // Function section + 0x01, 0x01, // We're going to define one function of type 1 (func (param i32) (result i32)) + 0x07, 0x05, // export section + 0x01, // 1 export + 0x01, 0x66, // called "f" + 0x00, // a function + 0x00, // at index 0 - 0x0a, 0x52, // Code section, - 0x01, 0x50, // one entry of length 50 - 0x01, 0x01, 0x70, // one local of type funcref - // Body of the function - 0x20, 0x00, // local.get $fptr - 0x25, 0x00, // table.get $funcs - 0x22, 0x01, // local.tee $fref - 0xfb, 0x14, 0x04, // ref.test $type4 - 0x02, 0x05, // block $b (type $blocktype) - 0x45, // i32.eqz - 0x0d, 0x00, // br_if $b - 0x41, 0x04, // i32.const 4 - 0x0f, // return - 0x0b, // end block + 0x0a, 0x52, // Code section, + 0x01, 0x50, // one entry of length 50 + 0x01, 0x01, 0x70, // one local of type funcref + // Body of the function + 0x20, 0x00, // local.get $fptr + 0x25, 0x00, // table.get $funcs + 0x22, 0x01, // local.tee $fref + 0xfb, 0x14, 0x04, // ref.test $type4 + 0x02, 0x05, // block $b (type $blocktype) + 0x45, // i32.eqz + 0x0d, 0x00, // br_if $b + 0x41, 0x04, // i32.const 4 + 0x0f, // return + 0x0b, // end block - 0x20, 0x01, // local.get $fref - 0xfb, 0x14, 0x03, // ref.test $type3 - 0x02, 0x05, // block $b (type $blocktype) - 0x45, // i32.eqz - 0x0d, 0x00, // br_if $b - 0x41, 0x03, // i32.const 3 - 0x0f, // return - 0x0b, // end block + 0x20, 0x01, // local.get $fref + 0xfb, 0x14, 0x03, // ref.test $type3 + 0x02, 0x05, // block $b (type $blocktype) + 0x45, // i32.eqz + 0x0d, 0x00, // br_if $b + 0x41, 0x03, // i32.const 3 + 0x0f, // return + 0x0b, // end block - 0x20, 0x01, // local.get $fref - 0xfb, 0x14, 0x02, // ref.test $type2 - 0x02, 0x05, // block $b (type $blocktype) - 0x45, // i32.eqz - 0x0d, 0x00, // br_if $b - 0x41, 0x02, // i32.const 2 - 0x0f, // return - 0x0b, // end block + 0x20, 0x01, // local.get $fref + 0xfb, 0x14, 0x02, // ref.test $type2 + 0x02, 0x05, // block $b (type $blocktype) + 0x45, // i32.eqz + 0x0d, 0x00, // br_if $b + 0x41, 0x02, // i32.const 2 + 0x0f, // return + 0x0b, // end block - 0x20, 0x01, // local.get $fref - 0xfb, 0x14, 0x01, // ref.test $type1 - 0x02, 0x05, // block $b (type $blocktype) - 0x45, // i32.eqz - 0x0d, 0x00, // br_if $b - 0x41, 0x01, // i32.const 1 - 0x0f, // return - 0x0b, // end block + 0x20, 0x01, // local.get $fref + 0xfb, 0x14, 0x01, // ref.test $type1 + 0x02, 0x05, // block $b (type $blocktype) + 0x45, // i32.eqz + 0x0d, 0x00, // br_if $b + 0x41, 0x01, // i32.const 1 + 0x0f, // return + 0x0b, // end block - 0x20, 0x01, // local.get $fref - 0xfb, 0x14, 0x00, // ref.test $type0 - 0x02, 0x05, // block $b (type $blocktype) - 0x45, // i32.eqz - 0x0d, 0x00, // br_if $b - 0x41, 0x00, // i32.const 0 - 0x0f, // return - 0x0b, // end block + 0x20, 0x01, // local.get $fref + 0xfb, 0x14, 0x00, // ref.test $type0 + 0x02, 0x05, // block $b (type $blocktype) + 0x45, // i32.eqz + 0x0d, 0x00, // br_if $b + 0x41, 0x00, // i32.const 0 + 0x0f, // return + 0x0b, // end block - 0x41, 0x7f, // i32.const -1 - 0x0b // end function - ]); - let ptr = 0; - try { - const mod = new WebAssembly.Module(code); - const inst = new WebAssembly.Instance(mod, {e: {t: wasmTable}}); - ptr = addFunction(inst.exports.f); - } catch(e) { - // If something goes wrong, we'll null out _PyEM_CountFuncParams and fall - // back to the JS trampoline. - } - Module._PyEM_CountArgsPtr = ptr; - const offset = HEAP32[__PyEM_EMSCRIPTEN_COUNT_ARGS_OFFSET/4]; - HEAP32[__PyRuntime/4 + offset] = ptr; + 0x41, 0x7f, // i32.const -1 + 0x0b // end function + ]); + let ptr = 0; + try { + const mod = new WebAssembly.Module(code); + const inst = new WebAssembly.Instance(mod, {e: {t: wasmTable}}); + ptr = addFunction(inst.exports.f); + } catch(e) { + // If something goes wrong, we'll null out _PyEM_CountFuncParams and fall + // back to the JS trampoline. + } + Module._PyEM_CountArgsPtr = ptr; + const offset = HEAP32[__PyEM_EMSCRIPTEN_COUNT_ARGS_OFFSET/4]; + HEAP32[__PyRuntime/4 + offset] = ptr; }); ); void _Py_EmscriptenTrampoline_Init(_PyRuntimeState *runtime) { - runtime->emscripten_count_args_function = _PyEM_GetCountArgsPtr(); + runtime->emscripten_count_args_function = _PyEM_GetCountArgsPtr(); } // We have to be careful to work correctly with memory snapshots. Even if we are @@ -200,7 +200,7 @@ _Py_EmscriptenTrampoline_Init(_PyRuntimeState *runtime) * Backwards compatible trampoline works with all JS runtimes */ EM_JS(PyObject*, _PyEM_TrampolineCall_JS, (PyCFunctionWithKeywords func, PyObject *arg1, PyObject *arg2, PyObject *arg3), { - return wasmTable.get(func)(arg1, arg2, arg3); + return wasmTable.get(func)(arg1, arg2, arg3); }); typedef PyObject* (*zero_arg)(void); @@ -214,23 +214,23 @@ _PyEM_TrampolineCall(PyCFunctionWithKeywords func, PyObject* args, PyObject* kw) { - CountArgsFunc count_args = _PyRuntime.emscripten_count_args_function; - if (count_args == 0) { - return _PyEM_TrampolineCall_JS(func, self, args, kw); - } - switch (count_args(func)) { - case 0: - return ((zero_arg)func)(); - case 1: - return ((one_arg)func)(self); - case 2: - return ((two_arg)func)(self, args); - case 3: - return ((three_arg)func)(self, args, kw); - default: - PyErr_SetString(PyExc_SystemError, "Handler takes too many arguments"); - return NULL; - } + CountArgsFunc count_args = _PyRuntime.emscripten_count_args_function; + if (count_args == 0) { + return _PyEM_TrampolineCall_JS(func, self, args, kw); + } + switch (count_args(func)) { + case 0: + return ((zero_arg)func)(); + case 1: + return ((one_arg)func)(self); + case 2: + return ((two_arg)func)(self, args); + case 3: + return ((three_arg)func)(self, args, kw); + default: + PyErr_SetString(PyExc_SystemError, "Handler takes too many arguments"); + return NULL; + } } #endif