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 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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(); |
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()) { |
| 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)) { |
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 |