generated_message_tctable_impl.h
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
32 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
33 
34 #include <cstdint>
35 #include <type_traits>
36 
37 #include <google/protobuf/parse_context.h>
38 #include <google/protobuf/extension_set.h>
40 #include <google/protobuf/message_lite.h>
41 #include <google/protobuf/metadata_lite.h>
42 #include <google/protobuf/port.h>
43 #include <google/protobuf/wire_format_lite.h>
44 
45 // Must come last:
46 #include <google/protobuf/port_def.inc>
47 
48 namespace google {
49 namespace protobuf {
50 
51 class Message;
52 class UnknownFieldSet;
53 
54 namespace internal {
55 
56 // PROTOBUF_TC_PARAM_DECL are the parameters for tailcall functions, it is
57 // defined in port_def.inc.
58 //
59 // Note that this is performance sensitive: changing the parameters will change
60 // the registers used by the ABI calling convention, which subsequently affects
61 // register selection logic inside the function.
62 
63 // PROTOBUF_TC_PARAM_PASS passes values to match PROTOBUF_TC_PARAM_DECL.
64 #define PROTOBUF_TC_PARAM_PASS msg, ptr, ctx, table, hasbits, data
65 
66 // PROTOBUF_TC_PARSE_* decide which function is used to parse message-typed
67 // fields. The guard macros are defined in port_def.inc.
68 #if PROTOBUF_TC_STATIC_PARSE_SINGULAR1
69 #define PROTOBUF_TC_PARSE_SINGULAR1(MESSAGE) MESSAGE::Tct_ParseS1
70 #else
71 #define PROTOBUF_TC_PARSE_SINGULAR1(MESSAGE) \
72  ::google::protobuf::internal::TcParser::SingularParseMessage<MESSAGE, uint8_t>
73 #endif // PROTOBUF_TC_STATIC_PARSE_SINGULAR1
74 
75 #if PROTOBUF_TC_STATIC_PARSE_SINGULAR2
76 #define PROTOBUF_TC_PARSE_SINGULAR2(MESSAGE) MESSAGE::Tct_ParseS2
77 #else
78 #define PROTOBUF_TC_PARSE_SINGULAR2(MESSAGE) \
79  ::google::protobuf::internal::TcParser::SingularParseMessage<MESSAGE, uint16_t>
80 #endif // PROTOBUF_TC_STATIC_PARSE_SINGULAR2
81 
82 #if PROTOBUF_TC_STATIC_PARSE_REPEATED1
83 #define PROTOBUF_TC_PARSE_REPEATED1(MESSAGE) MESSAGE::Tct_ParseR1
84 #else
85 #define PROTOBUF_TC_PARSE_REPEATED1(MESSAGE) \
86  ::google::protobuf::internal::TcParser::RepeatedParseMessage<MESSAGE, uint8_t>
87 #endif // PROTOBUF_TC_STATIC_PARSE_REPEATED1
88 
89 #if PROTOBUF_TC_STATIC_PARSE_REPEATED2
90 #define PROTOBUF_TC_PARSE_REPEATED2(MESSAGE) MESSAGE::Tct_ParseR2
91 #else
92 #define PROTOBUF_TC_PARSE_REPEATED2(MESSAGE) \
93  ::google::protobuf::internal::TcParser::RepeatedParseMessage<MESSAGE, uint16_t>
94 #endif // PROTOBUF_TC_STATIC_PARSE_REPEATED2
95 
96 #ifndef NDEBUG
97 template <size_t align>
98 #ifndef _MSC_VER
99 [[noreturn]]
100 #endif
101 void AlignFail(uintptr_t address) {
102  GOOGLE_LOG(FATAL) << "Unaligned (" << align << ") access at " << address;
103 }
104 
105 extern template void AlignFail<4>(uintptr_t);
106 extern template void AlignFail<8>(uintptr_t);
107 #endif
108 
109 // TcParser implements most of the parsing logic for tailcall tables.
110 class TcParser final {
111  public:
112  static const char* GenericFallback(PROTOBUF_TC_PARAM_DECL);
113  static const char* GenericFallbackLite(PROTOBUF_TC_PARAM_DECL);
114 
115  // Dispatch to the designated parse function
116  inline PROTOBUF_ALWAYS_INLINE static const char* TagDispatch(
117  PROTOBUF_TC_PARAM_DECL) {
118  const auto coded_tag = UnalignedLoad<uint16_t>(ptr);
119  const size_t idx = coded_tag & table->fast_idx_mask;
120  PROTOBUF_ASSUME((idx & 7) == 0);
121  auto* fast_entry = table->fast_entry(idx >> 3);
122  data = fast_entry->bits;
123  data.data ^= coded_tag;
124  PROTOBUF_MUSTTAIL return fast_entry->target(PROTOBUF_TC_PARAM_PASS);
125  }
126 
127  // We can only safely call from field to next field if the call is optimized
128  // to a proper tail call. Otherwise we blow through stack. Clang and gcc
129  // reliably do this optimization in opt mode, but do not perform this in debug
130  // mode. Luckily the structure of the algorithm is such that it's always
131  // possible to just return and use the enclosing parse loop as a trampoline.
132  static const char* ToTagDispatch(PROTOBUF_TC_PARAM_DECL) {
133  constexpr bool always_return = !PROTOBUF_TAILCALL;
134  if (always_return || !ctx->DataAvailable(ptr)) {
135  PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
136  }
137  PROTOBUF_MUSTTAIL return TagDispatch(PROTOBUF_TC_PARAM_PASS);
138  }
139 
140  static const char* ParseLoop(MessageLite* msg, const char* ptr,
141  ParseContext* ctx,
142  const TcParseTableBase* table) {
143  ScopedArenaSwap saved(msg, ctx);
144  const uint32_t has_bits_offset = table->has_bits_offset;
145  while (!ctx->Done(&ptr)) {
146  uint64_t hasbits = 0;
147  if (has_bits_offset) hasbits = RefAt<uint32_t>(msg, has_bits_offset);
148  ptr = TagDispatch(msg, ptr, ctx, table, hasbits, {});
149  if (ptr == nullptr) break;
150  if (ctx->LastTag() != 1) break; // Ended on terminating tag
151  }
152  return ptr;
153  }
154 
155  template <typename FieldType, typename TagType>
156  PROTOBUF_NOINLINE static const char* SingularParseMessage(
157  PROTOBUF_TC_PARAM_DECL) {
158  if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
159  return table->fallback(PROTOBUF_TC_PARAM_PASS);
160  }
161  ptr += sizeof(TagType);
162  hasbits |= (uint64_t{1} << data.hasbit_idx());
163  auto& field = RefAt<FieldType*>(msg, data.offset());
164  if (field == nullptr) {
165  auto arena = ctx->data().arena;
167  field = Arena::CreateMessage<FieldType>(arena);
168  } else {
169  field = Arena::Create<FieldType>(arena);
170  }
171  }
172  SyncHasbits(msg, hasbits, table);
173  return ctx->ParseMessage(field, ptr);
174  }
175 
176  template <typename FieldType, typename TagType>
177  PROTOBUF_NOINLINE static const char* RepeatedParseMessage(
178  PROTOBUF_TC_PARAM_DECL) {
179  if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
180  return table->fallback(PROTOBUF_TC_PARAM_PASS);
181  }
182  ptr += sizeof(TagType);
183  auto& field = RefAt<RepeatedPtrField<FieldType>>(msg, data.offset());
184  SyncHasbits(msg, hasbits, table);
185  ptr = ctx->ParseMessage(field.Add(), ptr);
186  return ptr;
187  }
188 
189  template <typename LayoutType, typename TagType>
190  static const char* SingularFixed(PROTOBUF_TC_PARAM_DECL);
191  template <typename LayoutType, typename TagType>
192  static const char* RepeatedFixed(PROTOBUF_TC_PARAM_DECL);
193  template <typename LayoutType, typename TagType>
194  static const char* PackedFixed(PROTOBUF_TC_PARAM_DECL);
195 
196  enum VarintDecode { kNoConversion = 0, kZigZag = 1 };
197  template <typename FieldType, typename TagType, VarintDecode zigzag>
198  static const char* SingularVarint(PROTOBUF_TC_PARAM_DECL);
199  template <typename FieldType, typename TagType, VarintDecode zigzag>
200  static const char* RepeatedVarint(PROTOBUF_TC_PARAM_DECL);
201  template <typename FieldType, typename TagType, VarintDecode zigzag>
202  static const char* PackedVarint(PROTOBUF_TC_PARAM_DECL);
203 
204  enum Utf8Type { kNoUtf8 = 0, kUtf8 = 1, kUtf8ValidateOnly = 2 };
205  template <typename TagType, Utf8Type utf8>
206  static const char* SingularString(PROTOBUF_TC_PARAM_DECL);
207  template <typename TagType, Utf8Type utf8>
208  static const char* RepeatedString(PROTOBUF_TC_PARAM_DECL);
209 
210  template <typename T>
211  static inline T& RefAt(void* x, size_t offset) {
212  T* target = reinterpret_cast<T*>(static_cast<char*>(x) + offset);
213 #ifndef NDEBUG
214  if (PROTOBUF_PREDICT_FALSE(
215  reinterpret_cast<uintptr_t>(target) % alignof(T) != 0)) {
216  AlignFail<alignof(T)>(reinterpret_cast<uintptr_t>(target));
217  }
218 #endif
219  return *target;
220  }
221 
222  static inline PROTOBUF_ALWAYS_INLINE void SyncHasbits(
223  MessageLite* msg, uint64_t hasbits, const TcParseTableBase* table) {
224  const uint32_t has_bits_offset = table->has_bits_offset;
225  if (has_bits_offset) {
226  // Only the first 32 has-bits are updated. Nothing above those is stored,
227  // but e.g. messages without has-bits update the upper bits.
228  RefAt<uint32_t>(msg, has_bits_offset) = static_cast<uint32_t>(hasbits);
229  }
230  }
231 
232  protected:
233  static inline PROTOBUF_ALWAYS_INLINE const char* ToParseLoop(
234  PROTOBUF_TC_PARAM_DECL) {
235  (void)data;
236  (void)ctx;
237  SyncHasbits(msg, hasbits, table);
238  return ptr;
239  }
240 
241  static inline PROTOBUF_ALWAYS_INLINE const char* Error(
242  PROTOBUF_TC_PARAM_DECL) {
243  (void)data;
244  (void)ctx;
245  (void)ptr;
246  SyncHasbits(msg, hasbits, table);
247  return nullptr;
248  }
249 
250  class ScopedArenaSwap final {
251  public:
253  : ctx_(ctx), saved_(ctx->data().arena) {
254  ctx_->data().arena = msg->GetArenaForAllocation();
255  }
256  ScopedArenaSwap(const ScopedArenaSwap&) = delete;
257  ~ScopedArenaSwap() { ctx_->data().arena = saved_; }
258 
259  private:
261  Arena* const saved_;
262  };
263 
264  template <class MessageBaseT, class UnknownFieldsT>
265  static const char* GenericFallbackImpl(PROTOBUF_TC_PARAM_DECL) {
266 #define CHK_(x) \
267  if (PROTOBUF_PREDICT_FALSE(!(x))) return nullptr /* NOLINT */
268 
269  SyncHasbits(msg, hasbits, table);
270  uint32_t tag;
272  CHK_(ptr);
273  if ((tag & 7) == WireFormatLite::WIRETYPE_END_GROUP || tag == 0) {
274  ctx->SetLastTag(tag);
275  return ptr;
276  }
277  (void)data;
278  uint32_t num = tag >> 3;
279  if (table->extension_range_low <= num &&
280  num <= table->extension_range_high) {
281  return RefAt<ExtensionSet>(msg, table->extension_offset)
282  .ParseField(tag, ptr,
283  static_cast<const MessageBaseT*>(table->default_instance),
284  &msg->_internal_metadata_, ctx);
285  }
286  return UnknownFieldParse(
287  tag, msg->_internal_metadata_.mutable_unknown_fields<UnknownFieldsT>(),
288  ptr, ctx);
289 #undef CHK_
290  }
291 };
292 
293 // Declare helper functions:
294 #include <google/protobuf/generated_message_tctable_impl.inc>
295 
296 } // namespace internal
297 } // namespace protobuf
298 } // namespace google
299 
300 #include <google/protobuf/port_undef.inc>
301 
302 #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
google::protobuf.internal::TcParser::ParseLoop
static const char * ParseLoop(MessageLite *msg, const char *ptr, ParseContext *ctx, const TcParseTableBase *table)
Definition: generated_message_tctable_impl.h:140
ctx::arena
upb_Arena * arena
Definition: conformance_upb.c:84
google::protobuf.internal::TcParser::ScopedArenaSwap::saved_
Arena *const saved_
Definition: generated_message_tctable_impl.h:261
ctx
Definition: benchmark-async.c:30
google::protobuf.internal::TcParser::GenericFallbackImpl
static const char * GenericFallbackImpl(PROTOBUF_TC_PARAM_DECL)
Definition: generated_message_tctable_impl.h:265
google::protobuf.internal::TcParser::ScopedArenaSwap::~ScopedArenaSwap
~ScopedArenaSwap()
Definition: generated_message_tctable_impl.h:257
google::protobuf.internal::UnknownFieldParse
const char * UnknownFieldParse(uint32 tag, std::string *unknown, const char *ptr, ParseContext *ctx)
Definition: bloaty/third_party/protobuf/src/google/protobuf/parse_context.cc:606
Arena
Definition: arena.c:39
google::protobuf.internal::ParseContext
Definition: bloaty/third_party/protobuf/src/google/protobuf/parse_context.h:336
google::protobuf
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:12
google::protobuf.internal::TcParser::ToParseLoop
static const PROTOBUF_ALWAYS_INLINE char * ToParseLoop(PROTOBUF_TC_PARAM_DECL)
Definition: generated_message_tctable_impl.h:233
ctx_
ClientContext ctx_
Definition: client_interceptors_end2end_test.cc:289
google::protobuf::MessageLite
Definition: bloaty/third_party/protobuf/src/google/protobuf/message_lite.h:184
google::protobuf.internal::TcParseTableBase
Definition: generated_message_tctable_decl.h:80
google::protobuf::python::cmessage::UnknownFieldSet
static PyObject * UnknownFieldSet(CMessage *self)
Definition: bloaty/third_party/protobuf/python/google/protobuf/pyext/message.cc:2512
T
#define T(upbtypeconst, upbtype, ctype, default_value)
arena
grpc_core::ScopedArenaPtr arena
Definition: binder_transport_test.cc:237
google::protobuf.internal::AlignFail< 8 >
template void AlignFail< 8 >(uintptr_t)
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
google::protobuf.internal.decoder.ReadTag
def ReadTag(buffer, pos)
Definition: bloaty/third_party/protobuf/python/google/protobuf/internal/decoder.py:174
tag
static void * tag(intptr_t t)
Definition: bad_client.cc:318
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
google::protobuf.internal::AlignFail
void AlignFail(uintptr_t address)
Definition: generated_message_tctable_impl.h:101
google::protobuf.internal::TcParser::TagDispatch
static const PROTOBUF_ALWAYS_INLINE char * TagDispatch(PROTOBUF_TC_PARAM_DECL)
Definition: generated_message_tctable_impl.h:116
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
google::protobuf.internal::TcParser
Definition: generated_message_tctable_impl.h:110
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
uintptr_t
_W64 unsigned int uintptr_t
Definition: stdint-msvc2008.h:119
google::protobuf.internal::TcParser::Utf8Type
Utf8Type
Definition: generated_message_tctable_impl.h:204
setup.idx
idx
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:197
msg
std::string msg
Definition: client_interceptors_end2end_test.cc:372
google::protobuf.internal::TcParser::RepeatedParseMessage
static const PROTOBUF_NOINLINE char * RepeatedParseMessage(PROTOBUF_TC_PARAM_DECL)
Definition: generated_message_tctable_impl.h:177
google::protobuf.internal::TcParser::ScopedArenaSwap::ScopedArenaSwap
ScopedArenaSwap(MessageLite *msg, ParseContext *ctx)
Definition: generated_message_tctable_impl.h:252
value
const char * value
Definition: hpack_parser_table.cc:165
google::protobuf.internal::TcParser::ToTagDispatch
static const char * ToTagDispatch(PROTOBUF_TC_PARAM_DECL)
Definition: generated_message_tctable_impl.h:132
FATAL
#define FATAL(msg)
Definition: task.h:88
generated_message_tctable_decl.h
field
const FieldDescriptor * field
Definition: bloaty/third_party/protobuf/src/google/protobuf/compiler/parser_unittest.cc:2692
absl::time_internal::cctz::detail::align
CONSTEXPR_F fields align(second_tag, fields f) noexcept
Definition: abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h:325
PROTOBUF_TC_PARAM_PASS
#define PROTOBUF_TC_PARAM_PASS
Definition: generated_message_tctable_impl.h:64
google::protobuf.internal::TcParser::SingularParseMessage
static const PROTOBUF_NOINLINE char * SingularParseMessage(PROTOBUF_TC_PARAM_DECL)
Definition: generated_message_tctable_impl.h:156
xds_manager.num
num
Definition: xds_manager.py:56
google::protobuf.internal::WireFormatLite::WIRETYPE_END_GROUP
@ WIRETYPE_END_GROUP
Definition: bloaty/third_party/protobuf/src/google/protobuf/wire_format_lite.h:106
internal
Definition: benchmark/test/output_test_helper.cc:20
table
uint8_t table[256]
Definition: hpack_parser.cc:456
google::protobuf.internal::TcParser::VarintDecode
VarintDecode
Definition: generated_message_tctable_impl.h:196
CHK_
#define CHK_(x)
google::protobuf.internal::TcParser::ScopedArenaSwap::ctx_
ParseContext *const ctx_
Definition: generated_message_tctable_impl.h:260
google::protobuf.internal::TcParser::RefAt
static T & RefAt(void *x, size_t offset)
Definition: generated_message_tctable_impl.h:211
GOOGLE_LOG
#define GOOGLE_LOG(LEVEL)
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/logging.h:146
google::protobuf.internal::TcParser::SyncHasbits
static PROTOBUF_ALWAYS_INLINE void SyncHasbits(MessageLite *msg, uint64_t hasbits, const TcParseTableBase *table)
Definition: generated_message_tctable_impl.h:222
setup.target
target
Definition: third_party/bloaty/third_party/protobuf/python/setup.py:179
google
Definition: bloaty/third_party/protobuf/benchmarks/util/data_proto2_to_proto3_util.h:11
Message
Definition: protobuf/php/ext/google/protobuf/message.c:53
google::protobuf.internal::TcParser::Error
static const PROTOBUF_ALWAYS_INLINE char * Error(PROTOBUF_TC_PARAM_DECL)
Definition: generated_message_tctable_impl.h:241
offset
voidpf uLong offset
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:142
google::protobuf.internal::TcParser::ScopedArenaSwap
Definition: generated_message_tctable_impl.h:250
google::protobuf.internal::AlignFail< 4 >
template void AlignFail< 4 >(uintptr_t)


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:59:24