| 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 |