From 3e5fe0061f9b3e9263a50369e7ddab8f105d109f Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Tue, 22 Nov 2022 09:51:09 -0800 Subject: [PATCH] Cleanup arena.h template dispatch. CreateInternal dispatch is not necessary, both sides did the same. OwnInternal can be changed with a std::conditional_t. PiperOrigin-RevId: 490267078 --- src/google/protobuf/arena.h | 69 +++++++-------------------- src/google/protobuf/arena_unittest.cc | 10 ++++ 2 files changed, 27 insertions(+), 52 deletions(-) diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index e76e66fabb..abce219e5d 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -270,8 +270,14 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { // is obtained from the arena). template PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) { - return CreateInternal(arena, std::is_convertible(), - static_cast(args)...); + if (arena == nullptr) { + return new T(std::forward(args)...); + } + auto destructor = + internal::ObjectDestructor::value, + T>::destructor; + return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor)) + T(std::forward(args)...); } // API to delete any objects not on an arena. This can be used to safely @@ -346,7 +352,15 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { // when the arena is destroyed or reset. template PROTOBUF_ALWAYS_INLINE void Own(T* object) { - OwnInternal(object, std::is_convertible()); + // Collapsing all template instantiations to one for generic Message reduces + // code size, using the virtual destructor instead. + using TypeToUse = + std::conditional_t::value, + MessageLite, T>; + if (object != nullptr) { + impl_.AddCleanup(static_cast(object), + &internal::arena_delete_object); + } } // Adds |object| to a list of objects whose destructors will be manually @@ -655,55 +669,6 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { arena->OwnDestructor(ptr); } - // These implement Create(). The second parameter has type 'true_type' if T is - // a subtype of Message and 'false_type' otherwise. - template - PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::true_type, - Args&&... args) { - if (arena == nullptr) { - return new T(std::forward(args)...); - } else { - auto destructor = - internal::ObjectDestructor::value, - T>::destructor; - T* result = - new (arena->AllocateInternal(sizeof(T), alignof(T), destructor)) - T(std::forward(args)...); - return result; - } - } - template - PROTOBUF_ALWAYS_INLINE static T* CreateInternal(Arena* arena, std::false_type, - Args&&... args) { - if (arena == nullptr) { - return new T(std::forward(args)...); - } else { - auto destructor = - internal::ObjectDestructor::value, - T>::destructor; - return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor)) - T(std::forward(args)...); - } - } - - // These implement Own(), which registers an object for deletion (destructor - // call and operator delete()). The second parameter has type 'true_type' if T - // is a subtype of Message and 'false_type' otherwise. Collapsing - // all template instantiations to one for generic Message reduces code size, - // using the virtual destructor instead. - template - PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) { - if (object != nullptr) { - impl_.AddCleanup(object, &internal::arena_delete_object); - } - } - template - PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::false_type) { - if (object != nullptr) { - impl_.AddCleanup(object, &internal::arena_delete_object); - } - } - // Implementation for GetArena(). Only message objects with // InternalArenaConstructable_ tags can be associated with an arena, and such // objects must implement a GetArena() method. diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index f96dc3261b..592cd9d5ae 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -334,6 +334,16 @@ TEST(ArenaTest, CreateDestroy) { strlen(arena_message->optional_string().c_str())); } +struct OnlyArenaConstructible { + using InternalArenaConstructable_ = void; + explicit OnlyArenaConstructible(Arena* arena) {} +}; + +TEST(ArenaTest, ArenaOnlyTypesCanBeConstructed) { + Arena arena; + Arena::CreateMessage(&arena); +} + TEST(ArenaTest, Parsing) { TestAllTypes original; TestUtil::SetAllFields(&original);