Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-15 09:11:35

0001 // Protocol Buffers - Google's data interchange format
0002 // Copyright 2008 Google Inc.  All rights reserved.
0003 //
0004 // Use of this source code is governed by a BSD-style
0005 // license that can be found in the LICENSE file or at
0006 // https://developers.google.com/open-source/licenses/bsd
0007 
0008 // A common header that is included across all protobuf headers.  We do our best
0009 // to avoid #defining any macros here; instead we generally put macros in
0010 // port_def.inc and port_undef.inc so they are not visible from outside of
0011 // protobuf.
0012 
0013 #ifndef GOOGLE_PROTOBUF_PORT_H__
0014 #define GOOGLE_PROTOBUF_PORT_H__
0015 
0016 #include <atomic>
0017 #include <cassert>
0018 #include <cstddef>
0019 #include <cstdint>
0020 #include <new>
0021 #include <optional>
0022 #include <string>
0023 #include <type_traits>
0024 #include <typeinfo>
0025 
0026 #include "absl/base/optimization.h"
0027 
0028 
0029 #include "absl/base/attributes.h"
0030 #include "absl/base/config.h"
0031 #include "absl/meta/type_traits.h"
0032 #include "absl/strings/string_view.h"
0033 
0034 #if defined(ABSL_HAVE_ADDRESS_SANITIZER)
0035 #include <sanitizer/asan_interface.h>
0036 #endif
0037 
0038 // must be last
0039 #include "google/protobuf/port_def.inc"
0040 
0041 
0042 namespace google {
0043 namespace protobuf {
0044 
0045 class MessageLite;
0046 
0047 namespace internal {
0048 
0049 PROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const std::string& str);
0050 
0051 struct MessageTraitsImpl;
0052 
0053 template <typename T>
0054 PROTOBUF_ALWAYS_INLINE void StrongPointer(T* var) {
0055 #if defined(__GNUC__)
0056   asm("" : : "r"(var));
0057 #else
0058   auto volatile unused = var;
0059   (void)&unused;  // Use address to avoid an extra load of "unused".
0060 #endif
0061 }
0062 
0063 #if defined(__x86_64__) && defined(__linux__) && !defined(__APPLE__) && \
0064     !defined(__ANDROID__) && defined(__clang__) && __clang_major__ >= 19
0065 // Optimized implementation for clang where we can generate a relocation without
0066 // adding runtime instructions.
0067 template <typename T, T ptr>
0068 PROTOBUF_ALWAYS_INLINE void StrongPointer() {
0069   // This injects a relocation in the code path without having to run code, but
0070   // we can only do it with a newer clang.
0071   asm(".reloc ., BFD_RELOC_NONE, %p0" ::"Ws"(ptr));
0072 }
0073 
0074 template <typename T, typename TraitsImpl = MessageTraitsImpl>
0075 PROTOBUF_ALWAYS_INLINE void StrongReferenceToType() {
0076   static constexpr auto ptr =
0077       decltype(TraitsImpl::template value<T>)::StrongPointer();
0078   // This is identical to the implementation of StrongPointer() above, but it
0079   // has to be explicitly inlined here or else Clang 19 will raise an error in
0080   // some configurations.
0081   asm(".reloc ., BFD_RELOC_NONE, %p0" ::"Ws"(ptr));
0082 }
0083 #else   // .reloc
0084 // Portable fallback. It usually generates a single LEA instruction or
0085 // equivalent.
0086 template <typename T, T ptr>
0087 PROTOBUF_ALWAYS_INLINE void StrongPointer() {
0088   StrongPointer(ptr);
0089 }
0090 
0091 template <typename T, typename TraitsImpl = MessageTraitsImpl>
0092 PROTOBUF_ALWAYS_INLINE void StrongReferenceToType() {
0093   return StrongPointer(
0094       decltype(TraitsImpl::template value<T>)::StrongPointer());
0095 }
0096 #endif  // .reloc
0097 
0098 
0099 // See comments on `AllocateAtLeast` for information on size returning new.
0100 struct SizedPtr {
0101   void* p;
0102   size_t n;
0103 };
0104 
0105 // Debug hook allowing setting up test scenarios for AllocateAtLeast usage.
0106 using AllocateAtLeastHookFn = SizedPtr (*)(size_t, void*);
0107 
0108 // `AllocAtLeastHook` API
0109 constexpr bool HaveAllocateAtLeastHook();
0110 void SetAllocateAtLeastHook(AllocateAtLeastHookFn fn, void* context = nullptr);
0111 
0112 #if !defined(NDEBUG) && defined(ABSL_HAVE_THREAD_LOCAL) && \
0113     defined(__cpp_inline_variables)
0114 
0115 // Hook data for current thread. These vars must not be accessed directly, use
0116 // the 'HaveAllocateAtLeastHook()` and `SetAllocateAtLeastHook()` API instead.
0117 inline thread_local AllocateAtLeastHookFn allocate_at_least_hook = nullptr;
0118 inline thread_local void* allocate_at_least_hook_context = nullptr;
0119 
0120 constexpr bool HaveAllocateAtLeastHook() { return true; }
0121 inline void SetAllocateAtLeastHook(AllocateAtLeastHookFn fn, void* context) {
0122   allocate_at_least_hook = fn;
0123   allocate_at_least_hook_context = context;
0124 }
0125 
0126 #else  // !NDEBUG && ABSL_HAVE_THREAD_LOCAL && __cpp_inline_variables
0127 
0128 constexpr bool HaveAllocateAtLeastHook() { return false; }
0129 inline void SetAllocateAtLeastHook(AllocateAtLeastHookFn fn, void* context) {}
0130 
0131 #endif  // !NDEBUG && ABSL_HAVE_THREAD_LOCAL && __cpp_inline_variables
0132 
0133 // Allocates at least `size` bytes. This function follows the c++ language
0134 // proposal from D0901R10 (http://wg21.link/D0901R10) and will be implemented
0135 // in terms of the new operator new semantics when available. The allocated
0136 // memory should be released by a call to `SizedDelete` or `::operator delete`.
0137 inline SizedPtr AllocateAtLeast(size_t size) {
0138 #if !defined(NDEBUG) && defined(ABSL_HAVE_THREAD_LOCAL) && \
0139     defined(__cpp_inline_variables)
0140   if (allocate_at_least_hook != nullptr) {
0141     return allocate_at_least_hook(size, allocate_at_least_hook_context);
0142   }
0143 #endif  // !NDEBUG && ABSL_HAVE_THREAD_LOCAL && __cpp_inline_variables
0144   return {::operator new(size), size};
0145 }
0146 
0147 inline void SizedDelete(void* p, size_t size) {
0148 #if defined(__cpp_sized_deallocation)
0149   ::operator delete(p, size);
0150 #else
0151   // Avoid -Wunused-parameter
0152   (void)size;
0153   ::operator delete(p);
0154 #endif
0155 }
0156 inline void SizedArrayDelete(void* p, size_t size) {
0157 #if defined(__cpp_sized_deallocation)
0158   ::operator delete[](p, size);
0159 #else
0160   // Avoid -Wunused-parameter
0161   (void)size;
0162   ::operator delete[](p);
0163 #endif
0164 }
0165 
0166 // Tag type used to invoke the constinit constructor overload of classes
0167 // such as ArenaStringPtr and MapFieldBase. Such constructors are internal
0168 // implementation details of the library.
0169 struct ConstantInitialized {
0170   explicit ConstantInitialized() = default;
0171 };
0172 
0173 // Tag type used to invoke the arena constructor overload of classes such
0174 // as ExtensionSet and MapFieldLite in aggregate initialization. These
0175 // classes typically don't have move/copy constructors, which rules out
0176 // explicit initialization in pre-C++17.
0177 struct ArenaInitialized {
0178   explicit ArenaInitialized() = default;
0179 };
0180 
0181 template <typename To, typename From>
0182 void AssertDownCast(From* from) {
0183   static_assert(std::is_base_of<From, To>::value, "illegal DownCast");
0184 
0185   // Check that this function is not used to downcast message types.
0186   // For those we should use {Down,Dynamic}CastTo{Message,Generated}.
0187   static_assert(!std::is_base_of_v<MessageLite, To>);
0188 
0189 #if PROTOBUF_RTTI
0190   // RTTI: debug mode only!
0191   assert(from == nullptr || dynamic_cast<To*>(from) != nullptr);
0192 #endif
0193 }
0194 
0195 template <typename To, typename From>
0196 inline To DownCast(From* f) {
0197   AssertDownCast<std::remove_pointer_t<To>>(f);
0198   return static_cast<To>(f);
0199 }
0200 
0201 template <typename ToRef, typename From>
0202 inline ToRef DownCast(From& f) {
0203   AssertDownCast<std::remove_reference_t<ToRef>>(&f);
0204   return static_cast<ToRef>(f);
0205 }
0206 
0207 // Looks up the name of `T` via RTTI, if RTTI is available.
0208 template <typename T>
0209 inline std::optional<absl::string_view> RttiTypeName() {
0210 #if PROTOBUF_RTTI
0211   return typeid(T).name();
0212 #else
0213   return std::nullopt;
0214 #endif
0215 }
0216 
0217 // Helpers for identifying our supported types.
0218 template <typename T>
0219 struct is_supported_integral_type
0220     : absl::disjunction<std::is_same<T, int32_t>, std::is_same<T, uint32_t>,
0221                         std::is_same<T, int64_t>, std::is_same<T, uint64_t>,
0222                         std::is_same<T, bool>> {};
0223 
0224 template <typename T>
0225 struct is_supported_floating_point_type
0226     : absl::disjunction<std::is_same<T, float>, std::is_same<T, double>> {};
0227 
0228 template <typename T>
0229 struct is_supported_string_type
0230     : absl::disjunction<std::is_same<T, std::string>> {};
0231 
0232 template <typename T>
0233 struct is_supported_scalar_type
0234     : absl::disjunction<is_supported_integral_type<T>,
0235                         is_supported_floating_point_type<T>,
0236                         is_supported_string_type<T>> {};
0237 
0238 template <typename T>
0239 struct is_supported_message_type
0240     : absl::disjunction<std::is_base_of<MessageLite, T>> {
0241   static constexpr auto force_complete_type = sizeof(T);
0242 };
0243 
0244 // To prevent sharing cache lines between threads
0245 #ifdef __cpp_aligned_new
0246 enum { kCacheAlignment = 64 };
0247 #else
0248 enum { kCacheAlignment = alignof(max_align_t) };  // do the best we can
0249 #endif
0250 
0251 // The maximum byte alignment we support.
0252 enum { kMaxMessageAlignment = 8 };
0253 
0254 inline constexpr bool EnableStableExperiments() {
0255 #if defined(PROTOBUF_ENABLE_STABLE_EXPERIMENTS)
0256   return true;
0257 #else
0258   return false;
0259 #endif
0260 }
0261 
0262 inline constexpr bool EnableExperimentalMicroString() {
0263 #if defined(PROTOBUF_ENABLE_EXPERIMENTAL_MICRO_STRING)
0264   return true;
0265 #endif
0266   return EnableStableExperiments();
0267 }
0268 
0269 inline constexpr bool ForceInlineStringInProtoc() {
0270   return EnableStableExperiments();
0271 }
0272 
0273 inline constexpr bool ForceEagerlyVerifiedLazyInProtoc() {
0274   return EnableStableExperiments();
0275 }
0276 
0277 // Returns true if debug hardening for clearing oneof message on arenas is
0278 // enabled.
0279 inline constexpr bool DebugHardenClearOneofMessageOnArena() {
0280 #ifdef NDEBUG
0281   return false;
0282 #else
0283   return true;
0284 #endif
0285 }
0286 
0287 constexpr bool HasAnySanitizer() {
0288 #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
0289     defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
0290   return true;
0291 #else
0292   return false;
0293 #endif
0294 }
0295 
0296 constexpr bool PerformDebugChecks() {
0297   if (HasAnySanitizer()) return true;
0298 #if defined(NDEBUG)
0299   return false;
0300 #else
0301   return true;
0302 #endif
0303 }
0304 
0305 // Force copy the default string to a string field so that non-optimized builds
0306 // have harder-to-rely-on address stability.
0307 constexpr bool DebugHardenForceCopyDefaultString() {
0308   return false;
0309 }
0310 
0311 constexpr bool DebugHardenForceCopyInRelease() {
0312   return false;
0313 }
0314 
0315 constexpr bool DebugHardenForceCopyInSwap() {
0316   return false;
0317 }
0318 
0319 constexpr bool DebugHardenForceCopyInMove() {
0320   return false;
0321 }
0322 
0323 constexpr bool DebugHardenForceAllocationOnConstruction() {
0324   return false;
0325 }
0326 
0327 constexpr bool DebugHardenFuzzMessageSpaceUsedLong() {
0328   return false;
0329 }
0330 
0331 inline constexpr bool DebugHardenVerifyHasBitConsistency() {
0332 #if !defined(NDEBUG) || defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
0333     defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
0334   return true;
0335 #endif
0336   return false;
0337 }
0338 
0339 // Reads n bytes from p, if PerformDebugChecks() is true. This allows ASAN to
0340 // detect if a range of memory is not valid when we expect it to be. The
0341 // volatile keyword is necessary here to prevent the compiler from optimizing
0342 // away the memory reads below.
0343 inline void AssertBytesAreReadable(const volatile char* p, int n) {
0344   if (PerformDebugChecks()) {
0345     for (int i = 0; i < n; ++i) {
0346       p[i];
0347     }
0348   }
0349 }
0350 
0351 // Returns true if pointers are 8B aligned, leaving least significant 3 bits
0352 // available.
0353 inline constexpr bool PtrIsAtLeast8BAligned() { return alignof(void*) >= 8; }
0354 
0355 inline constexpr bool IsLazyParsingSupported() {
0356   // We need 3 bits for pointer tagging in lazy parsing.
0357   return PtrIsAtLeast8BAligned();
0358 }
0359 
0360 #if defined(ABSL_IS_LITTLE_ENDIAN)
0361 constexpr bool IsLittleEndian() { return true; }
0362 #elif defined(ABSL_IS_BIG_ENDIAN)
0363 constexpr bool IsLittleEndian() { return false; }
0364 #else
0365 #error "Only little-endian and big-endian are supported"
0366 #endif
0367 constexpr bool IsBigEndian() { return !IsLittleEndian(); }
0368 
0369 //----------------------- Cache-prefetching utilities --------------------------
0370 
0371 struct PrefetchOpts {
0372   // WARNING: The numeric values of `Locality` and `MemOp` are significant
0373   // because they are directly consumed by `__builtin_prefetch()`:
0374   // see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
0375 
0376   // Indicates the cache locality to prefetch into.
0377   enum Locality : int {
0378     // Prefetch data into non-temporal cache structure and into a location close
0379     // to the processor, minimizing cache pollution.
0380     kNta = 0,
0381     // Prefetch data into L3 cache, or an implementation-specific choice.
0382     kLow = 1,
0383     // Prefetch data into L3 and L2 cache.
0384     kMedium = 2,
0385     // Prefetch data into all levels of cache.
0386     kHigh = 3,
0387   };
0388   // Indicates the intended memory access type to optimize prefetching for.
0389   enum MemOp : int { kRead = 0, kWrite = 1 };
0390   // Specifies the unit of `Amount` below.
0391   enum Unit : int { kBytes, kLines, kObjects };
0392 
0393   // The amount to prefetch, or the distance to prefetch from.
0394   struct Amount {
0395 #ifdef ABSL_REQUIRE_EXPLICIT_INIT
0396     const size_t num ABSL_REQUIRE_EXPLICIT_INIT;
0397     const Unit unit ABSL_REQUIRE_EXPLICIT_INIT;
0398 #else
0399     const size_t num = 1;
0400     const Unit unit = kLines;
0401 #endif
0402 
0403     // Scales this amount to bytes. If `unit` is `kObjects`, `T` must be a valid
0404     // pointed-to type. If it is not, an invalid zero amount is returned.
0405     template <typename T>
0406     constexpr Amount ToBytes() const {
0407       switch (unit) {
0408         case kBytes:
0409           return *this;
0410         case kLines:
0411           return {num * ABSL_CACHELINE_SIZE, kBytes};
0412         case kObjects:
0413           if constexpr (!std::is_same_v<T, void>) {
0414             return {num * sizeof(T), kBytes};
0415           } else {
0416             // Can't use `assert()` or `__builtin_trap()` here because they're
0417             // not constexpr. Just return an invalid amount instead.
0418             return {0, kBytes};
0419           }
0420       }
0421     }
0422 
0423     // Scales this amount to whole cache lines, rounding up. If `unit` is
0424     // `kObjects`, `T` must be a valid pointed-to type. If it is not, an invalid
0425     // zero amount is returned.
0426     template <typename T>
0427     constexpr Amount ToLines() const {
0428       switch (unit) {
0429         case kBytes:
0430           return {
0431               (num + ABSL_CACHELINE_SIZE - 1) / ABSL_CACHELINE_SIZE,
0432               kLines,
0433           };
0434         case kLines:
0435           return *this;
0436         case kObjects:
0437           if constexpr (!std::is_same_v<T, void>) {
0438             return {
0439                 (num * sizeof(T) + ABSL_CACHELINE_SIZE - 1) /
0440                     ABSL_CACHELINE_SIZE,
0441                 kLines,
0442             };
0443           } else {
0444             // Can't use `assert()` or `__builtin_trap()` here because they're
0445             // not constexpr. Just return an invalid amount instead.
0446             return {0, kBytes};
0447           }
0448       }
0449     }
0450   };
0451 
0452 #ifdef ABSL_REQUIRE_EXPLICIT_INIT
0453   const Amount num ABSL_REQUIRE_EXPLICIT_INIT;
0454 #else
0455   const Amount num = {1, kLines};
0456 #endif
0457   const Amount from = {0, kBytes};
0458   const Locality locality = kHigh;
0459   const MemOp mem_op = kRead;
0460 };
0461 
0462 // NOTE: Enable prefetching with Clang only: various problems with other
0463 // compilers, especially old ones.
0464 #if defined(__clang__) && ABSL_HAVE_BUILTIN(__builtin_prefetch)
0465 
0466 namespace detail {
0467 
0468 // Prefetches a single cache line. To form the address to prefetch, the base
0469 // `ptr` is first offset by `kOpts.from.num` bytes and furthermore by `line`
0470 // cache lines (note that `line` overrides `kOpts.num.num`).
0471 template <const PrefetchOpts& kOpts>
0472 PROTOBUF_ALWAYS_INLINE void PrefetchLine(const void* ptr, size_t line) {
0473   static_assert(kOpts.from.unit == PrefetchOpts::kBytes);
0474   const ptrdiff_t offset = kOpts.from.num + (line * ABSL_CACHELINE_SIZE);
0475   // Pointer + offset overflows don't matter for prefetching, because the
0476   // prefetch instruction is just a no-op for invalid addresses (although
0477   // potentially incurring the cost of a TLB page-walk if there's no valid
0478   // mapping for the page - but that should be rare in practice). Still, to
0479   // formally avoid UB, we perform the arithmetic in uintptr_t space.
0480   const void* prefetch_ptr =
0481       reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(ptr) + offset);
0482   __builtin_prefetch(prefetch_ptr, kOpts.mem_op, kOpts.locality);
0483 }
0484 
0485 }  // namespace detail
0486 
0487 // Prefetches a sequence of `kOpts.num.ToLines()` cache lines to the levels of
0488 // cache specified by `kOpts.locality`, starting at `ptr` base pointer
0489 // furthermore offset by `kOpts.from.ToBytes()` bytes, and optimized for
0490 // `kOpts.mem_op` type of expected memory access.
0491 //
0492 // The `kOpts` template parameter must be a compile-time constant, which means
0493 // either `inline constexpr` in the global scope or `static constexpr` in a
0494 // function or class.
0495 //
0496 // When `kOpts.num.unit` or `kOpts.from.unit` is `kObjects`, the `T` template
0497 // parameter must be explicitly specified and `sizeof(T)` must be valid and
0498 // non-zero (i.e. T must be a non-void, complete type): it is used to scale
0499 // `kOpts.num.num` and `kOpts.from.num` to bytes and lines, respectively.
0500 //
0501 // The `U` template parameter doesn't need to be explicitly specified: it is
0502 // deduced from `ptr` and, if non-void and `T` is also non-void, checked for
0503 // compatibility with `T` to prevent accidental mismatches between the actual
0504 // pointed-to and declared prefetched types.
0505 //
0506 // WARNING: Do not default `T` to `U` or vice versa: that may hide subtle errors
0507 // at call sites, e.g. when `ptr` points at the base class of the actual object.
0508 //
0509 // TODO: Simplify definition/usages after C++20 per the bug.
0510 template <const PrefetchOpts& kOpts, typename T = void, typename U>
0511 PROTOBUF_ALWAYS_INLINE void Prefetch(const U* ptr) {
0512   // TODO: Add a check: prefetched amount <= some reasonable limit.
0513   if constexpr (kOpts.num.unit == PrefetchOpts::kObjects ||
0514                 kOpts.from.unit == PrefetchOpts::kObjects) {
0515     static_assert(sizeof(T) > 0, "Need explicit, non-void, complete T");
0516   }
0517   if constexpr (!std::is_void_v<T> && !std::is_void_v<U>) {
0518     // Prevent accidental mistakes, but only when it's matters.
0519     static_assert(std::is_convertible_v<T*, U*>, "Type mismatch");
0520   }
0521   static constexpr PrefetchOpts kScaledOpts = {
0522       kOpts.num.ToLines<T>(),
0523       kOpts.from.ToBytes<T>(),
0524       kOpts.locality,
0525       kOpts.mem_op,
0526   };
0527   // Unroll the loop iterations by blocks of 16 in optimized builds.
0528 #pragma unroll 16
0529   for (size_t line = 0; line < kScaledOpts.num.num; ++line) {
0530     detail::PrefetchLine<kScaledOpts>(ptr, line);
0531   }
0532 }
0533 
0534 // Legacy prefetch functions.
0535 // TODO: Replace calls to these functions and remove them per the
0536 // bug.
0537 
0538 // Prefetch 5 64-byte cache line starting from 7 cache-lines ahead.
0539 // Constants are somewhat arbitrary and pretty aggressive, but were
0540 // chosen to give a better benchmark results. E.g. this is ~20%
0541 // faster, single cache line prefetch is ~12% faster, increasing
0542 // decreasing distance makes results 2-4% worse. Important note,
0543 // prefetch doesn't require a valid address, so it is ok to prefetch
0544 // past the end of message/valid memory. Only insert prefetch once per function.
0545 PROTOBUF_ALWAYS_INLINE void Prefetch5LinesFrom7Lines(const void* ptr) {
0546   static constexpr PrefetchOpts kOpts = {
0547       /*num=*/{5, PrefetchOpts::kLines},
0548       /*from=*/{7, PrefetchOpts::kLines},
0549       /*locality=*/PrefetchOpts::kHigh,
0550   };
0551   Prefetch<kOpts>(ptr);
0552 }
0553 
0554 // Prefetch 5 64-byte cache lines starting from 1 cache-line ahead.
0555 PROTOBUF_ALWAYS_INLINE void Prefetch5LinesFrom1Line(const void* ptr) {
0556   static constexpr PrefetchOpts kOpts = {
0557       /*num=*/{5, PrefetchOpts::kLines},
0558       /*from=*/{1, PrefetchOpts::kLines},
0559       /*locality=*/PrefetchOpts::kHigh,
0560   };
0561   Prefetch<kOpts>(ptr);
0562 }
0563 
0564 // This trampoline allows calling from codegen without needing a #include to
0565 // absl. It simplifies IWYU and deps.
0566 inline void PrefetchToLocalCache(const void* ptr) {
0567   static constexpr PrefetchOpts kOpts = {
0568       /*num=*/{1, PrefetchOpts::kLines},
0569       /*from=*/{0, PrefetchOpts::kLines},
0570       /*locality=*/PrefetchOpts::kHigh,
0571   };
0572   Prefetch<kOpts>(ptr);
0573 }
0574 
0575 #else  // defined(__clang__) || ABSL_HAVE_BUILTIN(__builtin_prefetch)
0576 
0577 template <const PrefetchOpts& kOpts, typename T, typename U>
0578 PROTOBUF_ALWAYS_INLINE void Prefetch(const void*) {}
0579 PROTOBUF_ALWAYS_INLINE void Prefetch5LinesFrom7Lines(const void* ptr) {}
0580 PROTOBUF_ALWAYS_INLINE void Prefetch5LinesFrom1Line(const void* ptr) {}
0581 inline void PrefetchToLocalCache(const void* ptr) {}
0582 
0583 #endif  // defined(__clang__) && ABSL_HAVE_BUILTIN(__builtin_prefetch)
0584 
0585 #if defined(NDEBUG) && ABSL_HAVE_BUILTIN(__builtin_unreachable)
0586 [[noreturn]] ABSL_ATTRIBUTE_COLD PROTOBUF_ALWAYS_INLINE void Unreachable() {
0587   __builtin_unreachable();
0588 }
0589 #elif ABSL_HAVE_BUILTIN(__builtin_FILE) && ABSL_HAVE_BUILTIN(__builtin_LINE)
0590 [[noreturn]] ABSL_ATTRIBUTE_COLD inline void Unreachable(
0591     const char* file = __builtin_FILE(), int line = __builtin_LINE()) {
0592   protobuf_assumption_failed("Unreachable", file, line);
0593 }
0594 #else
0595 [[noreturn]] ABSL_ATTRIBUTE_COLD inline void Unreachable() {
0596   protobuf_assumption_failed("Unreachable", "", 0);
0597 }
0598 #endif
0599 
0600 constexpr bool HasMemoryPoisoning() {
0601 #if defined(ABSL_HAVE_ADDRESS_SANITIZER)
0602   return true;
0603 #else
0604   return false;
0605 #endif
0606 }
0607 
0608 // Poison memory region when supported by sanitizer config.
0609 inline void PoisonMemoryRegion([[maybe_unused]] const void* p,
0610                                [[maybe_unused]] size_t n) {
0611 #if defined(ABSL_HAVE_ADDRESS_SANITIZER)
0612   ASAN_POISON_MEMORY_REGION(p, n);
0613 #else
0614   // Nothing
0615 #endif
0616 }
0617 
0618 inline void UnpoisonMemoryRegion([[maybe_unused]] const void* p,
0619                                  [[maybe_unused]] size_t n) {
0620 #if defined(ABSL_HAVE_ADDRESS_SANITIZER)
0621   ASAN_UNPOISON_MEMORY_REGION(p, n);
0622 #else
0623   // Nothing
0624 #endif
0625 }
0626 
0627 inline bool IsMemoryPoisoned([[maybe_unused]] const void* p) {
0628 #if defined(ABSL_HAVE_ADDRESS_SANITIZER)
0629   return __asan_address_is_poisoned(p);
0630 #else
0631   return false;
0632 #endif
0633 }
0634 
0635 #if defined(ABSL_HAVE_THREAD_SANITIZER)
0636 // TODO: it would be preferable to use __tsan_external_read/
0637 // __tsan_external_write, but they can cause dlopen issues.
0638 template <typename T>
0639 PROTOBUF_ALWAYS_INLINE void TSanRead(const T* impl) {
0640   char protobuf_tsan_dummy = impl->_tsan_detect_race;
0641   asm volatile("" : "+r"(protobuf_tsan_dummy));
0642 }
0643 
0644 // We currently use a dedicated member for TSan checking so the value of this
0645 // member is not important. We can unconditionally write to it without affecting
0646 // correctness of the rest of the class.
0647 template <typename T>
0648 PROTOBUF_ALWAYS_INLINE void TSanWrite(T* impl) {
0649   impl->_tsan_detect_race = 0;
0650 }
0651 #else
0652 PROTOBUF_ALWAYS_INLINE void TSanRead(const void*) {}
0653 PROTOBUF_ALWAYS_INLINE void TSanWrite(const void*) {}
0654 #endif
0655 
0656 // Like C++20's std::type_identity_t, usually used to alter type deduction in
0657 // templates.
0658 template <typename T>
0659 using type_identity_t = std::enable_if_t<true, T>;
0660 
0661 template <typename T>
0662 constexpr T* Launder(T* p) {
0663 #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
0664   return std::launder(p);
0665 #elif ABSL_HAVE_BUILTIN(__builtin_launder)
0666   return __builtin_launder(p);
0667 #else
0668   return p;
0669 #endif
0670 }
0671 
0672 #if defined(PROTOBUF_CUSTOM_VTABLE)
0673 template <typename T>
0674 constexpr bool EnableCustomNewFor() {
0675   return true;
0676 }
0677 #elif ABSL_HAVE_BUILTIN(__is_bitwise_cloneable)
0678 template <typename T>
0679 constexpr bool EnableCustomNewFor() {
0680   return __is_bitwise_cloneable(T);
0681 }
0682 #else
0683 template <typename T>
0684 constexpr bool EnableCustomNewFor() {
0685   return false;
0686 }
0687 #endif
0688 
0689 constexpr bool IsOss() { return true; }
0690 
0691 // Counter library for debugging internal protobuf logic.
0692 // It allows instrumenting code that has different options (eg fast vs slow
0693 // path) to get visibility into how much we are hitting each path.
0694 // When compiled with -DPROTOBUF_INTERNAL_ENABLE_DEBUG_COUNTERS, the counters
0695 // register an atexit handler to dump the table. Otherwise, they are a noop and
0696 // have not runtime cost.
0697 //
0698 // Usage:
0699 //
0700 // if (do_fast) {
0701 //   PROTOBUF_DEBUG_COUNTER("Foo.Fast").Inc();
0702 //   ...
0703 // } else {
0704 //   PROTOBUF_DEBUG_COUNTER("Foo.Slow").Inc();
0705 //   ...
0706 // }
0707 class PROTOBUF_EXPORT RealDebugCounter {
0708  public:
0709   explicit RealDebugCounter(absl::string_view name) { Register(name); }
0710   // Lossy increment.
0711   void Inc() { counter_.store(value() + 1, std::memory_order_relaxed); }
0712   size_t value() const { return counter_.load(std::memory_order_relaxed); }
0713 
0714  private:
0715   void Register(absl::string_view name);
0716   std::atomic<size_t> counter_{};
0717 };
0718 
0719 // When the feature is not enabled, the type is a noop.
0720 class NoopDebugCounter {
0721  public:
0722   explicit constexpr NoopDebugCounter() = default;
0723   constexpr void Inc() {}
0724 };
0725 
0726 // Default empty string object. Don't use this directly. Instead, call
0727 // GetEmptyString() to get the reference. This empty string is aligned with a
0728 // minimum alignment of 8 bytes to match the requirement of ArenaStringPtr.
0729 
0730 // Take advantage of C++20 constexpr support in std::string.
0731 class alignas(8) GlobalEmptyStringConstexpr {
0732  public:
0733   const std::string& get() const { return value_; }
0734   // Nothing to init, or destroy.
0735   std::string* Init() const { return nullptr; }
0736 
0737   // Disable the optimization for MSVC.
0738   // There are some builds where the default constructed string can't be used as
0739   // `constinit` even though the constructor is `constexpr` and can be used
0740   // during constant evaluation.
0741 #if !defined(_MSC_VER)
0742   template <typename T = std::string, bool = (T(), true)>
0743   static constexpr std::true_type HasConstexprDefaultConstructor(int) {
0744     return {};
0745   }
0746 #endif
0747   static constexpr std::false_type HasConstexprDefaultConstructor(char) {
0748     return {};
0749   }
0750 
0751  private:
0752   std::string value_;
0753 };
0754 
0755 class alignas(8) GlobalEmptyStringDynamicInit {
0756  public:
0757   const std::string& get() const {
0758     return *reinterpret_cast<const std::string*>(internal::Launder(buffer_));
0759   }
0760   std::string* Init() {
0761     return ::new (static_cast<void*>(buffer_)) std::string();
0762   }
0763 
0764  private:
0765   alignas(std::string) char buffer_[sizeof(std::string)];
0766 };
0767 
0768 using GlobalEmptyString = std::conditional_t<
0769     GlobalEmptyStringConstexpr::HasConstexprDefaultConstructor(0),
0770     const GlobalEmptyStringConstexpr, GlobalEmptyStringDynamicInit>;
0771 
0772 PROTOBUF_EXPORT extern GlobalEmptyString fixed_address_empty_string;
0773 
0774 enum class BoundsCheckMode { kNoEnforcement, kReturnDefault, kAbort };
0775 
0776 PROTOBUF_EXPORT constexpr BoundsCheckMode GetBoundsCheckMode() {
0777 #if defined(PROTOBUF_INTERNAL_BOUNDS_CHECK_MODE_ABORT)
0778   return BoundsCheckMode::kAbort;
0779 #elif defined(PROTOBUF_INTERNAL_BOUNDS_CHECK_MODE_RETURN_DEFAULT)
0780   return BoundsCheckMode::kReturnDefault;
0781 #else
0782   return BoundsCheckMode::kNoEnforcement;
0783 #endif
0784 }
0785 
0786 
0787 #if defined(__x86_64__) && defined(__SSE4_2__)
0788 
0789 constexpr bool HasCrc32() { return true; }
0790 inline uint32_t Crc32(uint32_t crc, uint64_t v) {
0791   return __builtin_ia32_crc32di(crc, v);
0792 }
0793 
0794 #elif defined(__ARM_FEATURE_CRC32)
0795 
0796 constexpr bool HasCrc32() { return true; }
0797 inline uint32_t Crc32(uint32_t crc, uint64_t v) {
0798   return __builtin_arm_crc32cd(crc, v);
0799 }
0800 
0801 #else
0802 
0803 constexpr bool HasCrc32() { return false; }
0804 inline uint32_t Crc32(uint32_t, uint64_t) { return 0; }
0805 
0806 #endif
0807 
0808 }  // namespace internal
0809 }  // namespace protobuf
0810 }  // namespace google
0811 
0812 #include "google/protobuf/port_undef.inc"
0813 
0814 #endif  // GOOGLE_PROTOBUF_PORT_H__