Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(290)

Side by Side Diff: src/value-serializer.cc

Issue 2275033003: Blink-compatible serialization of ArrayBuffer transfer. (Closed)
Patch Set: Accepts Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/value-serializer.h ('k') | test/unittests/value-serializer-unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/value-serializer.h ('k') | test/unittests/value-serializer-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698