Skip to content

Commit 552bf46

Browse files
Bad
1 parent e4f1624 commit 552bf46

11 files changed

Lines changed: 532 additions & 1629 deletions

Include/internal/pycore_opcode_metadata.h

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

Python/bytecodes.c

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#define USE_COMPUTED_GOTOS 0
4747
#include "ceval_macros.h"
4848
#include "../Include/internal/pycore_code.h"
49+
#include "../Include/internal/pycore_opcode_metadata.h"
4950
#include "../Include/internal/pycore_stackref.h"
5051

5152
/* Flow control macros */
@@ -1221,7 +1222,7 @@ dummy_func(
12211222
tstate->current_frame = frame->previous;
12221223
assert(!_PyErr_Occurred(tstate));
12231224
PyObject *result = PyStackRef_AsPyObjectSteal(retval);
1224-
#if !_Py_TAIL_CALL_INTERP
1225+
#if !_Py_TAIL_CALL_INTERP && !TRACING_JIT
12251226
assert(frame == &entry.frame);
12261227
#endif
12271228
#ifdef _Py_TIER2
@@ -1233,7 +1234,13 @@ dummy_func(
12331234
}
12341235
#endif
12351236
LLTRACE_RESUME_FRAME();
1237+
#if defined(TRACING_JIT) && !_Py_TAIL_CALL_INTERP
1238+
// We should have exited the trace earlier once we hit
1239+
// the entry frame.
1240+
Py_UNREACHABLE();
1241+
#else
12361242
return result;
1243+
#endif
12371244
}
12381245

