| 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 // Version 9: (imported from Blink) | 26 // Version 9: (imported from Blink) |
| 27 // Version 10: one-byte (Latin-1) strings | 27 // Version 10: one-byte (Latin-1) strings |
| 28 // Version 11: properly separate undefined from the hole in arrays | 28 // Version 11: properly separate undefined from the hole in arrays |
| 29 static const uint32_t kLatestVersion = 11; | 29 // Version 12: regexp and string objects share normal string encoding |
| 30 static const uint32_t kLatestVersion = 12; |
| 30 | 31 |
| 31 static const int kPretenureThreshold = 100 * KB; | 32 static const int kPretenureThreshold = 100 * KB; |
| 32 | 33 |
| 33 template <typename T> | 34 template <typename T> |
| 34 static size_t BytesNeededForVarint(T value) { | 35 static size_t BytesNeededForVarint(T value) { |
| 35 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value, | 36 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value, |
| 36 "Only unsigned integer types can be written as varints."); | 37 "Only unsigned integer types can be written as varints."); |
| 37 size_t result = 0; | 38 size_t result = 0; |
| 38 do { | 39 do { |
| 39 result++; | 40 result++; |
| (...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) { | 641 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) { |
| 641 Object* inner_value = value->value(); | 642 Object* inner_value = value->value(); |
| 642 if (inner_value->IsTrue(isolate_)) { | 643 if (inner_value->IsTrue(isolate_)) { |
| 643 WriteTag(SerializationTag::kTrueObject); | 644 WriteTag(SerializationTag::kTrueObject); |
| 644 } else if (inner_value->IsFalse(isolate_)) { | 645 } else if (inner_value->IsFalse(isolate_)) { |
| 645 WriteTag(SerializationTag::kFalseObject); | 646 WriteTag(SerializationTag::kFalseObject); |
| 646 } else if (inner_value->IsNumber()) { | 647 } else if (inner_value->IsNumber()) { |
| 647 WriteTag(SerializationTag::kNumberObject); | 648 WriteTag(SerializationTag::kNumberObject); |
| 648 WriteDouble(inner_value->Number()); | 649 WriteDouble(inner_value->Number()); |
| 649 } else if (inner_value->IsString()) { | 650 } else if (inner_value->IsString()) { |
| 650 // TODO(jbroman): Replace UTF-8 encoding with the same options available for | |
| 651 // ordinary strings. | |
| 652 WriteTag(SerializationTag::kStringObject); | 651 WriteTag(SerializationTag::kStringObject); |
| 653 v8::Local<v8::String> api_string = | 652 WriteString(handle(String::cast(inner_value), isolate_)); |
| 654 Utils::ToLocal(handle(String::cast(inner_value), isolate_)); | |
| 655 uint32_t utf8_length = api_string->Utf8Length(); | |
| 656 WriteVarint(utf8_length); | |
| 657 uint8_t* dest; | |
| 658 if (ReserveRawBytes(utf8_length).To(&dest)) { | |
| 659 api_string->WriteUtf8(reinterpret_cast<char*>(dest), utf8_length, nullptr, | |
| 660 v8::String::NO_NULL_TERMINATION); | |
| 661 } | |
| 662 } else { | 653 } else { |
| 663 DCHECK(inner_value->IsSymbol()); | 654 DCHECK(inner_value->IsSymbol()); |
| 664 ThrowDataCloneError(MessageTemplate::kDataCloneError, value); | 655 ThrowDataCloneError(MessageTemplate::kDataCloneError, value); |
| 665 return Nothing<bool>(); | 656 return Nothing<bool>(); |
| 666 } | 657 } |
| 667 return ThrowIfOutOfMemory(); | 658 return ThrowIfOutOfMemory(); |
| 668 } | 659 } |
| 669 | 660 |
| 670 void ValueSerializer::WriteJSRegExp(JSRegExp* regexp) { | 661 void ValueSerializer::WriteJSRegExp(JSRegExp* regexp) { |
| 671 WriteTag(SerializationTag::kRegExp); | 662 WriteTag(SerializationTag::kRegExp); |
| 672 v8::Local<v8::String> api_string = | 663 WriteString(handle(regexp->Pattern(), isolate_)); |
| 673 Utils::ToLocal(handle(regexp->Pattern(), isolate_)); | |
| 674 uint32_t utf8_length = api_string->Utf8Length(); | |
| 675 WriteVarint(utf8_length); | |
| 676 uint8_t* dest; | |
| 677 if (ReserveRawBytes(utf8_length).To(&dest)) { | |
| 678 api_string->WriteUtf8(reinterpret_cast<char*>(dest), utf8_length, nullptr, | |
| 679 v8::String::NO_NULL_TERMINATION); | |
| 680 } | |
| 681 WriteVarint(static_cast<uint32_t>(regexp->GetFlags())); | 664 WriteVarint(static_cast<uint32_t>(regexp->GetFlags())); |
| 682 } | 665 } |
| 683 | 666 |
| 684 Maybe<bool> ValueSerializer::WriteJSMap(Handle<JSMap> map) { | 667 Maybe<bool> ValueSerializer::WriteJSMap(Handle<JSMap> map) { |
| 685 // First copy the key-value pairs, since getters could mutate them. | 668 // First copy the key-value pairs, since getters could mutate them. |
| 686 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table())); | 669 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table())); |
| 687 int length = table->NumberOfElements() * 2; | 670 int length = table->NumberOfElements() * 2; |
| 688 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length); | 671 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length); |
| 689 { | 672 { |
| 690 DisallowHeapAllocation no_gc; | 673 DisallowHeapAllocation no_gc; |
| (...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1151 case SerializationTag::kWasmModule: | 1134 case SerializationTag::kWasmModule: |
| 1152 return ReadWasmModule(); | 1135 return ReadWasmModule(); |
| 1153 default: | 1136 default: |
| 1154 // TODO(jbroman): Introduce an explicit tag for host objects to avoid | 1137 // TODO(jbroman): Introduce an explicit tag for host objects to avoid |
| 1155 // having to treat every unknown tag as a potential host object. | 1138 // having to treat every unknown tag as a potential host object. |
| 1156 position_--; | 1139 position_--; |
| 1157 return ReadHostObject(); | 1140 return ReadHostObject(); |
| 1158 } | 1141 } |
| 1159 } | 1142 } |
| 1160 | 1143 |
| 1144 MaybeHandle<String> ValueDeserializer::ReadString() { |
| 1145 if (version_ < 12) return ReadUtf8String(); |
| 1146 Handle<Object> object; |
| 1147 if (!ReadObject().ToHandle(&object) || !object->IsString()) { |
| 1148 return MaybeHandle<String>(); |
| 1149 } |
| 1150 return Handle<String>::cast(object); |
| 1151 } |
| 1152 |
| 1161 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { | 1153 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { |
| 1162 uint32_t utf8_length; | 1154 uint32_t utf8_length; |
| 1163 Vector<const uint8_t> utf8_bytes; | 1155 Vector<const uint8_t> utf8_bytes; |
| 1164 if (!ReadVarint<uint32_t>().To(&utf8_length) || | 1156 if (!ReadVarint<uint32_t>().To(&utf8_length) || |
| 1165 utf8_length > | 1157 utf8_length > |
| 1166 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) || | 1158 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) || |
| 1167 !ReadRawBytes(utf8_length).To(&utf8_bytes)) { | 1159 !ReadRawBytes(utf8_length).To(&utf8_bytes)) { |
| 1168 return MaybeHandle<String>(); | 1160 return MaybeHandle<String>(); |
| 1169 } | 1161 } |
| 1170 return isolate_->factory()->NewStringFromUtf8( | 1162 return isolate_->factory()->NewStringFromUtf8( |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1389 if (!ReadDouble().To(&number)) return MaybeHandle<JSValue>(); | 1381 if (!ReadDouble().To(&number)) return MaybeHandle<JSValue>(); |
| 1390 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject( | 1382 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject( |
| 1391 isolate_->number_function(), pretenure_)); | 1383 isolate_->number_function(), pretenure_)); |
| 1392 Handle<Object> number_object = | 1384 Handle<Object> number_object = |
| 1393 isolate_->factory()->NewNumber(number, pretenure_); | 1385 isolate_->factory()->NewNumber(number, pretenure_); |
| 1394 value->set_value(*number_object); | 1386 value->set_value(*number_object); |
| 1395 break; | 1387 break; |
| 1396 } | 1388 } |
| 1397 case SerializationTag::kStringObject: { | 1389 case SerializationTag::kStringObject: { |
| 1398 Handle<String> string; | 1390 Handle<String> string; |
| 1399 if (!ReadUtf8String().ToHandle(&string)) return MaybeHandle<JSValue>(); | 1391 if (!ReadString().ToHandle(&string)) return MaybeHandle<JSValue>(); |
| 1400 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject( | 1392 value = Handle<JSValue>::cast(isolate_->factory()->NewJSObject( |
| 1401 isolate_->string_function(), pretenure_)); | 1393 isolate_->string_function(), pretenure_)); |
| 1402 value->set_value(*string); | 1394 value->set_value(*string); |
| 1403 break; | 1395 break; |
| 1404 } | 1396 } |
| 1405 default: | 1397 default: |
| 1406 UNREACHABLE(); | 1398 UNREACHABLE(); |
| 1407 return MaybeHandle<JSValue>(); | 1399 return MaybeHandle<JSValue>(); |
| 1408 } | 1400 } |
| 1409 AddObjectWithID(id, value); | 1401 AddObjectWithID(id, value); |
| 1410 return value; | 1402 return value; |
| 1411 } | 1403 } |
| 1412 | 1404 |
| 1413 MaybeHandle<JSRegExp> ValueDeserializer::ReadJSRegExp() { | 1405 MaybeHandle<JSRegExp> ValueDeserializer::ReadJSRegExp() { |
| 1414 uint32_t id = next_id_++; | 1406 uint32_t id = next_id_++; |
| 1415 Handle<String> pattern; | 1407 Handle<String> pattern; |
| 1416 uint32_t raw_flags; | 1408 uint32_t raw_flags; |
| 1417 Handle<JSRegExp> regexp; | 1409 Handle<JSRegExp> regexp; |
| 1418 if (!ReadUtf8String().ToHandle(&pattern) || | 1410 if (!ReadString().ToHandle(&pattern) || |
| 1419 !ReadVarint<uint32_t>().To(&raw_flags) || | 1411 !ReadVarint<uint32_t>().To(&raw_flags) || |
| 1420 !JSRegExp::New(pattern, static_cast<JSRegExp::Flags>(raw_flags)) | 1412 !JSRegExp::New(pattern, static_cast<JSRegExp::Flags>(raw_flags)) |
| 1421 .ToHandle(®exp)) { | 1413 .ToHandle(®exp)) { |
| 1422 return MaybeHandle<JSRegExp>(); | 1414 return MaybeHandle<JSRegExp>(); |
| 1423 } | 1415 } |
| 1424 AddObjectWithID(id, regexp); | 1416 AddObjectWithID(id, regexp); |
| 1425 return regexp; | 1417 return regexp; |
| 1426 } | 1418 } |
| 1427 | 1419 |
| 1428 MaybeHandle<JSMap> ValueDeserializer::ReadJSMap() { | 1420 MaybeHandle<JSMap> ValueDeserializer::ReadJSMap() { |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1934 if (stack.size() != 1) { | 1926 if (stack.size() != 1) { |
| 1935 isolate_->Throw(*isolate_->factory()->NewError( | 1927 isolate_->Throw(*isolate_->factory()->NewError( |
| 1936 MessageTemplate::kDataCloneDeserializationError)); | 1928 MessageTemplate::kDataCloneDeserializationError)); |
| 1937 return MaybeHandle<Object>(); | 1929 return MaybeHandle<Object>(); |
| 1938 } | 1930 } |
| 1939 return scope.CloseAndEscape(stack[0]); | 1931 return scope.CloseAndEscape(stack[0]); |
| 1940 } | 1932 } |
| 1941 | 1933 |
| 1942 } // namespace internal | 1934 } // namespace internal |
| 1943 } // namespace v8 | 1935 } // namespace v8 |
| OLD | NEW |