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