Avoid calling GetArena() multiple times.

PiperOrigin-RevId: 583188151
pull/14784/head
Protobuf Team Bot 1 year ago committed by Copybara-Service
parent 838d9b7c7f
commit b0d7441f83
  1. 15
      src/google/protobuf/compiler/cpp/field_generators/cord_field.cc
  2. 19
      src/google/protobuf/dynamic_message.cc
  3. 88
      src/google/protobuf/extension_set.cc
  4. 81
      src/google/protobuf/generated_message_reflection.cc
  5. 7
      src/google/protobuf/repeated_ptr_field.cc

@ -352,8 +352,9 @@ void CordOneofFieldGenerator::GenerateInlineAccessorDefinitions(
clear_$oneof_name$(); clear_$oneof_name$();
set_has_$name$(); set_has_$name$();
$field$ = new ::absl::Cord; $field$ = new ::absl::Cord;
if (GetArena() != nullptr) { ::$proto_ns$::Arena* arena = GetArena();
GetArena()->Own($field$); if (arena != nullptr) {
arena->Own($field$);
} }
} }
*$field$ = value; *$field$ = value;
@ -372,8 +373,9 @@ void CordOneofFieldGenerator::GenerateInlineAccessorDefinitions(
clear_$oneof_name$(); clear_$oneof_name$();
set_has_$name$(); set_has_$name$();
$field$ = new ::absl::Cord; $field$ = new ::absl::Cord;
if (GetArena() != nullptr) { ::$proto_ns$::Arena* arena = GetArena();
GetArena()->Own($field$); if (arena != nullptr) {
arena->Own($field$);
} }
} }
*$field$ = value; *$field$ = value;
@ -387,8 +389,9 @@ void CordOneofFieldGenerator::GenerateInlineAccessorDefinitions(
clear_$oneof_name$(); clear_$oneof_name$();
set_has_$name$(); set_has_$name$();
$field$ = new ::absl::Cord; $field$ = new ::absl::Cord;
if (GetArena() != nullptr) { ::$proto_ns$::Arena* arena = GetArena();
GetArena()->Own($field$); if (arena != nullptr) {
arena->Own($field$);
} }
} }
return $field$; return $field$;

@ -351,6 +351,7 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
// constructor.) // constructor.)
const Descriptor* descriptor = type_info_->type; const Descriptor* descriptor = type_info_->type;
Arena* arena = GetArena();
// Initialize oneof cases. // Initialize oneof cases.
int oneof_count = 0; int oneof_count = 0;
for (int i = 0; i < descriptor->oneof_decl_count(); ++i) { for (int i = 0; i < descriptor->oneof_decl_count(); ++i) {
@ -360,7 +361,7 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
} }
if (type_info_->extensions_offset != -1) { if (type_info_->extensions_offset != -1) {
new (MutableExtensionsRaw()) ExtensionSet(GetArena()); new (MutableExtensionsRaw()) ExtensionSet(arena);
} }
for (int i = 0; i < descriptor->field_count(); i++) { for (int i = 0; i < descriptor->field_count(); i++) {
const FieldDescriptor* field = descriptor->field(i); const FieldDescriptor* field = descriptor->field(i);
@ -374,7 +375,7 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
if (!field->is_repeated()) { \ if (!field->is_repeated()) { \
new (field_ptr) TYPE(field->default_value_##TYPE()); \ new (field_ptr) TYPE(field->default_value_##TYPE()); \
} else { \ } else { \
new (field_ptr) RepeatedField<TYPE>(GetArena()); \ new (field_ptr) RepeatedField<TYPE>(arena); \
} \ } \
break; break;
@ -391,7 +392,7 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
if (!field->is_repeated()) { if (!field->is_repeated()) {
new (field_ptr) int{field->default_value_enum()->number()}; new (field_ptr) int{field->default_value_enum()->number()};
} else { } else {
new (field_ptr) RepeatedField<int>(GetArena()); new (field_ptr) RepeatedField<int>(arena);
} }
break; break;
@ -403,7 +404,7 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr(); ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
asp->InitDefault(); asp->InitDefault();
} else { } else {
new (field_ptr) RepeatedPtrField<std::string>(GetArena()); new (field_ptr) RepeatedPtrField<std::string>(arena);
} }
break; break;
} }
@ -418,20 +419,20 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
// when the constructor is called inside GetPrototype(), in which // when the constructor is called inside GetPrototype(), in which
// case we have already locked the factory. // case we have already locked the factory.
if (lock_factory) { if (lock_factory) {
if (GetArena() != nullptr) { if (arena != nullptr) {
new (field_ptr) DynamicMapField( new (field_ptr) DynamicMapField(
type_info_->factory->GetPrototype(field->message_type()), type_info_->factory->GetPrototype(field->message_type()),
GetArena()); arena);
} else { } else {
new (field_ptr) DynamicMapField( new (field_ptr) DynamicMapField(
type_info_->factory->GetPrototype(field->message_type())); type_info_->factory->GetPrototype(field->message_type()));
} }
} else { } else {
if (GetArena() != nullptr) { if (arena != nullptr) {
new (field_ptr) new (field_ptr)
DynamicMapField(type_info_->factory->GetPrototypeNoLock( DynamicMapField(type_info_->factory->GetPrototypeNoLock(
field->message_type()), field->message_type()),
GetArena()); arena);
} else { } else {
new (field_ptr) new (field_ptr)
DynamicMapField(type_info_->factory->GetPrototypeNoLock( DynamicMapField(type_info_->factory->GetPrototypeNoLock(
@ -439,7 +440,7 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
} }
} }
} else { } else {
new (field_ptr) RepeatedPtrField<Message>(GetArena()); new (field_ptr) RepeatedPtrField<Message>(arena);
} }
} }
break; break;

