@@ -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+
16041608void 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