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

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

Issue 2232323004: Blink-compatible serialization of numbers. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@vs1
Patch Set: for consistency, use sizeof(double) everywhere Created 4 years, 4 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
« 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/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
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
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
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