File indexing completed on 2024-05-12 17:15:55
0001 /* 0002 SPDX-FileCopyrightText: 2014-2017 Milian Wolff <mail@milianw.de> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #ifndef TRACETREE_H 0008 #define TRACETREE_H 0009 0010 /** 0011 * @file tracetree.h 0012 * @brief Efficiently combine and store the data of multiple Traces. 0013 */ 0014 0015 #include <algorithm> 0016 #include <vector> 0017 0018 #include "trace.h" 0019 0020 struct TraceEdge 0021 { 0022 Trace::ip_t instructionPointer; 0023 // index associated to the backtrace up to this instruction pointer 0024 // the evaluation process can then reverse-map the index to the parent ip 0025 // to rebuild the backtrace from the bottom-up 0026 uint32_t index; 0027 // sorted list of children, assumed to be small 0028 std::vector<TraceEdge> children; 0029 }; 0030 0031 /** 0032 * Top-down tree of backtrace instruction pointers. 0033 * 0034 * This is supposed to be a memory efficient storage of all instruction pointers 0035 * ever encountered in any backtrace. 0036 */ 0037 class TraceTree 0038 { 0039 public: 0040 void clear() 0041 { 0042 m_root.children.clear(); 0043 m_index = 1; 0044 } 0045 0046 /** 0047 * Index the data in @p trace and return the index of the last instruction 0048 * pointer. 0049 * 0050 * Unknown instruction pointers will be handled by the @p callback 0051 */ 0052 template <typename Fun> 0053 uint32_t index(const Trace& trace, Fun callback) 0054 { 0055 uint32_t index = 0; 0056 TraceEdge* parent = &m_root; 0057 for (int i = trace.size() - 1; i >= 0; --i) { 0058 const auto ip = trace[i]; 0059 if (!ip) { 0060 continue; 0061 } 0062 auto it = 0063 std::lower_bound(parent->children.begin(), parent->children.end(), ip, 0064 [](const TraceEdge& l, const Trace::ip_t ip) { return l.instructionPointer < ip; }); 0065 if (it == parent->children.end() || it->instructionPointer != ip) { 0066 index = m_index++; 0067 it = parent->children.insert(it, {ip, index, {}}); 0068 if (!callback(reinterpret_cast<uintptr_t>(ip), parent->index)) { 0069 return 0; 0070 } 0071 } 0072 index = it->index; 0073 parent = &(*it); 0074 } 0075 return index; 0076 } 0077 0078 private: 0079 TraceEdge m_root = {0, 0, {}}; 0080 uint32_t m_index = 1; 0081 }; 0082 0083 #endif // TRACETREE_H