-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
gh-106213: Make Emscripten trampolines work with JSPI #106219
New issue
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
Merged
Merged
Changes from 8 commits
Commits
Show all changes
42 commits
Select commit
Hold shift + click to select a range
8e2ad18
Make Emscripten trampolines work with JSPI
hoodmane 6903fd5
Add blurb
hoodmane af6850c
Add more comments
hoodmane ffb24ff
Fix typo
hoodmane 85d88ec
Cleanup
hoodmane 9d8f23e
Use EM_JS instead of EM_ASM
hoodmane 2dc1399
Fix typo
hoodmane 418efb4
Merge branch 'main' into jspi-trampoline
hoodmane d900dfd
Move type reflection flag into _PyRuntime
hoodmane 62a2f7f
Merge branch 'main' into jspi-trampoline
hoodmane cd3f8bf
Update pycore_emscripten_trampoline.h declarations
hoodmane 2c45f1b
Merge branch 'main' into jspi-trampoline
hoodmane 3951848
Include pycore_runtime.h
hoodmane dfd43d7
Fix typo
hoodmane b0b50f4
Use wasmTable.get instead of getWasmTableEntry
hoodmane 1c1b9ed
Replace another instance of getWasmTableEntry with wasmTable.get
hoodmane 44f0371
Use branch in macro to choose trampoline
hoodmane bd609e5
Fix non emscripten platforms
hoodmane a00d94f
Fix compile warnings on non-emscripten platforms
hoodmane 68f4dba
Fix spelling
hoodmane 1d49e79
Fix formatting
hoodmane afb9ad5
Revert whitespace changes
hoodmane aa213e0
Call _Py_EmscriptenTrampoline_Init before setting _initialized to 1
hoodmane 00afb90
Sort include list
hoodmane 20ad6ab
Follow pep 7
hoodmane ae7584c
Merge branch 'main' into jspi-trampoline
hoodmane 1b6b6af
Move wasm_type_reflection_available to end of struct
hoodmane 381bb12
Address review comments
hoodmane 58c7613
Update Include/internal/pycore_runtime.h
hoodmane eccf06d
Merge branch 'main' into jspi-trampoline
brettcannon 5fff95d
Merge branch 'main' into jspi-trampoline
hoodmane f08a02b
Merge branch 'jspi-trampoline' of github.com:hoodmane/cpython into js…
hoodmane 6b27584
Merge branch 'main' into jspi-trampoline
brettcannon 22a8c75
Fix merge
hoodmane b40bb7b
Merge branch 'jspi-trampoline' of github.com:hoodmane/cpython into js…
hoodmane 28b33b3
Merge branch 'main' into jspi-trampoline
brettcannon 9ecc480
Merge branch 'main' into jspi-trampoline
brettcannon 4aa1487
Test setting ac_cv_libatomic_needed=no
hoodmane a57dfdc
Set libatomic_needed=no if cross compiling
hoodmane 6358371
Merge branch 'main' into jspi-trampoline
hoodmane 6781a48
Merge branch 'main' into jspi-trampoline
brettcannon fd59df4
Merge branch 'main' into jspi-trampoline
brettcannon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
#ifndef Py_EMSCRIPTEN_TRAMPOLINE_H | ||
#define Py_EMSCRIPTEN_TRAMPOLINE_H | ||
|
||
|
||
/** | ||
* 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(void); | ||
|
||
PyObject* | ||
_PyEM_TrampolineCall(PyCFunctionWithKeywords func, | ||
PyObject* self, | ||
PyObject* args, | ||
PyObject* 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)) | ||
|
||
#else // defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) | ||
|
||
#define _Py_EmscriptenTrampoline_Init() | ||
|
||
#define _PyCFunction_TrampolineCall(meth, self, args) \ | ||
(meth)((self), (args)) | ||
#define _PyCFunctionWithKeywords_TrampolineCall(meth, self, args, kw) \ | ||
(meth)((self), (args), (kw)) | ||
|
||
#endif // defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE) | ||
#endif // ndef Py_EMSCRIPTEN_SIGNAL_H |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
Misc/NEWS.d/next/Core and Builtins/2023-06-29-09-42-56.gh-issue-106213.TCUgzM.rst
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#if defined(PY_CALL_TRAMPOLINE) | ||
|
||
#include <emscripten.h> | ||
#include <Python.h> | ||
|
||
static int type_reflection_available; | ||
erlend-aasland marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** | ||
* 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(){ | ||
type_reflection_available = _PyEM_detect_type_reflection(); | ||
} | ||
|
||
/** | ||
* Backwards compatible trampoline works with all JS runtimes | ||
*/ | ||
EM_JS_DEPS(_PyEMJS_TrampolineCall, "$getWasmTableEntry") | ||
EM_JS(PyObject*, _PyEMJS_TrampolineCall, (PyCFunctionWithKeywords func, PyObject *arg1, PyObject *arg2, PyObject *arg3), { | ||
return getWasmTableEntry(func)(arg1, arg2, arg3); | ||
} | ||
); | ||
erlend-aasland marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** | ||
* 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(getWasmTableEntry(func)).parameters.length; | ||
erlend-aasland marked this conversation as resolved.
Show resolved
Hide resolved
|
||
_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(PyCFunctionWithKeywords func, | ||
PyObject* self, | ||
PyObject* args, | ||
PyObject* kw) | ||
{ | ||
if (!type_reflection_available) { | ||
return _PyEMJS_TrampolineCall(func, self, args, kw); | ||
} else { | ||
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.