Skip to content

Commit 0a2c8f4

Browse files
clementperonclaude
andcommitted
gh-156780: Emscripten: drop the trampoline's dependence on exports
The trampoline exports _PyRuntime's address itself and reuses a placeholder's table slot, so libpython no longer needs -sEXPORTED_FUNCTIONS=__PyRuntime or a growable function table. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent 9bd670c commit 0a2c8f4

3 files changed

Lines changed: 20 additions & 5 deletions

File tree

Python/emscripten_trampoline.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,19 @@ typedef PyObject* (*TrampolineFunc)(int* success,
4747
PyObject* args,
4848
PyObject* kw);
4949

50+
// Lets JS reach _PyRuntime without it being in -sEXPORTED_FUNCTIONS.
51+
EMSCRIPTEN_KEEPALIVE _PyRuntimeState *const _PyEM_runtime = &_PyRuntime;
52+
53+
// Its table slot is taken over by the wasm-gc trampoline, so the table
54+
// never grows.
55+
static PyObject*
56+
trampoline_placeholder(int* success, PyCFunctionWithKeywords func,
57+
PyObject* self, PyObject* args, PyObject* kw)
58+
{
59+
Py_FatalError("Emscripten trampoline slot was not set up");
60+
}
61+
EMSCRIPTEN_KEEPALIVE const TrampolineFunc _PyEM_trampoline_slot = trampoline_placeholder;
62+
5063
/**
5164
* Backwards compatible trampoline works with all JS runtimes
5265
*/
@@ -79,7 +92,9 @@ function getPyEMTrampolinePtr() {
7992
const trampolineInstance = new WebAssembly.Instance(trampolineModule, {
8093
env: { __indirect_function_table: wasmTable, memory: wasmMemory },
8194
});
82-
return addFunction(trampolineInstance.exports.trampoline_call);
95+
const slot = HEAPU32[__PyEM_trampoline_slot / 4];
96+
wasmTable.set(slot, trampolineInstance.exports.trampoline_call);
97+
return slot;
8398
}
8499
// We have to be careful to work correctly with memory snapshots -- the value of
85100
// _PyRuntimeState.emscripten_trampoline needs to reflect whether wasm-gc is
@@ -90,12 +105,12 @@ function getPyEMTrampolinePtr() {
90105
addOnPreRun(function setEmscriptenTrampoline() {
91106
const ptr = getPyEMTrampolinePtr();
92107
const offset = HEAP32[__PyEM_EMSCRIPTEN_TRAMPOLINE_OFFSET / 4];
93-
HEAP32[(__PyRuntime + offset) / 4] = ptr;
108+
HEAP32[(HEAPU32[__PyEM_runtime / 4] + offset) / 4] = ptr;
94109
});
95110
);
96111

97112
EM_JS_DEPS(_PyEM_TrampolineCall,
98-
"$wasmTable,$wasmMemory,$addFunction,$addOnPreRun");
113+
"$wasmTable,$wasmMemory,$addOnPreRun");
99114

100115
PyObject*
101116
_PyEM_TrampolineCall(PyCFunctionWithKeywords func,

configure

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2440,7 +2440,7 @@ AS_CASE([$ac_sys_system],
24402440
dnl Include file system support
24412441
AS_VAR_APPEND([LINKFORSHARED], [" -sFORCE_FILESYSTEM -lidbfs.js -lnodefs.js -lproxyfs.js -lworkerfs.js"])
24422442
AS_VAR_APPEND([LINKFORSHARED], [" -sEXPORTED_RUNTIME_METHODS=FS,callMain,ENV,HEAPU32,TTY,ERRNO_CODES"])
2443-
AS_VAR_APPEND([LINKFORSHARED], [" -sEXPORTED_FUNCTIONS=_main,_Py_Version,__PyRuntime,_PyGILState_GetThisThreadState,__PyEM_EMSCRIPTEN_TRAMPOLINE_OFFSET"])
2443+
AS_VAR_APPEND([LINKFORSHARED], [" -sEXPORTED_FUNCTIONS=_main,_Py_Version,_PyGILState_GetThisThreadState,__PyEM_EMSCRIPTEN_TRAMPOLINE_OFFSET"])
24442444
AS_VAR_APPEND([LINKFORSHARED], [" -sSTACK_SIZE=5MB"])
24452445
dnl Avoid bugs in JS fallback string decoding path
24462446
AS_VAR_APPEND([LINKFORSHARED], [" -sTEXTDECODER=2"])

0 commit comments

Comments
 (0)