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

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

Issue 2255313002: Revert of Blink-compatible serialization of arrays, both dense and sparse. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 kDouble = 'N', 53 kDouble = 'N',
54 // byteLength:uint32_t, then raw data 54 // byteLength:uint32_t, then raw data
55 kUtf8String = 'S', 55 kUtf8String = 'S',
56 kTwoByteString = 'c', 56 kTwoByteString = 'c',
57 // Reference to a serialized object. objectID:uint32_t 57 // Reference to a serialized object. objectID:uint32_t
58 kObjectReference = '^', 58 kObjectReference = '^',
59 // Beginning of a JS object. 59 // Beginning of a JS object.
60 kBeginJSObject = 'o', 60 kBeginJSObject = 'o',
61 // End of a JS object. numProperties:uint32_t 61 // End of a JS object. numProperties:uint32_t
62 kEndJSObject = '{', 62 kEndJSObject = '{',
63 // Beginning of a sparse JS array. length:uint32_t
64 // Elements and properties are written as key/value pairs, like objects.
65 kBeginSparseJSArray = 'a',
66 // End of a sparse JS array. numProperties:uint32_t length:uint32_t
67 kEndSparseJSArray = '@',
68 // Beginning of a dense JS array. length:uint32_t
69 // |length| elements, followed by properties as key/value pairs
70 kBeginDenseJSArray = 'A',
71 // End of a dense JS array. numProperties:uint32_t length:uint32_t
72 kEndDenseJSArray = '$',
73 }; 63 };
74 64
75 ValueSerializer::ValueSerializer(Isolate* isolate) 65 ValueSerializer::ValueSerializer(Isolate* isolate)
76 : isolate_(isolate), 66 : isolate_(isolate),
77 zone_(isolate->allocator()), 67 zone_(isolate->allocator()),
78 id_map_(isolate->heap(), &zone_) {} 68 id_map_(isolate->heap(), &zone_) {}
79 69
80 ValueSerializer::~ValueSerializer() {} 70 ValueSerializer::~ValueSerializer() {}
81 71
82 void ValueSerializer::WriteHeader() { 72 void ValueSerializer::WriteHeader() {
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 InstanceType instance_type = receiver->map()->instance_type(); 246 InstanceType instance_type = receiver->map()->instance_type();
257 if (receiver->IsCallable() || instance_type <= LAST_SPECIAL_RECEIVER_TYPE) { 247 if (receiver->IsCallable() || instance_type <= LAST_SPECIAL_RECEIVER_TYPE) {
258 return Nothing<bool>(); 248 return Nothing<bool>();
259 } 249 }
260 250
261 // If we are at the end of the stack, abort. This function may recurse. 251 // If we are at the end of the stack, abort. This function may recurse.
262 if (StackLimitCheck(isolate_).HasOverflowed()) return Nothing<bool>(); 252 if (StackLimitCheck(isolate_).HasOverflowed()) return Nothing<bool>();
263 253
264 HandleScope scope(isolate_); 254 HandleScope scope(isolate_);
265 switch (instance_type) { 255 switch (instance_type) {
266 case JS_ARRAY_TYPE:
267 return WriteJSArray(Handle<JSArray>::cast(receiver));
268 case JS_OBJECT_TYPE: 256 case JS_OBJECT_TYPE:
269 case JS_API_OBJECT_TYPE: 257 case JS_API_OBJECT_TYPE:
270 return WriteJSObject(Handle<JSObject>::cast(receiver)); 258 return WriteJSObject(Handle<JSObject>::cast(receiver));
271 default: 259 default:
272 UNIMPLEMENTED(); 260 UNIMPLEMENTED();
273 break; 261 break;
274 } 262 }
275 return Nothing<bool>(); 263 return Nothing<bool>();
276 } 264 }
277 265
278 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) { 266 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) {
279 WriteTag(SerializationTag::kBeginJSObject); 267 WriteTag(SerializationTag::kBeginJSObject);
280 Handle<FixedArray> keys; 268 Handle<FixedArray> keys;
281 uint32_t properties_written; 269 uint32_t properties_written;
282 if (!KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, 270 if (!KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
283 ENUMERABLE_STRINGS) 271 ENUMERABLE_STRINGS)
284 .ToHandle(&keys) || 272 .ToHandle(&keys) ||
285 !WriteJSObjectProperties(object, keys).To(&properties_written)) { 273 !WriteJSObjectProperties(object, keys).To(&properties_written)) {
286 return Nothing<bool>(); 274 return Nothing<bool>();
287 } 275 }
288 WriteTag(SerializationTag::kEndJSObject); 276 WriteTag(SerializationTag::kEndJSObject);
289 WriteVarint<uint32_t>(properties_written); 277 WriteVarint<uint32_t>(properties_written);
290 return Just(true); 278 return Just(true);
291 } 279 }
292 280
293 Maybe<bool> ValueSerializer::WriteJSArray(Handle<JSArray> array) {
294 uint32_t length;
295 array->length()->ToArrayLength(&length);
296
297 // To keep things simple, for now we decide between dense and sparse
298 // serialization based on elements kind. A more principled heuristic could
299 // count the elements, but would need to take care to note which indices
300 // existed (as only indices which were enumerable own properties at this point
301 // should be serialized).
302 const bool should_serialize_densely =
303 array->HasFastElements() && !array->HasFastHoleyElements();
304
305 if (should_serialize_densely) {
306 // TODO(jbroman): Distinguish between undefined and a hole (this can happen
307 // if serializing one of the elements deletes another). This requires wire
308 // format changes.
309 WriteTag(SerializationTag::kBeginDenseJSArray);
310 WriteVarint<uint32_t>(length);
311 for (uint32_t i = 0; i < length; i++) {
312 // Serializing the array's elements can have arbitrary side effects, so we
313 // cannot rely on still having fast elements, even if it did to begin
314 // with.
315 Handle<Object> element;
316 LookupIterator it(isolate_, array, i, array, LookupIterator::OWN);
317 if (!Object::GetProperty(&it).ToHandle(&element) ||
318 !WriteObject(element).FromMaybe(false)) {
319 return Nothing<bool>();
320 }
321 }
322 KeyAccumulator accumulator(isolate_, KeyCollectionMode::kOwnOnly,
323 ENUMERABLE_STRINGS);
324 if (!accumulator.CollectOwnPropertyNames(array, array).FromMaybe(false)) {
325 return Nothing<bool>();
326 }
327 Handle<FixedArray> keys =
328 accumulator.GetKeys(GetKeysConversion::kConvertToString);
329 uint32_t properties_written;
330 if (!WriteJSObjectProperties(array, keys).To(&properties_written)) {
331 return Nothing<bool>();
332 }
333 WriteTag(SerializationTag::kEndDenseJSArray);
334 WriteVarint<uint32_t>(properties_written);
335 WriteVarint<uint32_t>(length);
336 } else {
337 WriteTag(SerializationTag::kBeginSparseJSArray);
338 WriteVarint<uint32_t>(length);
339 Handle<FixedArray> keys;
340 uint32_t properties_written;
341 if (!KeyAccumulator::GetKeys(array, KeyCollectionMode::kOwnOnly,
342 ENUMERABLE_STRINGS)
343 .ToHandle(&keys) ||
344 !WriteJSObjectProperties(array, keys).To(&properties_written)) {
345 return Nothing<bool>();
346 }
347 WriteTag(SerializationTag::kEndSparseJSArray);
348 WriteVarint<uint32_t>(properties_written);
349 WriteVarint<uint32_t>(length);
350 }
351 return Just(true);
352 }
353
354 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties( 281 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties(
355 Handle<JSObject> object, Handle<FixedArray> keys) { 282 Handle<JSObject> object, Handle<FixedArray> keys) {
356 uint32_t properties_written = 0; 283 uint32_t properties_written = 0;
357 int length = keys->length(); 284 int length = keys->length();
358 for (int i = 0; i < length; i++) { 285 for (int i = 0; i < length; i++) {
359 Handle<Object> key(keys->get(i), isolate_); 286 Handle<Object> key(keys->get(i), isolate_);
360 287
361 bool success; 288 bool success;
362 LookupIterator it = LookupIterator::PropertyOrElement( 289 LookupIterator it = LookupIterator::PropertyOrElement(
363 isolate_, object, key, &success, LookupIterator::OWN); 290 isolate_, object, key, &success, LookupIterator::OWN);
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 return ReadUtf8String(); 447 return ReadUtf8String();
521 case SerializationTag::kTwoByteString: 448 case SerializationTag::kTwoByteString:
522 return ReadTwoByteString(); 449 return ReadTwoByteString();
523 case SerializationTag::kObjectReference: { 450 case SerializationTag::kObjectReference: {
524 uint32_t id; 451 uint32_t id;
525 if (!ReadVarint<uint32_t>().To(&id)) return MaybeHandle<Object>(); 452 if (!ReadVarint<uint32_t>().To(&id)) return MaybeHandle<Object>();
526 return GetObjectWithID(id); 453 return GetObjectWithID(id);
527 } 454 }
528 case SerializationTag::kBeginJSObject: 455 case SerializationTag::kBeginJSObject:
529 return ReadJSObject(); 456 return ReadJSObject();
530 case SerializationTag::kBeginSparseJSArray:
531 return ReadSparseJSArray();
532 case SerializationTag::kBeginDenseJSArray:
533 return ReadDenseJSArray();
534 default: 457 default:
535 return MaybeHandle<Object>(); 458 return MaybeHandle<Object>();
536 } 459 }
537 } 460 }
538 461
539 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { 462 MaybeHandle<String> ValueDeserializer::ReadUtf8String() {
540 uint32_t utf8_length; 463 uint32_t utf8_length;
541 Vector<const uint8_t> utf8_bytes; 464 Vector<const uint8_t> utf8_bytes;
542 if (!ReadVarint<uint32_t>().To(&utf8_length) || 465 if (!ReadVarint<uint32_t>().To(&utf8_length) ||
543 utf8_length > 466 utf8_length >
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 .To(&num_properties) || 510 .To(&num_properties) ||
588 !ReadVarint<uint32_t>().To(&expected_num_properties) || 511 !ReadVarint<uint32_t>().To(&expected_num_properties) ||
589 num_properties != expected_num_properties) { 512 num_properties != expected_num_properties) {
590 return MaybeHandle<JSObject>(); 513 return MaybeHandle<JSObject>();
591 } 514 }
592 515
593 DCHECK(HasObjectWithID(id)); 516 DCHECK(HasObjectWithID(id));
594 return scope.CloseAndEscape(object); 517 return scope.CloseAndEscape(object);
595 } 518 }
596 519
597 MaybeHandle<JSArray> ValueDeserializer::ReadSparseJSArray() {
598 // If we are at the end of the stack, abort. This function may recurse.
599 if (StackLimitCheck(isolate_).HasOverflowed()) return MaybeHandle<JSArray>();
600
601 uint32_t length;
602 if (!ReadVarint<uint32_t>().To(&length)) return MaybeHandle<JSArray>();
603
604 uint32_t id = next_id_++;
605 HandleScope scope(isolate_);
606 Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
607 JSArray::SetLength(array, length);
608 AddObjectWithID(id, array);
609
610 uint32_t num_properties;
611 uint32_t expected_num_properties;
612 uint32_t expected_length;
613 if (!ReadJSObjectProperties(array, SerializationTag::kEndSparseJSArray)
614 .To(&num_properties) ||
615 !ReadVarint<uint32_t>().To(&expected_num_properties) ||
616 !ReadVarint<uint32_t>().To(&expected_length) ||
617 num_properties != expected_num_properties || length != expected_length) {
618 return MaybeHandle<JSArray>();
619 }
620
621 DCHECK(HasObjectWithID(id));
622 return scope.CloseAndEscape(array);
623 }
624
625 MaybeHandle<JSArray> ValueDeserializer::ReadDenseJSArray() {
626 // If we are at the end of the stack, abort. This function may recurse.
627 if (StackLimitCheck(isolate_).HasOverflowed()) return MaybeHandle<JSArray>();
628
629 uint32_t length;
630 if (!ReadVarint<uint32_t>().To(&length)) return MaybeHandle<JSArray>();
631
632 uint32_t id = next_id_++;
633 HandleScope scope(isolate_);
634 Handle<JSArray> array = isolate_->factory()->NewJSArray(
635 FAST_HOLEY_ELEMENTS, length, length, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
636 AddObjectWithID(id, array);
637
638 Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate_);
639 for (uint32_t i = 0; i < length; i++) {
640 Handle<Object> element;
641 if (!ReadObject().ToHandle(&element)) return MaybeHandle<JSArray>();
642 // TODO(jbroman): Distinguish between undefined and a hole.
643 if (element->IsUndefined(isolate_)) continue;
644 elements->set(i, *element);
645 }
646
647 uint32_t num_properties;
648 uint32_t expected_num_properties;
649 uint32_t expected_length;
650 if (!ReadJSObjectProperties(array, SerializationTag::kEndDenseJSArray)
651 .To(&num_properties) ||
652 !ReadVarint<uint32_t>().To(&expected_num_properties) ||
653 !ReadVarint<uint32_t>().To(&expected_length) ||
654 num_properties != expected_num_properties || length != expected_length) {
655 return MaybeHandle<JSArray>();
656 }
657
658 DCHECK(HasObjectWithID(id));
659 return scope.CloseAndEscape(array);
660 }
661
662 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( 520 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties(
663 Handle<JSObject> object, SerializationTag end_tag) { 521 Handle<JSObject> object, SerializationTag end_tag) {
664 for (uint32_t num_properties = 0;; num_properties++) { 522 for (uint32_t num_properties = 0;; num_properties++) {
665 SerializationTag tag; 523 SerializationTag tag;
666 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); 524 if (!PeekTag().To(&tag)) return Nothing<uint32_t>();
667 if (tag == end_tag) { 525 if (tag == end_tag) {
668 ConsumeTag(end_tag); 526 ConsumeTag(end_tag);
669 return Just(num_properties); 527 return Just(num_properties);
670 } 528 }
671 529
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 } 640 }
783 #endif 641 #endif
784 position_ = end_; 642 position_ = end_;
785 643
786 if (stack.size() != 1) return MaybeHandle<Object>(); 644 if (stack.size() != 1) return MaybeHandle<Object>();
787 return scope.CloseAndEscape(stack[0]); 645 return scope.CloseAndEscape(stack[0]);
788 } 646 }
789 647
790 } // namespace internal 648 } // namespace internal
791 } // namespace v8 649 } // 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