Automated rollback of commit 40bed71a88.

PiperOrigin-RevId: 572366502
pull/14350/head
Protobuf Team Bot 1 year ago committed by Copybara-Service
parent c38ba8d8be
commit 126a64517e
  1. 31
      src/google/protobuf/arena.h
  2. 14
      src/google/protobuf/arena_unittest.cc
  3. 6
      src/google/protobuf/compiler/cpp/field_generators/message_field.cc
  4. 12
      src/google/protobuf/compiler/cpp/message.cc
  5. 54
      src/google/protobuf/compiler/plugin.pb.h
  6. 12
      src/google/protobuf/cpp_features.pb.h
  7. 444
      src/google/protobuf/descriptor.pb.h
  8. 5
      src/google/protobuf/extension_set.cc
  9. 22
      src/google/protobuf/generated_message_reflection.cc
  10. 4
      src/google/protobuf/generated_message_tctable_lite.cc
  11. 2
      src/google/protobuf/generated_message_util.cc
  12. 4
      src/google/protobuf/message.cc
  13. 7
      src/google/protobuf/message_lite.h
  14. 12
      src/google/protobuf/proto3_arena_unittest.cc
  15. 10
      src/google/protobuf/reflection_ops.cc
  16. 30
      src/google/protobuf/repeated_field.h
  17. 6
      src/google/protobuf/repeated_ptr_field.cc
  18. 69
      src/google/protobuf/repeated_ptr_field.h

@ -261,7 +261,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
// again.
template <typename T>
PROTOBUF_ALWAYS_INLINE static void Destroy(T* obj) {
if (InternalGetArena(obj) == nullptr) delete obj;
if (InternalGetOwningArena(obj) == nullptr) delete obj;
}
// Allocates memory with the specific size and alignment.
@ -392,6 +392,21 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
struct Rank1 {};
struct Rank0 : Rank1 {};
static Arena* GetOwningArena(const T* p) {
return GetOwningArena(Rank0{}, p);
}
template <typename U>
static auto GetOwningArena(Rank0, const U* p)
-> EnableIfArena<decltype(p->GetOwningArena())> {
return p->GetOwningArena();
}
template <typename U>
static Arena* GetOwningArena(Rank1, const U*) {
return nullptr;
}
static void InternalSwap(T* a, T* b) { a->InternalSwap(b); }
static Arena* GetArena(T* p) { return GetArena(Rank0{}, p); }
@ -443,6 +458,20 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
friend class TestUtil::ReflectionTester;
};
// Provides access to protected GetOwningArena to generated messages. For
// internal use only.
template <typename T>
static Arena* InternalGetOwningArena(const T* p) {
return InternalHelper<T>::GetOwningArena(p);
}
// Wraps InternalGetArena() and will be removed soon.
// For internal use only.
template <typename T>
static Arena* InternalGetArenaForAllocation(T* p) {
return InternalHelper<T>::GetArena(p);
}
// Provides access to protected GetArena to generated messages.
// For internal use only.
template <typename T>

