Skip to content
Open
Show file tree
Hide file tree
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
7 changes: 1 addition & 6 deletions Include/cpython/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,7 @@ typedef struct {
PyObject *_co_freevars;
} _PyCoCached;

typedef struct {
int size;
int capacity;
struct _PyExecutorObject *executors[1];
} _PyExecutorArray;

typedef struct _PyExecutorArray _PyExecutorArray;

#ifdef Py_GIL_DISABLED

Expand Down
2 changes: 2 additions & 0 deletions Include/internal/pycore_interp_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,8 @@ struct _Py_unique_id_pool {

#endif

struct _PyExecutorObject;

typedef _Py_CODEUNIT *(*_PyJitEntryFuncPtr)(struct _PyExecutorObject *exec, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate);

#define _PyInterpreterGuard_GUARDS_NOT_ALLOWED UINTPTR_MAX
Expand Down
46 changes: 42 additions & 4 deletions Include/internal/pycore_optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,16 @@ typedef struct {
PyCodeObject *code; // Weak (NULL if no corresponding ENTER_EXECUTOR).
} _PyVMData;

typedef struct _PyExecutorHandle _PyExecutorHandle;

typedef struct _PyExitData {
uint32_t target;
uint16_t index:12;
uint16_t stack_cache:2;
uint16_t is_dynamic:1;
uint16_t is_control_flow:1;
_Py_BackoffCounter temperature;
struct _PyExecutorObject *executor;
_PyExecutorHandle *executor;
} _PyExitData;

typedef struct _PyExecutorObject {
Expand All @@ -202,12 +204,48 @@ typedef struct _PyExecutorObject {
_PyExitData exits[1];
} _PyExecutorObject;

static inline _PyExecutorObject *
_PyExecutor_FromHandle(_PyExecutorHandle *executor)
{
return (_PyExecutorObject *)executor;
}

static inline _PyExecutorHandle *
_PyExecutor_AsHandle(_PyExecutorObject *executor)
{
return (_PyExecutorHandle *)executor;
}

typedef struct _PyExecutorArrayInternal {
int size;
int capacity;
_PyExecutorObject *executors[1];
} _PyExecutorArrayInternal;

static inline _PyExecutorArrayInternal *
_PyExecutorArray_CAST(_PyExecutorArray *executors)
{
return (_PyExecutorArrayInternal *)executors;
}

static inline int
_PyExecutorArray_SIZE(_PyExecutorArray *executors)
{
return _PyExecutorArray_CAST(executors)->size;
}

static inline _PyExecutorObject **
_PyExecutorArray_EXECUTORS(_PyExecutorArray *executors)
{
return _PyExecutorArray_CAST(executors)->executors;
}

// Export for '_opcode' shared extension (JIT compiler).
PyAPI_FUNC(_PyExecutorObject*) _Py_GetExecutor(PyCodeObject *code, int offset);
PyAPI_FUNC(_PyExecutorHandle*) _Py_GetExecutor(PyCodeObject *code, int offset);

int _Py_ExecutorInit(_PyExecutorObject *, const _PyBloomFilter *);
void _Py_ExecutorDetach(_PyExecutorObject *);
PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj);
PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorHandle *executor, void *obj);

