typedef struct _PyInterpreterFrame {
_PyStackRef f_executable; /* Deferred or strong reference (code object or None) */
struct _PyInterpreterFrame *previous;
- PyObject *f_funcobj; /* Strong reference. Only valid if not on C stack */
+ _PyStackRef f_funcobj; /* Deferred or strong reference. Only valid if not on C stack */
PyObject *f_globals; /* Borrowed reference. Only valid if not on C stack */
PyObject *f_builtins; /* Borrowed reference. Only valid if not on C stack */
PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */
return (PyCodeObject *)executable;
}
+static inline PyFunctionObject *_PyFrame_GetFunction(_PyInterpreterFrame *f) {
+ PyObject *func = PyStackRef_AsPyObjectBorrow(f->f_funcobj);
+ assert(PyFunction_Check(func));
+ return (PyFunctionObject *)func;
+}
+
static inline _PyStackRef *_PyFrame_Stackbase(_PyInterpreterFrame *f) {
return (f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus);
}
*/
static inline void
_PyFrame_Initialize(
- _PyInterpreterFrame *frame, PyFunctionObject *func,
+ _PyInterpreterFrame *frame, _PyStackRef func,
PyObject *locals, PyCodeObject *code, int null_locals_from, _PyInterpreterFrame *previous)
{
frame->previous = previous;
- frame->f_funcobj = (PyObject *)func;
+ frame->f_funcobj = func;
frame->f_executable = PyStackRef_FromPyObjectNew(code);
- frame->f_builtins = func->func_builtins;
- frame->f_globals = func->func_globals;
+ PyFunctionObject *func_obj = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(func);
+ frame->f_builtins = func_obj->func_builtins;
+ frame->f_globals = func_obj->func_globals;
frame->f_locals = locals;
frame->stackpointer = frame->localsplus + code->co_nlocalsplus;
frame->frame_obj = NULL;
* Must be guarded by _PyThreadState_HasStackSpace()
* Consumes reference to func. */
static inline _PyInterpreterFrame *
-_PyFrame_PushUnchecked(PyThreadState *tstate, PyFunctionObject *func, int null_locals_from, _PyInterpreterFrame * previous)
+_PyFrame_PushUnchecked(PyThreadState *tstate, _PyStackRef func, int null_locals_from, _PyInterpreterFrame * previous)
{
CALL_STAT_INC(frames_pushed);
- PyCodeObject *code = (PyCodeObject *)func->func_code;
+ PyFunctionObject *func_obj = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(func);
+ PyCodeObject *code = (PyCodeObject *)func_obj->func_code;
_PyInterpreterFrame *new_frame = (_PyInterpreterFrame *)tstate->datastack_top;
tstate->datastack_top += code->co_framesize;
assert(tstate->datastack_top < tstate->datastack_limit);
tstate->datastack_top += code->co_framesize;
assert(tstate->datastack_top < tstate->datastack_limit);
frame->previous = previous;
- frame->f_funcobj = Py_None;
+ frame->f_funcobj = PyStackRef_None;
frame->f_executable = PyStackRef_FromPyObjectNew(code);
#ifdef Py_DEBUG
frame->f_builtins = NULL;
}
PyAPI_FUNC(_PyInterpreterFrame *)
-_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
+_PyEvalFramePushAndInit(PyThreadState *tstate, _PyStackRef func,
PyObject *locals, _PyStackRef const* args,
size_t argcount, PyObject *kwnames,
_PyInterpreterFrame *previous);
extern int _PyGC_VisitFrameStack(struct _PyInterpreterFrame *frame, visitproc visit, void *arg);
extern int _PyGC_VisitStackRef(union _PyStackRef *ref, visitproc visit, void *arg);
+// Like Py_VISIT but for _PyStackRef fields
+#define _Py_VISIT_STACKREF(ref) \
+ do { \
+ if (!PyStackRef_IsNull(ref)) { \
+ int vret = _PyGC_VisitStackRef(&(ref), visit, arg); \
+ if (vret) \
+ return vret; \
+ } \
+ } while (0)
+
+
#ifdef __cplusplus
}
#endif
static PyObject *
record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
{
- if (PyFunction_Check(f->f_funcobj)) {
+ if (PyStackRef_FunctionCheck(f->f_funcobj)) {
+ PyFunctionObject *func = _PyFrame_GetFunction(f);
PyObject *module = _get_current_module();
assert(module != NULL);
module_state *state = get_module_state(module);
Py_DECREF(module);
- int res = PyList_Append(state->record_list,
- ((PyFunctionObject *)f->f_funcobj)->func_name);
+ int res = PyList_Append(state->record_list, func->func_name);
if (res < 0) {
return NULL;
}
/* Kill all local variables including specials, if we own them */
if (f->f_frame == frame && frame->owner == FRAME_OWNED_BY_FRAME_OBJECT) {
PyStackRef_CLEAR(frame->f_executable);
- Py_CLEAR(frame->f_funcobj);
+ PyStackRef_CLEAR(frame->f_funcobj);
Py_CLEAR(frame->f_locals);
_PyStackRef *locals = _PyFrame_GetLocalsArray(frame);
_PyStackRef *sp = frame->stackpointer;
init_frame(_PyInterpreterFrame *frame, PyFunctionObject *func, PyObject *locals)
{
PyCodeObject *code = (PyCodeObject *)func->func_code;
- _PyFrame_Initialize(frame, (PyFunctionObject*)Py_NewRef(func),
+ _PyFrame_Initialize(frame, PyStackRef_FromPyObjectNew(func),
Py_XNewRef(locals), code, 0, NULL);
}
PyCodeObject *co = _PyFrame_GetCode(frame);
int lasti = _PyInterpreterFrame_LASTI(frame);
if (!(lasti < 0 && _PyCode_CODE(co)->op.code == COPY_FREE_VARS
- && PyFunction_Check(frame->f_funcobj)))
+ && PyStackRef_FunctionCheck(frame->f_funcobj)))
{
/* Free vars are initialized */
return;
}
/* Free vars have not been initialized -- Do that */
- PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
+ PyFunctionObject *func = _PyFrame_GetFunction(frame);
+ PyObject *closure = func->func_closure;
int offset = PyUnstable_Code_GetFirstFree(co);
for (int i = 0; i < co->co_nfreevars; ++i) {
PyObject *o = PyTuple_GET_ITEM(closure, i);
else {
// We still need to visit the code object when the frame is cleared to
// ensure that it's kept alive if the reference is deferred.
- int err = _PyGC_VisitStackRef(&gen->gi_iframe.f_executable, visit, arg);
- if (err) {
- return err;
- }
+ _Py_VISIT_STACKREF(gen->gi_iframe.f_executable);
}
/* No need to visit cr_origin, because it's just tuples/str/int, so can't
participate in a reference cycle. */
if (f == NULL) {
Py_RETURN_NONE;
}
- if (f == NULL || f->f_funcobj == NULL) {
+ if (f == NULL || PyStackRef_IsNull(f->f_funcobj)) {
Py_RETURN_NONE;
}
- PyObject *r = PyFunction_GetModule(f->f_funcobj);
+ PyObject *r = PyFunction_GetModule(PyStackRef_AsPyObjectBorrow(f->f_funcobj));
if (!r) {
PyErr_Clear();
Py_RETURN_NONE;
assert(code->co_argcount == 2);
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize));
STAT_INC(BINARY_SUBSCR, hit);
- Py_INCREF(getitem);
}
op(_BINARY_SUBSCR_INIT_CALL, (container, sub -- new_frame: _PyInterpreterFrame* )) {
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
PyObject *getitem = ht->_spec_cache.getitem;
- new_frame = _PyFrame_PushUnchecked(tstate, (PyFunctionObject *)getitem, 2, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(getitem), 2, frame);
SYNC_SP();
new_frame->localsplus[0] = container;
new_frame->localsplus[1] = sub;
inst(COPY_FREE_VARS, (--)) {
/* Copy closure variables to free variables */
PyCodeObject *co = _PyFrame_GetCode(frame);
- assert(PyFunction_Check(frame->f_funcobj));
- PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
+ assert(PyStackRef_FunctionCheck(frame->f_funcobj));
+ PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
+ PyObject *closure = func->func_closure;
assert(oparg == co->co_nfreevars);
int offset = co->co_nlocalsplus - oparg;
for (int i = 0; i < oparg; ++i) {
DEOPT_IF(code->co_argcount != 1);
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize));
STAT_INC(LOAD_ATTR, hit);
- Py_INCREF(fget);
- new_frame = _PyFrame_PushUnchecked(tstate, f, 1, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame);
new_frame->localsplus[0] = owner;
}
STAT_INC(LOAD_ATTR, hit);
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
- Py_INCREF(f);
- _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2, frame);
+ _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(
+ tstate, PyStackRef_FromPyObjectNew(f), 2, frame);
// Manipulate stack directly because we exit with DISPATCH_INLINED().
STACK_SHRINK(1);
new_frame->localsplus[0] = owner;
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, total_args, NULL, frame
);
// Manipulate stack directly since we leave using DISPATCH_INLINED().
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, total_args, NULL, frame
);
// The frame has stolen all the arguments from the stack,
}
replicate(5) pure op(_INIT_CALL_PY_EXACT_ARGS, (callable, self_or_null[1], args[oparg] -- new_frame: _PyInterpreterFrame*)) {
- PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null[0]);
STAT_INC(CALL, hit);
- PyFunctionObject *func = (PyFunctionObject *)callable_o;
- new_frame = _PyFrame_PushUnchecked(tstate, func, oparg + has_self, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
_PyStackRef *first_non_self_local = new_frame->localsplus + has_self;
new_frame->localsplus[0] = self_or_null[0];
for (int i = 0; i < oparg; i++) {
assert(_PyCode_CODE(_PyFrame_GetCode(shim))[0].op.code == EXIT_INIT_CHECK);
/* Push self onto stack of shim */
shim->localsplus[0] = PyStackRef_DUP(self);
- PyFunctionObject *init_func = (PyFunctionObject *)PyStackRef_AsPyObjectSteal(init);
args[-1] = self;
init_frame = _PyEvalFramePushAndInit(
- tstate, init_func, NULL, args-1, oparg+1, NULL, shim);
+ tstate, init, NULL, args-1, oparg+1, NULL, shim);
SYNC_SP();
if (init_frame == NULL) {
_PyEval_FrameClearAndPop(tstate, shim);
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, positional_args, kwnames_o, frame
);
PyStackRef_CLOSE(kwnames);
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, positional_args, kwnames_o, frame
);
PyStackRef_CLOSE(kwnames);
int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func));
- _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(tstate,
- (PyFunctionObject *)PyStackRef_AsPyObjectSteal(func_st), locals,
- nargs, callargs, kwargs, frame);
+ _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(
+ tstate, func_st, locals,
+ nargs, callargs, kwargs, frame);
// Need to manually shrink the stack since we exit with DISPATCH_INLINED.
STACK_SHRINK(oparg + 3);
if (new_frame == NULL) {
}
inst(RETURN_GENERATOR, (-- res)) {
- assert(PyFunction_Check(frame->f_funcobj));
- PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;
+ assert(PyStackRef_FunctionCheck(frame->f_funcobj));
+ PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);
if (gen == NULL) {
ERROR_NO_POP();
}
tier2 op(_CHECK_FUNCTION, (func_version/2 -- )) {
- assert(PyFunction_Check(frame->f_funcobj));
- DEOPT_IF(((PyFunctionObject *)frame->f_funcobj)->func_version != func_version);
+ assert(PyStackRef_FunctionCheck(frame->f_funcobj));
+ PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
+ DEOPT_IF(func->func_version != func_version);
}
/* Internal -- for testing executors */
static void
lltrace_resume_frame(_PyInterpreterFrame *frame)
{
- PyObject *fobj = frame->f_funcobj;
+ PyObject *fobj = PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
if (!PyStackRef_CodeCheck(frame->f_executable) ||
fobj == NULL ||
!PyFunction_Check(fobj)
static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg);
static int get_exception_handler(PyCodeObject *, int, int*, int*, int*);
static _PyInterpreterFrame *
-_PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func,
+_PyEvalFramePushAndInit_Ex(PyThreadState *tstate, _PyStackRef func,
PyObject *locals, Py_ssize_t nargs, PyObject *callargs, PyObject *kwargs, _PyInterpreterFrame *previous);
#ifdef HAVE_ERRNO_H
#ifdef Py_DEBUG
/* Set these to invalid but identifiable values for debugging. */
- entry_frame.f_funcobj = (PyObject*)0xaaa0;
+ entry_frame.f_funcobj = (_PyStackRef){.bits = 0xaaa0};
entry_frame.f_locals = (PyObject*)0xaaa1;
entry_frame.frame_obj = (PyFrameObject*)0xaaa2;
entry_frame.f_globals = (PyObject*)0xaaa3;
/* Consumes references to func, locals and all the args */
_PyInterpreterFrame *
-_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
+_PyEvalFramePushAndInit(PyThreadState *tstate, _PyStackRef func,
PyObject *locals, _PyStackRef const* args,
size_t argcount, PyObject *kwnames, _PyInterpreterFrame *previous)
{
- PyCodeObject * code = (PyCodeObject *)func->func_code;
+ PyFunctionObject *func_obj = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(func);
+ PyCodeObject * code = (PyCodeObject *)func_obj->func_code;
CALL_STAT_INC(frames_pushed);
_PyInterpreterFrame *frame = _PyThreadState_PushFrame(tstate, code->co_framesize);
if (frame == NULL) {
goto fail;
}
_PyFrame_Initialize(frame, func, locals, code, 0, previous);
- if (initialize_locals(tstate, func, frame->localsplus, args, argcount, kwnames)) {
+ if (initialize_locals(tstate, func_obj, frame->localsplus, args, argcount, kwnames)) {
assert(frame->owner == FRAME_OWNED_BY_THREAD);
clear_thread_frame(tstate, frame);
return NULL;
return frame;
fail:
/* Consume the references */
- Py_DECREF(func);
+ PyStackRef_CLOSE(func);
Py_XDECREF(locals);
for (size_t i = 0; i < argcount; i++) {
PyStackRef_CLOSE(args[i]);
}
static _PyInterpreterFrame *
-_PyEvalFramePushAndInit_UnTagged(PyThreadState *tstate, PyFunctionObject *func,
+_PyEvalFramePushAndInit_UnTagged(PyThreadState *tstate, _PyStackRef func,
PyObject *locals, PyObject *const* args,
size_t argcount, PyObject *kwnames, _PyInterpreterFrame *previous)
{
Steals references to func, callargs and kwargs.
*/
static _PyInterpreterFrame *
-_PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func,
+_PyEvalFramePushAndInit_Ex(PyThreadState *tstate, _PyStackRef func,
PyObject *locals, Py_ssize_t nargs, PyObject *callargs, PyObject *kwargs, _PyInterpreterFrame *previous)
{
bool has_dict = (kwargs != NULL && PyDict_GET_SIZE(kwargs) > 0);
if (has_dict) {
newargs = _PyStack_UnpackDict(tstate, _PyTuple_ITEMS(callargs), nargs, kwargs, &kwnames);
if (newargs == NULL) {
- Py_DECREF(func);
+ PyStackRef_CLOSE(func);
goto error;
}
}
}
}
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_UnTagged(
- tstate, (PyFunctionObject *)func, locals,
+ tstate, func, locals,
newargs, nargs, kwnames, previous
);
if (has_dict) {
{
/* _PyEvalFramePushAndInit consumes the references
* to func, locals and all its arguments */
- Py_INCREF(func);
Py_XINCREF(locals);
for (size_t i = 0; i < argcount; i++) {
Py_INCREF(args[i]);
}
}
_PyInterpreterFrame *frame = _PyEvalFramePushAndInit_UnTagged(
- tstate, func, locals, args, argcount, kwnames, NULL);
+ tstate, PyStackRef_FromPyObjectNew(func), locals,
+ args, argcount, kwnames, NULL);
if (frame == NULL) {
return NULL;
}
JUMP_TO_JUMP_TARGET();
}
STAT_INC(BINARY_SUBSCR, hit);
- Py_INCREF(getitem);
break;
}
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
PyObject *getitem = ht->_spec_cache.getitem;
- new_frame = _PyFrame_PushUnchecked(tstate, (PyFunctionObject *)getitem, 2, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(getitem), 2, frame);
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
new_frame->localsplus[0] = container;
oparg = CURRENT_OPARG();
/* Copy closure variables to free variables */
PyCodeObject *co = _PyFrame_GetCode(frame);
- assert(PyFunction_Check(frame->f_funcobj));
- PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
+ assert(PyStackRef_FunctionCheck(frame->f_funcobj));
+ PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
+ PyObject *closure = func->func_closure;
assert(oparg == co->co_nfreevars);
int offset = co->co_nlocalsplus - oparg;
for (int i = 0; i < oparg; ++i) {
JUMP_TO_JUMP_TARGET();
}
STAT_INC(LOAD_ATTR, hit);
- Py_INCREF(fget);
- new_frame = _PyFrame_PushUnchecked(tstate, f, 1, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame);
new_frame->localsplus[0] = owner;
stack_pointer[-1].bits = (uintptr_t)new_frame;
break;
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, total_args, NULL, frame
);
// The frame has stolen all the arguments from the stack,
args = &stack_pointer[-oparg];
self_or_null = &stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null[0]);
STAT_INC(CALL, hit);
- PyFunctionObject *func = (PyFunctionObject *)callable_o;
- new_frame = _PyFrame_PushUnchecked(tstate, func, oparg + has_self, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
_PyStackRef *first_non_self_local = new_frame->localsplus + has_self;
new_frame->localsplus[0] = self_or_null[0];
for (int i = 0; i < oparg; i++) {
args = &stack_pointer[-oparg];
self_or_null = &stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null[0]);
STAT_INC(CALL, hit);
- PyFunctionObject *func = (PyFunctionObject *)callable_o;
- new_frame = _PyFrame_PushUnchecked(tstate, func, oparg + has_self, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
_PyStackRef *first_non_self_local = new_frame->localsplus + has_self;
new_frame->localsplus[0] = self_or_null[0];
for (int i = 0; i < oparg; i++) {
args = &stack_pointer[-oparg];
self_or_null = &stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null[0]);
STAT_INC(CALL, hit);
- PyFunctionObject *func = (PyFunctionObject *)callable_o;
- new_frame = _PyFrame_PushUnchecked(tstate, func, oparg + has_self, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
_PyStackRef *first_non_self_local = new_frame->localsplus + has_self;
new_frame->localsplus[0] = self_or_null[0];
for (int i = 0; i < oparg; i++) {
args = &stack_pointer[-oparg];
self_or_null = &stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null[0]);
STAT_INC(CALL, hit);
- PyFunctionObject *func = (PyFunctionObject *)callable_o;
- new_frame = _PyFrame_PushUnchecked(tstate, func, oparg + has_self, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
_PyStackRef *first_non_self_local = new_frame->localsplus + has_self;
new_frame->localsplus[0] = self_or_null[0];
for (int i = 0; i < oparg; i++) {
args = &stack_pointer[-oparg];
self_or_null = &stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null[0]);
STAT_INC(CALL, hit);
- PyFunctionObject *func = (PyFunctionObject *)callable_o;
- new_frame = _PyFrame_PushUnchecked(tstate, func, oparg + has_self, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
_PyStackRef *first_non_self_local = new_frame->localsplus + has_self;
new_frame->localsplus[0] = self_or_null[0];
for (int i = 0; i < oparg; i++) {
args = &stack_pointer[-oparg];
self_or_null = &stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null[0]);
STAT_INC(CALL, hit);
- PyFunctionObject *func = (PyFunctionObject *)callable_o;
- new_frame = _PyFrame_PushUnchecked(tstate, func, oparg + has_self, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
_PyStackRef *first_non_self_local = new_frame->localsplus + has_self;
new_frame->localsplus[0] = self_or_null[0];
for (int i = 0; i < oparg; i++) {
assert(_PyCode_CODE(_PyFrame_GetCode(shim))[0].op.code == EXIT_INIT_CHECK);
/* Push self onto stack of shim */
shim->localsplus[0] = PyStackRef_DUP(self);
- PyFunctionObject *init_func = (PyFunctionObject *)PyStackRef_AsPyObjectSteal(init);
args[-1] = self;
init_frame = _PyEvalFramePushAndInit(
- tstate, init_func, NULL, args-1, oparg+1, NULL, shim);
+ tstate, init, NULL, args-1, oparg+1, NULL, shim);
stack_pointer += -2 - oparg;
assert(WITHIN_STACK_BOUNDS());
if (init_frame == NULL) {
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, positional_args, kwnames_o, frame
);
PyStackRef_CLOSE(kwnames);
case _RETURN_GENERATOR: {
_PyStackRef res;
- assert(PyFunction_Check(frame->f_funcobj));
- PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;
+ assert(PyStackRef_FunctionCheck(frame->f_funcobj));
+ PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);
if (gen == NULL) {
JUMP_TO_ERROR();
case _CHECK_FUNCTION: {
uint32_t func_version = (uint32_t)CURRENT_OPERAND();
- assert(PyFunction_Check(frame->f_funcobj));
- if (((PyFunctionObject *)frame->f_funcobj)->func_version != func_version) {
+ assert(PyStackRef_FunctionCheck(frame->f_funcobj));
+ PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
+ if (func->func_version != func_version) {
UOP_STAT_INC(uopcode, miss);
JUMP_TO_JUMP_TARGET();
}
{
Py_VISIT(frame->frame_obj);
Py_VISIT(frame->f_locals);
- Py_VISIT(frame->f_funcobj);
- int err = _PyGC_VisitStackRef(&frame->f_executable, visit, arg);
- if (err) {
- return err;
- }
+ _Py_VISIT_STACKREF(frame->f_funcobj);
+ _Py_VISIT_STACKREF(frame->f_executable);
return _PyGC_VisitFrameStack(frame, visit, arg);
}
Py_DECREF(f);
}
_PyFrame_ClearLocals(frame);
- Py_DECREF(frame->f_funcobj);
+ PyStackRef_CLEAR(frame->f_funcobj);
}
/* Unstable API functions */
}
}
+ frame->f_funcobj = PyStackRef_AsStrongReference(frame->f_funcobj);
for (_PyStackRef *ref = frame->localsplus; ref < frame->stackpointer; ref++) {
if (!PyStackRef_IsNull(*ref) && PyStackRef_IsDeferred(*ref)) {
*ref = PyStackRef_AsStrongReference(*ref);
_PyStackRef *ref = _PyFrame_GetLocalsArray(frame);
/* locals and stack */
for (; ref < frame->stackpointer; ref++) {
- if (_PyGC_VisitStackRef(ref, visit, arg) < 0) {
- return -1;
- }
+ _Py_VISIT_STACKREF(*ref);
}
return 0;
}
assert(code->co_argcount == 2);
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), BINARY_SUBSCR);
STAT_INC(BINARY_SUBSCR, hit);
- Py_INCREF(getitem);
}
// _BINARY_SUBSCR_INIT_CALL
sub = stack_pointer[-1];
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
PyObject *getitem = ht->_spec_cache.getitem;
- new_frame = _PyFrame_PushUnchecked(tstate, (PyFunctionObject *)getitem, 2, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(getitem), 2, frame);
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
new_frame->localsplus[0] = container;
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, total_args, NULL, frame
);
// Manipulate stack directly since we leave using DISPATCH_INLINED().
assert(_PyCode_CODE(_PyFrame_GetCode(shim))[0].op.code == EXIT_INIT_CHECK);
/* Push self onto stack of shim */
shim->localsplus[0] = PyStackRef_DUP(self);
- PyFunctionObject *init_func = (PyFunctionObject *)PyStackRef_AsPyObjectSteal(init);
args[-1] = self;
init_frame = _PyEvalFramePushAndInit(
- tstate, init_func, NULL, args-1, oparg+1, NULL, shim);
+ tstate, init, NULL, args-1, oparg+1, NULL, shim);
stack_pointer += -2 - oparg;
assert(WITHIN_STACK_BOUNDS());
if (init_frame == NULL) {
// _INIT_CALL_PY_EXACT_ARGS
args = &stack_pointer[-oparg];
{
- PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null[0]);
STAT_INC(CALL, hit);
- PyFunctionObject *func = (PyFunctionObject *)callable_o;
- new_frame = _PyFrame_PushUnchecked(tstate, func, oparg + has_self, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
_PyStackRef *first_non_self_local = new_frame->localsplus + has_self;
new_frame->localsplus[0] = self_or_null[0];
for (int i = 0; i < oparg; i++) {
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, total_args, NULL, frame
);
// The frame has stolen all the arguments from the stack,
Py_ssize_t nargs = PyTuple_GET_SIZE(callargs);
int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func));
- _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(tstate,
- (PyFunctionObject *)PyStackRef_AsPyObjectSteal(func_st), locals,
+ _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(
+ tstate, func_st, locals,
nargs, callargs, kwargs, frame);
// Need to manually shrink the stack since we exit with DISPATCH_INLINED.
STACK_SHRINK(oparg + 3);
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, positional_args, kwnames_o, frame
);
PyStackRef_CLOSE(kwnames);
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, positional_args, kwnames_o, frame
);
PyStackRef_CLOSE(kwnames);
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, positional_args, kwnames_o, frame
);
PyStackRef_CLOSE(kwnames);
// _INIT_CALL_PY_EXACT_ARGS
args = &stack_pointer[-oparg];
{
- PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null[0]);
STAT_INC(CALL, hit);
- PyFunctionObject *func = (PyFunctionObject *)callable_o;
- new_frame = _PyFrame_PushUnchecked(tstate, func, oparg + has_self, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
_PyStackRef *first_non_self_local = new_frame->localsplus + has_self;
new_frame->localsplus[0] = self_or_null[0];
for (int i = 0; i < oparg; i++) {
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, total_args, NULL, frame
);
// The frame has stolen all the arguments from the stack,
INSTRUCTION_STATS(COPY_FREE_VARS);
/* Copy closure variables to free variables */
PyCodeObject *co = _PyFrame_GetCode(frame);
- assert(PyFunction_Check(frame->f_funcobj));
- PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
+ assert(PyStackRef_FunctionCheck(frame->f_funcobj));
+ PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
+ PyObject *closure = func->func_closure;
assert(oparg == co->co_nfreevars);
int offset = co->co_nlocalsplus - oparg;
for (int i = 0; i < oparg; ++i) {
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, total_args, NULL, frame
);
// Manipulate stack directly since we leave using DISPATCH_INLINED().
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);
STAT_INC(LOAD_ATTR, hit);
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
- Py_INCREF(f);
- _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2, frame);
+ _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(
+ tstate, PyStackRef_FromPyObjectNew(f), 2, frame);
// Manipulate stack directly because we exit with DISPATCH_INLINED().
STACK_SHRINK(1);
new_frame->localsplus[0] = owner;
DEOPT_IF(code->co_argcount != 1, LOAD_ATTR);
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);
STAT_INC(LOAD_ATTR, hit);
- Py_INCREF(fget);
- new_frame = _PyFrame_PushUnchecked(tstate, f, 1, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame);
new_frame->localsplus[0] = owner;
}
// _SAVE_RETURN_OFFSET
next_instr += 1;
INSTRUCTION_STATS(RETURN_GENERATOR);
_PyStackRef res;
- assert(PyFunction_Check(frame->f_funcobj));
- PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;
+ assert(PyStackRef_FunctionCheck(frame->f_funcobj));
+ PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);
if (gen == NULL) {
goto error;
Py_ssize_t nargs = PyTuple_GET_SIZE(callargs);
int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func));
- _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(tstate,
- (PyFunctionObject *)PyStackRef_AsPyObjectSteal(func_st), locals,
+ _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(
+ tstate, func_st, locals,
nargs, callargs, kwargs, frame);
// Need to manually shrink the stack since we exit with DISPATCH_INLINED.
STACK_SHRINK(oparg + 3);
{
bool first = true;
PyCodeObject *code = _PyFrame_GetCode(frame);
- PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;
+ PyFunctionObject *func = _PyFrame_GetFunction(frame);
assert(PyFunction_Check(func));
PyCodeObject *initial_code = code;
_Py_BloomFilter_Add(dependencies, initial_code);
return 1;
}
PyObject *globals = frame->f_globals;
- PyFunctionObject *function = (PyFunctionObject *)frame->f_funcobj;
+ PyFunctionObject *function = _PyFrame_GetFunction(frame);
assert(PyFunction_Check(function));
assert(function->func_builtins == builtins);
assert(function->func_globals == globals);
while (f && (_PyFrame_IsIncomplete(f) || depth-- > 0)) {
f = f->previous;
}
- if (f == NULL || f->f_funcobj == NULL) {
+ if (f == NULL || PyStackRef_IsNull(f->f_funcobj)) {
Py_RETURN_NONE;
}
- PyObject *r = PyFunction_GetModule(f->f_funcobj);
+ PyObject *func = PyStackRef_AsPyObjectBorrow(f->f_funcobj);
+ PyObject *r = PyFunction_GetModule(func);
if (!r) {
PyErr_Clear();
r = Py_None;
offset += 1
return []
+ def in_frame_push(idx: int) -> bool:
+ for tkn in reversed(node.block.tokens[: idx - 1]):
+ if tkn.kind == "SEMI" or tkn.kind == "LBRACE" or tkn.kind == "RBRACE":
+ return False
+ if tkn.kind == "IDENTIFIER" and tkn.text == "_PyFrame_PushUnchecked":
+ return True
+ return False
+
refs: dict[lexer.Token, str | None] = {}
for idx, tkn in enumerate(node.block.tokens):
if tkn.kind != "IDENTIFIER" or tkn.text != "PyStackRef_FromPyObjectNew":
continue
if idx == 0 or node.block.tokens[idx - 1].kind != "EQUALS":
+ if in_frame_push(idx):
+ # PyStackRef_FromPyObjectNew() is called in _PyFrame_PushUnchecked()
+ refs[tkn] = None
+ continue
raise analysis_error("Expected '=' before PyStackRef_FromPyObjectNew", tkn)
lhs = find_assignment_target(idx)
stack: Stack,
inst: Instruction | None,
) -> None:
- self.out.emit(tkn)
- emit_to(self.out, tkn_iter, "SEMI")
- self.out.emit(";\n")
-
target = uop.deferred_refs[tkn]
if target is None:
# An assignment we don't handle, such as to a pointer or array.
+ self.out.emit(tkn)
return
+ self.out.emit(tkn)
+ emit_to(self.out, tkn_iter, "SEMI")
+ self.out.emit(";\n")
+
# Flush the assignment to the stack. Note that we don't flush the
# stack pointer here, and instead are currently relying on initializing
# unused portions of the stack to NULL.