mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
GH-132508: Use tagged integers on the evaluation stack for the last instruction offset (GH-132545)
This commit is contained in:
parent
caee16f052
commit
ccf1b0b1c1
14 changed files with 129 additions and 60 deletions
|
@ -18,6 +18,7 @@ extern "C" {
|
||||||
((int)((IF)->instr_ptr - _PyFrame_GetBytecode((IF))))
|
((int)((IF)->instr_ptr - _PyFrame_GetBytecode((IF))))
|
||||||
|
|
||||||
static inline PyCodeObject *_PyFrame_GetCode(_PyInterpreterFrame *f) {
|
static inline PyCodeObject *_PyFrame_GetCode(_PyInterpreterFrame *f) {
|
||||||
|
assert(!PyStackRef_IsNull(f->f_executable));
|
||||||
PyObject *executable = PyStackRef_AsPyObjectBorrow(f->f_executable);
|
PyObject *executable = PyStackRef_AsPyObjectBorrow(f->f_executable);
|
||||||
assert(PyCode_Check(executable));
|
assert(PyCode_Check(executable));
|
||||||
return (PyCodeObject *)executable;
|
return (PyCodeObject *)executable;
|
||||||
|
|
|
@ -63,11 +63,13 @@ extern void _Py_stackref_associate(PyInterpreterState *interp, PyObject *obj, _P
|
||||||
|
|
||||||
static const _PyStackRef PyStackRef_NULL = { .index = 0 };
|
static const _PyStackRef PyStackRef_NULL = { .index = 0 };
|
||||||
|
|
||||||
#define PyStackRef_None ((_PyStackRef){ .index = 1 } )
|
// Use the first 3 even numbers for None, True and False.
|
||||||
#define PyStackRef_False ((_PyStackRef){ .index = 2 })
|
// Odd numbers are reserved for (tagged) integers
|
||||||
#define PyStackRef_True ((_PyStackRef){ .index = 3 })
|
#define PyStackRef_None ((_PyStackRef){ .index = 2 } )
|
||||||
|
#define PyStackRef_False ((_PyStackRef){ .index = 4 })
|
||||||
|
#define PyStackRef_True ((_PyStackRef){ .index = 6 })
|
||||||
|
|
||||||
#define LAST_PREDEFINED_STACKREF_INDEX 3
|
#define INITIAL_STACKREF_INDEX 8
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
PyStackRef_IsNull(_PyStackRef ref)
|
PyStackRef_IsNull(_PyStackRef ref)
|
||||||
|
@ -96,6 +98,7 @@ PyStackRef_IsNone(_PyStackRef ref)
|
||||||
static inline PyObject *
|
static inline PyObject *
|
||||||
_PyStackRef_AsPyObjectBorrow(_PyStackRef ref, const char *filename, int linenumber)
|
_PyStackRef_AsPyObjectBorrow(_PyStackRef ref, const char *filename, int linenumber)
|
||||||
{
|
{
|
||||||
|
assert((ref.index & 1) == 0);
|
||||||
_Py_stackref_record_borrow(ref, filename, linenumber);
|
_Py_stackref_record_borrow(ref, filename, linenumber);
|
||||||
return _Py_stackref_get_object(ref);
|
return _Py_stackref_get_object(ref);
|
||||||
}
|
}
|
||||||
|
@ -132,31 +135,45 @@ _PyStackRef_FromPyObjectImmortal(PyObject *obj, const char *filename, int linenu
|
||||||
}
|
}
|
||||||
#define PyStackRef_FromPyObjectImmortal(obj) _PyStackRef_FromPyObjectImmortal(_PyObject_CAST(obj), __FILE__, __LINE__)
|
#define PyStackRef_FromPyObjectImmortal(obj) _PyStackRef_FromPyObjectImmortal(_PyObject_CAST(obj), __FILE__, __LINE__)
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
PyStackRef_IsTaggedInt(_PyStackRef ref)
|
||||||
|
{
|
||||||
|
return (ref.index & 1) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
_PyStackRef_CLOSE(_PyStackRef ref, const char *filename, int linenumber)
|
_PyStackRef_CLOSE(_PyStackRef ref, const char *filename, int linenumber)
|
||||||
{
|
{
|
||||||
|
if (PyStackRef_IsTaggedInt(ref)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
PyObject *obj = _Py_stackref_close(ref, filename, linenumber);
|
PyObject *obj = _Py_stackref_close(ref, filename, linenumber);
|
||||||
Py_DECREF(obj);
|
Py_DECREF(obj);
|
||||||
}
|
}
|
||||||
#define PyStackRef_CLOSE(REF) _PyStackRef_CLOSE((REF), __FILE__, __LINE__)
|
#define PyStackRef_CLOSE(REF) _PyStackRef_CLOSE((REF), __FILE__, __LINE__)
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
_PyStackRef_XCLOSE(_PyStackRef ref, const char *filename, int linenumber)
|
_PyStackRef_XCLOSE(_PyStackRef ref, const char *filename, int linenumber)
|
||||||
{
|
{
|
||||||
if (PyStackRef_IsNull(ref)) {
|
if (PyStackRef_IsNull(ref)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PyObject *obj = _Py_stackref_close(ref, filename, linenumber);
|
_PyStackRef_CLOSE(ref, filename, linenumber);
|
||||||
Py_DECREF(obj);
|
|
||||||
}
|
}
|
||||||
#define PyStackRef_XCLOSE(REF) _PyStackRef_XCLOSE((REF), __FILE__, __LINE__)
|
#define PyStackRef_XCLOSE(REF) _PyStackRef_XCLOSE((REF), __FILE__, __LINE__)
|
||||||
|
|
||||||
static inline _PyStackRef
|
static inline _PyStackRef
|
||||||
_PyStackRef_DUP(_PyStackRef ref, const char *filename, int linenumber)
|
_PyStackRef_DUP(_PyStackRef ref, const char *filename, int linenumber)
|
||||||
{
|
{
|
||||||
PyObject *obj = _Py_stackref_get_object(ref);
|
if (PyStackRef_IsTaggedInt(ref)) {
|
||||||
Py_INCREF(obj);
|
return ref;
|
||||||
return _Py_stackref_create(obj, filename, linenumber);
|
}
|
||||||
|
else {
|
||||||
|
PyObject *obj = _Py_stackref_get_object(ref);
|
||||||
|
Py_INCREF(obj);
|
||||||
|
return _Py_stackref_create(obj, filename, linenumber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#define PyStackRef_DUP(REF) _PyStackRef_DUP(REF, __FILE__, __LINE__)
|
#define PyStackRef_DUP(REF) _PyStackRef_DUP(REF, __FILE__, __LINE__)
|
||||||
|
|
||||||
|
@ -210,8 +227,40 @@ _PyStackRef_FromPyObjectNewMortal(PyObject *obj, const char *filename, int linen
|
||||||
|
|
||||||
extern int PyStackRef_Is(_PyStackRef a, _PyStackRef b);
|
extern int PyStackRef_Is(_PyStackRef a, _PyStackRef b);
|
||||||
|
|
||||||
|
extern bool PyStackRef_IsTaggedInt(_PyStackRef ref);
|
||||||
|
|
||||||
|
extern intptr_t PyStackRef_UntagInt(_PyStackRef ref);
|
||||||
|
|
||||||
|
extern _PyStackRef PyStackRef_TagInt(intptr_t i);
|
||||||
|
|
||||||
|
extern bool
|
||||||
|
PyStackRef_IsNullOrInt(_PyStackRef ref);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#define Py_INT_TAG 3
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
PyStackRef_IsTaggedInt(_PyStackRef i)
|
||||||
|
{
|
||||||
|
return (i.bits & Py_INT_TAG) == Py_INT_TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline _PyStackRef
|
||||||
|
PyStackRef_TagInt(intptr_t i)
|
||||||
|
{
|
||||||
|
assert(Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, (i << 2), 2) == i);
|
||||||
|
return (_PyStackRef){ .bits = ((((uintptr_t)i) << 2) | Py_INT_TAG) };
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline intptr_t
|
||||||
|
PyStackRef_UntagInt(_PyStackRef i)
|
||||||
|
{
|
||||||
|
assert((i.bits & Py_INT_TAG) == Py_INT_TAG);
|
||||||
|
intptr_t val = (intptr_t)i.bits;
|
||||||
|
return Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, val, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
|
|
||||||
|
@ -232,6 +281,8 @@ static const _PyStackRef PyStackRef_NULL = { .bits = Py_TAG_DEFERRED};
|
||||||
#define PyStackRef_IsTrue(ref) (PyStackRef_AsPyObjectBorrow(ref) == Py_True)
|
#define PyStackRef_IsTrue(ref) (PyStackRef_AsPyObjectBorrow(ref) == Py_True)
|
||||||
#define PyStackRef_IsFalse(ref) (PyStackRef_AsPyObjectBorrow(ref) == Py_False)
|
#define PyStackRef_IsFalse(ref) (PyStackRef_AsPyObjectBorrow(ref) == Py_False)
|
||||||
|
|
||||||
|
#define PyStackRef_IsNullOrInt(stackref) (PyStackRef_IsNull(stackref) || PyStackRef_IsTaggedInt(stackref))
|
||||||
|
|
||||||
static inline PyObject *
|
static inline PyObject *
|
||||||
PyStackRef_AsPyObjectBorrow(_PyStackRef stackref)
|
PyStackRef_AsPyObjectBorrow(_PyStackRef stackref)
|
||||||
{
|
{
|
||||||
|
@ -451,6 +502,7 @@ PyStackRef_RefcountOnObject(_PyStackRef ref)
|
||||||
static inline PyObject *
|
static inline PyObject *
|
||||||
PyStackRef_AsPyObjectBorrow(_PyStackRef ref)
|
PyStackRef_AsPyObjectBorrow(_PyStackRef ref)
|
||||||
{
|
{
|
||||||
|
assert(!PyStackRef_IsTaggedInt(ref));
|
||||||
return BITS_TO_PTR_MASKED(ref);
|
return BITS_TO_PTR_MASKED(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,6 +639,12 @@ PyStackRef_CLOSE(_PyStackRef ref)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
PyStackRef_IsNullOrInt(_PyStackRef ref)
|
||||||
|
{
|
||||||
|
return PyStackRef_IsNull(ref) || PyStackRef_IsTaggedInt(ref);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct)
|
PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct)
|
||||||
{
|
{
|
||||||
|
@ -726,7 +784,7 @@ _Py_TryXGetStackRef(PyObject **src, _PyStackRef *out)
|
||||||
// Like Py_VISIT but for _PyStackRef fields
|
// Like Py_VISIT but for _PyStackRef fields
|
||||||
#define _Py_VISIT_STACKREF(ref) \
|
#define _Py_VISIT_STACKREF(ref) \
|
||||||
do { \
|
do { \
|
||||||
if (!PyStackRef_IsNull(ref)) { \
|
if (!PyStackRef_IsNullOrInt(ref)) { \
|
||||||
int vret = _PyGC_VisitStackRef(&(ref), visit, arg); \
|
int vret = _PyGC_VisitStackRef(&(ref), visit, arg); \
|
||||||
if (vret) \
|
if (vret) \
|
||||||
return vret; \
|
return vret; \
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Uses tagged integers on the evaluation stack to represent the instruction
|
||||||
|
offsets when reraising an exception. This avoids the need to box the integer
|
||||||
|
which could fail in low memory conditions.
|
|
@ -1813,15 +1813,16 @@ frame_lineno_set_impl(PyFrameObject *self, PyObject *value)
|
||||||
start_stack = pop_value(start_stack);
|
start_stack = pop_value(start_stack);
|
||||||
}
|
}
|
||||||
while (start_stack > best_stack) {
|
while (start_stack > best_stack) {
|
||||||
|
_PyStackRef popped = _PyFrame_StackPop(self->f_frame);
|
||||||
if (top_of_stack(start_stack) == Except) {
|
if (top_of_stack(start_stack) == Except) {
|
||||||
/* Pop exception stack as well as the evaluation stack */
|
/* Pop exception stack as well as the evaluation stack */
|
||||||
PyObject *exc = PyStackRef_AsPyObjectBorrow(_PyFrame_StackPop(self->f_frame));
|
PyObject *exc = PyStackRef_AsPyObjectBorrow(popped);
|
||||||
assert(PyExceptionInstance_Check(exc) || exc == Py_None);
|
assert(PyExceptionInstance_Check(exc) || exc == Py_None);
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
Py_XSETREF(tstate->exc_info->exc_value, exc == Py_None ? NULL : exc);
|
Py_XSETREF(tstate->exc_info->exc_value, exc == Py_None ? NULL : exc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PyStackRef_XCLOSE(_PyFrame_StackPop(self->f_frame));
|
PyStackRef_XCLOSE(popped);
|
||||||
}
|
}
|
||||||
start_stack = pop_value(start_stack);
|
start_stack = pop_value(start_stack);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1384,16 +1384,7 @@ dummy_func(
|
||||||
|
|
||||||
assert(oparg >= 0 && oparg <= 2);
|
assert(oparg >= 0 && oparg <= 2);
|
||||||
if (oparg) {
|
if (oparg) {
|
||||||
PyObject *lasti = PyStackRef_AsPyObjectBorrow(values[0]);
|
frame->instr_ptr = _PyFrame_GetBytecode(frame) + PyStackRef_UntagInt(values[0]);
|
||||||
if (PyLong_Check(lasti)) {
|
|
||||||
frame->instr_ptr = _PyFrame_GetBytecode(frame) + PyLong_AsLong(lasti);
|
|
||||||
assert(!_PyErr_Occurred(tstate));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int");
|
|
||||||
Py_DECREF(exc);
|
|
||||||
ERROR_NO_POP();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
assert(exc && PyExceptionInstance_Check(exc));
|
assert(exc && PyExceptionInstance_Check(exc));
|
||||||
_PyErr_SetRaisedException(tstate, exc);
|
_PyErr_SetRaisedException(tstate, exc);
|
||||||
|
@ -3472,7 +3463,7 @@ dummy_func(
|
||||||
if (tb == NULL) {
|
if (tb == NULL) {
|
||||||
tb = Py_None;
|
tb = Py_None;
|
||||||
}
|
}
|
||||||
assert(PyStackRef_LongCheck(lasti));
|
assert(PyStackRef_IsTaggedInt(lasti));
|
||||||
(void)lasti; // Shut up compiler warning if asserts are off
|
(void)lasti; // Shut up compiler warning if asserts are off
|
||||||
PyObject *stack[5] = {NULL, PyStackRef_AsPyObjectBorrow(exit_self), exc, val_o, tb};
|
PyObject *stack[5] = {NULL, PyStackRef_AsPyObjectBorrow(exit_self), exc, val_o, tb};
|
||||||
int has_self = !PyStackRef_IsNull(exit_self);
|
int has_self = !PyStackRef_IsNull(exit_self);
|
||||||
|
@ -5378,11 +5369,8 @@ dummy_func(
|
||||||
}
|
}
|
||||||
if (lasti) {
|
if (lasti) {
|
||||||
int frame_lasti = _PyInterpreterFrame_LASTI(frame);
|
int frame_lasti = _PyInterpreterFrame_LASTI(frame);
|
||||||
PyObject *lasti = PyLong_FromLong(frame_lasti);
|
_PyStackRef lasti = PyStackRef_TagInt(frame_lasti);
|
||||||
if (lasti == NULL) {
|
_PyFrame_StackPush(frame, lasti);
|
||||||
goto exception_unwind;
|
|
||||||
}
|
|
||||||
_PyFrame_StackPush(frame, PyStackRef_FromPyObjectSteal(lasti));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make the raw exception data
|
/* Make the raw exception data
|
||||||
|
|
|
@ -146,6 +146,10 @@ dump_item(_PyStackRef item)
|
||||||
printf("<NULL>");
|
printf("<NULL>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (PyStackRef_IsTaggedInt(item)) {
|
||||||
|
printf("%" PRId64, (int64_t)PyStackRef_UntagInt(item));
|
||||||
|
return;
|
||||||
|
}
|
||||||
PyObject *obj = PyStackRef_AsPyObjectBorrow(item);
|
PyObject *obj = PyStackRef_AsPyObjectBorrow(item);
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
printf("<nil>");
|
printf("<nil>");
|
||||||
|
|
2
Python/executor_cases.c.h
generated
2
Python/executor_cases.c.h
generated
|
@ -4470,7 +4470,7 @@
|
||||||
if (tb == NULL) {
|
if (tb == NULL) {
|
||||||
tb = Py_None;
|
tb = Py_None;
|
||||||
}
|
}
|
||||||
assert(PyStackRef_LongCheck(lasti));
|
assert(PyStackRef_IsTaggedInt(lasti));
|
||||||
(void)lasti;
|
(void)lasti;
|
||||||
PyObject *stack[5] = {NULL, PyStackRef_AsPyObjectBorrow(exit_self), exc, val_o, tb};
|
PyObject *stack[5] = {NULL, PyStackRef_AsPyObjectBorrow(exit_self), exc, val_o, tb};
|
||||||
int has_self = !PyStackRef_IsNull(exit_self);
|
int has_self = !PyStackRef_IsNull(exit_self);
|
||||||
|
|
10
Python/gc.c
10
Python/gc.c
|
@ -547,6 +547,7 @@ _PyGC_VisitStackRef(_PyStackRef *ref, visitproc visit, void *arg)
|
||||||
// This is a bit tricky! We want to ignore stackrefs with embedded
|
// This is a bit tricky! We want to ignore stackrefs with embedded
|
||||||
// refcounts when computing the incoming references, but otherwise treat
|
// refcounts when computing the incoming references, but otherwise treat
|
||||||
// them like normal.
|
// them like normal.
|
||||||
|
assert(!PyStackRef_IsTaggedInt(*ref));
|
||||||
if (!PyStackRef_RefcountOnObject(*ref) && (visit == visit_decref)) {
|
if (!PyStackRef_RefcountOnObject(*ref) && (visit == visit_decref)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -560,7 +561,9 @@ _PyGC_VisitFrameStack(_PyInterpreterFrame *frame, visitproc visit, void *arg)
|
||||||
_PyStackRef *ref = _PyFrame_GetLocalsArray(frame);
|
_PyStackRef *ref = _PyFrame_GetLocalsArray(frame);
|
||||||
/* locals and stack */
|
/* locals and stack */
|
||||||
for (; ref < frame->stackpointer; ref++) {
|
for (; ref < frame->stackpointer; ref++) {
|
||||||
_Py_VISIT_STACKREF(*ref);
|
if (!PyStackRef_IsTaggedInt(*ref)) {
|
||||||
|
_Py_VISIT_STACKREF(*ref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1495,8 +1498,11 @@ mark_stacks(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, b
|
||||||
objects_marked += move_to_reachable(func, &reachable, visited_space);
|
objects_marked += move_to_reachable(func, &reachable, visited_space);
|
||||||
while (sp > locals) {
|
while (sp > locals) {
|
||||||
sp--;
|
sp--;
|
||||||
|
if (PyStackRef_IsNullOrInt(*sp)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
PyObject *op = PyStackRef_AsPyObjectBorrow(*sp);
|
PyObject *op = PyStackRef_AsPyObjectBorrow(*sp);
|
||||||
if (op == NULL || _Py_IsImmortal(op)) {
|
if (_Py_IsImmortal(op)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (_PyObject_IS_GC(op)) {
|
if (_PyObject_IS_GC(op)) {
|
||||||
|
|
|
@ -265,7 +265,7 @@ frame_disable_deferred_refcounting(_PyInterpreterFrame *frame)
|
||||||
|
|
||||||
frame->f_funcobj = PyStackRef_AsStrongReference(frame->f_funcobj);
|
frame->f_funcobj = PyStackRef_AsStrongReference(frame->f_funcobj);
|
||||||
for (_PyStackRef *ref = frame->localsplus; ref < frame->stackpointer; ref++) {
|
for (_PyStackRef *ref = frame->localsplus; ref < frame->stackpointer; ref++) {
|
||||||
if (!PyStackRef_IsNull(*ref) && PyStackRef_IsDeferred(*ref)) {
|
if (!PyStackRef_IsNullOrInt(*ref) && PyStackRef_IsDeferred(*ref)) {
|
||||||
*ref = PyStackRef_AsStrongReference(*ref);
|
*ref = PyStackRef_AsStrongReference(*ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -420,7 +420,7 @@ gc_visit_heaps(PyInterpreterState *interp, mi_block_visit_fun *visitor,
|
||||||
static inline void
|
static inline void
|
||||||
gc_visit_stackref(_PyStackRef stackref)
|
gc_visit_stackref(_PyStackRef stackref)
|
||||||
{
|
{
|
||||||
if (PyStackRef_IsDeferred(stackref) && !PyStackRef_IsNull(stackref)) {
|
if (PyStackRef_IsDeferred(stackref) && !PyStackRef_IsNullOrInt(stackref)) {
|
||||||
PyObject *obj = PyStackRef_AsPyObjectBorrow(stackref);
|
PyObject *obj = PyStackRef_AsPyObjectBorrow(stackref);
|
||||||
if (_PyObject_GC_IS_TRACKED(obj) && !gc_is_frozen(obj)) {
|
if (_PyObject_GC_IS_TRACKED(obj) && !gc_is_frozen(obj)) {
|
||||||
gc_add_refs(obj, 1);
|
gc_add_refs(obj, 1);
|
||||||
|
@ -817,7 +817,7 @@ gc_abort_mark_alive(PyInterpreterState *interp,
|
||||||
static int
|
static int
|
||||||
gc_visit_stackref_mark_alive(gc_mark_args_t *args, _PyStackRef stackref)
|
gc_visit_stackref_mark_alive(gc_mark_args_t *args, _PyStackRef stackref)
|
||||||
{
|
{
|
||||||
if (!PyStackRef_IsNull(stackref)) {
|
if (!PyStackRef_IsNullOrInt(stackref)) {
|
||||||
PyObject *op = PyStackRef_AsPyObjectBorrow(stackref);
|
PyObject *op = PyStackRef_AsPyObjectBorrow(stackref);
|
||||||
if (gc_mark_enqueue(op, args) < 0) {
|
if (gc_mark_enqueue(op, args) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1706,6 +1706,7 @@ _PyGC_VisitStackRef(_PyStackRef *ref, visitproc visit, void *arg)
|
||||||
// This is a bit tricky! We want to ignore deferred references when
|
// This is a bit tricky! We want to ignore deferred references when
|
||||||
// computing the incoming references, but otherwise treat them like
|
// computing the incoming references, but otherwise treat them like
|
||||||
// regular references.
|
// regular references.
|
||||||
|
assert(!PyStackRef_IsTaggedInt(*ref));
|
||||||
if (!PyStackRef_IsDeferred(*ref) ||
|
if (!PyStackRef_IsDeferred(*ref) ||
|
||||||
(visit != visit_decref && visit != visit_decref_unreachable))
|
(visit != visit_decref && visit != visit_decref_unreachable))
|
||||||
{
|
{
|
||||||
|
|
24
Python/generated_cases.c.h
generated
24
Python/generated_cases.c.h
generated
|
@ -10191,20 +10191,7 @@
|
||||||
PyObject *exc = PyStackRef_AsPyObjectSteal(exc_st);
|
PyObject *exc = PyStackRef_AsPyObjectSteal(exc_st);
|
||||||
assert(oparg >= 0 && oparg <= 2);
|
assert(oparg >= 0 && oparg <= 2);
|
||||||
if (oparg) {
|
if (oparg) {
|
||||||
PyObject *lasti = PyStackRef_AsPyObjectBorrow(values[0]);
|
frame->instr_ptr = _PyFrame_GetBytecode(frame) + PyStackRef_UntagInt(values[0]);
|
||||||
if (PyLong_Check(lasti)) {
|
|
||||||
frame->instr_ptr = _PyFrame_GetBytecode(frame) + PyLong_AsLong(lasti);
|
|
||||||
assert(!_PyErr_Occurred(tstate));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
stack_pointer += -1;
|
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
|
||||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
|
||||||
_PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int");
|
|
||||||
Py_DECREF(exc);
|
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
|
||||||
JUMP_TO_LABEL(error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
assert(exc && PyExceptionInstance_Check(exc));
|
assert(exc && PyExceptionInstance_Check(exc));
|
||||||
stack_pointer += -1;
|
stack_pointer += -1;
|
||||||
|
@ -12059,7 +12046,7 @@
|
||||||
if (tb == NULL) {
|
if (tb == NULL) {
|
||||||
tb = Py_None;
|
tb = Py_None;
|
||||||
}
|
}
|
||||||
assert(PyStackRef_LongCheck(lasti));
|
assert(PyStackRef_IsTaggedInt(lasti));
|
||||||
(void)lasti;
|
(void)lasti;
|
||||||
PyObject *stack[5] = {NULL, PyStackRef_AsPyObjectBorrow(exit_self), exc, val_o, tb};
|
PyObject *stack[5] = {NULL, PyStackRef_AsPyObjectBorrow(exit_self), exc, val_o, tb};
|
||||||
int has_self = !PyStackRef_IsNull(exit_self);
|
int has_self = !PyStackRef_IsNull(exit_self);
|
||||||
|
@ -12231,11 +12218,8 @@ JUMP_TO_LABEL(error);
|
||||||
}
|
}
|
||||||
if (lasti) {
|
if (lasti) {
|
||||||
int frame_lasti = _PyInterpreterFrame_LASTI(frame);
|
int frame_lasti = _PyInterpreterFrame_LASTI(frame);
|
||||||
PyObject *lasti = PyLong_FromLong(frame_lasti);
|
_PyStackRef lasti = PyStackRef_TagInt(frame_lasti);
|
||||||
if (lasti == NULL) {
|
_PyFrame_StackPush(frame, lasti);
|
||||||
JUMP_TO_LABEL(exception_unwind);
|
|
||||||
}
|
|
||||||
_PyFrame_StackPush(frame, PyStackRef_FromPyObjectSteal(lasti));
|
|
||||||
}
|
}
|
||||||
PyObject *exc = _PyErr_GetRaisedException(tstate);
|
PyObject *exc = _PyErr_GetRaisedException(tstate);
|
||||||
_PyFrame_StackPush(frame, PyStackRef_FromPyObjectSteal(exc));
|
_PyFrame_StackPush(frame, PyStackRef_FromPyObjectSteal(exc));
|
||||||
|
|
|
@ -684,7 +684,7 @@ init_interpreter(PyInterpreterState *interp,
|
||||||
interp->dtoa = (struct _dtoa_state)_dtoa_state_INIT(interp);
|
interp->dtoa = (struct _dtoa_state)_dtoa_state_INIT(interp);
|
||||||
}
|
}
|
||||||
#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
||||||
interp->next_stackref = 1;
|
interp->next_stackref = INITIAL_STACKREF_INDEX;
|
||||||
_Py_hashtable_allocator_t alloc = {
|
_Py_hashtable_allocator_t alloc = {
|
||||||
.malloc = malloc,
|
.malloc = malloc,
|
||||||
.free = free,
|
.free = free,
|
||||||
|
|
|
@ -70,7 +70,7 @@ _Py_stackref_close(_PyStackRef ref, const char *filename, int linenumber)
|
||||||
|
|
||||||
}
|
}
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
if (ref.index <= LAST_PREDEFINED_STACKREF_INDEX) {
|
if (ref.index < INITIAL_STACKREF_INDEX) {
|
||||||
if (ref.index == 0) {
|
if (ref.index == 0) {
|
||||||
_Py_FatalErrorFormat(__func__, "Passing NULL to PyStackRef_CLOSE at %s:%d\n", filename, linenumber);
|
_Py_FatalErrorFormat(__func__, "Passing NULL to PyStackRef_CLOSE at %s:%d\n", filename, linenumber);
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,8 @@ _Py_stackref_create(PyObject *obj, const char *filename, int linenumber)
|
||||||
Py_FatalError("Cannot create a stackref for NULL");
|
Py_FatalError("Cannot create a stackref for NULL");
|
||||||
}
|
}
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyInterpreterState *interp = PyInterpreterState_Get();
|
||||||
uint64_t new_id = interp->next_stackref++;
|
uint64_t new_id = interp->next_stackref;
|
||||||
|
interp->next_stackref = new_id + 2;
|
||||||
TableEntry *entry = make_table_entry(obj, filename, linenumber);
|
TableEntry *entry = make_table_entry(obj, filename, linenumber);
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
Py_FatalError("No memory left for stackref debug table");
|
Py_FatalError("No memory left for stackref debug table");
|
||||||
|
@ -127,7 +128,7 @@ _Py_stackref_create(PyObject *obj, const char *filename, int linenumber)
|
||||||
void
|
void
|
||||||
_Py_stackref_record_borrow(_PyStackRef ref, const char *filename, int linenumber)
|
_Py_stackref_record_borrow(_PyStackRef ref, const char *filename, int linenumber)
|
||||||
{
|
{
|
||||||
if (ref.index <= LAST_PREDEFINED_STACKREF_INDEX) {
|
if (ref.index < INITIAL_STACKREF_INDEX) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyInterpreterState *interp = PyInterpreterState_Get();
|
||||||
|
@ -151,8 +152,7 @@ _Py_stackref_record_borrow(_PyStackRef ref, const char *filename, int linenumber
|
||||||
void
|
void
|
||||||
_Py_stackref_associate(PyInterpreterState *interp, PyObject *obj, _PyStackRef ref)
|
_Py_stackref_associate(PyInterpreterState *interp, PyObject *obj, _PyStackRef ref)
|
||||||
{
|
{
|
||||||
assert(interp->next_stackref >= ref.index);
|
assert(ref.index < INITIAL_STACKREF_INDEX);
|
||||||
interp->next_stackref = ref.index+1;
|
|
||||||
TableEntry *entry = make_table_entry(obj, "builtin-object", 0);
|
TableEntry *entry = make_table_entry(obj, "builtin-object", 0);
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
Py_FatalError("No memory left for stackref debug table");
|
Py_FatalError("No memory left for stackref debug table");
|
||||||
|
@ -197,4 +197,23 @@ _PyStackRef_CLOSE_SPECIALIZED(_PyStackRef ref, destructor destruct, const char *
|
||||||
_Py_DECREF_SPECIALIZED(obj, destruct);
|
_Py_DECREF_SPECIALIZED(obj, destruct);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_PyStackRef PyStackRef_TagInt(intptr_t i)
|
||||||
|
{
|
||||||
|
return (_PyStackRef){ .index = (i << 1) + 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr_t
|
||||||
|
PyStackRef_UntagInt(_PyStackRef i)
|
||||||
|
{
|
||||||
|
assert(PyStackRef_IsTaggedInt(i));
|
||||||
|
intptr_t val = (intptr_t)i.index;
|
||||||
|
return Py_ARITHMETIC_RIGHT_SHIFT(intptr_t, val, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PyStackRef_IsNullOrInt(_PyStackRef ref)
|
||||||
|
{
|
||||||
|
return PyStackRef_IsNull(ref) || PyStackRef_IsTaggedInt(ref);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -678,6 +678,9 @@ NON_ESCAPING_FUNCTIONS = (
|
||||||
"JUMP_TO_LABEL",
|
"JUMP_TO_LABEL",
|
||||||
"restart_backoff_counter",
|
"restart_backoff_counter",
|
||||||
"_Py_ReachedRecursionLimit",
|
"_Py_ReachedRecursionLimit",
|
||||||
|
"PyStackRef_IsTaggedInt",
|
||||||
|
"PyStackRef_TagInt",
|
||||||
|
"PyStackRef_UntagInt",
|
||||||
)
|
)
|
||||||
|
|
||||||
def check_escaping_calls(instr: parser.CodeDef, escapes: dict[SimpleStmt, EscapingCall]) -> None:
|
def check_escaping_calls(instr: parser.CodeDef, escapes: dict[SimpleStmt, EscapingCall]) -> None:
|
||||||
|
|
|
@ -293,6 +293,7 @@ class StencilGroup:
|
||||||
hole.kind
|
hole.kind
|
||||||
in {"R_AARCH64_CALL26", "R_AARCH64_JUMP26", "ARM64_RELOC_BRANCH26"}
|
in {"R_AARCH64_CALL26", "R_AARCH64_JUMP26", "ARM64_RELOC_BRANCH26"}
|
||||||
and hole.value is HoleValue.ZERO
|
and hole.value is HoleValue.ZERO
|
||||||
|
and hole.symbol not in self.symbols
|
||||||
):
|
):
|
||||||
hole.func = "patch_aarch64_trampoline"
|
hole.func = "patch_aarch64_trampoline"
|
||||||
hole.need_state = True
|
hole.need_state = True
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue