FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
cpython/Python/emscripten_trampoline.c at 3.14 · python/cpython · GitHub
Uh oh!
There was an error while loading.
Please reload this page
.
python
/
cpython
Public
Uh oh!
There was an error while loading.
Please reload this page
.
Notifications
You must be signed in to change notification settings
Fork
35.3k
Star
74.9k
Code
Issues
5k+
Pull requests
2.5k
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
cpython
/
Python
/
emscripten_trampoline.c
Copy path
More file actions
More file actions
Latest commit
History
History
History
118 lines (111 loc) · 5.05 KB
Breadcrumbs
cpython
/
Python
/
emscripten_trampoline.c
Copy path
File metadata and controls
118 lines (111 loc) · 5.05 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#if
defined(
PY_CALL_TRAMPOLINE
)
#include
<emscripten.h>
// EM_JS, EM_JS_DEPS
#include
<Python.h>
#include
"pycore_runtime.h"
// _PyRuntime
// We use the _PyRuntime.emscripten_trampoline field to store a function pointer
// for a wasm-gc based trampoline if it works. Otherwise fall back to JS
// trampoline. The JS trampoline breaks stack switching but every runtime that
// supports stack switching also supports wasm-gc.
//
// We'd like to make the trampoline call into a direct call but currently we
// need to import the wasmTable to compile trampolineModule. emcc >= 4.0.19
// defines the table in WebAssembly and exports it so we won't have access to it
// until after the main module is compiled.
//
// To fix this, one natural solution would be to pass a funcref to the
// trampoline instead of a table index. Several PRs would be needed to fix
// things in llvm and emscripten in order to make this possible.
//
// The performance costs of an extra call_indirect aren't that large anyways.
// The JIT should notice that the target is always the same and turn into a
// check
//
// if (call_target != expected) deoptimize;
// direct_call(call_target, args);
// Offset of emscripten_trampoline in _PyRuntimeState. There's a couple of
// alternatives:
//
// 1. Just make emscripten_trampoline a real C global variable instead of a
// field of _PyRuntimeState. This would violate our rule against mutable
// globals.
//
// 2. #define a preprocessor constant equal to a hard coded number and make a
// _Static_assert(offsetof(_PyRuntimeState, emscripten_trampoline) == OURCONSTANT)
// This has the disadvantage that we have to update the hard coded constant
// when _PyRuntimeState changes
//
// So putting the mutable constant in _PyRuntime and using a immutable global to
// record the offset so we can access it from JS is probably the best way.
EMSCRIPTEN_KEEPALIVE
const
int
_PyEM_EMSCRIPTEN_TRAMPOLINE_OFFSET
=
offsetof(
_PyRuntimeState
,
emscripten_trampoline
);
typedef
PyObject
*
(
*
TrampolineFunc
)(
int
*
success
,
PyCFunctionWithKeywords
func
,
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kw
);
/**
* 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
);
}
// Try to compile wasm-gc trampoline if possible.
function
getPyEMTrampolinePtr
() {
// Starting with iOS 18.3.1, WebKit on iOS has an issue with the garbage
// collector that breaks the call trampoline. See #130418 and
// https://bugs.webkit.org/show_bug.cgi?id=293113 for details.
let
isIOS
=
globalThis
.
navigator
&&
(
/
iPad
|
iPhone
|
iPod
/.
test
(
navigator
.
userAgent
)
||
// Starting with iPadOS 13, iPads might send a platform string that looks like a desktop Mac.
// To differentiate, we check if the platform is 'MacIntel' (common for Macs and newer iPads)
// AND if the device has multi-touch capabilities (navigator.maxTouchPoints > 1)
(
navigator
.
platform
==
=
'MacIntel'
&&
typeof
navigator
.
maxTouchPoints
!=
=
'undefined'
&&
navigator
.
maxTouchPoints
>
1
)
);
if
(
isIOS
) {
return
0
;
}
let
trampolineModule
;
try
{
trampolineModule
=
getWasmTrampolineModule
();
}
catch
(
e
) {
// Compilation error due to missing wasm-gc support, fall back to JS
// trampoline
return
0
;
}
const
trampolineInstance
=
new
WebAssembly
.
Instance
(
trampolineModule
, {
env
: {
__indirect_function_table
:
wasmTable
,
memory
:
wasmMemory
},
});
return
addFunction
(
trampolineInstance
.
exports
.
trampoline_call
);
}
// We have to be careful to work correctly with memory snapshots -- the value of
// _PyRuntimeState.emscripten_trampoline needs to reflect whether wasm-gc is
// available in the current runtime, not in the runtime the snapshot was taken
// in. This writes the appropriate value to
// _PyRuntimeState.emscripten_trampoline from JS startup code that runs every
// time, whether we are restoring a snapshot or not.
addOnPreRun
(
function
setEmscriptenTrampoline
() {
const
ptr
=
getPyEMTrampolinePtr
();
const
offset
=
HEAP32
[
__PyEM_EMSCRIPTEN_TRAMPOLINE_OFFSET
/
4
];
HEAP32
[(
__PyRuntime
+
offset
) /
4
]
=
ptr
;
});
);
PyObject
*
_PyEM_TrampolineCall
(
PyCFunctionWithKeywords
func
,
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kw
)
{
TrampolineFunc
trampoline
=
_PyRuntime
.
emscripten_trampoline
;
if
(
trampoline
==
0
) {
return
_PyEM_TrampolineCall_JS
(
func
,
self
,
args
,
kw
);
}
int
success
=
1
;
PyObject
*
result
=
trampoline
(
&
success
,
func
,
self
,
args
,
kw
);
if
(!
success
) {
PyErr_SetString
(
PyExc_SystemError
,
"Handler takes too many arguments"
);
}
return
result
;
}
#else
// This is exported so we need to define it even when it isn't used
__attribute__((
used
))
const
int
_PyEM_EMSCRIPTEN_TRAMPOLINE_OFFSET
=
0
;
#endif
Back
|
FazBrowse Home
|
New Git URL