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/compiler.h" 28 #include "perfetto/base/logging.h" 29 #include "perfetto/trace_processor/ref_counted.h" 30 #include "src/trace_processor/containers/bit_vector.h" 31 #include "src/trace_processor/containers/row_map.h" 32 #include "src/trace_processor/containers/string_pool.h" 33 #include "src/trace_processor/db/column.h" 34 #include "src/trace_processor/db/column/data_layer.h" 35 #include "src/trace_processor/db/column/selector_overlay.h" 36 #include "src/trace_processor/db/column_storage.h" 37 #include "src/trace_processor/db/column_storage_overlay.h" 38 #include "src/trace_processor/db/table.h" 39 40 namespace perfetto::trace_processor::macros_internal { 41 42 // We define this class to allow the table macro below to compile without 43 // needing templates; in reality none of the methods will be called because the 44 // pointer to this class will always be null. 45 class RootParentTable : public Table { 46 public: 47 struct Row { 48 public: 49 explicit Row(std::nullptr_t = nullptr) {} 50 typeRow51 const char* type() const { return type_; } 52 53 protected: 54 const char* type_ = nullptr; 55 }; 56 // This class only exists to allow typechecking to work correctly in Insert 57 // below. If we had C++17 and if constexpr, we could statically verify that 58 // this was never created but for now, we still need to define it to satisfy 59 // the typechecker. 60 struct IdAndRow { 61 uint32_t id; 62 }; 63 struct RowNumber { row_numberRowNumber64 static uint32_t row_number() { PERFETTO_FATAL("Should not be called"); } 65 }; Insert(const Row &)66 static IdAndRow Insert(const Row&) { PERFETTO_FATAL("Should not be called"); } 67 68 private: 69 explicit RootParentTable(std::nullptr_t); 70 }; 71 72 // The parent class for all macro generated tables. 73 // This class is used to extract common code from the macro tables to reduce 74 // code size. 75 class MacroTable : public Table { 76 public: 77 // We don't want a move or copy constructor because we store pointers to 78 // fields of macro tables which will be invalidated if we move/copy them. 79 MacroTable(const MacroTable&) = delete; 80 MacroTable& operator=(const MacroTable&) = delete; 81 82 MacroTable(MacroTable&&) = delete; 83 MacroTable& operator=(MacroTable&&) noexcept = delete; 84 85 protected: 86 // Constructors for tables created by the regular constructor. MacroTable(StringPool * pool,std::vector<ColumnLegacy> columns,const MacroTable * parent)87 PERFETTO_NO_INLINE explicit MacroTable(StringPool* pool, 88 std::vector<ColumnLegacy> columns, 89 const MacroTable* parent) 90 : Table(pool, 0u, std::move(columns), EmptyOverlaysFromParent(parent)), 91 allow_inserts_(true), 92 parent_(parent) {} 93 94 // Constructor for tables created by SelectAndExtendParent. MacroTable(StringPool * pool,std::vector<ColumnLegacy> columns,const MacroTable & parent,const RowMap & parent_overlay)95 MacroTable(StringPool* pool, 96 std::vector<ColumnLegacy> columns, 97 const MacroTable& parent, 98 const RowMap& parent_overlay) 99 : Table(pool, 100 parent_overlay.size(), 101 std::move(columns), 102 SelectedOverlaysFromParent(parent, parent_overlay)), 103 allow_inserts_(false), 104 parent_(&parent) {} 105 106 ~MacroTable() override; 107 UpdateOverlaysAfterParentInsert()108 PERFETTO_NO_INLINE void UpdateOverlaysAfterParentInsert() { 109 CopyLastInsertFrom(parent_->overlays()); 110 } 111 UpdateSelfOverlayAfterInsert()112 PERFETTO_NO_INLINE void UpdateSelfOverlayAfterInsert() { 113 IncrementRowCountAndAddToLastOverlay(); 114 } 115 116 PERFETTO_NO_INLINE static std::vector<ColumnLegacy> CopyColumnsFromParentOrAddRootColumns(MacroTable * self,const MacroTable * parent)117 CopyColumnsFromParentOrAddRootColumns(MacroTable* self, 118 const MacroTable* parent) { 119 std::vector<ColumnLegacy> columns; 120 if (parent) { 121 for (const ColumnLegacy& col : parent->columns()) { 122 columns.emplace_back(col, col.index_in_table(), col.overlay_index()); 123 } 124 } else { 125 columns.emplace_back(ColumnLegacy::IdColumn(0, 0)); 126 columns.emplace_back("type", &self->type_, ColumnLegacy::kNonNull, 1, 0); 127 } 128 return columns; 129 } 130 OnConstructionCompletedRegularConstructor(std::initializer_list<RefPtr<column::DataLayer>> storage_layers,std::initializer_list<RefPtr<column::DataLayer>> null_layers)131 PERFETTO_NO_INLINE void OnConstructionCompletedRegularConstructor( 132 std::initializer_list<RefPtr<column::DataLayer>> storage_layers, 133 std::initializer_list<RefPtr<column::DataLayer>> null_layers) { 134 std::vector<RefPtr<column::DataLayer>> overlay_layers( 135 OverlayCount(parent_) + 1); 136 for (uint32_t i = 0; i < overlay_layers.size() - 1; ++i) { 137 PERFETTO_CHECK(overlays()[i].row_map().IsBitVector()); 138 overlay_layers[i].reset(new column::SelectorOverlay( 139 overlays()[i].row_map().GetIfBitVector())); 140 } 141 Table::OnConstructionCompleted(storage_layers, null_layers, 142 std::move(overlay_layers)); 143 } 144 145 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)146 PERFETTO_NO_INLINE static void AddColumnToVector( 147 std::vector<ColumnLegacy>& columns, 148 const char* name, 149 ColumnStorage<T>* storage, 150 uint32_t flags, 151 uint32_t column_index, 152 uint32_t overlay_index) { 153 columns.emplace_back(name, storage, flags, column_index, overlay_index); 154 } 155 OverlayCount(const MacroTable * parent)156 static uint32_t OverlayCount(const MacroTable* parent) { 157 return parent ? static_cast<uint32_t>(parent->overlays().size()) : 0; 158 } 159 160 // Stores whether inserts are allowed into this macro table; by default 161 // inserts are allowed but they are disallowed when a parent table is extended 162 // with |ExtendParent|; the rationale for this is that extensions usually 163 // happen in dynamic tables and they should not be allowed to insert rows into 164 // the real (static) tables. 165 bool allow_inserts_ = true; 166 167 // Stores the most specific "derived" type of this row in the table. 168 // 169 // For example, suppose a row is inserted into the gpu_slice table. This will 170 // also cause a row to be inserted into the slice table. For users querying 171 // the slice table, they will want to know the "real" type of this slice (i.e. 172 // they will want to see that the type is gpu_slice). This sparse vector 173 // stores precisely the real type. 174 // 175 // Only relevant for parentless tables. Will be empty and unreferenced by 176 // tables with parents. 177 ColumnStorage<StringPool::Id> type_; 178 179 private: 180 PERFETTO_NO_INLINE static std::vector<ColumnStorageOverlay> EmptyOverlaysFromParent(const MacroTable * parent)181 EmptyOverlaysFromParent(const MacroTable* parent) { 182 std::vector<ColumnStorageOverlay> overlays( 183 parent ? parent->overlays().size() : 0); 184 for (auto& overlay : overlays) { 185 overlay = ColumnStorageOverlay(BitVector()); 186 } 187 overlays.emplace_back(); 188 return overlays; 189 } 190 PERFETTO_NO_INLINE static std::vector<ColumnStorageOverlay> SelectedOverlaysFromParent(const macros_internal::MacroTable & parent,const RowMap & rm)191 SelectedOverlaysFromParent(const macros_internal::MacroTable& parent, 192 const RowMap& rm) { 193 std::vector<ColumnStorageOverlay> overlays; 194 for (const auto& overlay : parent.overlays()) { 195 overlays.emplace_back(overlay.SelectRows(rm)); 196 PERFETTO_DCHECK(overlays.back().size() == rm.size()); 197 } 198 overlays.emplace_back(rm.size()); 199 return overlays; 200 } 201 202 const MacroTable* parent_ = nullptr; 203 }; 204 205 // Abstract iterator class for macro tables. 206 // Extracted to allow sharing with view code. 207 template <typename Iterator, 208 typename MacroTable, 209 typename RowNumber, 210 typename ConstRowReference> 211 class AbstractConstIterator { 212 public: 213 explicit operator bool() const { return bool(iterator_); } 214 215 Iterator& operator++() { 216 ++iterator_; 217 return *this_it(); 218 } 219 220 // Returns a RowNumber for the current row. row_number()221 RowNumber row_number() const { 222 return RowNumber(this_it()->CurrentRowNumber()); 223 } 224 225 // Returns a ConstRowReference to the current row. row_reference()226 ConstRowReference row_reference() const { 227 return ConstRowReference(table_, this_it()->CurrentRowNumber()); 228 } 229 230 protected: AbstractConstIterator(const MacroTable * table,Table::Iterator iterator)231 explicit AbstractConstIterator(const MacroTable* table, 232 Table::Iterator iterator) 233 : iterator_(std::move(iterator)), table_(table) { 234 static_assert(std::is_base_of<Table, MacroTable>::value, 235 "Template param should be a subclass of Table."); 236 } 237 238 Table::Iterator iterator_; 239 const MacroTable* table_; 240 241 private: this_it()242 Iterator* this_it() { return static_cast<Iterator*>(this); } this_it()243 const Iterator* this_it() const { return static_cast<const Iterator*>(this); } 244 }; 245 246 // Abstract RowNumber class for macro tables. 247 // Extracted to allow sharing with view code. 248 template <typename MacroTable, 249 typename ConstRowReference, 250 typename RowReference = void> 251 class AbstractRowNumber { 252 public: 253 // Converts this RowNumber to a RowReference for the given |table|. 254 template < 255 typename RR = RowReference, 256 typename = typename std::enable_if<!std::is_same<RR, void>::value>::type> ToRowReference(MacroTable * table)257 RR ToRowReference(MacroTable* table) const { 258 return RR(table, row_number_); 259 } 260 261 // Converts this RowNumber to a ConstRowReference for the given |table|. ToRowReference(const MacroTable & table)262 ConstRowReference ToRowReference(const MacroTable& table) const { 263 return ConstRowReference(&table, row_number_); 264 } 265 266 // Converts this object to the underlying int value. row_number()267 uint32_t row_number() const { return row_number_; } 268 269 // Allows sorting + storage in a map/set. 270 bool operator<(const AbstractRowNumber& other) const { 271 return row_number_ < other.row_number_; 272 } 273 274 protected: AbstractRowNumber(uint32_t row_number)275 explicit AbstractRowNumber(uint32_t row_number) : row_number_(row_number) {} 276 277 private: 278 uint32_t row_number_ = 0; 279 }; 280 281 // Abstract ConstRowReference class for macro tables. 282 // Extracted to allow sharing with view code. 283 template <typename MacroTable, typename RowNumber> 284 class AbstractConstRowReference { 285 public: 286 // Converts this RowReference to a RowNumber object which is more memory 287 // efficient to store. ToRowNumber()288 RowNumber ToRowNumber() { return RowNumber(row_number_); } 289 290 protected: AbstractConstRowReference(const MacroTable * table,uint32_t row_number)291 AbstractConstRowReference(const MacroTable* table, uint32_t row_number) 292 : table_(table), row_number_(row_number) {} 293 294 const MacroTable* table_ = nullptr; 295 uint32_t row_number_ = 0; 296 }; 297 298 } // namespace perfetto::trace_processor::macros_internal 299 300 #endif // SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_ 301