gh-118926: Spill deferred references to stack in cases generator (#122748)

This automatically spills the results from `_PyStackRef_FromPyObjectNew`
to the in-memory stack so that the deferred references are visible to
the GC before we make any possibly escaping call.

Co-authored-by: Ken Jin <kenjin@python.org>
This commit is contained in:
Sam Gross 2024-08-07 13:23:53 -04:00 committed by GitHub
parent 967a4f1d18
commit 3e753c689a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 176 additions and 63 deletions

View file

@ -1424,7 +1424,7 @@ dummy_func(
"no locals found");
ERROR_IF(true, error);
}
locals = PyStackRef_FromPyObjectNew(l);;
locals = PyStackRef_FromPyObjectNew(l);
}
inst(LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) {

View file

@ -1469,10 +1469,10 @@
}
STAT_INC(UNPACK_SEQUENCE, hit);
val0 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 0));
val1 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 1));
PyStackRef_CLOSE(seq);
stack_pointer[-1] = val1;
stack_pointer[0] = val0;
val1 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 1));
stack_pointer[-1] = val1;
PyStackRef_CLOSE(seq);
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
@ -1612,7 +1612,7 @@
"no locals found");
if (true) JUMP_TO_ERROR();
}
locals = PyStackRef_FromPyObjectNew(l);;
locals = PyStackRef_FromPyObjectNew(l);
stack_pointer[0] = locals;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
@ -2422,8 +2422,8 @@
STAT_INC(LOAD_ATTR, hit);
null = PyStackRef_NULL;
attr = PyStackRef_FromPyObjectNew(attr_o);
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
PyStackRef_CLOSE(owner);
break;
}
@ -2444,8 +2444,8 @@
STAT_INC(LOAD_ATTR, hit);
null = PyStackRef_NULL;
attr = PyStackRef_FromPyObjectNew(attr_o);
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
PyStackRef_CLOSE(owner);
stack_pointer[0] = null;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
@ -2481,9 +2481,9 @@
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
attr = PyStackRef_FromPyObjectNew(descr);
stack_pointer[-1] = attr;
null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
break;
}
@ -2497,9 +2497,9 @@
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
attr = PyStackRef_FromPyObjectNew(descr);
stack_pointer[-1] = attr;
null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
stack_pointer[-1] = attr;
stack_pointer[0] = null;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
@ -3437,8 +3437,8 @@
assert(descr != NULL);
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
attr = PyStackRef_FromPyObjectNew(descr);
self = owner;
stack_pointer[-1] = attr;
self = owner;
stack_pointer[0] = self;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
@ -3458,8 +3458,8 @@
assert(descr != NULL);
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
attr = PyStackRef_FromPyObjectNew(descr);
self = owner;
stack_pointer[-1] = attr;
self = owner;
stack_pointer[0] = self;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
@ -3523,8 +3523,8 @@
assert(descr != NULL);
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
attr = PyStackRef_FromPyObjectNew(descr);
self = owner;
stack_pointer[-1] = attr;
self = owner;
stack_pointer[0] = self;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
@ -3546,8 +3546,10 @@
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
PyObject *self = ((PyMethodObject *)callable_o)->im_self;
maybe_self = PyStackRef_FromPyObjectNew(self);
stack_pointer[-1 - oparg] = maybe_self;
PyObject *method = ((PyMethodObject *)callable_o)->im_func;
func = PyStackRef_FromPyObjectNew(method);
stack_pointer[-2 - oparg] = func;
/* Make sure that callable and all args are in memory */
args[-2] = func;
args[-1] = maybe_self;
@ -3557,8 +3559,6 @@
func = callable;
maybe_self = self_or_null;
}
stack_pointer[-2 - oparg] = func;
stack_pointer[-1 - oparg] = maybe_self;
break;
}
@ -3666,11 +3666,11 @@
assert(PyStackRef_IsNull(null));
assert(Py_TYPE(callable_o) == &PyMethod_Type);
self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
stack_pointer[-1 - oparg] = self;
method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
stack_pointer[-2 - oparg] = method;
assert(PyStackRef_FunctionCheck(method));
PyStackRef_CLOSE(callable);
stack_pointer[-2 - oparg] = method;
stack_pointer[-1 - oparg] = self;
break;
}
@ -3763,10 +3763,10 @@
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
STAT_INC(CALL, hit);
self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
func = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
PyStackRef_CLOSE(callable);
stack_pointer[-2 - oparg] = func;
stack_pointer[-1 - oparg] = self;
func = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
stack_pointer[-2 - oparg] = func;
PyStackRef_CLOSE(callable);
break;
}
@ -5088,8 +5088,8 @@
_PyStackRef null;
PyObject *ptr = (PyObject *)CURRENT_OPERAND();
value = PyStackRef_FromPyObjectNew(ptr);
null = PyStackRef_NULL;
stack_pointer[0] = value;
null = PyStackRef_NULL;
stack_pointer[1] = null;
stack_pointer += 2;
assert(WITHIN_STACK_BOUNDS());

