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

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

Issue 2658793004: ValueSerializer: Support efficiently reading and writing one-byte strings. (Closed)
Patch Set: merge with master Created 3 years, 10 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/conversions.h" 10 #include "src/conversions.h"
11 #include "src/factory.h" 11 #include "src/factory.h"
12 #include "src/flags.h" 12 #include "src/flags.h"
13 #include "src/handles-inl.h" 13 #include "src/handles-inl.h"
14 #include "src/isolate.h" 14 #include "src/isolate.h"
15 #include "src/objects-inl.h" 15 #include "src/objects-inl.h"
16 #include "src/objects.h" 16 #include "src/objects.h"
17 #include "src/snapshot/code-serializer.h" 17 #include "src/snapshot/code-serializer.h"
18 #include "src/transitions.h" 18 #include "src/transitions.h"
19 #include "src/wasm/wasm-module.h" 19 #include "src/wasm/wasm-module.h"
20 #include "src/wasm/wasm-objects.h" 20 #include "src/wasm/wasm-objects.h"
21 #include "src/wasm/wasm-result.h" 21 #include "src/wasm/wasm-result.h"
22 22
23 namespace v8 { 23 namespace v8 {
24 namespace internal { 24 namespace internal {
25 25
26 static const uint32_t kLatestVersion = 9; 26 // Version 9: (imported from Blink)
27 // Version 10: one-byte (Latin-1) strings
28 static const uint32_t kLatestVersion = 10;
29
27 static const int kPretenureThreshold = 100 * KB; 30 static const int kPretenureThreshold = 100 * KB;
28 31
29 template <typename T> 32 template <typename T>
30 static size_t BytesNeededForVarint(T value) { 33 static size_t BytesNeededForVarint(T value) {
31 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value, 34 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
32 "Only unsigned integer types can be written as varints."); 35 "Only unsigned integer types can be written as varints.");
33 size_t result = 0; 36 size_t result = 0;
34 do { 37 do {
35 result++; 38 result++;
36 value >>= 7; 39 value >>= 7;
(...skipping 17 matching lines...) Expand all
54 // (like sint32 in protobuf) 57 // (like sint32 in protobuf)
55 kInt32 = 'I', 58 kInt32 = 'I',
56 // Number represented as 32-bit unsigned integer, varint-encoded 59 // Number represented as 32-bit unsigned integer, varint-encoded
57 // (like uint32 in protobuf) 60 // (like uint32 in protobuf)
58 kUint32 = 'U', 61 kUint32 = 'U',
59 // Number represented as a 64-bit double. 62 // Number represented as a 64-bit double.
60 // Host byte order is used (N.B. this makes the format non-portable). 63 // Host byte order is used (N.B. this makes the format non-portable).
61 kDouble = 'N', 64 kDouble = 'N',
62 // byteLength:uint32_t, then raw data 65 // byteLength:uint32_t, then raw data
63 kUtf8String = 'S', 66 kUtf8String = 'S',
67 kOneByteString = '"',
64 kTwoByteString = 'c', 68 kTwoByteString = 'c',
65 // Reference to a serialized object. objectID:uint32_t 69 // Reference to a serialized object. objectID:uint32_t
66 kObjectReference = '^', 70 kObjectReference = '^',
67 // Beginning of a JS object. 71 // Beginning of a JS object.
68 kBeginJSObject = 'o', 72 kBeginJSObject = 'o',
69 // End of a JS object. numProperties:uint32_t 73 // End of a JS object. numProperties:uint32_t
70 kEndJSObject = '{', 74 kEndJSObject = '{',
71 // Beginning of a sparse JS array. length:uint32_t 75 // Beginning of a sparse JS array. length:uint32_t
72 // Elements and properties are written as key/value pairs, like objects. 76 // Elements and properties are written as key/value pairs, like objects.
73 kBeginSparseJSArray = 'a', 77 kBeginSparseJSArray = 'a',
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 WriteTag(SerializationTag::kDouble); 369 WriteTag(SerializationTag::kDouble);
366 WriteDouble(number->value()); 370 WriteDouble(number->value());
367 } 371 }
368 372
369 void ValueSerializer::WriteString(Handle<String> string) { 373 void ValueSerializer::WriteString(Handle<String> string) {
370 string = String::Flatten(string); 374 string = String::Flatten(string);
371 DisallowHeapAllocation no_gc; 375 DisallowHeapAllocation no_gc;
372 String::FlatContent flat = string->GetFlatContent(); 376 String::FlatContent flat = string->GetFlatContent();
373 DCHECK(flat.IsFlat()); 377 DCHECK(flat.IsFlat());
374 if (flat.IsOneByte()) { 378 if (flat.IsOneByte()) {
375 // The existing format uses UTF-8, rather than Latin-1. As a result we must
376 // to do work to encode strings that have characters outside ASCII.
377 // TODO(jbroman): In a future format version, consider adding a tag for
378 // Latin-1 strings, so that this can be skipped.
379 WriteTag(SerializationTag::kUtf8String);
380 Vector<const uint8_t> chars = flat.ToOneByteVector(); 379 Vector<const uint8_t> chars = flat.ToOneByteVector();
381 if (String::IsAscii(chars.begin(), chars.length())) { 380 WriteTag(SerializationTag::kOneByteString);
382 WriteOneByteString(chars); 381 WriteOneByteString(chars);
383 } else {
384 v8::Local<v8::String> api_string = Utils::ToLocal(string);
385 uint32_t utf8_length = api_string->Utf8Length();
386 WriteVarint(utf8_length);
387 uint8_t* dest;
388 if (ReserveRawBytes(utf8_length).To(&dest)) {
389 api_string->WriteUtf8(reinterpret_cast<char*>(dest), utf8_length,
390 nullptr, v8::String::NO_NULL_TERMINATION);
391 }
392 }
393 } else if (flat.IsTwoByte()) { 382 } else if (flat.IsTwoByte()) {
394 Vector<const uc16> chars = flat.ToUC16Vector(); 383 Vector<const uc16> chars = flat.ToUC16Vector();
395 uint32_t byte_length = chars.length() * sizeof(uc16); 384 uint32_t byte_length = chars.length() * sizeof(uc16);
396 // The existing reading code expects 16-byte strings to be aligned. 385 // The existing reading code expects 16-byte strings to be aligned.
397 if ((buffer_size_ + 1 + BytesNeededForVarint(byte_length)) & 1) 386 if ((buffer_size_ + 1 + BytesNeededForVarint(byte_length)) & 1)
398 WriteTag(SerializationTag::kPadding); 387 WriteTag(SerializationTag::kPadding);
399 WriteTag(SerializationTag::kTwoByteString); 388 WriteTag(SerializationTag::kTwoByteString);
400 WriteTwoByteString(chars); 389 WriteTwoByteString(chars);
401 } else { 390 } else {
402 UNREACHABLE(); 391 UNREACHABLE();
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after
1109 return isolate_->factory()->NewNumberFromUint(number.FromJust(), 1098 return isolate_->factory()->NewNumberFromUint(number.FromJust(),
1110 pretenure_); 1099 pretenure_);
1111 } 1100 }
1112 case SerializationTag::kDouble: { 1101 case SerializationTag::kDouble: {
1113 Maybe<double> number = ReadDouble(); 1102 Maybe<double> number = ReadDouble();
1114 if (number.IsNothing()) return MaybeHandle<Object>(); 1103 if (number.IsNothing()) return MaybeHandle<Object>();
1115 return isolate_->factory()->NewNumber(number.FromJust(), pretenure_); 1104 return isolate_->factory()->NewNumber(number.FromJust(), pretenure_);
1116 } 1105 }
1117 case SerializationTag::kUtf8String: 1106 case SerializationTag::kUtf8String:
1118 return ReadUtf8String(); 1107 return ReadUtf8String();
1108 case SerializationTag::kOneByteString:
1109 return ReadOneByteString();
1119 case SerializationTag::kTwoByteString: 1110 case SerializationTag::kTwoByteString:
1120 return ReadTwoByteString(); 1111 return ReadTwoByteString();
1121 case SerializationTag::kObjectReference: { 1112 case SerializationTag::kObjectReference: {
1122 uint32_t id; 1113 uint32_t id;
1123 if (!ReadVarint<uint32_t>().To(&id)) return MaybeHandle<Object>(); 1114 if (!ReadVarint<uint32_t>().To(&id)) return MaybeHandle<Object>();
1124 return GetObjectWithID(id); 1115 return GetObjectWithID(id);
1125 } 1116 }
1126 case SerializationTag::kBeginJSObject: 1117 case SerializationTag::kBeginJSObject:
1127 return ReadJSObject(); 1118 return ReadJSObject();
1128 case SerializationTag::kBeginSparseJSArray: 1119 case SerializationTag::kBeginSparseJSArray:
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1168 if (!ReadVarint<uint32_t>().To(&utf8_length) || 1159 if (!ReadVarint<uint32_t>().To(&utf8_length) ||
1169 utf8_length > 1160 utf8_length >
1170 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) || 1161 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1171 !ReadRawBytes(utf8_length).To(&utf8_bytes)) { 1162 !ReadRawBytes(utf8_length).To(&utf8_bytes)) {
1172 return MaybeHandle<String>(); 1163 return MaybeHandle<String>();
1173 } 1164 }
1174 return isolate_->factory()->NewStringFromUtf8( 1165 return isolate_->factory()->NewStringFromUtf8(
1175 Vector<const char>::cast(utf8_bytes), pretenure_); 1166 Vector<const char>::cast(utf8_bytes), pretenure_);
1176 } 1167 }
1177 1168
1169 MaybeHandle<String> ValueDeserializer::ReadOneByteString() {
1170 uint32_t byte_length;
1171 Vector<const uint8_t> bytes;
1172 if (!ReadVarint<uint32_t>().To(&byte_length) ||
1173 byte_length >
1174 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1175 !ReadRawBytes(byte_length).To(&bytes)) {
1176 return MaybeHandle<String>();
1177 }
1178 return isolate_->factory()->NewStringFromOneByte(bytes, pretenure_);
1179 }
1180
1178 MaybeHandle<String> ValueDeserializer::ReadTwoByteString() { 1181 MaybeHandle<String> ValueDeserializer::ReadTwoByteString() {
1179 uint32_t byte_length; 1182 uint32_t byte_length;
1180 Vector<const uint8_t> bytes; 1183 Vector<const uint8_t> bytes;
1181 if (!ReadVarint<uint32_t>().To(&byte_length) || 1184 if (!ReadVarint<uint32_t>().To(&byte_length) ||
1182 byte_length > 1185 byte_length >
1183 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) || 1186 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
1184 byte_length % sizeof(uc16) != 0 || 1187 byte_length % sizeof(uc16) != 0 ||
1185 !ReadRawBytes(byte_length).To(&bytes)) { 1188 !ReadRawBytes(byte_length).To(&bytes)) {
1186 return MaybeHandle<String>(); 1189 return MaybeHandle<String>();
1187 } 1190 }
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after
1916 if (stack.size() != 1) { 1919 if (stack.size() != 1) {
1917 isolate_->Throw(*isolate_->factory()->NewError( 1920 isolate_->Throw(*isolate_->factory()->NewError(
1918 MessageTemplate::kDataCloneDeserializationError)); 1921 MessageTemplate::kDataCloneDeserializationError));
1919 return MaybeHandle<Object>(); 1922 return MaybeHandle<Object>();
1920 } 1923 }
1921 return scope.CloseAndEscape(stack[0]); 1924 return scope.CloseAndEscape(stack[0]);
1922 } 1925 }
1923 1926
1924 } // namespace internal 1927 } // namespace internal
1925 } // namespace v8 1928 } // 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