Coverage Report

Created: 2025-07-04 06:49

/src/cpython/Objects/frameobject.c
Line
Count
Source (jump to first uncovered line)
1
/* Frame object implementation */
2
3
#include "Python.h"
4
#include "pycore_cell.h"          // PyCell_GetRef()
5
#include "pycore_ceval.h"         // _PyEval_SetOpcodeTrace()
6
#include "pycore_code.h"          // CO_FAST_LOCAL
7
#include "pycore_dict.h"          // _PyDict_LoadBuiltinsFromGlobals()
8
#include "pycore_frame.h"         // PyFrameObject
9
#include "pycore_function.h"      // _PyFunction_FromConstructor()
10
#include "pycore_genobject.h"     // _PyGen_GetGeneratorFromFrame()
11
#include "pycore_interpframe.h"   // _PyFrame_GetLocalsArray()
12
#include "pycore_modsupport.h"    // _PyArg_CheckPositional()
13
#include "pycore_object.h"        // _PyObject_GC_UNTRACK()
14
#include "pycore_opcode_metadata.h" // _PyOpcode_Caches
15
#include "pycore_optimizer.h"     // _Py_Executors_InvalidateDependency()
16
#include "pycore_unicodeobject.h" // _PyUnicode_Equal()
17
18
#include "frameobject.h"          // PyFrameLocalsProxyObject
19
#include "opcode.h"               // EXTENDED_ARG
20
21
#include "clinic/frameobject.c.h"
22
23
24
#define PyFrameObject_CAST(op)  \
25
27.4M
    (assert(PyObject_TypeCheck((op), &PyFrame_Type)), (PyFrameObject *)(op))
26
27
#define PyFrameLocalsProxyObject_CAST(op)                           \
28
16
    (                                                               \
29
16
        assert(PyObject_TypeCheck((op), &PyFrameLocalsProxy_Type)), \
30
16
        (PyFrameLocalsProxyObject *)(op)                            \
31
16
    )