@ -630,38 +630,40 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
ClearExtension(number); ClearExtension(number);
return; return;
} }
ABSL_DCHECK(message->GetArena() == nullptr || message->GetArena() == arena_); Arena* const arena = arena_;
Arena* message_arena = message->GetArena(); Arena* const message_arena = message->GetArena();
ABSL_DCHECK(message_arena == nullptr || message_arena == arena);
Extension* extension; Extension* extension;
if (MaybeNewExtension(number, descriptor, &extension)) { if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type; extension->type = type;
ABSL_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); ABSL_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
extension->is_repeated = false; extension->is_repeated = false;
extension->is_lazy = false; extension->is_lazy = false;
if (message_arena == arena_) { if (message_arena == arena) {
extension->message_value = message; extension->message_value = message;
} else if (message_arena == nullptr) { } else if (message_arena == nullptr) {
extension->message_value = message; extension->message_value = message;
arena_->Own(message); // not nullptr because not equal to message_arena arena->Own(message); // not nullptr because not equal to message_arena
} else { } else {
extension->message_value = message->New(arena_); extension->message_value = message->New(arena);
extension->message_value->CheckTypeAndMergeFrom(*message); extension->message_value->CheckTypeAndMergeFrom(*message);
} }
} else { } else {
ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE);
if (extension->is_lazy) { if (extension->is_lazy) {
extension->lazymessage_value->SetAllocatedMessage(message, arena_); extension->lazymessage_value->SetAllocatedMessage(message, arena);
} else { } else {
if (arena_ == nullptr) { if (arena == nullptr) {
delete extension->message_value; delete extension->message_value;
} }
if (message_arena == arena_) { if (message_arena == arena) {
extension->message_value = message; extension->message_value = message;
} else if (message_arena == nullptr) { } else if (message_arena == nullptr) {
extension->message_value = message; extension->message_value = message;
arena_->Own(message); // not nullptr because not equal to message_arena arena->Own(message); // not nullptr because not equal to message_arena
} else { } else {
extension->message_value = message->New(arena_); extension->message_value = message->New(arena);
extension->message_value->CheckTypeAndMergeFrom(*message); extension->message_value->CheckTypeAndMergeFrom(*message);
} }
} }
@ -708,8 +710,9 @@ MessageLite* ExtensionSet::ReleaseMessage(int number,
ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE);
MessageLite* ret = nullptr; MessageLite* ret = nullptr;
if (extension->is_lazy) { if (extension->is_lazy) {
ret = extension->lazymessage_value->ReleaseMessage(prototype, arena_); Arena* const arena = arena_;
if (arena_ == nullptr) { ret = extension->lazymessage_value->ReleaseMessage(prototype, arena);
if (arena == nullptr) {
delete extension->lazymessage_value; delete extension->lazymessage_value;
} }
} else { } else {
@ -737,9 +740,10 @@ MessageLite* ExtensionSet::UnsafeArenaReleaseMessage(
ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE); ABSL_DCHECK_TYPE(*extension, OPTIONAL_FIELD, MESSAGE);
MessageLite* ret = nullptr; MessageLite* ret = nullptr;
if (extension->is_lazy) { if (extension->is_lazy) {
Arena* const arena = arena_;
ret = extension->lazymessage_value->UnsafeArenaReleaseMessage(prototype, ret = extension->lazymessage_value->UnsafeArenaReleaseMessage(prototype,
arena_); arena);
if (arena_ == nullptr) { if (arena == nullptr) {
delete extension->lazymessage_value; delete extension->lazymessage_value;
} }
} else { } else {
@ -994,10 +998,11 @@ void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee,
HANDLE_TYPE(STRING, string, RepeatedPtrField<std::string>); HANDLE_TYPE(STRING, string, RepeatedPtrField<std::string>);
#undef HANDLE_TYPE #undef HANDLE_TYPE
case WireFormatLite::CPPTYPE_MESSAGE: case WireFormatLite::CPPTYPE_MESSAGE: {
Arena* const arena = arena_;
if (is_new) { if (is_new) {
extension->repeated_message_value = extension->repeated_message_value =
Arena::CreateMessage<RepeatedPtrField<MessageLite>>(arena_); Arena::CreateMessage<RepeatedPtrField<MessageLite>>(arena);
} }
// We can't call RepeatedPtrField<MessageLite>::MergeFrom() because // We can't call RepeatedPtrField<MessageLite>::MergeFrom() because
// it would attempt to allocate new objects. // it would attempt to allocate new objects.
@ -1010,12 +1015,13 @@ void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee,
extension->repeated_message_value) extension->repeated_message_value)
->AddFromCleared<GenericTypeHandler<MessageLite>>(); ->AddFromCleared<GenericTypeHandler<MessageLite>>();
if (target == nullptr) { if (target == nullptr) {
target = other_message.New(arena_); target = other_message.New(arena);
extension->repeated_message_value->AddAllocated(target); extension->repeated_message_value->AddAllocated(target);
} }
target->CheckTypeAndMergeFrom(other_message); target->CheckTypeAndMergeFrom(other_message);
} }
break; break;
}
} }
} else { } else {
if (!other_extension.is_cleared) { if (!other_extension.is_cleared) {
@ -1041,6 +1047,7 @@ void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee,
other_extension.descriptor); other_extension.descriptor);
break; break;
case WireFormatLite::CPPTYPE_MESSAGE: { case WireFormatLite::CPPTYPE_MESSAGE: {
Arena* const arena = arena_;
Extension* extension; Extension* extension;
bool is_new = bool is_new =
MaybeNewExtension(number, other_extension.descriptor, &extension); MaybeNewExtension(number, other_extension.descriptor, &extension);
@ -1051,14 +1058,14 @@ void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee,
if (other_extension.is_lazy) { if (other_extension.is_lazy) {
extension->is_lazy = true; extension->is_lazy = true;
extension->lazymessage_value = extension->lazymessage_value =
other_extension.lazymessage_value->New(arena_); other_extension.lazymessage_value->New(arena);
extension->lazymessage_value->MergeFrom( extension->lazymessage_value->MergeFrom(
GetPrototypeForLazyMessage(extendee, number), GetPrototypeForLazyMessage(extendee, number),
*other_extension.lazymessage_value, arena_); *other_extension.lazymessage_value, arena);
} else { } else {
extension->is_lazy = false; extension->is_lazy = false;
extension->message_value = extension->message_value =
other_extension.message_value->New(arena_); other_extension.message_value->New(arena);
extension->message_value->CheckTypeAndMergeFrom( extension->message_value->CheckTypeAndMergeFrom(
*other_extension.message_value); *other_extension.message_value);
} }
@ -1070,7 +1077,7 @@ void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee,
if (extension->is_lazy) { if (extension->is_lazy) {
extension->lazymessage_value->MergeFrom( extension->lazymessage_value->MergeFrom(
GetPrototypeForLazyMessage(extendee, number), GetPrototypeForLazyMessage(extendee, number),
*other_extension.lazymessage_value, arena_); *other_extension.lazymessage_value, arena);
} else { } else {
extension->message_value->CheckTypeAndMergeFrom( extension->message_value->CheckTypeAndMergeFrom(
other_extension.lazymessage_value->GetMessage( other_extension.lazymessage_value->GetMessage(
@ -1079,7 +1086,7 @@ void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee,
} else { } else {
if (extension->is_lazy) { if (extension->is_lazy) {
extension->lazymessage_value extension->lazymessage_value
->MutableMessage(*other_extension.message_value, arena_) ->MutableMessage(*other_extension.message_value, arena)
->CheckTypeAndMergeFrom(*other_extension.message_value); ->CheckTypeAndMergeFrom(*other_extension.message_value);
} else { } else {
extension->message_value->CheckTypeAndMergeFrom( extension->message_value->CheckTypeAndMergeFrom(
@ -1097,9 +1104,9 @@ void ExtensionSet::InternalExtensionMergeFrom(const MessageLite* extendee,
void ExtensionSet::Swap(const MessageLite* extendee, ExtensionSet* other) { void ExtensionSet::Swap(const MessageLite* extendee, ExtensionSet* other) {
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() != nullptr && GetArena() == other->GetArena()) { if (arena_ != nullptr && arena_ == other->arena_) {
#else // PROTOBUF_FORCE_COPY_IN_SWAP #else // PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() == other->GetArena()) { if (arena_ == other->arena_) {
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP #endif // !PROTOBUF_FORCE_COPY_IN_SWAP
InternalSwap(other); InternalSwap(other);
} else { } else {
@ -1127,7 +1134,9 @@ void ExtensionSet::SwapExtension(const MessageLite* extendee,
ExtensionSet* other, int number) { ExtensionSet* other, int number) {
if (this == other) return; if (this == other) return;
if (GetArena() == other->GetArena()) { Arena* const arena = arena_;
Arena* const other_arena = other->arena_;
if (arena == other_arena) {
UnsafeShallowSwapExtension(other, number); UnsafeShallowSwapExtension(other, number);
return; return;
} }
@ -1144,23 +1153,20 @@ void ExtensionSet::SwapExtension(const MessageLite* extendee,
// We do it this way to reuse the copy-across-arenas logic already // We do it this way to reuse the copy-across-arenas logic already
// implemented in ExtensionSet's MergeFrom. // implemented in ExtensionSet's MergeFrom.
ExtensionSet temp; ExtensionSet temp;
temp.InternalExtensionMergeFrom(extendee, number, *other_ext, temp.InternalExtensionMergeFrom(extendee, number, *other_ext, other_arena);
other->GetArena());
Extension* temp_ext = temp.FindOrNull(number); Extension* temp_ext = temp.FindOrNull(number);
other_ext->Clear(); other_ext->Clear();
other->InternalExtensionMergeFrom(extendee, number, *this_ext, other->InternalExtensionMergeFrom(extendee, number, *this_ext, arena);
this->GetArena());
this_ext->Clear(); this_ext->Clear();
InternalExtensionMergeFrom(extendee, number, *temp_ext, temp.GetArena()); InternalExtensionMergeFrom(extendee, number, *temp_ext, temp.GetArena());
} else if (this_ext == nullptr) { } else if (this_ext == nullptr) {
InternalExtensionMergeFrom(extendee, number, *other_ext, other->GetArena()); InternalExtensionMergeFrom(extendee, number, *other_ext, other_arena);
if (other->GetArena() == nullptr) other_ext->Free(); if (other_arena == nullptr) other_ext->Free();
other->Erase(number); other->Erase(number);
} else { } else {
other->InternalExtensionMergeFrom(extendee, number, *this_ext, other->InternalExtensionMergeFrom(extendee, number, *this_ext, arena);
this->GetArena()); if (arena == nullptr) this_ext->Free();
if (GetArena() == nullptr) this_ext->Free();
Erase(number); Erase(number);
} }
} }
@ -1173,7 +1179,7 @@ void ExtensionSet::UnsafeShallowSwapExtension(ExtensionSet* other, int number) {
if (this_ext == other_ext) return; if (this_ext == other_ext) return;
ABSL_DCHECK_EQ(GetArena(), other->GetArena()); ABSL_DCHECK_EQ(arena_, other->arena_);
if (this_ext != nullptr && other_ext != nullptr) { if (this_ext != nullptr && other_ext != nullptr) {
std::swap(*this_ext, *other_ext); std::swap(*this_ext, *other_ext);
@ -1189,16 +1195,17 @@ void ExtensionSet::UnsafeShallowSwapExtension(ExtensionSet* other, int number) {
bool ExtensionSet::IsInitialized(const MessageLite* extendee) const { bool ExtensionSet::IsInitialized(const MessageLite* extendee) const {
// Extensions are never required. However, we need to check that all // Extensions are never required. However, we need to check that all
// embedded messages are initialized. // embedded messages are initialized.
Arena* const arena = arena_;
if (PROTOBUF_PREDICT_FALSE(is_large())) { if (PROTOBUF_PREDICT_FALSE(is_large())) {
for (const auto& kv : *map_.large) { for (const auto& kv : *map_.large) {
if (!kv.second.IsInitialized(this, extendee, kv.first, arena_)) { if (!kv.second.IsInitialized(this, extendee, kv.first, arena)) {
return false; return false;
} }
} }
return true; return true;
} }
for (const KeyValue* it = flat_begin(); it != flat_end(); ++it) { for (const KeyValue* it = flat_begin(); it != flat_end(); ++it) {
if (!it->second.IsInitialized(this, extendee, it->first, arena_)) { if (!it->second.IsInitialized(this, extendee, it->first, arena)) {
return false; return false;
} }
} }
@ -1639,8 +1646,9 @@ void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) {
const KeyValue* begin = flat_begin(); const KeyValue* begin = flat_begin();
const KeyValue* end = flat_end(); const KeyValue* end = flat_end();
AllocatedData new_map; AllocatedData new_map;
Arena* const arena = arena_;
if (new_flat_capacity > kMaximumFlatCapacity) { if (new_flat_capacity > kMaximumFlatCapacity) {
new_map.large = Arena::Create<LargeMap>(arena_); new_map.large = Arena::Create<LargeMap>(arena);
LargeMap::iterator hint = new_map.large->begin(); LargeMap::iterator hint = new_map.large->begin();
for (const KeyValue* it = begin; it != end; ++it) { for (const KeyValue* it = begin; it != end; ++it) {
hint = new_map.large->insert(hint, {it->first, it->second}); hint = new_map.large->insert(hint, {it->first, it->second});
@ -1648,11 +1656,11 @@ void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) {
flat_size_ = static_cast<uint16_t>(-1); flat_size_ = static_cast<uint16_t>(-1);
ABSL_DCHECK(is_large()); ABSL_DCHECK(is_large());
} else { } else {
new_map.flat = Arena::CreateArray<KeyValue>(arena_, new_flat_capacity); new_map.flat = Arena::CreateArray<KeyValue>(arena, new_flat_capacity);
std::copy(begin, end, new_map.flat); std::copy(begin, end, new_map.flat);
} }
if (arena_ == nullptr) { if (arena == nullptr) {
DeleteFlatMap(begin, flat_capacity_); DeleteFlatMap(begin, flat_capacity_);
} }
flat_capacity_ = new_flat_capacity; flat_capacity_ = new_flat_capacity;

@ -1044,21 +1044,24 @@ void Reflection::SwapOneofField(Message* lhs, Message* rhs,
} }
} }
void Reflection::Swap(Message* message1, Message* message2) const { void Reflection::Swap(Message* lhs, Message* rhs) const {
if (message1 == message2) return; if (lhs == rhs) return;
Arena* lhs_arena = lhs->GetArena();
Arena* rhs_arena = rhs->GetArena();
// TODO: Other Reflection methods should probably check this too. // TODO: Other Reflection methods should probably check this too.
ABSL_CHECK_EQ(message1->GetReflection(), this) ABSL_CHECK_EQ(lhs->GetReflection(), this)
<< "First argument to Swap() (of type \"" << "First argument to Swap() (of type \""
<< message1->GetDescriptor()->full_name() << lhs->GetDescriptor()->full_name()
<< "\") is not compatible with this reflection object (which is for type " << "\") is not compatible with this reflection object (which is for type "
"\"" "\""
<< descriptor_->full_name() << descriptor_->full_name()
<< "\"). Note that the exact same class is required; not just the same " << "\"). Note that the exact same class is required; not just the same "
"descriptor."; "descriptor.";
ABSL_CHECK_EQ(message2->GetReflection(), this) ABSL_CHECK_EQ(rhs->GetReflection(), this)
<< "Second argument to Swap() (of type \"" << "Second argument to Swap() (of type \""
<< message2->GetDescriptor()->full_name() << rhs->GetDescriptor()->full_name()
<< "\") is not compatible with this reflection object (which is for type " << "\") is not compatible with this reflection object (which is for type "
"\"" "\""
<< descriptor_->full_name() << descriptor_->full_name()
@ -1068,32 +1071,31 @@ void Reflection::Swap(Message* message1, Message* message2) const {
// Check that both messages are in the same arena (or both on the heap). We // Check that both messages are in the same arena (or both on the heap). We
// need to copy all data if not, due to ownership semantics. // need to copy all data if not, due to ownership semantics.
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
if (message1->GetArena() == nullptr || if (lhs_arena == nullptr || lhs_arena != rhs_arena) {
message1->GetArena() != message2->GetArena()) {
#else // PROTOBUF_FORCE_COPY_IN_SWAP #else // PROTOBUF_FORCE_COPY_IN_SWAP
if (message1->GetArena() != message2->GetArena()) { if (lhs_arena != rhs_arena) {
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP #endif // !PROTOBUF_FORCE_COPY_IN_SWAP
// One of the two is guaranteed to have an arena. Switch things around // One of the two is guaranteed to have an arena. Switch things around
// to guarantee that message1 has an arena. // to guarantee that lhs has an arena.
Arena* arena = message1->GetArena(); Arena* arena = lhs_arena;
if (arena == nullptr) { if (arena == nullptr) {
arena = message2->GetArena(); arena = rhs_arena;
std::swap(message1, message2); // Swapping names for pointers! std::swap(lhs, rhs); // Swapping names for pointers!
} }
Message* temp = message1->New(arena); Message* temp = lhs->New(arena);
temp->MergeFrom(*message2); temp->MergeFrom(*rhs);
message2->CopyFrom(*message1); rhs->CopyFrom(*lhs);
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP #ifdef PROTOBUF_FORCE_COPY_IN_SWAP
message1->CopyFrom(*temp); lhs->CopyFrom(*temp);
if (arena == nullptr) delete temp; if (arena == nullptr) delete temp;
#else // PROTOBUF_FORCE_COPY_IN_SWAP #else // PROTOBUF_FORCE_COPY_IN_SWAP
Swap(message1, temp); Swap(lhs, temp);
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP #endif // !PROTOBUF_FORCE_COPY_IN_SWAP
return; return;
} }
UnsafeArenaSwap(message1, message2); UnsafeArenaSwap(lhs, rhs);
} }
template <bool unsafe_shallow_swap> template <bool unsafe_shallow_swap>
@ -2318,27 +2320,34 @@ void Reflection::SetAllocatedMessage(Message* message, Message* sub_message,
ABSL_DCHECK(sub_message == nullptr || sub_message->GetArena() == nullptr || ABSL_DCHECK(sub_message == nullptr || sub_message->GetArena() == nullptr ||
sub_message->GetArena() == message->GetArena()); sub_message->GetArena() == message->GetArena());
if (sub_message == nullptr) {
UnsafeArenaSetAllocatedMessage(message, nullptr, field);
return;
}
Arena* arena = message->GetArena();
Arena* sub_arena = sub_message->GetArena();
if (arena == sub_arena) {
UnsafeArenaSetAllocatedMessage(message, sub_message, field);
return;
}
// If message and sub-message are in different memory ownership domains // If message and sub-message are in different memory ownership domains
// (different arenas, or one is on heap and one is not), then we may need to // (different arenas, or one is on heap and one is not), then we may need to
// do a copy. // do a copy.
if (sub_message != nullptr && if (sub_arena == nullptr) {
sub_message->GetArena() != message->GetArena()) { ABSL_DCHECK_NE(arena, nullptr);
if (sub_message->GetArena() == nullptr && message->GetArena() != nullptr) { // Case 1: parent is on an arena and child is heap-allocated. We can add
// Case 1: parent is on an arena and child is heap-allocated. We can add // the child to the arena's Own() list to free on arena destruction, then
// the child to the arena's Own() list to free on arena destruction, then // set our pointer.
// set our pointer. arena->Own(sub_message);
message->GetArena()->Own(sub_message);
UnsafeArenaSetAllocatedMessage(message, sub_message, field);
} else {
// Case 2: all other cases. We need to make a copy. MutableMessage() will
// either get the existing message object, or instantiate a new one as
// appropriate w.r.t. our arena.
Message* sub_message_copy = MutableMessage(message, field);
sub_message_copy->CopyFrom(*sub_message);
}
} else {
// Same memory ownership domains.
UnsafeArenaSetAllocatedMessage(message, sub_message, field); UnsafeArenaSetAllocatedMessage(message, sub_message, field);
} else {
// Case 2: all other cases. We need to make a copy. MutableMessage() will
// either get the existing message object, or instantiate a new one as
// appropriate w.r.t. our arena.
Message* sub_message_copy = MutableMessage(message, field);
sub_message_copy->CopyFrom(*sub_message);
} }
} }

@ -97,10 +97,11 @@ void RepeatedPtrFieldBase::DestroyProtos() {
template <typename F> template <typename F>
auto* RepeatedPtrFieldBase::AddInternal(F factory) { auto* RepeatedPtrFieldBase::AddInternal(F factory) {
using Result = decltype(factory(GetArena())); Arena* const arena = GetArena();
using Result = decltype(factory(arena));
if (tagged_rep_or_elem_ == nullptr) { if (tagged_rep_or_elem_ == nullptr) {
ExchangeCurrentSize(1); ExchangeCurrentSize(1);
tagged_rep_or_elem_ = factory(GetArena()); tagged_rep_or_elem_ = factory(arena);
return static_cast<Result>(tagged_rep_or_elem_); return static_cast<Result>(tagged_rep_or_elem_);
} }
if (using_sso()) { if (using_sso()) {
@ -122,7 +123,7 @@ auto* RepeatedPtrFieldBase::AddInternal(F factory) {
Rep* r = rep(); Rep* r = rep();
++r->allocated_size; ++r->allocated_size;
void*& result = r->elements[ExchangeCurrentSize(current_size_ + 1)]; void*& result = r->elements[ExchangeCurrentSize(current_size_ + 1)];
result = factory(GetArena()); result = factory(arena);
return static_cast<Result>(result); return static_cast<Result>(result);
} }

Loading…
Cancel
Save