@ -561,6 +561,16 @@ TEST(ArenaTest, UnsafeArenaSwap) {
TestUtil::ExpectAllFieldsSet(*message2);
}
TEST(ArenaTest, GetOwningArena) {
Arena arena;
auto* m1 = Arena::CreateMessage<TestAllTypes>(&arena);
EXPECT_EQ(Arena::InternalGetOwningArena(m1), &arena);
EXPECT_EQ(&arena, Arena::InternalGetOwningArena(
m1->mutable_repeated_foreign_message()));
EXPECT_EQ(&arena,
Arena::InternalGetOwningArena(m1->mutable_repeated_int32()));
}
TEST(ArenaTest, SwapBetweenArenasUsingReflection) {
Arena arena1;
TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
@ -713,7 +723,7 @@ TEST(ArenaTest, SetAllocatedAcrossArenasWithReflection) {
#if GTEST_HAS_DEATH_TEST
EXPECT_DEBUG_DEATH(
r->SetAllocatedMessage(arena1_message, arena2_submessage, msg_field),
"GetArena");
"GetOwningArena");
#endif
EXPECT_NE(arena2_submessage,
arena1_message->mutable_optional_nested_message());
@ -726,7 +736,7 @@ TEST(ArenaTest, SetAllocatedAcrossArenasWithReflection) {
#if GTEST_HAS_DEATH_TEST
EXPECT_DEBUG_DEATH(
r->SetAllocatedMessage(heap_message, arena1_submessage, msg_field),
"GetArena");
"GetOwningArena");
#endif
EXPECT_NE(arena1_submessage, heap_message->mutable_optional_nested_message());
delete heap_message;

@ -287,7 +287,8 @@ void SingularMessage::GenerateInlineAccessorDefinitions(io::Printer* p) const {
//~ When $Submsg$ is a cross-file type, have to read the arena
//~ through the virtual method, because the type isn't defined in
//~ this file, only forward-declated.
$pb$::Arena* submessage_arena = $base_cast$(value)->GetArena();
$pb$::Arena* submessage_arena =
$pb$::Arena::InternalGetOwningArena($base_cast$(value));
if (message_arena != submessage_arena) {
value = $pbi$::GetOwnedMessage(message_arena, value, submessage_arena);
}
@ -574,7 +575,8 @@ void OneofMessage::GenerateNonInlineAccessorDefinitions(io::Printer* p) const {
$pb$::Arena* message_arena = GetArena();
clear_$oneof_name$();
if ($name$) {
$pb$::Arena* submessage_arena = $foreign_cast$($name$)->GetArena();
$pb$::Arena* submessage_arena =
$pb$::Arena::InternalGetOwningArena($foreign_cast$($name$));
if (message_arena != submessage_arena) {
$name$ = $pbi$::GetOwnedMessage(message_arena, $name$, submessage_arena);
}

@ -1297,9 +1297,9 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) {
"}\n"
"inline $classname$& operator=($classname$&& from) noexcept {\n"
" if (this == &from) return *this;\n"
" if (GetArena() == from.GetArena()\n"
" if (GetOwningArena() == from.GetOwningArena()\n"
"#ifdef PROTOBUF_FORCE_COPY_IN_MOVE\n"
" && GetArena() != nullptr\n"
" && GetOwningArena() != nullptr\n"
"#endif // !PROTOBUF_FORCE_COPY_IN_MOVE\n"
" ) {\n"
" InternalSwap(&from);\n"
@ -1459,10 +1459,10 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) {
"inline void Swap($classname$* other) {\n"
" if (other == this) return;\n"
"#ifdef PROTOBUF_FORCE_COPY_IN_SWAP\n"
" if (GetArena() != nullptr &&\n"
" GetArena() == other->GetArena()) {\n "
" if (GetOwningArena() != nullptr &&\n"
" GetOwningArena() == other->GetOwningArena()) {\n "
"#else // PROTOBUF_FORCE_COPY_IN_SWAP\n"
" if (GetArena() == other->GetArena()) {\n"
" if (GetOwningArena() == other->GetOwningArena()) {\n"
"#endif // !PROTOBUF_FORCE_COPY_IN_SWAP\n"
" InternalSwap(other);\n"
" } else {\n"
@ -1471,7 +1471,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* p) {
"}\n"
"void UnsafeArenaSwap($classname$* other) {\n"
" if (other == this) return;\n"
" $DCHK$(GetArena() == other->GetArena());\n"
" $DCHK$(GetOwningArena() == other->GetOwningArena());\n"
" InternalSwap(other);\n"
"}\n");

@ -142,9 +142,9 @@ class PROTOC_EXPORT Version final :
}
inline Version& operator=(Version&& from) noexcept {
if (this == &from) return *this;
if (GetArena() == from.GetArena()
if (GetOwningArena() == from.GetOwningArena()
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
&& GetArena() != nullptr
&& GetOwningArena() != nullptr
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
) {
InternalSwap(&from);
@ -188,10 +188,10 @@ class PROTOC_EXPORT Version final :
inline void Swap(Version* other) {
if (other == this) return;
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() != nullptr &&
GetArena() == other->GetArena()) {
if (GetOwningArena() != nullptr &&
GetOwningArena() == other->GetOwningArena()) {
#else // PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() == other->GetArena()) {
if (GetOwningArena() == other->GetOwningArena()) {
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
InternalSwap(other);
} else {
@ -200,7 +200,7 @@ class PROTOC_EXPORT Version final :
}
void UnsafeArenaSwap(Version* other) {
if (other == this) return;
ABSL_DCHECK(GetArena() == other->GetArena());
ABSL_DCHECK(GetOwningArena() == other->GetOwningArena());
InternalSwap(other);
}
@ -364,9 +364,9 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final :
}
inline CodeGeneratorResponse_File& operator=(CodeGeneratorResponse_File&& from) noexcept {
if (this == &from) return *this;
if (GetArena() == from.GetArena()
if (GetOwningArena() == from.GetOwningArena()
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
&& GetArena() != nullptr
&& GetOwningArena() != nullptr
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
) {
InternalSwap(&from);
@ -410,10 +410,10 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final :
inline void Swap(CodeGeneratorResponse_File* other) {
if (other == this) return;
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() != nullptr &&
GetArena() == other->GetArena()) {
if (GetOwningArena() != nullptr &&
GetOwningArena() == other->GetOwningArena()) {
#else // PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() == other->GetArena()) {
if (GetOwningArena() == other->GetOwningArena()) {
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
InternalSwap(other);
} else {
@ -422,7 +422,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final :
}
void UnsafeArenaSwap(CodeGeneratorResponse_File* other) {
if (other == this) return;
ABSL_DCHECK(GetArena() == other->GetArena());
ABSL_DCHECK(GetOwningArena() == other->GetOwningArena());
InternalSwap(other);
}
@ -602,9 +602,9 @@ class PROTOC_EXPORT CodeGeneratorResponse final :
}
inline CodeGeneratorResponse& operator=(CodeGeneratorResponse&& from) noexcept {
if (this == &from) return *this;
if (GetArena() == from.GetArena()
if (GetOwningArena() == from.GetOwningArena()
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
&& GetArena() != nullptr
&& GetOwningArena() != nullptr
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
) {
InternalSwap(&from);
@ -648,10 +648,10 @@ class PROTOC_EXPORT CodeGeneratorResponse final :
inline void Swap(CodeGeneratorResponse* other) {
if (other == this) return;
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() != nullptr &&
GetArena() == other->GetArena()) {
if (GetOwningArena() != nullptr &&
GetOwningArena() == other->GetOwningArena()) {
#else // PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() == other->GetArena()) {
if (GetOwningArena() == other->GetOwningArena()) {
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
InternalSwap(other);
} else {
@ -660,7 +660,7 @@ class PROTOC_EXPORT CodeGeneratorResponse final :
}
void UnsafeArenaSwap(CodeGeneratorResponse* other) {
if (other == this) return;
ABSL_DCHECK(GetArena() == other->GetArena());
ABSL_DCHECK(GetOwningArena() == other->GetOwningArena());
InternalSwap(other);
}
@ -841,9 +841,9 @@ class PROTOC_EXPORT CodeGeneratorRequest final :
}
inline CodeGeneratorRequest& operator=(CodeGeneratorRequest&& from) noexcept {
if (this == &from) return *this;
if (GetArena() == from.GetArena()
if (GetOwningArena() == from.GetOwningArena()
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
&& GetArena() != nullptr
&& GetOwningArena() != nullptr
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
) {
InternalSwap(&from);
@ -887,10 +887,10 @@ class PROTOC_EXPORT CodeGeneratorRequest final :
inline void Swap(CodeGeneratorRequest* other) {
if (other == this) return;
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() != nullptr &&
GetArena() == other->GetArena()) {
if (GetOwningArena() != nullptr &&
GetOwningArena() == other->GetOwningArena()) {
#else // PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() == other->GetArena()) {
if (GetOwningArena() == other->GetOwningArena()) {
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
InternalSwap(other);
} else {
@ -899,7 +899,7 @@ class PROTOC_EXPORT CodeGeneratorRequest final :
}
void UnsafeArenaSwap(CodeGeneratorRequest* other) {
if (other == this) return;
ABSL_DCHECK(GetArena() == other->GetArena());
ABSL_DCHECK(GetOwningArena() == other->GetOwningArena());
InternalSwap(other);
}
@ -1610,7 +1610,8 @@ inline void CodeGeneratorRequest::set_allocated_compiler_version(::google::proto
}
if (value != nullptr) {
::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::compiler::Version*>(value)->GetArena();
::google::protobuf::Arena* submessage_arena =
::google::protobuf::Arena::InternalGetOwningArena(reinterpret_cast<::google::protobuf::compiler::Version*>(value));
if (message_arena != submessage_arena) {
value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena);
}
@ -1918,7 +1919,8 @@ inline void CodeGeneratorResponse_File::set_allocated_generated_code_info(::goog
}
if (value != nullptr) {
::google::protobuf::Arena* submessage_arena = reinterpret_cast<::google::protobuf::MessageLite*>(value)->GetArena();
::google::protobuf::Arena* submessage_arena =
::google::protobuf::Arena::InternalGetOwningArena(reinterpret_cast<::google::protobuf::MessageLite*>(value));
if (message_arena != submessage_arena) {
value = ::google::protobuf::internal::GetOwnedMessage(message_arena, value, submessage_arena);
}

@ -94,9 +94,9 @@ class PROTOBUF_EXPORT CppFeatures final :
}
inline CppFeatures& operator=(CppFeatures&& from) noexcept {
if (this == &from) return *this;
if (GetArena() == from.GetArena()
if (GetOwningArena() == from.GetOwningArena()
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
&& GetArena() != nullptr
&& GetOwningArena() != nullptr
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
) {
InternalSwap(&from);
@ -140,10 +140,10 @@ class PROTOBUF_EXPORT CppFeatures final :
inline void Swap(CppFeatures* other) {
if (other == this) return;
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() != nullptr &&
GetArena() == other->GetArena()) {
if (GetOwningArena() != nullptr &&
GetOwningArena() == other->GetOwningArena()) {
#else // PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() == other->GetArena()) {
if (GetOwningArena() == other->GetOwningArena()) {
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
InternalSwap(other);
} else {
@ -152,7 +152,7 @@ class PROTOBUF_EXPORT CppFeatures final :
}
void UnsafeArenaSwap(CppFeatures* other) {
if (other == this) return;
ABSL_DCHECK(GetArena() == other->GetArena());
ABSL_DCHECK(GetOwningArena() == other->GetOwningArena());
InternalSwap(other);
}

File diff suppressed because it is too large Load Diff

@ -626,8 +626,9 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
ClearExtension(number);
return;
}
ABSL_DCHECK(message->GetArena() == nullptr || message->GetArena() == arena_);
Arena* message_arena = message->GetArena();
ABSL_DCHECK(message->GetOwningArena() == nullptr ||
message->GetOwningArena() == arena_);
Arena* message_arena = message->GetOwningArena();
Extension* extension;
if (MaybeNewExtension(number, descriptor, &extension)) {
extension->type = type;

@ -1064,16 +1064,16 @@ void Reflection::Swap(Message* message1, Message* message2) const {
// 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.
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
if (message1->GetArena() == nullptr ||
message1->GetArena() != message2->GetArena()) {
if (message1->GetOwningArena() == nullptr ||
message1->GetOwningArena() != message2->GetOwningArena()) {
#else // PROTOBUF_FORCE_COPY_IN_SWAP
if (message1->GetArena() != message2->GetArena()) {
if (message1->GetOwningArena() != message2->GetOwningArena()) {
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
// One of the two is guaranteed to have an arena. Switch things around
// to guarantee that message1 has an arena.
Arena* arena = message1->GetArena();
Arena* arena = message1->GetOwningArena();
if (arena == nullptr) {
arena = message2->GetArena();
arena = message2->GetOwningArena();
std::swap(message1, message2); // Swapping names for pointers!
}
@ -1203,7 +1203,7 @@ bool Reflection::HasField(const Message& message,
}
void Reflection::UnsafeArenaSwap(Message* lhs, Message* rhs) const {
ABSL_DCHECK_EQ(lhs->GetArena(), rhs->GetArena());
ABSL_DCHECK_EQ(lhs->GetOwningArena(), rhs->GetOwningArena());
InternalSwap(lhs, rhs);
}
@ -2311,15 +2311,17 @@ void Reflection::UnsafeArenaSetAllocatedMessage(
void Reflection::SetAllocatedMessage(Message* message, Message* sub_message,
const FieldDescriptor* field) const {
ABSL_DCHECK(sub_message == nullptr || sub_message->GetArena() == nullptr ||
sub_message->GetArena() == message->GetArena());
ABSL_DCHECK(sub_message == nullptr ||
sub_message->GetOwningArena() == nullptr ||
sub_message->GetOwningArena() == message->GetArena());
// 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
// do a copy.
if (sub_message != nullptr &&
sub_message->GetArena() != message->GetArena()) {
if (sub_message->GetArena() == nullptr && message->GetArena() != nullptr) {
sub_message->GetOwningArena() != message->GetArena()) {
if (sub_message->GetOwningArena() == nullptr &&
message->GetArena() != nullptr) {
// 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
// set our pointer.

@ -1557,7 +1557,7 @@ PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedString(
}
};
auto* arena = field.GetArena();
auto* arena = field.GetOwningArena();
SerialArena* serial_arena;
if (PROTOBUF_PREDICT_TRUE(arena != nullptr &&
arena->impl_.GetSerialArenaFast(&serial_arena) &&
@ -2260,7 +2260,7 @@ PROTOBUF_NOINLINE const char* TcParser::MpRepeatedString(
const char* ptr2 = ptr;
uint32_t next_tag;
auto* arena = field.GetArena();
auto* arena = field.GetOwningArena();
SerialArena* serial_arena;
if (PROTOBUF_PREDICT_TRUE(
arena != nullptr &&

@ -368,7 +368,7 @@ void GenericSwap(MessageLite* m1, MessageLite* m2) {
MessageLite* GetOwnedMessageInternal(Arena* message_arena,
MessageLite* submessage,
Arena* submessage_arena) {
ABSL_DCHECK(submessage->GetArena() == submessage_arena);
ABSL_DCHECK(Arena::InternalGetOwningArena(submessage) == submessage_arena);
ABSL_DCHECK(message_arena != submessage_arena);
ABSL_DCHECK_EQ(submessage_arena, nullptr);
if (message_arena != nullptr && submessage_arena == nullptr) {

@ -414,8 +414,8 @@ template <>
PROTOBUF_NOINLINE
#endif
Arena*
GenericTypeHandler<Message>::GetArena(Message* value) {
return value->GetArena();
GenericTypeHandler<Message>::GetOwningArena(Message* value) {
return value->GetOwningArena();
}
template void InternalMetadata::DoClear<UnknownFieldSet>();

@ -514,6 +514,13 @@ class PROTOBUF_EXPORT MessageLite {
inline explicit MessageLite(Arena* arena) : _internal_metadata_(arena) {}
// Returns the arena, if any, that directly owns this message and its internal
// memory (Arena::Own is different in that the arena doesn't directly own the
// internal memory). This method is used in proto's implementation for
// swapping, moving and setting allocated, for deciding whether the ownership
// of this message or its internal memory could be changed.
Arena* GetOwningArena() const { return _internal_metadata_.arena(); }
struct ClassData {
// Note: The order of arguments in the functions is chosen so that it has
// the same ABI as the member function that calls them. Eg the `this`

@ -28,6 +28,18 @@ using proto3_arena_unittest::TestAllTypes;
namespace google {
namespace protobuf {
namespace internal {
class Proto3ArenaTestHelper {
public:
template <typename T>
static Arena* GetOwningArena(const T& msg) {
return msg.GetOwningArena();
}
};
} // namespace internal
namespace {
// We selectively set/check a few representative fields rather than all fields
// as this test is only expected to cover the basics of arena support.

@ -415,14 +415,16 @@ void ReflectionOps::FindInitializationErrors(const Message& message,
void GenericSwap(Message* lhs, Message* rhs) {
#ifndef PROTOBUF_FORCE_COPY_IN_SWAP
ABSL_DCHECK(lhs->GetArena() != rhs->GetArena());
ABSL_DCHECK(lhs->GetArena() != nullptr || rhs->GetArena() != nullptr);
ABSL_DCHECK(Arena::InternalGetOwningArena(lhs) !=
Arena::InternalGetOwningArena(rhs));
ABSL_DCHECK(Arena::InternalGetOwningArena(lhs) != nullptr ||
Arena::InternalGetOwningArena(rhs) != nullptr);
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
// At least one of these must have an arena, so make `rhs` point to it.
Arena* arena = rhs->GetArena();
Arena* arena = Arena::InternalGetOwningArena(rhs);
if (arena == nullptr) {
std::swap(lhs, rhs);
arena = rhs->GetArena();
arena = Arena::InternalGetOwningArena(rhs);
}
// Improve efficiency by placing the temporary on an arena so that messages

@ -293,10 +293,7 @@ class RepeatedField final
// Gets the Arena on which this RepeatedField stores its elements.
// Note: this can be inaccurate for split default fields so we make this
// function non-const.
inline Arena* GetArena() {
return (total_size_ == 0) ? static_cast<Arena*>(arena_or_elements_)
: rep()->arena;
}
inline Arena* GetArena() { return GetOwningArena(); }
// For internal use only.
//
@ -330,6 +327,12 @@ class RepeatedField final
RepeatedField(Arena* arena, const RepeatedField& rhs);
// Gets the Arena on which this RepeatedField stores its elements.
inline Arena* GetOwningArena() const {
return (total_size_ == 0) ? static_cast<Arena*>(arena_or_elements_)
: rep()->arena;
}
// Swaps entire contents with "other". Should be called only if the caller can
// guarantee that both repeated fields are on the same arena or are on the
// heap. Swapping between different arenas is disallowed and caught by a
@ -497,7 +500,7 @@ RepeatedField<Element>::~RepeatedField() {
#ifndef NDEBUG
// Try to trigger segfault / asan failure in non-opt builds if arena_
// lifetime has ended before the destructor.
auto arena = GetArena();
auto arena = GetOwningArena();
if (arena) (void)arena->SpaceAllocated();
#endif
if (total_size_ > 0) {
@ -522,7 +525,7 @@ inline RepeatedField<Element>::RepeatedField(RepeatedField&& other) noexcept
// We don't just call Swap(&other) here because it would perform 3 copies if
// other is on an arena. This field can't be on an arena because arena
// construction always uses the Arena* accepting constructor.
if (other.GetArena()) {
if (other.GetOwningArena()) {
CopyFrom(other);
} else {
InternalSwap(&other);
@ -536,9 +539,9 @@ inline RepeatedField<Element>& RepeatedField<Element>::operator=(
// We don't just call Swap(&other) here because it would perform 3 copies if
// the two fields are on different arenas.
if (this != &other) {
if (GetArena() != other.GetArena()
if (GetOwningArena() != other.GetOwningArena()
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|| GetArena() == nullptr
|| GetOwningArena() == nullptr
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
) {
CopyFrom(other);
@ -831,13 +834,14 @@ template <typename Element>
void RepeatedField<Element>::Swap(RepeatedField* other) {
if (this == other) return;
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() != nullptr && GetArena() == other->GetArena()) {
if (GetOwningArena() != nullptr &&
GetOwningArena() == other->GetOwningArena()) {
#else // PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() == other->GetArena()) {
if (GetOwningArena() == other->GetOwningArena()) {
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
InternalSwap(other);
} else {
RepeatedField<Element> temp(other->GetArena());
RepeatedField<Element> temp(other->GetOwningArena());
temp.MergeFrom(*this);
CopyFrom(*other);
other->UnsafeArenaSwap(&temp);
@ -847,7 +851,7 @@ void RepeatedField<Element>::Swap(RepeatedField* other) {
template <typename Element>
void RepeatedField<Element>::UnsafeArenaSwap(RepeatedField* other) {
if (this == other) return;
ABSL_DCHECK_EQ(GetArena(), other->GetArena());
ABSL_DCHECK_EQ(GetOwningArena(), other->GetOwningArena());
InternalSwap(other);
}
@ -936,7 +940,7 @@ PROTOBUF_NOINLINE void RepeatedField<Element>::GrowNoAnnotate(int current_size,
int new_size) {
ABSL_DCHECK_GT(new_size, total_size_);
Rep* new_rep;
Arena* arena = GetArena();
Arena* arena = GetOwningArena();
new_size = internal::CalculateReserveSize<Element, kRepHeaderSize>(
total_size_, new_size);

@ -34,7 +34,7 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) {
ABSL_DCHECK(extend_amount > 0);
constexpr size_t ptr_size = sizeof(rep()->elements[0]);
int new_capacity = total_size_ + extend_amount;
Arena* arena = GetArena();
Arena* arena = GetOwningArena();
new_capacity = internal::CalculateReserveSize<void*, kRepHeaderSize>(
total_size_, new_capacity);
ABSL_CHECK_LE(
@ -207,7 +207,7 @@ void RepeatedPtrFieldBase::MergeFromConcreteMessage(
dst += recycled;
src += recycled;
}
Arena* arena = GetArena();
Arena* arena = GetOwningArena();
for (; src < end; ++src, ++dst) {
*dst = copy_fn(arena, **src);
}
@ -230,7 +230,7 @@ void RepeatedPtrFieldBase::MergeFrom<MessageLite>(
dst += recycled;
src += recycled;
}
Arena* arena = GetArena();
Arena* arena = GetOwningArena();
for (; src < end; ++src, ++dst) {
*dst = (*src)->New(arena);
(*dst)->CheckTypeAndMergeFrom(**src);

@ -386,9 +386,10 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
PROTOBUF_NDEBUG_INLINE void Swap(RepeatedPtrFieldBase* other) {
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() != nullptr && GetArena() == other->GetArena())
if (GetOwningArena() != nullptr &&
GetOwningArena() == other->GetOwningArena())
#else // PROTOBUF_FORCE_COPY_IN_SWAP
if (GetArena() == other->GetArena())
if (GetOwningArena() == other->GetOwningArena())
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
{
InternalSwap(other);
@ -494,9 +495,10 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
void AddCleared(Value<TypeHandler>* value) {
ABSL_DCHECK(GetArena() == nullptr) << "AddCleared() can only be used on a "
"RepeatedPtrField not on an arena.";
ABSL_DCHECK(TypeHandler::GetArena(value) == nullptr)
ABSL_DCHECK(GetOwningArena() == nullptr)
<< "AddCleared() can only be used on a "
"RepeatedPtrField not on an arena.";
ABSL_DCHECK(TypeHandler::GetOwningArena(value) == nullptr)
<< "AddCleared() can only accept values not on an arena.";
MaybeExtend();
if (using_sso()) {
@ -508,7 +510,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
PROTOBUF_NODISCARD Value<TypeHandler>* ReleaseCleared() {
ABSL_DCHECK(GetArena() == nullptr)
ABSL_DCHECK(GetOwningArena() == nullptr)
<< "ReleaseCleared() can only be used on a RepeatedPtrField not on "
<< "an arena.";
ABSL_DCHECK(tagged_rep_or_elem_ != nullptr);
@ -525,8 +527,8 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
// AddAllocated version that implements arena-safe copying behavior.
template <typename TypeHandler>
void AddAllocatedInternal(Value<TypeHandler>* value, std::true_type) {
Arena* element_arena = TypeHandler::GetArena(value);
Arena* arena = GetArena();
Arena* element_arena = TypeHandler::GetOwningArena(value);
Arena* arena = GetOwningArena();
if (arena == element_arena && allocated_size() < total_size_) {
// Fast path: underlying arena representation (tagged pointer) is equal to
// our arena pointer, and we can add to array without resizing it (at
@ -592,7 +594,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
// First, release an element.
Value<TypeHandler>* result = UnsafeArenaReleaseLast<TypeHandler>();
// Now perform a copy if we're on an arena.
Arena* arena = GetArena();
Arena* arena = GetOwningArena();
#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
auto* new_result = copy<TypeHandler>(result);
@ -609,7 +611,7 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
// this is the same as UnsafeArenaReleaseLast(). Note that we
// ABSL_DCHECK-fail if we're on an arena, since the user really should
// implement the copy operation in this case.
ABSL_DCHECK(GetArena() == nullptr)
ABSL_DCHECK(GetOwningArena() == nullptr)
<< "ReleaseLast() called on a RepeatedPtrField that is on an arena, "
<< "with a type that does not implement MergeFrom. This is unsafe; "
<< "please implement MergeFrom for your type.";
@ -619,15 +621,16 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
PROTOBUF_NOINLINE void SwapFallback(RepeatedPtrFieldBase* other) {
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
ABSL_DCHECK(GetArena() == nullptr || other->GetArena() != GetArena());
ABSL_DCHECK(GetOwningArena() == nullptr ||
other->GetOwningArena() != GetOwningArena());
#else // PROTOBUF_FORCE_COPY_IN_SWAP
ABSL_DCHECK(other->GetArena() != GetArena());
ABSL_DCHECK(other->GetOwningArena() != GetOwningArena());
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
// Copy semantics in this case. We try to improve efficiency by placing the
// temporary on |other|'s arena so that messages are copied twice rather
// than three times.
RepeatedPtrFieldBase temp(other->GetArena());
RepeatedPtrFieldBase temp(other->GetOwningArena());
if (!this->empty()) {
temp.MergeFrom<typename TypeHandler::Type>(*this);
}
@ -637,7 +640,9 @@ class PROTOBUF_EXPORT RepeatedPtrFieldBase {
}
// Gets the Arena on which this RepeatedPtrField stores its elements.
inline Arena* GetArena() const { return arena_; }
inline Arena* GetArena() const { return GetOwningArena(); }
inline Arena* GetOwningArena() const { return arena_; }
private:
using InternalArenaConstructable_ = void;
@ -880,8 +885,8 @@ class GenericTypeHandler {
delete value;
#endif
}
static inline Arena* GetArena(GenericType* value) {
return Arena::InternalGetArena(value);
static inline Arena* GetOwningArena(GenericType* value) {
return Arena::InternalGetOwningArena(value);
}
static inline void Clear(GenericType* value) { value->Clear(); }
@ -903,8 +908,9 @@ inline MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
return NewFromPrototypeHelper(prototype, arena);
}
template <>
inline Arena* GenericTypeHandler<MessageLite>::GetArena(MessageLite* value) {
return value->GetArena();
inline Arena* GenericTypeHandler<MessageLite>::GetOwningArena(
MessageLite* value) {
return value->GetOwningArena();
}
template <typename GenericType>
@ -931,7 +937,8 @@ 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>::GetOwningArena(
Message* value);
class StringTypeHandler {
public:
@ -948,7 +955,7 @@ class StringTypeHandler {
Arena* arena) {
return New(arena);
}
static inline Arena* GetArena(std::string*) { return nullptr; }
static inline Arena* GetOwningArena(std::string*) { return nullptr; }
static inline void Delete(std::string* value, Arena* arena) {
if (arena == nullptr) {
delete value;
@ -1300,6 +1307,9 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase {
RepeatedPtrField(Arena* arena, const RepeatedPtrField& rhs);
// Internal version of GetArena().
inline Arena* GetOwningArena() const;
// Implementations for ExtractSubrange(). The copying behavior must be
// included only if the type supports the necessary operations (e.g.,
// MergeFrom()), so we must resolve this at compile time. ExtractSubrange()
@ -1384,7 +1394,7 @@ inline RepeatedPtrField<Element>::RepeatedPtrField(
// We don't just call Swap(&other) here because it would perform 3 copies if
// other is on an arena. This field can't be on an arena because arena
// construction always uses the Arena* accepting constructor.
if (other.GetArena()) {
if (other.GetOwningArena()) {
CopyFrom(other);
} else {
InternalSwap(&other);
@ -1398,9 +1408,9 @@ inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
// We don't just call Swap(&other) here because it would perform 3 copies if
// the two fields are on different arenas.
if (this != &other) {
if (GetArena() != other.GetArena()
if (GetOwningArena() != other.GetOwningArena()
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|| GetArena() == nullptr
|| GetOwningArena() == nullptr
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
) {
CopyFrom(other);
@ -1482,7 +1492,7 @@ inline void RepeatedPtrField<Element>::DeleteSubrange(int start, int num) {
ABSL_DCHECK_GE(num, 0);
ABSL_DCHECK_LE(start + num, size());
void** subrange = raw_mutable_data() + start;
Arena* arena = GetArena();
Arena* arena = GetOwningArena();
for (int i = 0; i < num; ++i) {
using H = CommonHandler<TypeHandler>;
H::Delete(static_cast<Element*>(subrange[i]), arena);
@ -1513,7 +1523,7 @@ inline void RepeatedPtrField<Element>::ExtractSubrangeInternal(
<< "Releasing elements without transferring ownership is an unsafe "
"operation. Use UnsafeArenaExtractSubrange.";
if (elements != nullptr) {
Arena* arena = GetArena();
Arena* arena = GetOwningArena();
auto* extracted = data() + start;
#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
// Always copy.
@ -1549,7 +1559,7 @@ inline void RepeatedPtrField<Element>::ExtractSubrangeInternal(
// ExtractSubrange() must return heap-allocated objects by contract, and we
// cannot fulfill this contract if we are an on arena, we must ABSL_DCHECK()
// that we are not on an arena.
ABSL_DCHECK(GetArena() == nullptr)
ABSL_DCHECK(GetOwningArena() == nullptr)
<< "ExtractSubrange() when arena is non-nullptr is only supported when "
<< "the Element type supplies a MergeFrom() operation to make copies.";
UnsafeArenaExtractSubrange(start, num, elements);
@ -1634,7 +1644,7 @@ template <typename Element>
inline void RepeatedPtrField<Element>::UnsafeArenaSwap(
RepeatedPtrField* other) {
if (this == other) return;
ABSL_DCHECK_EQ(GetArena(), other->GetArena());
ABSL_DCHECK_EQ(GetOwningArena(), other->GetOwningArena());
RepeatedPtrFieldBase::InternalSwap(other);
}
@ -1655,6 +1665,11 @@ inline Arena* RepeatedPtrField<Element>::GetArena() const {
}
#endif // !PROTOBUF_FUTURE_REMOVE_CONST_REPEATEDFIELD_GETARENA_API
template <typename Element>
inline Arena* RepeatedPtrField<Element>::GetOwningArena() const {
return RepeatedPtrFieldBase::GetOwningArena();
}
template <typename Element>
inline size_t RepeatedPtrField<Element>::SpaceUsedExcludingSelfLong() const {
// `google::protobuf::Message` has a virtual method `SpaceUsedLong`, hence we can

Loading…
Cancel
Save