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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "platform/SharedBufferStep.h"
6 #include "platform/SharedBuffer.h"
7
8 namespace blink {
9
10 static inline size_t SegmentIndex(size_t position) {
11 return position / SharedBuffer::kSegmentSize;
12 }
13
14 static inline size_t OffsetInSegment(size_t position) {
15 return position % SharedBuffer::kSegmentSize;
16 }
17
18 static inline char* AllocateSegment() {
19 return static_cast<char*>(WTF::Partitions::FastMalloc(
20 SharedBuffer::kSegmentSize, "blink::SharedBufferStep"));
21 }
22
23 static inline void FreeSegment(char* p) {
24 WTF::Partitions::FastFree(p);
25 }
26
27 PassRefPtr<SharedBufferStep::BufferVector>
28 SharedBufferStep::BufferVector::AdoptVector(Vector<char>& vector) {
29 RefPtr<SharedBufferStep::BufferVector> buffer = BufferVector::Create();
30 buffer->vector_.swap(vector);
31 return buffer.Release();
32 }
33
34 PassRefPtr<SharedBufferStep::BufferVector>
35 SharedBufferStep::BufferVector::ForwardStep() {
36 RefPtr<SharedBufferStep::BufferVector> next_step = BufferVector::Create();
37 next_step->Append(data(), size());
38 return next_step.Release();
39 }
40
41 PassRefPtr<SharedBufferStep::SegmentVector>
42 SharedBufferStep::SegmentVector::ForwardStep() {
43 RefPtr<SegmentVector> next_step = SegmentVector::Create(segmented_position_);
44 next_step->vector_.Append(vector_.data(), vector_.size());
45 next_step->segmented_position_ = segmented_position_;
46 next_step->segmented_size_ = segmented_size_;
47 next_step_segments_ = next_step;
48 return next_step.Release();
49 }
50
51 SharedBufferStep::SegmentVector::~SegmentVector() {
52 clear();
53 }
54
55 void SharedBufferStep::SegmentVector::clear() {
56 if (next_step_segments_) {
57 return;
58 }
59
60 for (size_t i = 0; i < vector_.size(); ++i) {
61 FreeSegment(vector_.at(i));
62 }
63
64 vector_.clear();
65 segmented_position_ = 0;
66 segmented_size_ = 0;
67 next_step_segments_ = nullptr;
68 }
69
70 PassRefPtr<SharedBufferStep> SharedBufferStep::AdoptVector(
71 Vector<char>& vector) {
72 RefPtr<BufferVector> buffer = BufferVector::AdoptVector(vector);
73 RefPtr<SegmentVector> segments = SegmentVector::Create(vector.size());
74 RefPtr<SharedBufferStep> step =
75 SharedBufferStep::Create(vector.size(), buffer, segments);
76 return step.Release();
77 }
78
79 size_t SharedBufferStep::GetSomeData(const char*& some_data,
80 size_t position) const {
81 size_t total_size = size();
82 if (position >= total_size) {
83 some_data = 0;
84 return 0;
85 }
86
87 SECURITY_DCHECK(position < size_);
88 size_t available_size = 0;
89 size_t max_available_size = size_ - position;
90
91 size_t consecutive_size = buffer_->size();
92 if (position < consecutive_size) {
93 some_data = buffer_->data() + position;
94 available_size = consecutive_size - position;
95 return std::min(available_size, max_available_size);
96 }
97
98 position -= segments_->segmented_position();
99 size_t segments = segments_->size();
100 size_t segment = SegmentIndex(position);
101 if (segment < segments) {
102 size_t position_in_segment = OffsetInSegment(position);
103 some_data = segments_->at(segment) + position_in_segment;
104 if (segment == segments - 1) {
105 available_size = segments_->segmented_size() - position;
106 } else {
107 available_size = SharedBuffer::kSegmentSize - position_in_segment;
108 }
109 return std::min(available_size, max_available_size);
110 }
111
112 NOTREACHED();
113 return 0;
114 }
115
116 bool SharedBufferStep::GetBytes(void* dest, size_t byte_length) const {
117 if (!dest)
118 return false;
119
120 const char* segment = nullptr;
121 size_t load_position = 0;
122 size_t write_position = 0;
123 while (byte_length > 0) {
124 size_t load_size = GetSomeData(segment, load_position);
125 if (load_size == 0)
126 break;
127
128 if (byte_length < load_size)
129 load_size = byte_length;
130 memcpy(static_cast<char*>(dest) + write_position, segment, load_size);
131 load_position += load_size;
132 write_position += load_size;
133 byte_length -= load_size;
134 }
135
136 return byte_length == 0;
137 }
138
139 sk_sp<SkData> SharedBufferStep::GetAsSkData() const {
140 size_t buffer_length = size();
141 sk_sp<SkData> data = SkData::MakeUninitialized(buffer_length);
142 char* buffer = static_cast<char*>(data->writable_data());
143
144 if (GetBytes(buffer, buffer_length)) {
145 // Don't return the incomplete SkData.
146 return data;
147 }
148
149 NOTREACHED();
150 return nullptr;
151 }
152
153 PassRefPtr<SharedBufferStep> SharedBufferStep::Copy() const {
154 RefPtr<SharedBufferStep> clone(AdoptRef(new SharedBufferStep));
155 clone->size_ = size_;
156 clone->buffer_->ReserveInitialCapacity(size_);
157 clone->buffer_->Append(buffer_->data(), buffer_->size());
158 if (!segments_->IsEmpty()) {
159 const char* segment = 0;
160 size_t position = buffer_->size();
161 while (size_t segment_size = GetSomeData(segment, position)) {
162 clone->buffer_->Append(segment, segment_size);
163 position += segment_size;
164 }
165 DCHECK_EQ(position, clone->size());
166 }
167 return clone.Release();
168 }
169
170 PassRefPtr<SharedBufferStep> SharedBufferStep::Append(
171 const char* data,
172 size_t length,
173 bool forward_step_if_needed) {
174 RefPtr<SharedBufferStep> next_step(this);
175 if (!length) {
176 return next_step.Release();
177 }
178
179 DCHECK_GE(size_, buffer_->size());
180
181 if (size_ + length <= SharedBuffer::kSegmentSize) {
182 // No need to use segments for small resource data.
183 if (forward_step_if_needed &&
184 buffer_->capacity() < buffer_->size() + length) {
185 RefPtr<BufferVector> next_step_buffer = buffer_->ForwardStep();
186 next_step =
187 AdoptRef(new SharedBufferStep(size_, next_step_buffer, segments_));
188 }
189
190 next_step->buffer_->Append(data, length);
191 next_step->size_ += length;
192 next_step->segments_->set_segmented_position(next_step->size_);
193 return next_step.Release();
194 }
195
196 size_t dst_segmented_size = segments_->segmented_size() + length;
197
198 if (forward_step_if_needed) {
199 size_t dst_segments_count =
200 dst_segmented_size / SharedBuffer::kSegmentSize +
201 ((dst_segmented_size % SharedBuffer::kSegmentSize != 0) ? 1 : 0);
202 if (segments_->capacity() < dst_segments_count) {
203 RefPtr<SegmentVector> next_step_segments = segments_->ForwardStep();
204 next_step =
205 AdoptRef(new SharedBufferStep(size_, buffer_, next_step_segments));
206 }
207 }
208
209 RefPtr<SegmentVector> dst_segments = next_step->segments_;
210
211 size_t position_in_segment = OffsetInSegment(dst_segments->segmented_size());
212
213 char* segment;
214 if (!position_in_segment) {
215 segment = AllocateSegment();
216 dst_segments->push_back(segment);
217 } else {
218 segment = dst_segments->back() + position_in_segment;
219 }
220
221 size_t segment_free_space = SharedBuffer::kSegmentSize - position_in_segment;
222 size_t bytes_to_copy = std::min(length, segment_free_space);
223 size_t bytes_for_fill = length;
224
225 for (;;) {
226 memcpy(segment, data, bytes_to_copy);
227 if (bytes_for_fill == bytes_to_copy)
228 break;
229
230 bytes_for_fill -= bytes_to_copy;
231 data += bytes_to_copy;
232 segment = AllocateSegment();
233 dst_segments->push_back(segment);
234 bytes_to_copy = std::min(bytes_for_fill,
235 static_cast<size_t>(SharedBuffer::kSegmentSize));
236 }
237
238 dst_segments->set_segmented_size(dst_segmented_size);
239 next_step->size_ += length;
240 return next_step.Release();
241 }
242
243 PassRefPtr<SharedBufferStep> SharedBufferStep::MergeSegmentsIntoBuffer(
244 bool forward_step_if_needed) const {
245 SharedBufferStep* step = const_cast<SharedBufferStep*>(this);
246 RefPtr<SharedBufferStep> next_step(step);
247 size_t buffer_size = buffer_->size();
248 if (size_ <= buffer_size) {
249 return next_step.Release();
250 }
251
252 RefPtr<SegmentVector> next_step_segments = SegmentVector::Create(size_);
253
254 if (forward_step_if_needed) {
255 RefPtr<BufferVector> next_step_buffer = buffer_;
256 if (buffer_->capacity() < size_) {
257 next_step_buffer = buffer_->ForwardStep();
258 }
259 next_step = AdoptRef(
260 new SharedBufferStep(size_, next_step_buffer, next_step_segments));
261 }
262
263 RefPtr<BufferVector> dst_buffer = next_step->buffer_;
264
265 size_t bytesLeft = size_ - buffer_size;
266 for (size_t i = 0; i < segments_->size(); ++i) {
267 size_t bytes_to_copy =
268 std::min(bytesLeft, static_cast<size_t>(SharedBuffer::kSegmentSize));
269 dst_buffer->Append(segments_->at(i), bytes_to_copy);
270 bytesLeft -= bytes_to_copy;
271 }
272
273 if (!forward_step_if_needed) {
274 segments_ = next_step_segments;
275 }
276
277 return next_step.Release();
278 }
279
280 PassRefPtr<SharedBufferStep> SharedBufferStep::Clear(
281 bool forward_step_if_needed) {
282 if (forward_step_if_needed) {
283 return SharedBufferStep::Create();
284 }
285
286 buffer_->clear();
287 segments_->clear();
288 size_ = 0;
289 return this;
290 }
291
292 SharedBufferStep::SharedBufferStep() : size_(0) {
293 buffer_ = BufferVector::Create();
294 segments_ = SegmentVector::Create(0);
295 }
296
297 SharedBufferStep::SharedBufferStep(size_t size) : size_(size) {
298 buffer_ = BufferVector::Create(size);
299 segments_ = SegmentVector::Create(size);
300 }
301 }
OLDNEW
« 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