32
33
#define OFF(x) offsetof(PyFrameObject, x)
34
35
/*[clinic input]
36
class frame "PyFrameObject *" "&PyFrame_Type"
37
[clinic start generated code]*/
38
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2d1dbf2e06cf351f]*/
39
40
41
// Returns new reference or NULL
42
static PyObject *
43
framelocalsproxy_getval(_PyInterpreterFrame *frame, PyCodeObject *co, int i)
44
14
{
45
14
    _PyStackRef *fast = _PyFrame_GetLocalsArray(frame);
46
14
    _PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
47
48
14
    PyObject *value = PyStackRef_AsPyObjectBorrow(fast[i]);
49
14
    PyObject *cell = NULL;
50
51
14
    if (value == NULL) {
52
14
        return NULL;
53
14
    }
54
55
0
    if (kind == CO_FAST_FREE || kind & CO_FAST_CELL) {
56
        // The cell was set when the frame was created from
57
        // the function's closure.
58
        // GH-128396: With PEP 709, it's possible to have a fast variable in
59
        // an inlined comprehension that has the same name as the cell variable
60
        // in the frame, where the `kind` obtained from frame can not guarantee
61
        // that the variable is a cell.
62
        // If the variable is not a cell, we are okay with it and we can simply
63
        // return the value.
64
0
        if (PyCell_Check(value)) {
65
0
            cell = value;
66
0
        }
67
0
    }
68
69
0
    if (cell != NULL) {
70
0
        value = PyCell_GetRef((PyCellObject *)cell);
71
0
    }
72
0
    else {
73
0
        Py_XINCREF(value);
74
0
    }
75
76
0
    if (value == NULL) {
77
0
        return NULL;
78
0
    }
79
80
0
    return value;
81
0
}
82
83
static bool
84
framelocalsproxy_hasval(_PyInterpreterFrame *frame, PyCodeObject *co, int i)
85
14
{
86
14
    PyObject *value = framelocalsproxy_getval(frame, co, i);
87
14
    if (value == NULL) {
88
14
        return false;
89
14
    }
90
0
    Py_DECREF(value);
91
0
    return true;
92
14
}
93
94
static int
95
framelocalsproxy_getkeyindex(PyFrameObject *frame, PyObject *key, bool read, PyObject **value_ptr)
96
0
{
97
    /*
98
     * Returns -2 (!) if an error occurred; exception will be set.
99
     * Returns the fast locals index of the key on success:
100
     *   - if read == true, returns the index if the value is not NULL
101
     *   - if read == false, returns the index if the value is not hidden
102
     * Otherwise returns -1.
103
     *
104
     * If read == true and value_ptr is not NULL, *value_ptr is set to
105
     * the value of the key if it is found (with a new reference).
106
     */
107
108
    // value_ptr should only be given if we are reading the value
109
0
    assert(read || value_ptr == NULL);
110
111
0
    PyCodeObject *co = _PyFrame_GetCode(frame->f_frame);
112
113
    // Ensure that the key is hashable.
114
0
    Py_hash_t key_hash = PyObject_Hash(key);
115
0
    if (key_hash == -1) {
116
0
        return -2;
117
0
    }
118
119
0
    bool found = false;
120
121
    // We do 2 loops here because it's highly possible the key is interned
122
    // and we can do a pointer comparison.
123
0
    for (int i = 0; i < co->co_nlocalsplus; i++) {
124
0
        PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
125
0
        if (name == key) {
126
0
            if (read) {
127
0
                PyObject *value = framelocalsproxy_getval(frame->f_frame, co, i);
128
0
                if (value != NULL) {
129
0
                    if (value_ptr != NULL) {
130
0
                        *value_ptr = value;
131
0
                    }
132
0
                    else {
133
0
                        Py_DECREF(value);
134
0
                    }
135
0
                    return i;
136
0
                }
137
0
            } else {
138
0
                if (!(_PyLocals_GetKind(co->co_localspluskinds, i) & CO_FAST_HIDDEN)) {
139
0
                    return i;
140
0
                }
141
0
            }
142
0
            found = true;
143
0
        }
144
0
    }
145
0
    if (found) {
146
        // This is an attempt to read an unset local variable or
147
        // write to a variable that is hidden from regular write operations
148
0
        return -1;
149
0
    }
150
    // This is unlikely, but we need to make sure. This means the key
151
    // is not interned.
152
0
    for (int i = 0; i < co->co_nlocalsplus; i++) {
153
0
        PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
154
0
        Py_hash_t name_hash = PyObject_Hash(name);
155
0
        assert(name_hash != -1);  // keys are exact unicode
156
0
        if (name_hash != key_hash) {
157
0
            continue;
158
0
        }
159
0
        int same = PyObject_RichCompareBool(name, key, Py_EQ);
160
0
        if (same < 0) {
161
0
            return -2;
162
0
        }
163
0
        if (same) {
164
0
            if (read) {
165
0
                PyObject *value = framelocalsproxy_getval(frame->f_frame, co, i);
166
0
                if (value != NULL) {
167
0
                    if (value_ptr != NULL) {
168
0
                        *value_ptr = value;
169
0
                    }
170
0
                    else {
171
0
                        Py_DECREF(value);
172
0
                    }
173
0
                    return i;
174
0
                }
175
0
            } else {
176
0
                if (!(_PyLocals_GetKind(co->co_localspluskinds, i) & CO_FAST_HIDDEN)) {
177
0
                    return i;
178
0
                }
179
0
            }
180
0
        }
181
0
    }
182
183
0
    return -1;
184
0
}
185
186
static PyObject *
187
framelocalsproxy_getitem(PyObject *self, PyObject *key)
188
0
{
189
0
    PyFrameObject *frame = PyFrameLocalsProxyObject_CAST(self)->frame;
190
0
    PyObject *value = NULL;
191
192
0
    int i = framelocalsproxy_getkeyindex(frame, key, true, &value);
193
0
    if (i == -2) {
194
0
        return NULL;
195
0
    }
196
0
    if (i >= 0) {
197
0
        assert(value != NULL);
198
0
        return value;
199
0
    }
200
0
    assert(value == NULL);
201
202
    // Okay not in the fast locals, try extra locals
203
204
0
    PyObject *extra = frame->f_extra_locals;
205
0
    if (extra != NULL) {
206
0
        if (PyDict_GetItemRef(extra, key, &value) < 0) {
207
0
            return NULL;
208
0
        }
209
0
        if (value != NULL) {
210
0
            return value;
211
0
        }
212
0
    }
213
214
0
    PyErr_Format(PyExc_KeyError, "local variable '%R' is not defined", key);
215
0
    return NULL;
216
0
}
217
218
static int
219
add_overwritten_fast_local(PyFrameObject *frame, PyObject *obj)
220
0
{
221
0
    Py_ssize_t new_size;
222
0
    if (frame->f_overwritten_fast_locals == NULL) {
223
0
        new_size = 1;
224
0
    }
225
0
    else {
226
0
        Py_ssize_t size = PyTuple_Size(frame->f_overwritten_fast_locals);
227
0
        if (size == -1) {
228
0
            return -1;
229
0
        }
230
0
        new_size = size + 1;
231
0
    }
232
0
    PyObject *new_tuple = PyTuple_New(new_size);
233
0
    if (new_tuple == NULL) {
234
0
        return -1;
235
0
    }
236
0
    for (Py_ssize_t i = 0; i < new_size - 1; i++) {
237
0
        PyObject *o = PyTuple_GET_ITEM(frame->f_overwritten_fast_locals, i);
238
0
        PyTuple_SET_ITEM(new_tuple, i, Py_NewRef(o));
239
0
    }
240
0
    PyTuple_SET_ITEM(new_tuple, new_size - 1, Py_NewRef(obj));
241
0
    Py_XSETREF(frame->f_overwritten_fast_locals, new_tuple);
242
0
    return 0;
243
0
}
244
245
static int
246
framelocalsproxy_setitem(PyObject *self, PyObject *key, PyObject *value)
247
0
{
248
    /* Merge locals into fast locals */
249
0
    PyFrameObject *frame = PyFrameLocalsProxyObject_CAST(self)->frame;
250
0
    _PyStackRef *fast = _PyFrame_GetLocalsArray(frame->f_frame);
251
0
    PyCodeObject *co = _PyFrame_GetCode(frame->f_frame);
252
253
0
    int i = framelocalsproxy_getkeyindex(frame, key, false, NULL);
254
0
    if (i == -2) {
255
0
        return -1;
256
0
    }
257
0
    if (i >= 0) {
258
0
        if (value == NULL) {
259
0
            PyErr_SetString(PyExc_ValueError, "cannot remove local variables from FrameLocalsProxy");
260
0
            return -1;
261
0
        }
262
263
0
        _Py_Executors_InvalidateDependency(PyInterpreterState_Get(), co, 1);
264
265
0
        _PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
266
0
        _PyStackRef oldvalue = fast[i];
267
0
        PyObject *cell = NULL;
268
0
        if (kind == CO_FAST_FREE) {
269
            // The cell was set when the frame was created from
270
            // the function's closure.
271
0
            assert(!PyStackRef_IsNull(oldvalue) && PyCell_Check(PyStackRef_AsPyObjectBorrow(oldvalue)));
272
0
            cell = PyStackRef_AsPyObjectBorrow(oldvalue);
273
0
        } else if (kind & CO_FAST_CELL && !PyStackRef_IsNull(oldvalue)) {
274
0
            PyObject *as_obj = PyStackRef_AsPyObjectBorrow(oldvalue);
275
0
            if (PyCell_Check(as_obj)) {
276
0
                cell = as_obj;
277
0
            }
278
0
        }
279
0
        if (cell != NULL) {
280
0
            Py_XINCREF(value);
281
0
            PyCell_SetTakeRef((PyCellObject *)cell, value);
282
0
        } else if (value != PyStackRef_AsPyObjectBorrow(oldvalue)) {
283
0
            PyObject *old_obj = PyStackRef_AsPyObjectBorrow(fast[i]);
284
0
            if (old_obj != NULL && !_Py_IsImmortal(old_obj)) {
285
0
                if (add_overwritten_fast_local(frame, old_obj) < 0) {
286
0
                    return -1;
287
0
                }
288
0
                PyStackRef_CLOSE(fast[i]);
289
0
            }
290
0
            fast[i] = PyStackRef_FromPyObjectNew(value);
291
0
        }
292
0
        return 0;
293
0
    }
294
295
    // Okay not in the fast locals, try extra locals
296
297
0
    PyObject *extra = frame->f_extra_locals;
298
299
0
    if (extra == NULL) {
300
0
        if (value == NULL) {
301
0
            _PyErr_SetKeyError(key);
302
0
            return -1;
303
0
        }
304
0
        extra = PyDict_New();
305
0
        if (extra == NULL) {
306
0
            return -1;
307
0
        }
308
0
        frame->f_extra_locals = extra;
309
0
    }
310
311
0
    assert(PyDict_Check(extra));
312
313
0
    if (value == NULL) {
314
0
        return PyDict_DelItem(extra, key);
315
0
    } else {
316
0
        return PyDict_SetItem(extra, key, value);
317
0
    }
318
0
}
319
320
static int
321
framelocalsproxy_merge(PyObject* self, PyObject* other)
322
0
{
323
0
    if (!PyDict_Check(other) && !PyFrameLocalsProxy_Check(other)) {
324
0
        return -1;
325
0
    }
326
327
0
    PyObject *keys = PyMapping_Keys(other);
328
0
    if (keys == NULL) {
329
0
        return -1;
330
0
    }
331
332
0
    PyObject *iter = PyObject_GetIter(keys);
333
0
    Py_DECREF(keys);
334
0
    if (iter == NULL) {
335
0
        return -1;
336
0
    }
337
338
0
    PyObject *key = NULL;
339
0
    PyObject *value = NULL;
340
341
0
    while ((key = PyIter_Next(iter)) != NULL) {
342
0
        value = PyObject_GetItem(other, key);
343
0
        if (value == NULL) {
344
0
            Py_DECREF(key);
345
0
            Py_DECREF(iter);
346
0
            return -1;
347
0
        }
348
349
0
        if (framelocalsproxy_setitem(self, key, value) < 0) {
350
0
            Py_DECREF(key);
351
0
            Py_DECREF(value);
352
0
            Py_DECREF(iter);
353
0
            return -1;
354
0
        }
355
356
0
        Py_DECREF(key);
357
0
        Py_DECREF(value);
358
0
    }
359
360
0
    Py_DECREF(iter);
361
362
0
    if (PyErr_Occurred()) {
363
0
        return -1;
364
0
    }
365
366
0
    return 0;
367
0
}
368
369
static PyObject *
370
framelocalsproxy_keys(PyObject *self, PyObject *Py_UNUSED(ignored))
371
0
{
372
0
    PyFrameObject *frame = PyFrameLocalsProxyObject_CAST(self)->frame;
373
0
    PyCodeObject *co = _PyFrame_GetCode(frame->f_frame);
374
0
    PyObject *names = PyList_New(0);
375
0
    if (names == NULL) {
376
0
        return NULL;
377
0
    }
378
379
0
    for (int i = 0; i < co->co_nlocalsplus; i++) {
380
0
        if (framelocalsproxy_hasval(frame->f_frame, co, i)) {
381
0
            PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
382
0
            if (PyList_Append(names, name) < 0) {
383
0
                Py_DECREF(names);
384
0
                return NULL;
385
0
            }
386
0
        }
387
0
    }
388
389
    // Iterate through the extra locals
390
0
    if (frame->f_extra_locals) {
391
0
        assert(PyDict_Check(frame->f_extra_locals));
392
393
0
        Py_ssize_t i = 0;
394
0
        PyObject *key = NULL;
395
0
        PyObject *value = NULL;
396
397
0
        while (PyDict_Next(frame->f_extra_locals, &i, &key, &value)) {
398
0
            if (PyList_Append(names, key) < 0) {
399
0
                Py_DECREF(names);
400
0
                return NULL;
401
0
            }
402
0
        }
403
0
    }
404
405
0
    return names;
406
0
}
407
408
static void
409
framelocalsproxy_dealloc(PyObject *self)
410
16
{
411
16
    PyFrameLocalsProxyObject *proxy = PyFrameLocalsProxyObject_CAST(self);
412
16
    PyObject_GC_UnTrack(self);
413
16
    Py_CLEAR(proxy->frame);
414
16
    Py_TYPE(self)->tp_free(self);
415
16
}
416
417
static PyObject *
418
framelocalsproxy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
419
16
{
420
16
    if (PyTuple_GET_SIZE(args) != 1) {
421
0
        PyErr_Format(PyExc_TypeError,
422
0
                     "FrameLocalsProxy expected 1 argument, got %zd",
423
0
                     PyTuple_GET_SIZE(args));
424
0
        return NULL;
425
0
    }
426
16
    PyObject *item = PyTuple_GET_ITEM(args, 0);
427
428
16
    if (!PyFrame_Check(item)) {
429
0
        PyErr_Format(PyExc_TypeError, "expect frame, not %T", item);
430
0
        return NULL;
431
0
    }
432
16
    PyFrameObject *frame = (PyFrameObject*)item;
433
434
16
    if (kwds != NULL && PyDict_Size(kwds) != 0) {
435
0
        PyErr_SetString(PyExc_TypeError,
436
0
                        "FrameLocalsProxy takes no keyword arguments");
437
0
        return 0;
438
0
    }
439
440
16
    PyFrameLocalsProxyObject *self = (PyFrameLocalsProxyObject *)type->tp_alloc(type, 0);
441
16
    if (self == NULL) {
442
0
        return NULL;
443
0
    }
444
445
16
    ((PyFrameLocalsProxyObject*)self)->frame = (PyFrameObject*)Py_NewRef(frame);
446
447
16
    return (PyObject *)self;
448
16
}
449
450
static int
451
framelocalsproxy_tp_clear(PyObject *self)
452
0
{
453
0
    PyFrameLocalsProxyObject *proxy = PyFrameLocalsProxyObject_CAST(self);
454
0
    Py_CLEAR(proxy->frame);
455
0
    return 0;
456
0
}
457
458
static int
459
framelocalsproxy_visit(PyObject *self, visitproc visit, void *arg)
460
0
{
461
0
    PyFrameLocalsProxyObject *proxy = PyFrameLocalsProxyObject_CAST(self);
462
0
    Py_VISIT(proxy->frame);
463
0
    return 0;
464
0
}
465
466
static PyObject *
467
framelocalsproxy_iter(PyObject *self)
468
0
{
469
0
    PyObject* keys = framelocalsproxy_keys(self, NULL);
470
0
    if (keys == NULL) {
471
0
        return NULL;
472
0
    }
473
474
0
    PyObject* iter = PyObject_GetIter(keys);
475
0
    Py_XDECREF(keys);
476
477
0
    return iter;
478
0
}
479
480
static PyObject *
481
framelocalsproxy_richcompare(PyObject *lhs, PyObject *rhs, int op)
482
0
{
483
0
    PyFrameLocalsProxyObject *self = PyFrameLocalsProxyObject_CAST(lhs);
484
0
    if (PyFrameLocalsProxy_Check(rhs)) {
485
0
        PyFrameLocalsProxyObject *other = (PyFrameLocalsProxyObject *)rhs;
486
0
        bool result = self->frame == other->frame;
487
0
        if (op == Py_EQ) {
488
0
            return PyBool_FromLong(result);
489
0
        } else if (op == Py_NE) {
490
0
            return PyBool_FromLong(!result);
491
0
        }
492
0
    } else if (PyDict_Check(rhs)) {
493
0
        PyObject *dct = PyDict_New();
494
0
        if (dct == NULL) {
495
0
            return NULL;
496
0
        }
497
498
0
        if (PyDict_Update(dct, lhs) < 0) {
499
0
            Py_DECREF(dct);
500
0
            return NULL;
501
0
        }
502
503
0
        PyObject *result = PyObject_RichCompare(dct, rhs, op);
504
0
        Py_DECREF(dct);
505
0
        return result;
506
0
    }
507
508
0
    Py_RETURN_NOTIMPLEMENTED;
509
0
}
510
511
static PyObject *
512
framelocalsproxy_repr(PyObject *self)
513
0
{
514
0
    int i = Py_ReprEnter(self);
515
0
    if (i != 0) {
516
0
        return i > 0 ? PyUnicode_FromString("{...}") : NULL;
517
0
    }
518
519
0
    PyObject *dct = PyDict_New();
520
0
    if (dct == NULL) {
521
0
        Py_ReprLeave(self);
522
0
        return NULL;
523
0
    }
524
525
0
    if (PyDict_Update(dct, self) < 0) {
526
0
        Py_DECREF(dct);
527
0
        Py_ReprLeave(self);
528
0
        return NULL;
529
0
    }
530
531
0
    PyObject *repr = PyObject_Repr(dct);
532
0
    Py_DECREF(dct);
533
534
0
    Py_ReprLeave(self);
535
536
0
    return repr;
537
0
}
538
539
static PyObject*
540
framelocalsproxy_or(PyObject *self, PyObject *other)
541
0
{
542
0
    if (!PyDict_Check(other) && !PyFrameLocalsProxy_Check(other)) {
543
0
        Py_RETURN_NOTIMPLEMENTED;
544
0
    }
545
546
0
    PyObject *result = PyDict_New();
547
0
    if (result == NULL) {
548
0
        return NULL;
549
0
    }
550
551
0
    if (PyDict_Update(result, self) < 0) {
552
0
        Py_DECREF(result);
553
0
        return NULL;
554
0
    }
555
556
0
    if (PyDict_Update(result, other) < 0) {
557
0
        Py_DECREF(result);
558
0
        return NULL;
559
0
    }
560
561
0
    return result;
562
0
}
563
564
static PyObject*
565
framelocalsproxy_inplace_or(PyObject *self, PyObject *other)
566
0
{
567
0
    if (!PyDict_Check(other) && !PyFrameLocalsProxy_Check(other)) {
568
0
        Py_RETURN_NOTIMPLEMENTED;
569
0
    }
570
571
0
    if (framelocalsproxy_merge(self, other) < 0) {
572
0
        Py_RETURN_NOTIMPLEMENTED;
573
0
    }
574
575
0
    return Py_NewRef(self);
576
0
}
577
578
static PyObject *
579
framelocalsproxy_values(PyObject *self, PyObject *Py_UNUSED(ignored))
580
0
{
581
0
    PyFrameObject *frame = PyFrameLocalsProxyObject_CAST(self)->frame;
582
0
    PyCodeObject *co = _PyFrame_GetCode(frame->f_frame);
583
0
    PyObject *values = PyList_New(0);
584
0
    if (values == NULL) {
585
0
        return NULL;
586
0
    }
587
588
0
    for (int i = 0; i < co->co_nlocalsplus; i++) {
589
0
        PyObject *value = framelocalsproxy_getval(frame->f_frame, co, i);
590
0
        if (value) {
591
0
            if (PyList_Append(values, value) < 0) {
592
0
                Py_DECREF(values);
593
0
                Py_DECREF(value);
594
0
                return NULL;
595
0
            }
596
0
            Py_DECREF(value);
597
0
        }
598
0
    }
599
600
    // Iterate through the extra locals
601
0
    if (frame->f_extra_locals) {
602
0
        Py_ssize_t j = 0;
603
0
        PyObject *key = NULL;
604
0
        PyObject *value = NULL;
605
0
        while (PyDict_Next(frame->f_extra_locals, &j, &key, &value)) {
606
0
            if (PyList_Append(values, value) < 0) {
607
0
                Py_DECREF(values);
608
0
                return NULL;
609
0
            }
610
0
        }
611
0
    }
612
613
0
    return values;
614
0
}
615
616
static PyObject *
617
framelocalsproxy_items(PyObject *self, PyObject *Py_UNUSED(ignored))
618
0
{
619
0
    PyFrameObject *frame = PyFrameLocalsProxyObject_CAST(self)->frame;
620
0
    PyCodeObject *co = _PyFrame_GetCode(frame->f_frame);
621
0
    PyObject *items = PyList_New(0);
622
0
    if (items == NULL) {
623
0
        return NULL;
624
0
    }
625
626
0
    for (int i = 0; i < co->co_nlocalsplus; i++) {
627
0
        PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
628
0
        PyObject *value = framelocalsproxy_getval(frame->f_frame, co, i);
629
630
0
        if (value) {
631
0
            PyObject *pair = PyTuple_Pack(2, name, value);
632
0
            if (pair == NULL) {
633
0
                Py_DECREF(items);
634
0
                Py_DECREF(value);
635
0
                return NULL;
636
0
            }
637
638
0
            if (PyList_Append(items, pair) < 0) {
639
0
                Py_DECREF(items);
640
0
                Py_DECREF(pair);
641
0
                Py_DECREF(value);
642
0
                return NULL;
643
0
            }
644
645
0
            Py_DECREF(pair);
646
0
            Py_DECREF(value);
647
0
        }
648
0
    }
649
650
    // Iterate through the extra locals
651
0
    if (frame->f_extra_locals) {
652
0
        Py_ssize_t j = 0;
653
0
        PyObject *key = NULL;
654
0
        PyObject *value = NULL;
655
0
        while (PyDict_Next(frame->f_extra_locals, &j, &key, &value)) {
656
0
            PyObject *pair = PyTuple_Pack(2, key, value);
657
0
            if (pair == NULL) {
658
0
                Py_DECREF(items);
659
0
                return NULL;
660
0
            }
661
662
0
            if (PyList_Append(items, pair) < 0) {
663
0
                Py_DECREF(items);
664
0
                Py_DECREF(pair);
665
0
                return NULL;
666
0
            }
667
668
0
            Py_DECREF(pair);
669
0
        }
670
0
    }
671
672
0
    return items;
673
0
}
674
675
static Py_ssize_t
676
framelocalsproxy_length(PyObject *self)
677
0
{
678
0
    PyFrameObject *frame = PyFrameLocalsProxyObject_CAST(self)->frame;
679
0
    PyCodeObject *co = _PyFrame_GetCode(frame->f_frame);
680
0
    Py_ssize_t size = 0;
681
682
0
    if (frame->f_extra_locals != NULL) {
683
0
        assert(PyDict_Check(frame->f_extra_locals));
684
0
        size += PyDict_Size(frame->f_extra_locals);
685
0
    }
686
687
0
    for (int i = 0; i < co->co_nlocalsplus; i++) {
688
0
        if (framelocalsproxy_hasval(frame->f_frame, co, i)) {
689
0
            size++;
690
0
        }
691
0
    }
692
0
    return size;
693
0
}
694
695
static int
696
framelocalsproxy_contains(PyObject *self, PyObject *key)
697
0
{
698
0
    PyFrameObject *frame = PyFrameLocalsProxyObject_CAST(self)->frame;
699
700
0
    int i = framelocalsproxy_getkeyindex(frame, key, true, NULL);
701
0
    if (i == -2) {
702
0
        return -1;
703
0
    }
704
0
    if (i >= 0) {
705
0
        return 1;
706
0
    }
707
708
0
    PyObject *extra = frame->f_extra_locals;
709
0
    if (extra != NULL) {
710
0
        return PyDict_Contains(extra, key);
711
0
    }
712
713
0
    return 0;
714
0
}
715
716
static PyObject* framelocalsproxy___contains__(PyObject *self, PyObject *key)
717
0
{
718
0
    int result = framelocalsproxy_contains(self, key);
719
0
    if (result < 0) {
720
0
        return NULL;
721
0
    }
722
0
    return PyBool_FromLong(result);
723
0
}
724
725
static PyObject*
726
framelocalsproxy_update(PyObject *self, PyObject *other)
727
0
{
728
0
    if (framelocalsproxy_merge(self, other) < 0) {
729
0
        PyErr_SetString(PyExc_TypeError, "update() argument must be dict or another FrameLocalsProxy");
730
0
        return NULL;
731
0
    }
732
733
0
    Py_RETURN_NONE;
734
0
}
735
736
static PyObject*
737
framelocalsproxy_get(PyObject* self, PyObject *const *args, Py_ssize_t nargs)
738
0
{
739
0
    if (nargs < 1 || nargs > 2) {
740
0
        PyErr_SetString(PyExc_TypeError, "get expected 1 or 2 arguments");
741
0
        return NULL;
742
0
    }
743
744
0
    PyObject *key = args[0];
745
0
    PyObject *default_value = Py_None;
746
747
0
    if (nargs == 2) {
748
0
        default_value = args[1];
749
0
    }
750
751
0
    PyObject *result = framelocalsproxy_getitem(self, key);
752
753
0
    if (result == NULL) {
754
0
        if (PyErr_ExceptionMatches(PyExc_KeyError)) {
755
0
            PyErr_Clear();
756
0
            return Py_XNewRef(default_value);
757
0
        }
758
0
        return NULL;
759
0
    }
760
761
0
    return result;
762
0
}
763
764
static PyObject*
765
framelocalsproxy_setdefault(PyObject* self, PyObject *const *args, Py_ssize_t nargs)
766
0
{
767
0
    if (nargs < 1 || nargs > 2) {
768
0
        PyErr_SetString(PyExc_TypeError, "setdefault expected 1 or 2 arguments");
769
0
        return NULL;
770
0
    }
771
772
0
    PyObject *key = args[0];
773
0
    PyObject *default_value = Py_None;
774
775
0
    if (nargs == 2) {
776
0
        default_value = args[1];
777
0
    }
778
779
0
    PyObject *result = framelocalsproxy_getitem(self, key);
780
781
0
    if (result == NULL) {
782
0
        if (PyErr_ExceptionMatches(PyExc_KeyError)) {
783
0
            PyErr_Clear();
784
0
            if (framelocalsproxy_setitem(self, key, default_value) < 0) {
785
0
                return NULL;
786
0
            }
787
0
            return Py_XNewRef(default_value);
788
0
        }
789
0
        return NULL;
790
0
    }
791
792
0
    return result;
793
0
}
794
795
static PyObject*
796
framelocalsproxy_pop(PyObject* self, PyObject *const *args, Py_ssize_t nargs)
797
0
{
798
0
    if (!_PyArg_CheckPositional("pop", nargs, 1, 2)) {
799
0
        return NULL;
800
0
    }
801
802
0
    PyObject *key = args[0];
803
0
    PyObject *default_value = NULL;
804
805
0
    if (nargs == 2) {
806
0
        default_value = args[1];
807
0
    }
808
809
0
    PyFrameObject *frame = PyFrameLocalsProxyObject_CAST(self)->frame;
810
811
0
    int i = framelocalsproxy_getkeyindex(frame, key, false, NULL);
812
0
    if (i == -2) {
813
0
        return NULL;
814
0
    }
815
816
0
    if (i >= 0) {
817
0
        PyErr_SetString(PyExc_ValueError, "cannot remove local variables from FrameLocalsProxy");
818
0
        return NULL;
819
0
    }
820
821
0
    PyObject *result = NULL;
822
823
0
    if (frame->f_extra_locals == NULL) {
824
0
        if (default_value != NULL) {
825
0
            return Py_XNewRef(default_value);
826
0
        } else {
827
0
            _PyErr_SetKeyError(key);
828
0
            return NULL;
829
0
        }
830
0
    }
831
832
0
    if (PyDict_Pop(frame->f_extra_locals, key, &result) < 0) {
833
0
        return NULL;
834
0
    }
835
836
0
    if (result == NULL) {
837
0
        if (default_value != NULL) {
838
0
            return Py_XNewRef(default_value);
839
0
        } else {
840
0
            _PyErr_SetKeyError(key);
841
0
            return NULL;
842
0
        }
843
0
    }
844
845
0
    return result;
846
0
}
847
848
static PyObject*
849
framelocalsproxy_copy(PyObject *self, PyObject *Py_UNUSED(ignored))
850
0
{
851
0
    PyObject* result = PyDict_New();
852
853
0
    if (result == NULL) {
854
0
        return NULL;
855
0
    }
856
857
0
    if (PyDict_Update(result, self) < 0) {
858
0
        Py_DECREF(result);
859
0
        return NULL;
860
0
    }
861
862
0
    return result;
863
0
}
864
865
static PyObject*
866
framelocalsproxy_reversed(PyObject *self, PyObject *Py_UNUSED(ignored))
867
0
{
868
0
    PyObject *result = framelocalsproxy_keys(self, NULL);
869
870
0
    if (result == NULL) {
871
0
        return NULL;
872
0
    }
873
874
0
    if (PyList_Reverse(result) < 0) {
875
0
        Py_DECREF(result);
876
0
        return NULL;
877
0
    }
878
0
    return result;
879
0
}
880
881
static PyNumberMethods framelocalsproxy_as_number = {
882
    .nb_or = framelocalsproxy_or,
883
    .nb_inplace_or = framelocalsproxy_inplace_or,
884
};
885
886
static PySequenceMethods framelocalsproxy_as_sequence = {
887
    .sq_contains = framelocalsproxy_contains,
888
};
889
890
static PyMappingMethods framelocalsproxy_as_mapping = {
891
    .mp_length = framelocalsproxy_length,
892
    .mp_subscript = framelocalsproxy_getitem,
893
    .mp_ass_subscript = framelocalsproxy_setitem,
894
};
895
896
static PyMethodDef framelocalsproxy_methods[] = {
897
    {"__contains__", framelocalsproxy___contains__, METH_O | METH_COEXIST, NULL},
898
    {"__getitem__", framelocalsproxy_getitem, METH_O | METH_COEXIST, NULL},
899
    {"update", framelocalsproxy_update, METH_O, NULL},
900
    {"__reversed__", framelocalsproxy_reversed, METH_NOARGS, NULL},
901
    {"copy", framelocalsproxy_copy, METH_NOARGS, NULL},
902
    {"keys", framelocalsproxy_keys, METH_NOARGS, NULL},
903
    {"values", framelocalsproxy_values, METH_NOARGS, NULL},
904
    {"items", _PyCFunction_CAST(framelocalsproxy_items), METH_NOARGS, NULL},
905
    {"get", _PyCFunction_CAST(framelocalsproxy_get), METH_FASTCALL, NULL},
906
    {"pop", _PyCFunction_CAST(framelocalsproxy_pop), METH_FASTCALL, NULL},
907
    {
908
        "setdefault",
909
        _PyCFunction_CAST(framelocalsproxy_setdefault),
910
        METH_FASTCALL,
911
        NULL
912
    },
913
    {NULL, NULL}   /* sentinel */
914
};
915
916
PyTypeObject PyFrameLocalsProxy_Type = {
917
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
918
    .tp_name = "FrameLocalsProxy",
919
    .tp_basicsize = sizeof(PyFrameLocalsProxyObject),
920
    .tp_dealloc = framelocalsproxy_dealloc,
921
    .tp_repr = &framelocalsproxy_repr,
922
    .tp_as_number = &framelocalsproxy_as_number,
923
    .tp_as_sequence = &framelocalsproxy_as_sequence,
924
    .tp_as_mapping = &framelocalsproxy_as_mapping,
925
    .tp_getattro = PyObject_GenericGetAttr,
926
    .tp_setattro = PyObject_GenericSetAttr,
927
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MAPPING,
928
    .tp_traverse = framelocalsproxy_visit,
929
    .tp_clear = framelocalsproxy_tp_clear,
930
    .tp_richcompare = framelocalsproxy_richcompare,
931
    .tp_iter = framelocalsproxy_iter,
932
    .tp_methods = framelocalsproxy_methods,
933
    .tp_alloc = PyType_GenericAlloc,
934
    .tp_new = framelocalsproxy_new,
935
    .tp_free = PyObject_GC_Del,
936
};
937
938
PyObject *
939
_PyFrameLocalsProxy_New(PyFrameObject *frame)
940
16
{
941
16
    PyObject* args = PyTuple_Pack(1, frame);
942
16
    if (args == NULL) {
943
0
        return NULL;
944
0
    }
945
946
16
    PyObject* proxy = framelocalsproxy_new(&PyFrameLocalsProxy_Type, args, NULL);
947
16
    Py_DECREF(args);
948
16
    return proxy;
949
16
}
950
951
static PyMemberDef frame_memberlist[] = {
952
    {"f_trace_lines",   Py_T_BOOL,         OFF(f_trace_lines), 0},
953
    {NULL}      /* Sentinel */
954
};
955
956
/*[clinic input]
957
@critical_section
958
@getter
959
frame.f_locals as frame_locals
960
961
Return the mapping used by the frame to look up local variables.
962
[clinic start generated code]*/
963
964
static PyObject *
965
frame_locals_get_impl(PyFrameObject *self)
966
/*[clinic end generated code: output=b4ace8bb4cae71f4 input=7bd444d0dc8ddf44]*/
967
16
{
968
16
    assert(!_PyFrame_IsIncomplete(self->f_frame));
969
970
16
    PyCodeObject *co = _PyFrame_GetCode(self->f_frame);
971
972
16
    if (!(co->co_flags & CO_OPTIMIZED) && !_PyFrame_HasHiddenLocals(self->f_frame)) {
973
0
        if (self->f_frame->f_locals == NULL) {
974
            // We found cases when f_locals is NULL for non-optimized code.
975
            // We fill the f_locals with an empty dict to avoid crash until
976
            // we find the root cause.
977
0
            self->f_frame->f_locals = PyDict_New();
978
0
            if (self->f_frame->f_locals == NULL) {
979
0
                return NULL;
980
0
            }
981
0
        }
982
0
        return Py_NewRef(self->f_frame->f_locals);
983
0
    }
984
985
16
    return _PyFrameLocalsProxy_New(self);
986
16
}
987
988
int
989
PyFrame_GetLineNumber(PyFrameObject *f)
990
2.35k
{
991
2.35k
    assert(f != NULL);
992
2.35k
    if (f->f_lineno == -1) {
993
        // We should calculate it once. If we can't get the line number,
994
        // set f->f_lineno to 0.
995
0
        f->f_lineno = PyUnstable_InterpreterFrame_GetLine(f->f_frame);
996
0
        if (f->f_lineno < 0) {
997
0
            f->f_lineno = 0;
998
0
            return -1;
999
0
        }
1000
0
    }
1001
1002
2.35k
    if (f->f_lineno > 0) {
1003
0
        return f->f_lineno;
1004
0
    }
1005
2.35k
    return PyUnstable_InterpreterFrame_GetLine(f->f_frame);
1006
2.35k
}
1007
1008
/*[clinic input]
1009
@critical_section
1010
@getter
1011
frame.f_lineno as frame_lineno
1012
1013
Return the current line number in the frame.
1014
[clinic start generated code]*/
1015
1016
static PyObject *
1017
frame_lineno_get_impl(PyFrameObject *self)
1018
/*[clinic end generated code: output=70f35de5ac7ad630 input=87b9ec648b742936]*/
1019
0
{
1020
0
    int lineno = PyFrame_GetLineNumber(self);
1021
0
    if (lineno < 0) {
1022
0
        Py_RETURN_NONE;
1023
0
    }
1024
0
    return PyLong_FromLong(lineno);
1025
0
}
1026
1027
/*[clinic input]
1028
@critical_section
1029
@getter
1030
frame.f_lasti as frame_lasti
1031
1032
Return the index of the last attempted instruction in the frame.
1033
[clinic start generated code]*/
1034
1035
static PyObject *
1036
frame_lasti_get_impl(PyFrameObject *self)
1037
/*[clinic end generated code: output=03275b4f0327d1a2 input=0225ed49cb1fbeeb]*/
1038
0
{
1039
0
    int lasti = _PyInterpreterFrame_LASTI(self->f_frame);
1040
0
    if (lasti < 0) {
1041
0
        return PyLong_FromLong(-1);
1042
0
    }
1043
0
    return PyLong_FromLong(lasti * sizeof(_Py_CODEUNIT));
1044
0
}
1045
1046
/*[clinic input]
1047
@critical_section
1048
@getter
1049
frame.f_globals as frame_globals
1050
1051
Return the global variables in the frame.
1052
[clinic start generated code]*/
1053
1054
static PyObject *
1055
frame_globals_get_impl(PyFrameObject *self)
1056
/*[clinic end generated code: output=7758788c32885528 input=7fff7241357d314d]*/
1057
0
{
1058
0
    PyObject *globals = self->f_frame->f_globals;
1059
0
    if (globals == NULL) {
1060
0
        globals = Py_None;
1061
0
    }
1062
0
    return Py_NewRef(globals);
1063
0
}
1064
1065
/*[clinic input]
1066
@critical_section
1067
@getter
1068
frame.f_builtins as frame_builtins
1069
1070
Return the built-in variables in the frame.
1071
[clinic start generated code]*/
1072
1073
static PyObject *
1074
frame_builtins_get_impl(PyFrameObject *self)
1075
/*[clinic end generated code: output=45362faa6d42c702 input=27c696d6ffcad2c7]*/
1076
0
{
1077
0
    PyObject *builtins = self->f_frame->f_builtins;
1078
0
    if (builtins == NULL) {
1079
0
        builtins = Py_None;
1080
0
    }
1081
0
    return Py_NewRef(builtins);
1082
0
}
1083
1084
/*[clinic input]
1085
@getter
1086
frame.f_code as frame_code
1087
1088
Return the code object being executed in this frame.
1089
[clinic start generated code]*/
1090
1091
static PyObject *
1092
frame_code_get_impl(PyFrameObject *self)
1093
/*[clinic end generated code: output=a5ed6207395a8cef input=e127e7098c124816]*/
1094
0
{
1095
0
    if (PySys_Audit("object.__getattr__", "Os", self, "f_code") < 0) {
1096
0
        return NULL;
1097
0
    }
1098
0
    return (PyObject *)PyFrame_GetCode(self);
1099
0
}
1100
1101
/*[clinic input]
1102
@critical_section
1103
@getter
1104
frame.f_back as frame_back
1105
[clinic start generated code]*/
1106
1107
static PyObject *
1108
frame_back_get_impl(PyFrameObject *self)
1109
/*[clinic end generated code: output=3a84c22a55a63c79 input=9e528570d0e1f44a]*/
1110
0
{
1111
0
    PyObject *res = (PyObject *)PyFrame_GetBack(self);
1112
0
    if (res == NULL) {
1113
0
        Py_RETURN_NONE;
1114
0
    }
1115
0
    return res;
1116
0
}
1117
1118
/*[clinic input]
1119
@critical_section
1120
@getter
1121
frame.f_trace_opcodes as frame_trace_opcodes
1122
1123
Return True if opcode tracing is enabled, False otherwise.
1124
[clinic start generated code]*/
1125
1126
static PyObject *
1127
frame_trace_opcodes_get_impl(PyFrameObject *self)
1128
/*[clinic end generated code: output=53ff41d09cc32e87 input=4eb91dc88e04677a]*/
1129
0
{
1130
0
    return self->f_trace_opcodes ? Py_True : Py_False;
1131
0
}
1132
1133
/*[clinic input]
1134
@critical_section
1135
@setter
1136
frame.f_trace_opcodes as frame_trace_opcodes
1137
[clinic start generated code]*/
1138
1139
static int
1140
frame_trace_opcodes_set_impl(PyFrameObject *self, PyObject *value)
1141
/*[clinic end generated code: output=92619da2bfccd449 input=7e286eea3c0333ff]*/
1142
0
{
1143
0
    if (!PyBool_Check(value)) {
1144
0
        PyErr_SetString(PyExc_TypeError,
1145
0
                        "attribute value type must be bool");
1146
0
        return -1;
1147
0
    }
1148
0
    if (value == Py_True) {
1149
0
        self->f_trace_opcodes = 1;
1150
0
        if (self->f_trace) {
1151
0
            return _PyEval_SetOpcodeTrace(self, true);
1152
0
        }
1153
0
    }
1154
0
    else {
1155
0
        self->f_trace_opcodes = 0;
1156
0
        return _PyEval_SetOpcodeTrace(self, false);
1157
0
    }
1158
0
    return 0;
1159
0
}
1160
1161
/* Model the evaluation stack, to determine which jumps
1162
 * are safe and how many values needs to be popped.
1163
 * The stack is modelled by a 64 integer, treating any
1164
 * stack that can't fit into 64 bits as "overflowed".
1165
 */
