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

Unified Diff: src/value-serializer.cc

Issue 2768923002: WIP: Allow ValueSerializer clients to transfer long strings out of band.
Patch Set: Created 3 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/value-serializer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/value-serializer.cc
diff --git a/src/value-serializer.cc b/src/value-serializer.cc
index 4b8b454c5d6e89a509cd06b10d77d71fb75e9b7b..330ba5557b616663f5efd8f9a75762d1a7aae1b3 100644
--- a/src/value-serializer.cc
+++ b/src/value-serializer.cc
@@ -71,6 +71,8 @@ enum class SerializationTag : uint8_t {
kUtf8String = 'S',
kOneByteString = '"',
kTwoByteString = 'c',
+ // ID:uint32_t. Only used if the client requests it.
+ kLongString = '>',
// Reference to a serialized object. objectID:uint32_t
kObjectReference = '^',
// Beginning of a JS object.
@@ -160,8 +162,8 @@ ValueSerializer::ValueSerializer(Isolate* isolate,
delegate_(delegate),
zone_(isolate->allocator(), ZONE_NAME),
id_map_(isolate->heap(), ZoneAllocationPolicy(&zone_)),
- array_buffer_transfer_map_(isolate->heap(),
- ZoneAllocationPolicy(&zone_)) {}
+ array_buffer_transfer_map_(isolate->heap(), ZoneAllocationPolicy(&zone_)),
+ long_string_map_(isolate->heap(), ZoneAllocationPolicy(&zone_)) {}
ValueSerializer::~ValueSerializer() {
if (buffer_) {
@@ -341,8 +343,7 @@ Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) {
}
default:
if (object->IsString()) {
- WriteString(Handle<String>::cast(object));
- return ThrowIfOutOfMemory();
+ return WriteString(Handle<String>::cast(object));
} else if (object->IsJSReceiver()) {
return WriteJSReceiver(Handle<JSReceiver>::cast(object));
} else {
@@ -385,7 +386,22 @@ void ValueSerializer::WriteHeapNumber(HeapNumber* number) {
WriteDouble(number->value());
}
-void ValueSerializer::WriteString(Handle<String> string) {
+Maybe<bool> ValueSerializer::WriteString(Handle<String> string) {
+ if (long_string_threshold_ >= 0 &&
+ V8_UNLIKELY(string->length() >= long_string_threshold_)) {
+ uint32_t* entry = long_string_map_.Find(string);
+ if (!entry) {
+ entry = long_string_map_.Get(string);
+ Maybe<uint32_t> index = delegate_->GetLongStringId(
+ reinterpret_cast<v8::Isolate*>(isolate_), Utils::ToLocal(string));
+ RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
+ *entry = index.FromJust();
+ }
+ WriteTag(SerializationTag::kLongString);
+ WriteVarint(*entry);
+ return ThrowIfOutOfMemory();
+ }
+
string = String::Flatten(string);
DisallowHeapAllocation no_gc;
String::FlatContent flat = string->GetFlatContent();
@@ -405,6 +421,7 @@ void ValueSerializer::WriteString(Handle<String> string) {
} else {
UNREACHABLE();
}
+ return ThrowIfOutOfMemory();
}
Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
@@ -1069,6 +1086,26 @@ void ValueDeserializer::TransferArrayBuffer(
}
}
+void ValueDeserializer::TransferLongString(uint32_t transfer_id,
+ Handle<String> string) {
+ if (long_string_map_.is_null()) {
+ long_string_map_ =
+ Handle<SeededNumberDictionary>::cast(isolate_->global_handles()->Create(
+ *SeededNumberDictionary::New(isolate_, 0)));
+ }
+ Handle<SeededNumberDictionary> dictionary =
+ long_string_map_.ToHandleChecked();
+ Handle<JSObject> not_a_prototype_holder;
+ Handle<SeededNumberDictionary> new_dictionary =
+ SeededNumberDictionary::AtNumberPut(dictionary, transfer_id, string,
+ not_a_prototype_holder);
+ if (!new_dictionary.is_identical_to(dictionary)) {
+ GlobalHandles::Destroy(Handle<Object>::cast(dictionary).location());
+ long_string_map_ = Handle<SeededNumberDictionary>::cast(
+ isolate_->global_handles()->Create(*new_dictionary));
+ }
+}
+
MaybeHandle<Object> ValueDeserializer::ReadObject() {
MaybeHandle<Object> result = ReadObjectInternal();
@@ -1129,6 +1166,8 @@ MaybeHandle<Object> ValueDeserializer::ReadObjectInternal() {
return ReadOneByteString();
case SerializationTag::kTwoByteString:
return ReadTwoByteString();
+ case SerializationTag::kLongString:
+ return ReadLongString();
case SerializationTag::kObjectReference: {
uint32_t id;
if (!ReadVarint<uint32_t>().To(&id)) return MaybeHandle<Object>();
@@ -1241,6 +1280,20 @@ MaybeHandle<String> ValueDeserializer::ReadTwoByteString() {
return string;
}
+MaybeHandle<String> ValueDeserializer::ReadLongString() {
+ uint32_t transfer_id;
+ Handle<SeededNumberDictionary> transfer_map;
+ if (!ReadVarint<uint32_t>().To(&transfer_id) ||
+ !long_string_map_.ToHandle(&transfer_map)) {
+ return MaybeHandle<String>();
+ }
+ int index = transfer_map->FindEntry(isolate_, transfer_id);
+ if (index == SeededNumberDictionary::kNotFound) {
+ return MaybeHandle<String>();
+ }
+ return handle(String::cast(transfer_map->ValueAt(index)), isolate_);
+}
+
bool ValueDeserializer::ReadExpectedString(Handle<String> expected) {
// In the case of failure, the position in the stream is reset.
const uint8_t* original_position = position_;
« no previous file with comments | « src/value-serializer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698