summaryrefslogtreecommitdiffstats
path: root/Objects/frameobject.c
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2022-03-25 12:57:50 (GMT)
committerGitHub <noreply@github.com>2022-03-25 12:57:50 (GMT)
commitd7163bb35d1ed46bde9affcd4eb267dfd0b703dd (patch)
tree50ced5b75c3e1579c4e23fd7c404ac33c53b7fc3 /Objects/frameobject.c
parentb68431fadb3150134ac6ccbf501cdfeaf4c75678 (diff)
downloadcpython-d7163bb35d1ed46bde9affcd4eb267dfd0b703dd.zip
cpython-d7163bb35d1ed46bde9affcd4eb267dfd0b703dd.tar.gz
cpython-d7163bb35d1ed46bde9affcd4eb267dfd0b703dd.tar.bz2
bpo-42197: Don't create `f_locals` dictionary unless we actually need it. (GH-32055)
* `PyFrame_FastToLocalsWithError` and `PyFrame_LocalsToFast` are no longer called during profile and tracing. (Contributed by Fabio Zadrozny) * Make accesses to a frame's `f_locals` safe from C code, not relying on calls to `PyFrame_FastToLocals` or `PyFrame_LocalsToFast`. * Document new `PyFrame_GetLocals` C-API function.
Diffstat (limited to 'Objects/frameobject.c')
-rw-r--r--Objects/frameobject.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 5c6a8bc..13dfbf6 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -840,6 +840,7 @@ _PyFrame_New_NoTrack(PyCodeObject *code)
f->f_trace = NULL;
f->f_trace_lines = 1;
f->f_trace_opcodes = 0;
+ f->f_fast_as_locals = 0;
f->f_lineno = 0;
return f;
}
@@ -1004,7 +1005,11 @@ PyFrame_FastToLocalsWithError(PyFrameObject *f)
PyErr_BadInternalCall();
return -1;
}
- return _PyFrame_FastToLocalsWithError(f->f_frame);
+ int err = _PyFrame_FastToLocalsWithError(f->f_frame);
+ if (err == 0) {
+ f->f_fast_as_locals = 1;
+ }
+ return err;
}
void
@@ -1028,8 +1033,9 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear)
PyObject *error_type, *error_value, *error_traceback;
PyCodeObject *co;
locals = frame->f_locals;
- if (locals == NULL)
+ if (locals == NULL) {
return;
+ }
fast = _PyFrame_GetLocalsArray(frame);
co = frame->f_code;
@@ -1088,13 +1094,12 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear)
void
PyFrame_LocalsToFast(PyFrameObject *f, int clear)
{
- if (f == NULL || _PyFrame_GetState(f) == FRAME_CLEARED) {
- return;
+ if (f && f->f_fast_as_locals && _PyFrame_GetState(f) != FRAME_CLEARED) {
+ _PyFrame_LocalsToFast(f->f_frame, clear);
+ f->f_fast_as_locals = 0;
}
- _PyFrame_LocalsToFast(f->f_frame, clear);
}
-
PyCodeObject *
PyFrame_GetCode(PyFrameObject *frame)
{
@@ -1119,6 +1124,12 @@ PyFrame_GetBack(PyFrameObject *frame)
}
PyObject*
+PyFrame_GetLocals(PyFrameObject *frame)
+{
+ return frame_getlocals(frame, NULL);
+}
+
+PyObject*
_PyEval_BuiltinsFromGlobals(PyThreadState *tstate, PyObject *globals)
{
PyObject *builtins = PyDict_GetItemWithError(globals, &_Py_ID(__builtins__));