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 |