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

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: static_cast in unit tests 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
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 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
47 "Only unsigned integer types can be written as varints.");
48 uint8_t stack_buffer[sizeof(T) * 8 / 7 + 1];
49 uint8_t* next_byte = &stack_buffer[0];
50 do {
51 *next_byte = (value & 0x7f) | 0x80;
52 next_byte++;
53 value >>= 7;
54 } while (value);
55 *(next_byte - 1) &= 0x7f;
56 buffer_.insert(buffer_.end(), stack_buffer, next_byte);
57 }
58
59 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) {
60 if (object->IsSmi()) UNIMPLEMENTED();
61
62 DCHECK(object->IsHeapObject());
63 switch (HeapObject::cast(*object)->map()->instance_type()) {
Camillo Bruni 2016/08/12 09:54:44 This is much slower than directly comparing agains
jbroman 2016/08/12 15:16:34 I'll be branching on the instance type of all obje
64 case ODDBALL_TYPE:
65 WriteOddball(Oddball::cast(*object));
66 return Just(true);
67 default:
68 UNIMPLEMENTED();
69 return Nothing<bool>();
70 }
71 }
72
73 void ValueSerializer::WriteOddball(Oddball* oddball) {
74 SerializationTag tag = SerializationTag::kUndefined;
75 switch (oddball->kind()) {
76 case Oddball::kUndefined:
77 tag = SerializationTag::kUndefined;
78 break;
79 case Oddball::kFalse:
80 tag = SerializationTag::kFalse;
81 break;
82 case Oddball::kTrue:
83 tag = SerializationTag::kTrue;
84 break;
85 case Oddball::kNull:
86 tag = SerializationTag::kNull;
87 break;
88 default:
89 UNREACHABLE();
90 break;
91 }
92 WriteTag(tag);
93 }
94
95 ValueDeserializer::ValueDeserializer(Isolate* isolate,
96 Vector<const uint8_t> data)
97 : isolate_(isolate),
98 position_(data.start()),
99 end_(data.start() + data.length()) {}
100
101 ValueDeserializer::~ValueDeserializer() {}
102
103 Maybe<bool> ValueDeserializer::ReadHeader() {
104 if (position_ < end_ &&
105 *position_ == static_cast<uint8_t>(SerializationTag::kVersion)) {
106 ReadTag().ToChecked();
107 if (!ReadVarint<uint32_t>().To(&version_)) return Nothing<bool>();
108 if (version_ > kLatestVersion) return Nothing<bool>();
109 }
110 return Just(true);
111 }
112
113 Maybe<SerializationTag> ValueDeserializer::ReadTag() {
114 SerializationTag tag;
115 do {
116 if (position_ >= end_) return Nothing<SerializationTag>();
117 tag = static_cast<SerializationTag>(*position_);
118 position_++;
119 } while (tag == SerializationTag::kPadding);
120 return Just(tag);
121 }
122
123 template <typename T>
124 Maybe<T> ValueDeserializer::ReadVarint() {
125 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
126 "Only unsigned integer types can be read as varints.");
127 T value = 0;
128 unsigned shift = 0;
129 bool has_another_byte;
130 do {
131 if (position_ >= end_) return Nothing<T>();
132 uint8_t byte = *position_;
133 if (V8_LIKELY(shift < sizeof(T) * 8)) {
134 value |= (byte & 0x7f) << shift;
135 shift += 7;
136 }
137 has_another_byte = byte & 0x80;
138 position_++;
139 } while (has_another_byte);
140 return Just(value);
141 }
142
143 MaybeHandle<Object> ValueDeserializer::ReadObject() {
144 SerializationTag tag;
145 if (!ReadTag().To(&tag)) return MaybeHandle<Object>();
146 switch (tag) {
147 case SerializationTag::kVerifyObjectCount:
148 // Read the count and ignore it.
149 if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>();
150 return ReadObject();
151 case SerializationTag::kUndefined:
152 return isolate_->factory()->undefined_value();
153 case SerializationTag::kNull:
154 return isolate_->factory()->null_value();
155 case SerializationTag::kTrue:
156 return isolate_->factory()->true_value();
157 case SerializationTag::kFalse:
158 return isolate_->factory()->false_value();
159 default:
160 return MaybeHandle<Object>();
161 }
162 }
163
164 } // namespace internal
165 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698