Skip to content

Commit 593a348

Browse files
committed
Refactor interpreter frame code into its own file. Improve a few names.
1 parent 90ed5b6 commit 593a348

File tree

7 files changed

+146
-139
lines changed

7 files changed

+146
-139
lines changed

Include/internal/pycore_frame.h

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ static inline int _PyFrameHasCompleted(InterpreterFrame *f) {
4949

5050
#define FRAME_SPECIALS_SIZE ((sizeof(InterpreterFrame)-1)/sizeof(PyObject *))
5151

52-
void _PyFrame_TakeInterpreterFrame(PyFrameObject *f, InterpreterFrame *locals);
52+
InterpreterFrame *
53+
_PyInterpreterFrame_HeapAlloc(PyFrameConstructor *con, PyObject *locals);
5354

5455
static inline void
5556
_PyFrame_InitializeSpecials(
@@ -68,17 +69,6 @@ _PyFrame_InitializeSpecials(
6869
frame->f_state = FRAME_CREATED;
6970
}
7071

71-
static inline void
72-
_PyFrame_ClearSpecials(InterpreterFrame *frame)
73-
{
74-
frame->generator = NULL;
75-
Py_XDECREF(frame->frame_obj);
76-
Py_XDECREF(frame->f_locals);
77-
Py_DECREF(frame->f_globals);
78-
Py_DECREF(frame->f_builtins);
79-
Py_DECREF(frame->f_code);
80-
}
81-
8272
/* Gets the pointer to the locals array
8373
* that precedes this frame.
8474
*/
@@ -118,6 +108,9 @@ _PyFrame_GetFrameObject(InterpreterFrame *frame)
118108
int
119109
_PyFrame_Clear(InterpreterFrame * frame, int take);
120110

111+
int
112+
_PyFrame_Traverse(InterpreterFrame *frame, visitproc visit, void *arg);
113+
121114
int
122115
_PyFrame_FastToLocalsWithError(InterpreterFrame *frame);
123116

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ PYTHON_OBJS= \
350350
Python/context.o \
351351
Python/dynamic_annotations.o \
352352
Python/errors.o \
353+
Python/frame.o \
353354
Python/frozenmain.o \
354355
Python/future.o \
355356
Python/getargs.o \

Objects/frameobject.c

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -671,21 +671,7 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
671671
return 0;
672672
}
673673
assert(f->f_frame->frame_obj == NULL);
674-
/* locals */
675-
PyObject **locals = _PyFrame_GetLocalsArray(f->f_frame);
676-
for (int i = 0; i < f->f_frame->nlocalsplus; i++) {
677-
Py_VISIT(locals[i]);
678-
}
679-
/* stack */
680-
for (int i = 0; i < f->f_frame->stackdepth; i++) {
681-
Py_VISIT(f->f_frame->stack[i]);
682-
}
683-
684-
Py_VISIT(f->f_frame->f_globals);
685-
Py_VISIT(f->f_frame->f_builtins);
686-
Py_VISIT(f->f_frame->f_locals);
687-
Py_VISIT(f->f_frame->f_code);
688-
return 0;
674+
return _PyFrame_Traverse(f->f_frame, visit, arg);
689675
}
690676

691677
static int
@@ -856,35 +842,6 @@ frame_alloc(InterpreterFrame *frame, int owns)
856842
return f;
857843
}
858844

