1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 // This file contains routines to generate tail-call table parsing tables. 9 // Everything in this file is for internal use only. 10 11 #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_GEN_H__ 12 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_GEN_H__ 13 14 #include <cstdint> 15 #include <vector> 16 17 #include "absl/types/span.h" 18 #include "absl/types/variant.h" 19 #include "google/protobuf/descriptor.h" 20 #include "google/protobuf/descriptor.pb.h" 21 22 // Must come last: 23 #include "google/protobuf/port_def.inc" 24 25 namespace google { 26 namespace protobuf { 27 namespace internal { 28 enum class TcParseFunction : uint8_t; 29 30 namespace field_layout { 31 enum TransformValidation : uint16_t; 32 } // namespace field_layout 33 34 // Helper class for generating tailcall parsing functions. 35 struct PROTOBUF_EXPORT TailCallTableInfo { 36 struct MessageOptions { 37 bool is_lite; 38 bool uses_codegen; 39 // TODO: remove this after A/B test is done. 40 bool should_profile_driven_cluster_aux_subtable; 41 }; 42 struct FieldOptions { 43 const FieldDescriptor* field; 44 int has_bit_index; 45 // For presence awareness (e.g. PDProto). 46 float presence_probability; 47 // kTvEager, kTvLazy, or 0 48 field_layout::TransformValidation lazy_opt; 49 bool is_string_inlined; 50 bool is_implicitly_weak; 51 bool use_direct_tcparser_table; 52 bool should_split; 53 int inlined_string_index; 54 }; 55 56 TailCallTableInfo(const Descriptor* descriptor, 57 const MessageOptions& message_options, 58 absl::Span<const FieldOptions> ordered_fields); 59 60 TcParseFunction fallback_function; 61 62 // Fields parsed by the table fast-path. 63 struct FastFieldInfo { 64 struct Empty {}; 65 struct Field { 66 TcParseFunction func; 67 const FieldDescriptor* field; 68 uint16_t coded_tag; 69 uint8_t hasbit_idx; 70 uint8_t aux_idx; 71 72 // For internal caching. 73 float presence_probability; 74 }; 75 struct NonField { 76 TcParseFunction func; 77 uint16_t coded_tag; 78 uint16_t nonfield_info; 79 }; 80 absl::variant<Empty, Field, NonField> data; 81 is_emptyTailCallTableInfo::FastFieldInfo82 bool is_empty() const { return absl::holds_alternative<Empty>(data); } AsFieldTailCallTableInfo::FastFieldInfo83 const Field* AsField() const { return absl::get_if<Field>(&data); } AsNonFieldTailCallTableInfo::FastFieldInfo84 const NonField* AsNonField() const { return absl::get_if<NonField>(&data); } 85 }; 86 std::vector<FastFieldInfo> fast_path_fields; 87 88 // Fields parsed by mini parsing routines. 89 struct FieldEntryInfo { 90 const FieldDescriptor* field; 91 int hasbit_idx; 92 int inlined_string_idx; 93 uint16_t aux_idx; 94 uint16_t type_card; 95 96 // For internal caching. 97 cpp::Utf8CheckMode utf8_check_mode; 98 }; 99 std::vector<FieldEntryInfo> field_entries; 100 101 enum AuxType { 102 kNothing = 0, 103 kInlinedStringDonatedOffset, 104 kSplitOffset, 105 kSplitSizeof, 106 kSubMessage, 107 kSubTable, 108 kSubMessageWeak, 109 kMessageVerifyFunc, 110 kSelfVerifyFunc, 111 kEnumRange, 112 kEnumValidator, 113 kNumericOffset, 114 kMapAuxInfo, 115 }; 116 struct AuxEntry { 117 AuxType type; 118 struct EnumRange { 119 int16_t start; 120 uint16_t size; 121 }; 122 union { 123 const FieldDescriptor* field; 124 const Descriptor* desc; 125 uint32_t offset; 126 EnumRange enum_range; 127 }; 128 }; 129 std::vector<AuxEntry> aux_entries; 130 131 struct SkipEntry16 { 132 uint16_t skipmap; 133 uint16_t field_entry_offset; 134 }; 135 struct SkipEntryBlock { 136 uint32_t first_fnum; 137 std::vector<SkipEntry16> entries; 138 }; 139 struct NumToEntryTable { 140 uint32_t skipmap32; // for fields #1 - #32 141 std::vector<SkipEntryBlock> blocks; 142 // Compute the number of uint16_t required to represent this table. size16TailCallTableInfo::NumToEntryTable143 int size16() const { 144 int size = 2; // for the termination field# 145 for (const auto& block : blocks) { 146 // 2 for the field#, 1 for a count of skip entries, 2 for each entry. 147 size += static_cast<int>(3 + block.entries.size() * 2); 148 } 149 return size; 150 } 151 }; 152 NumToEntryTable num_to_entry_table; 153 154 std::vector<uint8_t> field_name_data; 155 156 // Table size. 157 int table_size_log2; 158 }; 159 160 } // namespace internal 161 } // namespace protobuf 162 } // namespace google 163 164 #include "google/protobuf/port_undef.inc" 165 166 #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_GEN_H__ 167