-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
gh-115999: Implement thread-local bytecode and enable specialization for BINARY_OP
#123926
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 52 commits
776a1e1
2b40870
344d7ad
f203d00
82b456a
b021704
aea69c5
552277d
50a6089
3f1d941
7d2eb27
d5476b9
e3b367a
b2375bf
2707f8e
3fdcb28
4a55ce5
8b3ff60
862afa1
0b4d952
7795e99
693a4cc
b43531e
9025f43
c44c7d9
e2a6656
e6513d1
a18396f
81fe1a2
837645e
f13e132
942f628
66cb24d
ad12bd4
1bbbbbc
e63e403
8b97771
d34adeb
6d4fe73
c2d8693
b104782
deb5216
2f11cc7
04f1ac3
aa330b1
7dfd1ca
7c9da24
dd144d0
ad180d1
95d2264
b6380de
adb59ef
39c947d
2cc5830
96ec126
5ecebd9
815b2fe
fb90d23
4e42414
814e4ca
ba3930a
cb8a774
0f8a55b
70ce0fe
f512353
4be2b1f
61c7aa9
ab6222c
6bbb220
4580e3c
b992f44
4c040d3
5b7658c
bec5bce
c9054b7
1a48ab2
b16ae5f
176b24e
c107495
07f9140
4cbe237
38ff315
338f7e5
bcd1bb2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,6 +68,9 @@ typedef struct _PyInterpreterFrame { | |
PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */ | ||
PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */ | ||
_Py_CODEUNIT *instr_ptr; /* Instruction currently executing (or about to begin) */ | ||
#ifdef Py_GIL_DISABLED | ||
Yhg1s marked this conversation as resolved.
Show resolved
Hide resolved
|
||
_Py_CODEUNIT *bytecode; | ||
#endif | ||
_PyStackRef *stackpointer; | ||
uint16_t return_offset; /* Only relevant during a function call */ | ||
char owner; | ||
|
@@ -76,14 +79,24 @@ typedef struct _PyInterpreterFrame { | |
} _PyInterpreterFrame; | ||
|
||
#define _PyInterpreterFrame_LASTI(IF) \ | ||
((int)((IF)->instr_ptr - _PyCode_CODE(_PyFrame_GetCode(IF)))) | ||
((int)((IF)->instr_ptr - _PyFrame_GetBytecode((IF)))) | ||
|
||
static inline PyCodeObject *_PyFrame_GetCode(_PyInterpreterFrame *f) { | ||
PyObject *executable = PyStackRef_AsPyObjectBorrow(f->f_executable); | ||
assert(PyCode_Check(executable)); | ||
return (PyCodeObject *)executable; | ||
} | ||
|
||
static inline _Py_CODEUNIT * | ||
_PyFrame_GetBytecode(_PyInterpreterFrame *f) | ||
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. You were storing the bytecode in the frame directly before, IIRC. Does it makes things faster overall, or is it just more compact? 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.
Yep. You suggested storing
|
||
{ | ||
#ifdef Py_GIL_DISABLED | ||
return f->bytecode; | ||
#else | ||
return _PyCode_CODE(_PyFrame_GetCode(f)); | ||
#endif | ||
} | ||
|
||
static inline PyFunctionObject *_PyFrame_GetFunction(_PyInterpreterFrame *f) { | ||
PyObject *func = PyStackRef_AsPyObjectBorrow(f->f_funcobj); | ||
assert(PyFunction_Check(func)); | ||
|
@@ -171,6 +184,7 @@ _PyFrame_Initialize( | |
} | ||
|
||
#ifdef Py_GIL_DISABLED | ||
frame->bytecode = frame->instr_ptr; | ||
// On GIL disabled, we walk the entire stack in GC. Since stacktop | ||
// is not always in sync with the real stack pointer, we have | ||
// no choice but to traverse the entire stack. | ||
|
@@ -224,7 +238,8 @@ _PyFrame_IsIncomplete(_PyInterpreterFrame *frame) | |
return true; | ||
} | ||
return frame->owner != FRAME_OWNED_BY_GENERATOR && | ||
frame->instr_ptr < _PyCode_CODE(_PyFrame_GetCode(frame)) + _PyFrame_GetCode(frame)->_co_firsttraceable; | ||
frame->instr_ptr < _PyFrame_GetBytecode(frame) + | ||
_PyFrame_GetCode(frame)->_co_firsttraceable; | ||
} | ||
|
||
static inline _PyInterpreterFrame * | ||
|
@@ -344,6 +359,7 @@ _PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int | |
frame->return_offset = 0; | ||
|
||
#ifdef Py_GIL_DISABLED | ||
frame->bytecode = frame->instr_ptr; | ||
assert(code->co_nlocalsplus == 0); | ||
for (int i = 0; i < code->co_stacksize; i++) { | ||
frame->localsplus[i] = PyStackRef_NULL; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
#ifndef Py_INTERNAL_INDEX_POOL_H | ||
#define Py_INTERNAL_INDEX_POOL_H | ||
|
||
#include "Python.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#ifndef Py_BUILD_CORE | ||
# error "this header requires Py_BUILD_CORE define" | ||
#endif | ||
|
||
#ifdef Py_GIL_DISABLED | ||
|
||
// This contains code for allocating unique indices in an array. It is used by | ||
// the free-threaded build to assign each thread a globally unique index into | ||
// each code object's thread-local bytecode array. | ||
|
||
// A min-heap of indices | ||
typedef struct _PyIndexHeap { | ||
Py_ssize_t *values; | ||
|
||
// Number of items stored in values | ||
Py_ssize_t size; | ||
|
||
// Maximum number of items that can be stored in values | ||
Py_ssize_t capacity; | ||
} _PyIndexHeap; | ||
|
||
// An unbounded pool of indices. Indices are allocated starting from 0. They | ||
// may be released back to the pool once they are no longer in use. | ||
typedef struct _PyIndexPool { | ||
PyMutex mutex; | ||
|
||
// Min heap of indices available for allocation | ||
_PyIndexHeap free_indices; | ||
|
||
// Next index to allocate if no free indices are available | ||
Py_ssize_t next_index; | ||
} _PyIndexPool; | ||
|
||
// Allocate the smallest available index. Returns -1 on error. | ||
extern Py_ssize_t _PyIndexPool_AllocIndex(_PyIndexPool *indices); | ||
|
||
// Release `index` back to the pool | ||
extern void _PyIndexPool_FreeIndex(_PyIndexPool *indices, Py_ssize_t index); | ||
|
||
extern void _PyIndexPool_Fini(_PyIndexPool *indices); | ||
|
||
#endif // Py_GIL_DISABLED | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
#endif // !Py_INTERNAL_INDEX_POOL_H |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.