12391246
// The stack effect here is a bit misleading.
@@ -1522,7 +1529,7 @@ dummy_func(
15221529

15231530
tier1 inst(CLEANUP_THROW, (sub_iter, last_sent_val, exc_value_st -- none, value)) {
15241531
PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st);
1525-
#if !_Py_TAIL_CALL_INTERP
1532+
#if !_Py_TAIL_CALL_INTERP && !TRACING_JIT
15261533
assert(throwflag);
15271534
#endif
15281535
assert(exc_value && PyExceptionInstance_Check(exc_value));
@@ -2977,6 +2984,7 @@ dummy_func(
29772984
DISPATCH();
29782985
}
29792986
}
2987+
#ifndef TRACING_JIT
29802988
int _is_sys_tracing = (tstate->c_tracefunc != NULL) || (tstate->c_profilefunc != NULL);
29812989
if (!_is_sys_tracing) {
29822990
/* Back up over EXTENDED_ARGs so executor is inserted at the correct place */
@@ -2987,12 +2995,41 @@ dummy_func(
29872995
}
29882996
_PyJit_InitializeTracing(tstate, frame, insert_exec_at, next_instr, STACK_LEVEL(), 0, NULL);
29892997
ENTER_TRACING();
2998+
SAVE_STACK();
2999+
_PyJitTracerReturnValue retval = _PyEval_EvalFrameDefaultTracing(frame, tstate, next_instr, opcode, oparg);
3000+
next_instr = retval.next_instr;
3001+
RELOAD_STACK();
3002+
_PyCeval_LabelIds status = retval.status;
3003+
if (status == CEVAL_LABEL_error) {
3004+
goto error;
3005+
}
3006+
else if (status == CEVAL_LABEL_exception_unwind) {
3007+
goto exception_unwind;
3008+
}
3009+
else if (status == CEVAL_LABEL_exit_unwind) {
3010+
goto exit_unwind;
3011+
}
3012+
else if (status == CEVAL_LABEL_pop_1_error) {
3013+
goto pop_1_error;
3014+
}
3015+
else if (status == CEVAL_LABEL_pop_2_error) {
3016+
goto pop_2_error;
3017+
}
3018+
else if (status == CEVAL_LABEL_start_frame) {
3019+
goto start_frame;
3020+
}
3021+
29903022
}
3023+
#endif
3024+
#if TRACING_JIT
29913025
int _jump_taken = false;
29923026
PyCodeObject *old_code = _PyFrame_GetCode(frame);
29933027
PyFunctionObject *old_func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
29943028
int _old_stack_level = 0;
29953029
TRACING_DISPATCH();
3030+
#else
3031+
DISPATCH();
3032+
#endif
29963033
}
29973034
else {
29983035
ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter);
@@ -3059,9 +3096,10 @@ dummy_func(
30593096
tstate->jit_exit = NULL;
30603097
#if TRACING_JIT
30613098
RECORD_TRACE_NO_DISPATCH();
3062-
#endif
3063-
TIER1_TO_TIER2(executor);
3099+
// We should have cut the executor here and ended the trace.
30643100
#else
3101+
TIER1_TO_TIER2(executor);
3102+
#endif
30653103
Py_FatalError("ENTER_EXECUTOR is not supported in this build");
30663104
#endif /* _Py_TIER2 */
30673105
}
@@ -5622,7 +5660,7 @@ dummy_func(
56225660
goto exit_unwind;
56235661
}
56245662
next_instr = frame->instr_ptr;
5625-
#ifdef Py_DEBUG
5663+
#if defined(Py_DEBUG) && !TRACING_JIT
56265664
int lltrace = maybe_lltrace_resume_frame(frame, GLOBALS());
56275665
if (lltrace < 0) {
56285666
JUMP_TO_LABEL(exit_unwind);

Python/ceval.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,55 @@ typedef struct {
10481048
_PyStackRef stack[1];
10491049
} _PyEntryFrame;
10501050

1051+
1052+
#if defined(_Py_TIER2) && !_Py_TAIL_CALL_INTERP
1053+
1054+
typedef struct {
1055+
_PyCeval_LabelIds status;
1056+
_Py_CODEUNIT *next_instr;
1057+
} _PyJitTracerReturnValue;
1058+
1059+
static _PyJitTracerReturnValue
1060+
record_trace(PyThreadState *tstate, _PyInterpreterFrame *frame, PyCodeObject *old_code, PyFunctionObject *old_func, int _old_stack_level, _Py_CODEUNIT *this_instr, _Py_CODEUNIT *next_instr, int opcode, int oparg, int _jump_taken)
1061+
{
1062+
int full = add_to_code_trace(tstate, frame, old_code, old_func, _old_stack_level, this_instr, next_instr, opcode, oparg, _jump_taken);
1063+
if (full) {
1064+
int err = bail_tracing_and_jit(tstate, frame);
1065+
if (err < 0) {
1066+
return ((_PyJitTracerReturnValue){CEVAL_LABEL_error, next_instr});
1067+
}
1068+
return ((_PyJitTracerReturnValue){CEVAL_LABEL_JIT_DONE_TRACING, next_instr});
1069+
}
1070+
return ((_PyJitTracerReturnValue){CEVAL_LABEL_JIT_CONTINUE_TRACING, NULL});
1071+
}
1072+
1073+
_PyJitTracerReturnValue DONT_SLP_VECTORIZE
1074+
_PyEval_EvalFrameDefaultTracing(_PyInterpreterFrame *frame,
1075+
PyThreadState *tstate, _Py_CODEUNIT *next_instr, int opcode, int oparg)
1076+
{
1077+
#if USE_COMPUTED_GOTOS
1078+
#define USE_JIT_TARGETS
1079+
/* Import the static jump table */
1080+
#include "opcode_targets.h"
1081+
#undef USE_JIT_TARGETS
1082+
void **opcode_targets = opcode_tracing_targets_table;
1083+
#endif
1084+
_Py_CODEUNIT *this_instr = frame->instr_ptr;
1085+
int _jump_taken = false;
1086+
PyCodeObject *old_code = _PyFrame_GetCode(frame);
1087+
PyFunctionObject *old_func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
1088+
int _old_stack_level = 0;
1089+
int is_tracing_flag = true;
1090+
_PyStackRef *stack_pointer = frame->stackpointer;
1091+
TRACING_DISPATCH();
1092+
{
1093+
#include "generated_tracer_cases.c.h"
1094+
error:
1095+
return ((_PyJitTracerReturnValue){CEVAL_LABEL_error, next_instr});
1096+
}
1097+
1098+
#endif
1099+
10511100
PyObject* _Py_HOT_FUNCTION DONT_SLP_VECTORIZE
10521101
_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag)
10531102
{
@@ -1068,6 +1117,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
10681117
uint8_t opcode; /* Current opcode */
10691118
int oparg; /* Current opcode argument, if any */
10701119
assert(tstate->current_frame == NULL || tstate->current_frame->stackpointer != NULL);
1120+
const bool is_tracing_flag = false;
10711121
#endif
10721122
_PyEntryFrame entry;
10731123

@@ -1154,7 +1204,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
11541204
#else
11551205
goto start_frame;
11561206
# include "generated_cases.c.h"
1157-
#include "generated_tracer_cases.c.h"
11581207
#endif
11591208

11601209

Python/ceval_macros.h

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,6 @@
8484
# define Py_PRESERVE_NONE_CC __attribute__((preserve_none))
8585
Py_PRESERVE_NONE_CC typedef PyObject* (*py_tail_call_funcptr)(TAIL_CALL_PARAMS);
8686

87-
# define DISPATCH_TABLE_VAR instruction_funcptr_table
88-
# define DISPATCH_TABLE instruction_funcptr_handler_table
89-
# define TRACING_DISPATCH_TABLE instruction_funcptr_tracing_table
90-
# define TARGET(op) Py_PRESERVE_NONE_CC PyObject *_TAIL_CALL_##op(TAIL_CALL_PARAMS)
91-
# define TRACING_TARGET(op) Py_PRESERVE_NONE_CC PyObject *_TAIL_CALL_TRACING_##op(TAIL_CALL_PARAMS)
92-
9387
# define DISPATCH_GOTO() \
9488
do { \
9589
Py_MUSTTAIL return (((py_tail_call_funcptr *)instruction_funcptr_table)[opcode])(TAIL_CALL_ARGS); \
@@ -111,8 +105,6 @@
111105
# endif
112106
# define LABEL(name) TARGET(name)
113107
#elif USE_COMPUTED_GOTOS
114-
# define DISPATCH_TABLE_VAR opcode_targets
115-
# define DISPATCH_TABLE opcode_targets_table
116108
# define TRACING_DISPATCH_TABLE opcode_tracing_targets_table
117109
# define TARGET(op) TARGET_##op:
118110
# define TRACING_TARGET(op) TARGET_TRACING_##op:
@@ -129,21 +121,21 @@
129121
# define LABEL(name) name:
130122
#endif
131123

132-
#define TRACING_JUMP_TO_LABEL(label) \
133-
RECORD_DYNAMIC_JUMP_TAKEN() \
134-
RECORD_TRACE_NO_DISPATCH() \
135-
assert(!IS_JIT_TRACING()); \
136-
JUMP_TO_LABEL(label);
137124

138-
#if _Py_TAIL_CALL_INTERP || USE_COMPUTED_GOTOS
125+
#if _Py_TIER2
126+
#if _Py_TAIL_CALL_INTERP
127+
# define DISPATCH_TABLE_VAR instruction_funcptr_table
128+
# define DISPATCH_TABLE instruction_funcptr_handler_table
129+
# define TRACING_DISPATCH_TABLE instruction_funcptr_tracing_table
130+
# define ENTER_TRACING() DISPATCH_TABLE_VAR = TRACING_DISPATCH_TABLE
131+
# define TARGET(op) Py_PRESERVE_NONE_CC PyObject *_TAIL_CALL_##op(TAIL_CALL_PARAMS)
132+
# define TRACING_TARGET(op) Py_PRESERVE_NONE_CC PyObject *_TAIL_CALL_TRACING_##op(TAIL_CALL_PARAMS)
133+
139134
# define IS_JIT_TRACING() (DISPATCH_TABLE_VAR == TRACING_DISPATCH_TABLE)
140135
// tstate->interp->jit_state.last_specialized_instr != this_instr is required to not get stuck in infinite
141136
// specialization loops due to specialization failure.
142137
# define IS_JIT_TRACING_MAKING_PROGRESS() (IS_JIT_TRACING() && tstate->interp->jit_state.last_specialized_instr != this_instr)
143-
# define ENTER_TRACING() \
144-
DISPATCH_TABLE_VAR = TRACING_DISPATCH_TABLE;
145-
# define LEAVE_TRACING() \
146-
DISPATCH_TABLE_VAR = DISPATCH_TABLE;
138+
# define LEAVE_TRACING() DISPATCH_TABLE_VAR = DISPATCH_TABLE;
147139
# define RECORD_TRACE_NO_DISPATCH() do { \
148140
int err = 0; \
149141
_PyFrame_SetStackPointer(frame, stack_pointer); \
@@ -158,8 +150,33 @@
158150
stack_pointer = _PyFrame_GetStackPointer(frame); \
159151
if (err < 0) { JUMP_TO_LABEL(error); } \
160152
} while (0);
161-
#endif
153+
#define TRACING_JUMP_TO_LABEL(label) \
154+
RECORD_DYNAMIC_JUMP_TAKEN() \
155+
RECORD_TRACE_NO_DISPATCH() \
156+
assert(!IS_JIT_TRACING()); \
157+
JUMP_TO_LABEL(label);
162158

159+
#else
160+
// Note: computed gotos interpreter slows down a lot with tracing.
161+
// So we can't use the same dispatch table technique the tail calling
162+
// interpreter uses.
163+
# define ENTER_TRACING()
164+
# define IS_JIT_TRACING() (is_tracing_flag)
165+
# define IS_JIT_TRACING_MAKING_PROGRESS() (IS_JIT_TRACING() && tstate->interp->jit_state.last_specialized_instr != this_instr)
166+
# define RECORD_TRACE_NO_ERR_CHECK() \
167+
_PyFrame_SetStackPointer(frame, stack_pointer); \
168+
_PyJitTracerReturnValue jit_status = record_trace(tstate, frame, old_code, old_func, _old_stack_level, this_instr, next_instr, opcode, oparg, _jump_taken); \
169+
stack_pointer = _PyFrame_GetStackPointer(frame);
170+
# define RECORD_TRACE_NO_DISPATCH() \
171+
RECORD_TRACE_NO_ERR_CHECK(); \
172+
if (jit_status.status != CEVAL_LABEL_JIT_CONTINUE_TRACING) { return jit_status; }
173+
#define TRACING_JUMP_TO_LABEL(label) \
174+
RECORD_DYNAMIC_JUMP_TAKEN(); \
175+
RECORD_TRACE_NO_ERR_CHECK(); \
176+
(void)(jit_status); \
177+
return ((_PyJitTracerReturnValue){CEVAL_LABEL_##label, next_instr});
178+
#endif
179+
#endif
163180

164181
/* PRE_DISPATCH_GOTO() does lltrace if enabled. Normally a no-op */
165182
#ifdef Py_DEBUG
@@ -204,14 +221,6 @@ do { \
204221
DISPATCH_GOTO(); \
205222
}
206223

207-
#define TRACING_SPECIALIZE_DISPATCH_SAME_OPARG() \
208-
{ \
209-
tstate->interp->jit_state.last_specialized_instr = this_instr; \
210-
opcode = next_instr->op.code; \
211-
PRE_DISPATCH_GOTO(); \
212-
DISPATCH_GOTO(); \
213-
}
214-
215224
#define DISPATCH_INLINED(NEW_FRAME) \
216225
do { \
217226
assert(tstate->interp->eval_frame == NULL); \
@@ -222,6 +231,14 @@ do { \
222231
JUMP_TO_LABEL(start_frame); \
223232
} while (0)
224233

234+
#define TRACING_SPECIALIZE_DISPATCH_SAME_OPARG() \
235+
{ \
236+
tstate->interp->jit_state.last_specialized_instr = this_instr; \
237+
opcode = next_instr->op.code; \
238+
PRE_DISPATCH_GOTO(); \
239+
DISPATCH_GOTO(); \
240+
}
241+
225242
#define TRACING_DISPATCH_INLINED(NEW_FRAME) \
226243
tstate->interp->jit_state.last_specialized_instr = this_instr; \
227244
RECORD_TRACE_NO_DISPATCH(); \

0 commit comments

Comments
 (0)