1# Copyright (C) 2022 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from typing import List 16from typing import Optional 17 18from python.generators.trace_processor_table.public import Alias 19from python.generators.trace_processor_table.public import ColumnFlag 20from python.generators.trace_processor_table.util import ParsedTable 21from python.generators.trace_processor_table.util import ParsedColumn 22from python.generators.trace_processor_table.util import parse_type 23from python.generators.trace_processor_table.util import typed_column_type 24 25 26class ColumnSerializer: 27 """Functions for serializing a single Column in a table into C++.""" 28 29 def __init__(self, table: ParsedTable, column: ParsedColumn, col_index: int): 30 self.col_index = col_index 31 self.parsed_col = column 32 self.col = self.parsed_col.column 33 self.name = self.col.name 34 self.flags = self.col.flags 35 self.typed_column_type = typed_column_type(table.table, self.parsed_col) 36 self.cpp_type = parse_type(table.table, 37 self.col.type).cpp_type_with_optionality() 38 39 self.is_implicit_id = self.parsed_col.is_implicit_id 40 self.is_implicit_type = self.parsed_col.is_implicit_type 41 self.is_ancestor = self.parsed_col.is_ancestor 42 43 def colindex(self) -> str: 44 return f' static constexpr uint32_t {self.name} = {self.col_index};' 45 46 def coltype_enum(self) -> str: 47 return f' using {self.name} = {self.typed_column_type};' 48 49 def row_field(self) -> Optional[str]: 50 if self.is_implicit_id or self.is_implicit_type: 51 return None 52 if self.is_ancestor: 53 return None 54 return f' {self.cpp_type} {self.name};' 55 56 def row_param(self) -> Optional[str]: 57 if self.is_implicit_id or self.is_implicit_type: 58 return None 59 return f'{self.cpp_type} in_{self.name} = {{}}' 60 61 def parent_row_initializer(self) -> Optional[str]: 62 if self.is_implicit_id or self.is_implicit_type: 63 return None 64 if not self.is_ancestor: 65 return None 66 return f'std::move(in_{self.name})' 67 68 def row_initializer(self) -> Optional[str]: 69 if self.is_implicit_id or self.is_implicit_type: 70 return None 71 if self.is_ancestor: 72 return None 73 return f'{self.name}(std::move(in_{self.name}))' 74 75 def const_row_ref_getter(self) -> Optional[str]: 76 return f'''ColumnType::{self.name}::type {self.name}() const {{ 77 return table_->{self.name}()[row_number_]; 78 }}''' 79 80 def row_ref_getter(self) -> Optional[str]: 81 if self.is_implicit_id or self.is_implicit_type: 82 return None 83 return f'''void set_{self.name}( 84 ColumnType::{self.name}::non_optional_type v) {{ 85 return mutable_table()->mutable_{self.name}()->Set(row_number_, v); 86 }}''' 87 88 def flag(self) -> Optional[str]: 89 if self.is_implicit_id or self.is_implicit_type: 90 return None 91 if self.is_ancestor: 92 return None 93 default = f'ColumnType::{self.name}::default_flags()' 94 if self.flags == ColumnFlag.NONE: 95 flags = default 96 else: 97 flags = f'static_cast<uint32_t>({to_cpp_flags(self.flags)}) | {default}' 98 return f''' 99 static constexpr uint32_t {self.name} = {flags}; 100 ''' 101 102 def storage_init(self) -> Optional[str]: 103 if self.is_implicit_id or self.is_implicit_type: 104 return None 105 if self.is_ancestor: 106 return None 107 108 storage = f'ColumnStorage<ColumnType::{self.name}::stored_type>' 109 dense = str(ColumnFlag.DENSE in self.flags).lower() 110 return f'''{self.name}_({storage}::Create<{dense}>())''' 111 112 def column_init(self) -> Optional[str]: 113 if self.is_implicit_id or self.is_implicit_type: 114 return None 115 if self.is_ancestor: 116 return None 117 return f''' 118 columns_.emplace_back("{self.name}", &{self.name}_, ColumnFlag::{self.name}, 119 this, static_cast<uint32_t>(columns_.size()), 120 olay_idx); 121 ''' 122 123 def shrink_to_fit(self) -> Optional[str]: 124 if self.is_implicit_id: 125 return None 126 if self.is_ancestor: 127 return None 128 return f' {self.name}_.ShrinkToFit();' 129 130 def append(self) -> Optional[str]: 131 if self.is_implicit_id or self.is_implicit_type: 132 return None 133 if self.is_ancestor: 134 return None 135 return f' mutable_{self.name}()->Append(std::move(row.{self.name}));' 136 137 def accessor(self) -> Optional[str]: 138 inner = f'columns_[ColumnIndex::{self.name}]' 139 return f''' 140 const {self.typed_column_type}& {self.name}() const {{ 141 return static_cast<const ColumnType::{self.name}&>({inner}); 142 }} 143 ''' 144 145 def mutable_accessor(self) -> Optional[str]: 146 if self.is_implicit_id or self.is_implicit_type: 147 return None 148 return f''' 149 {self.typed_column_type}* mutable_{self.name}() {{ 150 return static_cast<ColumnType::{self.name}*>( 151 &columns_[ColumnIndex::{self.name}]); 152 }} 153 ''' 154 155 def storage(self) -> Optional[str]: 156 if self.is_implicit_id or self.is_implicit_type: 157 return None 158 if self.is_ancestor: 159 return None 160 name = self.name 161 return f' ColumnStorage<ColumnType::{name}::stored_type> {name}_;' 162 163 def iterator_getter(self) -> Optional[str]: 164 name = self.name 165 return f''' 166 ColumnType::{self.name}::type {name}() const {{ 167 const auto& col = table_->{name}(); 168 return col.GetAtIdx(its_[col.overlay_index()].index()); 169 }} 170 ''' 171 172 def iterator_setter(self) -> Optional[str]: 173 if self.is_implicit_id or self.is_implicit_type: 174 return None 175 return f''' 176 void set_{self.name}(ColumnType::{self.name}::non_optional_type v) {{ 177 auto* col = mutable_table_->mutable_{self.name}(); 178 col->SetAtIdx(its_[col->overlay_index()].index(), v); 179 }} 180 ''' 181 182 def static_schema(self) -> Optional[str]: 183 if self.is_implicit_id or self.is_implicit_type: 184 return None 185 return f''' 186 schema.columns.emplace_back(Table::Schema::Column{{ 187 "{self.name}", ColumnType::{self.name}::SqlValueType(), false, 188 {str(ColumnFlag.SORTED in self.flags).lower()}, 189 {str(ColumnFlag.HIDDEN in self.flags).lower()}, 190 {str(ColumnFlag.SET_ID in self.flags).lower()}}}); 191 ''' 192 193 def row_eq(self) -> Optional[str]: 194 if self.is_implicit_id or self.is_implicit_type: 195 return None 196 return f'ColumnType::{self.name}::Equals({self.name}, other.{self.name})' 197 198 def extend_parent_param(self) -> Optional[str]: 199 if self.is_implicit_id or self.is_implicit_type: 200 return None 201 if self.is_ancestor: 202 return None 203 return f'ColumnStorage<ColumnType::{self.name}::stored_type> {self.name}' 204 205 def extend_parent_param_arg(self) -> Optional[str]: 206 if self.is_implicit_id or self.is_implicit_type: 207 return None 208 if self.is_ancestor: 209 return None 210 return f'std::move({self.name})' 211 212 def static_assert_flags(self) -> Optional[str]: 213 if self.is_implicit_id or self.is_implicit_type: 214 return None 215 if self.is_ancestor: 216 return None 217 return f''' 218 static_assert( 219 Column::IsFlagsAndTypeValid<ColumnType::{self.name}::stored_type>( 220 ColumnFlag::{self.name}), 221 "Column type and flag combination is not valid"); 222 ''' 223 224 def extend_nullable_vector(self) -> Optional[str]: 225 if self.is_implicit_id or self.is_implicit_type: 226 return None 227 if self.is_ancestor: 228 return None 229 return f''' 230 PERFETTO_DCHECK({self.name}.size() == parent_overlay.size()); 231 {self.name}_ = std::move({self.name}); 232 ''' 233 234 235class TableSerializer(object): 236 """Functions for seralizing a single Table into C++.""" 237 238 def __init__(self, parsed: ParsedTable): 239 self.table = parsed.table 240 self.table_name = parsed.table.class_name 241 self.column_serializers = [] 242 243 if parsed.table.parent: 244 self.parent_class_name = parsed.table.parent.class_name 245 else: 246 self.parent_class_name = 'macros_internal::RootParentTable' 247 248 self.column_serializers = [] 249 for c in parsed.columns: 250 # Aliases should be ignored as they are handled in SQL currently. 251 if isinstance(c.column.type, Alias): 252 continue 253 self.column_serializers.append( 254 ColumnSerializer(parsed, c, len(self.column_serializers))) 255 256 def foreach_col(self, serialize_fn, delimiter='\n') -> str: 257 lines = [] 258 for c in self.column_serializers: 259 serialized = serialize_fn(c) 260 if serialized: 261 lines.append(serialized.lstrip('\n').rstrip()) 262 return delimiter.join(lines).strip() 263 264 def id_defn(self) -> str: 265 if self.table.parent: 266 return f''' 267 using Id = {self.table.parent.class_name}::Id; 268 ''' 269 return ''' 270 struct Id : public BaseId { 271 Id() = default; 272 explicit constexpr Id(uint32_t v) : BaseId(v) {} 273 }; 274 static_assert(std::is_trivially_destructible<Id>::value, 275 "Inheritance used without trivial destruction"); 276 ''' 277 278 def row_struct(self) -> str: 279 param = self.foreach_col( 280 ColumnSerializer.row_param, delimiter=',\n ') 281 parent_row_init = self.foreach_col( 282 ColumnSerializer.parent_row_initializer, delimiter=', ') 283 row_init = self.foreach_col( 284 ColumnSerializer.row_initializer, delimiter=',\n ') 285 parent_separator = ',' if row_init else '' 286 row_eq = self.foreach_col(ColumnSerializer.row_eq, delimiter=' &&\n ') 287 return f''' 288 struct Row : public {self.parent_class_name}::Row {{ 289 Row({param}, 290 std::nullptr_t = nullptr) 291 : {self.parent_class_name}::Row({parent_row_init}){parent_separator} 292 {row_init} {{ 293 type_ = "{self.table.sql_name}"; 294 }} 295 {self.foreach_col(ColumnSerializer.row_field)} 296 297 bool operator==(const {self.table_name}::Row& other) const {{ 298 return type() == other.type() && {row_eq}; 299 }} 300 }}; 301 ''' 302 303 def const_row_reference_struct(self) -> str: 304 row_ref_getters = self.foreach_col( 305 ColumnSerializer.const_row_ref_getter, delimiter='\n ') 306 return f''' 307 class ConstRowReference : public macros_internal::AbstractConstRowReference< 308 {self.table_name}, RowNumber> {{ 309 public: 310 ConstRowReference(const {self.table_name}* table, uint32_t row_number) 311 : AbstractConstRowReference(table, row_number) {{}} 312 313 {row_ref_getters} 314 }}; 315 static_assert(std::is_trivially_destructible<ConstRowReference>::value, 316 "Inheritance used without trivial destruction"); 317 ''' 318 319 def row_reference_struct(self) -> str: 320 row_ref_getters = self.foreach_col( 321 ColumnSerializer.row_ref_getter, delimiter='\n ') 322 return f''' 323 class RowReference : public ConstRowReference {{ 324 public: 325 RowReference(const {self.table_name}* table, uint32_t row_number) 326 : ConstRowReference(table, row_number) {{}} 327 328 {row_ref_getters} 329 330 private: 331 {self.table_name}* mutable_table() const {{ 332 return const_cast<{self.table_name}*>(table_); 333 }} 334 }}; 335 static_assert(std::is_trivially_destructible<RowReference>::value, 336 "Inheritance used without trivial destruction"); 337 ''' 338 339 def constructor(self) -> str: 340 storage_init = self.foreach_col( 341 ColumnSerializer.storage_init, delimiter=',\n ') 342 if self.table.parent: 343 parent_param = f', {self.parent_class_name}* parent' 344 parent_arg = 'parent' 345 parent_init = 'parent_(parent)' + (', ' if storage_init else '') 346 else: 347 parent_param = '' 348 parent_arg = 'nullptr' 349 parent_init = '' 350 col_init = self.foreach_col(ColumnSerializer.column_init) 351 if col_init: 352 olay = 'uint32_t olay_idx = static_cast<uint32_t>(overlays_.size()) - 1;' 353 else: 354 olay = '' 355 return f''' 356 explicit {self.table_name}(StringPool* pool{parent_param}) 357 : macros_internal::MacroTable(pool, {parent_arg}), 358 {parent_init}{storage_init} {{ 359 {self.foreach_col(ColumnSerializer.static_assert_flags)} 360 {olay} 361 {col_init} 362 }} 363 ''' 364 365 def parent_field(self) -> str: 366 if self.table.parent: 367 return f''' 368 {self.parent_class_name}* parent_ = nullptr; 369 ''' 370 return '' 371 372 def insert_common(self) -> str: 373 if self.table.parent: 374 return ''' 375 Id id = Id{parent_->Insert(row).id}; 376 UpdateOverlaysAfterParentInsert(); 377 ''' 378 return ''' 379 Id id = Id{row_number}; 380 type_.Append(string_pool_->InternString(row.type())); 381 ''' 382 383 def const_iterator(self) -> str: 384 iterator_getters = self.foreach_col( 385 ColumnSerializer.iterator_getter, delimiter='\n') 386 return f''' 387 class ConstIterator; 388 class ConstIterator : public macros_internal::AbstractConstIterator< 389 ConstIterator, {self.table_name}, RowNumber, ConstRowReference> {{ 390 public: 391 {iterator_getters} 392 393 protected: 394 explicit ConstIterator(const {self.table_name}* table, 395 std::vector<ColumnStorageOverlay> overlays) 396 : AbstractConstIterator(table, std::move(overlays)) {{}} 397 398 uint32_t CurrentRowNumber() const {{ 399 return its_.back().index(); 400 }} 401 402 private: 403 friend class {self.table_name}; 404 friend class AbstractConstIterator; 405 }}; 406 ''' 407 408 def iterator(self) -> str: 409 iterator_setters = self.foreach_col( 410 ColumnSerializer.iterator_setter, delimiter='\n') 411 return f''' 412 class Iterator : public ConstIterator {{ 413 public: 414 {iterator_setters} 415 416 RowReference row_reference() const {{ 417 return RowReference(mutable_table_, CurrentRowNumber()); 418 }} 419 420 private: 421 friend class {self.table_name}; 422 423 explicit Iterator({self.table_name}* table, 424 std::vector<ColumnStorageOverlay> overlays) 425 : ConstIterator(table, std::move(overlays)), 426 mutable_table_(table) {{}} 427 428 {self.table_name}* mutable_table_ = nullptr; 429 }}; 430 ''' 431 432 def extend(self) -> str: 433 if not self.table.parent: 434 return '' 435 params = self.foreach_col( 436 ColumnSerializer.extend_parent_param, delimiter='\n, ') 437 args = self.foreach_col( 438 ColumnSerializer.extend_parent_param_arg, delimiter=', ') 439 delim = ',' if params else '' 440 return f''' 441 static std::unique_ptr<Table> ExtendParent( 442 const {self.parent_class_name}& parent{delim} 443 {params}) {{ 444 return std::unique_ptr<Table>(new {self.table_name}( 445 parent.string_pool(), parent, RowMap(0, parent.row_count()){delim} 446 {args})); 447 }} 448 449 static std::unique_ptr<Table> SelectAndExtendParent( 450 const {self.parent_class_name}& parent, 451 std::vector<{self.parent_class_name}::RowNumber> parent_overlay{delim} 452 {params}) {{ 453 std::vector<uint32_t> prs_untyped(parent_overlay.size()); 454 for (uint32_t i = 0; i < parent_overlay.size(); ++i) {{ 455 prs_untyped[i] = parent_overlay[i].row_number(); 456 }} 457 return std::unique_ptr<Table>(new {self.table_name}( 458 parent.string_pool(), parent, RowMap(std::move(prs_untyped)){delim} 459 {args})); 460 }} 461 ''' 462 463 def extend_constructor(self) -> str: 464 if not self.table.parent: 465 return '' 466 params = self.foreach_col( 467 ColumnSerializer.extend_parent_param, delimiter='\n, ') 468 if params: 469 olay = 'uint32_t olay_idx = static_cast<uint32_t>(overlays_.size()) - 1;' 470 else: 471 olay = '' 472 return f''' 473 {self.table_name}(StringPool* pool, 474 const {self.parent_class_name}& parent, 475 const RowMap& parent_overlay{',' if params else ''} 476 {params}) 477 : macros_internal::MacroTable(pool, parent, parent_overlay) {{ 478 {self.foreach_col(ColumnSerializer.static_assert_flags)} 479 {self.foreach_col(ColumnSerializer.extend_nullable_vector)} 480 481 {olay} 482 {self.foreach_col(ColumnSerializer.column_init)} 483 }} 484 ''' 485 486 def serialize(self) -> str: 487 return f''' 488class {self.table_name} : public macros_internal::MacroTable {{ 489 public: 490 {self.id_defn().lstrip()} 491 struct ColumnIndex {{ 492 {self.foreach_col(ColumnSerializer.colindex)} 493 }}; 494 struct ColumnType {{ 495 {self.foreach_col(ColumnSerializer.coltype_enum)} 496 }}; 497 {self.row_struct().strip()} 498 struct ColumnFlag {{ 499 {self.foreach_col(ColumnSerializer.flag)} 500 }}; 501 502 class RowNumber; 503 class ConstRowReference; 504 class RowReference; 505 506 class RowNumber : public macros_internal::AbstractRowNumber< 507 {self.table_name}, ConstRowReference, RowReference> {{ 508 public: 509 explicit RowNumber(uint32_t row_number) 510 : AbstractRowNumber(row_number) {{}} 511 }}; 512 static_assert(std::is_trivially_destructible<RowNumber>::value, 513 "Inheritance used without trivial destruction"); 514 515 {self.const_row_reference_struct().strip()} 516 {self.row_reference_struct().strip()} 517 518 {self.const_iterator().strip()} 519 {self.iterator().strip()} 520 521 struct IdAndRow {{ 522 Id id; 523 uint32_t row; 524 RowReference row_reference; 525 RowNumber row_number; 526 }}; 527 528 {self.constructor().strip()} 529 ~{self.table_name}() override; 530 531 static const char* Name() {{ return "{self.table.sql_name}"; }} 532 533 static Table::Schema ComputeStaticSchema() {{ 534 Table::Schema schema; 535 schema.columns.emplace_back(Table::Schema::Column{{ 536 "id", SqlValue::Type::kLong, true, true, false, false}}); 537 schema.columns.emplace_back(Table::Schema::Column{{ 538 "type", SqlValue::Type::kString, false, false, false, false}}); 539 {self.foreach_col(ColumnSerializer.static_schema)} 540 return schema; 541 }} 542 543 ConstIterator IterateRows() const {{ 544 return ConstIterator(this, CopyOverlays()); 545 }} 546 547 Iterator IterateRows() {{ return Iterator(this, CopyOverlays()); }} 548 549 ConstIterator FilterToIterator( 550 const std::vector<Constraint>& cs, 551 RowMap::OptimizeFor opt = RowMap::OptimizeFor::kMemory) const {{ 552 return ConstIterator(this, FilterAndApplyToOverlays(cs, opt)); 553 }} 554 555 Iterator FilterToIterator( 556 const std::vector<Constraint>& cs, 557 RowMap::OptimizeFor opt = RowMap::OptimizeFor::kMemory) {{ 558 return Iterator(this, FilterAndApplyToOverlays(cs, opt)); 559 }} 560 561 void ShrinkToFit() {{ 562 {self.foreach_col(ColumnSerializer.shrink_to_fit)} 563 }} 564 565 std::optional<ConstRowReference> FindById(Id find_id) const {{ 566 std::optional<uint32_t> row = id().IndexOf(find_id); 567 return row ? std::make_optional(ConstRowReference(this, *row)) 568 : std::nullopt; 569 }} 570 571 std::optional<RowReference> FindById(Id find_id) {{ 572 std::optional<uint32_t> row = id().IndexOf(find_id); 573 return row ? std::make_optional(RowReference(this, *row)) : std::nullopt; 574 }} 575 576 IdAndRow Insert(const Row& row) {{ 577 uint32_t row_number = row_count(); 578 {self.insert_common().strip()} 579 {self.foreach_col(ColumnSerializer.append)} 580 UpdateSelfOverlayAfterInsert(); 581 return IdAndRow{{std::move(id), row_number, RowReference(this, row_number), 582 RowNumber(row_number)}}; 583 }} 584 585 {self.extend().strip()} 586 587 {self.foreach_col(ColumnSerializer.accessor)} 588 589 {self.foreach_col(ColumnSerializer.mutable_accessor)} 590 591 private: 592 {self.extend_constructor().strip()} 593 {self.parent_field().strip()} 594 {self.foreach_col(ColumnSerializer.storage)} 595}}; 596 '''.strip('\n') 597 598 599def serialize_header(ifdef_guard: str, tables: List[ParsedTable], 600 include_paths: List[str]) -> str: 601 """Serializes a table header file containing the given set of tables.""" 602 include_paths_str = '\n'.join([f'#include "{i}"' for i in include_paths]) 603 tables_str = '\n\n'.join([TableSerializer(t).serialize() for t in tables]) 604 return f''' 605#ifndef {ifdef_guard} 606#define {ifdef_guard} 607 608#include "src/trace_processor/tables/macros_internal.h" 609 610{include_paths_str} 611 612namespace perfetto {{ 613namespace trace_processor {{ 614namespace tables {{ 615 616{tables_str.strip()} 617 618}} // namespace tables 619}} // namespace trace_processor 620}} // namespace perfetto 621 622#endif // {ifdef_guard} 623 '''.strip() 624 625 626def to_cpp_flags(raw_flag: ColumnFlag) -> str: 627 """Converts a ColumnFlag to the C++ flags which it represents 628 629 It is not valid to call this function with ColumnFlag.NONE as in this case 630 defaults for that column should be implicitly used.""" 631 632 assert raw_flag != ColumnFlag.NONE 633 flags = [] 634 if ColumnFlag.SORTED in raw_flag: 635 flags.append('Column::Flag::kSorted') 636 if ColumnFlag.HIDDEN in raw_flag: 637 flags.append('Column::Flag::kHidden') 638 if ColumnFlag.DENSE in raw_flag: 639 flags.append('Column::Flag::kDense') 640 if ColumnFlag.SET_ID in raw_flag: 641 flags.append('Column::Flag::kSetId') 642 return ' | '.join(flags) 643