View file

@ -867,8 +867,10 @@
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
PyObject *self = ((PyMethodObject *)callable_o)->im_self;
maybe_self = PyStackRef_FromPyObjectNew(self);
stack_pointer[-1 - oparg] = maybe_self;
PyObject *method = ((PyMethodObject *)callable_o)->im_func;
func = PyStackRef_FromPyObjectNew(method);
stack_pointer[-2 - oparg] = func;
/* Make sure that callable and all args are in memory */
args[-2] = func;
args[-1] = maybe_self;
@ -1063,12 +1065,12 @@
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
STAT_INC(CALL, hit);
self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
stack_pointer[-1 - oparg] = self;
func = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
stack_pointer[-2 - oparg] = func;
PyStackRef_CLOSE(callable);
}
// flush
stack_pointer[-2 - oparg] = func;
stack_pointer[-1 - oparg] = self;
// _CHECK_FUNCTION_VERSION
callable = stack_pointer[-2 - oparg];
{
@ -1172,13 +1174,13 @@
assert(PyStackRef_IsNull(null));
assert(Py_TYPE(callable_o) == &PyMethod_Type);
self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
stack_pointer[-1 - oparg] = self;
method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
stack_pointer[-2 - oparg] = method;
assert(PyStackRef_FunctionCheck(method));
PyStackRef_CLOSE(callable);
}
// flush
stack_pointer[-2 - oparg] = method;
stack_pointer[-1 - oparg] = self;
// _PY_FRAME_GENERAL
args = &stack_pointer[-oparg];
self_or_null = stack_pointer[-1 - oparg];
@ -2534,6 +2536,7 @@
int matches = PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration);
if (matches) {
value = PyStackRef_FromPyObjectNew(((PyStopIterationObject *)exc_value)->value);
stack_pointer[-2] = value;
PyStackRef_CLOSE(sub_iter_st);
PyStackRef_CLOSE(last_sent_val_st);
PyStackRef_CLOSE(exc_value_st);
@ -2545,7 +2548,6 @@
goto exception_unwind;
}
stack_pointer[-3] = none;
stack_pointer[-2] = value;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@ -3330,8 +3332,8 @@
assert(seq);
assert(it->it_index < PyList_GET_SIZE(seq));
next = PyStackRef_FromPyObjectNew(PyList_GET_ITEM(seq, it->it_index++));
stack_pointer[0] = next;
}
stack_pointer[0] = next;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@ -3423,8 +3425,8 @@
assert(seq);
assert(it->it_index < PyTuple_GET_SIZE(seq));
next = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq, it->it_index++));
stack_pointer[0] = next;
}
stack_pointer[0] = next;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
@ -3634,8 +3636,10 @@
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
PyObject *self = ((PyMethodObject *)callable_o)->im_self;
maybe_self = PyStackRef_FromPyObjectNew(self);
stack_pointer[-1 - oparg] = maybe_self;
PyObject *method = ((PyMethodObject *)callable_o)->im_func;
func = PyStackRef_FromPyObjectNew(method);
stack_pointer[-2 - oparg] = func;
/* Make sure that callable and all args are in memory */
args[-2] = func;
args[-1] = maybe_self;
@ -4071,6 +4075,7 @@
// _LOAD_CONST
{
value = PyStackRef_FromPyObjectNew(GETITEM(FRAME_CO_CONSTS, oparg));
stack_pointer[0] = value;
}
// _RETURN_VALUE_EVENT
val = value;
@ -4453,10 +4458,10 @@
STAT_INC(LOAD_ATTR, hit);
assert(descr != NULL);
attr = PyStackRef_FromPyObjectNew(descr);
stack_pointer[-1] = attr;
null = PyStackRef_NULL;
PyStackRef_CLOSE(owner);
}
stack_pointer[-1] = attr;
if (oparg & 1) stack_pointer[0] = null;
stack_pointer += (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
@ -4577,9 +4582,9 @@
assert(descr != NULL);
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
attr = PyStackRef_FromPyObjectNew(descr);
stack_pointer[-1] = attr;
self = owner;
}
stack_pointer[-1] = attr;
stack_pointer[0] = self;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
@ -4613,9 +4618,9 @@
assert(descr != NULL);
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
attr = PyStackRef_FromPyObjectNew(descr);
stack_pointer[-1] = attr;
self = owner;
}
stack_pointer[-1] = attr;
stack_pointer[0] = self;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
@ -4661,9 +4666,9 @@
assert(descr != NULL);
assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
attr = PyStackRef_FromPyObjectNew(descr);
stack_pointer[-1] = attr;
self = owner;
}
stack_pointer[-1] = attr;
stack_pointer[0] = self;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
@ -4739,8 +4744,8 @@
assert(descr != NULL);
PyStackRef_CLOSE(owner);
attr = PyStackRef_FromPyObjectNew(descr);
stack_pointer[-1] = attr;
}
stack_pointer[-1] = attr;
DISPATCH();
}
@ -4781,8 +4786,8 @@
assert(descr != NULL);
PyStackRef_CLOSE(owner);
attr = PyStackRef_FromPyObjectNew(descr);
stack_pointer[-1] = attr;
}
stack_pointer[-1] = attr;
DISPATCH();
}
@ -4878,10 +4883,10 @@
STAT_INC(LOAD_ATTR, hit);
null = PyStackRef_NULL;
attr = PyStackRef_FromPyObjectNew(attr_o);
stack_pointer[-1] = attr;
PyStackRef_CLOSE(owner);
}
/* Skip 5 cache entries */
stack_pointer[-1] = attr;
if (oparg & 1) stack_pointer[0] = null;
stack_pointer += (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
@ -5290,7 +5295,7 @@
"no locals found");
if (true) goto error;
}
locals = PyStackRef_FromPyObjectNew(l);;
locals = PyStackRef_FromPyObjectNew(l);
stack_pointer[0] = locals;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
@ -5958,6 +5963,7 @@
// _LOAD_CONST
{
value = PyStackRef_FromPyObjectNew(GETITEM(FRAME_CO_CONSTS, oparg));
stack_pointer[0] = value;
}
// _RETURN_VALUE
retval = value;
@ -7018,10 +7024,10 @@
DEOPT_IF(PyTuple_GET_SIZE(seq_o) != 2, UNPACK_SEQUENCE);
STAT_INC(UNPACK_SEQUENCE, hit);
val0 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 0));
val1 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 1));
PyStackRef_CLOSE(seq);
stack_pointer[-1] = val1;
stack_pointer[0] = val0;
val1 = PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq_o, 1));
stack_pointer[-1] = val1;
PyStackRef_CLOSE(seq);
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();