• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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