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 2 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
// #240
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
Arena*
GenericTypeHandler<Message>::GetArena(Message* value) {

@ -713,16 +713,6 @@ absl::Cord MessageLite::SerializePartialAsCord() const {
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
// various InternalMetadata routines.
template <>

@ -33,6 +33,15 @@ namespace protobuf {
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) {
ABSL_DCHECK(extend_amount > 0);
constexpr size_t kPtrSize = sizeof(rep()->elements[0]);

@ -89,6 +89,11 @@ struct ArenaOffsetHelper {
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.
template <typename Type>
class GenericTypeHandler;
@ -107,10 +112,8 @@ class GenericTypeHandler;
//
// static Type* New(Arena* arena);
// static Type* New(Arena* arena, Type&& value);
// static Type* NewFromPrototype(const Type* prototype, Arena* arena);
// static void Delete(Type*, Arena* arena);
// static void Clear(Type*);
// static void Merge(const Type& from, Type* to);
//
// // Only needs to be implemented if SpaceUsedExcludingSelf() is called.
// static int SpaceUsedLong(const Type&);
@ -331,10 +334,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
static inline Value<TypeHandler>* copy(const Value<TypeHandler>* value) {
using H = CommonHandler<TypeHandler>;
auto* new_value = H::NewFromPrototype(value, nullptr);
H::Merge(*value, new_value);
return cast<TypeHandler>(new_value);
return cast<TypeHandler>(CloneSlow(nullptr, *value));
}
// Used for constructing iterators.
@ -499,9 +499,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
my_arena->Own(value);
} else if (my_arena != value_arena) {
ABSL_DCHECK(value_arena != nullptr);
auto* new_value = TypeHandler::NewFromPrototype(value, my_arena);
H::Merge(*value, new_value);
value = new_value;
value = cast<TypeHandler>(CloneSlow(my_arena, *value));
}
UnsafeArenaAddAllocated<H>(value);
@ -824,10 +822,6 @@ class GenericTypeHandler {
static inline Type* New(Arena* arena, Type&& 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) {
if (arena != nullptr) return;
#ifdef __cpp_if_constexpr
@ -843,44 +837,20 @@ class GenericTypeHandler {
#endif
}
static inline void Clear(Type* value) { value->Clear(); }
static void Merge(const Type& from, Type* to);
static inline size_t SpaceUsedLong(const Type& value) {
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 <>
inline Arena* GenericTypeHandler<MessageLite>::GetArena(MessageLite* value) {
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
// to allow proto2-lite (which includes this header) to be independent of
// Message.
template <>
PROTOBUF_EXPORT Message* GenericTypeHandler<Message>::NewFromPrototype(
const Message* prototype, Arena* arena);
template <>
PROTOBUF_EXPORT Arena* GenericTypeHandler<Message>::GetArena(Message* value);
PROTOBUF_EXPORT void* NewStringElement(Arena* arena);
@ -899,9 +869,6 @@ class GenericTypeHandler<std::string> {
static PROTOBUF_NOINLINE Type* New(Arena* arena, Type&& 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) {
if (arena == nullptr) {
delete value;

Loading…
Cancel
Save