1166
1167
typedef enum kind {
1168
    Iterator = 1,
1169
    Except = 2,
1170
    Object = 3,
1171
    Null = 4,
1172
    Lasti = 5,
1173
} Kind;
1174
1175
static int
1176
0
compatible_kind(Kind from, Kind to) {
1177
0
    if (to == 0) {
1178
0
        return 0;
1179
0
    }
1180
0
    if (to == Object) {
1181
0
        return from != Null;
1182
0
    }
1183
0
    if (to == Null) {
1184
0
        return 1;
1185
0
    }
1186
0
    return from == to;
1187
0
}
1188
1189
0
#define BITS_PER_BLOCK 3
1190
1191
0
#define UNINITIALIZED -2
1192
0
#define OVERFLOWED -1
1193
1194
0
#define MAX_STACK_ENTRIES (63/BITS_PER_BLOCK)
1195
0
#define WILL_OVERFLOW (1ULL<<((MAX_STACK_ENTRIES-1)*BITS_PER_BLOCK))
1196
1197
0
#define EMPTY_STACK 0
1198
1199
static inline int64_t
1200
push_value(int64_t stack, Kind kind)
1201
0
{
1202
0
    if (((uint64_t)stack) >= WILL_OVERFLOW) {
1203
0
        return OVERFLOWED;
1204
0
    }
1205
0
    else {
1206
0
        return (stack << BITS_PER_BLOCK) | kind;
1207
0
    }
1208
0
}
1209
1210
static inline int64_t
1211
pop_value(int64_t stack)
1212
0
{
1213
0
    return Py_ARITHMETIC_RIGHT_SHIFT(int64_t, stack, BITS_PER_BLOCK);
1214
0
}
1215
1216
0
#define MASK ((1<<BITS_PER_BLOCK)-1)
1217
1218
static inline Kind
1219
top_of_stack(int64_t stack)
1220
0
{
1221
0
    return stack & MASK;
1222
0
}
1223
1224
static inline Kind
1225
peek(int64_t stack, int n)
1226
0
{
1227
0
    assert(n >= 1);
1228
0
    return (stack>>(BITS_PER_BLOCK*(n-1))) & MASK;
1229
0
}
1230
1231
static Kind
1232
stack_swap(int64_t stack, int n)
1233
0
{
1234
0
    assert(n >= 1);
1235
0
    Kind to_swap = peek(stack, n);
1236
0
    Kind top = top_of_stack(stack);
1237
0
    int shift = BITS_PER_BLOCK*(n-1);
1238
0
    int64_t replaced_low = (stack & ~(MASK << shift)) | (top << shift);
1239
0
    int64_t replaced_top = (replaced_low & ~MASK) | to_swap;
1240
0
    return replaced_top;
1241
0
}
1242
1243
static int64_t
1244
0
pop_to_level(int64_t stack, int level) {
1245
0
    if (level == 0) {
1246
0
        return EMPTY_STACK;
1247
0
    }
1248
0
    int64_t max_item = (1<<BITS_PER_BLOCK) - 1;
1249
0
    int64_t level_max_stack = max_item << ((level-1) * BITS_PER_BLOCK);
1250
0
    while (stack > level_max_stack) {
1251
0
        stack = pop_value(stack);
1252
0
    }
1253
0
    return stack;
1254
0
}
1255
1256
#if 0
1257
/* These functions are useful for debugging the stack marking code */
1258
1259
static char
1260
tos_char(int64_t stack) {
1261
    switch(top_of_stack(stack)) {
1262
        case Iterator:
1263
            return 'I';
1264
        case Except:
1265
            return 'E';
1266
        case Object:
1267
            return 'O';
1268
        case Lasti:
1269
            return 'L';
1270
        case Null:
1271
            return 'N';
1272
    }
1273
    return '?';
1274
}
1275
1276
static void
1277
print_stack(int64_t stack) {
1278
    if (stack < 0) {
1279
        if (stack == UNINITIALIZED) {
1280
            printf("---");
1281
        }
1282
        else if (stack == OVERFLOWED) {
1283
            printf("OVERFLOWED");
1284
        }
1285
        else {
1286
            printf("??");
1287
        }
1288
        return;
1289
    }
1290
    while (stack) {
1291
        printf("%c", tos_char(stack));
1292
        stack = pop_value(stack);
1293
    }
1294
}
1295
1296
static void
1297
print_stacks(int64_t *stacks, int n) {
1298
    for (int i = 0; i < n; i++) {
1299
        printf("%d: ", i);
1300
        print_stack(stacks[i]);
1301
        printf("\n");
1302
    }
1303
}
1304
1305
#endif
1306
1307
static int64_t *
1308
mark_stacks(PyCodeObject *code_obj, int len)
1309
0
{
1310
0
    PyObject *co_code = _PyCode_GetCode(code_obj);
1311
0
    if (co_code == NULL) {
1312
0
        return NULL;
1313
0
    }
1314
0
    int64_t *stacks = PyMem_New(int64_t, len+1);
1315
1316
0
    if (stacks == NULL) {
1317
0
        PyErr_NoMemory();
1318
0
        Py_DECREF(co_code);
1319
0
        return NULL;
1320
0
    }
1321
0
    for (int i = 1; i <= len; i++) {
1322
0
        stacks[i] = UNINITIALIZED;
1323
0
    }
1324
0
    stacks[0] = EMPTY_STACK;
1325
0
    int todo = 1;
1326
0
    while (todo) {
1327
0
        todo = 0;
1328
        /* Scan instructions */
1329
0
        for (int i = 0; i < len;) {
1330
0
            int j;
1331
0
            int64_t next_stack = stacks[i];
1332
0
            _Py_CODEUNIT inst = _Py_GetBaseCodeUnit(code_obj, i);
1333
0
            int opcode = inst.op.code;
1334
0
            int oparg = 0;
1335
0
            while (opcode == EXTENDED_ARG) {
1336
0
                oparg = (oparg << 8) | inst.op.arg;
1337
0
                i++;
1338
0
                inst = _Py_GetBaseCodeUnit(code_obj, i);
1339
0
                opcode = inst.op.code;
1340
0
                stacks[i] = next_stack;
1341
0
            }
1342
0
            oparg = (oparg << 8) | inst.op.arg;
1343
0
            int next_i = i + _PyOpcode_Caches[opcode] + 1;
1344
0
            if (next_stack == UNINITIALIZED) {
1345
0
                i = next_i;
1346
0
                continue;
1347
0
            }
1348
0
            switch (opcode) {
1349
0
                case POP_JUMP_IF_FALSE:
1350
0
                case POP_JUMP_IF_TRUE:
1351
0
                case POP_JUMP_IF_NONE:
1352
0
                case POP_JUMP_IF_NOT_NONE:
1353
0
                {
1354
0
                    int64_t target_stack;
1355
0
                    j = next_i + oparg;
1356
0
                    assert(j < len);
1357
0
                    next_stack = pop_value(next_stack);
1358
0
                    target_stack = next_stack;
1359
0
                    assert(stacks[j] == UNINITIALIZED || stacks[j] == target_stack);
1360
0
                    stacks[j] = target_stack;
1361
0
                    stacks[next_i] = next_stack;
1362
0
                    break;
1363
0
                }
1364
0
                case SEND:
1365
0
                    j = oparg + i + INLINE_CACHE_ENTRIES_SEND + 1;
1366
0
                    assert(j < len);
1367
0
                    assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack);
1368
0
                    stacks[j] = next_stack;
1369
0
                    stacks[next_i] = next_stack;
1370
0
                    break;
1371
0
                case JUMP_FORWARD:
1372
0
                    j = oparg + i + 1;
1373
0
                    assert(j < len);
1374
0
                    assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack);
1375
0
                    stacks[j] = next_stack;
1376
0
                    break;
1377
0
                case JUMP_BACKWARD:
1378
0
                case JUMP_BACKWARD_NO_INTERRUPT:
1379
0
                    j = next_i - oparg;
1380
0
                    assert(j >= 0);
1381
0
                    assert(j < len);
1382
0
                    if (stacks[j] == UNINITIALIZED && j < i) {
1383
0
                        todo = 1;
1384
0
                    }
1385
0
                    assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack);
1386
0
                    stacks[j] = next_stack;
1387
0
                    break;
1388
0
                case GET_ITER:
1389
0
                    next_stack = push_value(pop_value(next_stack), Iterator);
1390
0
                    next_stack = push_value(next_stack, Iterator);
1391
0
                    stacks[next_i] = next_stack;
1392
0
                    break;
1393
0
                case GET_AITER:
1394
0
                    next_stack = push_value(pop_value(next_stack), Iterator);
1395
0
                    stacks[next_i] = next_stack;
1396
0
                    break;
1397
0
                case FOR_ITER:
1398
0
                {
1399
0
                    int64_t target_stack = push_value(next_stack, Object);
1400
0
                    stacks[next_i] = target_stack;
1401
0
                    j = oparg + 1 + INLINE_CACHE_ENTRIES_FOR_ITER + i;
1402
0
                    assert(j < len);
1403
0
                    assert(stacks[j] == UNINITIALIZED || stacks[j] == target_stack);
1404
0
                    stacks[j] = target_stack;
1405
0
                    break;
1406
0
                }
1407
0
                case END_ASYNC_FOR:
1408
0
                    next_stack = pop_value(pop_value(next_stack));
1409
0
                    stacks[next_i] = next_stack;
1410
0
                    break;
1411
0
                case PUSH_EXC_INFO:
1412
0
                    next_stack = push_value(next_stack, Except);
1413
0
                    stacks[next_i] = next_stack;
1414
0
                    break;
1415
0
                case POP_EXCEPT:
1416
0
                    assert(top_of_stack(next_stack) == Except);
1417
0
                    next_stack = pop_value(next_stack);
1418
0
                    stacks[next_i] = next_stack;
1419
0
                    break;
1420
0
                case RETURN_VALUE:
1421
0
                    assert(pop_value(next_stack) == EMPTY_STACK);
1422
0
                    assert(top_of_stack(next_stack) == Object);
1423
0
                    break;
1424
0
                case RAISE_VARARGS:
1425
0
                    break;
1426
0
                case RERAISE:
1427
0
                    assert(top_of_stack(next_stack) == Except);
1428
                    /* End of block */
1429
0
                    break;
1430
0
                case PUSH_NULL:
1431
0
                    next_stack = push_value(next_stack, Null);
1432
0
                    stacks[next_i] = next_stack;
1433
0
                    break;
1434
0
                case LOAD_GLOBAL:
1435
0
                {
1436
0
                    int j = oparg;
1437
0
                    next_stack = push_value(next_stack, Object);
1438
0
                    if (j & 1) {
1439
0
                        next_stack = push_value(next_stack, Null);
1440
0
                    }
1441
0
                    stacks[next_i] = next_stack;
1442
0
                    break;
1443
0
                }
1444
0
                case LOAD_ATTR:
1445
0
                {
1446
0
                    assert(top_of_stack(next_stack) == Object);
1447
0
                    int j = oparg;
1448
0
                    if (j & 1) {
1449
0
                        next_stack = pop_value(next_stack);
1450
0
                        next_stack = push_value(next_stack, Object);
1451
0
                        next_stack = push_value(next_stack, Null);
1452
0
                    }
1453
0
                    stacks[next_i] = next_stack;
1454
0
                    break;
1455
0
                }
1456
0
                case SWAP:
1457
0
                {
1458
0
                    int n = oparg;
1459
0
                    next_stack = stack_swap(next_stack, n);
1460
0
                    stacks[next_i] = next_stack;
1461
0
                    break;
1462
0
                }
1463
0
                case COPY:
1464
0
                {
1465
0
                    int n = oparg;
1466
0
                    next_stack = push_value(next_stack, peek(next_stack, n));
1467
0
                    stacks[next_i] = next_stack;
1468
0
                    break;
1469
0
                }
1470
0
                case CACHE:
1471
0
                case RESERVED:
1472
0
                {
1473
0
                    assert(0);
1474
0
                }
1475
0
                default:
1476
0
                {
1477
0
                    int delta = PyCompile_OpcodeStackEffect(opcode, oparg);
1478
0
                    assert(delta != PY_INVALID_STACK_EFFECT);
1479
0
                    while (delta < 0) {
1480
0
                        next_stack = pop_value(next_stack);
1481
0
                        delta++;
1482
0
                    }
1483
0
                    while (delta > 0) {
1484
0
                        next_stack = push_value(next_stack, Object);
1485
0
                        delta--;
1486
0
                    }
1487
0
                    stacks[next_i] = next_stack;
1488
0
                }
1489
0
            }
