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 "src/trace_processor/db/table.h"
23 #include "src/trace_processor/db/typed_column.h"
24 
25 namespace perfetto {
26 namespace trace_processor {
27 namespace macros_internal {
28 
29 // We define this class to allow the table macro below to compile without
30 // needing templates; in reality none of the methods will be called because the
31 // pointer to this class will always be null.
32 class RootParentTable : public Table {
33  public:
34   struct Row {
35    public:
RowRow36     Row(std::nullptr_t) {}
37 
typeRow38     const char* type() const { return type_; }
39 
40    protected:
41     const char* type_ = nullptr;
42   };
43   // This class only exists to allow typechecking to work correctly in Insert
44   // below. If we had C++17 and if constexpr, we could statically verify that
45   // this was never created but for now, we still need to define it to satisfy
46   // the typechecker.
47   struct IdAndRow {
48     uint32_t id;
49     uint32_t row;
50   };
Insert(const Row &)51   IdAndRow Insert(const Row&) { PERFETTO_FATAL("Should not be called"); }
52 };
53 
54 // IdHelper is used to figure out the Id type for a table.
55 //
56 // We do this using templates with the following algorithm:
57 // 1. If the parent class is anything but RootParentTable, the Id of the
58 //    table is the same as the Id of the parent.
59 // 2. If the parent class is RootParentTable (i.e. the table is a root
60 //    table), then the Id is the one defined in the table itself.
61 // The net result of this is that all tables in the hierarchy get the
62 // same type of Id - the one defined in the root table of that hierarchy.
63 //
64 // Reasoning: We do this because using uint32_t is very overloaded and
65 // having a wrapper type for ids is very helpful to avoid confusion with
66 // row indices (especially because ids and row indices often appear in
67 // similar places in the codebase - that is at insertion in parsers and
68 // in trackers).
69 template <typename ParentClass, typename Class>
70 struct IdHelper {
71   using Id = typename ParentClass::Id;
72 };
73 template <typename Class>
74 struct IdHelper<RootParentTable, Class> {
75   using Id = typename Class::DefinedId;
76 };
77 
78 // The parent class for all macro generated tables.
79 // This class is used to extract common code from the macro tables to reduce
80 // code size.
81 class MacroTable : public Table {
82  public:
83   MacroTable(const char* name, StringPool* pool, Table* parent)
84       : Table(pool, parent), name_(name), parent_(parent) {
85     row_maps_.emplace_back();
86     if (!parent) {
87       columns_.emplace_back(
88           Column::IdColumn(this, static_cast<uint32_t>(columns_.size()),
89                            static_cast<uint32_t>(row_maps_.size()) - 1));
90       columns_.emplace_back(
91           Column("type", &type_, Column::kNoFlag, this,
92                  static_cast<uint32_t>(columns_.size()),
93                  static_cast<uint32_t>(row_maps_.size()) - 1));
94     }
95   }
96   ~MacroTable() override;
97 
98   // We don't want a move or copy constructor because we store pointers to
99   // fields of macro tables which will be invalidated if we move/copy them.
100   MacroTable(const MacroTable&) = delete;
101   MacroTable& operator=(const MacroTable&) = delete;
102 
103   MacroTable(MacroTable&&) = delete;
104   MacroTable& operator=(MacroTable&&) noexcept = delete;
105 
106   const char* table_name() const { return name_; }
107 
108  protected:
109   void UpdateRowMapsAfterParentInsert() {
110     if (parent_ != nullptr) {
111       // If there is a parent table, add the last inserted row in each of the
112       // parent row maps to the corresponding row map in the child.
113       for (uint32_t i = 0; i < parent_->row_maps().size(); ++i) {
114         const RowMap& parent_rm = parent_->row_maps()[i];
115         row_maps_[i].Insert(parent_rm.Get(parent_rm.size() - 1));
116       }
117     }
118     // Also add the index of the new row to the identity row map and increment
119     // the size.
120     row_maps_.back().Insert(row_count_++);
121   }
122 
123   // Stores the most specific "derived" type of this row in the table.
124   //
125   // For example, suppose a row is inserted into the gpu_slice table. This will
126   // also cause a row to be inserted into the slice table. For users querying
127   // the slice table, they will want to know the "real" type of this slice (i.e.
128   // they will want to see that the type is gpu_slice). This sparse vector
129   // stores precisely the real type.
130   //
131   // Only relevant for parentless tables. Will be empty and unreferenced by
132   // tables with parents.
133   NullableVector<StringPool::Id> type_;
134 
135  private:
136   const char* name_ = nullptr;
137   Table* parent_ = nullptr;
138 };
139 
140 }  // namespace macros_internal
141 
142 // Ignore GCC warning about a missing argument for a variadic macro parameter.
143 #if defined(__GNUC__) || defined(__clang__)
144 #pragma GCC system_header
145 #endif
146 
147 // Basic helper macros.
148 #define PERFETTO_TP_NOOP(...)
149 
150 // Gets the class name from a table definition.
151 #define PERFETTO_TP_EXTRACT_TABLE_CLASS(class_name, ...) class_name
152 #define PERFETTO_TP_TABLE_CLASS(DEF) \
153   DEF(PERFETTO_TP_EXTRACT_TABLE_CLASS, PERFETTO_TP_NOOP, PERFETTO_TP_NOOP)
154 
155 // Gets the table name from the table definition.
156 #define PERFETTO_TP_EXTRACT_TABLE_NAME(_, table_name) table_name
157 #define PERFETTO_TP_TABLE_NAME(DEF) \
158   DEF(PERFETTO_TP_EXTRACT_TABLE_NAME, PERFETTO_TP_NOOP, PERFETTO_TP_NOOP)
159 
160 // Gets the parent definition from a table definition.
161 #define PERFETTO_TP_EXTRACT_PARENT_DEF(PARENT_DEF, _) PARENT_DEF
162 #define PERFETTO_TP_PARENT_DEF(DEF) \
163   DEF(PERFETTO_TP_NOOP, PERFETTO_TP_EXTRACT_PARENT_DEF, PERFETTO_TP_NOOP)
164 
165 // Invokes FN on each column in the definition of the table. We define a
166 // recursive macro as we need to walk up the hierarchy until we hit the root.
167 // Currently, we hardcode 5 levels but this can be increased as necessary.
168 #define PERFETTO_TP_ALL_COLUMNS_0(DEF, arg) \
169   static_assert(false, "Macro recursion depth exceeded");
170 #define PERFETTO_TP_ALL_COLUMNS_1(DEF, arg) \
171   DEF(PERFETTO_TP_NOOP, PERFETTO_TP_ALL_COLUMNS_0, arg)
172 #define PERFETTO_TP_ALL_COLUMNS_2(DEF, arg) \
173   DEF(PERFETTO_TP_NOOP, PERFETTO_TP_ALL_COLUMNS_1, arg)
174 #define PERFETTO_TP_ALL_COLUMNS_3(DEF, arg) \
175   DEF(PERFETTO_TP_NOOP, PERFETTO_TP_ALL_COLUMNS_2, arg)
176 #define PERFETTO_TP_ALL_COLUMNS_4(DEF, arg) \
177   DEF(PERFETTO_TP_NOOP, PERFETTO_TP_ALL_COLUMNS_3, arg)
178 #define PERFETTO_TP_ALL_COLUMNS(DEF, arg) \
179   DEF(PERFETTO_TP_NOOP, PERFETTO_TP_ALL_COLUMNS_4, arg)
180 
181 // Invokes FN on each column in the table definition.
182 #define PERFETTO_TP_TABLE_COLUMNS(DEF, FN) \
183   DEF(PERFETTO_TP_NOOP, PERFETTO_TP_NOOP, FN)
184 
185 // Invokes FN on each column in every ancestor of the table.
186 #define PERFETTO_TP_PARENT_COLUMNS(DEF, FN) \
187   PERFETTO_TP_ALL_COLUMNS(PERFETTO_TP_PARENT_DEF(DEF), FN)
188 
189 // Basic macros for extracting column info from a schema.
190 #define PERFETTO_TP_NAME_COMMA(type, name, ...) name,
191 #define PERFETTO_TP_TYPE_NAME_COMMA(type, name, ...) type name,
192 
193 // Constructor parameters of Table::Row.
194 // We name this name_c to avoid a clash with the field names of
195 // Table::Row.
196 #define PERFETTO_TP_ROW_CONSTRUCTOR(type, name, ...) type name##_c = {},
197 
198 // Constructor parameters for parent of Row.
199 #define PERFETTO_TP_PARENT_ROW_CONSTRUCTOR(type, name, ...) name##_c,
200 
201 // Initializes the members of Table::Row.
202 #define PERFETTO_TP_ROW_INITIALIZER(type, name, ...) name = name##_c;
203 
204 // Defines the variable in Table::Row.
205 #define PERFETTO_TP_ROW_DEFINITION(type, name, ...) type name = {};
206 
207 // Used to generate an equality implementation on Table::Row.
208 #define PERFETTO_TP_ROW_EQUALS(type, name, ...) \
209   TypedColumn<type>::Equals(other.name, name)&&
210 
211 // Defines the parent row field in Insert.
212 #define PERFETTO_TP_PARENT_ROW_INSERT(type, name, ...) row.name,
213 
214 // Defines the member variable in the Table.
215 #define PERFETTO_TP_TABLE_MEMBER(type, name, ...) \
216   NullableVector<TypedColumn<type>::serialized_type> name##_;
217 
218 #define PERFETTO_TP_COLUMN_FLAG_HAS_FLAG_COL(type, name, flags) \
219   case ColumnIndex::name:                                       \
220     return static_cast<uint32_t>(flags) | TypedColumn<type>::default_flags();
221 
222 #define PERFETTO_TP_COLUMN_FLAG_NO_FLAG_COL(type, name) \
223   case ColumnIndex::name:                               \
224     return TypedColumn<type>::default_flags();
225 
226 #define PERFETTO_TP_COLUMN_FLAG_CHOOSER(type, name, maybe_flags, fn, ...) fn
227 
228 // MSVC has slightly different rules about __VA_ARGS__ expansion. This makes it
229 // behave similarly to GCC/Clang.
230 // See https://stackoverflow.com/q/5134523/14028266 .
231 #define PERFETTO_TP_EXPAND_VA_ARGS(x) x
232 
233 #define PERFETTO_TP_COLUMN_FLAG(...)                          \
234   PERFETTO_TP_EXPAND_VA_ARGS(PERFETTO_TP_COLUMN_FLAG_CHOOSER( \
235       __VA_ARGS__, PERFETTO_TP_COLUMN_FLAG_HAS_FLAG_COL,      \
236       PERFETTO_TP_COLUMN_FLAG_NO_FLAG_COL)(__VA_ARGS__))
237 
238 // Creates the sparse vector with the given flags.
239 #define PERFETTO_TP_TABLE_CONSTRUCTOR_SV(type, name, ...)               \
240   name##_ =                                                             \
241       (FlagsForColumn(ColumnIndex::name) & Column::Flag::kDense)        \
242           ? NullableVector<TypedColumn<type>::serialized_type>::Dense() \
243           : NullableVector<TypedColumn<type>::serialized_type>::Sparse();
244 
245 // Invokes the chosen column constructor by passing the given args.
246 #define PERFETTO_TP_TABLE_CONSTRUCTOR_COLUMN(type, name, ...)               \
247   columns_.emplace_back(#name, &name##_, FlagsForColumn(ColumnIndex::name), \
248                         this, columns_.size(), row_maps_.size() - 1);
249 
250 // Inserts the value into the corresponding column.
251 #define PERFETTO_TP_COLUMN_APPEND(type, name, ...) \
252   mutable_##name()->Append(std::move(row.name));
253 
254 // Creates a schema entry for the corresponding column.
255 #define PERFETTO_TP_COLUMN_SCHEMA(type, name, ...)          \
256   schema.columns.emplace_back(Table::Schema::Column{        \
257       #name, TypedColumn<type>::SqlValueType(), false,      \
258       static_cast<bool>(FlagsForColumn(ColumnIndex::name) & \
259                         Column::Flag::kSorted),             \
260       static_cast<bool>(FlagsForColumn(ColumnIndex::name) & \
261                         Column::Flag::kHidden)});
262 
263 // Defines the accessors for a column.
264 #define PERFETTO_TP_TABLE_COL_ACCESSOR(type, name, ...)       \
265   const TypedColumn<type>& name() const {                     \
266     return static_cast<const TypedColumn<type>&>(             \
267         columns_[static_cast<uint32_t>(ColumnIndex::name)]);  \
268   }                                                           \
269                                                               \
270   TypedColumn<type>* mutable_##name() {                       \
271     return static_cast<TypedColumn<type>*>(                   \
272         &columns_[static_cast<uint32_t>(ColumnIndex::name)]); \
273   }
274 
275 // Definition used as the parent of root tables.
276 #define PERFETTO_TP_ROOT_TABLE_PARENT_DEF(NAME, PARENT, C) \
277   NAME(macros_internal::RootParentTable, "root")
278 
279 // For more general documentation, see PERFETTO_TP_TABLE in macros.h.
280 #define PERFETTO_TP_TABLE_INTERNAL(table_name, class_name, parent_class_name, \
281                                    DEF)                                       \
282   class class_name : public macros_internal::MacroTable {                     \
283    private:                                                                   \
284     /*                                                                        \
285      * Allows IdHelper to access DefinedId for root tables.                   \
286      * Needs to be defined here to allow the public using declaration of Id   \
287      * below to work correctly.                                               \
288      */                                                                       \
289     friend struct macros_internal::IdHelper<parent_class_name, class_name>;   \
290                                                                               \
291     /*                                                                        \
292      * Defines a new id type for a heirarchy of tables.                       \
293      * We define it here as we need this type to be visible for the public    \
294      * using declaration of Id below.                                         \
295      * Note: This type will only used if this table is a root table.          \
296      */                                                                       \
297     struct DefinedId : public BaseId {                                        \
298       DefinedId() = default;                                                  \
299       explicit constexpr DefinedId(uint32_t v) : BaseId(v) {}                 \
300     };                                                                        \
301                                                                               \
302    public:                                                                    \
303     /*                                                                        \
304      * This defines the type of the id to be the type of the root             \
305      * table of the hierarchy - see IdHelper for more details.                \
306      */                                                                       \
307     using Id = macros_internal::IdHelper<parent_class_name, class_name>::Id;  \
308     struct Row : parent_class_name::Row {                                     \
309       /*                                                                      \
310        * Expands to Row(col_type1 col1_c, base::Optional<col_type2> col2_c,   \
311        * ...)                                                                 \
312        */                                                                     \
313       Row(PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_ROW_CONSTRUCTOR)           \
314               std::nullptr_t = nullptr)                                       \
315           : parent_class_name::Row(PERFETTO_TP_PARENT_COLUMNS(                \
316                 DEF,                                                          \
317                 PERFETTO_TP_PARENT_ROW_CONSTRUCTOR) nullptr) {                \
318         type_ = table_name;                                                   \
319                                                                               \
320         /*                                                                    \
321          * Expands to                                                         \
322          * col1 = col1_c;                                                     \
323          * col2 = col2_c;                                                     \
324          * ...                                                                \
325          */                                                                   \
326         PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_ROW_INITIALIZER)           \
327       }                                                                       \
328                                                                               \
329       bool operator==(const class_name::Row& other) const {                   \
330         return PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_ROW_EQUALS) true;     \
331       }                                                                       \
332                                                                               \
333       /*                                                                      \
334        * Expands to                                                           \
335        * col_type1 col1 = {};                                                 \
336        * base::Optional<col_type2> col2 = {};                                 \
337        * ...                                                                  \
338        */                                                                     \
339       PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_ROW_DEFINITION)              \
340     };                                                                        \
341                                                                               \
342     enum class ColumnIndex : uint32_t {                                       \
343       id,                                                                     \
344       type, /* Expands to col1, col2, ... */                                  \
345       PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_NAME_COMMA) kNumCols           \
346     };                                                                        \
347                                                                               \
348     /* Return value of Insert giving access to id and row number */           \
349     struct IdAndRow {                                                         \
350       Id id;                                                                  \
351       uint32_t row;                                                           \
352     };                                                                        \
353                                                                               \
354     class_name(StringPool* pool, parent_class_name* parent)                   \
355         : macros_internal::MacroTable(table_name, pool, parent),              \
356           parent_(parent) {                                                   \
357       /*                                                                      \
358        * Expands to                                                           \
359        * col1_ = NullableVector<col1_type>(mode)                              \
360        * ...                                                                  \
361        */                                                                     \
362       PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_TABLE_CONSTRUCTOR_SV);       \
363       /*                                                                      \
364        * Expands to                                                           \
365        * columns_.emplace_back("col1", col1_, Column::kNoFlag, this,          \
366        *                        columns_.size(), row_maps_.size() - 1);       \
367        * columns_.emplace_back("col2", col2_, Column::kNoFlag, this,          \
368        *                       columns_.size(), row_maps_.size() - 1);        \
369        * ...                                                                  \
370        */                                                                     \
371       PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_TABLE_CONSTRUCTOR_COLUMN);   \
372     }                                                                         \
373     ~class_name() override;                                                   \
374                                                                               \
375     IdAndRow Insert(const Row& row) {                                         \
376       Id id;                                                                  \
377       uint32_t row_number = row_count();                                      \
378       if (parent_ == nullptr) {                                               \
379         id = Id{row_number};                                                  \
380         type_.Append(string_pool_->InternString(row.type()));                 \
381       } else {                                                                \
382         id = Id{parent_->Insert(row).id};                                     \
383       }                                                                       \
384       UpdateRowMapsAfterParentInsert();                                       \
385                                                                               \
386       /*                                                                      \
387        * Expands to                                                           \
388        * col1_.Append(row.col1);                                              \
389        * col2_.Append(row.col2);                                              \
390        * ...                                                                  \
391        */                                                                     \
392       PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_COLUMN_APPEND);              \
393       return {id, row_number};                                                \
394     }                                                                         \
395                                                                               \
396     const IdColumn<Id>& id() const {                                          \
397       return static_cast<const IdColumn<Id>&>(                                \
398           columns_[static_cast<uint32_t>(ColumnIndex::id)]);                  \
399     }                                                                         \
400                                                                               \
401     const TypedColumn<StringPool::Id>& type() const {                         \
402       return static_cast<const TypedColumn<StringPool::Id>&>(                 \
403           columns_[static_cast<uint32_t>(ColumnIndex::type)]);                \
404     }                                                                         \
405                                                                               \
406     static Table::Schema Schema() {                                           \
407       Table::Schema schema;                                                   \
408       schema.columns.emplace_back(Table::Schema::Column{                      \
409           "id", SqlValue::Type::kLong, true, true, false});                   \
410       schema.columns.emplace_back(Table::Schema::Column{                      \
411           "type", SqlValue::Type::kString, false, false, false});             \
412       PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_COLUMN_SCHEMA);                \
413       return schema;                                                          \
414     }                                                                         \
415                                                                               \
416     /*                                                                        \
417      * Expands to                                                             \
418      * const TypedColumn<col1_type>& col1() { return col1_; }                 \
419      * TypedColumn<col1_type>* mutable_col1() { return &col1_; }              \
420      * const TypedColumn<col2_type>& col2() { return col2_; }                 \
421      * TypedColumn<col2_type>* mutable_col2() { return &col2_; }              \
422      * ...                                                                    \
423      */                                                                       \
424     PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_TABLE_COL_ACCESSOR)              \
425                                                                               \
426    private:                                                                   \
427     static uint32_t FlagsForColumn(const ColumnIndex index) {                 \
428       switch (index) {                                                        \
429         case ColumnIndex::kNumCols:                                           \
430           PERFETTO_FATAL("Invalid index");                                    \
431         case ColumnIndex::id:                                                 \
432           return Column::kIdFlags;                                            \
433         case ColumnIndex::type:                                               \
434           return Column::kNoFlag;                                             \
435           /*                                                                  \
436            * Expands to:                                                      \
437            *  case ColumnIndex::col1:                                         \
438            *    return TypedColumn<col_type1>::default_flags();               \
439            *  ...                                                             \
440            */                                                                 \
441           PERFETTO_TP_ALL_COLUMNS(DEF, PERFETTO_TP_COLUMN_FLAG)               \
442       }                                                                       \
443       PERFETTO_FATAL("For GCC");                                              \
444     }                                                                         \
445                                                                               \
446     parent_class_name* parent_;                                               \
447                                                                               \
448     /*                                                                        \
449      * Expands to                                                             \
450      * NullableVector<col1_type> col1_;                                       \
451      * NullableVector<col2_type> col2_;                                       \
452      * ...                                                                    \
453      */                                                                       \
454     PERFETTO_TP_TABLE_COLUMNS(DEF, PERFETTO_TP_TABLE_MEMBER)                  \
455   }
456 
457 }  // namespace trace_processor
458 }  // namespace perfetto
459 
460 #endif  // SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_
461