From 5b8e90f4041e7e643aae47b8d1c1fb98e7250c6a Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Fri, 17 May 2024 08:36:07 -0700 Subject: [PATCH] Refactor the way we turn on the optimization in StrongPointer. Some versions of gcc seem to advertise __cpp_nontype_template_args but not support the argument in some cases. Only attempt the template parameter if we are using the optimized .reloc approach. Fixes https://github.com/protocolbuffers/protobuf/issues/16868 PiperOrigin-RevId: 634787159 --- src/google/protobuf/port.h | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/google/protobuf/port.h b/src/google/protobuf/port.h index a31722cd4d..6c4bb04f11 100644 --- a/src/google/protobuf/port.h +++ b/src/google/protobuf/port.h @@ -49,31 +49,35 @@ inline PROTOBUF_ALWAYS_INLINE void StrongPointer(T* var) { #endif } -// Similar to the overload above, but optimized for constant inputs. +#if defined(__x86_64__) && defined(__linux__) && !defined(__APPLE__) && \ + !defined(__ANDROID__) && defined(__clang__) && __clang_major__ >= 19 +// Optimized implementation for clang where we can generate a relocation without +// adding runtime instructions. template inline PROTOBUF_ALWAYS_INLINE void StrongPointer() { -#if defined(__x86_64__) && defined(__linux__) && !defined(__APPLE__) && \ - !defined(__ANDROID__) && defined(__clang__) && __clang_major__ >= 19 && \ - !defined(PROTOBUF_INTERNAL_TEMPORARY_STRONG_POINTER_OPT_OUT) // This injects a relocation in the code path without having to run code, but // we can only do it with a newer clang. asm(".reloc ., BFD_RELOC_NONE, %p0" ::"Ws"(ptr)); -#else - StrongPointer(ptr); -#endif } template inline PROTOBUF_ALWAYS_INLINE void StrongReferenceToType() { - constexpr auto ptr = T::template GetStrongPointerForType(); -#if defined(__cpp_nontype_template_args) && \ - __cpp_nontype_template_args >= 201411L - // We can only use `ptr` as a template parameter since C++17 + static constexpr auto ptr = T::template GetStrongPointerForType(); return StrongPointer(); -#else - return StrongPointer(ptr); -#endif } +#else // .reloc +// Portable fallback. It usually generates a single LEA instruction or +// equivalent. +template +inline PROTOBUF_ALWAYS_INLINE void StrongPointer() { + StrongPointer(ptr); +} + +template +inline PROTOBUF_ALWAYS_INLINE void StrongReferenceToType() { + return StrongPointer(T::template GetStrongPointerForType()); +} +#endif // .reloc // See comments on `AllocateAtLeast` for information on size returning new.