-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
gh-111520: Integrate the Tier 2 interpreter in the Tier 1 interpreter #111428
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
97984d3
157a450
d1b9c1b
d805312
e0e60ce
a720f1a
b808f6d
a0aed59
75605c7
5e84476
917b7a2
9067eb0
6a4e495
81f1883
ee27e73
7ebc228
a1d0108
a96ac7f
e02409d
fdf1a2f
2a6450c
4783de3
b9516a1
33c3fae
998e054
19d9d40
03de1bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -201,15 +201,15 @@ maybe_lltrace_resume_frame(_PyInterpreterFrame *frame, _PyInterpreterFrame *skip | |||||||||||||||
if (r < 0) { | ||||||||||||||||
return -1; | ||||||||||||||||
} | ||||||||||||||||
int lltrace = r; | ||||||||||||||||
int lltrace = r * 5; // Levels 1-4 only trace uops | ||||||||||||||||
if (!lltrace) { | ||||||||||||||||
// When tracing executed uops, also trace bytecode | ||||||||||||||||
char *uop_debug = Py_GETENV("PYTHONUOPSDEBUG"); | ||||||||||||||||
if (uop_debug != NULL && *uop_debug >= '0') { | ||||||||||||||||
lltrace = (*uop_debug - '0') >= 5; // TODO: Parse an int and all that | ||||||||||||||||
// Can also be controlled by environment variable | ||||||||||||||||
char *python_lltrace = Py_GETENV("PYTHON_LLTRACE"); | ||||||||||||||||
if (python_lltrace != NULL && *python_lltrace >= '0') { | ||||||||||||||||
lltrace = *python_lltrace - '0'; // TODO: Parse an int and all that | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
if (lltrace) { | ||||||||||||||||
if (lltrace >= 5) { | ||||||||||||||||
lltrace_resume_frame(frame); | ||||||||||||||||
} | ||||||||||||||||
return lltrace; | ||||||||||||||||
|
@@ -679,9 +679,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int | |||||||||||||||
#ifdef Py_STATS | ||||||||||||||||
int lastopcode = 0; | ||||||||||||||||
#endif | ||||||||||||||||
// opcode is an 8-bit value to improve the code generated by MSVC | ||||||||||||||||
// for the big switch below (in combination with the EXTRA_CASES macro). | ||||||||||||||||
uint8_t opcode; /* Current opcode */ | ||||||||||||||||
int opcode; /* Current opcode */ | ||||||||||||||||
int oparg; /* Current opcode argument, if any */ | ||||||||||||||||
#ifdef LLTRACE | ||||||||||||||||
int lltrace = 0; | ||||||||||||||||
|
@@ -729,6 +727,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int | |||||||||||||||
goto resume_with_error; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
/* State shared between Tier 1 and Tier 2 interpreter */ | ||||||||||||||||
_PyUOpExecutorObject *self = NULL; | ||||||||||||||||
|
||||||||||||||||
/* Local "register" variables. | ||||||||||||||||
* These are cached values from the frame and code object. */ | ||||||||||||||||
|
||||||||||||||||
|
@@ -765,7 +766,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int | |||||||||||||||
/* Start instructions */ | ||||||||||||||||
#if !USE_COMPUTED_GOTOS | ||||||||||||||||
dispatch_opcode: | ||||||||||||||||
switch (opcode) | ||||||||||||||||
// Cast to an 8-bit value to improve the code generated by MSVC | ||||||||||||||||
// (in combination with the EXTRA_CASES macro). | ||||||||||||||||
switch ((uint8_t)opcode) | ||||||||||||||||
#endif | ||||||||||||||||
{ | ||||||||||||||||
|
||||||||||||||||
|
@@ -913,7 +916,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int | |||||||||||||||
} | ||||||||||||||||
/* Resume normal execution */ | ||||||||||||||||
#ifdef LLTRACE | ||||||||||||||||
if (lltrace) { | ||||||||||||||||
if (lltrace >= 5) { | ||||||||||||||||
lltrace_resume_frame(frame); | ||||||||||||||||
} | ||||||||||||||||
#endif | ||||||||||||||||
|
@@ -942,6 +945,123 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int | |||||||||||||||
stack_pointer = _PyFrame_GetStackPointer(frame); | ||||||||||||||||
goto error; | ||||||||||||||||
|
||||||||||||||||
|
||||||||||||||||
|
||||||||||||||||
// The Tier 2 interpreter is also here! | ||||||||||||||||
enter_tier_two: | ||||||||||||||||
|
||||||||||||||||
#undef LOAD_IP | ||||||||||||||||
#define LOAD_IP(UNUSED) \ | ||||||||||||||||
do { ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive; } while (0) | ||||||||||||||||
|
||||||||||||||||
#undef GOTO_ERROR | ||||||||||||||||
#define GOTO_ERROR(LABEL) goto LABEL ## _tier_two | ||||||||||||||||
|
||||||||||||||||
#undef DEOPT_IF | ||||||||||||||||
#define DEOPT_IF(COND, INSTNAME) \ | ||||||||||||||||
if ((COND)) { \ | ||||||||||||||||
goto deoptimize_tier_two;\ | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
#ifdef Py_STATS | ||||||||||||||||
// Disable these macros that apply to Tier 1 stats when we are in Tier 2 | ||||||||||||||||
#undef STAT_INC | ||||||||||||||||
#define STAT_INC(opname, name) ((void)0) | ||||||||||||||||
#undef STAT_DEC | ||||||||||||||||
#define STAT_DEC(opname, name) ((void)0) | ||||||||||||||||
#undef CALL_STAT_INC | ||||||||||||||||
#define CALL_STAT_INC(name) ((void)0) | ||||||||||||||||
#endif | ||||||||||||||||
|
||||||||||||||||
#undef ENABLE_SPECIALIZATION | ||||||||||||||||
#define ENABLE_SPECIALIZATION 0 | ||||||||||||||||
|
||||||||||||||||
#ifdef Py_DEBUG | ||||||||||||||||
#define DPRINTF(level, ...) \ | ||||||||||||||||
if (lltrace >= (level)) { printf(__VA_ARGS__); } | ||||||||||||||||
#else | ||||||||||||||||
#define DPRINTF(level, ...) | ||||||||||||||||
#endif | ||||||||||||||||
|
||||||||||||||||
CHECK_EVAL_BREAKER(); | ||||||||||||||||
|
||||||||||||||||
OPT_STAT_INC(traces_executed); | ||||||||||||||||
_Py_CODEUNIT *ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive; | ||||||||||||||||
gvanrossum marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
_PyUOpInstruction *next_uop = self->trace; | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should have been set by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes and no. It would mean that |
||||||||||||||||
uint64_t operand; | ||||||||||||||||
#ifdef Py_STATS | ||||||||||||||||
uint64_t trace_uop_execution_counter = 0; | ||||||||||||||||
#endif | ||||||||||||||||
|
||||||||||||||||
for (;;) { | ||||||||||||||||
opcode = next_uop->opcode; | ||||||||||||||||
oparg = next_uop->oparg; | ||||||||||||||||
operand = next_uop->operand; | ||||||||||||||||
DPRINTF(3, | ||||||||||||||||
"%4d: uop %s, oparg %d, operand %" PRIu64 ", stack_level %d\n", | ||||||||||||||||
(int)(next_uop - self->trace), | ||||||||||||||||
opcode < 256 ? _PyOpcode_OpName[opcode] : _PyOpcode_uop_name[opcode], | ||||||||||||||||
oparg, | ||||||||||||||||
operand, | ||||||||||||||||
(int)(stack_pointer - _PyFrame_Stackbase(frame))); | ||||||||||||||||
next_uop++; | ||||||||||||||||
OPT_STAT_INC(uops_executed); | ||||||||||||||||
UOP_EXE_INC(opcode); | ||||||||||||||||
#ifdef Py_STATS | ||||||||||||||||
trace_uop_execution_counter++; | ||||||||||||||||
#endif | ||||||||||||||||
|
||||||||||||||||
switch (opcode) { | ||||||||||||||||
|
||||||||||||||||
#undef TIER_ONE | ||||||||||||||||
#define TIER_TWO 2 | ||||||||||||||||
#include "executor_cases.c.h" | ||||||||||||||||
|
||||||||||||||||
default: | ||||||||||||||||
gvanrossum marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||
{ | ||||||||||||||||
fprintf(stderr, "Unknown uop %d, oparg %d, operand %" PRIu64 "\n", | ||||||||||||||||
opcode, oparg, operand); | ||||||||||||||||
Py_FatalError("Unknown uop"); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
unbound_local_error_tier_two: | ||||||||||||||||
_PyEval_FormatExcCheckArg(tstate, PyExc_UnboundLocalError, | ||||||||||||||||
UNBOUNDLOCAL_ERROR_MSG, | ||||||||||||||||
PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg) | ||||||||||||||||
); | ||||||||||||||||
goto error_tier_two; | ||||||||||||||||
|
||||||||||||||||
pop_4_error_tier_two: | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't this be shared with tier 1? Unwinding should work the same. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alas, not quite. The debug output is different, the stats collection is different, but most importantly, we need to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also we need to set |
||||||||||||||||
STACK_SHRINK(1); | ||||||||||||||||
pop_3_error_tier_two: | ||||||||||||||||
STACK_SHRINK(1); | ||||||||||||||||
pop_2_error_tier_two: | ||||||||||||||||
STACK_SHRINK(1); | ||||||||||||||||
pop_1_error_tier_two: | ||||||||||||||||
STACK_SHRINK(1); | ||||||||||||||||
error_tier_two: | ||||||||||||||||
DPRINTF(2, "Error: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand); | ||||||||||||||||
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); | ||||||||||||||||
frame->return_offset = 0; // Don't leave this random | ||||||||||||||||
_PyFrame_SetStackPointer(frame, stack_pointer); | ||||||||||||||||
Py_DECREF(self); | ||||||||||||||||
goto resume_with_error; | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We may not need to reset
Suggested change
|
||||||||||||||||
|
||||||||||||||||
deoptimize_tier_two: | ||||||||||||||||
// On DEOPT_IF we just repeat the last instruction. | ||||||||||||||||
// This presumes nothing was popped from the stack (nor pushed). | ||||||||||||||||
DPRINTF(2, "DEOPT: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand); | ||||||||||||||||
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); | ||||||||||||||||
frame->return_offset = 0; // Dispatch to frame->instr_ptr | ||||||||||||||||
_PyFrame_SetStackPointer(frame, stack_pointer); | ||||||||||||||||
Py_DECREF(self); | ||||||||||||||||
enter_tier_one: | ||||||||||||||||
next_instr = frame->instr_ptr; | ||||||||||||||||
goto resume_frame; | ||||||||||||||||
|
||||||||||||||||
} | ||||||||||||||||
#if defined(__GNUC__) | ||||||||||||||||
# pragma GCC diagnostic pop | ||||||||||||||||
|
Uh oh!
There was an error while loading. Please reload this page.