Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Tools/jit/trampoline.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ _Py_CODEUNIT *
_JIT_ENTRY(
_PyExecutorObject *exec, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate
) {
typedef DECLARE_TARGET((*jit_func));
typedef _Py_CODEUNIT *__attribute__((preserve_none)) (*jit_func)(_PyInterpreterFrame *, _PyStackRef *, PyThreadState *);
jit_func jitted = (jit_func)exec->jit_code;
Comment on lines +13 to 14
Copy link
Member

@chris-eibl chris-eibl Oct 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
typedef _Py_CODEUNIT *__attribute__((preserve_none)) (*jit_func)(_PyInterpreterFrame *, _PyStackRef *, PyThreadState *);
jit_func jitted = (jit_func)exec->jit_code;
jit_func_preserve_none jitted = (jit_func_preserve_none)exec->jit_code;

I suggest to use

// To use preserve_none in JIT builds, we need to declare a separate function
// pointer with __attribute__((preserve_none)), since this attribute may not be
// supported by the compiler used to build the rest of the interpreter.
typedef jit_func __attribute__((preserve_none)) jit_func_preserve_none;

which builds on top of
typedef _Py_CODEUNIT *(*jit_func)(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate);

and IMHO is better than duplicating?

Copy link
Member

@chris-eibl chris-eibl Oct 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the other usage of jit_func_preserve_none in

#define TIER2_TO_TIER2(EXECUTOR) \
do { \
OPT_STAT_INC(traces_executed); \
_PyExecutorObject *_executor = (EXECUTOR); \
jit_func_preserve_none jitted = _executor->jit_code; \
__attribute__((musttail)) return jitted(frame, stack_pointer, tstate); \
} while (0)

suggests that it is even possible to omit the cast in

jit_func_preserve_none jitted = (jit_func_preserve_none)exec->jit_code;

and indeed the same code is generated for emit_trampoline in the stencils header 1.

Footnotes

  1. Tested only for x86_64-pc-windows-msvc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the back and forth, but having a closer look and playing on Godbolt suggests that the cast is better in case of -Wpedantic, since strictly speaking void *jit_code

typedef struct _PyExecutorObject {
PyObject_VAR_HEAD
const _PyUOpInstruction *trace;
_PyVMData vm_data; /* Used by the VM, but opaque to the optimizer */
uint32_t exit_count;
uint32_t code_size;
size_t jit_size;
void *jit_code;
_PyExitData exits[1];
} _PyExecutorObject;

is a data pointer. So maybe change to a cast in TIER2_TO_TIER2, too?

return jitted(frame, stack_pointer, tstate);
}
Loading