| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |