/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_ #define SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_ #include #include "perfetto/ext/base/small_vector.h" #include "src/trace_processor/db/table.h" #include "src/trace_processor/db/typed_column.h" namespace perfetto { namespace trace_processor { namespace macros_internal { // We define this class to allow the table macro below to compile without // needing templates; in reality none of the methods will be called because the // pointer to this class will always be null. class RootParentTable : public Table { public: struct Row { public: Row(std::nullptr_t = nullptr) {} const char* type() const { return type_; } protected: const char* type_ = nullptr; }; // This class only exists to allow typechecking to work correctly in Insert // below. If we had C++17 and if constexpr, we could statically verify that // this was never created but for now, we still need to define it to satisfy // the typechecker. struct IdAndRow { uint32_t id; }; struct RowNumber { uint32_t row_number() { PERFETTO_FATAL("Should not be called"); } }; IdAndRow Insert(const Row&) { PERFETTO_FATAL("Should not be called"); } private: explicit RootParentTable(std::nullptr_t); }; // The parent class for all macro generated tables. // This class is used to extract common code from the macro tables to reduce // code size. class MacroTable : public Table { protected: // Constructors for tables created by the regular constructor. MacroTable(StringPool* pool, const Table* parent = nullptr) : Table(pool), allow_inserts_(true), parent_(parent) { if (!parent) { overlays_.emplace_back(); columns_.emplace_back(Column::IdColumn(this, 0, 0)); columns_.emplace_back( Column("type", &type_, Column::kNonNull, this, 1, 0)); return; } overlays_.resize(parent->overlays().size() + 1); for (const Column& col : parent->columns()) { columns_.emplace_back(col, this, col.index_in_table(), col.overlay_index()); } } // Constructor for tables created by SelectAndExtendParent. MacroTable(StringPool* pool, const Table& parent, const RowMap& parent_overlay) : Table(pool), allow_inserts_(false) { row_count_ = parent_overlay.size(); for (const auto& rm : parent.overlays()) { overlays_.emplace_back(rm.SelectRows(parent_overlay)); PERFETTO_DCHECK(overlays_.back().size() == row_count_); } overlays_.emplace_back(ColumnStorageOverlay(row_count_)); for (const Column& col : parent.columns()) { columns_.emplace_back(col, this, col.index_in_table(), col.overlay_index()); } } ~MacroTable() override; // We don't want a move or copy constructor because we store pointers to // fields of macro tables which will be invalidated if we move/copy them. MacroTable(const MacroTable&) = delete; MacroTable& operator=(const MacroTable&) = delete; MacroTable(MacroTable&&) = delete; MacroTable& operator=(MacroTable&&) noexcept = delete; void UpdateOverlaysAfterParentInsert() { // Add the last inserted row in each of the parent row maps to the // corresponding row map in the child. for (uint32_t i = 0; i < parent_->overlays().size(); ++i) { const ColumnStorageOverlay& parent_rm = parent_->overlays()[i]; overlays_[i].Insert(parent_rm.Get(parent_rm.size() - 1)); } } void UpdateSelfOverlayAfterInsert() { // Also add the index of the new row to the identity row map and increment // the size. overlays_.back().Insert(row_count_++); } std::vector FilterAndApplyToOverlays( const std::vector& cs, RowMap::OptimizeFor optimize_for) const { RowMap rm = FilterToRowMap(cs, optimize_for); std::vector overlays; overlays.reserve(overlays_.size()); for (uint32_t i = 0; i < overlays_.size(); ++i) { overlays.emplace_back(overlays_[i].SelectRows(rm)); } return overlays; } // Stores whether inserts are allowed into this macro table; by default // inserts are allowed but they are disallowed when a parent table is extended // with |ExtendParent|; the rationale for this is that extensions usually // happen in dynamic tables and they should not be allowed to insert rows into // the real (static) tables. bool allow_inserts_ = true; // Stores the most specific "derived" type of this row in the table. // // For example, suppose a row is inserted into the gpu_slice table. This will // also cause a row to be inserted into the slice table. For users querying // the slice table, they will want to know the "real" type of this slice (i.e. // they will want to see that the type is gpu_slice). This sparse vector // stores precisely the real type. // // Only relevant for parentless tables. Will be empty and unreferenced by // tables with parents. ColumnStorage type_; private: const Table* parent_ = nullptr; }; // Abstract iterator class for macro tables. // Extracted to allow sharing with view code. template class AbstractConstIterator { public: explicit operator bool() const { return its_[0]; } Iterator& operator++() { for (ColumnStorageOverlay::Iterator& it : its_) { it.Next(); } return *this_it(); } // Returns a RowNumber for the current row. RowNumber row_number() const { return RowNumber(this_it()->CurrentRowNumber()); } // Returns a ConstRowReference to the current row. ConstRowReference row_reference() const { return ConstRowReference(table_, this_it()->CurrentRowNumber()); } protected: explicit AbstractConstIterator(const MacroTable* table, std::vector overlays) : overlays_(std::move(overlays)), table_(table) { static_assert(std::is_base_of::value, "Template param should be a subclass of Table."); for (const auto& rm : overlays_) { its_.emplace_back(rm.IterateRows()); } } // Must not be modified as |its_| contains pointers into this vector. std::vector overlays_; std::vector its_; const MacroTable* table_; private: Iterator* this_it() { return static_cast(this); } const Iterator* this_it() const { return static_cast(this); } }; // Abstract RowNumber class for macro tables. // Extracted to allow sharing with view code. template class AbstractRowNumber { public: // Converts this RowNumber to a RowReference for the given |table|. template < typename RR = RowReference, typename = typename std::enable_if::value>::type> RR ToRowReference(MacroTable* table) const { return RR(table, row_number_); } // Converts this RowNumber to a ConstRowReference for the given |table|. ConstRowReference ToRowReference(const MacroTable& table) const { return ConstRowReference(&table, row_number_); } // Converts this object to the underlying int value. uint32_t row_number() const { return row_number_; } // Allows sorting + storage in a map/set. bool operator<(const AbstractRowNumber& other) const { return row_number_ < other.row_number_; } protected: explicit AbstractRowNumber(uint32_t row_number) : row_number_(row_number) {} private: uint32_t row_number_ = 0; }; // Abstract ConstRowReference class for macro tables. // Extracted to allow sharing with view code. template class AbstractConstRowReference { public: // Converts this RowReference to a RowNumber object which is more memory // efficient to store. RowNumber ToRowNumber() { return RowNumber(row_number_); } protected: AbstractConstRowReference(const MacroTable* table, uint32_t row_number) : table_(table), row_number_(row_number) {} const MacroTable* table_ = nullptr; uint32_t row_number_ = 0; }; } // namespace macros_internal } // namespace trace_processor } // namespace perfetto #endif // SRC_TRACE_PROCESSOR_TABLES_MACROS_INTERNAL_H_