llvm.org GIT mirror llvm / 81bc6fb
raw_svector_ostream: grow and reserve atomically Including the scratch buffer size in the initial reservation eliminates the subsequent malloc+move operation and offers a healthier constant growth with less memory wastage. When doing this, take care to avoid invalidating the source buffer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@212816 91177308-0d34-0410-b5e6-96231b3b80d8 Alp Toker 5 years ago
1 changed file(s) with 19 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
728728 }
729729
730730 void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) {
731 // If we're writing bytes from the end of the buffer into the smallvector, we
732 // don't need to copy the bytes, just commit the bytes because they are
733 // already in the right place.
734 if (Ptr == OS.end()) {
735 assert(OS.size() + Size <= OS.capacity() && "Invalid write_impl() call!");
736 OS.set_size(OS.size() + Size);
731 size_t NewSize = OS.size() + Size;
732 size_t NewReservation = NewSize + 64;
733
734 bool NoOverlap = Ptr + Size < OS.begin() || Ptr > OS.begin() + OS.capacity();
735
736 if (NoOverlap) {
737 assert(!GetNumBytesInBuffer());
738 OS.reserve(NewReservation);
739 memcpy(OS.end(), Ptr, Size);
740 OS.set_size(NewSize);
741 } else if (Ptr == OS.end()) {
742 // Grow the buffer to include the scratch area without copying.
743 assert(NewSize <= OS.capacity() && "Invalid write_impl() call!");
744 OS.set_size(NewSize);
745 OS.reserve(NewReservation);
737746 } else {
738 assert(GetNumBytesInBuffer() == 0 &&
739 "Should be writing from buffer if some bytes in it");
740 // Otherwise, do copy the bytes.
741 OS.append(Ptr, Ptr+Size);
742 }
743
744 // Grow the vector if necessary.
745 if (OS.capacity() - OS.size() < 64)
746 OS.reserve(OS.capacity() * 2);
747
748 // Update the buffer position.
747 OS.append(Ptr, Ptr + Size);
748 OS.reserve(NewReservation);
749 }
750
749751 SetBuffer(OS.end(), OS.capacity() - OS.size());
750752 }
751753