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

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

Issue 2232243003: Blink-compatible serialization of oddball values. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add comments explaining varints. 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/unittests.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "src/value-serializer.h"
6
7 #include <type_traits>
8
9 #include "src/base/logging.h"
10 #include "src/factory.h"
11 #include "src/handles-inl.h"
12 #include "src/isolate.h"
13 #include "src/objects-inl.h"
14 #include "src/objects.h"
15
16 namespace v8 {
17 namespace internal {
18
19 static const uint32_t kLatestVersion = 9;
20
21 enum class SerializationTag : uint8_t {
22 kVersion = 0xFF,
23 kPadding = '\0',
24 kVerifyObjectCount = '?',
25 kUndefined = '_',
26 kNull = '0',
27 kTrue = 'T',
28 kFalse = 'F',
29 };
30
31 ValueSerializer::ValueSerializer() {}
32
33 ValueSerializer::~ValueSerializer() {}
34
35 void ValueSerializer::WriteHeader() {
36 WriteTag(SerializationTag::kVersion);
37 WriteVarint(kLatestVersion);
38 }
39
40 void ValueSerializer::WriteTag(SerializationTag tag) {
41 buffer_.push_back(static_cast<uint8_t>(tag));
42 }
43
44 template <typename T>
45 void ValueSerializer::WriteVarint(T value) {
46 // Writes an unsigned integer as a base-128 varint.
47 // The number is written, 7 bits at a time, from the least significant to the
48 // most significant 7 bits. Each byte, except the last, has the MSB set.
49 // See also https://developers.google.com/protocol-buffers/docs/encoding
50 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
51 "Only unsigned integer types can be written as varints.");
52 uint8_t stack_buffer[sizeof(T) * 8 / 7 + 1];
53 uint8_t* next_byte = &stack_buffer[0];
54 do {
55 *next_byte = (value & 0x7f) | 0x80;
56 next_byte++;
57 value >>= 7;
58 } while (value);
59 *(next_byte - 1) &= 0x7f;
60 buffer_.insert(buffer_.end(), stack_buffer, next_byte);
61 }
62
63 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) {
64 if (object->IsSmi()) UNIMPLEMENTED();
65
66 DCHECK(object->IsHeapObject());
67 switch (HeapObject::cast(*object)->map()->instance_type()) {
68 case ODDBALL_TYPE:
69 WriteOddball(Oddball::cast(*object));
70 return Just(true);
71 default:
72 UNIMPLEMENTED();
73 return Nothing<bool>();
74 }
75 }
76
77 void ValueSerializer::WriteOddball(Oddball* oddball) {
78 SerializationTag tag = SerializationTag::kUndefined;
79 switch (oddball->kind()) {
80 case Oddball::kUndefined:
81 tag = SerializationTag::kUndefined;
82 break;
83 case Oddball::kFalse:
84 tag = SerializationTag::kFalse;
85 break;
86 case Oddball::kTrue:
87 tag = SerializationTag::kTrue;
88 break;
89 case Oddball::kNull:
90 tag = SerializationTag::kNull;
91 break;
92 default:
93 UNREACHABLE();
94 break;
95 }
96 WriteTag(tag);
97 }
98
99 ValueDeserializer::ValueDeserializer(Isolate* isolate,
100 Vector<const uint8_t> data)
101 : isolate_(isolate),
102 position_(data.start()),
103 end_(data.start() + data.length()) {}
104
105 ValueDeserializer::~ValueDeserializer() {}
106
107 Maybe<bool> ValueDeserializer::ReadHeader() {
108 if (position_ < end_ &&
109 *position_ == static_cast<uint8_t>(SerializationTag::kVersion)) {
110 ReadTag().ToChecked();
111 if (!ReadVarint<uint32_t>().To(&version_)) return Nothing<bool>();
112 if (version_ > kLatestVersion) return Nothing<bool>();
113 }
114 return Just(true);
115 }
116
117 Maybe<SerializationTag> ValueDeserializer::ReadTag() {
118 SerializationTag tag;
119 do {
120 if (position_ >= end_) return Nothing<SerializationTag>();
121 tag = static_cast<SerializationTag>(*position_);
122 position_++;
123 } while (tag == SerializationTag::kPadding);
124 return Just(tag);
125 }
126
127 template <typename T>
128 Maybe<T> ValueDeserializer::ReadVarint() {
129 // Reads an unsigned integer as a base-128 varint.
130 // The number is written, 7 bits at a time, from the least significant to the
131 // most significant 7 bits. Each byte, except the last, has the MSB set.
132 // If the varint is larger than T, any more significant bits are discarded.
133 // See also https://developers.google.com/protocol-buffers/docs/encoding
134 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
135 "Only unsigned integer types can be read as varints.");
136 T value = 0;
137 unsigned shift = 0;
138 bool has_another_byte;
139 do {
140 if (position_ >= end_) return Nothing<T>();
141 uint8_t byte = *position_;
142 if (V8_LIKELY(shift < sizeof(T) * 8)) {
143 value |= (byte & 0x7f) << shift;
144 shift += 7;
145 }
146 has_another_byte = byte & 0x80;
147 position_++;
148 } while (has_another_byte);
149 return Just(value);
150 }
151
152 MaybeHandle<Object> ValueDeserializer::ReadObject() {
153 SerializationTag tag;
154 if (!ReadTag().To(&tag)) return MaybeHandle<Object>();
155 switch (tag) {
156 case SerializationTag::kVerifyObjectCount:
157 // Read the count and ignore it.
158 if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>();
159 return ReadObject();
160 case SerializationTag::kUndefined:
161 return isolate_->factory()->undefined_value();
162 case SerializationTag::kNull:
163 return isolate_->factory()->null_value();
164 case SerializationTag::kTrue:
165 return isolate_->factory()->true_value();
166 case SerializationTag::kFalse:
167 return isolate_->factory()->false_value();
168 default:
169 return MaybeHandle<Object>();
170 }
171 }
172
173 } // namespace internal
174 } // namespace v8
OLDNEW
« no previous file with comments | « src/value-serializer.h ('k') | test/unittests/unittests.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698