Coverage Report

Created: 2026-04-12 06:54

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