Repository navigation
gh-139109: A new tracing JIT compiler frontend for CPython #140310
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 1 commit
795ef49
40bf6c1
13188a9
e63de39
fba9d2d
7192671
07542dd
021fc44
f886c43
3066963
20b283b
36554a5
92bba64
2e3ddc1
aada168
7b5c655
3e9f782
9a66605
108ab7f
fac8c74
fd3bb48
96b7bb2
396818b
57f417e
2c603cc
02f1fb4
dc414a3
0ffc2dd
2032b9c
299a068
8e0fb21
95eee89
6936a38
a274451
f55129e
71bd27b
e834c88
cae8f10
39bc819
ff92937
2589eb0
a2e92a6
cbb3ad2
9910b65
5102ab6
c0c14b4
7d4f866
1981f50
b879dab
093578c
d114944
e50ff65
54f6cd6
e3f18e6
608772f
1872715
460fb39
8d6f1db
a8762c2
72c2242
d76dc85
87c0b72
24cd7f9
8ae2e4c
f38ef69
960d647
1798ab1
681485f
9bb03a8
4b26cde
d820e22
00c81fa
ba64a5b
b00252e
754b3b7
6045a67
ec2971f
d49e367
55892a4
dd0e16f
d18c1a1
7d17741
8ebb6cb
c23e591
a62fe40
e4f1624
a7fcf24
eb73378
2b5fe3a
3385420
cedd7af
676faf8
cdcce30
1a3f129
e8fff00
7b2a8ca
abb1757
0fee4e9
ccc7893
eb970e0
abecfd6
8aeabd5
6bd1541
a53ca1d
ce66f3b
5733455
4aab2df
ab7527c
7e7b240
4a4a31f
72e1738
5e17707
1e132f0
bf17539
7ab76a8
86ab7f1
5f39672
440ad03
9cc7999
4b4e857
a5d918e
d601256
425fd51
1f8c3df
bdd2123
5f4f310
b5a9b07
8adaf4d
e918cb2
e9e2bb9
01c2d73
1d3aed1
7bfac26
ac0711d
da66058
692a992
84ee07b
72368ed
8e62fd1
92cc140
af9ea57
3ed1402
0a1bad2
0498568
d44ca1e
2dbc291
82ec8f1
f526688
c78a4e6
aa92d84
253f230
ffa2b72
897edf5
1ef4a37
0e92118
c75d91c
bf1ddab
a64215d
da5e7b7
83c85c3
6c77ee3
3fd3ab5
6429b2f
5cfc7a9
c5de275
b7b3c23
cda3dce
3f212a4
4f29dd3
5af4b0a
46c079a
4aeb4ab
fe3a6a1
10fa14a
0f978c4
3c80446
aaf6873
547f587
a55d766
278bbe6
f547880
7e2bc1d
fa3e285
251e19e
08ec600
f7c26d4
ae1d6fe
0658f1b
f8a764a
b72ab8b
8993e6c
fa45ae8
308ccc0
33cf287
3163d9b
658fd98
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,7 @@ | |
|
|
||
| #define USE_COMPUTED_GOTOS 0 | ||
| #include "ceval_macros.h" | ||
| #include "../Include/internal/pycore_stackref.h" | ||
|
|
||
| /* Flow control macros */ | ||
|
|
||
|
|
@@ -170,7 +171,6 @@ dummy_func( | |
|
|
||
| op(_QUICKEN_RESUME, (--)) { | ||
| #if ENABLE_SPECIALIZATION_FT | ||
| PyCodeObject *code = _PyFrame_GetCode(frame); | ||
| if (tstate->tracing == 0 && this_instr->op.code == RESUME) { | ||
| FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, RESUME_CHECK); | ||
| } | ||
|
|
@@ -5266,7 +5266,9 @@ dummy_func( | |
| tier2 op(_EXIT_TRACE, (exit_p/4 --)) { | ||
| _PyExitData *exit = (_PyExitData *)exit_p; | ||
| #if defined(Py_DEBUG) && !defined(_Py_JIT) | ||
| _Py_CODEUNIT *target = _PyFrame_GetBytecode(frame) + exit->target; | ||
| const _Py_CODEUNIT *target = ((frame->owner >= FRAME_OWNED_BY_INTERPRETER) | ||
| ? _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR : _PyFrame_GetBytecode(frame)) | ||
| + exit->target; | ||
| OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); | ||
| if (frame->lltrace >= 2) { | ||
| printf("SIDE EXIT: [UOp "); | ||
|
|
@@ -5420,7 +5422,8 @@ dummy_func( | |
| tier2 op(_COLD_EXIT, ( -- )) { | ||
|
Member
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. Could we keep this unchanged, and do any tweaks for better tracing in another PR?
Member
Author
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. The old code no longer makes sense/is really cumbersome with the new tracing style (deopt to tier 1 then begin tracing). So sadly I'd rather not :(. |
||
| _PyExitData *exit = tstate->jit_exit; | ||
| assert(exit != NULL); | ||
| _Py_CODEUNIT *target = _PyFrame_GetBytecode(frame) + exit->target; | ||
| _Py_CODEUNIT *target = ((frame->owner >= FRAME_OWNED_BY_INTERPRETER) | ||
|
Fidget-Spinner marked this conversation as resolved.
Outdated
|
||
| ? (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR : _PyFrame_GetBytecode(frame)) + exit->target; | ||
| _Py_BackoffCounter temperature = exit->temperature; | ||
| _PyExecutorObject *executor; | ||
| if (target->op.code == ENTER_EXECUTOR) { | ||
|
|
@@ -5429,6 +5432,9 @@ dummy_func( | |
| Py_INCREF(executor); | ||
| } | ||
| else { | ||
| if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) { | ||
|
Fidget-Spinner marked this conversation as resolved.
Outdated
|
||
| GOTO_TIER_ONE(target); | ||
| } | ||
| if (!backoff_counter_triggers(temperature)) { | ||
|
markshannon marked this conversation as resolved.
|
||
| exit->temperature = advance_backoff_counter(temperature); | ||
| GOTO_TIER_ONE(target); | ||
|
|
@@ -5664,14 +5670,14 @@ dummy_func( | |
| tstate->interp->jit_state.prev_instr = next_instr; | ||
| } | ||
| tstate->interp->jit_state.specialize_counter = 0; | ||
| PyCodeObject *prev_code = (PyCodeObject *)Py_NewRef(_PyFrame_GetCode(frame)); | ||
| PyCodeObject *prev_code = (PyCodeObject *)Py_NewRef(PyStackRef_AsPyObjectBorrow(frame->f_executable)); | ||
| if (tstate->interp->jit_state.prev_instr_code != prev_code) { | ||
| Py_SETREF(tstate->interp->jit_state.prev_instr_code, prev_code); | ||
| } | ||
|
|
||
| tstate->interp->jit_state.prev_instr_frame = frame; | ||
| tstate->interp->jit_state.prev_instr_oparg = oparg; | ||
| tstate->interp->jit_state.prev_instr_stacklevel = STACK_LEVEL(); | ||
| tstate->interp->jit_state.prev_instr_stacklevel = PyStackRef_IsNone(frame->f_executable) ? 2 : STACK_LEVEL(); | ||
| DISPATCH_GOTO_NON_TRACING(); | ||
| #else | ||
| Py_FatalError("JIT label executed in non-jit build."); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -931,44 +931,17 @@ int _Py_CheckRecursiveCallPy( | |
| return 0; | ||
| } | ||
|
|
||
| static const PyBytesObject no_location = { | ||
| PyVarObject_HEAD_INIT(&PyBytes_Type, 1) | ||
| .ob_sval = { NO_LOC_4 } | ||
| static const _Py_CODEUNIT _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS[] = { | ||
| /* Put a NOP at the start, so that the IP points into | ||
| * the code, rather than before it */ | ||
| { .op.code = NOP, .op.arg = 0 }, | ||
| { .op.code = INTERPRETER_EXIT, .op.arg = 0 }, /* reached on return */ | ||
| { .op.code = NOP, .op.arg = 0 }, | ||
| { .op.code = INTERPRETER_EXIT, .op.arg = 0 }, /* reached on yield */ | ||
| { .op.code = RESUME, .op.arg = RESUME_OPARG_DEPTH1_MASK | RESUME_AT_FUNC_START } | ||
| }; | ||
|
|
||
| #ifdef Py_GIL_DISABLED | ||
| static _PyCodeArray emtry_cleanup_tlbc = { | ||
| .size = 1, | ||
| .entries = {(char*) &_PyEntryFrameCode.co_code_adaptive}, | ||
| }; | ||
| #endif | ||
|
|
||
| const struct _PyCode12 _PyEntryFrameCode = { | ||
| _PyVarObject_HEAD_INIT(&PyCode_Type, 5), | ||
| .co_consts = (PyObject *)&_Py_SINGLETON(tuple_empty), | ||
| .co_names = (PyObject *)&_Py_SINGLETON(tuple_empty), | ||
| .co_exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty), | ||
| .co_flags = CO_OPTIMIZED | CO_NO_MONITORING_EVENTS, | ||
| .co_localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty), | ||
| .co_localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty), | ||
| .co_filename = &_Py_ID(_PyEval_EvalFrameDefault), | ||
| .co_name = &_Py_ID(_PyEval_EvalFrameDefault), | ||
| .co_qualname = &_Py_ID(_PyEval_EvalFrameDefault), | ||
| .co_linetable = (PyObject *)&no_location, | ||
| ._co_firsttraceable = 4, | ||
| .co_stacksize = 2, | ||
| .co_framesize = 2 + FRAME_SPECIALS_SIZE, | ||
| #ifdef Py_GIL_DISABLED | ||
| .co_tlbc = &emtry_cleanup_tlbc, | ||
| #endif | ||
| .co_code_adaptive = { | ||
| NOP, 0, | ||
| INTERPRETER_EXIT, 0, /* reached on return */ | ||
| NOP, 0, | ||
| INTERPRETER_EXIT, 0, /* reached on yield */ | ||
| RESUME, RESUME_OPARG_DEPTH1_MASK | RESUME_AT_FUNC_START | ||
| } | ||
| }; | ||
| const _Py_CODEUNIT *_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR = (_Py_CODEUNIT*)&_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS; | ||
|
Member
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. Remove this. It won't be needed.
Member
Author
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 need this when we're deopting to INTERPRETER_EXIT. |
||
|
|
||
| #ifdef Py_DEBUG | ||
| extern void _PyUOpPrint(const _PyUOpInstruction *uop); | ||
|
|
@@ -1140,8 +1113,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int | |
| entry.frame.f_globals = (PyObject*)0xaaa3; | ||
| entry.frame.f_builtins = (PyObject*)0xaaa4; | ||
| #endif | ||
| entry.frame.f_executable = PyStackRef_FromPyObjectBorrow((PyObject *)&_PyEntryFrameCode); | ||
| entry.frame.instr_ptr = ((_Py_CODEUNIT *)_PyEntryFrameCode.co_code_adaptive) + 1; | ||
| entry.frame.f_executable = PyStackRef_None; | ||
| entry.frame.instr_ptr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS + 1; | ||
| entry.frame.stackpointer = entry.stack; | ||
| entry.frame.owner = FRAME_OWNED_BY_INTERPRETER; | ||
| entry.frame.visited = 0; | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,7 +34,7 @@ | |
| static bool | ||
| has_space_for_executor(PyCodeObject *code, _Py_CODEUNIT *instr) | ||
| { | ||
| if (code == (PyCodeObject *)&_Py_InitCleanup || code == (PyCodeObject *)&_PyEntryFrameCode) { | ||
| if (code == (PyCodeObject *)&_Py_InitCleanup) { | ||
|
Member
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. NOTE: I don't think this should happen. This is fine for now, as it is safe. We can investigate later. |
||
| return false; | ||
| } | ||
| if (instr->op.code == ENTER_EXECUTOR) { | ||
|
|
@@ -580,7 +580,9 @@ _PyJit_translate_single_bytecode_to_trace( | |
| _Py_CODEUNIT *target_instr = this_instr; | ||
| uint32_t> | ||
|
|
||
| old_code); | ||
| *)old_code) | ||
|
Member
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. The previous instruction can never be
Member
Author
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. But we still need the target of INTERPRETER_EXIT to point the deopt to. |
||
| ? (int)(target_instr - _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS_PTR) | ||
| : INSTR_IP(target_instr, old_code); | ||
|
|
||
| // Rewind EXTENDED_ARG so that we see the whole thing. | ||
| // We must point to the first EXTENDED_ARG when deopting. | ||
|
|
@@ -858,7 +860,7 @@ _PyJit_translate_single_bytecode_to_trace( | |
| DPRINTF(2, "Adding %p func to op\n", (void *)operand); | ||
| _Py_BloomFilter_Add(dependencies, new_func); | ||
| } | ||
| else if (new_code != NULL) { | ||
| else if (new_code != NULL && !Py_IsNone((PyObject*)new_code)) { | ||
| operand = (uintptr_t)new_code | 1; | ||
| DPRINTF(2, "Adding %p code to op\n", (void *)operand); | ||
| _Py_BloomFilter_Add(dependencies, new_code); | ||
|
|
@@ -867,7 +869,7 @@ _PyJit_translate_single_bytecode_to_trace( | |
| operand = 0; | ||
| } | ||
| ADD_TO_TRACE(uop, oparg, operand, target); | ||
| trace[trace_length - 1].operand1 = ((int)(frame->stackpointer - _PyFrame_Stackbase(frame))); | ||
| trace[trace_length - 1].operand1 = PyStackRef_IsNone(frame->f_executable) ? 2 : ((int)(frame->stackpointer - _PyFrame_Stackbase(frame))); | ||
| break; | ||
| } | ||
| if (uop == _BINARY_OP_INPLACE_ADD_UNICODE) { | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd actually prefer to drop this whole block. It is logging the wrong thing (execution) at the wrong level (2) and making assumptions about the state of VM rather than just logging what it does.
If we are logging at level 4, we'll get the
_EXIT_TRACEin the log.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather we don't drop the block. It has proven extremely useful for me when debugging performance cliffs, as I can see where things deopt to. At he same time, level 4 has too much stuff, and takes too long to output on the benchmarks.