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" |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 bool valid_length = array->length()->ToArrayLength(&length); | 444 bool valid_length = array->length()->ToArrayLength(&length); |
445 DCHECK(valid_length); | 445 DCHECK(valid_length); |
446 USE(valid_length); | 446 USE(valid_length); |
447 | 447 |
448 // To keep things simple, for now we decide between dense and sparse | 448 // To keep things simple, for now we decide between dense and sparse |
449 // serialization based on elements kind. A more principled heuristic could | 449 // serialization based on elements kind. A more principled heuristic could |
450 // count the elements, but would need to take care to note which indices | 450 // count the elements, but would need to take care to note which indices |
451 // existed (as only indices which were enumerable own properties at this point | 451 // existed (as only indices which were enumerable own properties at this point |
452 // should be serialized). | 452 // should be serialized). |
453 const bool should_serialize_densely = | 453 const bool should_serialize_densely = |
454 array->HasFastElements() && !array->HasFastHoleyElements(); | 454 array->HasFastElements() && !array->HasFastHoleyElements(); |
Camillo Bruni
2016/09/07 02:28:07
This might be a future optimization point by seria
jbroman
2016/09/07 14:53:39
Yeah, it's possible, though it takes a little care
| |
455 | 455 |
456 if (should_serialize_densely) { | 456 if (should_serialize_densely) { |
457 // TODO(jbroman): Distinguish between undefined and a hole (this can happen | 457 // TODO(jbroman): Distinguish between undefined and a hole (this can happen |
458 // if serializing one of the elements deletes another). This requires wire | 458 // if serializing one of the elements deletes another). This requires wire |
459 // format changes. | 459 // format changes. |
460 WriteTag(SerializationTag::kBeginDenseJSArray); | 460 WriteTag(SerializationTag::kBeginDenseJSArray); |
461 WriteVarint<uint32_t>(length); | 461 WriteVarint<uint32_t>(length); |
462 for (uint32_t i = 0; i < length; i++) { | 462 uint32_t i = 0; |
463 | |
464 // Fast paths. Note that FAST_ELEMENTS in particular can bail due to the | |
465 // structure of the elements changing. | |
466 switch (array->GetElementsKind()) { | |
Camillo Bruni
2016/09/07 02:28:08
With only 3 cases present here there is currently
jbroman
2016/09/07 14:53:39
I'm not sure what operation could be added to Elem
| |
467 case FAST_SMI_ELEMENTS: { | |
468 Handle<FixedArray> elements(FixedArray::cast(array->elements()), | |
469 isolate_); | |
470 for (; i < length; i++) WriteSmi(Smi::cast(elements->get(i))); | |
471 break; | |
472 } | |
473 case FAST_DOUBLE_ELEMENTS: { | |
474 Handle<FixedDoubleArray> elements( | |
475 FixedDoubleArray::cast(array->elements()), isolate_); | |
476 for (; i < length; i++) { | |
477 WriteTag(SerializationTag::kDouble); | |
478 WriteDouble(elements->get_scalar(i)); | |
479 } | |
480 break; | |
481 } | |
482 case FAST_ELEMENTS: { | |
483 Handle<Object> old_length(array->length(), isolate_); | |
484 for (; i < length; i++) { | |
485 if (array->length() != *old_length || | |
486 array->GetElementsKind() != FAST_ELEMENTS) { | |
487 // Fall back to slow path. | |
488 break; | |
489 } | |
490 Handle<Object> element(FixedArray::cast(array->elements())->get(i), | |
491 isolate_); | |
492 if (!WriteObject(element).FromMaybe(false)) return Nothing<bool>(); | |
493 } | |
494 break; | |
495 } | |
496 default: | |
497 break; | |
498 } | |
499 | |
500 // If there are elements remaining, serialize them slowly. | |
501 for (; i < length; i++) { | |
463 // Serializing the array's elements can have arbitrary side effects, so we | 502 // Serializing the array's elements can have arbitrary side effects, so we |
464 // cannot rely on still having fast elements, even if it did to begin | 503 // cannot rely on still having fast elements, even if it did to begin |
465 // with. | 504 // with. |
466 Handle<Object> element; | 505 Handle<Object> element; |
467 LookupIterator it(isolate_, array, i, array, LookupIterator::OWN); | 506 LookupIterator it(isolate_, array, i, array, LookupIterator::OWN); |
468 if (!Object::GetProperty(&it).ToHandle(&element) || | 507 if (!Object::GetProperty(&it).ToHandle(&element) || |
469 !WriteObject(element).FromMaybe(false)) { | 508 !WriteObject(element).FromMaybe(false)) { |
Camillo Bruni
2016/09/07 02:28:07
edge-case nit: in the case where the array length
jbroman
2016/09/07 14:53:39
I've added such a test case, but it passes already
| |
470 return Nothing<bool>(); | 509 return Nothing<bool>(); |
471 } | 510 } |
472 } | 511 } |
512 | |
473 KeyAccumulator accumulator(isolate_, KeyCollectionMode::kOwnOnly, | 513 KeyAccumulator accumulator(isolate_, KeyCollectionMode::kOwnOnly, |
474 ENUMERABLE_STRINGS); | 514 ENUMERABLE_STRINGS); |
475 if (!accumulator.CollectOwnPropertyNames(array, array).FromMaybe(false)) { | 515 if (!accumulator.CollectOwnPropertyNames(array, array).FromMaybe(false)) { |
476 return Nothing<bool>(); | 516 return Nothing<bool>(); |
477 } | 517 } |
478 Handle<FixedArray> keys = | 518 Handle<FixedArray> keys = |
479 accumulator.GetKeys(GetKeysConversion::kConvertToString); | 519 accumulator.GetKeys(GetKeysConversion::kConvertToString); |
480 uint32_t properties_written; | 520 uint32_t properties_written; |
481 if (!WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) { | 521 if (!WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) { |
482 return Nothing<bool>(); | 522 return Nothing<bool>(); |
(...skipping 956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1439 if (stack.size() != 1) { | 1479 if (stack.size() != 1) { |
1440 isolate_->Throw(*isolate_->factory()->NewError( | 1480 isolate_->Throw(*isolate_->factory()->NewError( |
1441 MessageTemplate::kDataCloneDeserializationError)); | 1481 MessageTemplate::kDataCloneDeserializationError)); |
1442 return MaybeHandle<Object>(); | 1482 return MaybeHandle<Object>(); |
1443 } | 1483 } |
1444 return scope.CloseAndEscape(stack[0]); | 1484 return scope.CloseAndEscape(stack[0]); |
1445 } | 1485 } |
1446 | 1486 |
1447 } // namespace internal | 1487 } // namespace internal |
1448 } // namespace v8 | 1488 } // namespace v8 |
OLD | NEW |