OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |