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

Side by Side Diff: src/value-serializer.cc

Issue 2492943002: ValueSerializer: Replace use of std::vector with a delegate-allocated buffer. (Closed)
Patch Set: correct comment Created 4 years, 1 month 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
« no previous file with comments | « src/value-serializer.h ('k') | test/unittests/value-serializer-unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/value-serializer.h" 5 #include "src/value-serializer.h"
6 6
7 #include <type_traits> 7 #include <type_traits>
8 8
9 #include "src/base/logging.h" 9 #include "src/base/logging.h"
10 #include "src/conversions.h" 10 #include "src/conversions.h"
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 } // namespace 140 } // namespace
141 141
142 ValueSerializer::ValueSerializer(Isolate* isolate, 142 ValueSerializer::ValueSerializer(Isolate* isolate,
143 v8::ValueSerializer::Delegate* delegate) 143 v8::ValueSerializer::Delegate* delegate)
144 : isolate_(isolate), 144 : isolate_(isolate),
145 delegate_(delegate), 145 delegate_(delegate),
146 zone_(isolate->allocator(), ZONE_NAME), 146 zone_(isolate->allocator(), ZONE_NAME),
147 id_map_(isolate->heap(), &zone_), 147 id_map_(isolate->heap(), &zone_),
148 array_buffer_transfer_map_(isolate->heap(), &zone_) {} 148 array_buffer_transfer_map_(isolate->heap(), &zone_) {}
149 149
150 ValueSerializer::~ValueSerializer() {} 150 ValueSerializer::~ValueSerializer() {
151 if (buffer_) {
152 if (delegate_) {
153 delegate_->FreeBufferMemory(buffer_);
154 } else {
155 free(buffer_);
156 }
157 }
158 }
151 159
152 void ValueSerializer::WriteHeader() { 160 void ValueSerializer::WriteHeader() {
153 WriteTag(SerializationTag::kVersion); 161 WriteTag(SerializationTag::kVersion);
154 WriteVarint(kLatestVersion); 162 WriteVarint(kLatestVersion);
155 } 163 }
156 164
157 void ValueSerializer::WriteTag(SerializationTag tag) { 165 void ValueSerializer::WriteTag(SerializationTag tag) {
158 buffer_.push_back(static_cast<uint8_t>(tag)); 166 uint8_t raw_tag = static_cast<uint8_t>(tag);
167 WriteRawBytes(&raw_tag, sizeof(raw_tag));
159 } 168 }
160 169
161 template <typename T> 170 template <typename T>
162 void ValueSerializer::WriteVarint(T value) { 171 void ValueSerializer::WriteVarint(T value) {
163 // Writes an unsigned integer as a base-128 varint. 172 // Writes an unsigned integer as a base-128 varint.
164 // The number is written, 7 bits at a time, from the least significant to the 173 // The number is written, 7 bits at a time, from the least significant to the
165 // most significant 7 bits. Each byte, except the last, has the MSB set. 174 // most significant 7 bits. Each byte, except the last, has the MSB set.
166 // See also https://developers.google.com/protocol-buffers/docs/encoding 175 // See also https://developers.google.com/protocol-buffers/docs/encoding
167 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value, 176 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
168 "Only unsigned integer types can be written as varints."); 177 "Only unsigned integer types can be written as varints.");
169 uint8_t stack_buffer[sizeof(T) * 8 / 7 + 1]; 178 uint8_t stack_buffer[sizeof(T) * 8 / 7 + 1];
170 uint8_t* next_byte = &stack_buffer[0]; 179 uint8_t* next_byte = &stack_buffer[0];
171 do { 180 do {
172 *next_byte = (value & 0x7f) | 0x80; 181 *next_byte = (value & 0x7f) | 0x80;
173 next_byte++; 182 next_byte++;
174 value >>= 7; 183 value >>= 7;
175 } while (value); 184 } while (value);
176 *(next_byte - 1) &= 0x7f; 185 *(next_byte - 1) &= 0x7f;
177 buffer_.insert(buffer_.end(), stack_buffer, next_byte); 186 WriteRawBytes(stack_buffer, next_byte - stack_buffer);
178 } 187 }
179 188
180 template <typename T> 189 template <typename T>
181 void ValueSerializer::WriteZigZag(T value) { 190 void ValueSerializer::WriteZigZag(T value) {
182 // Writes a signed integer as a varint using ZigZag encoding (i.e. 0 is 191 // Writes a signed integer as a varint using ZigZag encoding (i.e. 0 is
183 // encoded as 0, -1 as 1, 1 as 2, -2 as 3, and so on). 192 // encoded as 0, -1 as 1, 1 as 2, -2 as 3, and so on).
184 // See also https://developers.google.com/protocol-buffers/docs/encoding 193 // See also https://developers.google.com/protocol-buffers/docs/encoding
185 // Note that this implementation relies on the right shift being arithmetic. 194 // Note that this implementation relies on the right shift being arithmetic.
186 static_assert(std::is_integral<T>::value && std::is_signed<T>::value, 195 static_assert(std::is_integral<T>::value && std::is_signed<T>::value,
187 "Only signed integer types can be written as zigzag."); 196 "Only signed integer types can be written as zigzag.");
188 using UnsignedT = typename std::make_unsigned<T>::type; 197 using UnsignedT = typename std::make_unsigned<T>::type;
189 WriteVarint((static_cast<UnsignedT>(value) << 1) ^ 198 WriteVarint((static_cast<UnsignedT>(value) << 1) ^
190 (value >> (8 * sizeof(T) - 1))); 199 (value >> (8 * sizeof(T) - 1)));
191 } 200 }
192 201
193 void ValueSerializer::WriteDouble(double value) { 202 void ValueSerializer::WriteDouble(double value) {
194 // Warning: this uses host endianness. 203 // Warning: this uses host endianness.
195 buffer_.insert(buffer_.end(), reinterpret_cast<const uint8_t*>(&value), 204 WriteRawBytes(&value, sizeof(value));
196 reinterpret_cast<const uint8_t*>(&value + 1));
197 } 205 }
198 206
199 void ValueSerializer::WriteOneByteString(Vector<const uint8_t> chars) { 207 void ValueSerializer::WriteOneByteString(Vector<const uint8_t> chars) {
200 WriteVarint<uint32_t>(chars.length()); 208 WriteVarint<uint32_t>(chars.length());
201 buffer_.insert(buffer_.end(), chars.begin(), chars.end()); 209 WriteRawBytes(chars.begin(), chars.length() * sizeof(uint8_t));
202 } 210 }
203 211
204 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) { 212 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) {
205 // Warning: this uses host endianness. 213 // Warning: this uses host endianness.
206 WriteVarint<uint32_t>(chars.length() * sizeof(uc16)); 214 WriteVarint<uint32_t>(chars.length() * sizeof(uc16));
207 buffer_.insert(buffer_.end(), reinterpret_cast<const uint8_t*>(chars.begin()), 215 WriteRawBytes(chars.begin(), chars.length() * sizeof(uc16));
208 reinterpret_cast<const uint8_t*>(chars.end()));
209 } 216 }
210 217
211 void ValueSerializer::WriteRawBytes(const void* source, size_t length) { 218 void ValueSerializer::WriteRawBytes(const void* source, size_t length) {
212 const uint8_t* begin = reinterpret_cast<const uint8_t*>(source); 219 memcpy(ReserveRawBytes(length), source, length);
213 buffer_.insert(buffer_.end(), begin, begin + length);
214 } 220 }
215 221
216 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { 222 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) {
217 if (!bytes) return nullptr; 223 size_t old_size = buffer_size_;
218 auto old_size = buffer_.size(); 224 size_t new_size = old_size + bytes;
219 buffer_.resize(buffer_.size() + bytes); 225 if (new_size > buffer_capacity_) ExpandBuffer(new_size);
226 buffer_size_ = new_size;
220 return &buffer_[old_size]; 227 return &buffer_[old_size];
221 } 228 }
222 229
230 void ValueSerializer::ExpandBuffer(size_t required_capacity) {
231 DCHECK_GT(required_capacity, buffer_capacity_);
232 size_t requested_capacity =
233 std::max(required_capacity, buffer_capacity_ * 2) + 64;
234 size_t provided_capacity = 0;
235 void* new_buffer = nullptr;
236 if (delegate_) {
237 new_buffer = delegate_->ReallocateBufferMemory(buffer_, requested_capacity,
238 &provided_capacity);
239 } else {
240 new_buffer = realloc(buffer_, requested_capacity);
241 provided_capacity = requested_capacity;
242 }
243 DCHECK_GE(provided_capacity, requested_capacity);
244 buffer_ = reinterpret_cast<uint8_t*>(new_buffer);
245 buffer_capacity_ = provided_capacity;
246 }
247
223 void ValueSerializer::WriteUint32(uint32_t value) { 248 void ValueSerializer::WriteUint32(uint32_t value) {
224 WriteVarint<uint32_t>(value); 249 WriteVarint<uint32_t>(value);
225 } 250 }
226 251
227 void ValueSerializer::WriteUint64(uint64_t value) { 252 void ValueSerializer::WriteUint64(uint64_t value) {
228 WriteVarint<uint64_t>(value); 253 WriteVarint<uint64_t>(value);
229 } 254 }
230 255
256 std::vector<uint8_t> ValueSerializer::ReleaseBuffer() {
257 return std::vector<uint8_t>(buffer_, buffer_ + buffer_size_);
258 }
259
260 std::pair<uint8_t*, size_t> ValueSerializer::Release() {
261 auto result = std::make_pair(buffer_, buffer_size_);
262 buffer_ = nullptr;
263 buffer_size_ = 0;
264 buffer_capacity_ = 0;
265 return result;
266 }
267
231 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, 268 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id,
232 Handle<JSArrayBuffer> array_buffer) { 269 Handle<JSArrayBuffer> array_buffer) {
233 DCHECK(!array_buffer_transfer_map_.Find(array_buffer)); 270 DCHECK(!array_buffer_transfer_map_.Find(array_buffer));
234 array_buffer_transfer_map_.Set(array_buffer, transfer_id); 271 array_buffer_transfer_map_.Set(array_buffer, transfer_id);
235 } 272 }
236 273
237 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { 274 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) {
238 if (object->IsSmi()) { 275 if (object->IsSmi()) {
239 WriteSmi(Smi::cast(*object)); 276 WriteSmi(Smi::cast(*object));
240 return Just(true); 277 return Just(true);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 uint32_t utf8_length = api_string->Utf8Length(); 368 uint32_t utf8_length = api_string->Utf8Length();
332 WriteVarint(utf8_length); 369 WriteVarint(utf8_length);
333 api_string->WriteUtf8( 370 api_string->WriteUtf8(
334 reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), utf8_length, 371 reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), utf8_length,
335 nullptr, v8::String::NO_NULL_TERMINATION); 372 nullptr, v8::String::NO_NULL_TERMINATION);
336 } 373 }
337 } else if (flat.IsTwoByte()) { 374 } else if (flat.IsTwoByte()) {
338 Vector<const uc16> chars = flat.ToUC16Vector(); 375 Vector<const uc16> chars = flat.ToUC16Vector();
339 uint32_t byte_length = chars.length() * sizeof(uc16); 376 uint32_t byte_length = chars.length() * sizeof(uc16);
340 // The existing reading code expects 16-byte strings to be aligned. 377 // The existing reading code expects 16-byte strings to be aligned.
341 if ((buffer_.size() + 1 + BytesNeededForVarint(byte_length)) & 1) 378 if ((buffer_size_ + 1 + BytesNeededForVarint(byte_length)) & 1)
342 WriteTag(SerializationTag::kPadding); 379 WriteTag(SerializationTag::kPadding);
343 WriteTag(SerializationTag::kTwoByteString); 380 WriteTag(SerializationTag::kTwoByteString);
344 WriteTwoByteString(chars); 381 WriteTwoByteString(chars);
345 } else { 382 } else {
346 UNREACHABLE(); 383 UNREACHABLE();
347 } 384 }
348 } 385 }
349 386
350 Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) { 387 Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
351 // If the object has already been serialized, just write its ID. 388 // If the object has already been serialized, just write its ID.
(...skipping 1473 matching lines...) Expand 10 before | Expand all | Expand 10 after
1825 if (stack.size() != 1) { 1862 if (stack.size() != 1) {
1826 isolate_->Throw(*isolate_->factory()->NewError( 1863 isolate_->Throw(*isolate_->factory()->NewError(
1827 MessageTemplate::kDataCloneDeserializationError)); 1864 MessageTemplate::kDataCloneDeserializationError));
1828 return MaybeHandle<Object>(); 1865 return MaybeHandle<Object>();
1829 } 1866 }
1830 return scope.CloseAndEscape(stack[0]); 1867 return scope.CloseAndEscape(stack[0]);
1831 } 1868 }
1832 1869
1833 } // namespace internal 1870 } // namespace internal
1834 } // namespace v8 1871 } // namespace v8
OLDNEW
« no previous file with comments | « src/value-serializer.h ('k') | test/unittests/value-serializer-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698