Skip to content

Commit 72f5665

Browse files
authored
GH-128682: Account for escapes in DECREF_INPUTS (GH-129953)
* Handle escapes in DECREF_INPUTS * Mark a few more functions as escaping * Replace DECREF_INPUTS with PyStackRef_CLOSE where possible
1 parent 3e222e3 commit 72f5665

18 files changed

+2220
-913
lines changed

Include/internal/pycore_ceval.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ PyAPI_FUNC(PyObject *) _PyEval_ImportName(PyThreadState *, _PyInterpreterFrame *
274274
PyAPI_FUNC(PyObject *)_PyEval_MatchClass(PyThreadState *tstate, PyObject *subject, PyObject *type, Py_ssize_t nargs, PyObject *kwargs);
275275
PyAPI_FUNC(PyObject *)_PyEval_MatchKeys(PyThreadState *tstate, PyObject *map, PyObject *keys);
276276
PyAPI_FUNC(void) _PyEval_MonitorRaise(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr);
277-
PyAPI_FUNC(int) _PyEval_UnpackIterableStackRef(PyThreadState *tstate, _PyStackRef v, int argcnt, int argcntafter, _PyStackRef *sp);
277+
PyAPI_FUNC(int) _PyEval_UnpackIterableStackRef(PyThreadState *tstate, PyObject *v, int argcnt, int argcntafter, _PyStackRef *sp);
278278
PyAPI_FUNC(void) _PyEval_FrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame);
279279
PyAPI_FUNC(PyObject **) _PyObjectArray_FromStackRefArray(_PyStackRef *input, Py_ssize_t nargs, PyObject **scratch);
280280

Include/internal/pycore_opcode_metadata.h

+16-16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

+15-15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_generated_cases.py

+25
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,7 @@ def test_stack_save_reload(self):
17231723
input = """
17241724
inst(BALANCED, ( -- )) {
17251725
SAVE_STACK();
1726+
code();
17261727
RELOAD_STACK();
17271728
}
17281729
"""
@@ -1737,12 +1738,36 @@ def test_stack_save_reload(self):
17371738
next_instr += 1;
17381739
INSTRUCTION_STATS(BALANCED);
17391740
_PyFrame_SetStackPointer(frame, stack_pointer);
1741+
code();
17401742
stack_pointer = _PyFrame_GetStackPointer(frame);
17411743
DISPATCH();
17421744
}
17431745
"""
17441746
self.run_cases_test(input, output)
17451747

1748+
def test_stack_save_reload_paired(self):
1749+
1750+
input = """
1751+
inst(BALANCED, ( -- )) {
1752+
SAVE_STACK();
1753+
RELOAD_STACK();
1754+
}
1755+
"""
1756+
1757+
output = """
1758+
TARGET(BALANCED) {
1759+
#if defined(Py_TAIL_CALL_INTERP)
1760+
int opcode = BALANCED;
1761+
(void)(opcode);
1762+
#endif
1763+
frame->instr_ptr = next_instr;
1764+
next_instr += 1;
1765+
INSTRUCTION_STATS(BALANCED);
1766+
DISPATCH();
1767+
}
1768+
"""
1769+
self.run_cases_test(input, output)
1770+
17461771
def test_stack_reload_only(self):
17471772

17481773
input = """
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
The internal (evaluation) stack is now spilled to memory whenever execution
2+
esacpes from the interpreter or JIT compiled code. This should have no
3+
observable effect in either Python or builtin extensions, but will allow
4+
various important optimizations in the future.

Objects/object.c

+5
Original file line numberDiff line numberDiff line change
@@ -2994,6 +2994,11 @@ _Py_Dealloc(PyObject *op)
29942994
destructor dealloc = type->tp_dealloc;
29952995
#ifdef Py_DEBUG
29962996
PyThreadState *tstate = _PyThreadState_GET();
2997+
#ifndef Py_GIL_DISABLED
2998+
/* This assertion doesn't hold for the free-threading build, as
2999+
* PyStackRef_CLOSE_SPECIALIZED is not implemented */
3000+
assert(tstate->current_frame == NULL || tstate->current_frame->stackpointer != NULL);
3001+
#endif
29973002
PyObject *old_exc = tstate != NULL ? tstate->current_exception : NULL;
29983003
// Keep the old exception type alive to prevent undefined behavior
29993004
// on (tstate->curexc_type != old_exc_type) below

0 commit comments

Comments
 (0)