Skip to content

Commit 4624d81

Browse files
ckennellycopybara-github
authored andcommitted
Use __builtin_operator_new to faciliate compiler optimizations of these allocs.
PiperOrigin-RevId: 818685458
1 parent 0d03515 commit 4624d81

File tree

11 files changed

+29
-35
lines changed

11 files changed

+29
-35
lines changed

src/google/protobuf/arena.h

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -760,14 +760,6 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8)
760760
template <typename T>
761761
PROTOBUF_NOINLINE void* PROTOBUF_NONNULL
762762
Arena::DefaultConstruct(Arena* PROTOBUF_NULLABLE arena) {
763-
auto operator_new = [](size_t size) -> void* {
764-
#if ABSL_HAVE_BUILTIN(__builtin_operator_new)
765-
return __builtin_operator_new(size);
766-
#else
767-
return ::operator new(size);
768-
#endif
769-
};
770-
771763
if constexpr (internal::FieldHasArenaOffset<T>()) {
772764
if (arena != nullptr) {
773765
using ArenaRepT = typename internal::FieldArenaRep<T>::Type;
@@ -781,12 +773,12 @@ Arena::DefaultConstruct(Arena* PROTOBUF_NULLABLE arena) {
781773
// Fields which use arena offsets don't have constructors that take an
782774
// arena pointer. Since the arena is nullptr, it is safe to default
783775
// construct the object.
784-
return new (operator_new(sizeof(T))) T();
776+
return new (internal::Allocate(sizeof(T))) T();
785777
}
786778
} else {
787779
static_assert(is_destructor_skippable<T>::value);
788780
void* mem = arena != nullptr ? arena->AllocateAligned(sizeof(T))
789-
: operator_new(sizeof(T));
781+
: internal::Allocate(sizeof(T));
790782
if constexpr (internal::HasDeprecatedArenaConstructor<T>()) {
791783
return new (mem) T(internal::InternalVisibility(), arena);
792784
} else {
@@ -818,11 +810,7 @@ PROTOBUF_NOINLINE void* PROTOBUF_NONNULL Arena::CopyConstruct(
818810
if (arena != nullptr) {
819811
mem = arena->AllocateAligned(sizeof(T));
820812
} else {
821-
#if ABSL_HAVE_BUILTIN(__builtin_operator_new)
822-
mem = __builtin_operator_new(sizeof(T));
823-
#else
824-
mem = ::operator new(sizeof(T));
825-
#endif
813+
mem = internal::Allocate(sizeof(T));
826814
}
827815
return new (mem) T(arena, *typed_from);
828816
}

src/google/protobuf/descriptor.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,7 +2288,7 @@ Type* DescriptorPool::Tables::Allocate() {
22882288

22892289
void* DescriptorPool::Tables::AllocateBytes(int size) {
22902290
if (size == 0) return nullptr;
2291-
void* p = ::operator new(size + RoundUpTo<8>(sizeof(int)));
2291+
void* p = internal::Allocate(size + RoundUpTo<8>(sizeof(int)));
22922292
int* sizep = static_cast<int*>(p);
22932293
misc_allocs_.emplace_back(sizep);
22942294
*sizep = size;
@@ -2305,7 +2305,7 @@ internal::FlatAllocator::Allocation* DescriptorPool::Tables::CreateFlatAlloc(
23052305
typename std::tuple_element<sizeof...(T) - 1, std::tuple<T...>>::type>();
23062306
size_t total_size =
23072307
last_end + RoundUpTo<FlatAlloc::kMaxAlign>(sizeof(FlatAlloc));
2308-
char* data = static_cast<char*>(::operator new(total_size));
2308+
char* data = static_cast<char*>(internal::Allocate(total_size));
23092309
auto* res = ::new (data) FlatAlloc(ends);
23102310
flat_allocs_.emplace_back(res);
23112311

src/google/protobuf/descriptor_database.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ bool EncodedDescriptorDatabase::Add(
600600

601601
bool EncodedDescriptorDatabase::AddCopy(
602602
const void* PROTOBUF_NONNULL encoded_file_descriptor, int size) {
603-
void* copy = operator new(size);
603+
void* copy = internal::Allocate(size);
604604
memcpy(copy, encoded_file_descriptor, size);
605605
files_to_delete_.push_back(copy);
606606
return Add(copy, size);

src/google/protobuf/dynamic_message.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -986,7 +986,7 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
986986
// Construct the reflection object.
987987

988988
// Allocate the prototype fields.
989-
void* base = operator new(size);
989+
void* base = internal::Allocate(size);
990990
memset(base, 0, size);
991991

992992
// We have already locked the factory so we should not lock in the constructor

src/google/protobuf/generated_message_reflection.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3067,7 +3067,7 @@ void Reflection::PrepareSplitMessageForWrite(Message* message) const {
30673067
if (*split == default_split) {
30683068
uint32_t size = schema_.SizeofSplit();
30693069
Arena* arena = message->GetArena();
3070-
*split = (arena == nullptr) ? ::operator new(size)
3070+
*split = (arena == nullptr) ? internal::Allocate(size)
30713071
: arena->AllocateAligned(size);
30723072
memcpy(*split, default_split, size);
30733073
}
@@ -3831,7 +3831,7 @@ const internal::TcParseTableBase* Reflection::CreateTcParseTable() const {
38313831
sizeof(TcParseTableBase::FieldAux) * table_info.aux_entries.size() +
38323832
sizeof(char) * table_info.field_name_data.size();
38333833

3834-
void* p = ::operator new(byte_size);
3834+
void* p = internal::Allocate(byte_size);
38353835
auto* res = ::new (p) TcParseTableBase{
38363836
static_cast<uint16_t>(schema_.HasHasbits() ? schema_.HasBitsOffset() : 0),
38373837
schema_.HasExtensionSet()

src/google/protobuf/generated_message_tctable_lite.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,8 +2042,8 @@ void* TcParser::MaybeGetSplitBase(MessageLite* msg, const bool is_split,
20422042
// Allocate split instance when needed.
20432043
uint32_t size = GetSizeofSplit(table);
20442044
Arena* arena = msg->GetArena();
2045-
split = (arena == nullptr) ? ::operator new(size)
2046-
: arena->AllocateAligned(size);
2045+
split =
2046+
(arena == nullptr) ? Allocate(size) : arena->AllocateAligned(size);
20472047
memcpy(split, default_split, size);
20482048
}
20492049
out = split;

src/google/protobuf/map.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ class PROTOBUF_EXPORT UntypedMapBase {
452452

453453
NodeBase* AllocNode(size_t node_size) {
454454
return static_cast<NodeBase*>(arena_ == nullptr
455-
? ::operator new(node_size)
455+
? Allocate(node_size)
456456
: arena_->AllocateAligned(node_size));
457457
}
458458

@@ -476,7 +476,7 @@ class PROTOBUF_EXPORT UntypedMapBase {
476476
ABSL_DCHECK_EQ(n & (n - 1), 0u);
477477
NodeBase** result =
478478
arena_ == nullptr
479-
? static_cast<NodeBase**>(::operator new(n * sizeof(NodeBase*)))
479+
? static_cast<NodeBase**>(Allocate(n * sizeof(NodeBase*)))
480480
: Arena::CreateArray<NodeBase*>(arena_, n);
481481
memset(result, 0, n * sizeof(result[0]));
482482
return result;

src/google/protobuf/message.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ void* CreateSplitMessageGeneric(Arena* arena, const void* default_split,
245245
const void* default_message) {
246246
ABSL_DCHECK_NE(message, default_message);
247247
void* split =
248-
(arena == nullptr) ? ::operator new(size) : arena->AllocateAligned(size);
248+
(arena == nullptr) ? Allocate(size) : arena->AllocateAligned(size);
249249
memcpy(split, default_split, size);
250250
return split;
251251
}

src/google/protobuf/message_lite.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,13 +1450,7 @@ PROTOBUF_ALWAYS_INLINE MessageLite* MessageCreator::New(
14501450
if (arena != nullptr) {
14511451
mem = arena->AllocateAligned(allocation_size_);
14521452
} else {
1453-
#if ABSL_HAVE_BUILTIN(__builtin_operator_new)
1454-
// Allows the compiler to merge or optimize away the allocation even if it
1455-
// would violate the observability guarantees of ::operator new.
1456-
mem = __builtin_operator_new(allocation_size_);
1457-
#else
1458-
mem = ::operator new(allocation_size_);
1459-
#endif
1453+
mem = Allocate(allocation_size_);
14601454
}
14611455
return PlacementNew(prototype_for_func, prototype_for_copy, mem, arena);
14621456
}

src/google/protobuf/port.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,18 @@ inline void SetAllocateAtLeastHook(AllocateAtLeastHookFn fn, void* context) {}
134134

135135
#endif // !NDEBUG && ABSL_HAVE_THREAD_LOCAL && __cpp_inline_variables
136136

137+
// Allocates `size` bytes. This wrapper allows memory allocations to be
138+
// optimized by the compiler since `operator new` is considered observable.
139+
inline void* Allocate(size_t size) {
140+
#if ABSL_HAVE_BUILTIN(__builtin_operator_new)
141+
// Allows the compiler to merge or optimize away the allocation even if it
142+
// would violate the observability guarantees of ::operator new.
143+
return __builtin_operator_new(size);
144+
#else
145+
return ::operator new(size);
146+
#endif
147+
}
148+
137149
// Allocates at least `size` bytes. This function follows the c++ language
138150
// proposal from D0901R10 (http://wg21.link/D0901R10) and will be implemented
139151
// in terms of the new operator new semantics when available. The allocated
@@ -145,7 +157,7 @@ inline SizedPtr AllocateAtLeast(size_t size) {
145157
return allocate_at_least_hook(size, allocate_at_least_hook_context);
146158
}
147159
#endif // !NDEBUG && ABSL_HAVE_THREAD_LOCAL && __cpp_inline_variables
148-
return {::operator new(size), size};
160+
return {Allocate(size), size};
149161
}
150162

151163
inline void SizedDelete(void* p, size_t size) {

0 commit comments

Comments
 (0)