Skip to content

Commit 5ac8ee1

Browse files
ezbrcopybara-github
authored andcommitted
Return backing array memory to arena in ExtensionSet.
Note: in 64-bit platforms, sizeof(ExtensionSet::KeyValue)==32. PiperOrigin-RevId: 658022141
1 parent 06a520c commit 5ac8ee1

File tree

2 files changed

+21
-5
lines changed

2 files changed

+21
-5
lines changed

src/google/protobuf/arena.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ template <typename Key, typename T>
5757
class Map;
5858
namespace internal {
5959
struct RepeatedFieldBase;
60+
class ExtensionSet;
6061
} // namespace internal
6162

6263
namespace arena_metrics {
@@ -648,7 +649,8 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final {
648649
template <typename>
649650
friend class RepeatedField; // For ReturnArrayMemory
650651
friend class internal::RepeatedPtrFieldBase; // For ReturnArrayMemory
651-
friend class internal::UntypedMapBase; // For ReturnArenaMemory
652+
friend class internal::UntypedMapBase; // For ReturnArrayMemory
653+
friend class internal::ExtensionSet; // For ReturnArrayMemory
652654

653655
friend struct internal::ArenaTestPeer;
654656
};

src/google/protobuf/extension_set.cc

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,10 @@ std::pair<ExtensionSet::Extension*, bool> ExtensionSet::Insert(int key) {
16011601
return Insert(key);
16021602
}
16031603

1604+
namespace {
1605+
constexpr bool IsPowerOfTwo(size_t n) { return (n & (n - 1)) == 0; }
1606+
} // namespace
1607+
16041608
void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) {
16051609
if (PROTOBUF_PREDICT_FALSE(is_large())) {
16061610
return; // LargeMap does not have a "reserve" method.
@@ -1614,8 +1618,8 @@ void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) {
16141618
new_flat_capacity = new_flat_capacity == 0 ? 1 : new_flat_capacity * 4;
16151619
} while (new_flat_capacity < minimum_new_capacity);
16161620

1617-
const KeyValue* begin = flat_begin();
1618-
const KeyValue* end = flat_end();
1621+
KeyValue* begin = flat_begin();
1622+
KeyValue* end = flat_end();
16191623
AllocatedData new_map;
16201624
Arena* const arena = arena_;
16211625
if (new_flat_capacity > kMaximumFlatCapacity) {
@@ -1631,8 +1635,18 @@ void ExtensionSet::GrowCapacity(size_t minimum_new_capacity) {
16311635
std::copy(begin, end, new_map.flat);
16321636
}
16331637

1634-
if (arena == nullptr) {
1635-
DeleteFlatMap(begin, flat_capacity_);
1638+
// ReturnArrayMemory is more efficient with power-of-2 bytes, and
1639+
// sizeof(KeyValue) is a power-of-2 on 64-bit platforms. flat_capacity_ is
1640+
// always a power-of-2.
1641+
ABSL_DCHECK(IsPowerOfTwo(sizeof(KeyValue)) || sizeof(void*) != 8)
1642+
<< sizeof(KeyValue) << " " << sizeof(void*);
1643+
ABSL_DCHECK(IsPowerOfTwo(flat_capacity_));
1644+
if (flat_capacity_ > 0) {
1645+
if (arena == nullptr) {
1646+
DeleteFlatMap(begin, flat_capacity_);
1647+
} else {
1648+
arena->ReturnArrayMemory(begin, sizeof(KeyValue) * flat_capacity_);
1649+
}
16361650
}
16371651
flat_capacity_ = new_flat_capacity;
16381652
map_ = new_map;

0 commit comments

Comments
 (0)