| 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/factory.h" | 10 #include "src/factory.h" |
| 11 #include "src/handles-inl.h" | 11 #include "src/handles-inl.h" |
| 12 #include "src/isolate.h" | 12 #include "src/isolate.h" |
| 13 #include "src/objects-inl.h" | 13 #include "src/objects-inl.h" |
| 14 #include "src/objects.h" | 14 #include "src/objects.h" |
| 15 | 15 |
| 16 namespace v8 { | 16 namespace v8 { |
| 17 namespace internal { | 17 namespace internal { |
| 18 | 18 |
| 19 static const uint32_t kLatestVersion = 9; | 19 static const uint32_t kLatestVersion = 9; |
| 20 | 20 |
| 21 template <typename T> |
| 22 static size_t BytesNeededForVarint(T value) { |
| 23 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value, |
| 24 "Only unsigned integer types can be written as varints."); |
| 25 size_t result = 0; |
| 26 do { |
| 27 result++; |
| 28 value >>= 7; |
| 29 } while (value); |
| 30 return result; |
| 31 } |
| 32 |
| 21 enum class SerializationTag : uint8_t { | 33 enum class SerializationTag : uint8_t { |
| 22 // version:uint32_t (if at beginning of data, sets version > 0) | 34 // version:uint32_t (if at beginning of data, sets version > 0) |
| 23 kVersion = 0xFF, | 35 kVersion = 0xFF, |
| 24 // ignore | 36 // ignore |
| 25 kPadding = '\0', | 37 kPadding = '\0', |
| 26 // refTableSize:uint32_t (previously used for sanity checks; safe to ignore) | 38 // refTableSize:uint32_t (previously used for sanity checks; safe to ignore) |
| 27 kVerifyObjectCount = '?', | 39 kVerifyObjectCount = '?', |
| 28 // Oddballs (no data). | 40 // Oddballs (no data). |
| 29 kUndefined = '_', | 41 kUndefined = '_', |
| 30 kNull = '0', | 42 kNull = '0', |
| 31 kTrue = 'T', | 43 kTrue = 'T', |
| 32 kFalse = 'F', | 44 kFalse = 'F', |
| 33 // Number represented as 32-bit integer, ZigZag-encoded | 45 // Number represented as 32-bit integer, ZigZag-encoded |
| 34 // (like sint32 in protobuf) | 46 // (like sint32 in protobuf) |
| 35 kInt32 = 'I', | 47 kInt32 = 'I', |
| 36 // Number represented as 32-bit unsigned integer, varint-encoded | 48 // Number represented as 32-bit unsigned integer, varint-encoded |
| 37 // (like uint32 in protobuf) | 49 // (like uint32 in protobuf) |
| 38 kUint32 = 'U', | 50 kUint32 = 'U', |
| 39 // Number represented as a 64-bit double. | 51 // Number represented as a 64-bit double. |
| 40 // Host byte order is used (N.B. this makes the format non-portable). | 52 // Host byte order is used (N.B. this makes the format non-portable). |
| 41 kDouble = 'N', | 53 kDouble = 'N', |
| 54 // byteLength:uint32_t, then raw data |
| 55 kUtf8String = 'S', |
| 56 kTwoByteString = 'c', |
| 42 }; | 57 }; |
| 43 | 58 |
| 44 ValueSerializer::ValueSerializer() {} | 59 ValueSerializer::ValueSerializer() {} |
| 45 | 60 |
| 46 ValueSerializer::~ValueSerializer() {} | 61 ValueSerializer::~ValueSerializer() {} |
| 47 | 62 |
| 48 void ValueSerializer::WriteHeader() { | 63 void ValueSerializer::WriteHeader() { |
| 49 WriteTag(SerializationTag::kVersion); | 64 WriteTag(SerializationTag::kVersion); |
| 50 WriteVarint(kLatestVersion); | 65 WriteVarint(kLatestVersion); |
| 51 } | 66 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 WriteVarint((static_cast<UnsignedT>(value) << 1) ^ | 100 WriteVarint((static_cast<UnsignedT>(value) << 1) ^ |
| 86 (value >> (8 * sizeof(T) - 1))); | 101 (value >> (8 * sizeof(T) - 1))); |
| 87 } | 102 } |
| 88 | 103 |
| 89 void ValueSerializer::WriteDouble(double value) { | 104 void ValueSerializer::WriteDouble(double value) { |
| 90 // Warning: this uses host endianness. | 105 // Warning: this uses host endianness. |
| 91 buffer_.insert(buffer_.end(), reinterpret_cast<const uint8_t*>(&value), | 106 buffer_.insert(buffer_.end(), reinterpret_cast<const uint8_t*>(&value), |
| 92 reinterpret_cast<const uint8_t*>(&value + 1)); | 107 reinterpret_cast<const uint8_t*>(&value + 1)); |
| 93 } | 108 } |
| 94 | 109 |
| 110 void ValueSerializer::WriteOneByteString(Vector<const uint8_t> chars) { |
| 111 WriteVarint<uint32_t>(chars.length()); |
| 112 buffer_.insert(buffer_.end(), chars.begin(), chars.end()); |
| 113 } |
| 114 |
| 115 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) { |
| 116 // Warning: this uses host endianness. |
| 117 WriteVarint<uint32_t>(chars.length() * sizeof(uc16)); |
| 118 buffer_.insert(buffer_.end(), reinterpret_cast<const uint8_t*>(chars.begin()), |
| 119 reinterpret_cast<const uint8_t*>(chars.end())); |
| 120 } |
| 121 |
| 122 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { |
| 123 auto old_size = buffer_.size(); |
| 124 buffer_.resize(buffer_.size() + bytes); |
| 125 return &buffer_[old_size]; |
| 126 } |
| 127 |
| 95 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { | 128 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { |
| 96 if (object->IsSmi()) { | 129 if (object->IsSmi()) { |
| 97 WriteSmi(Smi::cast(*object)); | 130 WriteSmi(Smi::cast(*object)); |
| 98 return Just(true); | 131 return Just(true); |
| 99 } | 132 } |
| 100 | 133 |
| 101 DCHECK(object->IsHeapObject()); | 134 DCHECK(object->IsHeapObject()); |
| 102 switch (HeapObject::cast(*object)->map()->instance_type()) { | 135 switch (HeapObject::cast(*object)->map()->instance_type()) { |
| 103 case ODDBALL_TYPE: | 136 case ODDBALL_TYPE: |
| 104 WriteOddball(Oddball::cast(*object)); | 137 WriteOddball(Oddball::cast(*object)); |
| 105 return Just(true); | 138 return Just(true); |
| 106 case HEAP_NUMBER_TYPE: | 139 case HEAP_NUMBER_TYPE: |
| 107 case MUTABLE_HEAP_NUMBER_TYPE: | 140 case MUTABLE_HEAP_NUMBER_TYPE: |
| 108 WriteHeapNumber(HeapNumber::cast(*object)); | 141 WriteHeapNumber(HeapNumber::cast(*object)); |
| 109 return Just(true); | 142 return Just(true); |
| 110 default: | 143 default: |
| 144 if (object->IsString()) { |
| 145 WriteString(Handle<String>::cast(object)); |
| 146 return Just(true); |
| 147 } |
| 111 UNIMPLEMENTED(); | 148 UNIMPLEMENTED(); |
| 112 return Nothing<bool>(); | 149 return Nothing<bool>(); |
| 113 } | 150 } |
| 114 } | 151 } |
| 115 | 152 |
| 116 void ValueSerializer::WriteOddball(Oddball* oddball) { | 153 void ValueSerializer::WriteOddball(Oddball* oddball) { |
| 117 SerializationTag tag = SerializationTag::kUndefined; | 154 SerializationTag tag = SerializationTag::kUndefined; |
| 118 switch (oddball->kind()) { | 155 switch (oddball->kind()) { |
| 119 case Oddball::kUndefined: | 156 case Oddball::kUndefined: |
| 120 tag = SerializationTag::kUndefined; | 157 tag = SerializationTag::kUndefined; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 139 static_assert(kSmiValueSize <= 32, "Expected SMI <= 32 bits."); | 176 static_assert(kSmiValueSize <= 32, "Expected SMI <= 32 bits."); |
| 140 WriteTag(SerializationTag::kInt32); | 177 WriteTag(SerializationTag::kInt32); |
| 141 WriteZigZag<int32_t>(smi->value()); | 178 WriteZigZag<int32_t>(smi->value()); |
| 142 } | 179 } |
| 143 | 180 |
| 144 void ValueSerializer::WriteHeapNumber(HeapNumber* number) { | 181 void ValueSerializer::WriteHeapNumber(HeapNumber* number) { |
| 145 WriteTag(SerializationTag::kDouble); | 182 WriteTag(SerializationTag::kDouble); |
| 146 WriteDouble(number->value()); | 183 WriteDouble(number->value()); |
| 147 } | 184 } |
| 148 | 185 |
| 186 void ValueSerializer::WriteString(Handle<String> string) { |
| 187 string = String::Flatten(string); |
| 188 DisallowHeapAllocation no_gc; |
| 189 String::FlatContent flat = string->GetFlatContent(); |
| 190 DCHECK(flat.IsFlat()); |
| 191 if (flat.IsOneByte()) { |
| 192 // The existing format uses UTF-8, rather than Latin-1. As a result we must |
| 193 // to do work to encode strings that have characters outside ASCII. |
| 194 // TODO(jbroman): In a future format version, consider adding a tag for |
| 195 // Latin-1 strings, so that this can be skipped. |
| 196 WriteTag(SerializationTag::kUtf8String); |
| 197 Vector<const uint8_t> chars = flat.ToOneByteVector(); |
| 198 if (String::IsAscii(chars.begin(), chars.length())) { |
| 199 WriteOneByteString(chars); |
| 200 } else { |
| 201 v8::Local<v8::String> api_string = Utils::ToLocal(string); |
| 202 uint32_t utf8_length = api_string->Utf8Length(); |
| 203 WriteVarint(utf8_length); |
| 204 api_string->WriteUtf8( |
| 205 reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), utf8_length, |
| 206 nullptr, v8::String::NO_NULL_TERMINATION); |
| 207 } |
| 208 } else if (flat.IsTwoByte()) { |
| 209 Vector<const uc16> chars = flat.ToUC16Vector(); |
| 210 uint32_t byte_length = chars.length() * sizeof(uc16); |
| 211 // The existing reading code expects 16-byte strings to be aligned. |
| 212 if ((buffer_.size() + 1 + BytesNeededForVarint(byte_length)) & 1) |
| 213 WriteTag(SerializationTag::kPadding); |
| 214 WriteTag(SerializationTag::kTwoByteString); |
| 215 WriteTwoByteString(chars); |
| 216 } else { |
| 217 UNREACHABLE(); |
| 218 } |
| 219 } |
| 220 |
| 149 ValueDeserializer::ValueDeserializer(Isolate* isolate, | 221 ValueDeserializer::ValueDeserializer(Isolate* isolate, |
| 150 Vector<const uint8_t> data) | 222 Vector<const uint8_t> data) |
| 151 : isolate_(isolate), | 223 : isolate_(isolate), |
| 152 position_(data.start()), | 224 position_(data.start()), |
| 153 end_(data.start() + data.length()) {} | 225 end_(data.start() + data.length()) {} |
| 154 | 226 |
| 155 ValueDeserializer::~ValueDeserializer() {} | 227 ValueDeserializer::~ValueDeserializer() {} |
| 156 | 228 |
| 157 Maybe<bool> ValueDeserializer::ReadHeader() { | 229 Maybe<bool> ValueDeserializer::ReadHeader() { |
| 158 if (position_ < end_ && | 230 if (position_ < end_ && |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 Maybe<double> ValueDeserializer::ReadDouble() { | 288 Maybe<double> ValueDeserializer::ReadDouble() { |
| 217 // Warning: this uses host endianness. | 289 // Warning: this uses host endianness. |
| 218 if (position_ > end_ - sizeof(double)) return Nothing<double>(); | 290 if (position_ > end_ - sizeof(double)) return Nothing<double>(); |
| 219 double value; | 291 double value; |
| 220 memcpy(&value, position_, sizeof(double)); | 292 memcpy(&value, position_, sizeof(double)); |
| 221 position_ += sizeof(double); | 293 position_ += sizeof(double); |
| 222 if (std::isnan(value)) value = std::numeric_limits<double>::quiet_NaN(); | 294 if (std::isnan(value)) value = std::numeric_limits<double>::quiet_NaN(); |
| 223 return Just(value); | 295 return Just(value); |
| 224 } | 296 } |
| 225 | 297 |
| 298 Maybe<Vector<const uint8_t>> ValueDeserializer::ReadRawBytes(int size) { |
| 299 if (size > end_ - position_) return Nothing<Vector<const uint8_t>>(); |
| 300 const uint8_t* start = position_; |
| 301 position_ += size; |
| 302 return Just(Vector<const uint8_t>(start, size)); |
| 303 } |
| 304 |
| 226 MaybeHandle<Object> ValueDeserializer::ReadObject() { | 305 MaybeHandle<Object> ValueDeserializer::ReadObject() { |
| 227 SerializationTag tag; | 306 SerializationTag tag; |
| 228 if (!ReadTag().To(&tag)) return MaybeHandle<Object>(); | 307 if (!ReadTag().To(&tag)) return MaybeHandle<Object>(); |
| 229 switch (tag) { | 308 switch (tag) { |
| 230 case SerializationTag::kVerifyObjectCount: | 309 case SerializationTag::kVerifyObjectCount: |
| 231 // Read the count and ignore it. | 310 // Read the count and ignore it. |
| 232 if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>(); | 311 if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>(); |
| 233 return ReadObject(); | 312 return ReadObject(); |
| 234 case SerializationTag::kUndefined: | 313 case SerializationTag::kUndefined: |
| 235 return isolate_->factory()->undefined_value(); | 314 return isolate_->factory()->undefined_value(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 247 case SerializationTag::kUint32: { | 326 case SerializationTag::kUint32: { |
| 248 Maybe<uint32_t> number = ReadVarint<uint32_t>(); | 327 Maybe<uint32_t> number = ReadVarint<uint32_t>(); |
| 249 if (number.IsNothing()) return MaybeHandle<Object>(); | 328 if (number.IsNothing()) return MaybeHandle<Object>(); |
| 250 return isolate_->factory()->NewNumberFromUint(number.FromJust()); | 329 return isolate_->factory()->NewNumberFromUint(number.FromJust()); |
| 251 } | 330 } |
| 252 case SerializationTag::kDouble: { | 331 case SerializationTag::kDouble: { |
| 253 Maybe<double> number = ReadDouble(); | 332 Maybe<double> number = ReadDouble(); |
| 254 if (number.IsNothing()) return MaybeHandle<Object>(); | 333 if (number.IsNothing()) return MaybeHandle<Object>(); |
| 255 return isolate_->factory()->NewNumber(number.FromJust()); | 334 return isolate_->factory()->NewNumber(number.FromJust()); |
| 256 } | 335 } |
| 336 case SerializationTag::kUtf8String: |
| 337 return ReadUtf8String(); |
| 338 case SerializationTag::kTwoByteString: |
| 339 return ReadTwoByteString(); |
| 257 default: | 340 default: |
| 258 return MaybeHandle<Object>(); | 341 return MaybeHandle<Object>(); |
| 259 } | 342 } |
| 260 } | 343 } |
| 261 | 344 |
| 345 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { |
| 346 uint32_t utf8_length; |
| 347 Vector<const uint8_t> utf8_bytes; |
| 348 if (!ReadVarint<uint32_t>().To(&utf8_length) || |
| 349 utf8_length > |
| 350 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) || |
| 351 !ReadRawBytes(utf8_length).To(&utf8_bytes)) |
| 352 return MaybeHandle<String>(); |
| 353 return isolate_->factory()->NewStringFromUtf8( |
| 354 Vector<const char>::cast(utf8_bytes)); |
| 355 } |
| 356 |
| 357 MaybeHandle<String> ValueDeserializer::ReadTwoByteString() { |
| 358 uint32_t byte_length; |
| 359 Vector<const uint8_t> bytes; |
| 360 if (!ReadVarint<uint32_t>().To(&byte_length) || |
| 361 byte_length > |
| 362 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) || |
| 363 byte_length % sizeof(uc16) != 0 || !ReadRawBytes(byte_length).To(&bytes)) |
| 364 return MaybeHandle<String>(); |
| 365 |
| 366 // Allocate an uninitialized string so that we can do a raw memcpy into the |
| 367 // string on the heap (regardless of alignment). |
| 368 Handle<SeqTwoByteString> string; |
| 369 if (!isolate_->factory() |
| 370 ->NewRawTwoByteString(byte_length / sizeof(uc16)) |
| 371 .ToHandle(&string)) |
| 372 return MaybeHandle<String>(); |
| 373 |
| 374 // Copy the bytes directly into the new string. |
| 375 // Warning: this uses host endianness. |
| 376 memcpy(string->GetChars(), bytes.begin(), bytes.length()); |
| 377 return string; |
| 378 } |
| 379 |
| 262 } // namespace internal | 380 } // namespace internal |
| 263 } // namespace v8 | 381 } // namespace v8 |
| OLD | NEW |