1490
0
            i = next_i;
1491
0
        }
1492
        /* Scan exception table */
1493
0
        unsigned char *start = (unsigned char *)PyBytes_AS_STRING(code_obj->co_exceptiontable);
1494
0
        unsigned char *end = start + PyBytes_GET_SIZE(code_obj->co_exceptiontable);
1495
0
        unsigned char *scan = start;
1496
0
        while (scan < end) {
1497
0
            int start_offset, size, handler;
1498
0
            scan = parse_varint(scan, &start_offset);
1499
0
            assert(start_offset >= 0 && start_offset < len);
1500
0
            scan = parse_varint(scan, &size);
1501
0
            assert(size >= 0 && start_offset+size <= len);
1502
0
            scan = parse_varint(scan, &handler);
1503
0
            assert(handler >= 0 && handler < len);
1504
0
            int depth_and_lasti;
1505
0
            scan = parse_varint(scan, &depth_and_lasti);
1506
0
            int level = depth_and_lasti >> 1;
1507
0
            int lasti = depth_and_lasti & 1;
1508
0
            if (stacks[start_offset] != UNINITIALIZED) {
1509
0
                if (stacks[handler] == UNINITIALIZED) {
1510
0
                    todo = 1;
1511
0
                    uint64_t target_stack = pop_to_level(stacks[start_offset], level);
1512
0
                    if (lasti) {
1513
0
                        target_stack = push_value(target_stack, Lasti);
1514
0
                    }
1515
0
                    target_stack = push_value(target_stack, Except);
1516
0
                    stacks[handler] = target_stack;
1517
0
                }
1518
0
            }
1519
0
        }
