GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — cpython/Python/frame.c at main · python/cpython Expand file tree/ Copy pathframe.cMore file actions 158 lines (145 loc) · 5.45 KB / Copy pathframe.cFile metadata and controls158 lines (145 loc) · 5.45 KB 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 #define _PY_INTERPRETER #include "Python.h" #include "pycore_frame.h" // _PyFrame_New_NoTrack() #include "pycore_interpframe.h" // _PyFrame_GetCode() #include "pycore_genobject.h" // _PyGen_GetGeneratorFromFrame() #include "pycore_stackref.h" // _Py_VISIT_STACKREF() int _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg) { Py_VISIT(frame->frame_obj); Py_VISIT(frame->f_locals); _Py_VISIT_STACKREF(frame->f_funcobj); _Py_VISIT_STACKREF(frame->f_executable); return _PyGC_VisitFrameStack(frame, visit, arg); } PyFrameObject * _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame) { PyObject *exc = PyErr_GetRaisedException(); PyFrameObject *f = _PyFrame_New_NoTrack(_PyFrame_GetCode(frame)); if (f == NULL) { Py_XDECREF(exc); return NULL; } PyErr_SetRaisedException(exc); // GH-97002: There was a time when a frame object could be created when we // are allocating the new frame object f above, so frame->frame_obj would // be assigned already. That path does not exist anymore. We won't call any // Python code in this function and garbage collection will not run. // Notice that _PyFrame_New_NoTrack() can potentially raise a MemoryError, // but it won't allocate a traceback until the frame unwinds, so we are safe // here. assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT); f->f_frame = frame; #ifdef Py_GIL_DISABLED PyFrameObject *expected = NULL; if (!_Py_atomic_compare_exchange_ptr(&frame->frame_obj, &expected, f)) { Py_DECREF(f); return expected; } #else assert(frame->frame_obj == NULL); frame->frame_obj = f; #endif return f; } static void take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame) { Py_BEGIN_CRITICAL_SECTION(f); assert(frame->owner < FRAME_OWNED_BY_INTERPRETER); assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT); _PyInterpreterFrame *new_frame = (_PyInterpreterFrame *)f->_f_frame_data; _PyFrame_Copy(frame, new_frame); // _PyFrame_Copy takes the reference to the executable, // so we need to restore it. new_frame->f_executable = PyStackRef_DUP(new_frame->f_executable); f->f_frame = new_frame; new_frame->owner = FRAME_OWNED_BY_FRAME_OBJECT; if (_PyFrame_IsIncomplete(new_frame)) { // This may be a newly-created generator or coroutine frame. Since it's // dead anyways, just pretend that the first RESUME ran: PyCodeObject *code = _PyFrame_GetCode(new_frame); new_frame->instr_ptr = _PyFrame_GetBytecode(new_frame) + code->_co_firsttraceable + 1; } assert(!_PyFrame_IsIncomplete(new_frame)); assert(f->f_back == NULL); _PyInterpreterFrame *prev = _PyFrame_GetFirstComplete(frame->previous); if (prev) { assert(prev->owner < FRAME_OWNED_BY_INTERPRETER); PyObject *exc = PyErr_GetRaisedException(); /* Link PyFrameObjects.f_back and remove link through _PyInterpreterFrame.previous */ PyFrameObject *back = _PyFrame_GetFrameObject(prev); if (back == NULL) { /* Memory error here. */ assert(PyErr_ExceptionMatches(PyExc_MemoryError)); /* Nothing we can do about it */ PyErr_Clear(); } else { f->f_back = (PyFrameObject *)Py_NewRef(back); } PyErr_SetRaisedException(exc); } if (!_PyObject_GC_IS_TRACKED((PyObject *)f)) { _PyObject_GC_TRACK((PyObject *)f); } Py_END_CRITICAL_SECTION(); } void _PyFrame_ClearLocals(_PyInterpreterFrame *frame) { assert(frame->stackpointer != NULL); _PyStackRef *sp = frame->stackpointer; _PyStackRef *locals = frame->localsplus; frame->stackpointer = locals; while (sp > locals) { sp--; PyStackRef_XCLOSE(*sp); } Py_CLEAR(frame->f_locals); } void _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame) { /* It is the responsibility of the owning generator/coroutine * to have cleared the enclosing generator, if any. */ assert(frame->owner != FRAME_OWNED_BY_GENERATOR || FT_ATOMIC_LOAD_INT8_RELAXED(_PyGen_GetGeneratorFromFrame(frame)->gi_frame_state) == FRAME_CLEARED); // GH-99729: Clearing this frame can expose the stack (via finalizers). It's // crucial that this frame has been unlinked, and is no longer visible: assert(_PyThreadState_GET()->current_frame != frame); PyFrameObject *f = FT_ATOMIC_LOAD_PTR_RELAXED(frame->frame_obj); if (f != NULL) { FT_ATOMIC_STORE_PTR_RELAXED(frame->frame_obj, NULL); if (!_PyObject_IsUniquelyReferenced((PyObject *)f)) { take_ownership(f, frame); Py_DECREF(f); return; } Py_DECREF(f); } _PyFrame_ClearLocals(frame); PyStackRef_CLEAR(frame->f_funcobj); } /* Unstable API functions */ PyObject * PyUnstable_InterpreterFrame_GetCode(struct _PyInterpreterFrame *frame) { return PyStackRef_AsPyObjectNew(frame->f_executable); } // NOTE: We allow racy accesses to the instruction pointer from other threads // for sys._current_frames() and similar APIs. int _Py_NO_SANITIZE_THREAD PyUnstable_InterpreterFrame_GetLasti(struct _PyInterpreterFrame *frame) { return _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT); } int _Py_NO_SANITIZE_THREAD PyUnstable_InterpreterFrame_GetLine(_PyInterpreterFrame *frame) { int addr = _PyInterpreterFrame_LASTI(frame) * sizeof(_Py_CODEUNIT); return PyCode_Addr2Line(_PyFrame_GetCode(frame), addr); } |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |