Chromium Code Reviews| 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/snapshot/serializer.h" | 5 #include "src/snapshot/serializer.h" |
| 6 | 6 |
| 7 #include "src/assembler-inl.h" | 7 #include "src/assembler-inl.h" |
| 8 #include "src/deoptimizer.h" | 8 #include "src/deoptimizer.h" |
| 9 #include "src/heap/heap-inl.h" | 9 #include "src/heap/heap-inl.h" |
| 10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 394 #endif // OBJECT_PRINT | 394 #endif // OBJECT_PRINT |
| 395 | 395 |
| 396 // Mark this object as already serialized. | 396 // Mark this object as already serialized. |
| 397 serializer_->reference_map()->Add(object_, back_reference); | 397 serializer_->reference_map()->Add(object_, back_reference); |
| 398 | 398 |
| 399 // Serialize the map (first word of the object). | 399 // Serialize the map (first word of the object). |
| 400 serializer_->SerializeObject(map, kPlain, kStartOfObject, 0); | 400 serializer_->SerializeObject(map, kPlain, kStartOfObject, 0); |
| 401 } | 401 } |
| 402 | 402 |
| 403 void Serializer::ObjectSerializer::SerializeExternalString() { | 403 void Serializer::ObjectSerializer::SerializeExternalString() { |
| 404 Heap* heap = serializer_->isolate()->heap(); | |
| 405 if (object_->map() != heap->native_source_string_map()) { | |
| 406 // Usually we cannot recreate resources for external strings. To work | |
| 407 // around this, external strings are serialized to look like ordinary | |
| 408 // sequential strings. | |
| 409 // The exception are native source code strings, since we can recreate | |
| 410 // their resources. | |
| 411 SerializeExternalStringAsSequentialString(); | |
| 412 } else { | |
| 413 DCHECK(object_->IsExternalOneByteString()); | |
| 414 DCHECK(ExternalOneByteString::cast(object_)->is_short()); | |
| 415 int size = object_->Size(); | |
| 416 Map* map = object_->map(); | |
| 417 AllocationSpace space = | |
| 418 MemoryChunk::FromAddress(object_->address())->owner()->identity(); | |
| 419 SerializePrologue(space, size, map); | |
| 420 // Serialize the rest of the object. | |
| 421 CHECK_EQ(0, bytes_processed_so_far_); | |
|
ulan
2017/04/06 17:53:08
Lines 413-421 are from the Serialize function.
Th
| |
| 422 bytes_processed_so_far_ = kPointerSize; | |
| 423 typedef v8::String::ExternalOneByteStringResource Resource; | |
| 424 Resource** resource_pointer = reinterpret_cast<Resource**>( | |
| 425 HeapObject::RawField(object_, ExternalString::kResourceOffset)); | |
| 426 | |
| 427 Address references_start = reinterpret_cast<Address>(resource_pointer); | |
| 428 OutputRawData(references_start); | |
| 429 if (!SerializeExternalNativeSourceString( | |
| 430 Natives::GetBuiltinsCount(), resource_pointer, | |
| 431 Natives::GetSourceCache(heap), kNativesStringResource)) { | |
| 432 bool result = SerializeExternalNativeSourceString( | |
| 433 ExtraNatives::GetBuiltinsCount(), resource_pointer, | |
| 434 ExtraNatives::GetSourceCache(heap), kExtraNativesStringResource); | |
| 435 // One of the strings in the natives cache should match the resource. We | |
| 436 // don't expect any other kinds of external strings here. | |
| 437 USE(result); | |
| 438 DCHECK(result); | |
| 439 } | |
| 440 OutputRawData(object_->address() + size); | |
| 441 } | |
| 442 } | |
| 443 | |
| 444 bool Serializer::ObjectSerializer::SerializeExternalNativeSourceString( | |
| 445 int builtin_count, | |
| 446 v8::String::ExternalOneByteStringResource** resource_pointer, | |
| 447 FixedArray* source_cache, int resource_index) { | |
| 448 Isolate* isolate = serializer_->isolate(); | |
|
ulan
2017/04/06 17:53:08
This function moved without any change.
| |
| 449 for (int i = 0; i < builtin_count; i++) { | |
| 450 Object* source = source_cache->get(i); | |
| 451 if (!source->IsUndefined(isolate)) { | |
| 452 ExternalOneByteString* string = ExternalOneByteString::cast(source); | |
| 453 typedef v8::String::ExternalOneByteStringResource Resource; | |
| 454 const Resource* resource = string->resource(); | |
| 455 if (resource == *resource_pointer) { | |
| 456 sink_->Put(resource_index, "NativesStringResource"); | |
| 457 sink_->PutSection(i, "NativesStringResourceEnd"); | |
| 458 bytes_processed_so_far_ += sizeof(resource); | |
| 459 return true; | |
| 460 } | |
| 461 } | |
| 462 } | |
| 463 return false; | |
| 464 } | |
| 465 | |
| 466 void Serializer::ObjectSerializer::SerializeExternalStringAsSequentialString() { | |
| 404 // Instead of serializing this as an external string, we serialize | 467 // Instead of serializing this as an external string, we serialize |
| 405 // an imaginary sequential string with the same content. | 468 // an imaginary sequential string with the same content. |
| 406 Isolate* isolate = serializer_->isolate(); | 469 Isolate* isolate = serializer_->isolate(); |
| 407 DCHECK(object_->IsExternalString()); | 470 DCHECK(object_->IsExternalString()); |
| 408 DCHECK(object_->map() != isolate->heap()->native_source_string_map()); | 471 DCHECK(object_->map() != isolate->heap()->native_source_string_map()); |
| 409 ExternalString* string = ExternalString::cast(object_); | 472 ExternalString* string = ExternalString::cast(object_); |
| 410 int length = string->length(); | 473 int length = string->length(); |
| 411 Map* map; | 474 Map* map; |
| 412 int content_size; | 475 int content_size; |
| 413 int allocation_size; | 476 int allocation_size; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 494 DisallowHeapAllocation no_gc_; | 557 DisallowHeapAllocation no_gc_; |
| 495 }; | 558 }; |
| 496 | 559 |
| 497 void Serializer::ObjectSerializer::Serialize() { | 560 void Serializer::ObjectSerializer::Serialize() { |
| 498 if (FLAG_trace_serializer) { | 561 if (FLAG_trace_serializer) { |
| 499 PrintF(" Encoding heap object: "); | 562 PrintF(" Encoding heap object: "); |
| 500 object_->ShortPrint(); | 563 object_->ShortPrint(); |
| 501 PrintF("\n"); | 564 PrintF("\n"); |
| 502 } | 565 } |
| 503 | 566 |
| 504 // We cannot serialize typed array objects correctly. | 567 if (object_->IsExternalString()) { |
| 505 DCHECK(!object_->IsJSTypedArray()); | 568 SerializeExternalString(); |
| 569 } else { | |
| 570 // We cannot serialize typed array objects correctly. | |
| 571 DCHECK(!object_->IsJSTypedArray()); | |
| 506 | 572 |
| 507 // We don't expect fillers. | 573 // We don't expect fillers. |
| 508 DCHECK(!object_->IsFiller()); | 574 DCHECK(!object_->IsFiller()); |
| 509 | 575 |
| 510 if (object_->IsScript()) { | 576 if (object_->IsScript()) { |
| 511 // Clear cached line ends. | 577 // Clear cached line ends. |
| 512 Object* undefined = serializer_->isolate()->heap()->undefined_value(); | 578 Object* undefined = serializer_->isolate()->heap()->undefined_value(); |
| 513 Script::cast(object_)->set_line_ends(undefined); | 579 Script::cast(object_)->set_line_ends(undefined); |
| 514 } | 580 } |
| 515 | 581 |
| 516 if (object_->IsExternalString()) { | 582 int size = object_->Size(); |
|
ulan
2017/04/06 17:53:08
This code just moved verbatim from 529.
| |
| 517 Heap* heap = serializer_->isolate()->heap(); | 583 Map* map = object_->map(); |
| 518 if (object_->map() != heap->native_source_string_map()) { | 584 AllocationSpace space = |
| 519 // Usually we cannot recreate resources for external strings. To work | 585 MemoryChunk::FromAddress(object_->address())->owner()->identity(); |
| 520 // around this, external strings are serialized to look like ordinary | 586 SerializePrologue(space, size, map); |
| 521 // sequential strings. | 587 |
| 522 // The exception are native source code strings, since we can recreate | 588 // Serialize the rest of the object. |
| 523 // their resources. In that case we fall through and leave it to | 589 CHECK_EQ(0, bytes_processed_so_far_); |
| 524 // VisitExternalOneByteString further down. | 590 bytes_processed_so_far_ = kPointerSize; |
| 525 SerializeExternalString(); | 591 |
| 592 RecursionScope recursion(serializer_); | |
| 593 // Objects that are immediately post processed during deserialization | |
| 594 // cannot be deferred, since post processing requires the object content. | |
| 595 if (recursion.ExceedsMaximum() && CanBeDeferred(object_)) { | |
| 596 serializer_->QueueDeferredObject(object_); | |
| 597 sink_->Put(kDeferred, "Deferring object content"); | |
| 526 return; | 598 return; |
| 527 } | 599 } |
| 600 | |
| 601 UnlinkWeakNextScope unlink_weak_next(object_); | |
| 602 | |
| 603 object_->IterateBody(map->instance_type(), size, this); | |
| 604 OutputRawData(object_->address() + size); | |
| 528 } | 605 } |
| 529 | |
| 530 int size = object_->Size(); | |
| 531 Map* map = object_->map(); | |
| 532 AllocationSpace space = | |
| 533 MemoryChunk::FromAddress(object_->address())->owner()->identity(); | |
| 534 SerializePrologue(space, size, map); | |
| 535 | |
| 536 // Serialize the rest of the object. | |
| 537 CHECK_EQ(0, bytes_processed_so_far_); | |
| 538 bytes_processed_so_far_ = kPointerSize; | |
| 539 | |
| 540 RecursionScope recursion(serializer_); | |
| 541 // Objects that are immediately post processed during deserialization | |
| 542 // cannot be deferred, since post processing requires the object content. | |
| 543 if (recursion.ExceedsMaximum() && CanBeDeferred(object_)) { | |
| 544 serializer_->QueueDeferredObject(object_); | |
| 545 sink_->Put(kDeferred, "Deferring object content"); | |
| 546 return; | |
| 547 } | |
| 548 | |
| 549 UnlinkWeakNextScope unlink_weak_next(object_); | |
| 550 | |
| 551 object_->IterateBody(map->instance_type(), size, this); | |
| 552 OutputRawData(object_->address() + size); | |
| 553 } | 606 } |
| 554 | 607 |
| 555 void Serializer::ObjectSerializer::SerializeDeferred() { | 608 void Serializer::ObjectSerializer::SerializeDeferred() { |
| 556 if (FLAG_trace_serializer) { | 609 if (FLAG_trace_serializer) { |
| 557 PrintF(" Encoding deferred heap object: "); | 610 PrintF(" Encoding deferred heap object: "); |
| 558 object_->ShortPrint(); | 611 object_->ShortPrint(); |
| 559 PrintF("\n"); | 612 PrintF("\n"); |
| 560 } | 613 } |
| 561 | 614 |
| 562 int size = object_->Size(); | 615 int size = object_->Size(); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 708 bytes_processed_so_far_ += kPointerSize; | 761 bytes_processed_so_far_ += kPointerSize; |
| 709 } | 762 } |
| 710 | 763 |
| 711 void Serializer::ObjectSerializer::VisitCell(RelocInfo* rinfo) { | 764 void Serializer::ObjectSerializer::VisitCell(RelocInfo* rinfo) { |
| 712 int skip = OutputRawData(rinfo->pc(), kCanReturnSkipInsteadOfSkipping); | 765 int skip = OutputRawData(rinfo->pc(), kCanReturnSkipInsteadOfSkipping); |
| 713 Cell* object = Cell::cast(rinfo->target_cell()); | 766 Cell* object = Cell::cast(rinfo->target_cell()); |
| 714 serializer_->SerializeObject(object, kPlain, kInnerPointer, skip); | 767 serializer_->SerializeObject(object, kPlain, kInnerPointer, skip); |
| 715 bytes_processed_so_far_ += kPointerSize; | 768 bytes_processed_so_far_ += kPointerSize; |
| 716 } | 769 } |
| 717 | 770 |
| 718 bool Serializer::ObjectSerializer::SerializeExternalNativeSourceString( | |
| 719 int builtin_count, | |
| 720 v8::String::ExternalOneByteStringResource** resource_pointer, | |
| 721 FixedArray* source_cache, int resource_index) { | |
| 722 Isolate* isolate = serializer_->isolate(); | |
| 723 for (int i = 0; i < builtin_count; i++) { | |
| 724 Object* source = source_cache->get(i); | |
| 725 if (!source->IsUndefined(isolate)) { | |
| 726 ExternalOneByteString* string = ExternalOneByteString::cast(source); | |
| 727 typedef v8::String::ExternalOneByteStringResource Resource; | |
| 728 const Resource* resource = string->resource(); | |
| 729 if (resource == *resource_pointer) { | |
| 730 sink_->Put(resource_index, "NativesStringResource"); | |
| 731 sink_->PutSection(i, "NativesStringResourceEnd"); | |
| 732 bytes_processed_so_far_ += sizeof(resource); | |
| 733 return true; | |
| 734 } | |
| 735 } | |
| 736 } | |
| 737 return false; | |
| 738 } | |
| 739 | |
| 740 void Serializer::ObjectSerializer::VisitExternalOneByteString( | |
| 741 v8::String::ExternalOneByteStringResource** resource_pointer) { | |
| 742 DCHECK_EQ(serializer_->isolate()->heap()->native_source_string_map(), | |
| 743 object_->map()); | |
| 744 DCHECK(ExternalOneByteString::cast(object_)->is_short()); | |
| 745 Address references_start = reinterpret_cast<Address>(resource_pointer); | |
| 746 OutputRawData(references_start); | |
| 747 if (SerializeExternalNativeSourceString( | |
| 748 Natives::GetBuiltinsCount(), resource_pointer, | |
| 749 Natives::GetSourceCache(serializer_->isolate()->heap()), | |
| 750 kNativesStringResource)) { | |
| 751 return; | |
| 752 } | |
| 753 if (SerializeExternalNativeSourceString( | |
| 754 ExtraNatives::GetBuiltinsCount(), resource_pointer, | |
| 755 ExtraNatives::GetSourceCache(serializer_->isolate()->heap()), | |
| 756 kExtraNativesStringResource)) { | |
| 757 return; | |
| 758 } | |
| 759 // One of the strings in the natives cache should match the resource. We | |
| 760 // don't expect any other kinds of external strings here. | |
| 761 UNREACHABLE(); | |
| 762 } | |
| 763 | |
| 764 Address Serializer::ObjectSerializer::PrepareCode() { | 771 Address Serializer::ObjectSerializer::PrepareCode() { |
| 765 Code* code = Code::cast(object_); | 772 Code* code = Code::cast(object_); |
| 766 if (FLAG_predictable) { | 773 if (FLAG_predictable) { |
| 767 // To make snapshots reproducible, we make a copy of the code object | 774 // To make snapshots reproducible, we make a copy of the code object |
| 768 // and wipe all pointers in the copy, which we then serialize. | 775 // and wipe all pointers in the copy, which we then serialize. |
| 769 code = serializer_->CopyCode(code); | 776 code = serializer_->CopyCode(code); |
| 770 int mode_mask = RelocInfo::kCodeTargetMask | | 777 int mode_mask = RelocInfo::kCodeTargetMask | |
| 771 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 778 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
| 772 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | 779 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
| 773 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) | | 780 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) | |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 826 if (to_skip != 0 && return_skip == kIgnoringReturn) { | 833 if (to_skip != 0 && return_skip == kIgnoringReturn) { |
| 827 sink_->Put(kSkip, "Skip"); | 834 sink_->Put(kSkip, "Skip"); |
| 828 sink_->PutInt(to_skip, "SkipDistance"); | 835 sink_->PutInt(to_skip, "SkipDistance"); |
| 829 to_skip = 0; | 836 to_skip = 0; |
| 830 } | 837 } |
| 831 return to_skip; | 838 return to_skip; |
| 832 } | 839 } |
| 833 | 840 |
| 834 } // namespace internal | 841 } // namespace internal |
| 835 } // namespace v8 | 842 } // namespace v8 |
| OLD | NEW |