1520
0
    }
1521
0
    Py_DECREF(co_code);
1522
0
    return stacks;
1523
0
}
1524
1525
static int
1526
compatible_stack(int64_t from_stack, int64_t to_stack)
1527
0
{
1528
0
    if (from_stack < 0 || to_stack < 0) {
1529
0
        return 0;
1530
0
    }
1531
0
    while(from_stack > to_stack) {
1532
0
        from_stack = pop_value(from_stack);
1533
0
    }
1534
0
    while(from_stack) {
1535
0
        Kind from_top = top_of_stack(from_stack);
1536
0
        Kind to_top = top_of_stack(to_stack);
1537
0
        if (!compatible_kind(from_top, to_top)) {
1538
0
            return 0;
1539
0
        }
1540
0
        from_stack = pop_value(from_stack);
1541
0
        to_stack = pop_value(to_stack);
1542
0
    }
1543
0
    return to_stack == 0;
1544
0
}
1545
1546
static const char *
1547
explain_incompatible_stack(int64_t to_stack)
1548
0
{
1549
0
    assert(to_stack != 0);
1550
0
    if (to_stack == OVERFLOWED) {
1551
0
        return "stack is too deep to analyze";
1552
0
    }
1553
0
    if (to_stack == UNINITIALIZED) {
1554
0
        return "can't jump into an exception handler, or code may be unreachable";
1555
0
    }
1556
0
    Kind target_kind = top_of_stack(to_stack);
1557
0
    switch(target_kind) {
1558
0
        case Except:
1559
0
            return "can't jump into an 'except' block as there's no exception";
1560
0
        case Lasti:
1561
0
            return "can't jump into a re-raising block as there's no location";
1562
0
        case Object:
1563
0
        case Null:
1564
0
            return "incompatible stacks";
1565
0
        case Iterator:
1566
0
            return "can't jump into the body of a for loop";
1567
0
        default:
1568
0
            Py_UNREACHABLE();
1569
0
    }
1570
0
}
1571
1572
static int *
1573
marklines(PyCodeObject *code, int len)
1574
0
{
1575
0
    PyCodeAddressRange bounds;
1576
0
    _PyCode_InitAddressRange(code, &bounds);
1577
0
    assert (bounds.ar_end == 0);
1578
0
    int last_line = -1;
1579
1580
0
    int *linestarts = PyMem_New(int, len);
1581
0
    if (linestarts == NULL) {
1582
0
        return NULL;
1583
0
    }
1584
0
    for (int i = 0; i < len; i++) {
1585
0
        linestarts[i] = -1;
1586
0
    }
1587
1588
0
    while (_PyLineTable_NextAddressRange(&bounds)) {
1589
0
        assert(bounds.ar_start / (int)sizeof(_Py_CODEUNIT) < len);
1590
0
        if (bounds.ar_line != last_line && bounds.ar_line != -1) {
1591
0
            linestarts[bounds.ar_start / sizeof(_Py_CODEUNIT)] = bounds.ar_line;
1592
0
            last_line = bounds.ar_line;
1593
0
        }
1594
0
    }
1595
0
    return linestarts;
1596
0
}
1597
1598
static int
1599
first_line_not_before(int *lines, int len, int line)
1600
0
{
1601
0
    int result = INT_MAX;
1602
0
    for (int i = 0; i < len; i++) {
1603
0
        if (lines[i] < result && lines[i] >= line) {
1604
0
            result = lines[i];
1605
0
        }
1606
0
    }
1607
0
    if (result == INT_MAX) {
1608
0
        return -1;
1609
0
    }
1610
0
    return result;
1611
0
}
1612
1613
static bool frame_is_suspended(PyFrameObject *frame)
1614
0
{
1615
0
    assert(!_PyFrame_IsIncomplete(frame->f_frame));
1616
0
    if (frame->f_frame->owner == FRAME_OWNED_BY_GENERATOR) {
1617
0
        PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame->f_frame);
1618
0
        return FRAME_STATE_SUSPENDED(gen->gi_frame_state);
1619
0
    }
