Coverage Report

Created: 2026-10-17 06:15

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