Skip to content

Commit db04fc8

Browse files
committed
Fixes
1 parent 39a9041 commit db04fc8

16 files changed

Lines changed: 142 additions & 56 deletions

Include/internal/pycore_interp_structs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,7 @@ struct _Py_unique_id_pool {
782782

783783
#endif
784784

785-
typedef _Py_CODEUNIT *(*_PyJitEntryFuncPtr)(struct _PyExecutorObject *exec, _PyInterpreterFrameCore *frame, _PyStackRef *stack_pointer, PyThreadState *tstate);
785+
typedef _Py_CODEUNIT *(*_PyJitEntryFuncPtr)(struct _PyExecutorObject *exec, _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate);
786786

787787
/* PyInterpreterState holds the global state for one of the runtime's
788788
interpreters. Typically the initial (main) interpreter is the only one.

Include/internal/pycore_interpframe.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *
214214

215215
#ifdef Py_GIL_DISABLED
216216
static inline void
217-
_PyFrame_InitializeTLBC(PyThreadState *tstate, _PyInterpreterFrameCore *frame,
217+
_PyFrame_InitializeTLBC(PyThreadState *tstate, _PyInterpreterFrame *frame,
218218
PyCodeObject *code)
219219
{
220220
_Py_CODEUNIT *tlbc = _PyCode_GetTLBCFast(tstate, code);

Include/internal/pycore_optimizer.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ typedef struct _PyJitTracerPreviousState {
8888
int instr_stacklevel;
8989
_Py_CODEUNIT *instr;
9090
PyCodeObject *instr_code; // Strong
91-
struct _PyInterpreterFrameCore *instr_frame;
91+
struct _PyInterpreterFrame *instr_frame;
9292
_PyBloomFilter dependencies;
9393
} _PyJitTracerPreviousState;
9494

@@ -311,7 +311,7 @@ extern int _Py_uop_frame_pop(JitOptContext *ctx, PyCodeObject *co, int curr_stac
311311

312312
PyAPI_FUNC(PyObject *) _Py_uop_symbols_test(PyObject *self, PyObject *ignored);
313313

314-
PyAPI_FUNC(int) _PyOptimizer_Optimize(_PyInterpreterFrameCore *frame, PyThreadState *tstate);
314+
PyAPI_FUNC(int) _PyOptimizer_Optimize(_PyInterpreterFrame *frame, PyThreadState *tstate);
315315

316316
static inline _PyExecutorObject *_PyExecutor_FromExit(_PyExitData *exit)
317317
{
@@ -331,10 +331,10 @@ PyAPI_FUNC(int) _PyDumpExecutors(FILE *out);
331331
PyAPI_FUNC(void) _Py_ClearExecutorDeletionList(PyInterpreterState *interp);
332332
#endif
333333

334-
PyAPI_FUNC(int) _PyJit_translate_single_bytecode_to_trace(PyThreadState *tstate, _PyInterpreterFrameCore *frame, _Py_CODEUNIT *next_instr, int stop_tracing_opcode);
334+
PyAPI_FUNC(int) _PyJit_translate_single_bytecode_to_trace(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *next_instr, int stop_tracing_opcode);
335335

336336
PyAPI_FUNC(int)
337-
_PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrameCore *frame,
337+
_PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame,
338338
_Py_CODEUNIT *curr_instr, _Py_CODEUNIT *start_instr,
339339
_Py_CODEUNIT *close_loop_instr, int curr_stackdepth, int chain_depth, _PyExitData *exit,
340340
int oparg, _PyExecutorObject *current_executor);

Lib/test/test_capi/test_misc.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,6 +2858,85 @@ def func():
28582858
names = ["func", "outer", "outer", "inner", "inner", "outer", "inner"]
28592859
self.do_test(func, names)
28602860

2861+
def test_jit_frame(self):
2862+
def fakefunc():
2863+
pass
2864+
2865+
def f():
2866+
return sys._getframe(1)
2867+
2868+
res = _testinternalcapi.call_with_jit_frame(fakefunc, f, ())
2869+
2870+
def test_jit_frame_globals(self):
2871+
"""jit executable can fill in globals when accessed"""
2872+
def fakefunc():
2873+
pass
2874+
2875+
fake_globals = {"abc":42}
2876+
def callback():
2877+
return {"globals": fake_globals}
2878+
2879+
res = _testinternalcapi.call_with_jit_frame(fakefunc, globals, (), callback)
2880+
self.assertEqual(res, fake_globals)
2881+
2882+
def test_jit_frame_builtins(self):
2883+
"""jit executable can fill in builtins when accessed"""
2884+
def fakefunc():
2885+
pass
2886+
2887+
fake_builtins = {"abc":42}
2888+
def callback():
2889+
return {"builtins": fake_builtins}
2890+
2891+
res = _testinternalcapi.call_with_jit_frame(fakefunc, _testlimitedcapi.eval_getbuiltins, (), callback)
2892+
self.assertEqual(res, fake_builtins)
2893+
2894+
def test_jit_frame_instr_ptr(self):
2895+
"""jit executable can fill in the instr ptr each time the frame is queried"""
2896+
def fakefunc():
2897+
pass
2898+
pass
2899+
pass
2900+
pass
2901+
2902+
offset = 0
2903+
linenos = []
2904+
def test():
2905+
for op in dis.get_instructions(fakefunc):
2906+
if op.opname in ("RESUME", "NOP", "RETURN_VALUE"):
2907+
nonlocal offset
2908+
offset = op.offset//2
2909+
linenos.append(sys._getframe(1).f_lineno)
2910+
2911+
def callback():
2912+
return {"instr_ptr": offset}
2913+
2914+
_testinternalcapi.call_with_jit_frame(fakefunc, test, (), callback)
2915+
base = fakefunc.__code__.co_firstlineno
2916+
self.assertEqual(linenos, [base, base + 1, base + 2, base + 3, base + 4])
2917+
2918+
def test_jit_frame_code(self):
2919+
"""internal C api checks the for a code executor"""
2920+
def fakefunc():
2921+
pass
2922+
2923+
def callback():
2924+
return _testinternalcapi.iframe_getcode(sys._getframe(1))
2925+
2926+
res = _testinternalcapi.call_with_jit_frame(fakefunc, callback, ())
2927+
self.assertEqual(res, fakefunc.__code__)
2928+
2929+
def test_jit_frame_line(self):
2930+
"""internal C api checks the for a code executor"""
2931+
def fakefunc():
2932+
pass
2933+
2934+
def callback():
2935+
return _testinternalcapi.iframe_getline(sys._getframe(1))
2936+
2937+
res = _testinternalcapi.call_with_jit_frame(fakefunc, callback, ())
2938+
self.assertEqual(res, fakefunc.__code__.co_firstlineno)
2939+
28612940

28622941
@unittest.skipUnless(support.Py_GIL_DISABLED, 'need Py_GIL_DISABLED')
28632942
class TestPyThreadId(unittest.TestCase):

Lib/test/test_sys.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1674,7 +1674,7 @@ def func():
16741674
return sys._getframe()
16751675
x = func()
16761676
if support.Py_GIL_DISABLED:
1677-
INTERPRETER_FRAME = '2Pc9PihP'
1677+
INTERPRETER_FRAME = '2Pc7PihP'
16781678
else:
16791679
INTERPRETER_FRAME = '2Pc7PhP'
16801680
check(x, size('3PiccPPP' + INTERPRETER_FRAME + 'P'))

Modules/_testinternalcapi/interpreter.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,11 @@ Test_EvalFrame(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
100100
/* Load thread-local bytecode */
101101
if (frame->tlbc_index != ((_PyThreadStateImpl *)tstate)->tlbc_index) {
102102
_Py_CODEUNIT *bytecode =
103-
_PyEval_GetExecutableCode(tstate, _PyFrame_GetCode(frame));
103+
_PyEval_GetExecutableCode(tstate, _PyFrame_GetCode(_PyFrame_Core(frame)));
104104
if (bytecode == NULL) {
105105
goto early_exit;
106106
}
107-
ptrdiff_t off = frame->instr_ptr - _PyFrame_GetBytecode(frame);
107+
ptrdiff_t off = frame->instr_ptr - _PyFrame_GetBytecode(_PyFrame_Core(frame));
108108
frame->tlbc_index = ((_PyThreadStateImpl *)tstate)->tlbc_index;
109109
frame->instr_ptr = bytecode + off;
110110
}

Modules/_testinternalcapi/test_cases.c.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11893,15 +11893,15 @@
1189311893
_PyJitTracerState *tracer = _tstate->jit_tracer_state;
1189411894
assert(tracer != NULL);
1189511895
tracer->prev_state.instr = next_instr;
11896-
PyObject *prev_code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
11896+
PyObject *prev_code = PyStackRef_AsPyObjectBorrow(FRAME_CORE->f_executable);
1189711897
if (tracer->prev_state.instr_code != (PyCodeObject *)prev_code) {
1189811898
_PyFrame_SetStackPointer(frame, stack_pointer);
1189911899
Py_SETREF(tracer->prev_state.instr_code, (PyCodeObject*)Py_NewRef((prev_code)));
1190011900
stack_pointer = _PyFrame_GetStackPointer(frame);
1190111901
}
1190211902
tracer->prev_state.instr_frame = frame;
1190311903
tracer->prev_state.instr_oparg = oparg;
11904-
tracer->prev_state.instr_stacklevel = PyStackRef_IsNone(frame->f_executable) ? 2 : STACK_LEVEL();
11904+
tracer->prev_state.instr_stacklevel = PyStackRef_IsNone(FRAME_CORE->f_executable) ? 2 : STACK_LEVEL();
1190511905
if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) {
1190611906
(&next_instr[1])->counter = trigger_backoff_counter();
1190711907
}