1620
0
    return false;
1621
0
}
1622
1623
/* Setter for f_lineno - you can set f_lineno from within a trace function in
1624
 * order to jump to a given line of code, subject to some restrictions.  Most
1625
 * lines are OK to jump to because they don't make any assumptions about the
1626
 * state of the stack (obvious because you could remove the line and the code
1627
 * would still work without any stack errors), but there are some constructs
1628
 * that limit jumping:
1629
 *
1630
 *  o Any exception handlers.
1631
 *  o 'for' and 'async for' loops can't be jumped into because the
1632
 *    iterator needs to be on the stack.
1633
 *  o Jumps cannot be made from within a trace function invoked with a
1634
 *    'return' or 'exception' event since the eval loop has been exited at
1635
 *    that time.
1636
 */
1637
/*[clinic input]
1638
@critical_section
1639
@setter
1640
frame.f_lineno as frame_lineno
1641
[clinic start generated code]*/
1642
1643
static int
1644
frame_lineno_set_impl(PyFrameObject *self, PyObject *value)
1645
/*[clinic end generated code: output=e64c86ff6be64292 input=36ed3c896b27fb91]*/
1646
0
{
1647
0
    PyCodeObject *code = _PyFrame_GetCode(self->f_frame);
1648
0
    if (value == NULL) {
1649
0
        PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
1650
0
        return -1;
1651
0
    }
1652
    /* f_lineno must be an integer. */
1653
0
    if (!PyLong_CheckExact(value)) {
1654
0
        PyErr_SetString(PyExc_ValueError,
1655
0
                        "lineno must be an integer");
1656
0
        return -1;
1657
0
    }
1658
1659
0
    bool is_suspended = frame_is_suspended(self);
1660
    /*
1661
     * This code preserves the historical restrictions on
1662
     * setting the line number of a frame.
1663
     * Jumps are forbidden on a 'return' trace event (except after a yield).
1664
     * Jumps from 'call' trace events are also forbidden.
1665
     * In addition, jumps are forbidden when not tracing,
1666
     * as this is a debugging feature.
1667
     */
1668
0
    int what_event = PyThreadState_GET()->what_event;
1669
0
    if (what_event < 0) {
1670
0
        PyErr_Format(PyExc_ValueError,
1671
0
                    "f_lineno can only be set in a trace function");
1672
0
        return -1;
1673
0
    }
1674
0
    switch (what_event) {
1675
0
        case PY_MONITORING_EVENT_PY_RESUME:
1676
0
        case PY_MONITORING_EVENT_JUMP:
1677
0
        case PY_MONITORING_EVENT_BRANCH:
1678
0
        case PY_MONITORING_EVENT_LINE:
1679
0
        case PY_MONITORING_EVENT_PY_YIELD:
1680
            /* Setting f_lineno is allowed for the above events */
1681
0
            break;
1682
0
        case PY_MONITORING_EVENT_PY_START:
1683
0
            PyErr_Format(PyExc_ValueError,
1684
0
                     "can't jump from the 'call' trace event of a new frame");
1685
0
            return -1;
1686
0
        case PY_MONITORING_EVENT_CALL:
1687
0
        case PY_MONITORING_EVENT_C_RETURN:
1688
0
            PyErr_SetString(PyExc_ValueError,
1689
0
                "can't jump during a call");
1690
0
            return -1;
1691
0
        case PY_MONITORING_EVENT_PY_RETURN:
1692
0
        case PY_MONITORING_EVENT_PY_UNWIND:
1693
0
        case PY_MONITORING_EVENT_PY_THROW:
1694
0
        case PY_MONITORING_EVENT_RAISE:
1695
0
        case PY_MONITORING_EVENT_C_RAISE:
1696
0
        case PY_MONITORING_EVENT_INSTRUCTION:
1697
0
        case PY_MONITORING_EVENT_EXCEPTION_HANDLED:
1698
0
            PyErr_Format(PyExc_ValueError,
1699
0
                "can only jump from a 'line' trace event");
1700
0
            return -1;
1701
0
        default:
1702
0
            PyErr_SetString(PyExc_SystemError,
1703
0
                "unexpected event type");
1704
0
            return -1;
1705
0
    }
1706
1707
0
    int new_lineno;
1708
1709
    /* Fail if the line falls outside the code block and
1710
        select first line with actual code. */
1711
0
    int overflow;
1712
0
    long l_new_lineno = PyLong_AsLongAndOverflow(value, &overflow);
1713
0
    if (overflow
1714
0
#if SIZEOF_LONG > SIZEOF_INT
1715
0
        || l_new_lineno > INT_MAX
1716
0
        || l_new_lineno < INT_MIN
1717
0
#endif
1718
0
    ) {
1719
0
        PyErr_SetString(PyExc_ValueError,
1720
0
                        "lineno out of range");
1721
0
        return -1;
1722
0
    }
1723
0
    new_lineno = (int)l_new_lineno;
1724
1725
0
    if (new_lineno < code->co_firstlineno) {
1726
0
        PyErr_Format(PyExc_ValueError,
1727
0
                    "line %d comes before the current code block",
1728
0
                    new_lineno);
1729
0
        return -1;
1730
0
    }
1731
1732
    /* PyCode_NewWithPosOnlyArgs limits co_code to be under INT_MAX so this
1733
     * should never overflow. */
1734
0
    int len = (int)Py_SIZE(code);
1735
0
    int *lines = marklines(code, len);
1736
0
    if (lines == NULL) {
1737
0
        return -1;
1738
0
    }
1739
1740
0
    new_lineno = first_line_not_before(lines, len, new_lineno);
1741
0
    if (new_lineno < 0) {
1742
0
        PyErr_Format(PyExc_ValueError,
1743
0
                    "line %d comes after the current code block",
1744
0
                    (int)l_new_lineno);
1745
0
        PyMem_Free(lines);
1746
0
        return -1;
1747
0
    }
1748
1749
0
    int64_t *stacks = mark_stacks(code, len);
1750
0
    if (stacks == NULL) {
1751
0
        PyMem_Free(lines);
1752
0
        return -1;
1753
0
    }
1754
1755
0
    int64_t best_stack = OVERFLOWED;
1756
0
    int best_addr = -1;
1757
0
    int64_t start_stack = stacks[_PyInterpreterFrame_LASTI(self->f_frame)];
1758
0
    int err = -1;
1759
0
    const char *msg = "cannot find bytecode for specified line";
1760
0
    for (int i = 0; i < len; i++) {
1761
0
        if (lines[i] == new_lineno) {
1762
0
            int64_t target_stack = stacks[i];
1763
0
            if (compatible_stack(start_stack, target_stack)) {
1764
0
                err = 0;
1765
0
                if (target_stack > best_stack) {
1766
0
                    best_stack = target_stack;
1767
0
                    best_addr = i;
1768
0
                }
1769
0
            }
1770
0
            else if (err < 0) {
1771
0
                if (start_stack == OVERFLOWED) {
1772
0
                    msg = "stack to deep to analyze";
1773
0
                }
1774
0
                else if (start_stack == UNINITIALIZED) {
1775
0
                    msg = "can't jump from unreachable code";
1776
0
                }
1777
0
                else {
1778
0
                    msg = explain_incompatible_stack(target_stack);
1779
0
                    err = 1;
1780
0
                }
1781
0
            }
1782
0
        }
1783
0
    }
1784
0
    PyMem_Free(stacks);
1785
0
    PyMem_Free(lines);
1786
0
    if (err) {
1787
0
        PyErr_SetString(PyExc_ValueError, msg);
1788
0
        return -1;
1789
0
    }
1790
    // Populate any NULL locals that the compiler might have "proven" to exist
1791
    // in the new location. Rather than crashing or changing co_code, just bind
1792
    // None instead:
1793
0
    int unbound = 0;
1794
0
    for (int i = 0; i < code->co_nlocalsplus; i++) {
1795
        // Counting every unbound local is overly-cautious, but a full flow
1796
        // analysis (like we do in the compiler) is probably too expensive:
1797
0
        unbound += PyStackRef_IsNull(self->f_frame->localsplus[i]);
1798
0
    }
1799
0
    if (unbound) {
1800
0
        const char *e = "assigning None to %d unbound local%s";
1801
0
        const char *s = (unbound == 1) ? "" : "s";
1802
0
        if (PyErr_WarnFormat(PyExc_RuntimeWarning, 0, e, unbound, s)) {
1803
0
            return -1;
1804
0
        }
1805
        // Do this in a second pass to avoid writing a bunch of Nones when
1806
        // warnings are being treated as errors and the previous bit raises:
1807
0
        for (int i = 0; i < code->co_nlocalsplus; i++) {
1808
0
            if (PyStackRef_IsNull(self->f_frame->localsplus[i])) {
1809
0
                self->f_frame->localsplus[i] = PyStackRef_None;
1810
0
                unbound--;
1811
0
            }
1812
0
        }
1813
0
        assert(unbound == 0);
1814
0
    }
1815
0
    if (is_suspended) {
1816
        /* Account for value popped by yield */
1817
0
        start_stack = pop_value(start_stack);
1818
0
    }
1819
0
    while (start_stack > best_stack) {
1820
0
        _PyStackRef popped = _PyFrame_StackPop(self->f_frame);
1821
0
        if (top_of_stack(start_stack) == Except) {
1822
            /* Pop exception stack as well as the evaluation stack */
1823
0
            PyObject *exc = PyStackRef_AsPyObjectBorrow(popped);
1824
0
            assert(PyExceptionInstance_Check(exc) || exc == Py_None);
1825
0
            PyThreadState *tstate = _PyThreadState_GET();
1826
0
            Py_XSETREF(tstate->exc_info->exc_value, exc == Py_None ? NULL : exc);
1827
0
        }
1828
0
        else {
1829
0
            PyStackRef_XCLOSE(popped);
1830
0
        }
1831
0
        start_stack = pop_value(start_stack);
1832
0
    }
1833
    /* Finally set the new lasti and return OK. */
1834
0
    self->f_lineno = 0;
1835
0
    self->f_frame->instr_ptr = _PyFrame_GetBytecode(self->f_frame) + best_addr;
1836
0
    return 0;
1837
0
}
1838
1839
/*[clinic input]
1840
@critical_section
1841
@getter
1842
frame.f_trace as frame_trace
1843
1844
Return the trace function for this frame, or None if no trace function is set.
1845
[clinic start generated code]*/
1846
1847
static PyObject *
1848
frame_trace_get_impl(PyFrameObject *self)
1849
/*[clinic end generated code: output=5475cbfce07826cd input=f382612525829773]*/
1850
0
{
1851
0
    PyObject* trace = self->f_trace;
1852
0
    if (trace == NULL) {
1853
0
        trace = Py_None;
1854
0
    }
1855
0
    return Py_NewRef(trace);
1856
0
}
1857
1858
/*[clinic input]
1859
@critical_section
1860
@setter
1861
frame.f_trace as frame_trace
1862
[clinic start generated code]*/
1863
1864
static int
1865
frame_trace_set_impl(PyFrameObject *self, PyObject *value)
1866
/*[clinic end generated code: output=d6fe08335cf76ae4 input=d96a18bda085707f]*/
1867
0
{
1868
0
    if (value == Py_None) {
1869
0
        value = NULL;
1870
0
    }
1871
0
    if (value != self->f_trace) {
1872
0
        Py_XSETREF(self->f_trace, Py_XNewRef(value));
1873
0
        if (value != NULL && self->f_trace_opcodes) {
1874
0
            return _PyEval_SetOpcodeTrace(self, true);
1875
0
        }
1876
0
    }
1877
0
    return 0;
1878
0
}
1879
1880
/*[clinic input]
1881
@critical_section
1882
@getter
1883
frame.f_generator as frame_generator
1884
1885
Return the generator or coroutine associated with this frame, or None.
1886
[clinic start generated code]*/
1887
1888
static PyObject *
1889
frame_generator_get_impl(PyFrameObject *self)
1890
/*[clinic end generated code: output=97aeb2392562e55b input=00a2bd008b239ab0]*/
1891
0
{
1892
0
    if (self->f_frame->owner == FRAME_OWNED_BY_GENERATOR) {
1893
0
        PyObject *gen = (PyObject *)_PyGen_GetGeneratorFromFrame(self->f_frame);
1894
0
        return Py_NewRef(gen);
1895
0
    }
1896
0
    Py_RETURN_NONE;
1897
0
}
1898
1899
1900
static PyGetSetDef frame_getsetlist[] = {
1901
    FRAME_BACK_GETSETDEF
1902
    FRAME_LOCALS_GETSETDEF
1903
    FRAME_LINENO_GETSETDEF
1904
    FRAME_TRACE_GETSETDEF
1905
    FRAME_LASTI_GETSETDEF
1906
    FRAME_GLOBALS_GETSETDEF
1907
    FRAME_BUILTINS_GETSETDEF
1908
    FRAME_CODE_GETSETDEF
1909
    FRAME_TRACE_OPCODES_GETSETDEF
1910
    FRAME_GENERATOR_GETSETDEF
1911
    {0}
1912
};
1913
1914
static void
1915
frame_dealloc(PyObject *op)
1916
27.3M
{
1917
    /* It is the responsibility of the owning generator/coroutine
1918
     * to have cleared the generator pointer */
1919
27.3M
    PyFrameObject *f = PyFrameObject_CAST(op);
1920
27.3M
    if (_PyObject_GC_IS_TRACKED(f)) {
1921
13.3M
        _PyObject_GC_UNTRACK(f);
1922
13.3M
    }
1923
1924
    /* GH-106092: If f->f_frame was on the stack and we reached the maximum
1925
     * nesting depth for deallocations, the trashcan may have delayed this
1926
     * deallocation until after f->f_frame is freed. Avoid dereferencing
1927
     * f->f_frame unless we know it still points to valid memory. */
1928
27.3M
    _PyInterpreterFrame *frame = (_PyInterpreterFrame *)f->_f_frame_data;
1929
1930
    /* Kill all local variables including specials, if we own them */
1931
27.3M
    if (f->f_frame == frame && frame->owner == FRAME_OWNED_BY_FRAME_OBJECT) {
1932
13.3M
        PyStackRef_CLEAR(frame->f_executable);
1933
13.3M
        PyStackRef_CLEAR(frame->f_funcobj);
1934
13.3M
        Py_CLEAR(frame->f_locals);
1935
13.3M
        _PyStackRef *locals = _PyFrame_GetLocalsArray(frame);
1936
13.3M
        _PyStackRef *sp = frame->stackpointer;
1937
45.6M
        while (sp > locals) {
1938
32.2M
            sp--;
1939
32.2M
            PyStackRef_CLEAR(*sp);
1940
32.2M
        }
1941
13.3M
    }
1942
27.3M
    Py_CLEAR(f->f_back);
1943
27.3M
    Py_CLEAR(f->f_trace);
1944
27.3M
    Py_CLEAR(f->f_extra_locals);
1945
27.3M
    Py_CLEAR(f->f_locals_cache);
1946
27.3M
    Py_CLEAR(f->f_overwritten_fast_locals);
1947
27.3M
    PyObject_GC_Del(f);
1948
27.3M
}
1949
1950
static int
1951
frame_traverse(PyObject *op, visitproc visit, void *arg)
1952
121k
{
1953
121k
    PyFrameObject *f = PyFrameObject_CAST(op);
1954
121k
    Py_VISIT(f->f_back);
1955
121k
    Py_VISIT(f->f_trace);
1956
121k
    Py_VISIT(f->f_extra_locals);
1957
121k
    Py_VISIT(f->f_locals_cache);
1958
121k
    Py_VISIT(f->f_overwritten_fast_locals);
1959
121k
    if (f->f_frame->owner != FRAME_OWNED_BY_FRAME_OBJECT) {
1960
0
        return 0;
1961
0
    }
1962
121k
    assert(f->f_frame->frame_obj == NULL);
1963
121k
    return _PyFrame_Traverse(f->f_frame, visit, arg);
1964
121k
}
1965
1966
static int
1967
frame_tp_clear(PyObject *op)
1968
0
{
1969
0
    PyFrameObject *f = PyFrameObject_CAST(op);
1970
0
    Py_CLEAR(f->f_trace);
1971
0
    Py_CLEAR(f->f_extra_locals);
1972
0
    Py_CLEAR(f->f_locals_cache);
1973
0
    Py_CLEAR(f->f_overwritten_fast_locals);
1974
1975
    /* locals and stack */
1976
0
    _PyStackRef *locals = _PyFrame_GetLocalsArray(f->f_frame);
1977
0
    _PyStackRef *sp = f->f_frame->stackpointer;
1978
0
    assert(sp >= locals);
1979
0
    while (sp > locals) {
1980
0
        sp--;
1981
0
        PyStackRef_CLEAR(*sp);
1982
0
    }
1983
0
    f->f_frame->stackpointer = locals;
1984
0
    Py_CLEAR(f->f_frame->f_locals);
1985
0
    return 0;
1986
0
}
1987
1988
/*[clinic input]
1989
@critical_section
1990
frame.clear
1991
1992
Clear all references held by the frame.
1993
[clinic start generated code]*/
1994
1995
static PyObject *
1996
frame_clear_impl(PyFrameObject *self)
1997
/*[clinic end generated code: output=864c662f16e9bfcc input=c358f9cff5f9b681]*/
1998
0
{
1999
0
    if (self->f_frame->owner == FRAME_OWNED_BY_GENERATOR) {
2000
0
        PyGenObject *gen = _PyGen_GetGeneratorFromFrame(self->f_frame);
2001
0
        if (gen->gi_frame_state == FRAME_EXECUTING) {
2002
0
            goto running;
2003
0
        }
2004
0
        if (FRAME_STATE_SUSPENDED(gen->gi_frame_state)) {
2005
0
            goto suspended;
2006
0
        }
2007
0
        _PyGen_Finalize((PyObject *)gen);
2008
0
    }
2009
0
    else if (self->f_frame->owner == FRAME_OWNED_BY_THREAD) {
2010
0
        goto running;
2011
0
    }
2012
0
    else {
2013
0
        assert(self->f_frame->owner == FRAME_OWNED_BY_FRAME_OBJECT);
2014
0
        (void)frame_tp_clear((PyObject *)self);
2015
0
    }
2016
0
    Py_RETURN_NONE;
2017
0
running:
2018
0
    PyErr_SetString(PyExc_RuntimeError,
2019
0
                    "cannot clear an executing frame");
2020
0
    return NULL;
2021
0
suspended:
2022
0
    PyErr_SetString(PyExc_RuntimeError,
2023
0
                    "cannot clear a suspended frame");
2024
0
    return NULL;
2025
0
}
2026
2027
/*[clinic input]
2028
@critical_section
2029
frame.__sizeof__
2030
2031
Return the size of the frame in memory, in bytes.
2032
[clinic start generated code]*/
2033
2034
static PyObject *
2035
frame___sizeof___impl(PyFrameObject *self)
2036
/*[clinic end generated code: output=82948688e81078e2 input=908f90a83e73131d]*/
2037
0
{
2038
0
    Py_ssize_t res;
2039
0
    res = offsetof(PyFrameObject, _f_frame_data) + offsetof(_PyInterpreterFrame, localsplus);
2040
0
    PyCodeObject *code = _PyFrame_GetCode(self->f_frame);
2041
0
    res += _PyFrame_NumSlotsForCodeObject(code) * sizeof(PyObject *);
2042
0
    return PyLong_FromSsize_t(res);
2043
0
}
2044
2045
static PyObject *
2046
frame_repr(PyObject *op)
2047
0
{
2048
0
    PyFrameObject *f = PyFrameObject_CAST(op);
2049
0
    int lineno = PyFrame_GetLineNumber(f);
2050
0
    PyCodeObject *code = _PyFrame_GetCode(f->f_frame);
2051
0
    return PyUnicode_FromFormat(
2052
0
        "<frame at %p, file %R, line %d, code %S>",
2053
0
        f, code->co_filename, lineno, code->co_name);
2054
0
}
2055
2056
static PyMethodDef frame_methods[] = {
2057
    FRAME_CLEAR_METHODDEF
2058
    FRAME___SIZEOF___METHODDEF
2059
    {NULL, NULL}  /* sentinel */
2060
};
2061
2062
PyTypeObject PyFrame_Type = {
2063
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2064
    "frame",
2065
    offsetof(PyFrameObject, _f_frame_data) +
2066
    offsetof(_PyInterpreterFrame, localsplus),
2067
    sizeof(PyObject *),
2068
    frame_dealloc,                              /* tp_dealloc */
2069
    0,                                          /* tp_vectorcall_offset */
2070
    0,                                          /* tp_getattr */
2071
    0,                                          /* tp_setattr */
2072
    0,                                          /* tp_as_async */
2073
    frame_repr,                                 /* tp_repr */
2074
    0,                                          /* tp_as_number */
2075
    0,                                          /* tp_as_sequence */
2076
    0,                                          /* tp_as_mapping */
2077
    0,                                          /* tp_hash */
2078
    0,                                          /* tp_call */
2079
    0,                                          /* tp_str */
2080
    PyObject_GenericGetAttr,                    /* tp_getattro */
2081
    PyObject_GenericSetAttr,                    /* tp_setattro */
2082
    0,                                          /* tp_as_buffer */
2083
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
2084
    0,                                          /* tp_doc */
2085
    frame_traverse,                             /* tp_traverse */
2086
    frame_tp_clear,                             /* tp_clear */
2087
    0,                                          /* tp_richcompare */
2088
    0,                                          /* tp_weaklistoffset */
2089
    0,                                          /* tp_iter */
2090
    0,                                          /* tp_iternext */
2091
    frame_methods,                              /* tp_methods */
2092
    frame_memberlist,                           /* tp_members */
2093
    frame_getsetlist,                           /* tp_getset */
2094
    0,                                          /* tp_base */
2095
    0,                                          /* tp_dict */
2096
};
2097
2098
static void
2099
init_frame(PyThreadState *tstate, _PyInterpreterFrame *frame,
2100
           PyFunctionObject *func, PyObject *locals)
