Include/internal/pycore_shadow_frame.h (90 lines of code) (raw):

/* Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) */ #ifndef Py_SHADOW_FRAME_H #define Py_SHADOW_FRAME_H #include "Python.h" #include "frameobject.h" #include "internal/pycore_shadow_frame_struct.h" #include <stdint.h> #ifndef Py_LIMITED_API #ifdef __cplusplus extern "C" { #endif // TODO(mpage) - Generalize bit setting/getting into helpers? static const unsigned int _PyShadowFrame_NumTagBits = 3; static const uintptr_t _PyShadowFrame_TagMask = (1 << _PyShadowFrame_NumTagBits) - 1; static const uintptr_t _PyShadowFrame_PtrMask = ~_PyShadowFrame_TagMask; #define TAG_MASK(num_bits, off) ((1 << num_bits) - 1) << off static const unsigned int kShadowFrameSize = sizeof(_PyShadowFrame); #define SHADOW_FRAME_FIELD_OFF(field) (int{(offsetof(_PyShadowFrame, field))}) static const unsigned int _PyShadowFrame_NumPtrKindBits = 2; static const unsigned int _PyShadowFrame_PtrKindOff = 0; static const uintptr_t _PyShadowFrame_PtrKindMask = TAG_MASK(_PyShadowFrame_NumPtrKindBits, _PyShadowFrame_PtrKindOff); static const unsigned int _PyShadowFrame_NumOwnerBits = 1; static const unsigned int _PyShadowFrame_OwnerOff = _PyShadowFrame_NumPtrKindBits; static const uintptr_t _PyShadowFrame_OwnerMask = TAG_MASK(_PyShadowFrame_NumOwnerBits, _PyShadowFrame_OwnerOff); #undef TAG_MASK static inline _PyShadowFrame_PtrKind _PyShadowFrame_GetPtrKind(_PyShadowFrame *shadow_frame) { return (_PyShadowFrame_PtrKind)(shadow_frame->data & _PyShadowFrame_PtrKindMask); } static inline void _PyShadowFrame_SetOwner(_PyShadowFrame *shadow_frame, _PyShadowFrame_Owner owner) { uintptr_t data = shadow_frame->data & ~_PyShadowFrame_OwnerMask; shadow_frame->data = data | (owner << _PyShadowFrame_OwnerOff); } static inline _PyShadowFrame_Owner _PyShadowFrame_GetOwner(_PyShadowFrame *shadow_frame) { uintptr_t data = shadow_frame->data & _PyShadowFrame_OwnerMask; return (_PyShadowFrame_Owner)(data >> _PyShadowFrame_OwnerOff); } static inline void *_PyShadowFrame_GetPtr(_PyShadowFrame *shadow_frame) { return (void *)(shadow_frame->data & _PyShadowFrame_PtrMask); } static inline PyFrameObject * _PyShadowFrame_GetPyFrame(_PyShadowFrame *shadow_frame) { assert(_PyShadowFrame_GetPtrKind(shadow_frame) == PYSF_PYFRAME); return (PyFrameObject *)_PyShadowFrame_GetPtr(shadow_frame); } int _PyShadowFrame_HasGen(_PyShadowFrame *shadow_frame); PyGenObject *_PyShadowFrame_GetGen(_PyShadowFrame *shadow_frame); void _PyShadowFrame_DumpStack(PyThreadState* state); static inline uintptr_t _PyShadowFrame_MakeData(void *ptr, _PyShadowFrame_PtrKind ptr_kind, _PyShadowFrame_Owner owner) { assert(((uintptr_t)ptr & _PyShadowFrame_PtrKindMask) == 0); return (uintptr_t)ptr | (owner << _PyShadowFrame_OwnerOff) | (ptr_kind << _PyShadowFrame_PtrKindOff); } static inline void _PyShadowFrame_PushInterp(PyThreadState *tstate, _PyShadowFrame *shadow_frame, PyFrameObject *py_frame) { shadow_frame->prev = tstate->shadow_frame; tstate->shadow_frame = shadow_frame; shadow_frame->data = _PyShadowFrame_MakeData(py_frame, PYSF_PYFRAME, PYSF_INTERP); } static inline void _PyShadowFrame_Pop(PyThreadState *tstate, _PyShadowFrame *shadow_frame) { assert(tstate->shadow_frame == shadow_frame); tstate->shadow_frame = shadow_frame->prev; shadow_frame->prev = NULL; } /* Return a borrowed reference to the code object for shadow_frame */ PyCodeObject *_PyShadowFrame_GetCode(_PyShadowFrame *shadow_frame); /* Returns the fully qualified name of code running in the frame */ PyObject *_PyShadowFrame_GetFullyQualifiedName(_PyShadowFrame *shadow_frame); /* Populates codeobject pointers in the given arrays. Meant to only be called from profiling frameworks. Both async_stack and sync_stack contain borrowed references. `async_stack` - Contains pointers to PyCodeObject on successful run. If errors occur, the contents should not be used. `async_linenos` - Is populated with the line numbers (corresponding to each) entry in `async_stack` `sync_stack` - Similar to `async_stack`, but contains sync stack entries. `sync_linenos` - Similar to `async_linenos`, but contains for the sync stack. `array_len` - Assumes that all the above arrays are of the same length, which is specified by this parameter. `async_stack_len_out`, `sync_stack_len_out` - These are out parameters. On successful run, they contain the lengths of the async and sync stacks respectively. */ PyAPI_FUNC(int) _PyShadowFrame_WalkAndPopulate( PyCodeObject** async_stack, int* async_linenos, PyCodeObject** sync_stack, int* sync_linenos, int array_capacity, int* async_stack_len_out, int* sync_stack_len_out); /* Looks up the awaiter shadow frame (if any) from the given shadow frame */ _PyShadowFrame* _PyShadowFrame_GetAwaiterFrame(_PyShadowFrame *shadow_frame); #ifdef __cplusplus } #endif #endif /* Py_LIMITED_API */ #endif /* !Py_SHADOW_FRAME_H */