|
|
|
@ -32,7 +32,6 @@ using type_info = ::type_info; |
|
|
|
|
#include "absl/base/optimization.h" |
|
|
|
|
#include "absl/base/prefetch.h" |
|
|
|
|
#include "absl/log/absl_check.h" |
|
|
|
|
#include "absl/utility/internal/if_constexpr.h" |
|
|
|
|
#include "google/protobuf/arena_align.h" |
|
|
|
|
#include "google/protobuf/arena_allocation_policy.h" |
|
|
|
|
#include "google/protobuf/port.h" |
|
|
|
@ -195,41 +194,31 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { |
|
|
|
|
// otherwise, returns a heap-allocated object.
|
|
|
|
|
template <typename T, typename... Args> |
|
|
|
|
PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) { |
|
|
|
|
return absl::utility_internal::IfConstexprElse< |
|
|
|
|
is_arena_constructable<T>::value>( |
|
|
|
|
// Arena-constructable
|
|
|
|
|
[arena](auto&&... args) { |
|
|
|
|
using Type = std::remove_const_t<T>; |
|
|
|
|
#ifdef __cpp_if_constexpr |
|
|
|
|
// DefaultConstruct/CopyConstruct are optimized for messages, which
|
|
|
|
|
// are both arena constructible and destructor skippable and they
|
|
|
|
|
// assume much. Don't use these functions unless the invariants
|
|
|
|
|
// hold.
|
|
|
|
|
if constexpr (is_destructor_skippable<T>::value) { |
|
|
|
|
constexpr auto construct_type = GetConstructType<T, Args&&...>(); |
|
|
|
|
// We delegate to DefaultConstruct/CopyConstruct where appropriate
|
|
|
|
|
// because protobuf generated classes have external templates for
|
|
|
|
|
// these functions for code size reasons. When `if constexpr` is not
|
|
|
|
|
// available always use the fallback.
|
|
|
|
|
if constexpr (construct_type == ConstructType::kDefault) { |
|
|
|
|
return static_cast<Type*>(DefaultConstruct<Type>(arena)); |
|
|
|
|
} else if constexpr (construct_type == ConstructType::kCopy) { |
|
|
|
|
return static_cast<Type*>(CopyConstruct<Type>(arena, &args...)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
return CreateArenaCompatible<Type>(arena, |
|
|
|
|
std::forward<Args>(args)...); |
|
|
|
|
}, |
|
|
|
|
// Non arena-constructable
|
|
|
|
|
[arena](auto&&... args) { |
|
|
|
|
if (ABSL_PREDICT_FALSE(arena == nullptr)) { |
|
|
|
|
return new T(std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
return new (arena->AllocateInternal<T>()) |
|
|
|
|
T(std::forward<Args>(args)...); |
|
|
|
|
}, |
|
|
|
|
std::forward<Args>(args)...); |
|
|
|
|
if constexpr (is_arena_constructable<T>::value) { |
|
|
|
|
using Type = std::remove_const_t<T>; |
|
|
|
|
// DefaultConstruct/CopyConstruct are optimized for messages, which
|
|
|
|
|
// are both arena constructible and destructor skippable and they
|
|
|
|
|
// assume much. Don't use these functions unless the invariants
|
|
|
|
|
// hold.
|
|
|
|
|
if constexpr (is_destructor_skippable<T>::value) { |
|
|
|
|
constexpr auto construct_type = GetConstructType<T, Args&&...>(); |
|
|
|
|
// We delegate to DefaultConstruct/CopyConstruct where appropriate
|
|
|
|
|
// because protobuf generated classes have external templates for
|
|
|
|
|
// these functions for code size reasons. When `if constexpr` is not
|
|
|
|
|
// available always use the fallback.
|
|
|
|
|
if constexpr (construct_type == ConstructType::kDefault) { |
|
|
|
|
return static_cast<Type*>(DefaultConstruct<Type>(arena)); |
|
|
|
|
} else if constexpr (construct_type == ConstructType::kCopy) { |
|
|
|
|
return static_cast<Type*>(CopyConstruct<Type>(arena, &args...)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return CreateArenaCompatible<Type>(arena, std::forward<Args>(args)...); |
|
|
|
|
} else { |
|
|
|
|
if (ABSL_PREDICT_FALSE(arena == nullptr)) { |
|
|
|
|
return new T(std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
return new (arena->AllocateInternal<T>()) T(std::forward<Args>(args)...); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// API to delete any objects not on an arena. This can be used to safely
|
|
|
|
|