2101
0
{
2102
0
    PyCodeObject *code = (PyCodeObject *)func->func_code;
2103
0
    _PyFrame_Initialize(tstate, frame, PyStackRef_FromPyObjectNew(func),
2104
0
                        Py_XNewRef(locals), code, 0, NULL);
2105
0
}
2106
2107
PyFrameObject*
2108
_PyFrame_New_NoTrack(PyCodeObject *code)
2109
27.3M
{
2110
27.3M
    CALL_STAT_INC(frame_objects_created);
2111
27.3M
    int slots = code->co_nlocalsplus + code->co_stacksize;
2112
27.3M
    PyFrameObject *f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, slots);
2113
27.3M
    if (f == NULL) {
2114
0
        return NULL;
2115
0
    }
2116
27.3M
    f->f_back = NULL;
2117
27.3M
    f->f_trace = NULL;
2118
27.3M
    f->f_trace_lines = 1;
2119
27.3M
    f->f_trace_opcodes = 0;
2120
27.3M
    f->f_lineno = 0;
2121
27.3M
    f->f_extra_locals = NULL;
2122
27.3M
    f->f_locals_cache = NULL;
2123
27.3M
    f->f_overwritten_fast_locals = NULL;
2124
27.3M
    return f;
2125
27.3M
}
2126
2127
/* Legacy API */
2128
PyFrameObject*
2129
PyFrame_New(PyThreadState *tstate, PyCodeObject *code,
2130
            PyObject *globals, PyObject *locals)
