@@ -24,6 +24,21 @@ static const char *NON_INIT_CORO_MSG = "can't send non-None value to a "
24
24
static const char * ASYNC_GEN_IGNORED_EXIT_MSG =
25
25
"async generator ignored GeneratorExit" ;
26
26
27
+ /* Returns a borrowed reference */
28
+ static inline PyCodeObject *
29
+ _PyGen_GetCode (PyGenObject * gen ) {
30
+ _PyInterpreterFrame * frame = (_PyInterpreterFrame * )(gen -> gi_iframe );
31
+ return frame -> f_code ;
32
+ }
33
+
34
+ PyCodeObject *
35
+ PyGen_GetCode (PyGenObject * gen ) {
36
+ assert (PyGen_Check (gen ));
37
+ PyCodeObject * res = _PyGen_GetCode (gen );
38
+ Py_INCREF (res );
39
+ return res ;
40
+ }
41
+
27
42
static inline int
28
43
exc_state_traverse (_PyErr_StackItem * exc_state , visitproc visit , void * arg )
29
44
{
@@ -34,7 +49,6 @@ exc_state_traverse(_PyErr_StackItem *exc_state, visitproc visit, void *arg)
34
49
static int
35
50
gen_traverse (PyGenObject * gen , visitproc visit , void * arg )
36
51
{
37
- Py_VISIT (gen -> gi_code );
38
52
Py_VISIT (gen -> gi_name );
39
53
Py_VISIT (gen -> gi_qualname );
40
54
if (gen -> gi_frame_state < FRAME_CLEARED ) {
@@ -88,8 +102,8 @@ _PyGen_Finalize(PyObject *self)
88
102
89
103
/* If `gen` is a coroutine, and if it was never awaited on,
90
104
issue a RuntimeWarning. */
91
- if ( gen -> gi_code != NULL &&
92
- (( PyCodeObject * ) gen -> gi_code )-> co_flags & CO_COROUTINE &&
105
+ assert ( _PyGen_GetCode ( gen ) != NULL );
106
+ if ( _PyGen_GetCode ( gen )-> co_flags & CO_COROUTINE &&
93
107
gen -> gi_frame_state == FRAME_CREATED )
94
108
{
95
109
_PyErr_WarnUnawaitedCoroutine ((PyObject * )gen );
@@ -137,12 +151,12 @@ gen_dealloc(PyGenObject *gen)
137
151
_PyInterpreterFrame * frame = (_PyInterpreterFrame * )gen -> gi_iframe ;
138
152
gen -> gi_frame_state = FRAME_CLEARED ;
139
153
frame -> previous = NULL ;
140
- _PyFrame_Clear (frame );
154
+ _PyFrame_ClearExceptCode (frame );
141
155
}
142
- if ((( PyCodeObject * ) gen -> gi_code )-> co_flags & CO_COROUTINE ) {
156
+ if (_PyGen_GetCode ( gen )-> co_flags & CO_COROUTINE ) {
143
157
Py_CLEAR (((PyCoroObject * )gen )-> cr_origin_or_finalizer );
144
158
}
145
- Py_CLEAR ( gen -> gi_code );
159
+ Py_DECREF ( _PyGen_GetCode ( gen ) );
146
160
Py_CLEAR (gen -> gi_name );
147
161
Py_CLEAR (gen -> gi_qualname );
148
162
_PyErr_ClearExcState (& gen -> gi_exc_state );
@@ -332,7 +346,7 @@ _PyGen_yf(PyGenObject *gen)
332
346
/* Return immediately if the frame didn't start yet. SEND
333
347
always come after LOAD_CONST: a code object should not start
334
348
with SEND */
335
- assert (_PyCode_CODE (gen -> gi_code )[0 ].op .code != SEND );
349
+ assert (_PyCode_CODE (_PyGen_GetCode ( gen ) )[0 ].op .code != SEND );
336
350
return NULL ;
337
351
}
338
352
_Py_CODEUNIT next = frame -> prev_instr [1 ];
@@ -767,6 +781,21 @@ gen_getframe(PyGenObject *gen, void *Py_UNUSED(ignored))
767
781
return _gen_getframe (gen , "gi_frame" );
768
782
}
769
783
784
+ static PyObject *
785
+ _gen_getcode (PyGenObject * gen , const char * const name )
786
+ {
787
+ if (PySys_Audit ("object.__getattr__" , "Os" , gen , name ) < 0 ) {
788
+ return NULL ;
789
+ }
790
+ return Py_NewRef (_PyGen_GetCode (gen ));
791
+ }
792
+
793
+ static PyObject *
794
+ gen_getcode (PyGenObject * gen , void * Py_UNUSED (ignored ))
795
+ {
796
+ return _gen_getcode (gen , "gi_code" );
797
+ }
798
+
770
799
static PyGetSetDef gen_getsetlist [] = {
771
800
{"__name__" , (getter )gen_get_name , (setter )gen_set_name ,
772
801
PyDoc_STR ("name of the generator" )},
@@ -777,11 +806,11 @@ static PyGetSetDef gen_getsetlist[] = {
777
806
{"gi_running" , (getter )gen_getrunning , NULL , NULL },
778
807
{"gi_frame" , (getter )gen_getframe , NULL , NULL },
779
808
{"gi_suspended" , (getter )gen_getsuspended , NULL , NULL },
809
+ {"gi_code" , (getter )gen_getcode , NULL , NULL },
780
810
{NULL } /* Sentinel */
781
811
};
782
812
783
813
static PyMemberDef gen_memberlist [] = {
784
- {"gi_code" , T_OBJECT , offsetof(PyGenObject , gi_code ), READONLY |PY_AUDIT_READ },
785
814
{NULL } /* Sentinel */
786
815
};
787
816
@@ -790,7 +819,7 @@ gen_sizeof(PyGenObject *gen, PyObject *Py_UNUSED(ignored))
790
819
{
791
820
Py_ssize_t res ;
792
821
res = offsetof(PyGenObject , gi_iframe ) + offsetof(_PyInterpreterFrame , localsplus );
793
- PyCodeObject * code = gen -> gi_code ;
822
+ PyCodeObject * code = _PyGen_GetCode ( gen ) ;
794
823
res += _PyFrame_NumSlotsForCodeObject (code ) * sizeof (PyObject * );
795
824
return PyLong_FromSsize_t (res );
796
825
}
@@ -878,7 +907,6 @@ make_gen(PyTypeObject *type, PyFunctionObject *func)
878
907
return NULL ;
879
908
}
880
909
gen -> gi_frame_state = FRAME_CLEARED ;
881
- gen -> gi_code = (PyCodeObject * )Py_NewRef (func -> func_code );
882
910
gen -> gi_weakreflist = NULL ;
883
911
gen -> gi_exc_state .exc_value = NULL ;
884
912
gen -> gi_exc_state .previous_item = NULL ;
@@ -960,20 +988,18 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
960
988
f -> f_frame = frame ;
961
989
frame -> owner = FRAME_OWNED_BY_GENERATOR ;
962
990
assert (PyObject_GC_IsTracked ((PyObject * )f ));
963
- gen -> gi_code = PyFrame_GetCode (f );
964
- Py_INCREF (gen -> gi_code );
965
991
Py_DECREF (f );
966
992
gen -> gi_weakreflist = NULL ;
967
993
gen -> gi_exc_state .exc_value = NULL ;
968
994
gen -> gi_exc_state .previous_item = NULL ;
969
995
if (name != NULL )
970
996
gen -> gi_name = Py_NewRef (name );
971
997
else
972
- gen -> gi_name = Py_NewRef (gen -> gi_code -> co_name );
998
+ gen -> gi_name = Py_NewRef (_PyGen_GetCode ( gen ) -> co_name );
973
999
if (qualname != NULL )
974
1000
gen -> gi_qualname = Py_NewRef (qualname );
975
1001
else
976
- gen -> gi_qualname = Py_NewRef (gen -> gi_code -> co_qualname );
1002
+ gen -> gi_qualname = Py_NewRef (_PyGen_GetCode ( gen ) -> co_qualname );
977
1003
_PyObject_GC_TRACK (gen );
978
1004
return (PyObject * )gen ;
979
1005
}
@@ -1001,7 +1027,7 @@ static int
1001
1027
gen_is_coroutine (PyObject * o )
1002
1028
{
1003
1029
if (PyGen_CheckExact (o )) {
1004
- PyCodeObject * code = ( PyCodeObject * )(( PyGenObject * )o )-> gi_code ;
1030
+ PyCodeObject * code = _PyGen_GetCode (( PyGenObject * )o );
1005
1031
if (code -> co_flags & CO_ITERABLE_COROUTINE ) {
1006
1032
return 1 ;
1007
1033
}
@@ -1110,6 +1136,12 @@ cr_getframe(PyCoroObject *coro, void *Py_UNUSED(ignored))
1110
1136
return _gen_getframe ((PyGenObject * )coro , "cr_frame" );
1111
1137
}
1112
1138
1139
+ static PyObject *
1140
+ cr_getcode (PyCoroObject * coro , void * Py_UNUSED (ignored ))
1141
+ {
1142
+ return _gen_getcode ((PyGenObject * )coro , "cr_code" );
1143
+ }
1144
+
1113
1145
1114
1146
static PyGetSetDef coro_getsetlist [] = {
1115
1147
{"__name__" , (getter )gen_get_name , (setter )gen_set_name ,
@@ -1120,12 +1152,12 @@ static PyGetSetDef coro_getsetlist[] = {
1120
1152
PyDoc_STR ("object being awaited on, or None" )},
1121
1153
{"cr_running" , (getter )cr_getrunning , NULL , NULL },
1122
1154
{"cr_frame" , (getter )cr_getframe , NULL , NULL },
1155
+ {"cr_code" , (getter )cr_getcode , NULL , NULL },
1123
1156
{"cr_suspended" , (getter )cr_getsuspended , NULL , NULL },
1124
1157
{NULL } /* Sentinel */
1125
1158
};
1126
1159
1127
1160
static PyMemberDef coro_memberlist [] = {
1128
- {"cr_code" , T_OBJECT , offsetof(PyCoroObject , cr_code ), READONLY |PY_AUDIT_READ },
1129
1161
{"cr_origin" , T_OBJECT , offsetof(PyCoroObject , cr_origin_or_finalizer ), READONLY },
1130
1162
{NULL } /* Sentinel */
1131
1163
};
@@ -1514,6 +1546,12 @@ ag_getframe(PyAsyncGenObject *ag, void *Py_UNUSED(ignored))
1514
1546
return _gen_getframe ((PyGenObject * )ag , "ag_frame" );
1515
1547
}
1516
1548
1549
+ static PyObject *
1550
+ ag_getcode (PyGenObject * gen , void * Py_UNUSED (ignored ))
1551
+ {
1552
+ return _gen_getcode (gen , "ag__code" );
1553
+ }
1554
+
1517
1555
static PyGetSetDef async_gen_getsetlist [] = {
1518
1556
{"__name__" , (getter )gen_get_name , (setter )gen_set_name ,
1519
1557
PyDoc_STR ("name of the async generator" )},
@@ -1522,13 +1560,13 @@ static PyGetSetDef async_gen_getsetlist[] = {
1522
1560
{"ag_await" , (getter )coro_get_cr_await , NULL ,
1523
1561
PyDoc_STR ("object being awaited on, or None" )},
1524
1562
{"ag_frame" , (getter )ag_getframe , NULL , NULL },
1563
+ {"ag_code" , (getter )ag_getcode , NULL , NULL },
1525
1564
{NULL } /* Sentinel */
1526
1565
};
1527
1566
1528
1567
static PyMemberDef async_gen_memberlist [] = {
1529
1568
{"ag_running" , T_BOOL , offsetof(PyAsyncGenObject , ag_running_async ),
1530
1569
READONLY },
1531
- {"ag_code" , T_OBJECT , offsetof(PyAsyncGenObject , ag_code ), READONLY |PY_AUDIT_READ },
1532
1570
{NULL } /* Sentinel */
1533
1571
};
1534
1572
0 commit comments