Python/bytecodes.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5337,7 +5337,7 @@ dummy_func(
53375337
tier2 op(_EXIT_TRACE, (exit_p/4 --)) {
53385338
_PyExitData *exit = (_PyExitData *)exit_p;
53395339
#if defined(Py_DEBUG) && !defined(_Py_JIT)
5340-
const _Py_CODEUNIT *target = ((frame->owner == FRAME_OWNED_BY_INTERPRETER)
5340+
const _Py_CODEUNIT *target = ((FRAME_CORE->owner == FRAME_OWNED_BY_INTERPRETER)
53415341
? _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR : _PyFrame_GetBytecode(FRAME_CORE))
53425342
+ exit->target;
53435343
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
@@ -5509,7 +5509,7 @@ dummy_func(
55095509

55105510
tier2 op(_DEOPT, (--)) {
55115511
SYNC_SP();
5512-
GOTO_TIER_ONE((frame->owner == FRAME_OWNED_BY_INTERPRETER)
5512+
GOTO_TIER_ONE((FRAME_CORE->owner == FRAME_OWNED_BY_INTERPRETER)
55135513
? _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR : _PyFrame_GetBytecode(FRAME_CORE) + CURRENT_TARGET());
55145514
Py_UNREACHABLE();
55155515
}
@@ -5547,7 +5547,7 @@ dummy_func(
55475547
tier2 op(_COLD_EXIT, ( -- )) {
55485548
_PyExitData *exit = tstate->jit_exit;
55495549
assert(exit != NULL);
5550-
assert(frame->owner < FRAME_OWNED_BY_INTERPRETER);
5550+
assert(FRAME_CORE->owner < FRAME_OWNED_BY_INTERPRETER);
55515551
_Py_CODEUNIT *target = _PyFrame_GetBytecode(FRAME_CORE) + exit->target;
55525552
_Py_BackoffCounter temperature = exit->temperature;
55535553
_PyExecutorObject *executor;
@@ -5802,14 +5802,14 @@ dummy_func(
58025802
_PyJitTracerState *tracer = _tstate->jit_tracer_state;
58035803
assert(tracer != NULL);
58045804
tracer->prev_state.instr = next_instr;
5805-
PyObject *prev_code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
5805+
PyObject *prev_code = PyStackRef_AsPyObjectBorrow(FRAME_CORE->f_executable);
58065806
if (tracer->prev_state.instr_code != (PyCodeObject *)prev_code) {
58075807
Py_SETREF(tracer->prev_state.instr_code, (PyCodeObject*)Py_NewRef((prev_code)));
58085808
}
58095809

58105810
tracer->prev_state.instr_frame = frame;
58115811
tracer->prev_state.instr_oparg = oparg;
5812-
tracer->prev_state.instr_stacklevel = PyStackRef_IsNone(frame->f_executable) ? 2 : STACK_LEVEL();
5812+
tracer->prev_state.instr_stacklevel = PyStackRef_IsNone(FRAME_CORE->f_executable) ? 2 : STACK_LEVEL();
58135813
if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) {
58145814
(&next_instr[1])->counter = trigger_backoff_counter();
58155815
}

Python/ceval.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,11 +1225,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
12251225
/* Load thread-local bytecode */
12261226
if (frame->tlbc_index != ((_PyThreadStateImpl *)tstate)->tlbc_index) {
12271227
_Py_CODEUNIT *bytecode =
1228-
_PyEval_GetExecutableCode(tstate, _PyFrame_GetCode(frame));
1228+
_PyEval_GetExecutableCode(tstate, _PyFrame_GetCode(_PyFrame_Core(frame)));
12291229
if (bytecode == NULL) {
12301230
goto early_exit;
12311231
}
1232-
ptrdiff_t off = frame->instr_ptr - _PyFrame_GetBytecode(frame);
1232+
ptrdiff_t off = frame->instr_ptr - _PyFrame_GetBytecode(_PyFrame_Core(frame));
12331233
frame->tlbc_index = ((_PyThreadStateImpl *)tstate)->tlbc_index;
12341234
frame->instr_ptr = bytecode + off;
12351235
}

Python/ceval_macros.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ GETITEM(PyObject *v, Py_ssize_t i) {
277277
#if defined(Py_DEBUG) && !defined(_Py_JIT)
278278
// This allows temporary stack "overflows", provided it's all in the cache at any point of time.
279279
#define WITHIN_STACK_BOUNDS_IGNORING_CACHE() \
280-
(frame->owner == FRAME_OWNED_BY_INTERPRETER || (STACK_LEVEL() >= 0 && (STACK_LEVEL()) <= STACK_SIZE()))
280+
(_PyFrame_Core(frame)->owner == FRAME_OWNED_BY_INTERPRETER || (STACK_LEVEL() >= 0 && (STACK_LEVEL()) <= STACK_SIZE()))
281281
#else
282282
#define WITHIN_STACK_BOUNDS_IGNORING_CACHE WITHIN_STACK_BOUNDS
283283
#endif
@@ -425,7 +425,7 @@ _PyFrame_SetStackPointer(frame, stack_pointer)
425425
do { \
426426
OPT_STAT_INC(traces_executed); \
427427
next_instr = _Py_jit_entry((EXECUTOR), frame, stack_pointer, tstate); \
428-
frame = tstate->current_frame; \
428+
frame = _PyFrame_Full(tstate->current_frame); \
429429
stack_pointer = _PyFrame_GetStackPointer(frame); \
430430
int keep_tracing_bit = (uintptr_t)next_instr & 1; \
431431
next_instr = (_Py_CODEUNIT *)(((uintptr_t)next_instr) & (~1)); \

0 commit comments

Comments
 (0)