Skip to content

Commit b4e2d5d

Browse files
zrr1999SigureMo
andauthored
[SOT] Extract FrameProxy to separate file frame_proxy.h and frame_proxy.c (#69837)
--------- Co-authored-by: SigureMo <[email protected]>
1 parent 239715a commit b4e2d5d

File tree

8 files changed

+200
-132
lines changed

8 files changed

+200
-132
lines changed

paddle/fluid/pybind/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ set(PYBIND_SRCS
140140
auto_parallel_py.cc
141141
sot/eval_frame_tools.cc
142142
sot/cpython_internals.c
143+
sot/frame_proxy.c
143144
sot/eval_frame.c
144145
sot/guards.cc
145146
op_callstack_utils.cc

paddle/fluid/pybind/jit.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ limitations under the License. */
2222
#include "paddle/fluid/jit/serializer.h"
2323
#include "paddle/fluid/pybind/sot/eval_frame.h"
2424
#include "paddle/fluid/pybind/sot/eval_frame_tools.h"
25+
#include "paddle/fluid/pybind/sot/frame_proxy.h"
2526
#include "paddle/fluid/pybind/sot/guards.h"
2627
#include "paddle/fluid/pybind/sot/macros.h"
2728
#include "paddle/phi/common/data_type.h"
@@ -119,6 +120,9 @@ void BindGuard(pybind11::module *m) {
119120
void BindSot(pybind11::module *m) {
120121
#if SOT_IS_SUPPORTED
121122
PyInit__eval_frame();
123+
#if PY_3_11_PLUS
124+
PyInit__frame_proxy();
125+
#endif
122126
m->def(
123127
"set_eval_frame",
124128
[](const py::object &py_func) {

paddle/fluid/pybind/sot/cpython_internals.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ limitations under the License. */
1414

1515
#include "paddle/fluid/pybind/sot/cpython_internals.h"
1616

17-
#include <frameobject.h>
18-
1917
#if SOT_IS_SUPPORTED
2018

19+
#if !PY_3_11_PLUS
20+
#include <frameobject.h>
21+
#endif
22+
2123
#if PY_3_11_PLUS
2224
#include <internal/pycore_code.h>
2325
#include <internal/pycore_frame.h>
@@ -682,7 +684,7 @@ static void Internal_take_ownership(PyFrameObject *f,
682684
} else {
683685
f->f_back = (PyFrameObject *)Py_NewRef(back);
684686
}
685-
#if PY_VERSION_HEX < PY_3_12_0_HEX
687+
#if !PY_3_12_PLUS
686688
frame->previous = NULL;
687689
#endif
688690
}

paddle/fluid/pybind/sot/eval_frame.c

Lines changed: 3 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -18,132 +18,25 @@ limitations under the License. */
1818

1919
#include "paddle/fluid/pybind/sot/cpython_internals.h"
2020
#include "paddle/fluid/pybind/sot/eval_frame_tools.h"
21+
#include "paddle/fluid/pybind/sot/frame_proxy.h"
2122

2223
#include <Python.h>
23-
#include <frameobject.h>
2424

25-
#if PY_3_8_PLUS && PY_VERSION_HEX < PY_3_9_0_HEX
25+
#if PY_3_8_PLUS && !PY_3_9_PLUS
2626
#define Py_BUILD_CORE // internal/pycore_pymem.h need this macro
2727
#include <internal/pycore_pystate.h>
2828
#undef Py_BUILD_CORE
2929
#endif
30-
#if PY_VERSION_HEX < PY_3_11_0_HEX
30+
#if !PY_3_11_PLUS
3131
#include <code.h>
3232
#endif
3333

3434
#include <object.h>
3535
#include <pystate.h>
3636

3737
#if PY_3_11_PLUS
38-
// To avoid the error: undefined symbol: _PyFrame_GetFrameObject, all we need is
39-
// to redefine this function based source code in python3.11. The advantage is
40-
// that we don't need any modification in eval_frame functions.
41-
typedef _PyInterpreterFrame FrameObject;
4238
#define CALL_STAT_INC(name) ((void)0)
4339

44-
// clang-format off
45-
// Define a proxy PyObject to access _PyInterpreterFrame's properties.
46-
// It will be passed as an argument to the eval frame's callback.
47-
typedef struct PyInterpreterFrameProxy {
48-
PyObject_HEAD
49-
_PyInterpreterFrame *frame;
50-
#if PY_3_13_PLUS
51-
PyObject* locals;
52-
#endif
53-
} PyInterpreterFrameProxy;
54-
// clang-format on
55-
56-
#define DECLARE_PROXY_PROPERTY(name) \
57-
static PyObject *PyInterpreterFrameProxy_property_##name( \
58-
PyInterpreterFrameProxy *self, void *closure) { \
59-
Py_XINCREF(self->frame->name); \
60-
return (PyObject *)self->frame->name; \
61-
}
62-
63-
// clang-format off
64-
#define REGISTER_PROXY_PROPERTY(property_name, func_name) \
65-
{ #property_name, (getter)PyInterpreterFrameProxy_property_##func_name, NULL, NULL, NULL }
66-
// clang-format on
67-
68-
#if PY_3_13_PLUS
69-
DECLARE_PROXY_PROPERTY(f_executable)
70-
#else
71-
DECLARE_PROXY_PROPERTY(f_code)
72-
#endif
73-
#if PY_3_13_PLUS
74-
static PyObject *PyInterpreterFrameProxy_property_f_locals(
75-
PyInterpreterFrameProxy *self, void *closure) {
76-
Py_XINCREF(self->locals);
77-
return self->locals;
78-
}
79-
#else
80-
DECLARE_PROXY_PROPERTY(f_locals)
81-
#endif
82-
DECLARE_PROXY_PROPERTY(f_globals)
83-
DECLARE_PROXY_PROPERTY(f_builtins)
84-
85-
// Refer to
86-
// https://github.com/python/cpython/blob/9414ddf91898892f3f6a672ae946931ee4b3ceb7/Objects/frameobject.c#L953-L961
87-
static PyObject *PyInterpreterFrameProxy_method_repr(
88-
PyInterpreterFrameProxy *self) {
89-
#if PY_3_13_PLUS
90-
int lineno = Internal_PyUnstable_InterpreterFrame_GetLine(self->frame);
91-
#else
92-
int lineno = Internal_PyInterpreterFrame_GetLine(self->frame);
93-
#endif
94-
PyCodeObject *code = PyFrame_GET_CODE(self->frame);
95-
return PyUnicode_FromFormat(
96-
"<PyInterpreterFrameProxy at %p, file %R, line %d, code %S>",
97-
self,
98-
code->co_filename,
99-
lineno,
100-
code->co_name);
101-
}
102-
103-
static PyGetSetDef PyInterpreterFrameProxy_properties[] = {
104-
#if PY_3_13_PLUS
105-
REGISTER_PROXY_PROPERTY(f_code, f_executable),
106-
#else
107-
REGISTER_PROXY_PROPERTY(f_code, f_code),
108-
#endif
109-
REGISTER_PROXY_PROPERTY(f_locals, f_locals),
110-
REGISTER_PROXY_PROPERTY(f_globals, f_globals),
111-
REGISTER_PROXY_PROPERTY(f_builtins, f_builtins),
112-
{NULL} /* Sentinel */
113-
};
114-
115-
// clang-format off
116-
static PyTypeObject PyInterpreterFrameProxyType = {
117-
PyVarObject_HEAD_INIT(NULL, 0)
118-
.tp_name = "paddle.framework.core.PyInterpreterFrameProxy",
119-
.tp_doc = PyDoc_STR("A proxy object for _PyInterpreterFrame, "
120-
"it's only define all properties we need."),
121-
.tp_repr = (reprfunc)PyInterpreterFrameProxy_method_repr,
122-
.tp_basicsize = sizeof(PyInterpreterFrameProxy),
123-
.tp_itemsize = 0,
124-
.tp_flags = Py_TPFLAGS_DEFAULT,
125-
.tp_getset = PyInterpreterFrameProxy_properties,
126-
};
127-
// clang-format on
128-
129-
PyInterpreterFrameProxy *PyInterpreterFrameProxy_New(
130-
_PyInterpreterFrame *frame) {
131-
PyTypeObject *type = &PyInterpreterFrameProxyType;
132-
PyInterpreterFrameProxy *self =
133-
(PyInterpreterFrameProxy *)type->tp_alloc(type, 0);
134-
if (!self) {
135-
// VLOG(7) << "Failed to allocate PyInterpreterFrameProxy";
136-
return NULL;
137-
}
138-
self->frame = frame;
139-
#if PY_3_13_PLUS
140-
self->locals = NULL;
141-
#endif
142-
return self;
143-
}
144-
145-
#else
146-
typedef PyFrameObject FrameObject;
14740
#endif
14841

14942
#ifdef _WIN32
@@ -556,13 +449,6 @@ PyMODINIT_FUNC PyInit__eval_frame() {
556449
Py_INCREF(Py_None);
557450
eval_frame_callback_set(Py_None);
558451

559-
#if PY_3_11_PLUS
560-
if (PyType_Ready(&PyInterpreterFrameProxyType) < 0) {
561-
// VLOG(7) << "PyInterpreterFrameProxyType has not been ready!";
562-
}
563-
Py_INCREF(&PyInterpreterFrameProxyType);
564-
#endif
565-
566452
return NULL;
567453
}
568454

paddle/fluid/pybind/sot/eval_frame_tools.h

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,11 @@ extern "C" {
1919
#endif
2020

2121
#include <Python.h>
22-
#include <frameobject.h>
22+
#include "paddle/fluid/pybind/sot/frame_proxy.h"
2323
#include "paddle/fluid/pybind/sot/macros.h"
2424

2525
#if SOT_IS_SUPPORTED
2626

27-
#if PY_3_11_PLUS
28-
#if PY_3_13_PLUS
29-
#define Py_BUILD_CORE
30-
#endif
31-
#include <internal/pycore_frame.h>
32-
typedef _PyInterpreterFrame FrameObject;
33-
#else
34-
typedef PyFrameObject FrameObject;
35-
#endif
36-
3727
int need_skip(FrameObject* frame);
3828
int is_code_without_graph(PyCodeObject* code);
3929

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/* Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License. */
14+
15+
#include "paddle/fluid/pybind/sot/frame_proxy.h"
16+
#include "paddle/fluid/pybind/sot/macros.h"
17+
18+
#if SOT_IS_SUPPORTED
19+
#include <Python.h>
20+
21+
#if PY_3_11_PLUS
22+
23+
#define DECLARE_PROXY_PROPERTY(name) \
24+
static PyObject *PyInterpreterFrameProxy_property_##name( \
25+
PyInterpreterFrameProxy *self, void *closure) { \
26+
Py_XINCREF(self->frame->name); \
27+
return (PyObject *)self->frame->name; \
28+
}
29+
30+
// clang-format off
31+
#define REGISTER_PROXY_PROPERTY(property_name, func_name) \
32+
{ #property_name, (getter)PyInterpreterFrameProxy_property_##func_name, NULL, NULL, NULL }
33+
// clang-format on
34+
35+
#if PY_3_13_PLUS
36+
DECLARE_PROXY_PROPERTY(f_executable)
37+
#else
38+
DECLARE_PROXY_PROPERTY(f_code)
39+
#endif
40+
#if PY_3_13_PLUS
41+
static PyObject *PyInterpreterFrameProxy_property_f_locals(
42+
PyInterpreterFrameProxy *self, void *closure) {
43+
Py_XINCREF(self->locals);
44+
return self->locals;
45+
}
46+
#else
47+
DECLARE_PROXY_PROPERTY(f_locals)
48+
#endif
49+
DECLARE_PROXY_PROPERTY(f_globals)
50+
DECLARE_PROXY_PROPERTY(f_builtins)
51+
52+
// Refer to
53+
// https://github.com/python/cpython/blob/9414ddf91898892f3f6a672ae946931ee4b3ceb7/Objects/frameobject.c#L953-L961
54+
static PyObject *PyInterpreterFrameProxy_method_repr(
55+
PyInterpreterFrameProxy *self) {
56+
#if PY_3_13_PLUS
57+
int lineno = Internal_PyUnstable_InterpreterFrame_GetLine(self->frame);
58+
#else
59+
int lineno = Internal_PyInterpreterFrame_GetLine(self->frame);
60+
#endif
61+
PyCodeObject *code = PyFrame_GET_CODE(self->frame);
62+
return PyUnicode_FromFormat(
63+
"<PyInterpreterFrameProxy at %p, file %R, line %d, code %S>",
64+
self,
65+
code->co_filename,
66+
lineno,
67+
code->co_name);
68+
}
69+
70+
static PyGetSetDef PyInterpreterFrameProxy_properties[] = {
71+
#if PY_3_13_PLUS
72+
REGISTER_PROXY_PROPERTY(f_code, f_executable),
73+
#else
74+
REGISTER_PROXY_PROPERTY(f_code, f_code),
75+
#endif
76+
REGISTER_PROXY_PROPERTY(f_locals, f_locals),
77+
REGISTER_PROXY_PROPERTY(f_globals, f_globals),
78+
REGISTER_PROXY_PROPERTY(f_builtins, f_builtins),
79+
{NULL} /* Sentinel */
80+
};
81+
82+
// clang-format off
83+
static PyTypeObject PyInterpreterFrameProxyType = {
84+
PyVarObject_HEAD_INIT(NULL, 0)
85+
.tp_name = "paddle.framework.core.PyInterpreterFrameProxy",
86+
.tp_doc = PyDoc_STR("A proxy object for _PyInterpreterFrame, "
87+
"it's only define all properties we need."),
88+
.tp_repr = (reprfunc)PyInterpreterFrameProxy_method_repr,
89+
.tp_basicsize = sizeof(PyInterpreterFrameProxy),
90+
.tp_itemsize = 0,
91+
.tp_flags = Py_TPFLAGS_DEFAULT,
92+
.tp_getset = PyInterpreterFrameProxy_properties,
93+
};
94+
// clang-format on
95+
96+
PyInterpreterFrameProxy *PyInterpreterFrameProxy_New(
97+
_PyInterpreterFrame *frame) {
98+
PyTypeObject *type = &PyInterpreterFrameProxyType;
99+
PyInterpreterFrameProxy *self =
100+
(PyInterpreterFrameProxy *)type->tp_alloc(type, 0);
101+
if (!self) {
102+
// VLOG(7) << "Failed to allocate PyInterpreterFrameProxy";
103+
return NULL;
104+
}
105+
self->frame = frame;
106+
#if PY_3_13_PLUS
107+
self->locals = NULL;
108+
#endif
109+
return self;
110+
}
111+
112+
PyMODINIT_FUNC PyInit__frame_proxy() {
113+
if (PyType_Ready(&PyInterpreterFrameProxyType) < 0) {
114+
// VLOG(7) << "PyInterpreterFrameProxyType has not been ready!";
115+
}
116+
Py_INCREF(&PyInterpreterFrameProxyType);
117+
return NULL;
118+
}
119+
120+
#endif
121+
122+
#endif

0 commit comments

Comments
 (0)