28
28
#define OFF (x ) offsetof(PyFrameObject, x)
29
29
30
30
31
- // Returns borrowed reference or NULL
31
+ // Returns new reference or NULL
32
32
static PyObject *
33
33
framelocalsproxy_getval (_PyInterpreterFrame * frame , PyCodeObject * co , int i )
34
34
{
@@ -57,7 +57,10 @@ framelocalsproxy_getval(_PyInterpreterFrame *frame, PyCodeObject *co, int i)
57
57
}
58
58
59
59
if (cell != NULL ) {
60
- value = PyCell_GET (cell );
60
+ value = PyCell_GetRef ((PyCellObject * )cell );
61
+ }
62
+ else {
63
+ Py_XINCREF (value );
61
64
}
62
65
63
66
if (value == NULL ) {
@@ -67,24 +70,42 @@ framelocalsproxy_getval(_PyInterpreterFrame *frame, PyCodeObject *co, int i)
67
70
return value ;
68
71
}
69
72
73
+ static bool
74
+ framelocalsproxy_hasval (_PyInterpreterFrame * frame , PyCodeObject * co , int i )
75
+ {
76
+ PyObject * value = framelocalsproxy_getval (frame , co , i );
77
+ if (value == NULL ) {
78
+ return false;
79
+ }
80
+ Py_DECREF (value );
81
+ return true;
82
+ }
83
+
70
84
static int
71
- framelocalsproxy_getkeyindex (PyFrameObject * frame , PyObject * key , bool read )
85
+ framelocalsproxy_getkeyindex (PyFrameObject * frame , PyObject * key , bool read , PyObject * * value_ptr )
72
86
{
73
87
/*
74
88
* Returns -2 (!) if an error occurred; exception will be set.
75
89
* Returns the fast locals index of the key on success:
76
90
* - if read == true, returns the index if the value is not NULL
77
91
* - if read == false, returns the index if the value is not hidden
78
92
* Otherwise returns -1.
93
+ *
94
+ * If read == true and value_ptr is not NULL, *value_ptr is set to
95
+ * the value of the key if it is found (with a new reference).
79
96
*/
80
97
98
+ // value_ptr should only be given if we are reading the value
99
+ assert (read || value_ptr == NULL );
100
+
81
101
PyCodeObject * co = _PyFrame_GetCode (frame -> f_frame );
82
102
83
103
// Ensure that the key is hashable.
84
104
Py_hash_t key_hash = PyObject_Hash (key );
85
105
if (key_hash == -1 ) {
86
106
return -2 ;
87
107
}
108
+
88
109
bool found = false;
89
110
90
111
// We do 2 loops here because it's highly possible the key is interned
@@ -93,7 +114,14 @@ framelocalsproxy_getkeyindex(PyFrameObject *frame, PyObject* key, bool read)
93
114
PyObject * name = PyTuple_GET_ITEM (co -> co_localsplusnames , i );
94
115
if (name == key ) {
95
116
if (read ) {
96
- if (framelocalsproxy_getval (frame -> f_frame , co , i ) != NULL ) {
117
+ PyObject * value = framelocalsproxy_getval (frame -> f_frame , co , i );
118
+ if (value != NULL ) {
119
+ if (value_ptr != NULL ) {
120
+ * value_ptr = value ;
121
+ }
122
+ else {
123
+ Py_DECREF (value );
124
+ }
97
125
return i ;
98
126
}
99
127
} else {
@@ -124,7 +152,14 @@ framelocalsproxy_getkeyindex(PyFrameObject *frame, PyObject* key, bool read)
124
152
}
125
153
if (same ) {
126
154
if (read ) {
127
- if (framelocalsproxy_getval (frame -> f_frame , co , i ) != NULL ) {
155
+ PyObject * value = framelocalsproxy_getval (frame -> f_frame , co , i );
156
+ if (value != NULL ) {
157
+ if (value_ptr != NULL ) {
158
+ * value_ptr = value ;
159
+ }
160
+ else {
161
+ Py_DECREF (value );
162
+ }
128
163
return i ;
129
164
}
130
165
} else {
@@ -142,25 +177,27 @@ static PyObject *
142
177
framelocalsproxy_getitem (PyObject * self , PyObject * key )
143
178
{
144
179
PyFrameObject * frame = PyFrameLocalsProxyObject_CAST (self )-> frame ;
145
- PyCodeObject * co = _PyFrame_GetCode ( frame -> f_frame ) ;
180
+ PyObject * value = NULL ;
146
181
147
- int i = framelocalsproxy_getkeyindex (frame , key , true);
182
+ int i = framelocalsproxy_getkeyindex (frame , key , true, & value );
148
183
if (i == -2 ) {
149
184
return NULL ;
150
185
}
151
186
if (i >= 0 ) {
152
- PyObject * value = framelocalsproxy_getval (frame -> f_frame , co , i );
153
187
assert (value != NULL );
154
- return Py_NewRef ( value ) ;
188
+ return value ;
155
189
}
190
+ assert (value == NULL );
156
191
157
192
// Okay not in the fast locals, try extra locals
158
193
159
194
PyObject * extra = frame -> f_extra_locals ;
160
195
if (extra != NULL ) {
161
- PyObject * value = PyDict_GetItem (extra , key );
196
+ if (PyDict_GetItemRef (extra , key , & value ) < 0 ) {
197
+ return NULL ;
198
+ }
162
199
if (value != NULL ) {
163
- return Py_NewRef ( value ) ;
200
+ return value ;
164
201
}
165
202
}
166
203
@@ -176,7 +213,7 @@ framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
176
213
_PyStackRef * fast = _PyFrame_GetLocalsArray (frame -> f_frame );
177
214
PyCodeObject * co = _PyFrame_GetCode (frame -> f_frame );
178
215
179
- int i = framelocalsproxy_getkeyindex (frame , key , false);
216
+ int i = framelocalsproxy_getkeyindex (frame , key , false, NULL );
180
217
if (i == -2 ) {
181
218
return -1 ;
182
219
}
@@ -297,8 +334,7 @@ framelocalsproxy_keys(PyObject *self, PyObject *Py_UNUSED(ignored))
297
334
}
298
335
299
336
for (int i = 0 ; i < co -> co_nlocalsplus ; i ++ ) {
300
- PyObject * val = framelocalsproxy_getval (frame -> f_frame , co , i );
301
- if (val ) {
337
+ if (framelocalsproxy_hasval (frame -> f_frame , co , i )) {
302
338
PyObject * name = PyTuple_GET_ITEM (co -> co_localsplusnames , i );
303
339
if (PyList_Append (names , name ) < 0 ) {
304
340
Py_DECREF (names );
@@ -511,8 +547,10 @@ framelocalsproxy_values(PyObject *self, PyObject *Py_UNUSED(ignored))
511
547
if (value ) {
512
548
if (PyList_Append (values , value ) < 0 ) {
513
549
Py_DECREF (values );
550
+ Py_DECREF (value );
514
551
return NULL ;
515
552
}
553
+ Py_DECREF (value );
516
554
}
517
555
}
518
556
@@ -550,16 +588,19 @@ framelocalsproxy_items(PyObject *self, PyObject *Py_UNUSED(ignored))
550
588
PyObject * pair = PyTuple_Pack (2 , name , value );
551
589
if (pair == NULL ) {
552
590
Py_DECREF (items );
591
+ Py_DECREF (value );
553
592
return NULL ;
554
593
}
555
594
556
595
if (PyList_Append (items , pair ) < 0 ) {
557
596
Py_DECREF (items );
558
597
Py_DECREF (pair );
598
+ Py_DECREF (value );
559
599
return NULL ;
560
600
}
561
601
562
602
Py_DECREF (pair );
603
+ Py_DECREF (value );
563
604
}
564
605
}
565
606
@@ -601,7 +642,7 @@ framelocalsproxy_length(PyObject *self)
601
642
}
602
643
603
644
for (int i = 0 ; i < co -> co_nlocalsplus ; i ++ ) {
604
- if (framelocalsproxy_getval (frame -> f_frame , co , i ) != NULL ) {
645
+ if (framelocalsproxy_hasval (frame -> f_frame , co , i )) {
605
646
size ++ ;
606
647
}
607
648
}
@@ -613,7 +654,7 @@ framelocalsproxy_contains(PyObject *self, PyObject *key)
613
654
{
614
655
PyFrameObject * frame = PyFrameLocalsProxyObject_CAST (self )-> frame ;
615
656
616
- int i = framelocalsproxy_getkeyindex (frame , key , true);
657
+ int i = framelocalsproxy_getkeyindex (frame , key , true, NULL );
617
658
if (i == -2 ) {
618
659
return -1 ;
619
660
}
@@ -724,7 +765,7 @@ framelocalsproxy_pop(PyObject* self, PyObject *const *args, Py_ssize_t nargs)
724
765
725
766
PyFrameObject * frame = PyFrameLocalsProxyObject_CAST (self )-> frame ;
726
767
727
- int i = framelocalsproxy_getkeyindex (frame , key , false);
768
+ int i = framelocalsproxy_getkeyindex (frame , key , false, NULL );
728
769
if (i == -2 ) {
729
770
return NULL ;
730
771
}
@@ -2066,9 +2107,7 @@ _PyFrame_HasHiddenLocals(_PyInterpreterFrame *frame)
2066
2107
_PyLocals_Kind kind = _PyLocals_GetKind (co -> co_localspluskinds , i );
2067
2108
2068
2109
if (kind & CO_FAST_HIDDEN ) {
2069
- PyObject * value = framelocalsproxy_getval (frame , co , i );
2070
-
2071
- if (value != NULL ) {
2110
+ if (framelocalsproxy_hasval (frame , co , i )) {
2072
2111
return true;
2073
2112
}
2074
2113
}
0 commit comments