#pragma once #include #include namespace torch { // struct that holds the result of symbolizing multiple tracebacks // each traceback is a list of indices into all_frames // (lots of Frames get duplicated across traces) struct TORCH_API SymbolizedTracebacks { std::vector all_frames; // index into all_frames, so that // it is possible to dedupe frame objects in // construction of python objects std::vector> tracebacks; }; struct TORCH_API CapturedTraceback : public c10::GatheredContext { struct PyFrame { void* code; // PyCodeObject*, but python headers not present int lasti; }; static std::shared_ptr gather( bool python, bool script, bool cpp); CapturedTraceback() = default; CapturedTraceback(const CapturedTraceback&) = delete; CapturedTraceback& operator=(const CapturedTraceback&) = delete; CapturedTraceback(CapturedTraceback&&) noexcept = default; CapturedTraceback& operator=(CapturedTraceback&&) noexcept = delete; ~CapturedTraceback() override; using visitproc = int (*)(void* self, void* arg); struct Python { virtual std::vector gather() = 0; virtual void release(std::vector& frames) = 0; virtual void appendSymbolized( const std::vector& to_symbolize, SymbolizedTracebacks& st) = 0; // tp_traverse/tp_clear implementations virtual int traverse( std::vector& frames, visitproc visit, void* arg) = 0; virtual int clear(std::vector& frames) = 0; virtual ~Python() = default; Python* next_ = nullptr; }; // called once by each python interpreter to // register python stack recording functionality // p cannot be deleted once added. static void addPythonUnwinder(Python* p); int traversePython(visitproc visit, void* arg); int clearPython(); private: std::vector frames_; std::vector cpp_frames_; std::vector script_frames_; friend TORCH_API SymbolizedTracebacks symbolize(const std::vector& to_symbolize); // non-owning reference to one of the immortal Python* objects // registered above. Python* python_ = nullptr; }; TORCH_API SymbolizedTracebacks symbolize(const std::vector& to_symbolize); } // namespace torch