| 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/factory.h" | 10 #include "src/factory.h" |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 // Boolean object. No data. | 75 // Boolean object. No data. |
| 76 kTrueObject = 'y', | 76 kTrueObject = 'y', |
| 77 kFalseObject = 'x', | 77 kFalseObject = 'x', |
| 78 // Number object. value:double | 78 // Number object. value:double |
| 79 kNumberObject = 'n', | 79 kNumberObject = 'n', |
| 80 // String object, UTF-8 encoding. byteLength:uint32_t, then raw data. | 80 // String object, UTF-8 encoding. byteLength:uint32_t, then raw data. |
| 81 kStringObject = 's', | 81 kStringObject = 's', |
| 82 // Regular expression, UTF-8 encoding. byteLength:uint32_t, raw data, | 82 // Regular expression, UTF-8 encoding. byteLength:uint32_t, raw data, |
| 83 // flags:uint32_t. | 83 // flags:uint32_t. |
| 84 kRegExp = 'R', | 84 kRegExp = 'R', |
| 85 // Beginning of a JS map. |
| 86 kBeginJSMap = ';', |
| 87 // End of a JS map. length:uint32_t. |
| 88 kEndJSMap = ':', |
| 89 // Beginning of a JS set. |
| 90 kBeginJSSet = '\'', |
| 91 // End of a JS set. length:uint32_t. |
| 92 kEndJSSet = ',', |
| 85 }; | 93 }; |
| 86 | 94 |
| 87 ValueSerializer::ValueSerializer(Isolate* isolate) | 95 ValueSerializer::ValueSerializer(Isolate* isolate) |
| 88 : isolate_(isolate), | 96 : isolate_(isolate), |
| 89 zone_(isolate->allocator()), | 97 zone_(isolate->allocator()), |
| 90 id_map_(isolate->heap(), &zone_) {} | 98 id_map_(isolate->heap(), &zone_) {} |
| 91 | 99 |
| 92 ValueSerializer::~ValueSerializer() {} | 100 ValueSerializer::~ValueSerializer() {} |
| 93 | 101 |
| 94 void ValueSerializer::WriteHeader() { | 102 void ValueSerializer::WriteHeader() { |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 case JS_API_OBJECT_TYPE: | 290 case JS_API_OBJECT_TYPE: |
| 283 return WriteJSObject(Handle<JSObject>::cast(receiver)); | 291 return WriteJSObject(Handle<JSObject>::cast(receiver)); |
| 284 case JS_DATE_TYPE: | 292 case JS_DATE_TYPE: |
| 285 WriteJSDate(JSDate::cast(*receiver)); | 293 WriteJSDate(JSDate::cast(*receiver)); |
| 286 return Just(true); | 294 return Just(true); |
| 287 case JS_VALUE_TYPE: | 295 case JS_VALUE_TYPE: |
| 288 return WriteJSValue(Handle<JSValue>::cast(receiver)); | 296 return WriteJSValue(Handle<JSValue>::cast(receiver)); |
| 289 case JS_REGEXP_TYPE: | 297 case JS_REGEXP_TYPE: |
| 290 WriteJSRegExp(JSRegExp::cast(*receiver)); | 298 WriteJSRegExp(JSRegExp::cast(*receiver)); |
| 291 return Just(true); | 299 return Just(true); |
| 300 case JS_MAP_TYPE: |
| 301 return WriteJSMap(Handle<JSMap>::cast(receiver)); |
| 302 case JS_SET_TYPE: |
| 303 return WriteJSSet(Handle<JSSet>::cast(receiver)); |
| 292 default: | 304 default: |
| 293 UNIMPLEMENTED(); | 305 UNIMPLEMENTED(); |
| 294 break; | 306 break; |
| 295 } | 307 } |
| 296 return Nothing<bool>(); | 308 return Nothing<bool>(); |
| 297 } | 309 } |
| 298 | 310 |
| 299 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) { | 311 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) { |
| 300 WriteTag(SerializationTag::kBeginJSObject); | 312 WriteTag(SerializationTag::kBeginJSObject); |
| 301 Handle<FixedArray> keys; | 313 Handle<FixedArray> keys; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 WriteTag(SerializationTag::kRegExp); | 422 WriteTag(SerializationTag::kRegExp); |
| 411 v8::Local<v8::String> api_string = | 423 v8::Local<v8::String> api_string = |
| 412 Utils::ToLocal(handle(regexp->Pattern(), isolate_)); | 424 Utils::ToLocal(handle(regexp->Pattern(), isolate_)); |
| 413 uint32_t utf8_length = api_string->Utf8Length(); | 425 uint32_t utf8_length = api_string->Utf8Length(); |
| 414 WriteVarint(utf8_length); | 426 WriteVarint(utf8_length); |
| 415 api_string->WriteUtf8(reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), | 427 api_string->WriteUtf8(reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), |
| 416 utf8_length, nullptr, v8::String::NO_NULL_TERMINATION); | 428 utf8_length, nullptr, v8::String::NO_NULL_TERMINATION); |
| 417 WriteVarint(static_cast<uint32_t>(regexp->GetFlags())); | 429 WriteVarint(static_cast<uint32_t>(regexp->GetFlags())); |
| 418 } | 430 } |
| 419 | 431 |
| 432 Maybe<bool> ValueSerializer::WriteJSMap(Handle<JSMap> map) { |
| 433 // First copy the key-value pairs, since getters could mutate them. |
| 434 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table())); |
| 435 int length = table->NumberOfElements() * 2; |
| 436 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length); |
| 437 { |
| 438 DisallowHeapAllocation no_gc; |
| 439 Oddball* the_hole = isolate_->heap()->the_hole_value(); |
| 440 int capacity = table->UsedCapacity(); |
| 441 int result_index = 0; |
| 442 for (int i = 0; i < capacity; i++) { |
| 443 Object* key = table->KeyAt(i); |
| 444 if (key == the_hole) continue; |
| 445 entries->set(result_index++, key); |
| 446 entries->set(result_index++, table->ValueAt(i)); |
| 447 } |
| 448 DCHECK_EQ(result_index, length); |
| 449 } |
| 450 |
| 451 // Then write it out. |
| 452 WriteTag(SerializationTag::kBeginJSMap); |
| 453 for (int i = 0; i < length; i++) { |
| 454 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { |
| 455 return Nothing<bool>(); |
| 456 } |
| 457 } |
| 458 WriteTag(SerializationTag::kEndJSMap); |
| 459 WriteVarint<uint32_t>(length); |
| 460 return Just(true); |
| 461 } |
| 462 |
| 463 Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet> set) { |
| 464 // First copy the element pointers, since getters could mutate them. |
| 465 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table())); |
| 466 int length = table->NumberOfElements(); |
| 467 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length); |
| 468 { |
| 469 DisallowHeapAllocation no_gc; |
| 470 Oddball* the_hole = isolate_->heap()->the_hole_value(); |
| 471 int capacity = table->UsedCapacity(); |
| 472 int result_index = 0; |
| 473 for (int i = 0; i < capacity; i++) { |
| 474 Object* key = table->KeyAt(i); |
| 475 if (key == the_hole) continue; |
| 476 entries->set(result_index++, key); |
| 477 } |
| 478 DCHECK_EQ(result_index, length); |
| 479 } |
| 480 |
| 481 // Then write it out. |
| 482 WriteTag(SerializationTag::kBeginJSSet); |
| 483 for (int i = 0; i < length; i++) { |
| 484 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { |
| 485 return Nothing<bool>(); |
| 486 } |
| 487 } |
| 488 WriteTag(SerializationTag::kEndJSSet); |
| 489 WriteVarint<uint32_t>(length); |
| 490 return Just(true); |
| 491 } |
| 492 |
| 420 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties( | 493 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties( |
| 421 Handle<JSObject> object, Handle<FixedArray> keys) { | 494 Handle<JSObject> object, Handle<FixedArray> keys) { |
| 422 uint32_t properties_written = 0; | 495 uint32_t properties_written = 0; |
| 423 int length = keys->length(); | 496 int length = keys->length(); |
| 424 for (int i = 0; i < length; i++) { | 497 for (int i = 0; i < length; i++) { |
| 425 Handle<Object> key(keys->get(i), isolate_); | 498 Handle<Object> key(keys->get(i), isolate_); |
| 426 | 499 |
| 427 bool success; | 500 bool success; |
| 428 LookupIterator it = LookupIterator::PropertyOrElement( | 501 LookupIterator it = LookupIterator::PropertyOrElement( |
| 429 isolate_, object, key, &success, LookupIterator::OWN); | 502 isolate_, object, key, &success, LookupIterator::OWN); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 return ReadDenseJSArray(); | 672 return ReadDenseJSArray(); |
| 600 case SerializationTag::kDate: | 673 case SerializationTag::kDate: |
| 601 return ReadJSDate(); | 674 return ReadJSDate(); |
| 602 case SerializationTag::kTrueObject: | 675 case SerializationTag::kTrueObject: |
| 603 case SerializationTag::kFalseObject: | 676 case SerializationTag::kFalseObject: |
| 604 case SerializationTag::kNumberObject: | 677 case SerializationTag::kNumberObject: |
| 605 case SerializationTag::kStringObject: | 678 case SerializationTag::kStringObject: |
| 606 return ReadJSValue(tag); | 679 return ReadJSValue(tag); |
| 607 case SerializationTag::kRegExp: | 680 case SerializationTag::kRegExp: |
| 608 return ReadJSRegExp(); | 681 return ReadJSRegExp(); |
| 682 case SerializationTag::kBeginJSMap: |
| 683 return ReadJSMap(); |
| 684 case SerializationTag::kBeginJSSet: |
| 685 return ReadJSSet(); |
| 609 default: | 686 default: |
| 610 return MaybeHandle<Object>(); | 687 return MaybeHandle<Object>(); |
| 611 } | 688 } |
| 612 } | 689 } |
| 613 | 690 |
| 614 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { | 691 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { |
| 615 uint32_t utf8_length; | 692 uint32_t utf8_length; |
| 616 Vector<const uint8_t> utf8_bytes; | 693 Vector<const uint8_t> utf8_bytes; |
| 617 if (!ReadVarint<uint32_t>().To(&utf8_length) || | 694 if (!ReadVarint<uint32_t>().To(&utf8_length) || |
| 618 utf8_length > | 695 utf8_length > |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 if (!ReadUtf8String().ToHandle(&pattern) || | 871 if (!ReadUtf8String().ToHandle(&pattern) || |
| 795 !ReadVarint<uint32_t>().To(&raw_flags) || | 872 !ReadVarint<uint32_t>().To(&raw_flags) || |
| 796 !JSRegExp::New(pattern, static_cast<JSRegExp::Flags>(raw_flags)) | 873 !JSRegExp::New(pattern, static_cast<JSRegExp::Flags>(raw_flags)) |
| 797 .ToHandle(®exp)) { | 874 .ToHandle(®exp)) { |
| 798 return MaybeHandle<JSRegExp>(); | 875 return MaybeHandle<JSRegExp>(); |
| 799 } | 876 } |
| 800 AddObjectWithID(id, regexp); | 877 AddObjectWithID(id, regexp); |
| 801 return regexp; | 878 return regexp; |
| 802 } | 879 } |
| 803 | 880 |
| 881 MaybeHandle<JSMap> ValueDeserializer::ReadJSMap() { |
| 882 // If we are at the end of the stack, abort. This function may recurse. |
| 883 if (StackLimitCheck(isolate_).HasOverflowed()) return MaybeHandle<JSMap>(); |
| 884 |
| 885 HandleScope scope(isolate_); |
| 886 uint32_t id = next_id_++; |
| 887 Handle<JSMap> map = isolate_->factory()->NewJSMap(); |
| 888 AddObjectWithID(id, map); |
| 889 |
| 890 Handle<JSFunction> map_set = isolate_->map_set(); |
| 891 uint32_t length = 0; |
| 892 while (true) { |
| 893 SerializationTag tag; |
| 894 if (!PeekTag().To(&tag)) return MaybeHandle<JSMap>(); |
| 895 if (tag == SerializationTag::kEndJSMap) { |
| 896 ConsumeTag(SerializationTag::kEndJSMap); |
| 897 break; |
| 898 } |
| 899 |
| 900 Handle<Object> argv[2]; |
| 901 if (!ReadObject().ToHandle(&argv[0]) || !ReadObject().ToHandle(&argv[1]) || |
| 902 Execution::Call(isolate_, map_set, map, arraysize(argv), argv) |
| 903 .is_null()) { |
| 904 return MaybeHandle<JSMap>(); |
| 905 } |
| 906 length += 2; |
| 907 } |
| 908 |
| 909 uint32_t expected_length; |
| 910 if (!ReadVarint<uint32_t>().To(&expected_length) || |
| 911 length != expected_length) { |
| 912 return MaybeHandle<JSMap>(); |
| 913 } |
| 914 DCHECK(HasObjectWithID(id)); |
| 915 return scope.CloseAndEscape(map); |
| 916 } |
| 917 |
| 918 MaybeHandle<JSSet> ValueDeserializer::ReadJSSet() { |
| 919 // If we are at the end of the stack, abort. This function may recurse. |
| 920 if (StackLimitCheck(isolate_).HasOverflowed()) return MaybeHandle<JSSet>(); |
| 921 |
| 922 HandleScope scope(isolate_); |
| 923 uint32_t id = next_id_++; |
| 924 Handle<JSSet> set = isolate_->factory()->NewJSSet(); |
| 925 AddObjectWithID(id, set); |
| 926 Handle<JSFunction> set_add = isolate_->set_add(); |
| 927 uint32_t length = 0; |
| 928 while (true) { |
| 929 SerializationTag tag; |
| 930 if (!PeekTag().To(&tag)) return MaybeHandle<JSSet>(); |
| 931 if (tag == SerializationTag::kEndJSSet) { |
| 932 ConsumeTag(SerializationTag::kEndJSSet); |
| 933 break; |
| 934 } |
| 935 |
| 936 Handle<Object> argv[1]; |
| 937 if (!ReadObject().ToHandle(&argv[0]) || |
| 938 Execution::Call(isolate_, set_add, set, arraysize(argv), argv) |
| 939 .is_null()) { |
| 940 return MaybeHandle<JSSet>(); |
| 941 } |
| 942 length++; |
| 943 } |
| 944 |
| 945 uint32_t expected_length; |
| 946 if (!ReadVarint<uint32_t>().To(&expected_length) || |
| 947 length != expected_length) { |
| 948 return MaybeHandle<JSSet>(); |
| 949 } |
| 950 DCHECK(HasObjectWithID(id)); |
| 951 return scope.CloseAndEscape(set); |
| 952 } |
| 953 |
| 804 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( | 954 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( |
| 805 Handle<JSObject> object, SerializationTag end_tag) { | 955 Handle<JSObject> object, SerializationTag end_tag) { |
| 806 for (uint32_t num_properties = 0;; num_properties++) { | 956 for (uint32_t num_properties = 0;; num_properties++) { |
| 807 SerializationTag tag; | 957 SerializationTag tag; |
| 808 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); | 958 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); |
| 809 if (tag == end_tag) { | 959 if (tag == end_tag) { |
| 810 ConsumeTag(end_tag); | 960 ConsumeTag(end_tag); |
| 811 return Just(num_properties); | 961 return Just(num_properties); |
| 812 } | 962 } |
| 813 | 963 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 958 } | 1108 } |
| 959 #endif | 1109 #endif |
| 960 position_ = end_; | 1110 position_ = end_; |
| 961 | 1111 |
| 962 if (stack.size() != 1) return MaybeHandle<Object>(); | 1112 if (stack.size() != 1) return MaybeHandle<Object>(); |
| 963 return scope.CloseAndEscape(stack[0]); | 1113 return scope.CloseAndEscape(stack[0]); |
| 964 } | 1114 } |
| 965 | 1115 |
| 966 } // namespace internal | 1116 } // namespace internal |
| 967 } // namespace v8 | 1117 } // namespace v8 |
| OLD | NEW |