Commit a8ba451f authored by Yutaka Hirano's avatar Yutaka Hirano Committed by Commit Bot

SharedBuffer cleanup

This CL:
 - introduces Segment to remove ad-hoc AllocateSegment / FreeSegment
   calls,
 - removes the const qualifier from Data to remove mutable from
   members,
 - inlines some functions, and
 - includes miscellaneous algorithmic simplification.

This CL doesn't change the behavior, and is not expected to improve or
regress performance.

Bug: None
Change-Id: If1700dd4ae430edbfbd8985836cd73505d441eb4
Reviewed-on: https://chromium-review.googlesource.com/1127573
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
Reviewed-by: default avatarFlorin Malita <fmalita@chromium.org>
Cr-Commit-Position: refs/heads/master@{#573495}
parent baa43bde
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
#include "third_party/blink/renderer/platform/shared_buffer.h" #include "third_party/blink/renderer/platform/shared_buffer.h"
#include <memory>
#include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h"
#include "third_party/blink/renderer/platform/wtf/text/unicode.h" #include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/text/utf8.h" #include "third_party/blink/renderer/platform/wtf/text/utf8.h"
...@@ -33,6 +35,8 @@ ...@@ -33,6 +35,8 @@
namespace blink { namespace blink {
constexpr unsigned SharedBuffer::kSegmentSize;
static inline size_t SegmentIndex(size_t position) { static inline size_t SegmentIndex(size_t position) {
return position / SharedBuffer::kSegmentSize; return position / SharedBuffer::kSegmentSize;
} }
...@@ -41,14 +45,24 @@ static inline size_t OffsetInSegment(size_t position) { ...@@ -41,14 +45,24 @@ static inline size_t OffsetInSegment(size_t position) {
return position % SharedBuffer::kSegmentSize; return position % SharedBuffer::kSegmentSize;
} }
static inline char* AllocateSegment() { class SharedBuffer::Segment final {
return static_cast<char*>(WTF::Partitions::FastMalloc( public:
SharedBuffer::kSegmentSize, "blink::SharedBuffer")); Segment() {
} ptr_.reset(static_cast<char*>(WTF::Partitions::FastMalloc(
SharedBuffer::kSegmentSize, "blink::SharedBuffer")));
}
~Segment() = default;
Segment(Segment&&) = default;
static inline void FreeSegment(char* p) { char* get() { return ptr_.get(); }
WTF::Partitions::FastFree(p); const char* get() const { return ptr_.get(); }
}
private:
struct Deleter {
void operator()(char* p) const { WTF::Partitions::FastFree(p); }
};
std::unique_ptr<char[], Deleter> ptr_;
};
SharedBuffer::SharedBuffer() : size_(0) {} SharedBuffer::SharedBuffer() : size_(0) {}
...@@ -61,9 +75,7 @@ SharedBuffer::SharedBuffer(const char* data, size_t size) : size_(size) { ...@@ -61,9 +75,7 @@ SharedBuffer::SharedBuffer(const char* data, size_t size) : size_(size) {
SharedBuffer::SharedBuffer(const unsigned char* data, size_t size) SharedBuffer::SharedBuffer(const unsigned char* data, size_t size)
: SharedBuffer(reinterpret_cast<const char*>(data), size) {} : SharedBuffer(reinterpret_cast<const char*>(data), size) {}
SharedBuffer::~SharedBuffer() { SharedBuffer::~SharedBuffer() = default;
Clear();
}
scoped_refptr<SharedBuffer> SharedBuffer::AdoptVector(Vector<char>& vector) { scoped_refptr<SharedBuffer> SharedBuffer::AdoptVector(Vector<char>& vector) {
scoped_refptr<SharedBuffer> buffer = Create(); scoped_refptr<SharedBuffer> buffer = Create();
...@@ -72,11 +84,7 @@ scoped_refptr<SharedBuffer> SharedBuffer::AdoptVector(Vector<char>& vector) { ...@@ -72,11 +84,7 @@ scoped_refptr<SharedBuffer> SharedBuffer::AdoptVector(Vector<char>& vector) {
return buffer; return buffer;
} }
size_t SharedBuffer::size() const { const char* SharedBuffer::Data() {
return size_;
}
const char* SharedBuffer::Data() const {
MergeSegmentsIntoBuffer(); MergeSegmentsIntoBuffer();
return buffer_.data(); return buffer_.data();
} }
...@@ -104,66 +112,43 @@ void SharedBuffer::AppendInternal(const char* data, size_t length) { ...@@ -104,66 +112,43 @@ void SharedBuffer::AppendInternal(const char* data, size_t length) {
return; return;
} }
char* segment; while (length > 0) {
if (!position_in_segment) { if (!position_in_segment)
segment = AllocateSegment(); segments_.push_back(Segment());
segments_.push_back(segment);
} else
segment = segments_.back() + position_in_segment;
size_t segment_free_space = kSegmentSize - position_in_segment;
size_t bytes_to_copy = std::min(length, segment_free_space);
for (;;) { size_t bytes_to_copy = std::min(length, kSegmentSize - position_in_segment);
memcpy(segment, data, bytes_to_copy); memcpy(segments_.back().get() + position_in_segment, data, bytes_to_copy);
if (length == bytes_to_copy)
break;
length -= bytes_to_copy;
data += bytes_to_copy; data += bytes_to_copy;
segment = AllocateSegment(); length -= bytes_to_copy;
segments_.push_back(segment); position_in_segment = 0;
bytes_to_copy = std::min(length, static_cast<size_t>(kSegmentSize));
} }
} }
void SharedBuffer::Append(const Vector<char>& data) {
Append(data.data(), data.size());
}
void SharedBuffer::Clear() { void SharedBuffer::Clear() {
for (size_t i = 0; i < segments_.size(); ++i)
FreeSegment(segments_[i]);
segments_.clear(); segments_.clear();
size_ = 0; size_ = 0;
buffer_.clear(); buffer_.clear();
} }
void SharedBuffer::MergeSegmentsIntoBuffer() const { void SharedBuffer::MergeSegmentsIntoBuffer() {
size_t buffer_size = buffer_.size(); size_t bytes_left = size_ - buffer_.size();
if (size_ > buffer_size) { for (const auto& segment : segments_) {
size_t bytes_left = size_ - buffer_size; size_t bytes_to_copy = std::min<size_t>(bytes_left, kSegmentSize);
for (size_t i = 0; i < segments_.size(); ++i) { buffer_.Append(segment.get(), bytes_to_copy);
size_t bytes_to_copy = bytes_left -= bytes_to_copy;
std::min(bytes_left, static_cast<size_t>(kSegmentSize));
buffer_.Append(segments_[i], bytes_to_copy);
bytes_left -= bytes_to_copy;
FreeSegment(segments_[i]);
}
segments_.clear();
} }
segments_.clear();
} }
size_t SharedBuffer::GetSomeDataInternal(const char*& some_data, size_t SharedBuffer::GetSomeDataInternal(const char*& some_data,
size_t position) const { size_t position) const {
size_t total_size = size(); if (position >= size_) {
if (position >= total_size) {
some_data = nullptr; some_data = nullptr;
return 0; return 0;
} }
SECURITY_DCHECK(position < size_); DCHECK(position < size_);
size_t consecutive_size = buffer_.size(); size_t consecutive_size = buffer_.size();
if (position < consecutive_size) { if (position < consecutive_size) {
some_data = buffer_.data() + position; some_data = buffer_.data() + position;
...@@ -171,20 +156,14 @@ size_t SharedBuffer::GetSomeDataInternal(const char*& some_data, ...@@ -171,20 +156,14 @@ size_t SharedBuffer::GetSomeDataInternal(const char*& some_data,
} }
position -= consecutive_size; position -= consecutive_size;
size_t segments = segments_.size(); size_t index = SegmentIndex(position);
size_t max_segmented_size = segments * kSegmentSize; size_t bytes_left = size_ - consecutive_size;
size_t segment = SegmentIndex(position); size_t position_in_segment = OffsetInSegment(position);
if (segment < segments) {
size_t bytes_left = total_size - consecutive_size; DCHECK_LT(index, segments_.size());
size_t segmented_size = std::min(max_segmented_size, bytes_left); some_data = segments_[index].get() + position_in_segment;
return index == segments_.size() - 1 ? bytes_left - position
size_t position_in_segment = OffsetInSegment(position); : kSegmentSize - position_in_segment;
some_data = segments_[segment] + position_in_segment;
return segment == segments - 1 ? segmented_size - position
: kSegmentSize - position_in_segment;
}
NOTREACHED();
return 0;
} }
bool SharedBuffer::GetBytesInternal(void* dest, size_t byte_length) const { bool SharedBuffer::GetBytesInternal(void* dest, size_t byte_length) const {
...@@ -211,8 +190,7 @@ bool SharedBuffer::GetBytesInternal(void* dest, size_t byte_length) const { ...@@ -211,8 +190,7 @@ bool SharedBuffer::GetBytesInternal(void* dest, size_t byte_length) const {
} }
sk_sp<SkData> SharedBuffer::GetAsSkData() const { sk_sp<SkData> SharedBuffer::GetAsSkData() const {
size_t buffer_length = size(); sk_sp<SkData> data = SkData::MakeUninitialized(size());
sk_sp<SkData> data = SkData::MakeUninitialized(buffer_length);
char* buffer = static_cast<char*>(data->writable_data()); char* buffer = static_cast<char*>(data->writable_data());
const char* segment = nullptr; const char* segment = nullptr;
size_t position = 0; size_t position = 0;
...@@ -221,11 +199,7 @@ sk_sp<SkData> SharedBuffer::GetAsSkData() const { ...@@ -221,11 +199,7 @@ sk_sp<SkData> SharedBuffer::GetAsSkData() const {
position += segment_size; position += segment_size;
} }
if (position != buffer_length) { DCHECK_EQ(position, size());
NOTREACHED();
// Don't return the incomplete SkData.
return nullptr;
}
return data; return data;
} }
......
...@@ -45,7 +45,7 @@ class WebProcessMemoryDump; ...@@ -45,7 +45,7 @@ class WebProcessMemoryDump;
class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> { class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
public: public:
enum : unsigned { kSegmentSize = 0x1000 }; static constexpr unsigned kSegmentSize = 0x1000;
static scoped_refptr<SharedBuffer> Create() { static scoped_refptr<SharedBuffer> Create() {
return base::AdoptRef(new SharedBuffer); return base::AdoptRef(new SharedBuffer);
...@@ -80,9 +80,9 @@ class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> { ...@@ -80,9 +80,9 @@ class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
// Calling this function will force internal segmented buffers to be merged // Calling this function will force internal segmented buffers to be merged
// into a flat buffer. Use getSomeData() whenever possible for better // into a flat buffer. Use getSomeData() whenever possible for better
// performance. // performance.
const char* Data() const; const char* Data();
size_t size() const; size_t size() const { return size_; }
bool IsEmpty() const { return !size(); } bool IsEmpty() const { return !size(); }
...@@ -93,7 +93,7 @@ class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> { ...@@ -93,7 +93,7 @@ class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t); ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t);
AppendInternal(data, size); AppendInternal(data, size);
} }
void Append(const Vector<char>&); void Append(const Vector<char>& data) { Append(data.data(), data.size()); }
void Clear(); void Clear();
...@@ -177,21 +177,23 @@ class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> { ...@@ -177,21 +177,23 @@ class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
}; };
private: private:
class Segment;
SharedBuffer(); SharedBuffer();
explicit SharedBuffer(size_t); explicit SharedBuffer(size_t);
SharedBuffer(const char*, size_t); SharedBuffer(const char*, size_t);
SharedBuffer(const unsigned char*, size_t); SharedBuffer(const unsigned char*, size_t);
// See SharedBuffer::data(). // See SharedBuffer::data().
void MergeSegmentsIntoBuffer() const; void MergeSegmentsIntoBuffer();
void AppendInternal(const char* data, size_t); void AppendInternal(const char* data, size_t);
bool GetBytesInternal(void* dest, size_t) const; bool GetBytesInternal(void* dest, size_t) const;
size_t GetSomeDataInternal(const char*& data, size_t position) const; size_t GetSomeDataInternal(const char*& data, size_t position) const;
size_t size_; size_t size_;
mutable Vector<char> buffer_; Vector<char> buffer_;
mutable Vector<char*> segments_; Vector<Segment> segments_;
}; };
// Current CopyAs specializations. // Current CopyAs specializations.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment