Refactor the code to consistently use the "base" implementation for copying

objects in the slow path. It reduces binary size.
Some calls already took care of doing so, but it is easy to miss.

Remove the now unused NewFromPrototype and Merge functions from the traits.

PiperOrigin-RevId: 683634339
pull/18593/head
Protobuf Team Bot 4 months ago committed by Copybara-Service
parent f7b0faf558
commit be9eb4bccf
  1. 11
      src/google/protobuf/message.cc
  2. 10
      src/google/protobuf/message_lite.cc
  3. 9
      src/google/protobuf/repeated_ptr_field.cc
  4. 47
      src/google/protobuf/repeated_ptr_field.h

@ -502,17 +502,6 @@ template <>
// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue // Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue
// #240 // #240
PROTOBUF_NOINLINE PROTOBUF_NOINLINE
#endif
Message*
GenericTypeHandler<Message>::NewFromPrototype(const Message* prototype,
Arena* arena) {
return prototype->New(arena);
}
template <>
#if defined(_MSC_VER) && (_MSC_VER >= 1800)
// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue
// #240
PROTOBUF_NOINLINE
#endif #endif
Arena* Arena*
GenericTypeHandler<Message>::GetArena(Message* value) { GenericTypeHandler<Message>::GetArena(Message* value) {

@ -713,16 +713,6 @@ absl::Cord MessageLite::SerializePartialAsCord() const {
namespace internal { namespace internal {
MessageLite* NewFromPrototypeHelper(const MessageLite* prototype,
Arena* arena) {
return prototype->New(arena);
}
template <>
void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
MessageLite* to) {
to->CheckTypeAndMergeFrom(from);
}
// Non-inline variants of std::string specializations for // Non-inline variants of std::string specializations for
// various InternalMetadata routines. // various InternalMetadata routines.
template <> template <>

@ -33,6 +33,15 @@ namespace protobuf {
namespace internal { namespace internal {
MessageLite* CloneSlow(Arena* arena, const MessageLite& value) {
auto* msg = value.New(arena);
msg->CheckTypeAndMergeFrom(value);
return msg;
}
std::string* CloneSlow(Arena* arena, const std::string& value) {
return Arena::Create<std::string>(arena, value);
}
void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) {
ABSL_DCHECK(extend_amount > 0); ABSL_DCHECK(extend_amount > 0);
constexpr size_t kPtrSize = sizeof(rep()->elements[0]); constexpr size_t kPtrSize = sizeof(rep()->elements[0]);

@ -89,6 +89,11 @@ struct ArenaOffsetHelper {
static constexpr size_t value = offsetof(T, arena_); static constexpr size_t value = offsetof(T, arena_);
}; };
// Copies the object in the arena.
// Used in the slow path. Out-of-line for lower binary size cost.
PROTOBUF_EXPORT MessageLite* CloneSlow(Arena* arena, const MessageLite& value);
PROTOBUF_EXPORT std::string* CloneSlow(Arena* arena, const std::string& value);
// Defined further below. // Defined further below.
template <typename Type> template <typename Type>
class GenericTypeHandler; class GenericTypeHandler;
@ -107,10 +112,8 @@ class GenericTypeHandler;
// //
// static Type* New(Arena* arena); // static Type* New(Arena* arena);
// static Type* New(Arena* arena, Type&& value); // static Type* New(Arena* arena, Type&& value);
// static Type* NewFromPrototype(const Type* prototype, Arena* arena);
// static void Delete(Type*, Arena* arena); // static void Delete(Type*, Arena* arena);
// static void Clear(Type*); // static void Clear(Type*);
// static void Merge(const Type& from, Type* to);
// //
// // Only needs to be implemented if SpaceUsedExcludingSelf() is called. // // Only needs to be implemented if SpaceUsedExcludingSelf() is called.
// static int SpaceUsedLong(const Type&); // static int SpaceUsedLong(const Type&);
@ -331,10 +334,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler> template <typename TypeHandler>
static inline Value<TypeHandler>* copy(const Value<TypeHandler>* value) { static inline Value<TypeHandler>* copy(const Value<TypeHandler>* value) {
using H = CommonHandler<TypeHandler>; return cast<TypeHandler>(CloneSlow(nullptr, *value));
auto* new_value = H::NewFromPrototype(value, nullptr);
H::Merge(*value, new_value);
return cast<TypeHandler>(new_value);
} }
// Used for constructing iterators. // Used for constructing iterators.
@ -499,9 +499,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
my_arena->Own(value); my_arena->Own(value);
} else if (my_arena != value_arena) { } else if (my_arena != value_arena) {
ABSL_DCHECK(value_arena != nullptr); ABSL_DCHECK(value_arena != nullptr);
auto* new_value = TypeHandler::NewFromPrototype(value, my_arena); value = cast<TypeHandler>(CloneSlow(my_arena, *value));
H::Merge(*value, new_value);
value = new_value;
} }
UnsafeArenaAddAllocated<H>(value); UnsafeArenaAddAllocated<H>(value);
@ -824,10 +822,6 @@ class GenericTypeHandler {
static inline Type* New(Arena* arena, Type&& value) { static inline Type* New(Arena* arena, Type&& value) {
return Arena::Create<Type>(arena, std::move(value)); return Arena::Create<Type>(arena, std::move(value));
} }
static inline Type* NewFromPrototype(const Type* /*prototype*/,
Arena* arena = nullptr) {
return New(arena);
}
static inline void Delete(Type* value, Arena* arena) { static inline void Delete(Type* value, Arena* arena) {
if (arena != nullptr) return; if (arena != nullptr) return;
#ifdef __cpp_if_constexpr #ifdef __cpp_if_constexpr
@ -843,44 +837,20 @@ class GenericTypeHandler {
#endif #endif
} }
static inline void Clear(Type* value) { value->Clear(); } static inline void Clear(Type* value) { value->Clear(); }
static void Merge(const Type& from, Type* to);
static inline size_t SpaceUsedLong(const Type& value) { static inline size_t SpaceUsedLong(const Type& value) {
return value.SpaceUsedLong(); return value.SpaceUsedLong();
} }
}; };
// NewFromPrototypeHelper() is not defined inline here, as we will need to do a
// virtual function dispatch anyways to go from Message* to call New/Merge. (The
// additional helper is needed as a workaround for MSVC.)
PROTOBUF_EXPORT MessageLite* NewFromPrototypeHelper(
const MessageLite* prototype, Arena* arena);
template <>
inline MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
const MessageLite* prototype, Arena* arena) {
return NewFromPrototypeHelper(prototype, arena);
}
template <> template <>
inline Arena* GenericTypeHandler<MessageLite>::GetArena(MessageLite* value) { inline Arena* GenericTypeHandler<MessageLite>::GetArena(MessageLite* value) {
return value->GetArena(); return value->GetArena();
} }
template <typename GenericType>
PROTOBUF_NOINLINE inline void GenericTypeHandler<GenericType>::Merge(
const GenericType& from, GenericType* to) {
to->MergeFrom(from);
}
template <>
PROTOBUF_EXPORT void GenericTypeHandler<MessageLite>::Merge(
const MessageLite& from, MessageLite* to);
// Message specialization bodies defined in message.cc. This split is necessary // Message specialization bodies defined in message.cc. This split is necessary
// to allow proto2-lite (which includes this header) to be independent of // to allow proto2-lite (which includes this header) to be independent of
// Message. // Message.
template <> template <>
PROTOBUF_EXPORT Message* GenericTypeHandler<Message>::NewFromPrototype(
const Message* prototype, Arena* arena);
template <>
PROTOBUF_EXPORT Arena* GenericTypeHandler<Message>::GetArena(Message* value); PROTOBUF_EXPORT Arena* GenericTypeHandler<Message>::GetArena(Message* value);
PROTOBUF_EXPORT void* NewStringElement(Arena* arena); PROTOBUF_EXPORT void* NewStringElement(Arena* arena);
@ -899,9 +869,6 @@ class GenericTypeHandler<std::string> {
static PROTOBUF_NOINLINE Type* New(Arena* arena, Type&& value) { static PROTOBUF_NOINLINE Type* New(Arena* arena, Type&& value) {
return Arena::Create<Type>(arena, std::move(value)); return Arena::Create<Type>(arena, std::move(value));
} }
static inline Type* NewFromPrototype(const Type*, Arena* arena) {
return New(arena);
}
static inline void Delete(Type* value, Arena* arena) { static inline void Delete(Type* value, Arena* arena) {
if (arena == nullptr) { if (arena == nullptr) {
delete value; delete value;

Loading…
Cancel
Save