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

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

Issue 2667553003: Revert of ValueSerializer: Distinguish between 'undefined' and an absent property. (Closed)
Patch Set: Created 3 years, 10 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 | « no previous file | 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/conversions.h" 10 #include "src/conversions.h"
11 #include "src/factory.h" 11 #include "src/factory.h"
12 #include "src/flags.h" 12 #include "src/flags.h"
13 #include "src/handles-inl.h" 13 #include "src/handles-inl.h"
14 #include "src/isolate.h" 14 #include "src/isolate.h"
15 #include "src/objects-inl.h" 15 #include "src/objects-inl.h"
16 #include "src/objects.h" 16 #include "src/objects.h"
17 #include "src/snapshot/code-serializer.h" 17 #include "src/snapshot/code-serializer.h"
18 #include "src/transitions.h" 18 #include "src/transitions.h"
19 #include "src/wasm/wasm-module.h" 19 #include "src/wasm/wasm-module.h"
20 #include "src/wasm/wasm-objects.h" 20 #include "src/wasm/wasm-objects.h"
21 #include "src/wasm/wasm-result.h" 21 #include "src/wasm/wasm-result.h"
22 22
23 namespace v8 { 23 namespace v8 {
24 namespace internal { 24 namespace internal {
25 25
26 // Version 9: (imported from Blink) 26 // Version 9: (imported from Blink)
27 // Version 10: one-byte (Latin-1) strings 27 // Version 10: one-byte (Latin-1) strings
28 // Version 11: properly separate undefined from the hole in arrays 28 static const uint32_t kLatestVersion = 10;
29 static const uint32_t kLatestVersion = 11;
30 29
31 static const int kPretenureThreshold = 100 * KB; 30 static const int kPretenureThreshold = 100 * KB;
32 31
33 template <typename T> 32 template <typename T>
34 static size_t BytesNeededForVarint(T value) { 33 static size_t BytesNeededForVarint(T value) {
35 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value, 34 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
36 "Only unsigned integer types can be written as varints."); 35 "Only unsigned integer types can be written as varints.");
37 size_t result = 0; 36 size_t result = 0;
38 do { 37 do {
39 result++; 38 result++;
40 value >>= 7; 39 value >>= 7;
41 } while (value); 40 } while (value);
42 return result; 41 return result;
43 } 42 }
44 43
45 enum class SerializationTag : uint8_t { 44 enum class SerializationTag : uint8_t {
46 // version:uint32_t (if at beginning of data, sets version > 0) 45 // version:uint32_t (if at beginning of data, sets version > 0)
47 kVersion = 0xFF, 46 kVersion = 0xFF,
48 // ignore 47 // ignore
49 kPadding = '\0', 48 kPadding = '\0',
50 // refTableSize:uint32_t (previously used for sanity checks; safe to ignore) 49 // refTableSize:uint32_t (previously used for sanity checks; safe to ignore)
51 kVerifyObjectCount = '?', 50 kVerifyObjectCount = '?',
52 // Oddballs (no data). 51 // Oddballs (no data).
53 kTheHole = '-',
54 kUndefined = '_', 52 kUndefined = '_',
55 kNull = '0', 53 kNull = '0',
56 kTrue = 'T', 54 kTrue = 'T',
57 kFalse = 'F', 55 kFalse = 'F',
58 // Number represented as 32-bit integer, ZigZag-encoded 56 // Number represented as 32-bit integer, ZigZag-encoded
59 // (like sint32 in protobuf) 57 // (like sint32 in protobuf)
60 kInt32 = 'I', 58 kInt32 = 'I',
61 // Number represented as 32-bit unsigned integer, varint-encoded 59 // Number represented as 32-bit unsigned integer, varint-encoded
62 // (like uint32 in protobuf) 60 // (like uint32 in protobuf)
63 kUint32 = 'U', 61 kUint32 = 'U',
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 // To keep things simple, for now we decide between dense and sparse 531 // To keep things simple, for now we decide between dense and sparse
534 // serialization based on elements kind. A more principled heuristic could 532 // serialization based on elements kind. A more principled heuristic could
535 // count the elements, but would need to take care to note which indices 533 // count the elements, but would need to take care to note which indices
536 // existed (as only indices which were enumerable own properties at this point 534 // existed (as only indices which were enumerable own properties at this point
537 // should be serialized). 535 // should be serialized).
538 const bool should_serialize_densely = 536 const bool should_serialize_densely =
539 array->HasFastElements() && !array->HasFastHoleyElements(); 537 array->HasFastElements() && !array->HasFastHoleyElements();
540 538
541 if (should_serialize_densely) { 539 if (should_serialize_densely) {
542 DCHECK_LE(length, static_cast<uint32_t>(FixedArray::kMaxLength)); 540 DCHECK_LE(length, static_cast<uint32_t>(FixedArray::kMaxLength));
541
542 // TODO(jbroman): Distinguish between undefined and a hole (this can happen
543 // if serializing one of the elements deletes another). This requires wire
544 // format changes.
543 WriteTag(SerializationTag::kBeginDenseJSArray); 545 WriteTag(SerializationTag::kBeginDenseJSArray);
544 WriteVarint<uint32_t>(length); 546 WriteVarint<uint32_t>(length);
545 uint32_t i = 0; 547 uint32_t i = 0;
546 548
547 // Fast paths. Note that FAST_ELEMENTS in particular can bail due to the 549 // Fast paths. Note that FAST_ELEMENTS in particular can bail due to the
548 // structure of the elements changing. 550 // structure of the elements changing.
549 switch (array->GetElementsKind()) { 551 switch (array->GetElementsKind()) {
550 case FAST_SMI_ELEMENTS: { 552 case FAST_SMI_ELEMENTS: {
551 Handle<FixedArray> elements(FixedArray::cast(array->elements()), 553 Handle<FixedArray> elements(FixedArray::cast(array->elements()),
552 isolate_); 554 isolate_);
(...skipping 27 matching lines...) Expand all
580 break; 582 break;
581 } 583 }
582 584
583 // If there are elements remaining, serialize them slowly. 585 // If there are elements remaining, serialize them slowly.
584 for (; i < length; i++) { 586 for (; i < length; i++) {
585 // Serializing the array's elements can have arbitrary side effects, so we 587 // Serializing the array's elements can have arbitrary side effects, so we
586 // cannot rely on still having fast elements, even if it did to begin 588 // cannot rely on still having fast elements, even if it did to begin
587 // with. 589 // with.
588 Handle<Object> element; 590 Handle<Object> element;
589 LookupIterator it(isolate_, array, i, array, LookupIterator::OWN); 591 LookupIterator it(isolate_, array, i, array, LookupIterator::OWN);
590 if (!it.IsFound()) {
591 // This can happen in the case where an array that was originally dense
592 // became sparse during serialization. It's too late to switch to the
593 // sparse format, but we can mark the elements as absent.
594 WriteTag(SerializationTag::kTheHole);
595 continue;
596 }
597 if (!Object::GetProperty(&it).ToHandle(&element) || 592 if (!Object::GetProperty(&it).ToHandle(&element) ||
598 !WriteObject(element).FromMaybe(false)) { 593 !WriteObject(element).FromMaybe(false)) {
599 return Nothing<bool>(); 594 return Nothing<bool>();
600 } 595 }
601 } 596 }
602 597
603 KeyAccumulator accumulator(isolate_, KeyCollectionMode::kOwnOnly, 598 KeyAccumulator accumulator(isolate_, KeyCollectionMode::kOwnOnly,
604 ENUMERABLE_STRINGS); 599 ENUMERABLE_STRINGS);
605 if (!accumulator.CollectOwnPropertyNames(array, array).FromMaybe(false)) { 600 if (!accumulator.CollectOwnPropertyNames(array, array).FromMaybe(false)) {
606 return Nothing<bool>(); 601 return Nothing<bool>();
(...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after
1318 1313
1319 uint32_t id = next_id_++; 1314 uint32_t id = next_id_++;
1320 HandleScope scope(isolate_); 1315 HandleScope scope(isolate_);
1321 Handle<JSArray> array = isolate_->factory()->NewJSArray( 1316 Handle<JSArray> array = isolate_->factory()->NewJSArray(
1322 FAST_HOLEY_ELEMENTS, length, length, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE, 1317 FAST_HOLEY_ELEMENTS, length, length, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE,
1323 pretenure_); 1318 pretenure_);
1324 AddObjectWithID(id, array); 1319 AddObjectWithID(id, array);
1325 1320
1326 Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate_); 1321 Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate_);
1327 for (uint32_t i = 0; i < length; i++) { 1322 for (uint32_t i = 0; i < length; i++) {
1328 SerializationTag tag;
1329 if (PeekTag().To(&tag) && tag == SerializationTag::kTheHole) {
1330 ConsumeTag(SerializationTag::kTheHole);
1331 continue;
1332 }
1333
1334 Handle<Object> element; 1323 Handle<Object> element;
1335 if (!ReadObject().ToHandle(&element)) return MaybeHandle<JSArray>(); 1324 if (!ReadObject().ToHandle(&element)) return MaybeHandle<JSArray>();
1336 1325 // TODO(jbroman): Distinguish between undefined and a hole.
1337 // Serialization versions less than 11 encode the hole the same as 1326 if (element->IsUndefined(isolate_)) continue;
1338 // undefined. For consistency with previous behavior, store these as the
1339 // hole. Past version 11, undefined means undefined.
1340 if (version_ < 11 && element->IsUndefined(isolate_)) continue;
1341
1342 elements->set(i, *element); 1327 elements->set(i, *element);
1343 } 1328 }
1344 1329
1345 uint32_t num_properties; 1330 uint32_t num_properties;
1346 uint32_t expected_num_properties; 1331 uint32_t expected_num_properties;
1347 uint32_t expected_length; 1332 uint32_t expected_length;
1348 if (!ReadJSObjectProperties(array, SerializationTag::kEndDenseJSArray, false) 1333 if (!ReadJSObjectProperties(array, SerializationTag::kEndDenseJSArray, false)
1349 .To(&num_properties) || 1334 .To(&num_properties) ||
1350 !ReadVarint<uint32_t>().To(&expected_num_properties) || 1335 !ReadVarint<uint32_t>().To(&expected_num_properties) ||
1351 !ReadVarint<uint32_t>().To(&expected_length) || 1336 !ReadVarint<uint32_t>().To(&expected_length) ||
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
1934 if (stack.size() != 1) { 1919 if (stack.size() != 1) {
1935 isolate_->Throw(*isolate_->factory()->NewError( 1920 isolate_->Throw(*isolate_->factory()->NewError(
1936 MessageTemplate::kDataCloneDeserializationError)); 1921 MessageTemplate::kDataCloneDeserializationError));
1937 return MaybeHandle<Object>(); 1922 return MaybeHandle<Object>();
1938 } 1923 }
1939 return scope.CloseAndEscape(stack[0]); 1924 return scope.CloseAndEscape(stack[0]);
1940 } 1925 }
1941 1926
1942 } // namespace internal 1927 } // namespace internal
1943 } // namespace v8 1928 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/unittests/value-serializer-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698