Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(685)

Unified Diff: third_party/WebKit/Source/platform/SharedBufferStep.cpp

Issue 2918443003: Remove redundant reading and writing of data about SharedBuffer.
Patch Set: benchmark Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/SharedBufferStep.cpp
diff --git a/third_party/WebKit/Source/platform/SharedBufferStep.cpp b/third_party/WebKit/Source/platform/SharedBufferStep.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..75394495f07a1bbce78fe8d22075808351a598ca
--- /dev/null
+++ b/third_party/WebKit/Source/platform/SharedBufferStep.cpp
@@ -0,0 +1,301 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "platform/SharedBufferStep.h"
+#include "platform/SharedBuffer.h"
+
+namespace blink {
+
+static inline size_t SegmentIndex(size_t position) {
+ return position / SharedBuffer::kSegmentSize;
+}
+
+static inline size_t OffsetInSegment(size_t position) {
+ return position % SharedBuffer::kSegmentSize;
+}
+
+static inline char* AllocateSegment() {
+ return static_cast<char*>(WTF::Partitions::FastMalloc(
+ SharedBuffer::kSegmentSize, "blink::SharedBufferStep"));
+}
+
+static inline void FreeSegment(char* p) {
+ WTF::Partitions::FastFree(p);
+}
+
+PassRefPtr<SharedBufferStep::BufferVector>
+SharedBufferStep::BufferVector::AdoptVector(Vector<char>& vector) {
+ RefPtr<SharedBufferStep::BufferVector> buffer = BufferVector::Create();
+ buffer->vector_.swap(vector);
+ return buffer.Release();
+}
+
+PassRefPtr<SharedBufferStep::BufferVector>
+SharedBufferStep::BufferVector::ForwardStep() {
+ RefPtr<SharedBufferStep::BufferVector> next_step = BufferVector::Create();
+ next_step->Append(data(), size());
+ return next_step.Release();
+}
+
+PassRefPtr<SharedBufferStep::SegmentVector>
+SharedBufferStep::SegmentVector::ForwardStep() {
+ RefPtr<SegmentVector> next_step = SegmentVector::Create(segmented_position_);
+ next_step->vector_.Append(vector_.data(), vector_.size());
+ next_step->segmented_position_ = segmented_position_;
+ next_step->segmented_size_ = segmented_size_;
+ next_step_segments_ = next_step;
+ return next_step.Release();
+}
+
+SharedBufferStep::SegmentVector::~SegmentVector() {
+ clear();
+}
+
+void SharedBufferStep::SegmentVector::clear() {
+ if (next_step_segments_) {
+ return;
+ }
+
+ for (size_t i = 0; i < vector_.size(); ++i) {
+ FreeSegment(vector_.at(i));
+ }
+
+ vector_.clear();
+ segmented_position_ = 0;
+ segmented_size_ = 0;
+ next_step_segments_ = nullptr;
+}
+
+PassRefPtr<SharedBufferStep> SharedBufferStep::AdoptVector(
+ Vector<char>& vector) {
+ RefPtr<BufferVector> buffer = BufferVector::AdoptVector(vector);
+ RefPtr<SegmentVector> segments = SegmentVector::Create(vector.size());
+ RefPtr<SharedBufferStep> step =
+ SharedBufferStep::Create(vector.size(), buffer, segments);
+ return step.Release();
+}
+
+size_t SharedBufferStep::GetSomeData(const char*& some_data,
+ size_t position) const {
+ size_t total_size = size();
+ if (position >= total_size) {
+ some_data = 0;
+ return 0;
+ }
+
+ SECURITY_DCHECK(position < size_);
+ size_t available_size = 0;
+ size_t max_available_size = size_ - position;
+
+ size_t consecutive_size = buffer_->size();
+ if (position < consecutive_size) {
+ some_data = buffer_->data() + position;
+ available_size = consecutive_size - position;
+ return std::min(available_size, max_available_size);
+ }
+
+ position -= segments_->segmented_position();
+ size_t segments = segments_->size();
+ size_t segment = SegmentIndex(position);
+ if (segment < segments) {
+ size_t position_in_segment = OffsetInSegment(position);
+ some_data = segments_->at(segment) + position_in_segment;
+ if (segment == segments - 1) {
+ available_size = segments_->segmented_size() - position;
+ } else {
+ available_size = SharedBuffer::kSegmentSize - position_in_segment;
+ }
+ return std::min(available_size, max_available_size);
+ }
+
+ NOTREACHED();
+ return 0;
+}
+
+bool SharedBufferStep::GetBytes(void* dest, size_t byte_length) const {
+ if (!dest)
+ return false;
+
+ const char* segment = nullptr;
+ size_t load_position = 0;
+ size_t write_position = 0;
+ while (byte_length > 0) {
+ size_t load_size = GetSomeData(segment, load_position);
+ if (load_size == 0)
+ break;
+
+ if (byte_length < load_size)
+ load_size = byte_length;
+ memcpy(static_cast<char*>(dest) + write_position, segment, load_size);
+ load_position += load_size;
+ write_position += load_size;
+ byte_length -= load_size;
+ }
+
+ return byte_length == 0;
+}
+
+sk_sp<SkData> SharedBufferStep::GetAsSkData() const {
+ size_t buffer_length = size();
+ sk_sp<SkData> data = SkData::MakeUninitialized(buffer_length);
+ char* buffer = static_cast<char*>(data->writable_data());
+
+ if (GetBytes(buffer, buffer_length)) {
+ // Don't return the incomplete SkData.
+ return data;
+ }
+
+ NOTREACHED();
+ return nullptr;
+}
+
+PassRefPtr<SharedBufferStep> SharedBufferStep::Copy() const {
+ RefPtr<SharedBufferStep> clone(AdoptRef(new SharedBufferStep));
+ clone->size_ = size_;
+ clone->buffer_->ReserveInitialCapacity(size_);
+ clone->buffer_->Append(buffer_->data(), buffer_->size());
+ if (!segments_->IsEmpty()) {
+ const char* segment = 0;
+ size_t position = buffer_->size();
+ while (size_t segment_size = GetSomeData(segment, position)) {
+ clone->buffer_->Append(segment, segment_size);
+ position += segment_size;
+ }
+ DCHECK_EQ(position, clone->size());
+ }
+ return clone.Release();
+}
+
+PassRefPtr<SharedBufferStep> SharedBufferStep::Append(
+ const char* data,
+ size_t length,
+ bool forward_step_if_needed) {
+ RefPtr<SharedBufferStep> next_step(this);
+ if (!length) {
+ return next_step.Release();
+ }
+
+ DCHECK_GE(size_, buffer_->size());
+
+ if (size_ + length <= SharedBuffer::kSegmentSize) {
+ // No need to use segments for small resource data.
+ if (forward_step_if_needed &&
+ buffer_->capacity() < buffer_->size() + length) {
+ RefPtr<BufferVector> next_step_buffer = buffer_->ForwardStep();
+ next_step =
+ AdoptRef(new SharedBufferStep(size_, next_step_buffer, segments_));
+ }
+
+ next_step->buffer_->Append(data, length);
+ next_step->size_ += length;
+ next_step->segments_->set_segmented_position(next_step->size_);
+ return next_step.Release();
+ }
+
+ size_t dst_segmented_size = segments_->segmented_size() + length;
+
+ if (forward_step_if_needed) {
+ size_t dst_segments_count =
+ dst_segmented_size / SharedBuffer::kSegmentSize +
+ ((dst_segmented_size % SharedBuffer::kSegmentSize != 0) ? 1 : 0);
+ if (segments_->capacity() < dst_segments_count) {
+ RefPtr<SegmentVector> next_step_segments = segments_->ForwardStep();
+ next_step =
+ AdoptRef(new SharedBufferStep(size_, buffer_, next_step_segments));
+ }
+ }
+
+ RefPtr<SegmentVector> dst_segments = next_step->segments_;
+
+ size_t position_in_segment = OffsetInSegment(dst_segments->segmented_size());
+
+ char* segment;
+ if (!position_in_segment) {
+ segment = AllocateSegment();
+ dst_segments->push_back(segment);
+ } else {
+ segment = dst_segments->back() + position_in_segment;
+ }
+
+ size_t segment_free_space = SharedBuffer::kSegmentSize - position_in_segment;
+ size_t bytes_to_copy = std::min(length, segment_free_space);
+ size_t bytes_for_fill = length;
+
+ for (;;) {
+ memcpy(segment, data, bytes_to_copy);
+ if (bytes_for_fill == bytes_to_copy)
+ break;
+
+ bytes_for_fill -= bytes_to_copy;
+ data += bytes_to_copy;
+ segment = AllocateSegment();
+ dst_segments->push_back(segment);
+ bytes_to_copy = std::min(bytes_for_fill,
+ static_cast<size_t>(SharedBuffer::kSegmentSize));
+ }
+
+ dst_segments->set_segmented_size(dst_segmented_size);
+ next_step->size_ += length;
+ return next_step.Release();
+}
+
+PassRefPtr<SharedBufferStep> SharedBufferStep::MergeSegmentsIntoBuffer(
+ bool forward_step_if_needed) const {
+ SharedBufferStep* step = const_cast<SharedBufferStep*>(this);
+ RefPtr<SharedBufferStep> next_step(step);
+ size_t buffer_size = buffer_->size();
+ if (size_ <= buffer_size) {
+ return next_step.Release();
+ }
+
+ RefPtr<SegmentVector> next_step_segments = SegmentVector::Create(size_);
+
+ if (forward_step_if_needed) {
+ RefPtr<BufferVector> next_step_buffer = buffer_;
+ if (buffer_->capacity() < size_) {
+ next_step_buffer = buffer_->ForwardStep();
+ }
+ next_step = AdoptRef(
+ new SharedBufferStep(size_, next_step_buffer, next_step_segments));
+ }
+
+ RefPtr<BufferVector> dst_buffer = next_step->buffer_;
+
+ size_t bytesLeft = size_ - buffer_size;
+ for (size_t i = 0; i < segments_->size(); ++i) {
+ size_t bytes_to_copy =
+ std::min(bytesLeft, static_cast<size_t>(SharedBuffer::kSegmentSize));
+ dst_buffer->Append(segments_->at(i), bytes_to_copy);
+ bytesLeft -= bytes_to_copy;
+ }
+
+ if (!forward_step_if_needed) {
+ segments_ = next_step_segments;
+ }
+
+ return next_step.Release();
+}
+
+PassRefPtr<SharedBufferStep> SharedBufferStep::Clear(
+ bool forward_step_if_needed) {
+ if (forward_step_if_needed) {
+ return SharedBufferStep::Create();
+ }
+
+ buffer_->clear();
+ segments_->clear();
+ size_ = 0;
+ return this;
+}
+
+SharedBufferStep::SharedBufferStep() : size_(0) {
+ buffer_ = BufferVector::Create();
+ segments_ = SegmentVector::Create(0);
+}
+
+SharedBufferStep::SharedBufferStep(size_t size) : size_(size) {
+ buffer_ = BufferVector::Create(size);
+ segments_ = SegmentVector::Create(size);
+}
+}
« no previous file with comments | « third_party/WebKit/Source/platform/SharedBufferStep.h ('k') | third_party/WebKit/Source/platform/graphics/BitmapImage.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698