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 #16868

PiperOrigin-RevId: 634787159
  • Loading branch information
protobuf-github-bot authored and copybara-github committed May 17, 2024
1 parent 2f3242c commit 5b8e90f
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 5b8e90f

Please sign in to comment.