 Chromium Code Reviews
 Chromium Code Reviews Issue 2232243003:
  Blink-compatible serialization of oddball values.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 2232243003:
  Blink-compatible serialization of oddball values.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| Index: src/value-serializer.cc | 
| diff --git a/src/value-serializer.cc b/src/value-serializer.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..50fde61bdc73e7d067cc5429e55cd8f527770ae8 | 
| --- /dev/null | 
| +++ b/src/value-serializer.cc | 
| @@ -0,0 +1,165 @@ | 
| +// Copyright 2016 the V8 project authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "src/value-serializer.h" | 
| + | 
| +#include <type_traits> | 
| + | 
| +#include "src/base/logging.h" | 
| +#include "src/factory.h" | 
| +#include "src/handles-inl.h" | 
| +#include "src/isolate.h" | 
| +#include "src/objects-inl.h" | 
| +#include "src/objects.h" | 
| + | 
| +namespace v8 { | 
| +namespace internal { | 
| + | 
| +static const uint32_t kLatestVersion = 9; | 
| + | 
| +enum class SerializationTag : uint8_t { | 
| + kVersion = 0xFF, | 
| + kPadding = '\0', | 
| + kVerifyObjectCount = '?', | 
| + kUndefined = '_', | 
| + kNull = '0', | 
| + kTrue = 'T', | 
| + kFalse = 'F', | 
| +}; | 
| + | 
| +ValueSerializer::ValueSerializer() {} | 
| + | 
| +ValueSerializer::~ValueSerializer() {} | 
| + | 
| +void ValueSerializer::WriteHeader() { | 
| + WriteTag(SerializationTag::kVersion); | 
| + WriteVarint(kLatestVersion); | 
| +} | 
| + | 
| +void ValueSerializer::WriteTag(SerializationTag tag) { | 
| + buffer_.push_back(static_cast<uint8_t>(tag)); | 
| +} | 
| + | 
| +template <typename T> | 
| +void ValueSerializer::WriteVarint(T value) { | 
| + static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value, | 
| + "Only unsigned integer types can be written as varints."); | 
| + uint8_t stack_buffer[sizeof(T) * 8 / 7 + 1]; | 
| + uint8_t* next_byte = &stack_buffer[0]; | 
| + do { | 
| + *next_byte = (value & 0x7f) | 0x80; | 
| + next_byte++; | 
| + value >>= 7; | 
| + } while (value); | 
| + *(next_byte - 1) &= 0x7f; | 
| + buffer_.insert(buffer_.end(), stack_buffer, next_byte); | 
| +} | 
| + | 
| +Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { | 
| + if (object->IsSmi()) UNIMPLEMENTED(); | 
| + | 
| + DCHECK(object->IsHeapObject()); | 
| + 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
 | 
| + case ODDBALL_TYPE: | 
| + WriteOddball(Oddball::cast(*object)); | 
| + return Just(true); | 
| + default: | 
| + UNIMPLEMENTED(); | 
| + return Nothing<bool>(); | 
| + } | 
| +} | 
| + | 
| +void ValueSerializer::WriteOddball(Oddball* oddball) { | 
| + SerializationTag tag = SerializationTag::kUndefined; | 
| + switch (oddball->kind()) { | 
| + case Oddball::kUndefined: | 
| + tag = SerializationTag::kUndefined; | 
| + break; | 
| + case Oddball::kFalse: | 
| + tag = SerializationTag::kFalse; | 
| + break; | 
| + case Oddball::kTrue: | 
| + tag = SerializationTag::kTrue; | 
| + break; | 
| + case Oddball::kNull: | 
| + tag = SerializationTag::kNull; | 
| + break; | 
| + default: | 
| + UNREACHABLE(); | 
| + break; | 
| + } | 
| + WriteTag(tag); | 
| +} | 
| + | 
| +ValueDeserializer::ValueDeserializer(Isolate* isolate, | 
| + Vector<const uint8_t> data) | 
| + : isolate_(isolate), | 
| + position_(data.start()), | 
| + end_(data.start() + data.length()) {} | 
| + | 
| +ValueDeserializer::~ValueDeserializer() {} | 
| + | 
| +Maybe<bool> ValueDeserializer::ReadHeader() { | 
| + if (position_ < end_ && | 
| + *position_ == static_cast<uint8_t>(SerializationTag::kVersion)) { | 
| + ReadTag().ToChecked(); | 
| + if (!ReadVarint<uint32_t>().To(&version_)) return Nothing<bool>(); | 
| + if (version_ > kLatestVersion) return Nothing<bool>(); | 
| + } | 
| + return Just(true); | 
| +} | 
| + | 
| +Maybe<SerializationTag> ValueDeserializer::ReadTag() { | 
| + SerializationTag tag; | 
| + do { | 
| + if (position_ >= end_) return Nothing<SerializationTag>(); | 
| + tag = static_cast<SerializationTag>(*position_); | 
| + position_++; | 
| + } while (tag == SerializationTag::kPadding); | 
| + return Just(tag); | 
| +} | 
| + | 
| +template <typename T> | 
| +Maybe<T> ValueDeserializer::ReadVarint() { | 
| + static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value, | 
| + "Only unsigned integer types can be read as varints."); | 
| + T value = 0; | 
| + unsigned shift = 0; | 
| + bool has_another_byte; | 
| + do { | 
| + if (position_ >= end_) return Nothing<T>(); | 
| + uint8_t byte = *position_; | 
| + if (V8_LIKELY(shift < sizeof(T) * 8)) { | 
| + value |= (byte & 0x7f) << shift; | 
| + shift += 7; | 
| + } | 
| + has_another_byte = byte & 0x80; | 
| + position_++; | 
| + } while (has_another_byte); | 
| + return Just(value); | 
| +} | 
| + | 
| +MaybeHandle<Object> ValueDeserializer::ReadObject() { | 
| + SerializationTag tag; | 
| + if (!ReadTag().To(&tag)) return MaybeHandle<Object>(); | 
| + switch (tag) { | 
| + case SerializationTag::kVerifyObjectCount: | 
| + // Read the count and ignore it. | 
| + if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>(); | 
| + return ReadObject(); | 
| + case SerializationTag::kUndefined: | 
| + return isolate_->factory()->undefined_value(); | 
| + case SerializationTag::kNull: | 
| + return isolate_->factory()->null_value(); | 
| + case SerializationTag::kTrue: | 
| + return isolate_->factory()->true_value(); | 
| + case SerializationTag::kFalse: | 
| + return isolate_->factory()->false_value(); | 
| + default: | 
| + return MaybeHandle<Object>(); | 
| + } | 
| +} | 
| + | 
| +} // namespace internal | 
| +} // namespace v8 |