diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc index d8a9d481d2..0626e15736 100644 --- a/src/google/protobuf/repeated_field.cc +++ b/src/google/protobuf/repeated_field.cc @@ -12,6 +12,8 @@ #include "google/protobuf/repeated_field.h" #include +#include +#include #include #include "absl/log/absl_check.h" @@ -28,8 +30,8 @@ namespace protobuf { template <> PROTOBUF_EXPORT_TEMPLATE_DEFINE size_t RepeatedField::SpaceUsedExcludingSelfLong() const { - size_t result = current_size_ * sizeof(absl::Cord); - for (int i = 0; i < current_size_; i++) { + size_t result = size() * sizeof(absl::Cord); + for (int i = 0; i < size(); i++) { // Estimate only. result += Get(i).size(); } diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 5351846558..a8eb940ce7 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -295,8 +295,8 @@ class RepeatedField final // Note: this can be inaccurate for split default fields so we make this // function non-const. inline Arena* GetArena() { - return (total_size_ == 0) ? static_cast(arena_or_elements_) - : rep()->arena; + return Capacity() == 0 ? static_cast(arena_or_elements_) + : rep()->arena; } // For internal use only. @@ -333,6 +333,9 @@ class RepeatedField final RepeatedField(Arena* arena, RepeatedField&& rhs); + void set_size(int s) { size_ = s; } + void set_capacity(int c) { capacity_ = c; } + // Swaps entire contents with "other". Should be called only if the caller can // guarantee that both repeated fields are on the same arena or are on the // heap. Swapping between different arenas is disallowed and caught by a @@ -373,9 +376,9 @@ class RepeatedField final // Reserves space to expand the field to at least the given size. // If the array is grown, it will always be at least doubled in size. // If `annotate_size` is true (the default), then this function will annotate - // the old container from `current_size` to `total_size_` (unpoison memory) + // the old container from `current_size` to `capacity_` (unpoison memory) // directly before it is being released, and annotate the new container from - // `total_size_` to `current_size` (poison unused memory). + // `capacity_` to `current_size` (poison unused memory). void Grow(int current_size, int new_size); void GrowNoAnnotate(int current_size, int new_size); @@ -386,7 +389,7 @@ class RepeatedField final void AnnotateSize(int old_size, int new_size) const { if (old_size != new_size) { ABSL_ANNOTATE_CONTIGUOUS_CONTAINER( - unsafe_elements(), unsafe_elements() + total_size_, + unsafe_elements(), unsafe_elements() + Capacity(), unsafe_elements() + old_size, unsafe_elements() + new_size); if (new_size < old_size) { ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED( @@ -396,21 +399,21 @@ class RepeatedField final } } - // Replaces current_size_ with new_size and returns the previous value of - // current_size_. This function is intended to be the only place where - // current_size_ is modified, with the exception of `AddInputIterator()` + // Replaces size_ with new_size and returns the previous value of + // size_. This function is intended to be the only place where + // size_ is modified, with the exception of `AddInputIterator()` // where the size of added items is not known in advance. inline int ExchangeCurrentSize(int new_size) { - const int prev_size = current_size_; + const int prev_size = size(); AnnotateSize(prev_size, new_size); - current_size_ = new_size; + set_size(new_size); return prev_size; } // Returns a pointer to elements array. // pre-condition: the array must have been allocated. Element* elements() const { - ABSL_DCHECK_GT(total_size_, 0); + ABSL_DCHECK_GT(Capacity(), 0); // Because of above pre-condition this cast is safe. return unsafe_elements(); } @@ -432,7 +435,7 @@ class RepeatedField final // Internal helper to delete all elements and deallocate the storage. template void InternalDeallocate() { - const size_t bytes = total_size_ * sizeof(Element) + kRepHeaderSize; + const size_t bytes = Capacity() * sizeof(Element) + kRepHeaderSize; if (rep()->arena == nullptr) { internal::SizedDelete(rep(), bytes); } else if (!in_destructor) { @@ -452,9 +455,9 @@ class RepeatedField final // empty (common case), and add only an 8-byte header to the elements array // when non-empty. We make sure to place the size fields directly in the // RepeatedField class to avoid costly cache misses due to the indirection. - int current_size_; - int total_size_; - // If total_size_ == 0 this points to an Arena otherwise it points to the + int size_; + int capacity_; + // If capacity_ == 0 this points to an Arena otherwise it points to the // elements member of a Rep struct. Using this invariant allows the storage of // the arena pointer without an extra allocation in the constructor. void* arena_or_elements_; @@ -464,22 +467,22 @@ class RepeatedField final template constexpr RepeatedField::RepeatedField() - : current_size_(0), total_size_(0), arena_or_elements_(nullptr) { + : size_(0), capacity_(0), arena_or_elements_(nullptr) { StaticValidityCheck(); } template inline RepeatedField::RepeatedField(Arena* arena) - : current_size_(0), total_size_(0), arena_or_elements_(arena) { + : size_(0), capacity_(0), arena_or_elements_(arena) { StaticValidityCheck(); } template inline RepeatedField::RepeatedField(Arena* arena, const RepeatedField& rhs) - : current_size_(0), total_size_(0), arena_or_elements_(arena) { + : size_(0), capacity_(0), arena_or_elements_(arena) { StaticValidityCheck(); - if (auto size = rhs.current_size_) { + if (auto size = rhs.size()) { Grow(0, size); ExchangeCurrentSize(size); UninitializedCopyN(rhs.elements(), size, unsafe_elements()); @@ -489,7 +492,7 @@ inline RepeatedField::RepeatedField(Arena* arena, template template RepeatedField::RepeatedField(Iter begin, Iter end) - : current_size_(0), total_size_(0), arena_or_elements_(nullptr) { + : size_(0), capacity_(0), arena_or_elements_(nullptr) { StaticValidityCheck(); Add(begin, end); } @@ -503,8 +506,8 @@ RepeatedField::~RepeatedField() { auto arena = GetArena(); if (arena) (void)arena->SpaceAllocated(); #endif - if (total_size_ > 0) { - Destroy(unsafe_elements(), unsafe_elements() + current_size_); + if (Capacity() > 0) { + Destroy(unsafe_elements(), unsafe_elements() + size()); InternalDeallocate(); } } @@ -553,42 +556,41 @@ inline RepeatedField& RepeatedField::operator=( template inline bool RepeatedField::empty() const { - return current_size_ == 0; + return size() == 0; } template inline int RepeatedField::size() const { - return current_size_; + return size_; } template inline int RepeatedField::Capacity() const { - return total_size_; + return capacity_; } template inline void RepeatedField::AddAlreadyReserved(Element value) { - ABSL_DCHECK_LT(current_size_, total_size_); - void* p = elements() + ExchangeCurrentSize(current_size_ + 1); + ABSL_DCHECK_LT(size(), Capacity()); + void* p = elements() + ExchangeCurrentSize(size() + 1); ::new (p) Element(std::move(value)); } template inline Element* RepeatedField::AddAlreadyReserved() ABSL_ATTRIBUTE_LIFETIME_BOUND { - ABSL_DCHECK_LT(current_size_, total_size_); + ABSL_DCHECK_LT(size(), Capacity()); // new (p) compiles into nothing: this is intentional as this // function is documented to return uninitialized data for trivial types. - void* p = elements() + ExchangeCurrentSize(current_size_ + 1); + void* p = elements() + ExchangeCurrentSize(size() + 1); return ::new (p) Element; } template inline Element* RepeatedField::AddNAlreadyReserved(int n) ABSL_ATTRIBUTE_LIFETIME_BOUND { - ABSL_DCHECK_GE(total_size_ - current_size_, n) - << total_size_ << ", " << current_size_; - Element* p = unsafe_elements() + ExchangeCurrentSize(current_size_ + n); + ABSL_DCHECK_GE(Capacity() - size(), n) << Capacity() << ", " << size(); + Element* p = unsafe_elements() + ExchangeCurrentSize(size() + n); for (Element *begin = p, *end = p + n; begin != end; ++begin) { new (static_cast(begin)) Element; } @@ -598,12 +600,12 @@ inline Element* RepeatedField::AddNAlreadyReserved(int n) template inline void RepeatedField::Resize(int new_size, const Element& value) { ABSL_DCHECK_GE(new_size, 0); - if (new_size > current_size_) { - if (new_size > total_size_) Grow(current_size_, new_size); + if (new_size > size()) { + if (new_size > Capacity()) Grow(size(), new_size); Element* first = elements() + ExchangeCurrentSize(new_size); - std::uninitialized_fill(first, elements() + current_size_, value); - } else if (new_size < current_size_) { - Destroy(unsafe_elements() + new_size, unsafe_elements() + current_size_); + std::uninitialized_fill(first, elements() + size(), value); + } else if (new_size < size()) { + Destroy(unsafe_elements() + new_size, unsafe_elements() + size()); ExchangeCurrentSize(new_size); } } @@ -612,7 +614,7 @@ template inline const Element& RepeatedField::Get(int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_DCHECK_GE(index, 0); - ABSL_DCHECK_LT(index, current_size_); + ABSL_DCHECK_LT(index, size()); return elements()[index]; } @@ -620,7 +622,7 @@ template inline const Element& RepeatedField::at(int index) const ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_CHECK_GE(index, 0); - ABSL_CHECK_LT(index, current_size_); + ABSL_CHECK_LT(index, size()); return elements()[index]; } @@ -628,7 +630,7 @@ template inline Element& RepeatedField::at(int index) ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_CHECK_GE(index, 0); - ABSL_CHECK_LT(index, current_size_); + ABSL_CHECK_LT(index, size()); return elements()[index]; } @@ -636,85 +638,85 @@ template inline Element* RepeatedField::Mutable(int index) ABSL_ATTRIBUTE_LIFETIME_BOUND { ABSL_DCHECK_GE(index, 0); - ABSL_DCHECK_LT(index, current_size_); + ABSL_DCHECK_LT(index, size()); return &elements()[index]; } template inline void RepeatedField::Set(int index, const Element& value) { ABSL_DCHECK_GE(index, 0); - ABSL_DCHECK_LT(index, current_size_); + ABSL_DCHECK_LT(index, size()); elements()[index] = value; } template inline void RepeatedField::Add(Element value) { - int total_size = total_size_; + int capacity = Capacity(); Element* elem = unsafe_elements(); - if (ABSL_PREDICT_FALSE(current_size_ == total_size)) { - Grow(current_size_, current_size_ + 1); - total_size = total_size_; + if (ABSL_PREDICT_FALSE(size() == capacity)) { + Grow(size(), size() + 1); + capacity = Capacity(); elem = unsafe_elements(); } - int new_size = current_size_ + 1; + int new_size = size() + 1; void* p = elem + ExchangeCurrentSize(new_size); ::new (p) Element(std::move(value)); // The below helps the compiler optimize dense loops. - ABSL_ASSUME(new_size == current_size_); + ABSL_ASSUME(new_size == size_); ABSL_ASSUME(elem == arena_or_elements_); - ABSL_ASSUME(total_size == total_size_); + ABSL_ASSUME(capacity == capacity_); } template inline Element* RepeatedField::Add() ABSL_ATTRIBUTE_LIFETIME_BOUND { - if (ABSL_PREDICT_FALSE(current_size_ == total_size_)) { - Grow(current_size_, current_size_ + 1); + if (ABSL_PREDICT_FALSE(size() == Capacity())) { + Grow(size(), size() + 1); } - void* p = unsafe_elements() + ExchangeCurrentSize(current_size_ + 1); + void* p = unsafe_elements() + ExchangeCurrentSize(size() + 1); return ::new (p) Element; } template template inline void RepeatedField::AddForwardIterator(Iter begin, Iter end) { - int total_size = total_size_; + int capacity = Capacity(); Element* elem = unsafe_elements(); - int new_size = current_size_ + static_cast(std::distance(begin, end)); - if (ABSL_PREDICT_FALSE(new_size > total_size)) { - Grow(current_size_, new_size); + int new_size = size() + static_cast(std::distance(begin, end)); + if (ABSL_PREDICT_FALSE(new_size > capacity)) { + Grow(size(), new_size); elem = unsafe_elements(); - total_size = total_size_; + capacity = Capacity(); } UninitializedCopy(begin, end, elem + ExchangeCurrentSize(new_size)); // The below helps the compiler optimize dense loops. - ABSL_ASSUME(new_size == current_size_); + ABSL_ASSUME(new_size == size_); ABSL_ASSUME(elem == arena_or_elements_); - ABSL_ASSUME(total_size == total_size_); + ABSL_ASSUME(capacity == capacity_); } template template inline void RepeatedField::AddInputIterator(Iter begin, Iter end) { - Element* first = unsafe_elements() + current_size_; - Element* last = unsafe_elements() + total_size_; - AnnotateSize(current_size_, total_size_); + Element* first = unsafe_elements() + size(); + Element* last = unsafe_elements() + Capacity(); + AnnotateSize(size(), Capacity()); while (begin != end) { if (ABSL_PREDICT_FALSE(first == last)) { int current_size = first - unsafe_elements(); GrowNoAnnotate(current_size, current_size + 1); first = unsafe_elements() + current_size; - last = unsafe_elements() + total_size_; + last = unsafe_elements() + Capacity(); } ::new (static_cast(first)) Element(*begin); ++begin; ++first; } - current_size_ = first - unsafe_elements(); - AnnotateSize(total_size_, current_size_); + set_size(first - unsafe_elements()); + AnnotateSize(Capacity(), size()); } template @@ -731,9 +733,9 @@ inline void RepeatedField::Add(Iter begin, Iter end) { template inline void RepeatedField::RemoveLast() { - ABSL_DCHECK_GT(current_size_, 0); - elements()[current_size_ - 1].~Element(); - ExchangeCurrentSize(current_size_ - 1); + ABSL_DCHECK_GT(size(), 0); + elements()[size() - 1].~Element(); + ExchangeCurrentSize(size() - 1); } template @@ -741,33 +743,32 @@ void RepeatedField::ExtractSubrange(int start, int num, Element* elements) { ABSL_DCHECK_GE(start, 0); ABSL_DCHECK_GE(num, 0); - ABSL_DCHECK_LE(start + num, this->current_size_); + ABSL_DCHECK_LE(start + num, size()); // Save the values of the removed elements if requested. if (elements != nullptr) { - for (int i = 0; i < num; ++i) elements[i] = this->Get(i + start); + for (int i = 0; i < num; ++i) elements[i] = Get(i + start); } // Slide remaining elements down to fill the gap. if (num > 0) { - for (int i = start + num; i < this->current_size_; ++i) - this->Set(i - num, this->Get(i)); - this->Truncate(this->current_size_ - num); + for (int i = start + num; i < size(); ++i) Set(i - num, Get(i)); + Truncate(size() - num); } } template inline void RepeatedField::Clear() { - Destroy(unsafe_elements(), unsafe_elements() + current_size_); + Destroy(unsafe_elements(), unsafe_elements() + size()); ExchangeCurrentSize(0); } template inline void RepeatedField::MergeFrom(const RepeatedField& other) { ABSL_DCHECK_NE(&other, this); - if (auto size = other.current_size_) { - Reserve(current_size_ + size); - Element* dst = elements() + ExchangeCurrentSize(current_size_ + size); + if (auto size = other.size()) { + Reserve(this->size() + size); + Element* dst = elements() + ExchangeCurrentSize(this->size() + size); UninitializedCopyN(other.elements(), size, dst); } } @@ -822,7 +823,7 @@ inline void RepeatedField::InternalSwap( // Swap all fields at once. static_assert(std::is_standard_layout>::value, "offsetof() requires standard layout before c++17"); - static constexpr size_t kOffset = offsetof(RepeatedField, current_size_); + static constexpr size_t kOffset = offsetof(RepeatedField, size_); internal::memswaparena_or_elements_) - kOffset>( reinterpret_cast(this) + kOffset, @@ -877,22 +878,22 @@ RepeatedField::cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND { template inline typename RepeatedField::iterator RepeatedField::end() ABSL_ATTRIBUTE_LIFETIME_BOUND { - return iterator(unsafe_elements() + current_size_); + return iterator(unsafe_elements() + size()); } template inline typename RepeatedField::const_iterator RepeatedField::end() const ABSL_ATTRIBUTE_LIFETIME_BOUND { - return const_iterator(unsafe_elements() + current_size_); + return const_iterator(unsafe_elements() + size()); } template inline typename RepeatedField::const_iterator RepeatedField::cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { - return const_iterator(unsafe_elements() + current_size_); + return const_iterator(unsafe_elements() + size()); } template inline size_t RepeatedField::SpaceUsedExcludingSelfLong() const { - return total_size_ > 0 ? (total_size_ * sizeof(Element) + kRepHeaderSize) : 0; + return Capacity() > 0 ? (Capacity() * sizeof(Element) + kRepHeaderSize) : 0; } namespace internal { @@ -926,8 +927,8 @@ inline int CalculateReserveSize(int total_size, int new_size) { template void RepeatedField::Reserve(int new_size) { - if (ABSL_PREDICT_FALSE(new_size > total_size_)) { - Grow(current_size_, new_size); + if (ABSL_PREDICT_FALSE(new_size > Capacity())) { + Grow(size(), new_size); } } @@ -936,12 +937,12 @@ void RepeatedField::Reserve(int new_size) { template PROTOBUF_NOINLINE void RepeatedField::GrowNoAnnotate(int current_size, int new_size) { - ABSL_DCHECK_GT(new_size, total_size_); + ABSL_DCHECK_GT(new_size, Capacity()); Rep* new_rep; Arena* arena = GetArena(); - new_size = internal::CalculateReserveSize( - total_size_, new_size); + new_size = internal::CalculateReserveSize(Capacity(), + new_size); ABSL_DCHECK_LE( static_cast(new_size), @@ -964,7 +965,7 @@ PROTOBUF_NOINLINE void RepeatedField::GrowNoAnnotate(int current_size, } new_rep->arena = arena; - if (total_size_ > 0) { + if (Capacity() > 0) { if (current_size > 0) { Element* pnew = new_rep->elements(); Element* pold = elements(); @@ -981,7 +982,7 @@ PROTOBUF_NOINLINE void RepeatedField::GrowNoAnnotate(int current_size, InternalDeallocate(); } - total_size_ = new_size; + set_capacity(new_size); arena_or_elements_ = new_rep->elements(); } @@ -993,16 +994,16 @@ PROTOBUF_NOINLINE void RepeatedField::GrowNoAnnotate(int current_size, template PROTOBUF_NOINLINE void RepeatedField::Grow(int current_size, int new_size) { - AnnotateSize(current_size, total_size_); + AnnotateSize(current_size, Capacity()); GrowNoAnnotate(current_size, new_size); - AnnotateSize(total_size_, current_size); + AnnotateSize(Capacity(), current_size); } template inline void RepeatedField::Truncate(int new_size) { - ABSL_DCHECK_LE(new_size, current_size_); - if (new_size < current_size_) { - Destroy(unsafe_elements() + new_size, unsafe_elements() + current_size_); + ABSL_DCHECK_LE(new_size, size()); + if (new_size < size()) { + Destroy(unsafe_elements() + new_size, unsafe_elements() + size()); ExchangeCurrentSize(new_size); } } diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index 45fe6adfa7..144e17c931 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -1240,8 +1240,8 @@ TEST(RepeatedField, HardenAgainstBadTruncate) { for (int size = 0; size < 10; ++size) { field.Truncate(size); #if GTEST_HAS_DEATH_TEST - EXPECT_DEBUG_DEATH(field.Truncate(size + 1), "new_size <= current_size_"); - EXPECT_DEBUG_DEATH(field.Truncate(size + 2), "new_size <= current_size_"); + EXPECT_DEBUG_DEATH(field.Truncate(size + 1), "new_size <= size"); + EXPECT_DEBUG_DEATH(field.Truncate(size + 2), "new_size <= size"); #elif defined(NDEBUG) field.Truncate(size + 1); field.Truncate(size + 1);