Skip to content

Commit

Permalink
Refactor the way we turn on the optimization in StrongPointer.
Browse files Browse the repository at this point in the history
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 protocolbuffers#16868

PiperOrigin-RevId: 634787159
  • Loading branch information
protobuf-github-bot authored and deannagarcia committed Jun 20, 2024
1 parent e5e71c2 commit 6a06647
Showing 1 changed file with 18 additions and 14 deletions.
32 changes: 18 additions & 14 deletions src/google/protobuf/port.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename T, T ptr>
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 <typename T>
inline PROTOBUF_ALWAYS_INLINE void StrongReferenceToType() {
constexpr auto ptr = T::template GetStrongPointerForType<T>();
#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<T>();
return StrongPointer<decltype(ptr), ptr>();
#else
return StrongPointer(ptr);
#endif
}
#else // .reloc
// Portable fallback. It usually generates a single LEA instruction or
// equivalent.
template <typename T, T ptr>
inline PROTOBUF_ALWAYS_INLINE void StrongPointer() {
StrongPointer(ptr);
}

template <typename T>
inline PROTOBUF_ALWAYS_INLINE void StrongReferenceToType() {
return StrongPointer(T::template GetStrongPointerForType<T>());
}
#endif // .reloc


// See comments on `AllocateAtLeast` for information on size returning new.
Expand Down

0 comments on commit 6a06647

Please sign in to comment.