1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_ 18 #define SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_ 19 20 #include <cstddef> 21 #include <cstdint> 22 #include <initializer_list> 23 #include <type_traits> 24 #include <utility> 25 #include <vector> 26 27 #include "perfetto/base/logging.h" 28 #include "perfetto/public/compiler.h" 29 #include "perfetto/trace_processor/ref_counted.h" 30 #include "src/trace_processor/containers/row_map.h" 31 #include "src/trace_processor/containers/string_pool.h" 32 #include "src/trace_processor/db/column.h" 33 #include "src/trace_processor/db/column/overlay_layer.h" 34 #include "src/trace_processor/db/column/storage_layer.h" 35 #include "src/trace_processor/db/column_storage.h" 36 #include "src/trace_processor/db/column_storage_overlay.h" 37 #include "src/trace_processor/db/table.h" 38 39 namespace perfetto::trace_processor::macros_internal { 40 41 // We define this class to allow the table macro below to compile without 42 // needing templates; in reality none of the methods will be called because the 43 // pointer to this class will always be null. 44 class RootParentTable : public Table { 45 public: 46 struct Row { 47 public: 48 explicit Row(std::nullptr_t = nullptr) {} 49 typeRow50 const char* type() const { return type_; } 51 52 protected: 53 const char* type_ = nullptr; 54 }; 55 // This class only exists to allow typechecking to work correctly in Insert 56 // below. If we had C++17 and if constexpr, we could statically verify that 57 // this was never created but for now, we still need to define it to satisfy 58 // the typechecker. 59 struct IdAndRow { 60 uint32_t id; 61 }; 62 struct RowNumber { row_numberRowNumber63 static uint32_t row_number() { PERFETTO_FATAL("Should not be called"); } 64 }; Insert(const Row &)65 static IdAndRow Insert(const Row&) { PERFETTO_FATAL("Should not be called"); } 66 67 private: 68 explicit RootParentTable(std::nullptr_t); 69 }; 70 71 // The parent class for all macro generated tables. 72 // This class is used to extract common code from the macro tables to reduce 73 // code size. 74 class MacroTable : public Table { 75 public: 76 // We don't want a move or copy constructor because we store pointers to 77 // fields of macro tables which will be invalidated if we move/copy them. 78 MacroTable(const MacroTable&) = delete; 79 MacroTable& operator=(const MacroTable&) = delete; 80 81 MacroTable(MacroTable&&) = delete; 82 MacroTable& operator=(MacroTable&&) noexcept = delete; 83 84 protected: 85 // Constructors for tables created by the regular constructor. 86 PERFETTO_NO_INLINE explicit MacroTable(StringPool* pool, 87 std::vector<ColumnLegacy> columns, 88 const MacroTable* parent); 89 90 // Constructor for tables created by SelectAndExtendParent. 91 MacroTable(StringPool* pool, 92 std::vector<ColumnLegacy> columns, 93 const MacroTable& parent, 94 const RowMap& parent_overlay); 95 96 ~MacroTable() override; 97 98 PERFETTO_NO_INLINE void UpdateOverlaysAfterParentInsert(); 99 100 PERFETTO_NO_INLINE void UpdateSelfOverlayAfterInsert(); 101 102 PERFETTO_NO_INLINE static std::vector<ColumnLegacy> 103 CopyColumnsFromParentOrAddRootColumns(MacroTable* self, 104 const MacroTable* parent); 105 106 PERFETTO_NO_INLINE void OnConstructionCompletedRegularConstructor( 107 std::initializer_list<RefPtr<column::StorageLayer>> storage_layers, 108 std::initializer_list<RefPtr<column::OverlayLayer>> null_layers); 109 110 template <typename T> AddColumnToVector(std::vector<ColumnLegacy> & columns,const char * name,ColumnStorage<T> * storage,uint32_t flags,uint32_t column_index,uint32_t overlay_index)111 PERFETTO_NO_INLINE static void AddColumnToVector( 112 std::vector<ColumnLegacy>& columns, 113 const char* name, 114 ColumnStorage<T>* storage, 115 uint32_t flags, 116 uint32_t column_index, 117 uint32_t overlay_index) { 118 columns.emplace_back(name, storage, flags, column_index, overlay_index); 119 } 120 OverlayCount(const MacroTable * parent)121 static uint32_t OverlayCount(const MacroTable* parent) { 122 return parent ? static_cast<uint32_t>(parent->overlays().size()) : 0; 123 } 124 125 // Stores whether inserts are allowed into this macro table; by default 126 // inserts are allowed but they are disallowed when a parent table is extended 127 // with |ExtendParent|; the rationale for this is that extensions usually 128 // happen in dynamic tables and they should not be allowed to insert rows into 129 // the real (static) tables. 130 bool allow_inserts_ = true; 131 132 // Stores the most specific "derived" type of this row in the table. 133 // 134 // For example, suppose a row is inserted into the gpu_slice table. This will 135 // also cause a row to be inserted into the slice table. For users querying 136 // the slice table, they will want to know the "real" type of this slice (i.e. 137 // they will want to see that the type is gpu_slice). This sparse vector 138 // stores precisely the real type. 139 // 140 // Only relevant for parentless tables. Will be empty and unreferenced by 141 // tables with parents. 142 ColumnStorage<StringPool::Id> type_; 143 144 private: 145 PERFETTO_NO_INLINE static std::vector<ColumnStorageOverlay> 146 EmptyOverlaysFromParent(const MacroTable* parent); 147 PERFETTO_NO_INLINE static std::vector<ColumnStorageOverlay> 148 SelectedOverlaysFromParent(const macros_internal::MacroTable& parent, 149 const RowMap& rm); 150 151 const MacroTable* parent_ = nullptr; 152 }; 153 154 class BaseConstIterator { 155 public: 156 explicit operator bool() const; 157 BaseConstIterator& operator++(); 158 159 protected: 160 explicit BaseConstIterator(const MacroTable* table, Table::Iterator iterator); 161 162 Table::Iterator iterator_; 163 const MacroTable* table_; 164 }; 165 166 // Abstract iterator class for macro tables. 167 // Extracted to allow sharing with view code. 168 template <typename Iterator, 169 typename MacroTable, 170 typename RowNumber, 171 typename ConstRowReference> 172 class AbstractConstIterator : public BaseConstIterator { 173 public: 174 Iterator& operator++() { 175 return static_cast<Iterator&>(BaseConstIterator::operator++()); 176 } 177 178 // Returns a RowNumber for the current row. row_number()179 RowNumber row_number() const { 180 return RowNumber(this_it()->CurrentRowNumber()); 181 } 182 183 // Returns a ConstRowReference to the current row. row_reference()184 ConstRowReference row_reference() const { 185 return ConstRowReference(table(), this_it()->CurrentRowNumber()); 186 } 187 188 protected: AbstractConstIterator(const MacroTable * table,Table::Iterator iterator)189 explicit AbstractConstIterator(const MacroTable* table, 190 Table::Iterator iterator) 191 : BaseConstIterator(table, std::move(iterator)) {} 192 table()193 const MacroTable* table() const { 194 return static_cast<const MacroTable*>(table_); 195 } 196 197 private: this_it()198 Iterator* this_it() { return static_cast<Iterator*>(this); } this_it()199 const Iterator* this_it() const { return static_cast<const Iterator*>(this); } 200 }; 201 202 class BaseRowNumber { 203 public: 204 // Converts this object to the underlying int value. row_number()205 uint32_t row_number() const { return row_number_; } 206 207 // Allows sorting + storage in a map/set. 208 bool operator<(const BaseRowNumber& other) const { 209 return row_number_ < other.row_number_; 210 } 211 212 protected: BaseRowNumber(uint32_t row_number)213 explicit BaseRowNumber(uint32_t row_number) : row_number_(row_number) {} 214 215 uint32_t row_number_ = 0; 216 }; 217 218 // Abstract RowNumber class for macro tables. 219 // Extracted to allow sharing with view code. 220 template <typename MacroTable, 221 typename ConstRowReference, 222 typename RowReference = void> 223 class AbstractRowNumber : public BaseRowNumber { 224 public: 225 // Converts this RowNumber to a RowReference for the given |table|. 226 template <typename RR = RowReference> ToRowReference(MacroTable * table)227 RR ToRowReference(MacroTable* table) const { 228 static_assert(!std::is_same_v<RR, void>); 229 return RR(table, row_number_); 230 } 231 232 // Converts this RowNumber to a ConstRowReference for the given |table|. ToRowReference(const MacroTable & table)233 ConstRowReference ToRowReference(const MacroTable& table) const { 234 return ConstRowReference(&table, row_number_); 235 } 236 237 protected: AbstractRowNumber(uint32_t row_number)238 explicit AbstractRowNumber(uint32_t row_number) : BaseRowNumber(row_number) {} 239 }; 240 241 class BaseRowReference { 242 protected: 243 BaseRowReference(const MacroTable* table, uint32_t row_number); 244 245 const MacroTable* table_ = nullptr; 246 uint32_t row_number_ = 0; 247 }; 248 249 // Abstract ConstRowReference class for macro tables. 250 // Extracted to allow sharing with view code. 251 template <typename MacroTable, typename RowNumber> 252 class AbstractConstRowReference : public BaseRowReference { 253 public: 254 // Converts this RowReference to a RowNumber object which is more memory 255 // efficient to store. ToRowNumber()256 RowNumber ToRowNumber() { return RowNumber(row_number_); } 257 258 protected: table()259 const MacroTable* table() const { 260 return static_cast<const MacroTable*>(table_); 261 } 262 AbstractConstRowReference(const MacroTable * table,uint32_t row_number)263 AbstractConstRowReference(const MacroTable* table, uint32_t row_number) 264 : BaseRowReference(table, row_number) {} 265 }; 266 267 } // namespace perfetto::trace_processor::macros_internal 268 269 #endif // SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_ 270