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

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

Issue 2269923004: Blink-compatible serialization of Map and Set objects. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: StackLimitCheck + HandleScope Created 4 years, 4 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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(&regexp)) { 874 .ToHandle(&regexp)) {
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
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
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