/* We use a bloomfilter with k = 6, m = 256
* The choice of k and the following constants
Expand Down Expand Up @@ -519,7 +557,7 @@ PyAPI_FUNC(int)
_PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame,
_Py_CODEUNIT *curr_instr, _Py_CODEUNIT *start_instr,
_Py_CODEUNIT *close_loop_instr, _PyStackRef *stack_pointer, int chain_depth, _PyExitData *exit,
int oparg, _PyExecutorObject *current_executor);
int oparg, _PyExecutorHandle *current_executor);

PyAPI_FUNC(void) _PyJit_FinalizeTracing(PyThreadState *tstate, int err);
PyAPI_FUNC(bool) _PyJit_EnterExecutorShouldStopTracing(int og_opcode);
Expand Down
3 changes: 2 additions & 1 deletion Modules/_opcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,8 @@ _opcode_get_executor_impl(PyObject *module, PyObject *code, int offset)
return NULL;
}
#ifdef _Py_TIER2
return (PyObject *)_Py_GetExecutor((PyCodeObject *)code, offset);
return (PyObject *)_PyExecutor_FromHandle(
_Py_GetExecutor((PyCodeObject *)code, offset));
#else
PyErr_Format(PyExc_RuntimeError,
"Executors are not available in this build");
Expand Down
4 changes: 2 additions & 2 deletions Modules/_testinternalcapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1788,7 +1788,7 @@ add_executor_dependency(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "OO", &exec, &obj)) {
return NULL;
}
_Py_Executor_DependsOn((_PyExecutorObject *)exec, obj);
_Py_Executor_DependsOn(_PyExecutor_AsHandle((_PyExecutorObject *)exec), obj);
Py_RETURN_NONE;
}

Expand Down Expand Up @@ -1821,7 +1821,7 @@ get_exit_executor(PyObject *self, PyObject *arg)
return NULL;
}
_PyExitData *exit = (_PyExitData *)ptr;
return Py_NewRef(exit->executor);
return Py_NewRef(_PyExecutor_FromHandle(exit->executor));
}

#endif
Expand Down
2 changes: 1 addition & 1 deletion Modules/_testinternalcapi/test_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Objects/codeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -2180,10 +2180,10 @@ static void
clear_executors(PyCodeObject *co)
{
assert(co->co_executors);
for (int i = 0; i < co->co_executors->size; i++) {
if (co->co_executors->executors[i]) {
_Py_ExecutorDetach(co->co_executors->executors[i]);
assert(co->co_executors->executors[i] == NULL);
for (int i = 0; i < _PyExecutorArray_SIZE(co->co_executors); i++) {
if (_PyExecutorArray_EXECUTORS(co->co_executors)[i]) {
_Py_ExecutorDetach(_PyExecutorArray_EXECUTORS(co->co_executors)[i]);
assert(_PyExecutorArray_EXECUTORS(co->co_executors)[i] == NULL);
}
}
PyMem_Free(co->co_executors);
Expand Down
16 changes: 8 additions & 8 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3585,7 +3585,7 @@ dummy_func(
tier1 inst(ENTER_EXECUTOR, (--)) {
#ifdef _Py_TIER2
PyCodeObject *code = _PyFrame_GetCode(frame);
_PyExecutorObject *executor = code->co_executors->executors[oparg & 255];
_PyExecutorObject *executor = ((_PyExecutorArrayInternal *)code->co_executors)->executors[oparg & 255];
if (IS_JIT_TRACING()) {
int og_opcode = executor->vm_data.opcode;
int og_oparg = (oparg & ~255) | executor->vm_data.oparg;
Expand Down Expand Up @@ -6151,7 +6151,7 @@ dummy_func(
}
#endif
tstate->jit_exit = exit;
TIER2_TO_TIER2(exit->executor);
TIER2_TO_TIER2((_PyExecutorObject *)exit->executor);
}

tier2 op(_DYNAMIC_EXIT, (exit_p/4 --)) {
Expand Down Expand Up @@ -6196,10 +6196,10 @@ dummy_func(
#ifndef _Py_JIT
assert(current_executor == (_PyExecutorObject*)executor);
#endif
assert(tstate->jit_exit == NULL || tstate->jit_exit->executor == current_executor);
assert(tstate->jit_exit == NULL || (_PyExecutorObject *)tstate->jit_exit->executor == current_executor);
tstate->current_executor = (PyObject *)current_executor;
if (!current_executor->vm_data.valid) {
assert(tstate->jit_exit->executor == current_executor);
assert((_PyExecutorObject *)tstate->jit_exit->executor == current_executor);
assert(tstate->current_executor == executor);
_PyExecutor_ClearExit(tstate->jit_exit);
DEOPT_IF(true);
Expand Down Expand Up @@ -6261,11 +6261,11 @@ dummy_func(
_PyExecutorObject *executor;
if (target->op.code == ENTER_EXECUTOR) {
PyCodeObject *code = _PyFrame_GetCode(frame);
executor = code->co_executors->executors[target->op.arg];
executor = ((_PyExecutorArrayInternal *)code->co_executors)->executors[target->op.arg];
Py_INCREF(executor);
assert(tstate->jit_exit == exit);
exit->executor = executor;
TIER2_TO_TIER2(exit->executor);
exit->executor = (_PyExecutorHandle *)executor;
TIER2_TO_TIER2((_PyExecutorObject *)exit->executor);
}
else {
SYNC_SP();
Expand All @@ -6281,7 +6281,7 @@ dummy_func(
// Note: it's safe to use target->op.arg here instead of the oparg given by EXTENDED_ARG.
// The invariant in the optimizer is the deopt target always points back to the first EXTENDED_ARG.
// So setting it to anything else is wrong.
int succ = _PyJit_TryInitializeTracing(tstate, frame, target, target, target, stack_pointer, chain_depth, exit, target->op.arg, previous_executor);
int succ = _PyJit_TryInitializeTracing(tstate, frame, target, target, target, stack_pointer, chain_depth, exit, target->op.arg, (_PyExecutorHandle *)previous_executor);
exit->temperature = restart_backoff_counter(exit->temperature);
if (succ) {
GOTO_TIER_ONE_CONTINUE_TRACING(target);
Expand Down
20 changes: 10 additions & 10 deletions Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Python/instrumentation.c
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ _Py_GetBaseCodeUnit(PyCodeObject *code, int i)
return inst;
}
if (opcode == ENTER_EXECUTOR) {
_PyExecutorObject *exec = code->co_executors->executors[inst.op.arg];
_PyExecutorObject *exec = _PyExecutorArray_EXECUTORS(code->co_executors)[inst.op.arg];
opcode = _PyOpcode_Deopt[exec->vm_data.opcode];
inst.op.code = opcode;
inst.op.arg = exec->vm_data.oparg;
Expand Down
Loading
Loading