| 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 enum class SerializationTag : uint8_t { | 21 enum class SerializationTag : uint8_t { |
| 22 // version:uint32_t (if at beginning of data, sets version > 0) |
| 22 kVersion = 0xFF, | 23 kVersion = 0xFF, |
| 24 // ignore |
| 23 kPadding = '\0', | 25 kPadding = '\0', |
| 26 // refTableSize:uint32_t (previously used for sanity checks; safe to ignore) |
| 24 kVerifyObjectCount = '?', | 27 kVerifyObjectCount = '?', |
| 28 // Oddballs (no data). |
| 25 kUndefined = '_', | 29 kUndefined = '_', |
| 26 kNull = '0', | 30 kNull = '0', |
| 27 kTrue = 'T', | 31 kTrue = 'T', |
| 28 kFalse = 'F', | 32 kFalse = 'F', |
| 33 // Number represented as 32-bit integer, ZigZag-encoded |
| 34 // (like sint32 in protobuf) |
| 35 kInt32 = 'I', |
| 36 // Number represented as 32-bit unsigned integer, varint-encoded |
| 37 // (like uint32 in protobuf) |
| 38 kUint32 = 'U', |
| 39 // Number represented as a 64-bit double. |
| 40 // Host byte order is used (N.B. this makes the format non-portable). |
| 41 kDouble = 'N', |
| 29 }; | 42 }; |
| 30 | 43 |
| 31 ValueSerializer::ValueSerializer() {} | 44 ValueSerializer::ValueSerializer() {} |
| 32 | 45 |
| 33 ValueSerializer::~ValueSerializer() {} | 46 ValueSerializer::~ValueSerializer() {} |
| 34 | 47 |
| 35 void ValueSerializer::WriteHeader() { | 48 void ValueSerializer::WriteHeader() { |
| 36 WriteTag(SerializationTag::kVersion); | 49 WriteTag(SerializationTag::kVersion); |
| 37 WriteVarint(kLatestVersion); | 50 WriteVarint(kLatestVersion); |
| 38 } | 51 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 53 uint8_t* next_byte = &stack_buffer[0]; | 66 uint8_t* next_byte = &stack_buffer[0]; |
| 54 do { | 67 do { |
| 55 *next_byte = (value & 0x7f) | 0x80; | 68 *next_byte = (value & 0x7f) | 0x80; |
| 56 next_byte++; | 69 next_byte++; |
| 57 value >>= 7; | 70 value >>= 7; |
| 58 } while (value); | 71 } while (value); |
| 59 *(next_byte - 1) &= 0x7f; | 72 *(next_byte - 1) &= 0x7f; |
| 60 buffer_.insert(buffer_.end(), stack_buffer, next_byte); | 73 buffer_.insert(buffer_.end(), stack_buffer, next_byte); |
| 61 } | 74 } |
| 62 | 75 |
| 76 template <typename T> |
| 77 void ValueSerializer::WriteZigZag(T value) { |
| 78 // Writes a signed integer as a varint using ZigZag encoding (i.e. 0 is |
| 79 // encoded as 0, -1 as 1, 1 as 2, -2 as 3, and so on). |
| 80 // See also https://developers.google.com/protocol-buffers/docs/encoding |
| 81 // Note that this implementation relies on the right shift being arithmetic. |
| 82 static_assert(std::is_integral<T>::value && std::is_signed<T>::value, |
| 83 "Only signed integer types can be written as zigzag."); |
| 84 using UnsignedT = typename std::make_unsigned<T>::type; |
| 85 WriteVarint((static_cast<UnsignedT>(value) << 1) ^ |
| 86 (value >> (8 * sizeof(T) - 1))); |
| 87 } |
| 88 |
| 89 void ValueSerializer::WriteDouble(double value) { |
| 90 // Warning: this uses host endianness. |
| 91 buffer_.insert(buffer_.end(), reinterpret_cast<const uint8_t*>(&value), |
| 92 reinterpret_cast<const uint8_t*>(&value + 1)); |
| 93 } |
| 94 |
| 63 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { | 95 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { |
| 64 if (object->IsSmi()) UNIMPLEMENTED(); | 96 if (object->IsSmi()) { |
| 97 WriteSmi(Smi::cast(*object)); |
| 98 return Just(true); |
| 99 } |
| 65 | 100 |
| 66 DCHECK(object->IsHeapObject()); | 101 DCHECK(object->IsHeapObject()); |
| 67 switch (HeapObject::cast(*object)->map()->instance_type()) { | 102 switch (HeapObject::cast(*object)->map()->instance_type()) { |
| 68 case ODDBALL_TYPE: | 103 case ODDBALL_TYPE: |
| 69 WriteOddball(Oddball::cast(*object)); | 104 WriteOddball(Oddball::cast(*object)); |
| 70 return Just(true); | 105 return Just(true); |
| 106 case HEAP_NUMBER_TYPE: |
| 107 case MUTABLE_HEAP_NUMBER_TYPE: |
| 108 WriteHeapNumber(HeapNumber::cast(*object)); |
| 109 return Just(true); |
| 71 default: | 110 default: |
| 72 UNIMPLEMENTED(); | 111 UNIMPLEMENTED(); |
| 73 return Nothing<bool>(); | 112 return Nothing<bool>(); |
| 74 } | 113 } |
| 75 } | 114 } |
| 76 | 115 |
| 77 void ValueSerializer::WriteOddball(Oddball* oddball) { | 116 void ValueSerializer::WriteOddball(Oddball* oddball) { |
| 78 SerializationTag tag = SerializationTag::kUndefined; | 117 SerializationTag tag = SerializationTag::kUndefined; |
| 79 switch (oddball->kind()) { | 118 switch (oddball->kind()) { |
| 80 case Oddball::kUndefined: | 119 case Oddball::kUndefined: |
| 81 tag = SerializationTag::kUndefined; | 120 tag = SerializationTag::kUndefined; |
| 82 break; | 121 break; |
| 83 case Oddball::kFalse: | 122 case Oddball::kFalse: |
| 84 tag = SerializationTag::kFalse; | 123 tag = SerializationTag::kFalse; |
| 85 break; | 124 break; |
| 86 case Oddball::kTrue: | 125 case Oddball::kTrue: |
| 87 tag = SerializationTag::kTrue; | 126 tag = SerializationTag::kTrue; |
| 88 break; | 127 break; |
| 89 case Oddball::kNull: | 128 case Oddball::kNull: |
| 90 tag = SerializationTag::kNull; | 129 tag = SerializationTag::kNull; |
| 91 break; | 130 break; |
| 92 default: | 131 default: |
| 93 UNREACHABLE(); | 132 UNREACHABLE(); |
| 94 break; | 133 break; |
| 95 } | 134 } |
| 96 WriteTag(tag); | 135 WriteTag(tag); |
| 97 } | 136 } |
| 98 | 137 |
| 138 void ValueSerializer::WriteSmi(Smi* smi) { |
| 139 static_assert(kSmiValueSize <= 32, "Expected SMI <= 32 bits."); |
| 140 WriteTag(SerializationTag::kInt32); |
| 141 WriteZigZag<int32_t>(smi->value()); |
| 142 } |
| 143 |
| 144 void ValueSerializer::WriteHeapNumber(HeapNumber* number) { |
| 145 WriteTag(SerializationTag::kDouble); |
| 146 WriteDouble(number->value()); |
| 147 } |
| 148 |
| 99 ValueDeserializer::ValueDeserializer(Isolate* isolate, | 149 ValueDeserializer::ValueDeserializer(Isolate* isolate, |
| 100 Vector<const uint8_t> data) | 150 Vector<const uint8_t> data) |
| 101 : isolate_(isolate), | 151 : isolate_(isolate), |
| 102 position_(data.start()), | 152 position_(data.start()), |
| 103 end_(data.start() + data.length()) {} | 153 end_(data.start() + data.length()) {} |
| 104 | 154 |
| 105 ValueDeserializer::~ValueDeserializer() {} | 155 ValueDeserializer::~ValueDeserializer() {} |
| 106 | 156 |
| 107 Maybe<bool> ValueDeserializer::ReadHeader() { | 157 Maybe<bool> ValueDeserializer::ReadHeader() { |
| 108 if (position_ < end_ && | 158 if (position_ < end_ && |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 if (V8_LIKELY(shift < sizeof(T) * 8)) { | 192 if (V8_LIKELY(shift < sizeof(T) * 8)) { |
| 143 value |= (byte & 0x7f) << shift; | 193 value |= (byte & 0x7f) << shift; |
| 144 shift += 7; | 194 shift += 7; |
| 145 } | 195 } |
| 146 has_another_byte = byte & 0x80; | 196 has_another_byte = byte & 0x80; |
| 147 position_++; | 197 position_++; |
| 148 } while (has_another_byte); | 198 } while (has_another_byte); |
| 149 return Just(value); | 199 return Just(value); |
| 150 } | 200 } |
| 151 | 201 |
| 202 template <typename T> |
| 203 Maybe<T> ValueDeserializer::ReadZigZag() { |
| 204 // Writes a signed integer as a varint using ZigZag encoding (i.e. 0 is |
| 205 // encoded as 0, -1 as 1, 1 as 2, -2 as 3, and so on). |
| 206 // See also https://developers.google.com/protocol-buffers/docs/encoding |
| 207 static_assert(std::is_integral<T>::value && std::is_signed<T>::value, |
| 208 "Only signed integer types can be read as zigzag."); |
| 209 using UnsignedT = typename std::make_unsigned<T>::type; |
| 210 UnsignedT unsigned_value; |
| 211 if (!ReadVarint<UnsignedT>().To(&unsigned_value)) return Nothing<T>(); |
| 212 return Just(static_cast<T>((unsigned_value >> 1) ^ |
| 213 -static_cast<T>(unsigned_value & 1))); |
| 214 } |
| 215 |
| 216 Maybe<double> ValueDeserializer::ReadDouble() { |
| 217 // Warning: this uses host endianness. |
| 218 if (position_ > end_ - sizeof(double)) return Nothing<double>(); |
| 219 double value; |
| 220 memcpy(&value, position_, sizeof(double)); |
| 221 position_ += sizeof(double); |
| 222 if (std::isnan(value)) value = std::numeric_limits<double>::quiet_NaN(); |
| 223 return Just(value); |
| 224 } |
| 225 |
| 152 MaybeHandle<Object> ValueDeserializer::ReadObject() { | 226 MaybeHandle<Object> ValueDeserializer::ReadObject() { |
| 153 SerializationTag tag; | 227 SerializationTag tag; |
| 154 if (!ReadTag().To(&tag)) return MaybeHandle<Object>(); | 228 if (!ReadTag().To(&tag)) return MaybeHandle<Object>(); |
| 155 switch (tag) { | 229 switch (tag) { |
| 156 case SerializationTag::kVerifyObjectCount: | 230 case SerializationTag::kVerifyObjectCount: |
| 157 // Read the count and ignore it. | 231 // Read the count and ignore it. |
| 158 if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>(); | 232 if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>(); |
| 159 return ReadObject(); | 233 return ReadObject(); |
| 160 case SerializationTag::kUndefined: | 234 case SerializationTag::kUndefined: |
| 161 return isolate_->factory()->undefined_value(); | 235 return isolate_->factory()->undefined_value(); |
| 162 case SerializationTag::kNull: | 236 case SerializationTag::kNull: |
| 163 return isolate_->factory()->null_value(); | 237 return isolate_->factory()->null_value(); |
| 164 case SerializationTag::kTrue: | 238 case SerializationTag::kTrue: |
| 165 return isolate_->factory()->true_value(); | 239 return isolate_->factory()->true_value(); |
| 166 case SerializationTag::kFalse: | 240 case SerializationTag::kFalse: |
| 167 return isolate_->factory()->false_value(); | 241 return isolate_->factory()->false_value(); |
| 242 case SerializationTag::kInt32: { |
| 243 Maybe<int32_t> number = ReadZigZag<int32_t>(); |
| 244 if (number.IsNothing()) return MaybeHandle<Object>(); |
| 245 return isolate_->factory()->NewNumberFromInt(number.FromJust()); |
| 246 } |
| 247 case SerializationTag::kUint32: { |
| 248 Maybe<uint32_t> number = ReadVarint<uint32_t>(); |
| 249 if (number.IsNothing()) return MaybeHandle<Object>(); |
| 250 return isolate_->factory()->NewNumberFromUint(number.FromJust()); |
| 251 } |
| 252 case SerializationTag::kDouble: { |
| 253 Maybe<double> number = ReadDouble(); |
| 254 if (number.IsNothing()) return MaybeHandle<Object>(); |
| 255 return isolate_->factory()->NewNumber(number.FromJust()); |
| 256 } |
| 168 default: | 257 default: |
| 169 return MaybeHandle<Object>(); | 258 return MaybeHandle<Object>(); |
| 170 } | 259 } |
| 171 } | 260 } |
| 172 | 261 |
| 173 } // namespace internal | 262 } // namespace internal |
| 174 } // namespace v8 | 263 } // namespace v8 |
| OLD | NEW |