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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 // Beginning of a JS map. | 85 // Beginning of a JS map. |
86 kBeginJSMap = ';', | 86 kBeginJSMap = ';', |
87 // End of a JS map. length:uint32_t. | 87 // End of a JS map. length:uint32_t. |
88 kEndJSMap = ':', | 88 kEndJSMap = ':', |
89 // Beginning of a JS set. | 89 // Beginning of a JS set. |
90 kBeginJSSet = '\'', | 90 kBeginJSSet = '\'', |
91 // End of a JS set. length:uint32_t. | 91 // End of a JS set. length:uint32_t. |
92 kEndJSSet = ',', | 92 kEndJSSet = ',', |
93 // Array buffer. byteLength:uint32_t, then raw data. | 93 // Array buffer. byteLength:uint32_t, then raw data. |
94 kArrayBuffer = 'B', | 94 kArrayBuffer = 'B', |
| 95 // Array buffer (transferred). transferID:uint32_t |
| 96 kArrayBufferTransfer = 't', |
95 }; | 97 }; |
96 | 98 |
97 ValueSerializer::ValueSerializer(Isolate* isolate) | 99 ValueSerializer::ValueSerializer(Isolate* isolate) |
98 : isolate_(isolate), | 100 : isolate_(isolate), |
99 zone_(isolate->allocator()), | 101 zone_(isolate->allocator()), |
100 id_map_(isolate->heap(), &zone_) {} | 102 id_map_(isolate->heap(), &zone_), |
| 103 array_buffer_transfer_map_(isolate->heap(), &zone_) {} |
101 | 104 |
102 ValueSerializer::~ValueSerializer() {} | 105 ValueSerializer::~ValueSerializer() {} |
103 | 106 |
104 void ValueSerializer::WriteHeader() { | 107 void ValueSerializer::WriteHeader() { |
105 WriteTag(SerializationTag::kVersion); | 108 WriteTag(SerializationTag::kVersion); |
106 WriteVarint(kLatestVersion); | 109 WriteVarint(kLatestVersion); |
107 } | 110 } |
108 | 111 |
109 void ValueSerializer::WriteTag(SerializationTag tag) { | 112 void ValueSerializer::WriteTag(SerializationTag tag) { |
110 buffer_.push_back(static_cast<uint8_t>(tag)); | 113 buffer_.push_back(static_cast<uint8_t>(tag)); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 buffer_.insert(buffer_.end(), begin, begin + length); | 168 buffer_.insert(buffer_.end(), begin, begin + length); |
166 } | 169 } |
167 | 170 |
168 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { | 171 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { |
169 if (!bytes) return nullptr; | 172 if (!bytes) return nullptr; |
170 auto old_size = buffer_.size(); | 173 auto old_size = buffer_.size(); |
171 buffer_.resize(buffer_.size() + bytes); | 174 buffer_.resize(buffer_.size() + bytes); |
172 return &buffer_[old_size]; | 175 return &buffer_[old_size]; |
173 } | 176 } |
174 | 177 |
| 178 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, |
| 179 Handle<JSArrayBuffer> array_buffer) { |
| 180 DCHECK(!array_buffer_transfer_map_.Find(array_buffer)); |
| 181 array_buffer_transfer_map_.Set(array_buffer, transfer_id); |
| 182 } |
| 183 |
175 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { | 184 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { |
176 if (object->IsSmi()) { | 185 if (object->IsSmi()) { |
177 WriteSmi(Smi::cast(*object)); | 186 WriteSmi(Smi::cast(*object)); |
178 return Just(true); | 187 return Just(true); |
179 } | 188 } |
180 | 189 |
181 DCHECK(object->IsHeapObject()); | 190 DCHECK(object->IsHeapObject()); |
182 switch (HeapObject::cast(*object)->map()->instance_type()) { | 191 switch (HeapObject::cast(*object)->map()->instance_type()) { |
183 case ODDBALL_TYPE: | 192 case ODDBALL_TYPE: |
184 WriteOddball(Oddball::cast(*object)); | 193 WriteOddball(Oddball::cast(*object)); |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { | 502 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { |
494 return Nothing<bool>(); | 503 return Nothing<bool>(); |
495 } | 504 } |
496 } | 505 } |
497 WriteTag(SerializationTag::kEndJSSet); | 506 WriteTag(SerializationTag::kEndJSSet); |
498 WriteVarint<uint32_t>(length); | 507 WriteVarint<uint32_t>(length); |
499 return Just(true); | 508 return Just(true); |
500 } | 509 } |
501 | 510 |
502 Maybe<bool> ValueSerializer::WriteJSArrayBuffer(JSArrayBuffer* array_buffer) { | 511 Maybe<bool> ValueSerializer::WriteJSArrayBuffer(JSArrayBuffer* array_buffer) { |
| 512 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer); |
| 513 if (transfer_entry) { |
| 514 DCHECK(array_buffer->was_neutered()); |
| 515 WriteTag(SerializationTag::kArrayBufferTransfer); |
| 516 WriteVarint(*transfer_entry); |
| 517 return Just(true); |
| 518 } |
| 519 |
503 if (array_buffer->was_neutered()) return Nothing<bool>(); | 520 if (array_buffer->was_neutered()) return Nothing<bool>(); |
504 double byte_length = array_buffer->byte_length()->Number(); | 521 double byte_length = array_buffer->byte_length()->Number(); |
505 if (byte_length > std::numeric_limits<uint32_t>::max()) { | 522 if (byte_length > std::numeric_limits<uint32_t>::max()) { |
506 return Nothing<bool>(); | 523 return Nothing<bool>(); |
507 } | 524 } |
508 WriteTag(SerializationTag::kArrayBuffer); | 525 WriteTag(SerializationTag::kArrayBuffer); |
509 WriteVarint<uint32_t>(byte_length); | 526 WriteVarint<uint32_t>(byte_length); |
510 WriteRawBytes(array_buffer->backing_store(), byte_length); | 527 WriteRawBytes(array_buffer->backing_store(), byte_length); |
511 return Just(true); | 528 return Just(true); |
512 } | 529 } |
(...skipping 30 matching lines...) Expand all Loading... |
543 Vector<const uint8_t> data) | 560 Vector<const uint8_t> data) |
544 : isolate_(isolate), | 561 : isolate_(isolate), |
545 position_(data.start()), | 562 position_(data.start()), |
546 end_(data.start() + data.length()), | 563 end_(data.start() + data.length()), |
547 id_map_(Handle<SeededNumberDictionary>::cast( | 564 id_map_(Handle<SeededNumberDictionary>::cast( |
548 isolate->global_handles()->Create( | 565 isolate->global_handles()->Create( |
549 *SeededNumberDictionary::New(isolate, 0)))) {} | 566 *SeededNumberDictionary::New(isolate, 0)))) {} |
550 | 567 |
551 ValueDeserializer::~ValueDeserializer() { | 568 ValueDeserializer::~ValueDeserializer() { |
552 GlobalHandles::Destroy(Handle<Object>::cast(id_map_).location()); | 569 GlobalHandles::Destroy(Handle<Object>::cast(id_map_).location()); |
| 570 |
| 571 Handle<Object> transfer_map_handle; |
| 572 if (array_buffer_transfer_map_.ToHandle(&transfer_map_handle)) { |
| 573 GlobalHandles::Destroy(transfer_map_handle.location()); |
| 574 } |
553 } | 575 } |
554 | 576 |
555 Maybe<bool> ValueDeserializer::ReadHeader() { | 577 Maybe<bool> ValueDeserializer::ReadHeader() { |
556 if (position_ < end_ && | 578 if (position_ < end_ && |
557 *position_ == static_cast<uint8_t>(SerializationTag::kVersion)) { | 579 *position_ == static_cast<uint8_t>(SerializationTag::kVersion)) { |
558 ReadTag().ToChecked(); | 580 ReadTag().ToChecked(); |
559 if (!ReadVarint<uint32_t>().To(&version_)) return Nothing<bool>(); | 581 if (!ReadVarint<uint32_t>().To(&version_)) return Nothing<bool>(); |
560 if (version_ > kLatestVersion) return Nothing<bool>(); | 582 if (version_ > kLatestVersion) return Nothing<bool>(); |
561 } | 583 } |
562 return Just(true); | 584 return Just(true); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 return Just(value); | 660 return Just(value); |
639 } | 661 } |
640 | 662 |
641 Maybe<Vector<const uint8_t>> ValueDeserializer::ReadRawBytes(int size) { | 663 Maybe<Vector<const uint8_t>> ValueDeserializer::ReadRawBytes(int size) { |
642 if (size > end_ - position_) return Nothing<Vector<const uint8_t>>(); | 664 if (size > end_ - position_) return Nothing<Vector<const uint8_t>>(); |
643 const uint8_t* start = position_; | 665 const uint8_t* start = position_; |
644 position_ += size; | 666 position_ += size; |
645 return Just(Vector<const uint8_t>(start, size)); | 667 return Just(Vector<const uint8_t>(start, size)); |
646 } | 668 } |
647 | 669 |
| 670 void ValueDeserializer::TransferArrayBuffer( |
| 671 uint32_t transfer_id, Handle<JSArrayBuffer> array_buffer) { |
| 672 if (array_buffer_transfer_map_.is_null()) { |
| 673 array_buffer_transfer_map_ = |
| 674 Handle<SeededNumberDictionary>::cast(isolate_->global_handles()->Create( |
| 675 *SeededNumberDictionary::New(isolate_, 0))); |
| 676 } |
| 677 Handle<SeededNumberDictionary> dictionary = |
| 678 array_buffer_transfer_map_.ToHandleChecked(); |
| 679 const bool used_as_prototype = false; |
| 680 Handle<SeededNumberDictionary> new_dictionary = |
| 681 SeededNumberDictionary::AtNumberPut(dictionary, transfer_id, array_buffer, |
| 682 used_as_prototype); |
| 683 if (!new_dictionary.is_identical_to(dictionary)) { |
| 684 GlobalHandles::Destroy(Handle<Object>::cast(dictionary).location()); |
| 685 array_buffer_transfer_map_ = Handle<SeededNumberDictionary>::cast( |
| 686 isolate_->global_handles()->Create(*new_dictionary)); |
| 687 } |
| 688 } |
| 689 |
648 MaybeHandle<Object> ValueDeserializer::ReadObject() { | 690 MaybeHandle<Object> ValueDeserializer::ReadObject() { |
649 SerializationTag tag; | 691 SerializationTag tag; |
650 if (!ReadTag().To(&tag)) return MaybeHandle<Object>(); | 692 if (!ReadTag().To(&tag)) return MaybeHandle<Object>(); |
651 switch (tag) { | 693 switch (tag) { |
652 case SerializationTag::kVerifyObjectCount: | 694 case SerializationTag::kVerifyObjectCount: |
653 // Read the count and ignore it. | 695 // Read the count and ignore it. |
654 if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>(); | 696 if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>(); |
655 return ReadObject(); | 697 return ReadObject(); |
656 case SerializationTag::kUndefined: | 698 case SerializationTag::kUndefined: |
657 return isolate_->factory()->undefined_value(); | 699 return isolate_->factory()->undefined_value(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 case SerializationTag::kStringObject: | 741 case SerializationTag::kStringObject: |
700 return ReadJSValue(tag); | 742 return ReadJSValue(tag); |
701 case SerializationTag::kRegExp: | 743 case SerializationTag::kRegExp: |
702 return ReadJSRegExp(); | 744 return ReadJSRegExp(); |
703 case SerializationTag::kBeginJSMap: | 745 case SerializationTag::kBeginJSMap: |
704 return ReadJSMap(); | 746 return ReadJSMap(); |
705 case SerializationTag::kBeginJSSet: | 747 case SerializationTag::kBeginJSSet: |
706 return ReadJSSet(); | 748 return ReadJSSet(); |
707 case SerializationTag::kArrayBuffer: | 749 case SerializationTag::kArrayBuffer: |
708 return ReadJSArrayBuffer(); | 750 return ReadJSArrayBuffer(); |
| 751 case SerializationTag::kArrayBufferTransfer: |
| 752 return ReadTransferredJSArrayBuffer(); |
709 default: | 753 default: |
710 return MaybeHandle<Object>(); | 754 return MaybeHandle<Object>(); |
711 } | 755 } |
712 } | 756 } |
713 | 757 |
714 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { | 758 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { |
715 uint32_t utf8_length; | 759 uint32_t utf8_length; |
716 Vector<const uint8_t> utf8_bytes; | 760 Vector<const uint8_t> utf8_bytes; |
717 if (!ReadVarint<uint32_t>().To(&utf8_length) || | 761 if (!ReadVarint<uint32_t>().To(&utf8_length) || |
718 utf8_length > | 762 utf8_length > |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
985 const bool should_initialize = false; | 1029 const bool should_initialize = false; |
986 Handle<JSArrayBuffer> array_buffer = isolate_->factory()->NewJSArrayBuffer(); | 1030 Handle<JSArrayBuffer> array_buffer = isolate_->factory()->NewJSArrayBuffer(); |
987 JSArrayBuffer::SetupAllocatingData(array_buffer, isolate_, byte_length, | 1031 JSArrayBuffer::SetupAllocatingData(array_buffer, isolate_, byte_length, |
988 should_initialize); | 1032 should_initialize); |
989 memcpy(array_buffer->backing_store(), position_, byte_length); | 1033 memcpy(array_buffer->backing_store(), position_, byte_length); |
990 position_ += byte_length; | 1034 position_ += byte_length; |
991 AddObjectWithID(id, array_buffer); | 1035 AddObjectWithID(id, array_buffer); |
992 return array_buffer; | 1036 return array_buffer; |
993 } | 1037 } |
994 | 1038 |
| 1039 MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadTransferredJSArrayBuffer() { |
| 1040 uint32_t id = next_id_++; |
| 1041 uint32_t transfer_id; |
| 1042 Handle<SeededNumberDictionary> transfer_map; |
| 1043 if (!ReadVarint<uint32_t>().To(&transfer_id) || |
| 1044 !array_buffer_transfer_map_.ToHandle(&transfer_map)) { |
| 1045 return MaybeHandle<JSArrayBuffer>(); |
| 1046 } |
| 1047 int index = transfer_map->FindEntry(isolate_, transfer_id); |
| 1048 if (index == SeededNumberDictionary::kNotFound) { |
| 1049 return MaybeHandle<JSArrayBuffer>(); |
| 1050 } |
| 1051 Handle<JSArrayBuffer> array_buffer( |
| 1052 JSArrayBuffer::cast(transfer_map->ValueAt(index)), isolate_); |
| 1053 AddObjectWithID(id, array_buffer); |
| 1054 return array_buffer; |
| 1055 } |
| 1056 |
995 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( | 1057 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( |
996 Handle<JSObject> object, SerializationTag end_tag) { | 1058 Handle<JSObject> object, SerializationTag end_tag) { |
997 for (uint32_t num_properties = 0;; num_properties++) { | 1059 for (uint32_t num_properties = 0;; num_properties++) { |
998 SerializationTag tag; | 1060 SerializationTag tag; |
999 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); | 1061 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); |
1000 if (tag == end_tag) { | 1062 if (tag == end_tag) { |
1001 ConsumeTag(end_tag); | 1063 ConsumeTag(end_tag); |
1002 return Just(num_properties); | 1064 return Just(num_properties); |
1003 } | 1065 } |
1004 | 1066 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1149 } | 1211 } |
1150 #endif | 1212 #endif |
1151 position_ = end_; | 1213 position_ = end_; |
1152 | 1214 |
1153 if (stack.size() != 1) return MaybeHandle<Object>(); | 1215 if (stack.size() != 1) return MaybeHandle<Object>(); |
1154 return scope.CloseAndEscape(stack[0]); | 1216 return scope.CloseAndEscape(stack[0]); |
1155 } | 1217 } |
1156 | 1218 |
1157 } // namespace internal | 1219 } // namespace internal |
1158 } // namespace v8 | 1220 } // namespace v8 |
OLD | NEW |