Skip to content

Commit 43322c1

Browse files
add workaround
1 parent a30fcb8 commit 43322c1

File tree

9 files changed

+74
-86
lines changed

9 files changed

+74
-86
lines changed

Include/internal/pycore_ceval.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,13 @@ _Py_BuiltinCallFastWithKeywords_StackRefSteal(
444444
_PyStackRef *arguments,
445445
int total_args);
446446

447+
PyAPI_FUNC(PyObject *)
448+
_PyCallMethodDescriptorO_StackRef(
449+
_PyStackRef callable,
450+
PyCFunction cfunc,
451+
_PyStackRef self_stackref,
452+
_PyStackRef arg_stackref);
453+
447454
PyAPI_FUNC(PyObject *)
448455
_PyCallMethodDescriptorFast_StackRefSteal(
449456
_PyStackRef callable,

Modules/_testinternalcapi/test_cases.c.h

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/bytecodes.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4756,14 +4756,14 @@ dummy_func(
47564756
}
47574757
// CPython promises to check all non-vectorcall function calls.
47584758
EXIT_IF(_Py_ReachedRecursionLimit(tstate));
4759-
_PyStackRef arg_stackref = arguments[1];
4760-
_PyStackRef self_stackref = arguments[0];
47614759
STAT_INC(CALL, hit);
47624760
PyCFunction cfunc = method->d_method->ml_meth;
4763-
PyObject *res_o = _PyCFunction_TrampolineCall(cfunc,
4764-
PyStackRef_AsPyObjectBorrow(self_stackref),
4765-
PyStackRef_AsPyObjectBorrow(arg_stackref));
4766-
_Py_LeaveRecursiveCallTstate(tstate);
4761+
PyObject *res_o = _PyCallMethodDescriptorO_StackRef(
4762+
callable,
4763+
cfunc,
4764+
arguments[0],
4765+
arguments[1]
4766+
);
47674767
assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
47684768
if (res_o == NULL) {
47694769
ERROR_NO_POP();
@@ -4779,11 +4779,12 @@ dummy_func(
47794779
assert(oparg == 2);
47804780
EXIT_IF(_Py_ReachedRecursionLimit(tstate));
47814781
STAT_INC(CALL, hit);
4782-
PyObject *res_o = _PyCFunction_TrampolineCall(
4783-
(PyCFunction)cfunc,
4784-
PyStackRef_AsPyObjectBorrow(args[0]),
4785-
PyStackRef_AsPyObjectBorrow(args[1]));
4786-
_Py_LeaveRecursiveCallTstate(tstate);
4782+
PyObject *res_o = _PyCallMethodDescriptorO_StackRef(
4783+
callable,
4784+
(PyCFunction)cfunc,
4785+
args[0],
4786+
args[1]
4787+
);
47874788
assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
47884789
if (res_o == NULL) {
47894790
ERROR_NO_POP();

Python/ceval.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,22 @@ _Py_BuiltinCallFastWithKeywords_StackRefSteal(
871871
return res;
872872
}
873873

874+
PyObject *
875+
_PyCallMethodDescriptorO_StackRef(
876+
_PyStackRef callable,
877+
PyCFunction cfunc,
878+
_PyStackRef self_stackref,
879+
_PyStackRef arg_stackref)
880+
{
881+
PyObject *self = PyStackRef_AsPyObjectBorrow(self_stackref);
882+
PyObject *arg = PyStackRef_AsPyObjectBorrow(arg_stackref);
883+
884+
PyObject *res = _PyCFunction_TrampolineCall(cfunc, self, arg);
885+
_Py_LeaveRecursiveCallTstate(_PyThreadState_GET());
886+
assert((res != NULL) ^ (PyErr_Occurred() != NULL));
887+
return res;
888+
}
889+
874890
PyObject *
875891
_PyCallMethodDescriptorFast_StackRefSteal(
876892
_PyStackRef callable,

Python/executor_cases.c.h

Lines changed: 11 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/jit.c

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -554,9 +554,7 @@ patch_x86_64_32rx(unsigned char *location, uint64_t value)
554554

555555
void patch_got_symbol(jit_state *state, int ordinal);
556556
void patch_aarch64_trampoline(unsigned char *location, int ordinal, jit_state *state);
557-
void patch_aarch64_trampoline_addr(unsigned char *location, int ordinal, uint64_t value, jit_state *state);
558557
void patch_x86_64_trampoline(unsigned char *location, int ordinal, jit_state *state);
559-
void patch_x86_64_trampoline_addr(unsigned char *location, int ordinal, uint64_t value, jit_state *state);
560558

561559
#include "jit_stencils.h"
562560

@@ -587,27 +585,28 @@ patch_got_symbol(jit_state *state, int ordinal)
587585
void
588586
patch_aarch64_trampoline(unsigned char *location, int ordinal, jit_state *state)
589587
{
590-
uint64_t value = (uintptr_t)symbols_map[ordinal];
591-
patch_aarch64_trampoline_addr(location, ordinal, value, state);
592-
}
593588

594-
// Generate and patch AArch64 trampolines for dynamic addresses (e.g. operands).
595-
// Unlike patch_aarch64_trampoline, the target address is passed directly rather
596-
// than looked up from symbols_map. The ordinal is used to allocate a trampoline slot.
597-
void
598-
patch_aarch64_trampoline_addr(unsigned char *location, int ordinal, uint64_t value, jit_state *state)
599-
{
600-
int64_t range = (int64_t)value - (int64_t)(uintptr_t)location;
589+
uint64_t value = (uintptr_t)symbols_map[ordinal];
590+
int64_t range = value - (uintptr_t)location;
601591

592+
// If we are in range of 28 signed bits, we patch the instruction with
593+
// the address of the symbol.
602594
if (range >= -(1 << 27) && range < (1 << 27)) {
603-
patch_aarch64_26r(location, value);
595+
patch_aarch64_26r(location, (uintptr_t)value);
604596
return;
605597
}
606598

599+
// Out of range - need a trampoline
607600
uint32_t *p = (uint32_t *)get_symbol_slot(ordinal, &state->trampolines, TRAMPOLINE_SIZE);
608601

609-
p[0] = 0x58000048; // ldr x8, 8
610-
p[1] = 0xD61F0100; // br x8
602+
/* Generate the trampoline
603+
0: 58000048 ldr x8, 8
604+
4: d61f0100 br x8
605+
8: 00000000 // The next two words contain the 64-bit address to jump to.
606+
c: 00000000
607+
*/
608+
p[0] = 0x58000048;
609+
p[1] = 0xD61F0100;
611610
p[2] = value & 0xffffffff;
612611
p[3] = value >> 32;
613612

@@ -619,13 +618,7 @@ void
619618
patch_x86_64_trampoline(unsigned char *location, int ordinal, jit_state *state)
620619
{
621620
uint64_t value = (uintptr_t)symbols_map[ordinal];
622-
patch_x86_64_trampoline_addr(location, ordinal, value, state);
623-
}
624-
625-
void
626-
patch_x86_64_trampoline_addr(unsigned char *location, int ordinal, uint64_t value, jit_state *state)
627-
{
628-
int64_t range = (int64_t)value - 4 - (int64_t)(uintptr_t)location;
621+
int64_t range = (int64_t)value - 4 - (int64_t)location;
629622

630623
// If we are in range of 32 signed bits, we can patch directly
631624
if (range >= -(1LL << 31) && range < (1LL << 31)) {

Tools/jit/_stencils.py

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -296,33 +296,6 @@ def process_relocations(self, known_symbols: dict[str, int]) -> None:
296296
self._trampolines.add(ordinal)
297297
hole.addend = ordinal
298298
hole.symbol = None
299-
# aarch64 trampolines for operand-based call targets (e.g. inlined cfunc)
300-
elif hole.kind in {
301-
"R_AARCH64_CALL26",
302-
"R_AARCH64_JUMP26",
303-
"ARM64_RELOC_BRANCH26",
304-
} and hole.value in {HoleValue.OPERAND0, HoleValue.OPERAND1}:
305-
value_expr = _HOLE_EXPRS[hole.value]
306-
ordinal = len(known_symbols)
307-
synth_name = f"_JIT_TRAMPOLINE_{hole.value.name}_{ordinal}"
308-
known_symbols[synth_name] = ordinal
309-
self._trampolines.add(ordinal)
310-
hole.func = "patch_aarch64_trampoline_addr"
311-
hole.need_state = True
312-
hole.custom_value = f"{ordinal}, {value_expr}"
313-
# x86_64 trampolines for operand-based call targets (e.g. inlined cfunc)
314-
elif (
315-
hole.kind in {"R_X86_64_PLT32", "X86_64_RELOC_BRANCH"}
316-
and hole.value in {HoleValue.OPERAND0, HoleValue.OPERAND1}
317-
):
318-
value_expr = _HOLE_EXPRS[hole.value]
319-
ordinal = len(known_symbols)
320-
synth_name = f"_JIT_TRAMPOLINE_{hole.value.name}_{ordinal}"
321-
known_symbols[synth_name] = ordinal
322-
self._trampolines.add(ordinal)
323-
hole.func = "patch_x86_64_trampoline_addr"
324-
hole.need_state = True
325-
hole.custom_value = f"{ordinal}, {value_expr}"
326299
# x86_64 Darwin trampolines for external symbols
327300
elif (
328301
hole.kind == "X86_64_RELOC_BRANCH"

Tools/jit/_writer.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,7 @@ def _dump_footer(
3535
yield f"static const void * const symbols_map[{max(len(symbols), 1)}] = {{"
3636
if symbols:
3737
for symbol, ordinal in symbols.items():
38-
if symbol.startswith("_JIT_TRAMPOLINE_"):
39-
yield f" [{ordinal}] = 0,"
40-
else:
41-
yield f" [{ordinal}] = &{symbol},"
38+
yield f" [{ordinal}] = &{symbol},"
4239
else:
4340
yield " 0"
4441
yield "};"

0 commit comments

Comments
 (0)