| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| #ifndef Py_EMSCRIPTEN_TRAMPOLINE_H | ||
| #define Py_EMSCRIPTEN_TRAMPOLINE_H | ||
|
|
||
| #include "pycore_runtime.h" // _PyRuntimeState | ||
|
|
||
| /** | ||
| * C function call trampolines to mitigate bad function pointer casts. | ||
| * | ||
| * Section 6.3.2.3, paragraph 8 reads: | ||
| * | ||
| * A pointer to a function of one type may be converted to a pointer to a | ||
| * function of another type and back again; the result shall compare equal to | ||
| * the original pointer. If a converted pointer is used to call a function | ||
| * whose type is not compatible with the pointed-to type, the behavior is | ||
| * undefined. | ||
| * | ||
| * Typical native ABIs ignore additional arguments or fill in missing values | ||
| * with 0/NULL in function pointer cast. Compilers do not show warnings when a | ||
| * function pointer is explicitly casted to an incompatible type. | ||
| * | ||
| * Bad fpcasts are an issue in WebAssembly. WASM's indirect_call has strict | ||
| * function signature checks. Argument count, types, and return type must match. | ||
| * | ||
| * Third party code unintentionally rely on problematic fpcasts. The call | ||
| * trampoline mitigates common occurrences of bad fpcasts on Emscripten. | ||
| */ | ||
|
|
||
| #if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) | ||
|
|
||
| void _Py_EmscriptenTrampoline_Init(_PyRuntimeState *runtime); | ||
|
|
||
| PyObject* | ||
| _PyEM_TrampolineCall_JavaScript(PyCFunctionWithKeywords func, | ||
| PyObject* self, | ||
| PyObject* args, | ||
| PyObject* kw); | ||
|
|
||
| PyObject* | ||
| _PyEM_TrampolineCall_Reflection(PyCFunctionWithKeywords func, | ||
| PyObject* self, | ||
| PyObject* args, | ||
| PyObject* kw); | ||
|
|
||
| #define _PyEM_TrampolineCall(meth, self, args, kw) \ | ||
| ((_PyRuntime.wasm_type_reflection_available) ? \ | ||
| (_PyEM_TrampolineCall_Reflection((PyCFunctionWithKeywords)(meth), (self), (args), (kw))) : \ | ||
| (_PyEM_TrampolineCall_JavaScript((PyCFunctionWithKeywords)(meth), (self), (args), (kw)))) | ||
|
|
||
| #define _PyCFunction_TrampolineCall(meth, self, args) \ | ||
| _PyEM_TrampolineCall( \ | ||
| (*(PyCFunctionWithKeywords)(void(*)(void))(meth)), (self), (args), NULL) | ||
|
|
||
| #define _PyCFunctionWithKeywords_TrampolineCall(meth, self, args, kw) \ | ||
| _PyEM_TrampolineCall((meth), (self), (args), (kw)) | ||
|
|
||
| #define descr_set_trampoline_call(set, obj, value, closure) \ | ||
| ((int)_PyEM_TrampolineCall((PyCFunctionWithKeywords)(set), (obj), (value), (PyObject*)(closure))) | ||
|
|
||
| #define descr_get_trampoline_call(get, obj, closure) \ | ||
| _PyEM_TrampolineCall((PyCFunctionWithKeywords)(get), (obj), (PyObject*)(closure), NULL) | ||
|
|
||
|
|
||
| #else // defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) | ||
|
|
||
| #define _Py_EmscriptenTrampoline_Init(runtime) | ||
|
|
||
| #define _PyCFunction_TrampolineCall(meth, self, args) \ | ||
| (meth)((self), (args)) | ||
|
|
||
| #define _PyCFunctionWithKeywords_TrampolineCall(meth, self, args, kw) \ | ||
| (meth)((self), (args), (kw)) | ||
|
|
||
| #define descr_set_trampoline_call(set, obj, value, closure) \ | ||
| (set)((obj), (value), (closure)) | ||
|
|
||
| #define descr_get_trampoline_call(get, obj, closure) \ | ||
| (get)((obj), (closure)) | ||
|
|
||
| #endif // defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) | ||
|
|
||
| #endif // ndef Py_EMSCRIPTEN_SIGNAL_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Changed the way that Emscripten call trampolines work for compatibility with | ||
| Wasm/JS Promise integration. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| #if defined(PY_CALL_TRAMPOLINE) | ||
|
|
||
| #include <emscripten.h> // EM_JS | ||
| #include <Python.h> | ||
| #include "pycore_runtime.h" // _PyRuntime | ||
|
|
||
|
|
||
| /** | ||
| * This is the GoogleChromeLabs approved way to feature detect type-reflection: | ||
| * https://github.com/GoogleChromeLabs/wasm-feature-detect/blob/main/src/detectors/type-reflection/index.js | ||
| */ | ||
| EM_JS(int, _PyEM_detect_type_reflection, (), { | ||
| return "Function" in WebAssembly; | ||
| }); | ||
|
|
||
| void | ||
| _Py_EmscriptenTrampoline_Init(_PyRuntimeState *runtime) | ||
| { | ||
| runtime->wasm_type_reflection_available = _PyEM_detect_type_reflection(); | ||
| } | ||
|
|
||
| /** | ||
| * Backwards compatible trampoline works with all JS runtimes | ||
| */ | ||
| EM_JS(PyObject*, | ||
| _PyEM_TrampolineCall_JavaScript, (PyCFunctionWithKeywords func, | ||
| PyObject *arg1, | ||
| PyObject *arg2, | ||
| PyObject *arg3), | ||
| { | ||
| return wasmTable.get(func)(arg1, arg2, arg3); | ||
| } | ||
| ); | ||
|
|
||
| /** | ||
| * In runtimes with WebAssembly type reflection, count the number of parameters | ||
| * and cast to the appropriate signature | ||
| */ | ||
| EM_JS(int, _PyEM_CountFuncParams, (PyCFunctionWithKeywords func), | ||
| { | ||
| let n = _PyEM_CountFuncParams.cache.get(func); | ||
|
|
||
| if (n !== undefined) { | ||
| return n; | ||
| } | ||
| n = WebAssembly.Function.type(wasmTable.get(func)).parameters.length; | ||
| _PyEM_CountFuncParams.cache.set(func, n); | ||
| return n; | ||
| } | ||
| _PyEM_CountFuncParams.cache = new Map(); | ||
| ) | ||
|
|
||
|
|
||
| typedef PyObject* (*zero_arg)(void); | ||
| typedef PyObject* (*one_arg)(PyObject*); | ||
| typedef PyObject* (*two_arg)(PyObject*, PyObject*); | ||
| typedef PyObject* (*three_arg)(PyObject*, PyObject*, PyObject*); | ||
|
|
||
|
|
||
| PyObject* | ||
| _PyEM_TrampolineCall_Reflection(PyCFunctionWithKeywords func, | ||
| PyObject* self, | ||
| PyObject* args, | ||
| PyObject* kw) | ||
| { | ||
| switch (_PyEM_CountFuncParams(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 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Back | FazBrowse Home | New Git URL |
Uh oh!
There was an error while loading. Please reload this page.