859-
void
860-
_PyFrame_TakeInterpreterFrame(PyFrameObject *f, InterpreterFrame *frame)
861-
{
862-
assert(f->f_own_locals_memory == 0);
863-
assert(frame->frame_obj == NULL);
864-
865-
f->f_own_locals_memory = 1;
866-
f->f_frame = frame;
867-
assert(f->f_back == NULL);
868-
if (frame->previous != NULL) {
869-
/* Link PyFrameObjects.f_back and remove link through InterpreterFrame.previous */
870-
PyFrameObject *back = _PyFrame_GetFrameObject(frame->previous);
871-
if (back == NULL) {
872-
/* Memory error here. */
873-
assert(_PyErr_GetTopmostException(_PyThreadState_GET())->exc_type == PyExc_MemoryError);
874-
/* Nothing we can do about it */
875-
PyErr_Clear();
876-
_PyErr_WriteUnraisableMsg("Out of memory lazily allocating frame->f_back", NULL);
877-
}
878-
else {
879-
f->f_back = (PyFrameObject *)Py_NewRef(back);
880-
}
881-
frame->previous = NULL;
882-
}
883-
if (!_PyObject_GC_IS_TRACKED((PyObject *)f)) {
884-
_PyObject_GC_TRACK((PyObject *)f);
885-
}
886-
}
887-
888845
PyFrameObject* _Py_HOT_FUNCTION
889846
_PyFrame_New_NoTrack(InterpreterFrame *frame, int owns)
890847
{

Objects/genobject.c

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,10 @@ gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
3838
InterpreterFrame *frame = gen->gi_xframe;
3939
if (frame != NULL) {
4040
assert(frame->frame_obj == NULL || frame->frame_obj->f_own_locals_memory == 0);
41-
Py_VISIT(frame->frame_obj);
42-
/* locals */
43-
PyObject **locals = _PyFrame_GetLocalsArray(frame);
44-
for (int i = 0; i < frame->nlocalsplus; i++) {
45-
Py_VISIT(locals[i]);
41+
int err = _PyFrame_Traverse(frame, visit, arg);
42+
if (err) {
43+
return err;
4644
}
47-
/* stack */
48-
for (int i = 0; i < frame->stackdepth; i++) {
49-
Py_VISIT(frame->stack[i]);
50-
}
51-
52-
Py_VISIT(frame->f_globals);
53-
Py_VISIT(frame->f_builtins);
54-
Py_VISIT(frame->f_locals);
55-
Py_VISIT(frame->f_code);
5645
}
5746
/* No need to visit cr_origin, because it's just tuples/str/int, so can't
5847
participate in a reference cycle. */

PCbuild/pythoncore.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@
455455
<ClCompile Include="..\Python\errors.c" />
456456
<ClCompile Include="..\Python\fileutils.c" />
457457
<ClCompile Include="..\Python\formatter_unicode.c" />
458+
<ClCompile Include="..\Python\frame.c" />
458459
<ClCompile Include="..\Python\frozen.c" />
459460
<ClCompile Include="..\Python\future.c" />
460461
<ClCompile Include="..\Python\getargs.c" />

Python/ceval.c

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -5113,75 +5113,6 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFrameConstructor *con,
51135113
return frame;
51145114
}
51155115

5116-
PyFrameObject *
5117-
_PyFrame_MakeAndSetFrameObject(InterpreterFrame *frame)
5118-
{
5119-
assert(frame->frame_obj == NULL);
5120-
PyObject *error_type, *error_value, *error_traceback;
5121-
PyErr_Fetch(&error_type, &error_value, &error_traceback);
5122-
PyFrameObject *f = _PyFrame_New_NoTrack(frame, 0);
5123-
if (f == NULL) {
5124-
Py_XDECREF(error_type);
5125-
Py_XDECREF(error_value);
5126-
Py_XDECREF(error_traceback);
5127-
}
5128-
else {
5129-
PyErr_Restore(error_type, error_value, error_traceback);
5130-
}
5131-
frame->frame_obj = f;
5132-
return f;
5133-
}
5134-
5135-
static InterpreterFrame *
5136-
copy_frame_to_heap(InterpreterFrame *frame)
5137-
{
5138-
5139-
Py_ssize_t size = ((char*)&frame->stack[frame->stackdepth]) - (char *)_PyFrame_GetLocalsArray(frame);
5140-
PyObject **copy = PyMem_Malloc(size);
5141-
if (copy == NULL) {
5142-
PyErr_NoMemory();
5143-
return NULL;
5144-
}
5145-
PyObject **locals = _PyFrame_GetLocalsArray(frame);
5146-
memcpy(copy, locals, size);
5147-
InterpreterFrame *res = (InterpreterFrame *)(copy + frame->nlocalsplus);
5148-
return res;
5149-
}
5150-
5151-
int
5152-
_PyFrame_Clear(InterpreterFrame * frame, int take)
5153-
{
5154-
PyObject **localsarray = ((PyObject **)frame)-frame->nlocalsplus;
5155-
if (frame->frame_obj) {
5156-
PyFrameObject *f = frame->frame_obj;
5157-
frame->frame_obj = NULL;
5158-
if (Py_REFCNT(f) > 1) {
5159-
if (!take) {
5160-
frame = copy_frame_to_heap(frame);
5161-
if (frame == NULL) {
5162-
return -1;
5163-
}
5164-
}
5165-
_PyFrame_TakeInterpreterFrame(f, frame);
5166-
Py_DECREF(f);
5167-
return 0;
5168-
}
5169-
Py_DECREF(f);
5170-
}
5171-
for (int i = 0; i < frame->nlocalsplus; i++) {
5172-
Py_XDECREF(localsarray[i]);
5173-
}
5174-
assert(frame->stackdepth >= 0);
5175-
for (int i = 0; i < frame->stackdepth; i++) {
5176-
Py_DECREF(frame->stack[i]);
5177-
}
5178-
_PyFrame_ClearSpecials(frame);
5179-
if (take) {
5180-
PyMem_Free(_PyFrame_GetLocalsArray(frame));
5181-
}
5182-
return 0;
5183-
}
5184-
51855116
static int
51865117
_PyEvalFrameClearAndPop(PyThreadState *tstate, InterpreterFrame * frame)
51875118
{

Python/frame.c

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
2+
#include "Python.h"
3+
#include "frameobject.h"
4+
#include "pycore_frame.h"
5+
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
6+
7+
int
8+
_PyFrame_Traverse(InterpreterFrame *frame, visitproc visit, void *arg)
9+
{
10+
Py_VISIT(frame->frame_obj);
11+
Py_VISIT(frame->f_globals);
12+
Py_VISIT(frame->f_builtins);
13+
Py_VISIT(frame->f_locals);
14+
Py_VISIT(frame->f_code);
15+
/* locals */
16+
PyObject **locals = _PyFrame_GetLocalsArray(frame);
17+
for (int i = 0; i < frame->nlocalsplus; i++) {
18+
Py_VISIT(locals[i]);
19+
}
20+
/* stack */
21+
for (int i = 0; i <frame->stackdepth; i++) {
22+
Py_VISIT(frame->stack[i]);
23+
}
24+
return 0;
25+
}
26+
27+
PyFrameObject *
28+
_PyFrame_MakeAndSetFrameObject(InterpreterFrame *frame)
29+
{
30+
assert(frame->frame_obj == NULL);
31+
PyObject *error_type, *error_value, *error_traceback;
32+
PyErr_Fetch(&error_type, &error_value, &error_traceback);
33+
PyFrameObject *f = _PyFrame_New_NoTrack(frame, 0);
34+
if (f == NULL) {
35+
Py_XDECREF(error_type);
36+
Py_XDECREF(error_value);
37+
Py_XDECREF(error_traceback);
38+
}
39+
else {
40+
PyErr_Restore(error_type, error_value, error_traceback);
41+
}
42+
frame->frame_obj = f;
43+
return f;
44+
}
45+
46+
47+
static InterpreterFrame *
48+
copy_frame_to_heap(InterpreterFrame *frame)
49+
{
50+
51+
Py_ssize_t size = ((char*)&frame->stack[frame->stackdepth]) - (char *)_PyFrame_GetLocalsArray(frame);
52+
PyObject **copy = PyMem_Malloc(size);
53+
if (copy == NULL) {
54+
PyErr_NoMemory();
55+
return NULL;
56+
}
57+
PyObject **locals = _PyFrame_GetLocalsArray(frame);
58+
memcpy(copy, locals, size);
59+
InterpreterFrame *res = (InterpreterFrame *)(copy + frame->nlocalsplus);
60+
return res;
61+
}
62+
63+
static inline void
64+
clear_specials(InterpreterFrame *frame)
65+
{
66+
frame->generator = NULL;
67+
Py_XDECREF(frame->frame_obj);
68+
Py_XDECREF(frame->f_locals);
69+
Py_DECREF(frame->f_globals);
70+
Py_DECREF(frame->f_builtins);
71+
Py_DECREF(frame->f_code);
72+
}
73+
74+
static void
75+
take_ownership(PyFrameObject *f, InterpreterFrame *frame)
76+
{
77+
assert(f->f_own_locals_memory == 0);
78+
assert(frame->frame_obj == NULL);
79+
80+
f->f_own_locals_memory = 1;
81+
f->f_frame = frame;
82+
assert(f->f_back == NULL);
83+
if (frame->previous != NULL) {
84+
/* Link PyFrameObjects.f_back and remove link through InterpreterFrame.previous */
85+
PyFrameObject *back = _PyFrame_GetFrameObject(frame->previous);
86+
if (back == NULL) {
87+
/* Memory error here. */
88+
assert(_PyErr_GetTopmostException(_PyThreadState_GET())->exc_type == PyExc_MemoryError);
89+
/* Nothing we can do about it */
90+
PyErr_Clear();
91+
_PyErr_WriteUnraisableMsg("Out of memory lazily allocating frame->f_back", NULL);
92+
}
93+
else {
94+
f->f_back = (PyFrameObject *)Py_NewRef(back);
95+
}
96+
frame->previous = NULL;
97+
}
98+
if (!_PyObject_GC_IS_TRACKED((PyObject *)f)) {
99+
_PyObject_GC_TRACK((PyObject *)f);
100+
}
101+
}
102+
103+
int
104+
_PyFrame_Clear(InterpreterFrame * frame, int take)
105+
{
106+
PyObject **localsarray = ((PyObject **)frame)-frame->nlocalsplus;
107+
if (frame->frame_obj) {
108+
PyFrameObject *f = frame->frame_obj;
109+
frame->frame_obj = NULL;
110+
if (Py_REFCNT(f) > 1) {
111+
if (!take) {
112+
frame = copy_frame_to_heap(frame);
113+
if (frame == NULL) {
114+
return -1;
115+
}
116+
}
117+
take_ownership(f, frame);
118+
Py_DECREF(f);
119+
return 0;
120+
}
121+
Py_DECREF(f);
122+
}
123+
for (int i = 0; i < frame->nlocalsplus; i++) {
124+
Py_XDECREF(localsarray[i]);
125+
}
126+
assert(frame->stackdepth >= 0);
127+
for (int i = 0; i < frame->stackdepth; i++) {
128+
Py_DECREF(frame->stack[i]);
129+
}
130+
clear_specials(frame);
131+
if (take) {
132+
PyMem_Free(_PyFrame_GetLocalsArray(frame));
133+
}
134+
return 0;
135+
}

0 commit comments

Comments
 (0)