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/conversions.h" | 10 #include "src/conversions.h" |
11 #include "src/factory.h" | 11 #include "src/factory.h" |
12 #include "src/handles-inl.h" | 12 #include "src/handles-inl.h" |
13 #include "src/isolate.h" | 13 #include "src/isolate.h" |
14 #include "src/objects-inl.h" | 14 #include "src/objects-inl.h" |
15 #include "src/objects.h" | 15 #include "src/objects.h" |
16 #include "src/transitions.h" | 16 #include "src/transitions.h" |
17 | 17 |
18 namespace v8 { | 18 namespace v8 { |
19 namespace internal { | 19 namespace internal { |
20 | 20 |
21 static const uint32_t kLatestVersion = 9; | 21 static const uint32_t kLatestVersion = 9; |
22 static const int kPretenureThreshold = 100 * KB; | 22 static const int kPretenureThreshold = 100 * KB; |
23 | 23 |
24 // More than 2^30 - 1 elements shouldn't be permitted in a dense array. | |
25 // This shouldn't be possible on the V8 heap anyhow | |
26 static const uint32_t kMaxDenseArrayLength = 0x3FFFFFFF; | |
Jakob Kummerow
2016/10/07 13:10:17
Why not FixedArray::kMaxLength?
jbroman
2016/10/11 16:37:27
OK, done. I have some vague unease about that valu
| |
27 | |
24 template <typename T> | 28 template <typename T> |
25 static size_t BytesNeededForVarint(T value) { | 29 static size_t BytesNeededForVarint(T value) { |
26 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value, | 30 static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value, |
27 "Only unsigned integer types can be written as varints."); | 31 "Only unsigned integer types can be written as varints."); |
28 size_t result = 0; | 32 size_t result = 0; |
29 do { | 33 do { |
30 result++; | 34 result++; |
31 value >>= 7; | 35 value >>= 7; |
32 } while (value); | 36 } while (value); |
33 return result; | 37 return result; |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
463 | 467 |
464 // To keep things simple, for now we decide between dense and sparse | 468 // To keep things simple, for now we decide between dense and sparse |
465 // serialization based on elements kind. A more principled heuristic could | 469 // serialization based on elements kind. A more principled heuristic could |
466 // count the elements, but would need to take care to note which indices | 470 // count the elements, but would need to take care to note which indices |
467 // existed (as only indices which were enumerable own properties at this point | 471 // existed (as only indices which were enumerable own properties at this point |
468 // should be serialized). | 472 // should be serialized). |
469 const bool should_serialize_densely = | 473 const bool should_serialize_densely = |
470 array->HasFastElements() && !array->HasFastHoleyElements(); | 474 array->HasFastElements() && !array->HasFastHoleyElements(); |
471 | 475 |
472 if (should_serialize_densely) { | 476 if (should_serialize_densely) { |
477 DCHECK_LE(length, kMaxDenseArrayLength); | |
478 | |
473 // TODO(jbroman): Distinguish between undefined and a hole (this can happen | 479 // TODO(jbroman): Distinguish between undefined and a hole (this can happen |
474 // if serializing one of the elements deletes another). This requires wire | 480 // if serializing one of the elements deletes another). This requires wire |
475 // format changes. | 481 // format changes. |
476 WriteTag(SerializationTag::kBeginDenseJSArray); | 482 WriteTag(SerializationTag::kBeginDenseJSArray); |
477 WriteVarint<uint32_t>(length); | 483 WriteVarint<uint32_t>(length); |
478 uint32_t i = 0; | 484 uint32_t i = 0; |
479 | 485 |
480 // Fast paths. Note that FAST_ELEMENTS in particular can bail due to the | 486 // Fast paths. Note that FAST_ELEMENTS in particular can bail due to the |
481 // structure of the elements changing. | 487 // structure of the elements changing. |
482 switch (array->GetElementsKind()) { | 488 switch (array->GetElementsKind()) { |
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1158 } | 1164 } |
1159 | 1165 |
1160 DCHECK(HasObjectWithID(id)); | 1166 DCHECK(HasObjectWithID(id)); |
1161 return scope.CloseAndEscape(array); | 1167 return scope.CloseAndEscape(array); |
1162 } | 1168 } |
1163 | 1169 |
1164 MaybeHandle<JSArray> ValueDeserializer::ReadDenseJSArray() { | 1170 MaybeHandle<JSArray> ValueDeserializer::ReadDenseJSArray() { |
1165 // If we are at the end of the stack, abort. This function may recurse. | 1171 // If we are at the end of the stack, abort. This function may recurse. |
1166 STACK_CHECK(isolate_, MaybeHandle<JSArray>()); | 1172 STACK_CHECK(isolate_, MaybeHandle<JSArray>()); |
1167 | 1173 |
1174 // We shouldn't permit an array larger than the biggest we can request from | |
1175 // V8. As an additional sanity check, since each entry will take at least one | |
1176 // byte to encode, if there are fewer bytes than that we can also fail fast. | |
1168 uint32_t length; | 1177 uint32_t length; |
1169 if (!ReadVarint<uint32_t>().To(&length)) return MaybeHandle<JSArray>(); | 1178 if (!ReadVarint<uint32_t>().To(&length) || length > kMaxDenseArrayLength || |
1179 length > static_cast<size_t>(end_ - position_)) { | |
1180 return MaybeHandle<JSArray>(); | |
1181 } | |
1170 | 1182 |
1171 uint32_t id = next_id_++; | 1183 uint32_t id = next_id_++; |
1172 HandleScope scope(isolate_); | 1184 HandleScope scope(isolate_); |
1173 Handle<JSArray> array = isolate_->factory()->NewJSArray( | 1185 Handle<JSArray> array = isolate_->factory()->NewJSArray( |
1174 FAST_HOLEY_ELEMENTS, length, length, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE, | 1186 FAST_HOLEY_ELEMENTS, length, length, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE, |
1175 pretenure_); | 1187 pretenure_); |
1176 AddObjectWithID(id, array); | 1188 AddObjectWithID(id, array); |
1177 | 1189 |
1178 Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate_); | 1190 Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate_); |
1179 for (uint32_t i = 0; i < length; i++) { | 1191 for (uint32_t i = 0; i < length; i++) { |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1724 if (stack.size() != 1) { | 1736 if (stack.size() != 1) { |
1725 isolate_->Throw(*isolate_->factory()->NewError( | 1737 isolate_->Throw(*isolate_->factory()->NewError( |
1726 MessageTemplate::kDataCloneDeserializationError)); | 1738 MessageTemplate::kDataCloneDeserializationError)); |
1727 return MaybeHandle<Object>(); | 1739 return MaybeHandle<Object>(); |
1728 } | 1740 } |
1729 return scope.CloseAndEscape(stack[0]); | 1741 return scope.CloseAndEscape(stack[0]); |
1730 } | 1742 } |
1731 | 1743 |
1732 } // namespace internal | 1744 } // namespace internal |
1733 } // namespace v8 | 1745 } // namespace v8 |
OLD | NEW |