2131
0
{
2132
0
    PyObject *builtins = _PyDict_LoadBuiltinsFromGlobals(globals);
2133
0
    if (builtins == NULL) {
2134
0
        return NULL;
2135
0
    }
2136
0
    PyFrameConstructor desc = {
2137
0
        .fc_globals = globals,
2138
0
        .fc_builtins = builtins,
2139
0
        .fc_name = code->co_name,
2140
0
        .fc_qualname = code->co_name,
2141
0
        .fc_code = (PyObject *)code,
2142
0
        .fc_defaults = NULL,
2143
0
        .fc_kwdefaults = NULL,
2144
0
        .fc_closure = NULL
2145
0
    };
2146
0
    PyFunctionObject *func = _PyFunction_FromConstructor(&desc);
2147
0
    _Py_DECREF_BUILTINS(builtins);
2148
0
    if (func == NULL) {
2149
0
        return NULL;
2150
0
    }
2151
0
    PyFrameObject *f = _PyFrame_New_NoTrack(code);
2152
0
    if (f == NULL) {
2153
0
        Py_DECREF(func);
2154
0
        return NULL;
2155
0
    }
2156
0
    init_frame(tstate, (_PyInterpreterFrame *)f->_f_frame_data, func, locals);
2157
0
    f->f_frame = (_PyInterpreterFrame *)f->_f_frame_data;
2158
0
    f->f_frame->owner = FRAME_OWNED_BY_FRAME_OBJECT;
2159
    // This frame needs to be "complete", so pretend that the first RESUME ran:
2160
0
    f->f_frame->instr_ptr = _PyCode_CODE(code) + code->_co_firsttraceable + 1;
2161
0
    assert(!_PyFrame_IsIncomplete(f->f_frame));
2162
0
    Py_DECREF(func);
2163
0
    _PyObject_GC_TRACK(f);
2164
0
    return f;
2165
0
}
2166
2167
// Initialize frame free variables if needed
2168
static void
2169
frame_init_get_vars(_PyInterpreterFrame *frame)
2170
0
{
2171
    // COPY_FREE_VARS has no quickened forms, so no need to use _PyOpcode_Deopt
2172
    // here:
2173
0
    PyCodeObject *co = _PyFrame_GetCode(frame);
2174
0
    int lasti = _PyInterpreterFrame_LASTI(frame);
2175
0
    if (!(lasti < 0
2176
0
          && _PyFrame_GetBytecode(frame)->op.code == COPY_FREE_VARS
2177
0
          && PyStackRef_FunctionCheck(frame->f_funcobj)))
2178
0
    {
2179
        /* Free vars are initialized */
2180
0
        return;
2181
0
    }
2182
2183
    /* Free vars have not been initialized -- Do that */
2184
0
    PyFunctionObject *func = _PyFrame_GetFunction(frame);
2185
0
    PyObject *closure = func->func_closure;
2186
0
    int offset = PyUnstable_Code_GetFirstFree(co);
2187
0
    for (int i = 0; i < co->co_nfreevars; ++i) {
2188
0
        PyObject *o = PyTuple_GET_ITEM(closure, i);
2189
0
        frame->localsplus[offset + i] = PyStackRef_FromPyObjectNew(o);
2190
0
    }
2191
    // COPY_FREE_VARS doesn't have inline CACHEs, either:
2192
0
    frame->instr_ptr = _PyFrame_GetBytecode(frame);
2193
0
}
2194
2195
2196
static int
2197
frame_get_var(_PyInterpreterFrame *frame, PyCodeObject *co, int i,
2198
              PyObject **pvalue)
2199
0
{
2200
0
    _PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
2201
2202
    /* If the namespace is unoptimized, then one of the
2203
       following cases applies:
2204
       1. It does not contain free variables, because it
2205
          uses import * or is a top-level namespace.
2206
       2. It is a class namespace.
2207
       We don't want to accidentally copy free variables
2208
       into the locals dict used by the class.
2209
    */
2210
0
    if (kind & CO_FAST_FREE && !(co->co_flags & CO_OPTIMIZED)) {
2211
0
        return 0;
2212
0
    }
2213
2214
0
    PyObject *value = NULL;
2215
0
    if (frame->stackpointer == NULL || frame->stackpointer > frame->localsplus + i) {
2216
0
        value = PyStackRef_AsPyObjectBorrow(frame->localsplus[i]);
2217
0
        if (kind & CO_FAST_FREE) {
2218
            // The cell was set by COPY_FREE_VARS.
2219
0
            assert(value != NULL && PyCell_Check(value));
2220
0
            value = PyCell_GetRef((PyCellObject *)value);
2221
0
        }
2222
0
        else if (kind & CO_FAST_CELL) {
2223
0
            if (value != NULL) {
2224
0
                if (PyCell_Check(value)) {
2225
0
                    assert(!_PyFrame_IsIncomplete(frame));
2226
0
                    value = PyCell_GetRef((PyCellObject *)value);
2227
0
                }
2228
0
                else {
2229
                    // (likely) Otherwise it is an arg (kind & CO_FAST_LOCAL),
2230
                    // with the initial value set when the frame was created...
2231
                    // (unlikely) ...or it was set via the f_locals proxy.
2232
0
                    Py_INCREF(value);
2233
0
                }
2234
0
            }
2235
0
        }
2236
0
        else {
2237
0
            Py_XINCREF(value);
2238
0
        }
2239
0
    }
2240
0
    *pvalue = value;
2241
0
    return 1;
2242
0
}
2243
2244
2245
bool
2246
_PyFrame_HasHiddenLocals(_PyInterpreterFrame *frame)
2247
136
{
2248
    /*
2249
     * This function returns if there are hidden locals introduced by PEP 709,
2250
     * which are the isolated fast locals for inline comprehensions
2251
     */
2252
136
    PyCodeObject* co = _PyFrame_GetCode(frame);
2253
2254
150
    for (int i = 0; i < co->co_nlocalsplus; i++) {
2255
14
        _PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
2256
2257
14
        if (kind & CO_FAST_HIDDEN) {
2258
14
            if (framelocalsproxy_hasval(frame, co, i)) {
2259
0
                return true;
2260
0
            }
2261
14
        }
2262
14
    }
2263
2264
136
    return false;
2265
136
}
2266
2267
2268
PyObject *
2269
_PyFrame_GetLocals(_PyInterpreterFrame *frame)
2270
136
{
2271
    // We should try to avoid creating the FrameObject if possible.
2272
    // So we check if the frame is a module or class level scope
2273
136
    PyCodeObject *co = _PyFrame_GetCode(frame);
2274
2275
136
    if (!(co->co_flags & CO_OPTIMIZED) && !_PyFrame_HasHiddenLocals(frame)) {
2276
136
        if (frame->f_locals == NULL) {
2277
            // We found cases when f_locals is NULL for non-optimized code.
2278
            // We fill the f_locals with an empty dict to avoid crash until
2279
            // we find the root cause.
2280
0
            frame->f_locals = PyDict_New();
2281
0
            if (frame->f_locals == NULL) {
2282
0
                return NULL;
2283
0
            }
2284
0
        }
2285
136
        return Py_NewRef(frame->f_locals);
2286
136
    }
2287
2288
0
    PyFrameObject* f = _PyFrame_GetFrameObject(frame);
2289
2290
0
    return _PyFrameLocalsProxy_New(f);
2291
136
}
2292
2293
2294
PyObject *
2295
PyFrame_GetVar(PyFrameObject *frame_obj, PyObject *name)
2296
0
{
2297
0
    if (!PyUnicode_Check(name)) {
2298
0
        PyErr_Format(PyExc_TypeError, "name must be str, not %s",
2299
0
                     Py_TYPE(name)->tp_name);
2300
0
        return NULL;
2301
0
    }
2302
2303
0
    _PyInterpreterFrame *frame = frame_obj->f_frame;
2304
0
    frame_init_get_vars(frame);
2305
2306
0
    PyCodeObject *co = _PyFrame_GetCode(frame);
2307
0
    for (int i = 0; i < co->co_nlocalsplus; i++) {
2308
0
        PyObject *var_name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
2309
0
        if (!_PyUnicode_Equal(var_name, name)) {
2310
0
            continue;
2311
0
        }
2312
2313
0
        PyObject *value;
2314
0
        if (!frame_get_var(frame, co, i, &value)) {
2315
0
            break;
2316
0
        }
2317
0
        if (value == NULL) {
2318
0
            break;
2319
0
        }
2320
0
        return value;
2321
0
    }
2322
2323
0
    PyErr_Format(PyExc_NameError, "variable %R does not exist", name);
2324
0
    return NULL;
2325
0
}
2326
2327
2328
PyObject *
2329
PyFrame_GetVarString(PyFrameObject *frame, const char *name)
2330
0
{
2331
0
    PyObject *name_obj = PyUnicode_FromString(name);
2332
0
    if (name_obj == NULL) {
2333
0
        return NULL;
2334
0
    }
2335
0
    PyObject *value = PyFrame_GetVar(frame, name_obj);
2336
0
    Py_DECREF(name_obj);
2337
0
    return value;
2338
0
}
2339
2340
2341
int
2342
PyFrame_FastToLocalsWithError(PyFrameObject *f)
2343
0
{
2344
    // Nothing to do here, as f_locals is now a write-through proxy in
2345
    // optimized frames. Soft-deprecated, since there's no maintenance hassle.
2346
0
    return 0;
2347
0
}
2348
2349
void
2350
PyFrame_FastToLocals(PyFrameObject *f)
2351
0
{
2352
    // Nothing to do here, as f_locals is now a write-through proxy in
2353
    // optimized frames. Soft-deprecated, since there's no maintenance hassle.
2354
0
    return;
2355
0
}
2356
2357
void
2358
PyFrame_LocalsToFast(PyFrameObject *f, int clear)
2359
0
{
2360
    // Nothing to do here, as f_locals is now a write-through proxy in
2361
    // optimized frames. Soft-deprecated, since there's no maintenance hassle.
2362
0
    return;
2363
0
}
2364
2365
int
2366
_PyFrame_IsEntryFrame(PyFrameObject *frame)
2367
0
{
2368
0
    assert(frame != NULL);
2369
0
    _PyInterpreterFrame *f = frame->f_frame;
2370
0
    assert(!_PyFrame_IsIncomplete(f));
2371
0
    return f->previous && f->previous->owner == FRAME_OWNED_BY_INTERPRETER;
2372
0
}
2373
2374
PyCodeObject *
2375
PyFrame_GetCode(PyFrameObject *frame)
2376
5.44k
{
2377
5.44k
    assert(frame != NULL);
2378
5.44k
    PyObject *code;
2379
5.44k
    Py_BEGIN_CRITICAL_SECTION(frame);
2380
5.44k
    assert(!_PyFrame_IsIncomplete(frame->f_frame));
2381
5.44k
    code = Py_NewRef(_PyFrame_GetCode(frame->f_frame));
2382
5.44k
    Py_END_CRITICAL_SECTION();
2383
5.44k
    return (PyCodeObject *)code;
2384
5.44k
}
2385
2386
2387
PyFrameObject*
2388
PyFrame_GetBack(PyFrameObject *frame)
2389
0
{
2390
0
    assert(frame != NULL);
2391
0
    assert(!_PyFrame_IsIncomplete(frame->f_frame));
2392
0
    PyFrameObject *back = frame->f_back;
2393
0
    if (back == NULL) {
2394
0
        _PyInterpreterFrame *prev = frame->f_frame->previous;
2395
0
        prev = _PyFrame_GetFirstComplete(prev);
2396
0
        if (prev) {
2397
0
            back = _PyFrame_GetFrameObject(prev);
2398
0
        }
2399
0
    }
2400
0
    return (PyFrameObject*)Py_XNewRef(back);
2401
0
}
2402
2403
PyObject*
2404
PyFrame_GetLocals(PyFrameObject *frame)
2405
0
{
2406
0
    assert(!_PyFrame_IsIncomplete(frame->f_frame));
2407
0
    return frame_locals_get((PyObject *)frame, NULL);
2408
0
}
2409
2410
PyObject*
2411
PyFrame_GetGlobals(PyFrameObject *frame)
2412
0
{
2413
0
    assert(!_PyFrame_IsIncomplete(frame->f_frame));
2414
0
    return frame_globals_get((PyObject *)frame, NULL);
2415
0
}
2416
2417
PyObject*
2418
PyFrame_GetBuiltins(PyFrameObject *frame)
2419
0
{
2420
0
    assert(!_PyFrame_IsIncomplete(frame->f_frame));
2421
0
    return frame_builtins_get((PyObject *)frame, NULL);
2422
0
}
2423
2424
int
2425
PyFrame_GetLasti(PyFrameObject *frame)
2426
0
{
2427
0
    int ret;
2428
0
    Py_BEGIN_CRITICAL_SECTION(frame);
2429
0
    assert(!_PyFrame_IsIncomplete(frame->f_frame));
2430
0
    int lasti = _PyInterpreterFrame_LASTI(frame->f_frame);
2431
0
    ret = lasti < 0 ? -1 : lasti * (int)sizeof(_Py_CODEUNIT);
2432
0
    Py_END_CRITICAL_SECTION();
2433
0
    return ret;
2434
0
}
2435
2436
PyObject *
2437
PyFrame_GetGenerator(PyFrameObject *frame)
2438
0
{
2439
0
    assert(!_PyFrame_IsIncomplete(frame->f_frame));
2440
0
    return frame_generator_get((PyObject *)frame, NULL);
2441
0
}