LCOV - code coverage report
Current view: top level - Objects - frameobject.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit 5e6661bce9] Lines: 112 688 16.3 %
Date: 2023-03-20 08:15:36 Functions: 14 53 26.4 %
Branches: 51 395 12.9 %

           Branch data     Line data    Source code
       1                 :            : /* Frame object implementation */
       2                 :            : 
       3                 :            : #include "Python.h"
       4                 :            : #include "pycore_ceval.h"         // _PyEval_BuiltinsFromGlobals()
       5                 :            : #include "pycore_code.h"          // CO_FAST_LOCAL, etc.
       6                 :            : #include "pycore_function.h"      // _PyFunction_FromConstructor()
       7                 :            : #include "pycore_moduleobject.h"  // _PyModule_GetDict()
       8                 :            : #include "pycore_object.h"        // _PyObject_GC_UNTRACK()
       9                 :            : #include "pycore_opcode.h"        // _PyOpcode_Caches
      10                 :            : 
      11                 :            : #include "frameobject.h"          // PyFrameObject
      12                 :            : #include "pycore_frame.h"
      13                 :            : #include "opcode.h"               // EXTENDED_ARG
      14                 :            : #include "structmember.h"         // PyMemberDef
      15                 :            : 
      16                 :            : #define OFF(x) offsetof(PyFrameObject, x)
      17                 :            : 
      18                 :            : static PyMemberDef frame_memberlist[] = {
      19                 :            :     {"f_trace_lines",   T_BOOL,         OFF(f_trace_lines), 0},
      20                 :            :     {"f_trace_opcodes", T_BOOL,         OFF(f_trace_opcodes), 0},
      21                 :            :     {NULL}      /* Sentinel */
      22                 :            : };
      23                 :            : 
      24                 :            : 
      25                 :            : static PyObject *
      26                 :          0 : frame_getlocals(PyFrameObject *f, void *closure)
      27                 :            : {
      28         [ #  # ]:          0 :     if (PyFrame_FastToLocalsWithError(f) < 0)
      29                 :          0 :         return NULL;
      30                 :          0 :     PyObject *locals = f->f_frame->f_locals;
      31                 :          0 :     return Py_NewRef(locals);
      32                 :            : }
      33                 :            : 
      34                 :            : int
      35                 :     105273 : PyFrame_GetLineNumber(PyFrameObject *f)
      36                 :            : {
      37                 :            :     assert(f != NULL);
      38         [ -  + ]:     105273 :     if (f->f_lineno != 0) {
      39                 :          0 :         return f->f_lineno;
      40                 :            :     }
      41                 :            :     else {
      42                 :     105273 :         return _PyInterpreterFrame_GetLine(f->f_frame);
      43                 :            :     }
      44                 :            : }
      45                 :            : 
      46                 :            : static PyObject *
      47                 :          0 : frame_getlineno(PyFrameObject *f, void *closure)
      48                 :            : {
      49                 :          0 :     int lineno = PyFrame_GetLineNumber(f);
      50         [ #  # ]:          0 :     if (lineno < 0) {
      51                 :          0 :         Py_RETURN_NONE;
      52                 :            :     }
      53                 :            :     else {
      54                 :          0 :         return PyLong_FromLong(lineno);
      55                 :            :     }
      56                 :            : }
      57                 :            : 
      58                 :            : static PyObject *
      59                 :          0 : frame_getlasti(PyFrameObject *f, void *closure)
      60                 :            : {
      61                 :          0 :     int lasti = _PyInterpreterFrame_LASTI(f->f_frame);
      62         [ #  # ]:          0 :     if (lasti < 0) {
      63                 :          0 :         return PyLong_FromLong(-1);
      64                 :            :     }
      65                 :          0 :     return PyLong_FromLong(lasti * sizeof(_Py_CODEUNIT));
      66                 :            : }
      67                 :            : 
      68                 :            : static PyObject *
      69                 :         18 : frame_getglobals(PyFrameObject *f, void *closure)
      70                 :            : {
      71                 :         18 :     PyObject *globals = f->f_frame->f_globals;
      72         [ -  + ]:         18 :     if (globals == NULL) {
      73                 :          0 :         globals = Py_None;
      74                 :            :     }
      75                 :         18 :     return Py_NewRef(globals);
      76                 :            : }
      77                 :            : 
      78                 :            : static PyObject *
      79                 :          0 : frame_getbuiltins(PyFrameObject *f, void *closure)
      80                 :            : {
      81                 :          0 :     PyObject *builtins = f->f_frame->f_builtins;
      82         [ #  # ]:          0 :     if (builtins == NULL) {
      83                 :          0 :         builtins = Py_None;
      84                 :            :     }
      85                 :          0 :     return Py_NewRef(builtins);
      86                 :            : }
      87                 :            : 
      88                 :            : static PyObject *
      89                 :         36 : frame_getcode(PyFrameObject *f, void *closure)
      90                 :            : {
      91         [ -  + ]:         36 :     if (PySys_Audit("object.__getattr__", "Os", f, "f_code") < 0) {
      92                 :          0 :         return NULL;
      93                 :            :     }
      94                 :         36 :     return (PyObject *)PyFrame_GetCode(f);
      95                 :            : }
      96                 :            : 
      97                 :            : static PyObject *
      98                 :          0 : frame_getback(PyFrameObject *f, void *closure)
      99                 :            : {
     100                 :          0 :     PyObject *res = (PyObject *)PyFrame_GetBack(f);
     101         [ #  # ]:          0 :     if (res == NULL) {
     102                 :          0 :         Py_RETURN_NONE;
     103                 :            :     }
     104                 :          0 :     return res;
     105                 :            : }
     106                 :            : 
     107                 :            : // Given the index of the effective opcode, scan back to construct the oparg
     108                 :            : // with EXTENDED_ARG. This only works correctly with *unquickened* code,
     109                 :            : // obtained via a call to _PyCode_GetCode!
     110                 :            : static unsigned int
     111                 :          0 : get_arg(const _Py_CODEUNIT *codestr, Py_ssize_t i)
     112                 :            : {
     113                 :            :     _Py_CODEUNIT word;
     114                 :          0 :     unsigned int oparg = codestr[i].op.arg;
     115   [ #  #  #  # ]:          0 :     if (i >= 1 && (word = codestr[i-1]).op.code == EXTENDED_ARG) {
     116                 :          0 :         oparg |= word.op.arg << 8;
     117   [ #  #  #  # ]:          0 :         if (i >= 2 && (word = codestr[i-2]).op.code == EXTENDED_ARG) {
     118                 :          0 :             oparg |= word.op.arg << 16;
     119   [ #  #  #  # ]:          0 :             if (i >= 3 && (word = codestr[i-3]).op.code == EXTENDED_ARG) {
     120                 :          0 :                 oparg |= word.op.arg << 24;
     121                 :            :             }
     122                 :            :         }
     123                 :            :     }
     124                 :          0 :     return oparg;
     125                 :            : }
     126                 :            : 
     127                 :            : /* Model the evaluation stack, to determine which jumps
     128                 :            :  * are safe and how many values needs to be popped.
     129                 :            :  * The stack is modelled by a 64 integer, treating any
     130                 :            :  * stack that can't fit into 64 bits as "overflowed".
     131                 :            :  */
     132                 :            : 
     133                 :            : typedef enum kind {
     134                 :            :     Iterator = 1,
     135                 :            :     Except = 2,
     136                 :            :     Object = 3,
     137                 :            :     Null = 4,
     138                 :            :     Lasti = 5,
     139                 :            : } Kind;
     140                 :            : 
     141                 :            : static int
     142                 :          0 : compatible_kind(Kind from, Kind to) {
     143         [ #  # ]:          0 :     if (to == 0) {
     144                 :          0 :         return 0;
     145                 :            :     }
     146         [ #  # ]:          0 :     if (to == Object) {
     147                 :          0 :         return from != Null;
     148                 :            :     }
     149         [ #  # ]:          0 :     if (to == Null) {
     150                 :          0 :         return 1;
     151                 :            :     }
     152                 :          0 :     return from == to;
     153                 :            : }
     154                 :            : 
     155                 :            : #define BITS_PER_BLOCK 3
     156                 :            : 
     157                 :            : #define UNINITIALIZED -2
     158                 :            : #define OVERFLOWED -1
     159                 :            : 
     160                 :            : #define MAX_STACK_ENTRIES (63/BITS_PER_BLOCK)
     161                 :            : #define WILL_OVERFLOW (1ULL<<((MAX_STACK_ENTRIES-1)*BITS_PER_BLOCK))
     162                 :            : 
     163                 :            : #define EMPTY_STACK 0
     164                 :            : 
     165                 :            : static inline int64_t
     166                 :          0 : push_value(int64_t stack, Kind kind)
     167                 :            : {
     168         [ #  # ]:          0 :     if (((uint64_t)stack) >= WILL_OVERFLOW) {
     169                 :          0 :         return OVERFLOWED;
     170                 :            :     }
     171                 :            :     else {
     172                 :          0 :         return (stack << BITS_PER_BLOCK) | kind;
     173                 :            :     }
     174                 :            : }
     175                 :            : 
     176                 :            : static inline int64_t
     177                 :          0 : pop_value(int64_t stack)
     178                 :            : {
     179                 :          0 :     return Py_ARITHMETIC_RIGHT_SHIFT(int64_t, stack, BITS_PER_BLOCK);
     180                 :            : }
     181                 :            : 
     182                 :            : #define MASK ((1<<BITS_PER_BLOCK)-1)
     183                 :            : 
     184                 :            : static inline Kind
     185                 :          0 : top_of_stack(int64_t stack)
     186                 :            : {
     187                 :          0 :     return stack & MASK;
     188                 :            : }
     189                 :            : 
     190                 :            : static inline Kind
     191                 :          0 : peek(int64_t stack, int n)
     192                 :            : {
     193                 :            :     assert(n >= 1);
     194                 :          0 :     return (stack>>(BITS_PER_BLOCK*(n-1))) & MASK;
     195                 :            : }
     196                 :            : 
     197                 :            : static Kind
     198                 :          0 : stack_swap(int64_t stack, int n)
     199                 :            : {
     200                 :            :     assert(n >= 1);
     201                 :          0 :     Kind to_swap = peek(stack, n);
     202                 :          0 :     Kind top = top_of_stack(stack);
     203                 :          0 :     int shift = BITS_PER_BLOCK*(n-1);
     204                 :          0 :     int64_t replaced_low = (stack & ~(MASK << shift)) | (top << shift);
     205                 :          0 :     int64_t replaced_top = (replaced_low & ~MASK) | to_swap;
     206                 :          0 :     return replaced_top;
     207                 :            : }
     208                 :            : 
     209                 :            : static int64_t
     210                 :          0 : pop_to_level(int64_t stack, int level) {
     211         [ #  # ]:          0 :     if (level == 0) {
     212                 :          0 :         return EMPTY_STACK;
     213                 :            :     }
     214                 :          0 :     int64_t max_item = (1<<BITS_PER_BLOCK) - 1;
     215                 :          0 :     int64_t level_max_stack = max_item << ((level-1) * BITS_PER_BLOCK);
     216         [ #  # ]:          0 :     while (stack > level_max_stack) {
     217                 :          0 :         stack = pop_value(stack);
     218                 :            :     }
     219                 :          0 :     return stack;
     220                 :            : }
     221                 :            : 
     222                 :            : #if 0
     223                 :            : /* These functions are useful for debugging the stack marking code */
     224                 :            : 
     225                 :            : static char
     226                 :            : tos_char(int64_t stack) {
     227                 :            :     switch(top_of_stack(stack)) {
     228                 :            :         case Iterator:
     229                 :            :             return 'I';
     230                 :            :         case Except:
     231                 :            :             return 'E';
     232                 :            :         case Object:
     233                 :            :             return 'O';
     234                 :            :         case Lasti:
     235                 :            :             return 'L';
     236                 :            :         case Null:
     237                 :            :             return 'N';
     238                 :            :     }
     239                 :            :     return '?';
     240                 :            : }
     241                 :            : 
     242                 :            : static void
     243                 :            : print_stack(int64_t stack) {
     244                 :            :     if (stack < 0) {
     245                 :            :         if (stack == UNINITIALIZED) {
     246                 :            :             printf("---");
     247                 :            :         }
     248                 :            :         else if (stack == OVERFLOWED) {
     249                 :            :             printf("OVERFLOWED");
     250                 :            :         }
     251                 :            :         else {
     252                 :            :             printf("??");
     253                 :            :         }
     254                 :            :         return;
     255                 :            :     }
     256                 :            :     while (stack) {
     257                 :            :         printf("%c", tos_char(stack));
     258                 :            :         stack = pop_value(stack);
     259                 :            :     }
     260                 :            : }
     261                 :            : 
     262                 :            : static void
     263                 :            : print_stacks(int64_t *stacks, int n) {
     264                 :            :     for (int i = 0; i < n; i++) {
     265                 :            :         printf("%d: ", i);
     266                 :            :         print_stack(stacks[i]);
     267                 :            :         printf("\n");
     268                 :            :     }
     269                 :            : }
     270                 :            : 
     271                 :            : #endif
     272                 :            : 
     273                 :            : static int64_t *
     274                 :          0 : mark_stacks(PyCodeObject *code_obj, int len)
     275                 :            : {
     276                 :          0 :     PyObject *co_code = _PyCode_GetCode(code_obj);
     277         [ #  # ]:          0 :     if (co_code == NULL) {
     278                 :          0 :         return NULL;
     279                 :            :     }
     280                 :          0 :     _Py_CODEUNIT *code = (_Py_CODEUNIT *)PyBytes_AS_STRING(co_code);
     281         [ #  # ]:          0 :     int64_t *stacks = PyMem_New(int64_t, len+1);
     282                 :            :     int i, j, opcode;
     283                 :            : 
     284         [ #  # ]:          0 :     if (stacks == NULL) {
     285                 :          0 :         PyErr_NoMemory();
     286                 :          0 :         Py_DECREF(co_code);
     287                 :          0 :         return NULL;
     288                 :            :     }
     289         [ #  # ]:          0 :     for (int i = 1; i <= len; i++) {
     290                 :          0 :         stacks[i] = UNINITIALIZED;
     291                 :            :     }
     292                 :          0 :     stacks[0] = EMPTY_STACK;
     293         [ #  # ]:          0 :     if (code_obj->co_flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR))
     294                 :            :     {
     295                 :            :         // Generators get sent None while starting:
     296                 :          0 :         stacks[0] = push_value(stacks[0], Object);
     297                 :            :     }
     298                 :          0 :     int todo = 1;
     299         [ #  # ]:          0 :     while (todo) {
     300                 :          0 :         todo = 0;
     301                 :            :         /* Scan instructions */
     302         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     303                 :          0 :             int64_t next_stack = stacks[i];
     304         [ #  # ]:          0 :             if (next_stack == UNINITIALIZED) {
     305                 :          0 :                 continue;
     306                 :            :             }
     307                 :          0 :             opcode = code[i].op.code;
     308   [ #  #  #  #  :          0 :             switch (opcode) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     309                 :          0 :                 case JUMP_IF_FALSE_OR_POP:
     310                 :            :                 case JUMP_IF_TRUE_OR_POP:
     311                 :            :                 case POP_JUMP_IF_FALSE:
     312                 :            :                 case POP_JUMP_IF_TRUE:
     313                 :            :                 {
     314                 :            :                     int64_t target_stack;
     315                 :          0 :                     int j = get_arg(code, i);
     316                 :          0 :                     j += i + 1;
     317                 :            :                     assert(j < len);
     318   [ #  #  #  # ]:          0 :                     if (stacks[j] == UNINITIALIZED && j < i) {
     319                 :          0 :                         todo = 1;
     320                 :            :                     }
     321   [ #  #  #  # ]:          0 :                     if (opcode == JUMP_IF_FALSE_OR_POP ||
     322                 :            :                         opcode == JUMP_IF_TRUE_OR_POP)
     323                 :            :                     {
     324                 :          0 :                         target_stack = next_stack;
     325                 :          0 :                         next_stack = pop_value(next_stack);
     326                 :            :                     }
     327                 :            :                     else {
     328                 :          0 :                         next_stack = pop_value(next_stack);
     329                 :          0 :                         target_stack = next_stack;
     330                 :            :                     }
     331                 :            :                     assert(stacks[j] == UNINITIALIZED || stacks[j] == target_stack);
     332                 :          0 :                     stacks[j] = target_stack;
     333                 :          0 :                     stacks[i+1] = next_stack;
     334                 :          0 :                     break;
     335                 :            :                 }
     336                 :          0 :                 case SEND:
     337                 :          0 :                     j = get_arg(code, i) + i + INLINE_CACHE_ENTRIES_SEND + 1;
     338                 :            :                     assert(j < len);
     339                 :            :                     assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack);
     340                 :          0 :                     stacks[j] = next_stack;
     341                 :          0 :                     stacks[i+1] = next_stack;
     342                 :          0 :                     break;
     343                 :          0 :                 case JUMP_FORWARD:
     344                 :          0 :                     j = get_arg(code, i) + i + 1;
     345                 :            :                     assert(j < len);
     346                 :            :                     assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack);
     347                 :          0 :                     stacks[j] = next_stack;
     348                 :          0 :                     break;
     349                 :          0 :                 case JUMP_BACKWARD:
     350                 :            :                 case JUMP_BACKWARD_NO_INTERRUPT:
     351                 :          0 :                     j = i + 1 - get_arg(code, i);
     352                 :            :                     assert(j >= 0);
     353                 :            :                     assert(j < len);
     354   [ #  #  #  # ]:          0 :                     if (stacks[j] == UNINITIALIZED && j < i) {
     355                 :          0 :                         todo = 1;
     356                 :            :                     }
     357                 :            :                     assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack);
     358                 :          0 :                     stacks[j] = next_stack;
     359                 :          0 :                     break;
     360                 :          0 :                 case COMPARE_AND_BRANCH:
     361                 :          0 :                     next_stack = pop_value(pop_value(next_stack));
     362                 :          0 :                     i++;
     363                 :          0 :                     j = get_arg(code, i) + i + 1;
     364                 :            :                     assert(j < len);
     365                 :            :                     assert(stacks[j] == UNINITIALIZED || stacks[j] == next_stack);
     366                 :          0 :                     stacks[j] = next_stack;
     367                 :          0 :                     break;
     368                 :          0 :                 case GET_ITER:
     369                 :            :                 case GET_AITER:
     370                 :          0 :                     next_stack = push_value(pop_value(next_stack), Iterator);
     371                 :          0 :                     stacks[i+1] = next_stack;
     372                 :          0 :                     break;
     373                 :          0 :                 case FOR_ITER:
     374                 :            :                 {
     375                 :          0 :                     int64_t target_stack = push_value(next_stack, Object);
     376                 :          0 :                     stacks[i+1] = target_stack;
     377                 :          0 :                     j = get_arg(code, i) + 1 + INLINE_CACHE_ENTRIES_FOR_ITER + i;
     378                 :            :                     assert(j < len);
     379                 :            :                     assert(stacks[j] == UNINITIALIZED || stacks[j] == target_stack);
     380                 :          0 :                     stacks[j] = target_stack;
     381                 :          0 :                     break;
     382                 :            :                 }
     383                 :          0 :                 case END_ASYNC_FOR:
     384                 :          0 :                     next_stack = pop_value(pop_value(next_stack));
     385                 :          0 :                     stacks[i+1] = next_stack;
     386                 :          0 :                     break;
     387                 :          0 :                 case PUSH_EXC_INFO:
     388                 :          0 :                     next_stack = push_value(next_stack, Except);
     389                 :          0 :                     stacks[i+1] = next_stack;
     390                 :          0 :                     break;
     391                 :          0 :                 case POP_EXCEPT:
     392                 :            :                     assert(top_of_stack(next_stack) == Except);
     393                 :          0 :                     next_stack = pop_value(next_stack);
     394                 :          0 :                     stacks[i+1] = next_stack;
     395                 :          0 :                     break;
     396                 :          0 :                 case RETURN_VALUE:
     397                 :            :                     assert(pop_value(next_stack) == EMPTY_STACK);
     398                 :            :                     assert(top_of_stack(next_stack) == Object);
     399                 :          0 :                     break;
     400                 :          0 :                 case RETURN_CONST:
     401                 :          0 :                     break;
     402                 :          0 :                 case RAISE_VARARGS:
     403                 :          0 :                     break;
     404                 :          0 :                 case RERAISE:
     405                 :            :                     assert(top_of_stack(next_stack) == Except);
     406                 :            :                     /* End of block */
     407                 :          0 :                     break;
     408                 :          0 :                 case PUSH_NULL:
     409                 :          0 :                     next_stack = push_value(next_stack, Null);
     410                 :          0 :                     stacks[i+1] = next_stack;
     411                 :          0 :                     break;
     412                 :          0 :                 case LOAD_GLOBAL:
     413                 :            :                 {
     414                 :          0 :                     int j = get_arg(code, i);
     415         [ #  # ]:          0 :                     if (j & 1) {
     416                 :          0 :                         next_stack = push_value(next_stack, Null);
     417                 :            :                     }
     418                 :          0 :                     next_stack = push_value(next_stack, Object);
     419                 :          0 :                     stacks[i+1] = next_stack;
     420                 :          0 :                     break;
     421                 :            :                 }
     422                 :          0 :                 case LOAD_ATTR:
     423                 :            :                 {
     424                 :            :                     assert(top_of_stack(next_stack) == Object);
     425                 :          0 :                     int j = get_arg(code, i);
     426         [ #  # ]:          0 :                     if (j & 1) {
     427                 :          0 :                         next_stack = pop_value(next_stack);
     428                 :          0 :                         next_stack = push_value(next_stack, Null);
     429                 :          0 :                         next_stack = push_value(next_stack, Object);
     430                 :            :                     }
     431                 :          0 :                     stacks[i+1] = next_stack;
     432                 :          0 :                     break;
     433                 :            :                 }
     434                 :          0 :                 case CALL:
     435                 :            :                 {
     436                 :          0 :                     int args = get_arg(code, i);
     437         [ #  # ]:          0 :                     for (int j = 0; j < args+2; j++) {
     438                 :          0 :                         next_stack = pop_value(next_stack);
     439                 :            :                     }
     440                 :          0 :                     next_stack = push_value(next_stack, Object);
     441                 :          0 :                     stacks[i+1] = next_stack;
     442                 :          0 :                     break;
     443                 :            :                 }
     444                 :          0 :                 case SWAP:
     445                 :            :                 {
     446                 :          0 :                     int n = get_arg(code, i);
     447                 :          0 :                     next_stack = stack_swap(next_stack, n);
     448                 :          0 :                     stacks[i+1] = next_stack;
     449                 :          0 :                     break;
     450                 :            :                 }
     451                 :          0 :                 case COPY:
     452                 :            :                 {
     453                 :          0 :                     int n = get_arg(code, i);
     454                 :          0 :                     next_stack = push_value(next_stack, peek(next_stack, n));
     455                 :          0 :                     stacks[i+1] = next_stack;
     456                 :          0 :                     break;
     457                 :            :                 }
     458                 :          0 :                 default:
     459                 :            :                 {
     460                 :          0 :                     int delta = PyCompile_OpcodeStackEffect(opcode, get_arg(code, i));
     461                 :            :                     assert(delta != PY_INVALID_STACK_EFFECT);
     462         [ #  # ]:          0 :                     while (delta < 0) {
     463                 :          0 :                         next_stack = pop_value(next_stack);
     464                 :          0 :                         delta++;
     465                 :            :                     }
     466         [ #  # ]:          0 :                     while (delta > 0) {
     467                 :          0 :                         next_stack = push_value(next_stack, Object);
     468                 :          0 :                         delta--;
     469                 :            :                     }
     470                 :          0 :                     stacks[i+1] = next_stack;
     471                 :            :                 }
     472                 :            :             }
     473                 :            :         }
     474                 :            :         /* Scan exception table */
     475                 :          0 :         unsigned char *start = (unsigned char *)PyBytes_AS_STRING(code_obj->co_exceptiontable);
     476                 :          0 :         unsigned char *end = start + PyBytes_GET_SIZE(code_obj->co_exceptiontable);
     477                 :          0 :         unsigned char *scan = start;
     478         [ #  # ]:          0 :         while (scan < end) {
     479                 :            :             int start_offset, size, handler;
     480                 :          0 :             scan = parse_varint(scan, &start_offset);
     481                 :            :             assert(start_offset >= 0 && start_offset < len);
     482                 :          0 :             scan = parse_varint(scan, &size);
     483                 :            :             assert(size >= 0 && start_offset+size <= len);
     484                 :          0 :             scan = parse_varint(scan, &handler);
     485                 :            :             assert(handler >= 0 && handler < len);
     486                 :            :             int depth_and_lasti;
     487                 :          0 :             scan = parse_varint(scan, &depth_and_lasti);
     488                 :          0 :             int level = depth_and_lasti >> 1;
     489                 :          0 :             int lasti = depth_and_lasti & 1;
     490         [ #  # ]:          0 :             if (stacks[start_offset] != UNINITIALIZED) {
     491         [ #  # ]:          0 :                 if (stacks[handler] == UNINITIALIZED) {
     492                 :          0 :                     todo = 1;
     493                 :          0 :                     uint64_t target_stack = pop_to_level(stacks[start_offset], level);
     494         [ #  # ]:          0 :                     if (lasti) {
     495                 :          0 :                         target_stack = push_value(target_stack, Lasti);
     496                 :            :                     }
     497                 :          0 :                     target_stack = push_value(target_stack, Except);
     498                 :          0 :                     stacks[handler] = target_stack;
     499                 :            :                 }
     500                 :            :             }
     501                 :            :         }
     502                 :            :     }
     503                 :          0 :     Py_DECREF(co_code);
     504                 :          0 :     return stacks;
     505                 :            : }
     506                 :            : 
     507                 :            : static int
     508                 :          0 : compatible_stack(int64_t from_stack, int64_t to_stack)
     509                 :            : {
     510   [ #  #  #  # ]:          0 :     if (from_stack < 0 || to_stack < 0) {
     511                 :          0 :         return 0;
     512                 :            :     }
     513         [ #  # ]:          0 :     while(from_stack > to_stack) {
     514                 :          0 :         from_stack = pop_value(from_stack);
     515                 :            :     }
     516         [ #  # ]:          0 :     while(from_stack) {
     517                 :          0 :         Kind from_top = top_of_stack(from_stack);
     518                 :          0 :         Kind to_top = top_of_stack(to_stack);
     519         [ #  # ]:          0 :         if (!compatible_kind(from_top, to_top)) {
     520                 :          0 :             return 0;
     521                 :            :         }
     522                 :          0 :         from_stack = pop_value(from_stack);
     523                 :          0 :         to_stack = pop_value(to_stack);
     524                 :            :     }
     525                 :          0 :     return to_stack == 0;
     526                 :            : }
     527                 :            : 
     528                 :            : static const char *
     529                 :          0 : explain_incompatible_stack(int64_t to_stack)
     530                 :            : {
     531                 :            :     assert(to_stack != 0);
     532         [ #  # ]:          0 :     if (to_stack == OVERFLOWED) {
     533                 :          0 :         return "stack is too deep to analyze";
     534                 :            :     }
     535         [ #  # ]:          0 :     if (to_stack == UNINITIALIZED) {
     536                 :          0 :         return "can't jump into an exception handler, or code may be unreachable";
     537                 :            :     }
     538                 :          0 :     Kind target_kind = top_of_stack(to_stack);
     539   [ #  #  #  #  :          0 :     switch(target_kind) {
                      # ]
     540                 :          0 :         case Except:
     541                 :          0 :             return "can't jump into an 'except' block as there's no exception";
     542                 :          0 :         case Lasti:
     543                 :          0 :             return "can't jump into a re-raising block as there's no location";
     544                 :          0 :         case Object:
     545                 :            :         case Null:
     546                 :          0 :             return "incompatible stacks";
     547                 :          0 :         case Iterator:
     548                 :          0 :             return "can't jump into the body of a for loop";
     549                 :          0 :         default:
     550                 :          0 :             Py_UNREACHABLE();
     551                 :            :     }
     552                 :            : }
     553                 :            : 
     554                 :            : static int *
     555                 :          0 : marklines(PyCodeObject *code, int len)
     556                 :            : {
     557                 :            :     PyCodeAddressRange bounds;
     558                 :          0 :     _PyCode_InitAddressRange(code, &bounds);
     559                 :            :     assert (bounds.ar_end == 0);
     560                 :          0 :     int last_line = -1;
     561                 :            : 
     562         [ #  # ]:          0 :     int *linestarts = PyMem_New(int, len);
     563         [ #  # ]:          0 :     if (linestarts == NULL) {
     564                 :          0 :         return NULL;
     565                 :            :     }
     566         [ #  # ]:          0 :     for (int i = 0; i < len; i++) {
     567                 :          0 :         linestarts[i] = -1;
     568                 :            :     }
     569                 :            : 
     570         [ #  # ]:          0 :     while (_PyLineTable_NextAddressRange(&bounds)) {
     571                 :            :         assert(bounds.ar_start / (int)sizeof(_Py_CODEUNIT) < len);
     572   [ #  #  #  # ]:          0 :         if (bounds.ar_line != last_line && bounds.ar_line != -1) {
     573                 :          0 :             linestarts[bounds.ar_start / sizeof(_Py_CODEUNIT)] = bounds.ar_line;
     574                 :          0 :             last_line = bounds.ar_line;
     575                 :            :         }
     576                 :            :     }
     577                 :          0 :     return linestarts;
     578                 :            : }
     579                 :            : 
     580                 :            : static int
     581                 :          0 : first_line_not_before(int *lines, int len, int line)
     582                 :            : {
     583                 :          0 :     int result = INT_MAX;
     584         [ #  # ]:          0 :     for (int i = 0; i < len; i++) {
     585   [ #  #  #  # ]:          0 :         if (lines[i] < result && lines[i] >= line) {
     586                 :          0 :             result = lines[i];
     587                 :            :         }
     588                 :            :     }
     589         [ #  # ]:          0 :     if (result == INT_MAX) {
     590                 :          0 :         return -1;
     591                 :            :     }
     592                 :          0 :     return result;
     593                 :            : }
     594                 :            : 
     595                 :            : static PyFrameState
     596                 :          0 : _PyFrame_GetState(PyFrameObject *frame)
     597                 :            : {
     598                 :            :     assert(!_PyFrame_IsIncomplete(frame->f_frame));
     599         [ #  # ]:          0 :     if (frame->f_frame->stacktop == 0) {
     600                 :          0 :         return FRAME_CLEARED;
     601                 :            :     }
     602   [ #  #  #  # ]:          0 :     switch(frame->f_frame->owner) {
     603                 :          0 :         case FRAME_OWNED_BY_GENERATOR:
     604                 :            :         {
     605                 :          0 :             PyGenObject *gen = _PyFrame_GetGenerator(frame->f_frame);
     606                 :          0 :             return gen->gi_frame_state;
     607                 :            :         }
     608                 :          0 :         case FRAME_OWNED_BY_THREAD:
     609                 :            :         {
     610         [ #  # ]:          0 :             if (_PyInterpreterFrame_LASTI(frame->f_frame) < 0) {
     611                 :          0 :                 return FRAME_CREATED;
     612                 :            :             }
     613         [ #  # ]:          0 :             switch (frame->f_frame->prev_instr->op.code)
     614                 :            :             {
     615                 :          0 :                 case COPY_FREE_VARS:
     616                 :            :                 case MAKE_CELL:
     617                 :            :                 case RETURN_GENERATOR:
     618                 :            :                     /* Frame not fully initialized */
     619                 :          0 :                     return FRAME_CREATED;
     620                 :          0 :                 default:
     621                 :          0 :                     return FRAME_EXECUTING;
     622                 :            :             }
     623                 :            :         }
     624                 :          0 :         case FRAME_OWNED_BY_FRAME_OBJECT:
     625                 :          0 :             return FRAME_COMPLETED;
     626                 :            :     }
     627                 :          0 :     Py_UNREACHABLE();
     628                 :            : }
     629                 :            : 
     630                 :            : /* Setter for f_lineno - you can set f_lineno from within a trace function in
     631                 :            :  * order to jump to a given line of code, subject to some restrictions.  Most
     632                 :            :  * lines are OK to jump to because they don't make any assumptions about the
     633                 :            :  * state of the stack (obvious because you could remove the line and the code
     634                 :            :  * would still work without any stack errors), but there are some constructs
     635                 :            :  * that limit jumping:
     636                 :            :  *
     637                 :            :  *  o Any exception handlers.
     638                 :            :  *  o 'for' and 'async for' loops can't be jumped into because the
     639                 :            :  *    iterator needs to be on the stack.
     640                 :            :  *  o Jumps cannot be made from within a trace function invoked with a
     641                 :            :  *    'return' or 'exception' event since the eval loop has been exited at
     642                 :            :  *    that time.
     643                 :            :  */
     644                 :            : static int
     645                 :          0 : frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignored))
     646                 :            : {
     647         [ #  # ]:          0 :     if (p_new_lineno == NULL) {
     648                 :          0 :         PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
     649                 :          0 :         return -1;
     650                 :            :     }
     651                 :            :     /* f_lineno must be an integer. */
     652         [ #  # ]:          0 :     if (!PyLong_CheckExact(p_new_lineno)) {
     653                 :          0 :         PyErr_SetString(PyExc_ValueError,
     654                 :            :                         "lineno must be an integer");
     655                 :          0 :         return -1;
     656                 :            :     }
     657                 :            : 
     658                 :          0 :     PyFrameState state = _PyFrame_GetState(f);
     659                 :            :     /*
     660                 :            :      * This code preserves the historical restrictions on
     661                 :            :      * setting the line number of a frame.
     662                 :            :      * Jumps are forbidden on a 'return' trace event (except after a yield).
     663                 :            :      * Jumps from 'call' trace events are also forbidden.
     664                 :            :      * In addition, jumps are forbidden when not tracing,
     665                 :            :      * as this is a debugging feature.
     666                 :            :      */
     667   [ #  #  #  #  :          0 :     switch(PyThreadState_GET()->tracing_what) {
                      # ]
     668                 :          0 :         case PyTrace_EXCEPTION:
     669                 :          0 :             PyErr_SetString(PyExc_ValueError,
     670                 :            :                 "can only jump from a 'line' trace event");
     671                 :          0 :             return -1;
     672                 :          0 :         case PyTrace_CALL:
     673                 :          0 :             PyErr_Format(PyExc_ValueError,
     674                 :            :                      "can't jump from the 'call' trace event of a new frame");
     675                 :          0 :             return -1;
     676                 :          0 :         case PyTrace_LINE:
     677                 :          0 :             break;
     678                 :          0 :         case PyTrace_RETURN:
     679         [ #  # ]:          0 :             if (state == FRAME_SUSPENDED) {
     680                 :          0 :                 break;
     681                 :            :             }
     682                 :            :             /* fall through */
     683                 :            :         default:
     684                 :          0 :             PyErr_SetString(PyExc_ValueError,
     685                 :            :                 "can only jump from a 'line' trace event");
     686                 :          0 :             return -1;
     687                 :            :     }
     688         [ #  # ]:          0 :     if (!f->f_trace) {
     689                 :          0 :         PyErr_Format(PyExc_ValueError,
     690                 :            :                     "f_lineno can only be set by a trace function");
     691                 :          0 :         return -1;
     692                 :            :     }
     693                 :            : 
     694                 :            :     int new_lineno;
     695                 :            : 
     696                 :            :     /* Fail if the line falls outside the code block and
     697                 :            :         select first line with actual code. */
     698                 :            :     int overflow;
     699                 :          0 :     long l_new_lineno = PyLong_AsLongAndOverflow(p_new_lineno, &overflow);
     700         [ #  # ]:          0 :     if (overflow
     701                 :            : #if SIZEOF_LONG > SIZEOF_INT
     702         [ #  # ]:          0 :         || l_new_lineno > INT_MAX
     703         [ #  # ]:          0 :         || l_new_lineno < INT_MIN
     704                 :            : #endif
     705                 :            :     ) {
     706                 :          0 :         PyErr_SetString(PyExc_ValueError,
     707                 :            :                         "lineno out of range");
     708                 :          0 :         return -1;
     709                 :            :     }
     710                 :          0 :     new_lineno = (int)l_new_lineno;
     711                 :            : 
     712         [ #  # ]:          0 :     if (new_lineno < f->f_frame->f_code->co_firstlineno) {
     713                 :          0 :         PyErr_Format(PyExc_ValueError,
     714                 :            :                     "line %d comes before the current code block",
     715                 :            :                     new_lineno);
     716                 :          0 :         return -1;
     717                 :            :     }
     718                 :            : 
     719                 :            :     /* PyCode_NewWithPosOnlyArgs limits co_code to be under INT_MAX so this
     720                 :            :      * should never overflow. */
     721                 :          0 :     int len = (int)Py_SIZE(f->f_frame->f_code);
     722                 :          0 :     int *lines = marklines(f->f_frame->f_code, len);
     723         [ #  # ]:          0 :     if (lines == NULL) {
     724                 :          0 :         return -1;
     725                 :            :     }
     726                 :            : 
     727                 :          0 :     new_lineno = first_line_not_before(lines, len, new_lineno);
     728         [ #  # ]:          0 :     if (new_lineno < 0) {
     729                 :          0 :         PyErr_Format(PyExc_ValueError,
     730                 :            :                     "line %d comes after the current code block",
     731                 :            :                     (int)l_new_lineno);
     732                 :          0 :         PyMem_Free(lines);
     733                 :          0 :         return -1;
     734                 :            :     }
     735                 :            : 
     736                 :          0 :     int64_t *stacks = mark_stacks(f->f_frame->f_code, len);
     737         [ #  # ]:          0 :     if (stacks == NULL) {
     738                 :          0 :         PyMem_Free(lines);
     739                 :          0 :         return -1;
     740                 :            :     }
     741                 :            : 
     742                 :          0 :     int64_t best_stack = OVERFLOWED;
     743                 :          0 :     int best_addr = -1;
     744                 :          0 :     int64_t start_stack = stacks[_PyInterpreterFrame_LASTI(f->f_frame)];
     745                 :          0 :     int err = -1;
     746                 :          0 :     const char *msg = "cannot find bytecode for specified line";
     747         [ #  # ]:          0 :     for (int i = 0; i < len; i++) {
     748         [ #  # ]:          0 :         if (lines[i] == new_lineno) {
     749                 :          0 :             int64_t target_stack = stacks[i];
     750         [ #  # ]:          0 :             if (compatible_stack(start_stack, target_stack)) {
     751                 :          0 :                 err = 0;
     752         [ #  # ]:          0 :                 if (target_stack > best_stack) {
     753                 :          0 :                     best_stack = target_stack;
     754                 :          0 :                     best_addr = i;
     755                 :            :                 }
     756                 :            :             }
     757         [ #  # ]:          0 :             else if (err < 0) {
     758         [ #  # ]:          0 :                 if (start_stack == OVERFLOWED) {
     759                 :          0 :                     msg = "stack to deep to analyze";
     760                 :            :                 }
     761         [ #  # ]:          0 :                 else if (start_stack == UNINITIALIZED) {
     762                 :          0 :                     msg = "can't jump from unreachable code";
     763                 :            :                 }
     764                 :            :                 else {
     765                 :          0 :                     msg = explain_incompatible_stack(target_stack);
     766                 :          0 :                     err = 1;
     767                 :            :                 }
     768                 :            :             }
     769                 :            :         }
     770                 :            :     }
     771                 :          0 :     PyMem_Free(stacks);
     772                 :          0 :     PyMem_Free(lines);
     773         [ #  # ]:          0 :     if (err) {
     774                 :          0 :         PyErr_SetString(PyExc_ValueError, msg);
     775                 :          0 :         return -1;
     776                 :            :     }
     777                 :            :     // Populate any NULL locals that the compiler might have "proven" to exist
     778                 :            :     // in the new location. Rather than crashing or changing co_code, just bind
     779                 :            :     // None instead:
     780                 :          0 :     int unbound = 0;
     781         [ #  # ]:          0 :     for (int i = 0; i < f->f_frame->f_code->co_nlocalsplus; i++) {
     782                 :            :         // Counting every unbound local is overly-cautious, but a full flow
     783                 :            :         // analysis (like we do in the compiler) is probably too expensive:
     784                 :          0 :         unbound += f->f_frame->localsplus[i] == NULL;
     785                 :            :     }
     786         [ #  # ]:          0 :     if (unbound) {
     787                 :          0 :         const char *e = "assigning None to %d unbound local%s";
     788         [ #  # ]:          0 :         const char *s = (unbound == 1) ? "" : "s";
     789         [ #  # ]:          0 :         if (PyErr_WarnFormat(PyExc_RuntimeWarning, 0, e, unbound, s)) {
     790                 :          0 :             return -1;
     791                 :            :         }
     792                 :            :         // Do this in a second pass to avoid writing a bunch of Nones when
     793                 :            :         // warnings are being treated as errors and the previous bit raises:
     794         [ #  # ]:          0 :         for (int i = 0; i < f->f_frame->f_code->co_nlocalsplus; i++) {
     795         [ #  # ]:          0 :             if (f->f_frame->localsplus[i] == NULL) {
     796                 :          0 :                 f->f_frame->localsplus[i] = Py_NewRef(Py_None);
     797                 :          0 :                 unbound--;
     798                 :            :             }
     799                 :            :         }
     800                 :            :         assert(unbound == 0);
     801                 :            :     }
     802         [ #  # ]:          0 :     if (state == FRAME_SUSPENDED) {
     803                 :            :         /* Account for value popped by yield */
     804                 :          0 :         start_stack = pop_value(start_stack);
     805                 :            :     }
     806         [ #  # ]:          0 :     while (start_stack > best_stack) {
     807         [ #  # ]:          0 :         if (top_of_stack(start_stack) == Except) {
     808                 :            :             /* Pop exception stack as well as the evaluation stack */
     809                 :          0 :             PyThreadState *tstate = _PyThreadState_GET();
     810                 :          0 :             _PyErr_StackItem *exc_info = tstate->exc_info;
     811                 :          0 :             PyObject *value = exc_info->exc_value;
     812                 :          0 :             PyObject *exc = _PyFrame_StackPop(f->f_frame);
     813                 :            :             assert(PyExceptionInstance_Check(exc) || exc == Py_None);
     814                 :          0 :             exc_info->exc_value = exc;
     815                 :          0 :             Py_XDECREF(value);
     816                 :            :         }
     817                 :            :         else {
     818                 :          0 :             PyObject *v = _PyFrame_StackPop(f->f_frame);
     819                 :          0 :             Py_XDECREF(v);
     820                 :            :         }
     821                 :          0 :         start_stack = pop_value(start_stack);
     822                 :            :     }
     823                 :            :     /* Finally set the new lasti and return OK. */
     824                 :          0 :     f->f_lineno = 0;
     825                 :          0 :     f->f_frame->prev_instr = _PyCode_CODE(f->f_frame->f_code) + best_addr;
     826                 :          0 :     return 0;
     827                 :            : }
     828                 :            : 
     829                 :            : static PyObject *
     830                 :          0 : frame_gettrace(PyFrameObject *f, void *closure)
     831                 :            : {
     832                 :          0 :     PyObject* trace = f->f_trace;
     833         [ #  # ]:          0 :     if (trace == NULL)
     834                 :          0 :         trace = Py_None;
     835                 :          0 :     return Py_NewRef(trace);
     836                 :            : }
     837                 :            : 
     838                 :            : static int
     839                 :          0 : frame_settrace(PyFrameObject *f, PyObject* v, void *closure)
     840                 :            : {
     841         [ #  # ]:          0 :     if (v == Py_None) {
     842                 :          0 :         v = NULL;
     843                 :            :     }
     844                 :          0 :     Py_XSETREF(f->f_trace, Py_XNewRef(v));
     845                 :          0 :     return 0;
     846                 :            : }
     847                 :            : 
     848                 :            : 
     849                 :            : static PyGetSetDef frame_getsetlist[] = {
     850                 :            :     {"f_back",          (getter)frame_getback, NULL, NULL},
     851                 :            :     {"f_locals",        (getter)frame_getlocals, NULL, NULL},
     852                 :            :     {"f_lineno",        (getter)frame_getlineno,
     853                 :            :                     (setter)frame_setlineno, NULL},
     854                 :            :     {"f_trace",         (getter)frame_gettrace, (setter)frame_settrace, NULL},
     855                 :            :     {"f_lasti",         (getter)frame_getlasti, NULL, NULL},
     856                 :            :     {"f_globals",       (getter)frame_getglobals, NULL, NULL},
     857                 :            :     {"f_builtins",      (getter)frame_getbuiltins, NULL, NULL},
     858                 :            :     {"f_code",          (getter)frame_getcode, NULL, NULL},
     859                 :            :     {0}
     860                 :            : };
     861                 :            : 
     862                 :            : static void
     863                 :     106583 : frame_dealloc(PyFrameObject *f)
     864                 :            : {
     865                 :            :     /* It is the responsibility of the owning generator/coroutine
     866                 :            :      * to have cleared the generator pointer */
     867                 :            : 
     868                 :            :     assert(f->f_frame->owner != FRAME_OWNED_BY_GENERATOR ||
     869                 :            :         _PyFrame_GetGenerator(f->f_frame)->gi_frame_state == FRAME_CLEARED);
     870                 :            : 
     871         [ +  + ]:     106583 :     if (_PyObject_GC_IS_TRACKED(f)) {
     872                 :       3459 :         _PyObject_GC_UNTRACK(f);
     873                 :            :     }
     874                 :            : 
     875   [ +  -  -  + ]:     106583 :     Py_TRASHCAN_BEGIN(f, frame_dealloc);
     876                 :     106583 :     PyCodeObject *co = NULL;
     877                 :            : 
     878                 :            :     /* Kill all local variables including specials, if we own them */
     879         [ +  + ]:     106583 :     if (f->f_frame->owner == FRAME_OWNED_BY_FRAME_OBJECT) {
     880                 :            :         assert(f->f_frame == (_PyInterpreterFrame *)f->_f_frame_data);
     881                 :       3459 :         _PyInterpreterFrame *frame = (_PyInterpreterFrame *)f->_f_frame_data;
     882                 :            :         /* Don't clear code object until the end */
     883                 :       3459 :         co = frame->f_code;
     884                 :       3459 :         frame->f_code = NULL;
     885         [ +  - ]:       3459 :         Py_CLEAR(frame->f_funcobj);
     886         [ +  + ]:       3459 :         Py_CLEAR(frame->f_locals);
     887                 :       3459 :         PyObject **locals = _PyFrame_GetLocalsArray(frame);
     888         [ +  + ]:      12254 :         for (int i = 0; i < frame->stacktop; i++) {
     889         [ +  + ]:       8795 :             Py_CLEAR(locals[i]);
     890                 :            :         }
     891                 :            :     }
     892         [ +  + ]:     106583 :     Py_CLEAR(f->f_back);
     893         [ -  + ]:     106583 :     Py_CLEAR(f->f_trace);
     894                 :     106583 :     PyObject_GC_Del(f);
     895                 :     106583 :     Py_XDECREF(co);
     896         [ +  - ]:     106583 :     Py_TRASHCAN_END;
     897                 :     106583 : }
     898                 :            : 
     899                 :            : static int
     900                 :          0 : frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
     901                 :            : {
     902   [ #  #  #  # ]:          0 :     Py_VISIT(f->f_back);
     903   [ #  #  #  # ]:          0 :     Py_VISIT(f->f_trace);
     904         [ #  # ]:          0 :     if (f->f_frame->owner != FRAME_OWNED_BY_FRAME_OBJECT) {
     905                 :          0 :         return 0;
     906                 :            :     }
     907                 :            :     assert(f->f_frame->frame_obj == NULL);
     908                 :          0 :     return _PyFrame_Traverse(f->f_frame, visit, arg);
     909                 :            : }
     910                 :            : 
     911                 :            : static int
     912                 :          6 : frame_tp_clear(PyFrameObject *f)
     913                 :            : {
     914         [ -  + ]:          6 :     Py_CLEAR(f->f_trace);
     915                 :            : 
     916                 :            :     /* locals and stack */
     917                 :          6 :     PyObject **locals = _PyFrame_GetLocalsArray(f->f_frame);
     918                 :            :     assert(f->f_frame->stacktop >= 0);
     919         [ +  + ]:         24 :     for (int i = 0; i < f->f_frame->stacktop; i++) {
     920         [ +  - ]:         18 :         Py_CLEAR(locals[i]);
     921                 :            :     }
     922                 :          6 :     f->f_frame->stacktop = 0;
     923                 :          6 :     return 0;
     924                 :            : }
     925                 :            : 
     926                 :            : static PyObject *
     927                 :        230 : frame_clear(PyFrameObject *f, PyObject *Py_UNUSED(ignored))
     928                 :            : {
     929         [ -  + ]:        230 :     if (f->f_frame->owner == FRAME_OWNED_BY_GENERATOR) {
     930                 :          0 :         PyGenObject *gen = _PyFrame_GetGenerator(f->f_frame);
     931         [ #  # ]:          0 :         if (gen->gi_frame_state == FRAME_EXECUTING) {
     932                 :          0 :             goto running;
     933                 :            :         }
     934                 :          0 :         _PyGen_Finalize((PyObject *)gen);
     935                 :            :     }
     936         [ +  + ]:        230 :     else if (f->f_frame->owner == FRAME_OWNED_BY_THREAD) {
     937                 :        224 :         goto running;
     938                 :            :     }
     939                 :            :     else {
     940                 :            :         assert(f->f_frame->owner == FRAME_OWNED_BY_FRAME_OBJECT);
     941                 :          6 :         (void)frame_tp_clear(f);
     942                 :            :     }
     943                 :          6 :     Py_RETURN_NONE;
     944                 :        224 : running:
     945                 :        224 :     PyErr_SetString(PyExc_RuntimeError,
     946                 :            :                     "cannot clear an executing frame");
     947                 :        224 :     return NULL;
     948                 :            : }
     949                 :            : 
     950                 :            : PyDoc_STRVAR(clear__doc__,
     951                 :            : "F.clear(): clear most references held by the frame");
     952                 :            : 
     953                 :            : static PyObject *
     954                 :          0 : frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored))
     955                 :            : {
     956                 :            :     Py_ssize_t res;
     957                 :          0 :     res = offsetof(PyFrameObject, _f_frame_data) + offsetof(_PyInterpreterFrame, localsplus);
     958                 :          0 :     PyCodeObject *code = f->f_frame->f_code;
     959                 :          0 :     res += _PyFrame_NumSlotsForCodeObject(code) * sizeof(PyObject *);
     960                 :          0 :     return PyLong_FromSsize_t(res);
     961                 :            : }
     962                 :            : 
     963                 :            : PyDoc_STRVAR(sizeof__doc__,
     964                 :            : "F.__sizeof__() -> size of F in memory, in bytes");
     965                 :            : 
     966                 :            : static PyObject *
     967                 :          0 : frame_repr(PyFrameObject *f)
     968                 :            : {
     969                 :          0 :     int lineno = PyFrame_GetLineNumber(f);
     970                 :          0 :     PyCodeObject *code = f->f_frame->f_code;
     971                 :          0 :     return PyUnicode_FromFormat(
     972                 :            :         "<frame at %p, file %R, line %d, code %S>",
     973                 :            :         f, code->co_filename, lineno, code->co_name);
     974                 :            : }
     975                 :            : 
     976                 :            : static PyMethodDef frame_methods[] = {
     977                 :            :     {"clear",           (PyCFunction)frame_clear,       METH_NOARGS,
     978                 :            :      clear__doc__},
     979                 :            :     {"__sizeof__",      (PyCFunction)frame_sizeof,      METH_NOARGS,
     980                 :            :      sizeof__doc__},
     981                 :            :     {NULL,              NULL}   /* sentinel */
     982                 :            : };
     983                 :            : 
     984                 :            : PyTypeObject PyFrame_Type = {
     985                 :            :     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     986                 :            :     "frame",
     987                 :            :     offsetof(PyFrameObject, _f_frame_data) +
     988                 :            :     offsetof(_PyInterpreterFrame, localsplus),
     989                 :            :     sizeof(PyObject *),
     990                 :            :     (destructor)frame_dealloc,                  /* tp_dealloc */
     991                 :            :     0,                                          /* tp_vectorcall_offset */
     992                 :            :     0,                                          /* tp_getattr */
     993                 :            :     0,                                          /* tp_setattr */
     994                 :            :     0,                                          /* tp_as_async */
     995                 :            :     (reprfunc)frame_repr,                       /* tp_repr */
     996                 :            :     0,                                          /* tp_as_number */
     997                 :            :     0,                                          /* tp_as_sequence */
     998                 :            :     0,                                          /* tp_as_mapping */
     999                 :            :     0,                                          /* tp_hash */
    1000                 :            :     0,                                          /* tp_call */
    1001                 :            :     0,                                          /* tp_str */
    1002                 :            :     PyObject_GenericGetAttr,                    /* tp_getattro */
    1003                 :            :     PyObject_GenericSetAttr,                    /* tp_setattro */
    1004                 :            :     0,                                          /* tp_as_buffer */
    1005                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
    1006                 :            :     0,                                          /* tp_doc */
    1007                 :            :     (traverseproc)frame_traverse,               /* tp_traverse */
    1008                 :            :     (inquiry)frame_tp_clear,                    /* tp_clear */
    1009                 :            :     0,                                          /* tp_richcompare */
    1010                 :            :     0,                                          /* tp_weaklistoffset */
    1011                 :            :     0,                                          /* tp_iter */
    1012                 :            :     0,                                          /* tp_iternext */
    1013                 :            :     frame_methods,                              /* tp_methods */
    1014                 :            :     frame_memberlist,                           /* tp_members */
    1015                 :            :     frame_getsetlist,                           /* tp_getset */
    1016                 :            :     0,                                          /* tp_base */
    1017                 :            :     0,                                          /* tp_dict */
    1018                 :            : };
    1019                 :            : 
    1020                 :            : static void
    1021                 :          0 : init_frame(_PyInterpreterFrame *frame, PyFunctionObject *func, PyObject *locals)
    1022                 :            : {
    1023                 :          0 :     PyCodeObject *code = (PyCodeObject *)func->func_code;
    1024                 :          0 :     _PyFrame_Initialize(frame, (PyFunctionObject*)Py_NewRef(func),
    1025                 :            :                         Py_XNewRef(locals), code, 0);
    1026                 :          0 :     frame->previous = NULL;
    1027                 :          0 : }
    1028                 :            : 
    1029                 :            : PyFrameObject*
    1030                 :     106583 : _PyFrame_New_NoTrack(PyCodeObject *code)
    1031                 :            : {
    1032                 :            :     CALL_STAT_INC(frame_objects_created);
    1033                 :     106583 :     int slots = code->co_nlocalsplus + code->co_stacksize;
    1034                 :     106583 :     PyFrameObject *f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, slots);
    1035         [ -  + ]:     106583 :     if (f == NULL) {
    1036                 :          0 :         return NULL;
    1037                 :            :     }
    1038                 :     106583 :     f->f_back = NULL;
    1039                 :     106583 :     f->f_trace = NULL;
    1040                 :     106583 :     f->f_trace_lines = 1;
    1041                 :     106583 :     f->f_trace_opcodes = 0;
    1042                 :     106583 :     f->f_fast_as_locals = 0;
    1043                 :     106583 :     f->f_lineno = 0;
    1044                 :     106583 :     return f;
    1045                 :            : }
    1046                 :            : 
    1047                 :            : /* Legacy API */
    1048                 :            : PyFrameObject*
    1049                 :          0 : PyFrame_New(PyThreadState *tstate, PyCodeObject *code,
    1050                 :            :             PyObject *globals, PyObject *locals)
    1051                 :            : {
    1052                 :          0 :     PyObject *builtins = _PyEval_BuiltinsFromGlobals(tstate, globals); // borrowed ref
    1053         [ #  # ]:          0 :     if (builtins == NULL) {
    1054                 :          0 :         return NULL;
    1055                 :            :     }
    1056                 :          0 :     PyFrameConstructor desc = {
    1057                 :            :         .fc_globals = globals,
    1058                 :            :         .fc_builtins = builtins,
    1059                 :          0 :         .fc_name = code->co_name,
    1060                 :          0 :         .fc_qualname = code->co_name,
    1061                 :            :         .fc_code = (PyObject *)code,
    1062                 :            :         .fc_defaults = NULL,
    1063                 :            :         .fc_kwdefaults = NULL,
    1064                 :            :         .fc_closure = NULL
    1065                 :            :     };
    1066                 :          0 :     PyFunctionObject *func = _PyFunction_FromConstructor(&desc);
    1067         [ #  # ]:          0 :     if (func == NULL) {
    1068                 :          0 :         return NULL;
    1069                 :            :     }
    1070                 :          0 :     PyFrameObject *f = _PyFrame_New_NoTrack(code);
    1071         [ #  # ]:          0 :     if (f == NULL) {
    1072                 :          0 :         Py_DECREF(func);
    1073                 :          0 :         return NULL;
    1074                 :            :     }
    1075                 :          0 :     init_frame((_PyInterpreterFrame *)f->_f_frame_data, func, locals);
    1076                 :          0 :     f->f_frame = (_PyInterpreterFrame *)f->_f_frame_data;
    1077                 :          0 :     f->f_frame->owner = FRAME_OWNED_BY_FRAME_OBJECT;
    1078                 :            :     // This frame needs to be "complete", so pretend that the first RESUME ran:
    1079                 :          0 :     f->f_frame->prev_instr = _PyCode_CODE(code) + code->_co_firsttraceable;
    1080                 :            :     assert(!_PyFrame_IsIncomplete(f->f_frame));
    1081                 :          0 :     Py_DECREF(func);
    1082                 :          0 :     _PyObject_GC_TRACK(f);
    1083                 :          0 :     return f;
    1084                 :            : }
    1085                 :            : 
    1086                 :            : static int
    1087                 :          0 : _PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg)
    1088                 :            : {
    1089                 :            :     // This only works when opcode is a non-quickened form:
    1090                 :            :     assert(_PyOpcode_Deopt[opcode] == opcode);
    1091                 :          0 :     int check_oparg = 0;
    1092                 :          0 :     for (_Py_CODEUNIT *instruction = _PyCode_CODE(frame->f_code);
    1093         [ #  # ]:          0 :          instruction < frame->prev_instr; instruction++)
    1094                 :            :     {
    1095                 :          0 :         int check_opcode = _PyOpcode_Deopt[instruction->op.code];
    1096                 :          0 :         check_oparg |= instruction->op.arg;
    1097   [ #  #  #  # ]:          0 :         if (check_opcode == opcode && check_oparg == oparg) {
    1098                 :          0 :             return 1;
    1099                 :            :         }
    1100         [ #  # ]:          0 :         if (check_opcode == EXTENDED_ARG) {
    1101                 :          0 :             check_oparg <<= 8;
    1102                 :            :         }
    1103                 :            :         else {
    1104                 :          0 :             check_oparg = 0;
    1105                 :            :         }
    1106                 :          0 :         instruction += _PyOpcode_Caches[check_opcode];
    1107                 :            :     }
    1108                 :          0 :     return 0;
    1109                 :            : }
    1110                 :            : 
    1111                 :            : 
    1112                 :            : // Initialize frame free variables if needed
    1113                 :            : static void
    1114                 :        164 : frame_init_get_vars(_PyInterpreterFrame *frame)
    1115                 :            : {
    1116                 :            :     // COPY_FREE_VARS has no quickened forms, so no need to use _PyOpcode_Deopt
    1117                 :            :     // here:
    1118                 :        164 :     PyCodeObject *co = frame->f_code;
    1119                 :        164 :     int lasti = _PyInterpreterFrame_LASTI(frame);
    1120   [ -  +  -  -  :        164 :     if (!(lasti < 0 && _PyCode_CODE(co)->op.code == COPY_FREE_VARS
                   -  - ]
    1121                 :          0 :           && PyFunction_Check(frame->f_funcobj)))
    1122                 :            :     {
    1123                 :            :         /* Free vars are initialized */
    1124                 :        164 :         return;
    1125                 :            :     }
    1126                 :            : 
    1127                 :            :     /* Free vars have not been initialized -- Do that */
    1128                 :          0 :     PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
    1129                 :          0 :     int offset = PyCode_GetFirstFree(co);
    1130         [ #  # ]:          0 :     for (int i = 0; i < co->co_nfreevars; ++i) {
    1131                 :          0 :         PyObject *o = PyTuple_GET_ITEM(closure, i);
    1132                 :          0 :         frame->localsplus[offset + i] = Py_NewRef(o);
    1133                 :            :     }
    1134                 :            :     // COPY_FREE_VARS doesn't have inline CACHEs, either:
    1135                 :          0 :     frame->prev_instr = _PyCode_CODE(frame->f_code);
    1136                 :            : }
    1137                 :            : 
    1138                 :            : 
    1139                 :            : static int
    1140                 :          8 : frame_get_var(_PyInterpreterFrame *frame, PyCodeObject *co, int i,
    1141                 :            :               PyObject **pvalue)
    1142                 :            : {
    1143                 :          8 :     _PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
    1144                 :            : 
    1145                 :            :     /* If the namespace is unoptimized, then one of the
    1146                 :            :        following cases applies:
    1147                 :            :        1. It does not contain free variables, because it
    1148                 :            :           uses import * or is a top-level namespace.
    1149                 :            :        2. It is a class namespace.
    1150                 :            :        We don't want to accidentally copy free variables
    1151                 :            :        into the locals dict used by the class.
    1152                 :            :     */
    1153   [ -  +  -  - ]:          8 :     if (kind & CO_FAST_FREE && !(co->co_flags & CO_OPTIMIZED)) {
    1154                 :          0 :         return 0;
    1155                 :            :     }
    1156                 :            : 
    1157                 :          8 :     PyObject *value = frame->localsplus[i];
    1158         [ +  - ]:          8 :     if (frame->stacktop) {
    1159         [ -  + ]:          8 :         if (kind & CO_FAST_FREE) {
    1160                 :            :             // The cell was set by COPY_FREE_VARS.
    1161                 :            :             assert(value != NULL && PyCell_Check(value));
    1162                 :          0 :             value = PyCell_GET(value);
    1163                 :            :         }
    1164         [ -  + ]:          8 :         else if (kind & CO_FAST_CELL) {
    1165                 :            :             // Note that no *_DEREF ops can happen before MAKE_CELL
    1166                 :            :             // executes.  So there's no need to duplicate the work
    1167                 :            :             // that MAKE_CELL would otherwise do later, if it hasn't
    1168                 :            :             // run yet.
    1169         [ #  # ]:          0 :             if (value != NULL) {
    1170   [ #  #  #  # ]:          0 :                 if (PyCell_Check(value) &&
    1171                 :          0 :                         _PyFrame_OpAlreadyRan(frame, MAKE_CELL, i)) {
    1172                 :            :                     // (likely) MAKE_CELL must have executed already.
    1173                 :          0 :                     value = PyCell_GET(value);
    1174                 :            :                 }
    1175                 :            :                 // (likely) Otherwise it it is an arg (kind & CO_FAST_LOCAL),
    1176                 :            :                 // with the initial value set when the frame was created...
    1177                 :            :                 // (unlikely) ...or it was set to some initial value by
    1178                 :            :                 // an earlier call to PyFrame_LocalsToFast().
    1179                 :            :             }
    1180                 :            :         }
    1181                 :            :     }
    1182                 :            :     else {
    1183                 :            :         assert(value == NULL);
    1184                 :            :     }
    1185                 :          8 :     *pvalue = value;
    1186                 :          8 :     return 1;
    1187                 :            : }
    1188                 :            : 
    1189                 :            : int
    1190                 :        164 : _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame)
    1191                 :            : {
    1192                 :            :     /* Merge fast locals into f->f_locals */
    1193                 :        164 :     PyObject *locals = frame->f_locals;
    1194         [ +  + ]:        164 :     if (locals == NULL) {
    1195                 :          2 :         locals = frame->f_locals = PyDict_New();
    1196         [ -  + ]:          2 :         if (locals == NULL) {
    1197                 :          0 :             return -1;
    1198                 :            :         }
    1199                 :            :     }
    1200                 :            : 
    1201                 :        164 :     frame_init_get_vars(frame);
    1202                 :            : 
    1203                 :        164 :     PyCodeObject *co = frame->f_code;
    1204         [ +  + ]:        172 :     for (int i = 0; i < co->co_nlocalsplus; i++) {
    1205                 :            :         PyObject *value;  // borrowed reference
    1206         [ -  + ]:          8 :         if (!frame_get_var(frame, co, i, &value)) {
    1207                 :          0 :             continue;
    1208                 :            :         }
    1209                 :            : 
    1210                 :          8 :         PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
    1211         [ +  + ]:          8 :         if (value == NULL) {
    1212         [ +  - ]:          4 :             if (PyObject_DelItem(locals, name) != 0) {
    1213         [ +  - ]:          4 :                 if (PyErr_ExceptionMatches(PyExc_KeyError)) {
    1214                 :          4 :                     PyErr_Clear();
    1215                 :            :                 }
    1216                 :            :                 else {
    1217                 :          0 :                     return -1;
    1218                 :            :                 }
    1219                 :            :             }
    1220                 :            :         }
    1221                 :            :         else {
    1222         [ -  + ]:          4 :             if (PyObject_SetItem(locals, name, value) != 0) {
    1223                 :          0 :                 return -1;
    1224                 :            :             }
    1225                 :            :         }
    1226                 :            :     }
    1227                 :        164 :     return 0;
    1228                 :            : }
    1229                 :            : 
    1230                 :            : 
    1231                 :            : PyObject *
    1232                 :          0 : PyFrame_GetVar(PyFrameObject *frame_obj, PyObject *name)
    1233                 :            : {
    1234         [ #  # ]:          0 :     if (!PyUnicode_Check(name)) {
    1235                 :          0 :         PyErr_Format(PyExc_TypeError, "name must be str, not %s",
    1236                 :          0 :                      Py_TYPE(name)->tp_name);
    1237                 :          0 :         return NULL;
    1238                 :            :     }
    1239                 :            : 
    1240                 :          0 :     _PyInterpreterFrame *frame = frame_obj->f_frame;
    1241                 :          0 :     frame_init_get_vars(frame);
    1242                 :            : 
    1243                 :          0 :     PyCodeObject *co = frame->f_code;
    1244         [ #  # ]:          0 :     for (int i = 0; i < co->co_nlocalsplus; i++) {
    1245                 :          0 :         PyObject *var_name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
    1246         [ #  # ]:          0 :         if (!_PyUnicode_Equal(var_name, name)) {
    1247                 :          0 :             continue;
    1248                 :            :         }
    1249                 :            : 
    1250                 :            :         PyObject *value;  // borrowed reference
    1251         [ #  # ]:          0 :         if (!frame_get_var(frame, co, i, &value)) {
    1252                 :          0 :             break;
    1253                 :            :         }
    1254         [ #  # ]:          0 :         if (value == NULL) {
    1255                 :          0 :             break;
    1256                 :            :         }
    1257                 :          0 :         return Py_NewRef(value);
    1258                 :            :     }
    1259                 :            : 
    1260                 :          0 :     PyErr_Format(PyExc_NameError, "variable %R does not exist", name);
    1261                 :          0 :     return NULL;
    1262                 :            : }
    1263                 :            : 
    1264                 :            : 
    1265                 :            : PyObject *
    1266                 :          0 : PyFrame_GetVarString(PyFrameObject *frame, const char *name)
    1267                 :            : {
    1268                 :          0 :     PyObject *name_obj = PyUnicode_FromString(name);
    1269         [ #  # ]:          0 :     if (name_obj == NULL) {
    1270                 :          0 :         return NULL;
    1271                 :            :     }
    1272                 :          0 :     PyObject *value = PyFrame_GetVar(frame, name_obj);
    1273                 :          0 :     Py_DECREF(name_obj);
    1274                 :          0 :     return value;
    1275                 :            : }
    1276                 :            : 
    1277                 :            : 
    1278                 :            : int
    1279                 :          0 : PyFrame_FastToLocalsWithError(PyFrameObject *f)
    1280                 :            : {
    1281                 :            :     assert(!_PyFrame_IsIncomplete(f->f_frame));
    1282         [ #  # ]:          0 :     if (f == NULL) {
    1283                 :          0 :         PyErr_BadInternalCall();
    1284                 :          0 :         return -1;
    1285                 :            :     }
    1286                 :          0 :     int err = _PyFrame_FastToLocalsWithError(f->f_frame);
    1287         [ #  # ]:          0 :     if (err == 0) {
    1288                 :          0 :         f->f_fast_as_locals = 1;
    1289                 :            :     }
    1290                 :          0 :     return err;
    1291                 :            : }
    1292                 :            : 
    1293                 :            : void
    1294                 :          0 : PyFrame_FastToLocals(PyFrameObject *f)
    1295                 :            : {
    1296                 :            :     int res;
    1297                 :            :     assert(!_PyFrame_IsIncomplete(f->f_frame));
    1298                 :            :     assert(!PyErr_Occurred());
    1299                 :            : 
    1300                 :          0 :     res = PyFrame_FastToLocalsWithError(f);
    1301         [ #  # ]:          0 :     if (res < 0)
    1302                 :          0 :         PyErr_Clear();
    1303                 :          0 : }
    1304                 :            : 
    1305                 :            : void
    1306                 :        162 : _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear)
    1307                 :            : {
    1308                 :            :     /* Merge locals into fast locals */
    1309                 :            :     PyObject *locals;
    1310                 :            :     PyObject **fast;
    1311                 :            :     PyCodeObject *co;
    1312                 :        162 :     locals = frame->f_locals;
    1313         [ -  + ]:        162 :     if (locals == NULL) {
    1314                 :          0 :         return;
    1315                 :            :     }
    1316                 :        162 :     fast = _PyFrame_GetLocalsArray(frame);
    1317                 :        162 :     co = frame->f_code;
    1318                 :            : 
    1319                 :        162 :     PyObject *exc = PyErr_GetRaisedException();
    1320         [ -  + ]:        162 :     for (int i = 0; i < co->co_nlocalsplus; i++) {
    1321                 :          0 :         _PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
    1322                 :            : 
    1323                 :            :         /* Same test as in PyFrame_FastToLocals() above. */
    1324   [ #  #  #  # ]:          0 :         if (kind & CO_FAST_FREE && !(co->co_flags & CO_OPTIMIZED)) {
    1325                 :          0 :             continue;
    1326                 :            :         }
    1327                 :          0 :         PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
    1328                 :          0 :         PyObject *value = PyObject_GetItem(locals, name);
    1329                 :            :         /* We only care about NULLs if clear is true. */
    1330         [ #  # ]:          0 :         if (value == NULL) {
    1331                 :          0 :             PyErr_Clear();
    1332         [ #  # ]:          0 :             if (!clear) {
    1333                 :          0 :                 continue;
    1334                 :            :             }
    1335                 :            :         }
    1336                 :          0 :         PyObject *oldvalue = fast[i];
    1337                 :          0 :         PyObject *cell = NULL;
    1338         [ #  # ]:          0 :         if (kind == CO_FAST_FREE) {
    1339                 :            :             // The cell was set when the frame was created from
    1340                 :            :             // the function's closure.
    1341                 :            :             assert(oldvalue != NULL && PyCell_Check(oldvalue));
    1342                 :          0 :             cell = oldvalue;
    1343                 :            :         }
    1344   [ #  #  #  # ]:          0 :         else if (kind & CO_FAST_CELL && oldvalue != NULL) {
    1345                 :            :             /* Same test as in PyFrame_FastToLocals() above. */
    1346   [ #  #  #  # ]:          0 :             if (PyCell_Check(oldvalue) &&
    1347                 :          0 :                     _PyFrame_OpAlreadyRan(frame, MAKE_CELL, i)) {
    1348                 :            :                 // (likely) MAKE_CELL must have executed already.
    1349                 :          0 :                 cell = oldvalue;
    1350                 :            :             }
    1351                 :            :             // (unlikely) Otherwise, it must have been set to some
    1352                 :            :             // initial value by an earlier call to PyFrame_LocalsToFast().
    1353                 :            :         }
    1354         [ #  # ]:          0 :         if (cell != NULL) {
    1355                 :          0 :             oldvalue = PyCell_GET(cell);
    1356         [ #  # ]:          0 :             if (value != oldvalue) {
    1357                 :          0 :                 PyCell_SET(cell, Py_XNewRef(value));
    1358                 :          0 :                 Py_XDECREF(oldvalue);
    1359                 :            :             }
    1360                 :            :         }
    1361         [ #  # ]:          0 :         else if (value != oldvalue) {
    1362         [ #  # ]:          0 :             if (value == NULL) {
    1363                 :            :                 // Probably can't delete this, since the compiler's flow
    1364                 :            :                 // analysis may have already "proven" that it exists here:
    1365                 :          0 :                 const char *e = "assigning None to unbound local %R";
    1366         [ #  # ]:          0 :                 if (PyErr_WarnFormat(PyExc_RuntimeWarning, 0, e, name)) {
    1367                 :            :                     // It's okay if frame_obj is NULL, just try anyways:
    1368                 :          0 :                     PyErr_WriteUnraisable((PyObject *)frame->frame_obj);
    1369                 :            :                 }
    1370                 :          0 :                 value = Py_NewRef(Py_None);
    1371                 :            :             }
    1372                 :          0 :             Py_XSETREF(fast[i], Py_NewRef(value));
    1373                 :            :         }
    1374                 :          0 :         Py_XDECREF(value);
    1375                 :            :     }
    1376                 :        162 :     PyErr_SetRaisedException(exc);
    1377                 :            : }
    1378                 :            : 
    1379                 :            : void
    1380                 :          0 : PyFrame_LocalsToFast(PyFrameObject *f, int clear)
    1381                 :            : {
    1382                 :            :     assert(!_PyFrame_IsIncomplete(f->f_frame));
    1383   [ #  #  #  #  :          0 :     if (f && f->f_fast_as_locals && _PyFrame_GetState(f) != FRAME_CLEARED) {
                   #  # ]
    1384                 :          0 :         _PyFrame_LocalsToFast(f->f_frame, clear);
    1385                 :          0 :         f->f_fast_as_locals = 0;
    1386                 :            :     }
    1387                 :          0 : }
    1388                 :            : 
    1389                 :            : int
    1390                 :          0 : _PyFrame_IsEntryFrame(PyFrameObject *frame)
    1391                 :            : {
    1392                 :            :     assert(frame != NULL);
    1393                 :          0 :     _PyInterpreterFrame *f = frame->f_frame;
    1394                 :            :     assert(!_PyFrame_IsIncomplete(f));
    1395   [ #  #  #  # ]:          0 :     return f->previous && f->previous->owner == FRAME_OWNED_BY_CSTACK;
    1396                 :            : }
    1397                 :            : 
    1398                 :            : PyCodeObject *
    1399                 :        136 : PyFrame_GetCode(PyFrameObject *frame)
    1400                 :            : {
    1401                 :            :     assert(frame != NULL);
    1402                 :            :     assert(!_PyFrame_IsIncomplete(frame->f_frame));
    1403                 :        136 :     PyCodeObject *code = frame->f_frame->f_code;
    1404                 :            :     assert(code != NULL);
    1405                 :        136 :     return (PyCodeObject*)Py_NewRef(code);
    1406                 :            : }
    1407                 :            : 
    1408                 :            : 
    1409                 :            : PyFrameObject*
    1410                 :         24 : PyFrame_GetBack(PyFrameObject *frame)
    1411                 :            : {
    1412                 :            :     assert(frame != NULL);
    1413                 :            :     assert(!_PyFrame_IsIncomplete(frame->f_frame));
    1414                 :         24 :     PyFrameObject *back = frame->f_back;
    1415         [ +  - ]:         24 :     if (back == NULL) {
    1416                 :         24 :         _PyInterpreterFrame *prev = frame->f_frame->previous;
    1417                 :         24 :         prev = _PyFrame_GetFirstComplete(prev);
    1418         [ +  - ]:         24 :         if (prev) {
    1419                 :         24 :             back = _PyFrame_GetFrameObject(prev);
    1420                 :            :         }
    1421                 :            :     }
    1422                 :         24 :     return (PyFrameObject*)Py_XNewRef(back);
    1423                 :            : }
    1424                 :            : 
    1425                 :            : PyObject*
    1426                 :          0 : PyFrame_GetLocals(PyFrameObject *frame)
    1427                 :            : {
    1428                 :            :     assert(!_PyFrame_IsIncomplete(frame->f_frame));
    1429                 :          0 :     return frame_getlocals(frame, NULL);
    1430                 :            : }
    1431                 :            : 
    1432                 :            : PyObject*
    1433                 :          0 : PyFrame_GetGlobals(PyFrameObject *frame)
    1434                 :            : {
    1435                 :            :     assert(!_PyFrame_IsIncomplete(frame->f_frame));
    1436                 :          0 :     return frame_getglobals(frame, NULL);
    1437                 :            : }
    1438                 :            : 
    1439                 :            : PyObject*
    1440                 :          0 : PyFrame_GetBuiltins(PyFrameObject *frame)
    1441                 :            : {
    1442                 :            :     assert(!_PyFrame_IsIncomplete(frame->f_frame));
    1443                 :          0 :     return frame_getbuiltins(frame, NULL);
    1444                 :            : }
    1445                 :            : 
    1446                 :            : int
    1447                 :          0 : PyFrame_GetLasti(PyFrameObject *frame)
    1448                 :            : {
    1449                 :            :     assert(!_PyFrame_IsIncomplete(frame->f_frame));
    1450                 :          0 :     int lasti = _PyInterpreterFrame_LASTI(frame->f_frame);
    1451         [ #  # ]:          0 :     if (lasti < 0) {
    1452                 :          0 :         return -1;
    1453                 :            :     }
    1454                 :          0 :     return lasti * sizeof(_Py_CODEUNIT);
    1455                 :            : }
    1456                 :            : 
    1457                 :            : PyObject *
    1458                 :          0 : PyFrame_GetGenerator(PyFrameObject *frame)
    1459                 :            : {
    1460                 :            :     assert(!_PyFrame_IsIncomplete(frame->f_frame));
    1461         [ #  # ]:          0 :     if (frame->f_frame->owner != FRAME_OWNED_BY_GENERATOR) {
    1462                 :          0 :         return NULL;
    1463                 :            :     }
    1464                 :          0 :     PyGenObject *gen = _PyFrame_GetGenerator(frame->f_frame);
    1465                 :          0 :     return Py_NewRef(gen);
    1466                 :            : }
    1467                 :            : 
    1468                 :            : PyObject*
    1469                 :     198108 : _PyEval_BuiltinsFromGlobals(PyThreadState *tstate, PyObject *globals)
    1470                 :            : {
    1471                 :     198108 :     PyObject *builtins = PyDict_GetItemWithError(globals, &_Py_ID(__builtins__));
    1472         [ +  - ]:     198108 :     if (builtins) {
    1473         [ +  + ]:     198108 :         if (PyModule_Check(builtins)) {
    1474                 :      22409 :             builtins = _PyModule_GetDict(builtins);
    1475                 :            :             assert(builtins != NULL);
    1476                 :            :         }
    1477                 :     198108 :         return builtins;
    1478                 :            :     }
    1479         [ #  # ]:          0 :     if (PyErr_Occurred()) {
    1480                 :          0 :         return NULL;
    1481                 :            :     }
    1482                 :            : 
    1483                 :          0 :     return _PyEval_GetBuiltins(tstate);
    1484                 :            : }

Generated by: LCOV version 1.14