Dedup `RepeatedPtrField::Add` methods to all use common implementation.

As a result, `AddMessage` get the same perf boost as main `Add` method from 1df8ea4.

PiperOrigin-RevId: 579201689
pull/14579/head
Protobuf Team Bot 1 year ago committed by Copybara-Service
parent b0d4b2c1fe
commit a3e45d27ee
  1. 9
      src/google/protobuf/generated_message_tctable_lite.cc
  2. 23
      src/google/protobuf/repeated_ptr_field.cc
  3. 33
      src/google/protobuf/repeated_ptr_field.h

@ -470,8 +470,7 @@ inline PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedParseMessageAuxImpl(
aux_is_table ? aux.table->default_instance : aux.message_default();
do {
ptr += sizeof(TagType);
MessageLite* submsg =
field.Add<GenericTypeHandler<MessageLite>>(default_instance);
MessageLite* submsg = field.AddMessage(default_instance);
if (aux_is_table) {
if (group_coding) {
ptr = ctx->ParseGroup<TcParser>(submsg, ptr,
@ -2426,8 +2425,7 @@ const char* TcParser::MpRepeatedMessageOrGroup(PROTOBUF_TC_PARAM_DECL) {
const char* ptr2 = ptr;
uint32_t next_tag;
do {
MessageLite* value =
field.template Add<GenericTypeHandler<MessageLite>>(default_instance);
MessageLite* value = field.AddMessage(default_instance);
ptr = is_group ? ctx->ParseGroup<TcParser>(value, ptr2, decoded_tag,
inner_table)
: ctx->ParseMessage<TcParser>(value, ptr2, inner_table);
@ -2448,8 +2446,7 @@ const char* TcParser::MpRepeatedMessageOrGroup(PROTOBUF_TC_PARAM_DECL) {
const char* ptr2 = ptr;
uint32_t next_tag;
do {
MessageLite* value =
field.template Add<GenericTypeHandler<MessageLite>>(default_instance);
MessageLite* value = field.AddMessage(default_instance);
ptr = is_group ? ctx->ParseGroup(value, ptr2, decoded_tag)
: ctx->ParseMessage(value, ptr2);
if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) goto error;

@ -126,14 +126,18 @@ void* RepeatedPtrFieldBase::AddOutOfLineHelper(void* obj) {
return r->elements[ExchangeCurrentSize(current_size_ + 1)] = obj;
}
void* RepeatedPtrFieldBase::AddOutOfLineHelper(ElementFactory factory) {
template <typename F>
auto* RepeatedPtrFieldBase::AddInternal(F factory) {
using Result = decltype(factory(GetArena()));
if (tagged_rep_or_elem_ == nullptr) {
ExchangeCurrentSize(1);
tagged_rep_or_elem_ = factory(GetArena());
return tagged_rep_or_elem_;
return static_cast<Result>(tagged_rep_or_elem_);
}
if (using_sso()) {
if (ExchangeCurrentSize(1) == 0) return tagged_rep_or_elem_;
if (ExchangeCurrentSize(1) == 0) {
return static_cast<Result>(tagged_rep_or_elem_);
}
} else {
absl::PrefetchToLocalCache(rep());
}
@ -142,14 +146,19 @@ void* RepeatedPtrFieldBase::AddOutOfLineHelper(ElementFactory factory) {
} else {
Rep* r = rep();
if (current_size_ != r->allocated_size) {
return r->elements[ExchangeCurrentSize(current_size_ + 1)];
return static_cast<Result>(
r->elements[ExchangeCurrentSize(current_size_ + 1)]);
}
}
Rep* r = rep();
++r->allocated_size;
void*& result = r->elements[ExchangeCurrentSize(current_size_ + 1)];
result = factory(GetArena());
return result;
return static_cast<Result>(result);
}
void* RepeatedPtrFieldBase::AddOutOfLineHelper(ElementFactory factory) {
return AddInternal(factory);
}
void RepeatedPtrFieldBase::CloseGap(int start, int num) {
@ -167,6 +176,10 @@ void RepeatedPtrFieldBase::CloseGap(int start, int num) {
ExchangeCurrentSize(current_size_ - num);
}
MessageLite* RepeatedPtrFieldBase::AddMessage(const MessageLite* prototype) {
return AddInternal([prototype](Arena* a) { return prototype->New(a); });
}
MessageLite* RepeatedPtrFieldBase::AddWeak(const MessageLite* prototype) {
if (current_size_ < allocated_size()) {
return reinterpret_cast<MessageLite*>(

@ -232,16 +232,6 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
return cast<Handler>(AddOutOfLineHelper(NewT<Value<Handler>>));
}
template <typename TypeHandler>
Value<TypeHandler>* Add(const Value<TypeHandler>* prototype) {
if (current_size_ < allocated_size()) {
return cast<TypeHandler>(
element_at(ExchangeCurrentSize(current_size_ + 1)));
}
auto* result = TypeHandler::NewFromPrototype(prototype, arena_);
return cast<TypeHandler>(AddOutOfLineHelper(result));
}
template <
typename TypeHandler,
typename std::enable_if<TypeHandler::Movable::value>::type* = nullptr>
@ -299,9 +289,14 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
}
// Creates and adds an element using the given prototype, without introducing
// a link-time dependency on the concrete message type. This method is used to
// implement implicit weak fields. The prototype may be nullptr, in which case
// an ImplicitWeakMessage will be used as a placeholder.
// a link-time dependency on the concrete message type.
//
// Pre-condition: prototype must not be nullptr.
MessageLite* AddMessage(const MessageLite* prototype);
// This method is similar to `AddMessage` except that prototype may be nullptr
// in which case an ImplicitWeakMessage will be used as a placeholder. It is
// used to implement implicit weak fields.
MessageLite* AddWeak(const MessageLite* prototype);
template <typename TypeHandler>
@ -847,8 +842,20 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
// array, including potentially resizing the array with Reserve if
// needed
void* AddOutOfLineHelper(void* obj);
// Internal helper for Add that keeps definition out-of-line.
void* AddOutOfLineHelper(ElementFactory factory);
// Common implementation used by various Add* methods. `factory` is an object
// used to construct a new element unless there are spare cleared elements
// ready for reuse. Returns pointer to the new element.
//
// Note: avoid inlining this function in methods such as `Add()` as this would
// drastically increase binary size due to template instantiation and implicit
// inlining. Instead, use wrapper functions with out-of-line definition
// similar to `AddOutOfLineHelper`.
template <typename F>
auto* AddInternal(F factory);
// A few notes on internal representation:
//
// We use an indirected approach, with struct Rep, to keep

Loading…
Cancel
Save