1  
       2  #include "Python.h"
       3  #include "frameobject.h"
       4  #include "pycore_code.h"          // stats
       5  #include "pycore_frame.h"
       6  #include "pycore_object.h"        // _PyObject_GC_UNTRACK()
       7  #include "opcode.h"
       8  
       9  int
      10  _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg)
      11  {
      12      Py_VISIT(frame->frame_obj);
      13      Py_VISIT(frame->f_locals);
      14      Py_VISIT(frame->f_func);
      15      Py_VISIT(frame->f_code);
      16     /* locals */
      17      PyObject **locals = _PyFrame_GetLocalsArray(frame);
      18      int i = 0;
      19      /* locals and stack */
      20      for (; i <frame->stacktop; i++) {
      21          Py_VISIT(locals[i]);
      22      }
      23      return 0;
      24  }
      25  
      26  PyFrameObject *
      27  _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
      28  {
      29      assert(frame->frame_obj == NULL);
      30      PyObject *error_type, *error_value, *error_traceback;
      31      PyErr_Fetch(&error_type, &error_value, &error_traceback);
      32  
      33      PyFrameObject *f = _PyFrame_New_NoTrack(frame->f_code);
      34      if (f == NULL) {
      35          Py_XDECREF(error_type);
      36          Py_XDECREF(error_value);
      37          Py_XDECREF(error_traceback);
      38          return NULL;
      39      }
      40      PyErr_Restore(error_type, error_value, error_traceback);
      41      if (frame->frame_obj) {
      42          // GH-97002: How did we get into this horrible situation? Most likely,
      43          // allocating f triggered a GC collection, which ran some code that
      44          // *also* created the same frame... while we were in the middle of
      45          // creating it! See test_sneaky_frame_object in test_frame.py for a
      46          // concrete example.
      47          //
      48          // Regardless, just throw f away and use that frame instead, since it's
      49          // already been exposed to user code. It's actually a bit tricky to do
      50          // this, since we aren't backed by a real _PyInterpreterFrame anymore.
      51          // Just pretend that we have an owned, cleared frame so frame_dealloc
      52          // doesn't make the situation worse:
      53          f->f_frame = (_PyInterpreterFrame *)f->_f_frame_data;
      54          f->f_frame->owner = FRAME_CLEARED;
      55          f->f_frame->frame_obj = f;
      56          Py_DECREF(f);
      57          return frame->frame_obj;
      58      }
      59      assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
      60      assert(frame->owner != FRAME_CLEARED);
      61      f->f_frame = frame;
      62      frame->frame_obj = f;
      63      return f;
      64  }
      65  
      66  void
      67  _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
      68  {
      69      assert(src->stacktop >= src->f_code->co_nlocalsplus);
      70      Py_ssize_t size = ((char*)&src->localsplus[src->stacktop]) - (char *)src;
      71      memcpy(dest, src, size);
      72      // Don't leave a dangling pointer to the old frame when creating generators
      73      // and coroutines:
      74      dest->previous = NULL;
      75  }
      76  
      77  
      78  static void
      79  take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
      80  {
      81      assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
      82      assert(frame->owner != FRAME_CLEARED);
      83      Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame;
      84      memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);
      85      frame = (_PyInterpreterFrame *)f->_f_frame_data;
      86      f->f_frame = frame;
      87      frame->owner = FRAME_OWNED_BY_FRAME_OBJECT;
      88      if (_PyFrame_IsIncomplete(frame)) {
      89          // This may be a newly-created generator or coroutine frame. Since it's
      90          // dead anyways, just pretend that the first RESUME ran:
      91          PyCodeObject *code = frame->f_code;
      92          frame->prev_instr = _PyCode_CODE(code) + code->_co_firsttraceable;
      93      }
      94      assert(!_PyFrame_IsIncomplete(frame));
      95      assert(f->f_back == NULL);
      96      _PyInterpreterFrame *prev = frame->previous;
      97      while (prev && _PyFrame_IsIncomplete(prev)) {
      98          prev = prev->previous;
      99      }
     100      if (prev) {
     101          /* Link PyFrameObjects.f_back and remove link through _PyInterpreterFrame.previous */
     102          PyFrameObject *back = _PyFrame_GetFrameObject(prev);
     103          if (back == NULL) {
     104              /* Memory error here. */
     105              assert(PyErr_ExceptionMatches(PyExc_MemoryError));
     106              /* Nothing we can do about it */
     107              PyErr_Clear();
     108          }
     109          else {
     110              f->f_back = (PyFrameObject *)Py_NewRef(back);
     111          }
     112          frame->previous = NULL;
     113      }
     114      if (!_PyObject_GC_IS_TRACKED((PyObject *)f)) {
     115          _PyObject_GC_TRACK((PyObject *)f);
     116      }
     117  }
     118  
     119  void
     120  _PyFrame_Clear(_PyInterpreterFrame *frame)
     121  {
     122      /* It is the responsibility of the owning generator/coroutine
     123       * to have cleared the enclosing generator, if any. */
     124      assert(frame->owner != FRAME_OWNED_BY_GENERATOR ||
     125          _PyFrame_GetGenerator(frame)->gi_frame_state == FRAME_CLEARED);
     126      // GH-99729: Clearing this frame can expose the stack (via finalizers). It's
     127      // crucial that this frame has been unlinked, and is no longer visible:
     128      assert(_PyThreadState_GET()->cframe->current_frame != frame);
     129      if (frame->frame_obj) {
     130          PyFrameObject *f = frame->frame_obj;
     131          frame->frame_obj = NULL;
     132          if (Py_REFCNT(f) > 1) {
     133              take_ownership(f, frame);
     134              Py_DECREF(f);
     135              return;
     136          }
     137          Py_DECREF(f);
     138      }
     139      assert(frame->stacktop >= 0);
     140      for (int i = 0; i < frame->stacktop; i++) {
     141          Py_XDECREF(frame->localsplus[i]);
     142      }
     143      Py_XDECREF(frame->frame_obj);
     144      Py_XDECREF(frame->f_locals);
     145      Py_DECREF(frame->f_func);
     146      Py_DECREF(frame->f_code);
     147  }
     148  
     149  /* Consumes reference to func */
     150  _PyInterpreterFrame *
     151  _PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func)
     152  {
     153      PyCodeObject *code = (PyCodeObject *)func->func_code;
     154      size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE;
     155      CALL_STAT_INC(frames_pushed);
     156      _PyInterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size);
     157      if (new_frame == NULL) {
     158          Py_DECREF(func);
     159          return NULL;
     160      }
     161      _PyFrame_InitializeSpecials(new_frame, func, NULL, code->co_nlocalsplus);
     162      return new_frame;
     163  }
     164  
     165  int
     166  _PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame)
     167  {
     168      int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT);
     169      return PyCode_Addr2Line(frame->f_code, addr);
     170  }