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

Side by Side Diff: src/serialize.cc

Issue 10918067: Refactoring of snapshots. This simplifies and improves (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 8 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « src/serialize.h ('k') | src/snapshot.h » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 592
593 593
594 bool Serializer::serialization_enabled_ = false; 594 bool Serializer::serialization_enabled_ = false;
595 bool Serializer::too_late_to_enable_now_ = false; 595 bool Serializer::too_late_to_enable_now_ = false;
596 596
597 597
598 Deserializer::Deserializer(SnapshotByteSource* source) 598 Deserializer::Deserializer(SnapshotByteSource* source)
599 : isolate_(NULL), 599 : isolate_(NULL),
600 source_(source), 600 source_(source),
601 external_reference_decoder_(NULL) { 601 external_reference_decoder_(NULL) {
602 } 602 for (int i = 0; i < LAST_SPACE + 1; i++) {
603 603 reservations_[i] = kUninitializedReservation;
604
605 // This routine both allocates a new object, and also keeps
606 // track of where objects have been allocated so that we can
607 // fix back references when deserializing.
608 Address Deserializer::Allocate(int space_index, Space* space, int size) {
609 Address address;
610 if (!SpaceIsLarge(space_index)) {
611 ASSERT(!SpaceIsPaged(space_index) ||
612 size <= Page::kPageSize - Page::kObjectStartOffset);
613 MaybeObject* maybe_new_allocation;
614 if (space_index == NEW_SPACE) {
615 maybe_new_allocation =
616 reinterpret_cast<NewSpace*>(space)->AllocateRaw(size);
617 } else {
618 maybe_new_allocation =
619 reinterpret_cast<PagedSpace*>(space)->AllocateRaw(size);
620 }
621 ASSERT(!maybe_new_allocation->IsFailure());
622 Object* new_allocation = maybe_new_allocation->ToObjectUnchecked();
623 HeapObject* new_object = HeapObject::cast(new_allocation);
624 address = new_object->address();
625 high_water_[space_index] = address + size;
626 } else {
627 ASSERT(SpaceIsLarge(space_index));
628 LargeObjectSpace* lo_space = reinterpret_cast<LargeObjectSpace*>(space);
629 Object* new_allocation;
630 if (space_index == kLargeData || space_index == kLargeFixedArray) {
631 new_allocation =
632 lo_space->AllocateRaw(size, NOT_EXECUTABLE)->ToObjectUnchecked();
633 } else {
634 ASSERT_EQ(kLargeCode, space_index);
635 new_allocation =
636 lo_space->AllocateRaw(size, EXECUTABLE)->ToObjectUnchecked();
637 }
638 HeapObject* new_object = HeapObject::cast(new_allocation);
639 // Record all large objects in the same space.
640 address = new_object->address();
641 pages_[LO_SPACE].Add(address);
642 } 604 }
643 last_object_address_ = address;
644 return address;
645 }
646
647
648 // This returns the address of an object that has been described in the
649 // snapshot as being offset bytes back in a particular space.
650 HeapObject* Deserializer::GetAddressFromEnd(int space) {
651 int offset = source_->GetInt();
652 ASSERT(!SpaceIsLarge(space));
653 offset <<= kObjectAlignmentBits;
654 return HeapObject::FromAddress(high_water_[space] - offset);
655 }
656
657
658 // This returns the address of an object that has been described in the
659 // snapshot as being offset bytes into a particular space.
660 HeapObject* Deserializer::GetAddressFromStart(int space) {
661 int offset = source_->GetInt();
662 if (SpaceIsLarge(space)) {
663 // Large spaces have one object per 'page'.
664 return HeapObject::FromAddress(pages_[LO_SPACE][offset]);
665 }
666 offset <<= kObjectAlignmentBits;
667 if (space == NEW_SPACE) {
668 // New space has only one space - numbered 0.
669 return HeapObject::FromAddress(pages_[space][0] + offset);
670 }
671 ASSERT(SpaceIsPaged(space));
672 int page_of_pointee = offset >> kPageSizeBits;
673 Address object_address = pages_[space][page_of_pointee] +
674 (offset & Page::kPageAlignmentMask);
675 return HeapObject::FromAddress(object_address);
676 } 605 }
677 606
678 607
679 void Deserializer::Deserialize() { 608 void Deserializer::Deserialize() {
680 isolate_ = Isolate::Current(); 609 isolate_ = Isolate::Current();
681 ASSERT(isolate_ != NULL); 610 ASSERT(isolate_ != NULL);
682 { 611 isolate_->heap()->ReserveSpace(reservations_, &high_water_[0]);
683 // Don't GC while deserializing - just expand the heap. 612 // No active threads.
684 AlwaysAllocateScope always_allocate; 613 ASSERT_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse());
685 // Don't use the free lists while deserializing. 614 // No active handles.
686 LinearAllocationScope allocate_linearly; 615 ASSERT(isolate_->handle_scope_implementer()->blocks()->is_empty());
687 // No active threads. 616 ASSERT_EQ(NULL, external_reference_decoder_);
688 ASSERT_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse()); 617 external_reference_decoder_ = new ExternalReferenceDecoder();
689 // No active handles. 618 isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
690 ASSERT(isolate_->handle_scope_implementer()->blocks()->is_empty()); 619 isolate_->heap()->RepairFreeListsAfterBoot();
691 ASSERT_EQ(NULL, external_reference_decoder_); 620 isolate_->heap()->IterateWeakRoots(this, VISIT_ALL);
692 external_reference_decoder_ = new ExternalReferenceDecoder();
693 isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
694 isolate_->heap()->IterateWeakRoots(this, VISIT_ALL);
695 621
696 isolate_->heap()->set_native_contexts_list( 622 isolate_->heap()->set_native_contexts_list(
697 isolate_->heap()->undefined_value()); 623 isolate_->heap()->undefined_value());
698 624
699 // Update data pointers to the external strings containing natives sources. 625 // Update data pointers to the external strings containing natives sources.
700 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { 626 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
701 Object* source = isolate_->heap()->natives_source_cache()->get(i); 627 Object* source = isolate_->heap()->natives_source_cache()->get(i);
702 if (!source->IsUndefined()) { 628 if (!source->IsUndefined()) {
703 ExternalAsciiString::cast(source)->update_data_cache(); 629 ExternalAsciiString::cast(source)->update_data_cache();
704 }
705 } 630 }
706 } 631 }
707 632
708 // Issue code events for newly deserialized code objects. 633 // Issue code events for newly deserialized code objects.
709 LOG_CODE_EVENT(isolate_, LogCodeObjects()); 634 LOG_CODE_EVENT(isolate_, LogCodeObjects());
710 LOG_CODE_EVENT(isolate_, LogCompiledFunctions()); 635 LOG_CODE_EVENT(isolate_, LogCompiledFunctions());
711 } 636 }
712 637
713 638
714 void Deserializer::DeserializePartial(Object** root) { 639 void Deserializer::DeserializePartial(Object** root) {
715 isolate_ = Isolate::Current(); 640 isolate_ = Isolate::Current();
716 // Don't GC while deserializing - just expand the heap. 641 for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
717 AlwaysAllocateScope always_allocate; 642 ASSERT(reservations_[i] != kUninitializedReservation);
718 // Don't use the free lists while deserializing. 643 }
719 LinearAllocationScope allocate_linearly; 644 isolate_->heap()->ReserveSpace(reservations_, &high_water_[0]);
720 if (external_reference_decoder_ == NULL) { 645 if (external_reference_decoder_ == NULL) {
721 external_reference_decoder_ = new ExternalReferenceDecoder(); 646 external_reference_decoder_ = new ExternalReferenceDecoder();
722 } 647 }
723 648
724 // Keep track of the code space start and end pointers in case new 649 // Keep track of the code space start and end pointers in case new
725 // code objects were unserialized 650 // code objects were unserialized
726 OldSpace* code_space = isolate_->heap()->code_space(); 651 OldSpace* code_space = isolate_->heap()->code_space();
727 Address start_address = code_space->top(); 652 Address start_address = code_space->top();
728 VisitPointer(root); 653 VisitPointer(root);
729 654
(...skipping 21 matching lines...) Expand all
751 ReadChunk(start, end, NEW_SPACE, NULL); 676 ReadChunk(start, end, NEW_SPACE, NULL);
752 } 677 }
753 678
754 679
755 // This routine writes the new object into the pointer provided and then 680 // This routine writes the new object into the pointer provided and then
756 // returns true if the new object was in young space and false otherwise. 681 // returns true if the new object was in young space and false otherwise.
757 // The reason for this strange interface is that otherwise the object is 682 // The reason for this strange interface is that otherwise the object is
758 // written very late, which means the FreeSpace map is not set up by the 683 // written very late, which means the FreeSpace map is not set up by the
759 // time we need to use it to mark the space at the end of a page free. 684 // time we need to use it to mark the space at the end of a page free.
760 void Deserializer::ReadObject(int space_number, 685 void Deserializer::ReadObject(int space_number,
761 Space* space,
762 Object** write_back) { 686 Object** write_back) {
763 int size = source_->GetInt() << kObjectAlignmentBits; 687 int size = source_->GetInt() << kObjectAlignmentBits;
764 Address address = Allocate(space_number, space, size); 688 Address address = Allocate(space_number, size);
765 *write_back = HeapObject::FromAddress(address); 689 *write_back = HeapObject::FromAddress(address);
766 Object** current = reinterpret_cast<Object**>(address); 690 Object** current = reinterpret_cast<Object**>(address);
767 Object** limit = current + (size >> kPointerSizeLog2); 691 Object** limit = current + (size >> kPointerSizeLog2);
768 if (FLAG_log_snapshot_positions) { 692 if (FLAG_log_snapshot_positions) {
769 LOG(isolate_, SnapshotPositionEvent(address, source_->position())); 693 LOG(isolate_, SnapshotPositionEvent(address, source_->position()));
770 } 694 }
771 ReadChunk(current, limit, space_number, address); 695 ReadChunk(current, limit, space_number, address);
772 #ifdef DEBUG 696 #ifdef DEBUG
773 bool is_codespace = (space == HEAP->code_space()) || 697 bool is_codespace = (space_number == CODE_SPACE);
774 ((space == HEAP->lo_space()) && (space_number == kLargeCode));
775 ASSERT(HeapObject::FromAddress(address)->IsCode() == is_codespace); 698 ASSERT(HeapObject::FromAddress(address)->IsCode() == is_codespace);
776 #endif 699 #endif
777 } 700 }
778 701
779
780 // This macro is always used with a constant argument so it should all fold
781 // away to almost nothing in the generated code. It might be nicer to do this
782 // with the ternary operator but there are type issues with that.
783 #define ASSIGN_DEST_SPACE(space_number) \
784 Space* dest_space; \
785 if (space_number == NEW_SPACE) { \
786 dest_space = isolate->heap()->new_space(); \
787 } else if (space_number == OLD_POINTER_SPACE) { \
788 dest_space = isolate->heap()->old_pointer_space(); \
789 } else if (space_number == OLD_DATA_SPACE) { \
790 dest_space = isolate->heap()->old_data_space(); \
791 } else if (space_number == CODE_SPACE) { \
792 dest_space = isolate->heap()->code_space(); \
793 } else if (space_number == MAP_SPACE) { \
794 dest_space = isolate->heap()->map_space(); \
795 } else if (space_number == CELL_SPACE) { \
796 dest_space = isolate->heap()->cell_space(); \
797 } else { \
798 ASSERT(space_number >= LO_SPACE); \
799 dest_space = isolate->heap()->lo_space(); \
800 }
801
802
803 static const int kUnknownOffsetFromStart = -1;
804
805
806 void Deserializer::ReadChunk(Object** current, 702 void Deserializer::ReadChunk(Object** current,
807 Object** limit, 703 Object** limit,
808 int source_space, 704 int source_space,
809 Address current_object_address) { 705 Address current_object_address) {
810 Isolate* const isolate = isolate_; 706 Isolate* const isolate = isolate_;
707 // Write barrier support costs around 1% in startup time. In fact there
708 // are no new space objects in current boot snapshots, so it's not needed,
709 // but that may change.
811 bool write_barrier_needed = (current_object_address != NULL && 710 bool write_barrier_needed = (current_object_address != NULL &&
812 source_space != NEW_SPACE && 711 source_space != NEW_SPACE &&
813 source_space != CELL_SPACE && 712 source_space != CELL_SPACE &&
814 source_space != CODE_SPACE && 713 source_space != CODE_SPACE &&
815 source_space != OLD_DATA_SPACE); 714 source_space != OLD_DATA_SPACE);
816 while (current < limit) { 715 while (current < limit) {
817 int data = source_->Get(); 716 int data = source_->Get();
818 switch (data) { 717 switch (data) {
819 #define CASE_STATEMENT(where, how, within, space_number) \ 718 #define CASE_STATEMENT(where, how, within, space_number) \
820 case where + how + within + space_number: \ 719 case where + how + within + space_number: \
821 ASSERT((where & ~kPointedToMask) == 0); \ 720 ASSERT((where & ~kPointedToMask) == 0); \
822 ASSERT((how & ~kHowToCodeMask) == 0); \ 721 ASSERT((how & ~kHowToCodeMask) == 0); \
823 ASSERT((within & ~kWhereToPointMask) == 0); \ 722 ASSERT((within & ~kWhereToPointMask) == 0); \
824 ASSERT((space_number & ~kSpaceMask) == 0); 723 ASSERT((space_number & ~kSpaceMask) == 0);
825 724
826 #define CASE_BODY(where, how, within, space_number_if_any, offset_from_start) \ 725 #define CASE_BODY(where, how, within, space_number_if_any) \
827 { \ 726 { \
828 bool emit_write_barrier = false; \ 727 bool emit_write_barrier = false; \
829 bool current_was_incremented = false; \ 728 bool current_was_incremented = false; \
830 int space_number = space_number_if_any == kAnyOldSpace ? \ 729 int space_number = space_number_if_any == kAnyOldSpace ? \
831 (data & kSpaceMask) : space_number_if_any; \ 730 (data & kSpaceMask) : space_number_if_any; \
832 if (where == kNewObject && how == kPlain && within == kStartOfObject) {\ 731 if (where == kNewObject && how == kPlain && within == kStartOfObject) {\
833 ASSIGN_DEST_SPACE(space_number) \ 732 ReadObject(space_number, current); \
834 ReadObject(space_number, dest_space, current); \
835 emit_write_barrier = (space_number == NEW_SPACE); \ 733 emit_write_barrier = (space_number == NEW_SPACE); \
836 } else { \ 734 } else { \
837 Object* new_object = NULL; /* May not be a real Object pointer. */ \ 735 Object* new_object = NULL; /* May not be a real Object pointer. */ \
838 if (where == kNewObject) { \ 736 if (where == kNewObject) { \
839 ASSIGN_DEST_SPACE(space_number) \ 737 ReadObject(space_number, &new_object); \
840 ReadObject(space_number, dest_space, &new_object); \
841 } else if (where == kRootArray) { \ 738 } else if (where == kRootArray) { \
842 int root_id = source_->GetInt(); \ 739 int root_id = source_->GetInt(); \
843 new_object = isolate->heap()->roots_array_start()[root_id]; \ 740 new_object = isolate->heap()->roots_array_start()[root_id]; \
844 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ 741 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \
845 } else if (where == kPartialSnapshotCache) { \ 742 } else if (where == kPartialSnapshotCache) { \
846 int cache_index = source_->GetInt(); \ 743 int cache_index = source_->GetInt(); \
847 new_object = isolate->serialize_partial_snapshot_cache() \ 744 new_object = isolate->serialize_partial_snapshot_cache() \
848 [cache_index]; \ 745 [cache_index]; \
849 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ 746 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \
850 } else if (where == kExternalReference) { \ 747 } else if (where == kExternalReference) { \
748 int skip = source_->GetInt(); \
749 current = reinterpret_cast<Object**>(reinterpret_cast<Address>( \
750 current) + skip); \
851 int reference_id = source_->GetInt(); \ 751 int reference_id = source_->GetInt(); \
852 Address address = external_reference_decoder_-> \ 752 Address address = external_reference_decoder_-> \
853 Decode(reference_id); \ 753 Decode(reference_id); \
854 new_object = reinterpret_cast<Object*>(address); \ 754 new_object = reinterpret_cast<Object*>(address); \
855 } else if (where == kBackref) { \ 755 } else if (where == kBackref) { \
856 emit_write_barrier = (space_number == NEW_SPACE); \ 756 emit_write_barrier = (space_number == NEW_SPACE); \
857 new_object = GetAddressFromEnd(data & kSpaceMask); \ 757 new_object = GetAddressFromEnd(data & kSpaceMask); \
858 } else { \ 758 } else { \
859 ASSERT(where == kFromStart); \ 759 ASSERT(where == kBackrefWithSkip); \
860 if (offset_from_start == kUnknownOffsetFromStart) { \ 760 int skip = source_->GetInt(); \
861 emit_write_barrier = (space_number == NEW_SPACE); \ 761 current = reinterpret_cast<Object**>( \
862 new_object = GetAddressFromStart(data & kSpaceMask); \ 762 reinterpret_cast<Address>(current) + skip); \
863 } else { \ 763 emit_write_barrier = (space_number == NEW_SPACE); \
864 Address object_address = pages_[space_number][0] + \ 764 new_object = GetAddressFromEnd(data & kSpaceMask); \
865 (offset_from_start << kObjectAlignmentBits); \
866 new_object = HeapObject::FromAddress(object_address); \
867 } \
868 } \ 765 } \
869 if (within == kInnerPointer) { \ 766 if (within == kInnerPointer) { \
870 if (space_number != CODE_SPACE || new_object->IsCode()) { \ 767 if (space_number != CODE_SPACE || new_object->IsCode()) { \
871 Code* new_code_object = reinterpret_cast<Code*>(new_object); \ 768 Code* new_code_object = reinterpret_cast<Code*>(new_object); \
872 new_object = reinterpret_cast<Object*>( \ 769 new_object = reinterpret_cast<Object*>( \
873 new_code_object->instruction_start()); \ 770 new_code_object->instruction_start()); \
874 } else { \ 771 } else { \
875 ASSERT(space_number == CODE_SPACE || space_number == kLargeCode);\ 772 ASSERT(space_number == CODE_SPACE); \
876 JSGlobalPropertyCell* cell = \ 773 JSGlobalPropertyCell* cell = \
877 JSGlobalPropertyCell::cast(new_object); \ 774 JSGlobalPropertyCell::cast(new_object); \
878 new_object = reinterpret_cast<Object*>( \ 775 new_object = reinterpret_cast<Object*>( \
879 cell->ValueAddress()); \ 776 cell->ValueAddress()); \
880 } \ 777 } \
881 } \ 778 } \
882 if (how == kFromCode) { \ 779 if (how == kFromCode) { \
883 Address location_of_branch_data = \ 780 Address location_of_branch_data = \
884 reinterpret_cast<Address>(current); \ 781 reinterpret_cast<Address>(current); \
885 Assembler::deserialization_set_special_target_at( \ 782 Assembler::deserialization_set_special_target_at( \
(...skipping 11 matching lines...) Expand all
897 isolate->heap()->RecordWrite( \ 794 isolate->heap()->RecordWrite( \
898 current_object_address, \ 795 current_object_address, \
899 static_cast<int>(current_address - current_object_address)); \ 796 static_cast<int>(current_address - current_object_address)); \
900 } \ 797 } \
901 if (!current_was_incremented) { \ 798 if (!current_was_incremented) { \
902 current++; \ 799 current++; \
903 } \ 800 } \
904 break; \ 801 break; \
905 } \ 802 } \
906 803
907 // This generates a case and a body for each space. The large object spaces are
908 // very rare in snapshots so they are grouped in one body.
909 #define ONE_PER_SPACE(where, how, within) \
910 CASE_STATEMENT(where, how, within, NEW_SPACE) \
911 CASE_BODY(where, how, within, NEW_SPACE, kUnknownOffsetFromStart) \
912 CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \
913 CASE_BODY(where, how, within, OLD_DATA_SPACE, kUnknownOffsetFromStart) \
914 CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \
915 CASE_BODY(where, how, within, OLD_POINTER_SPACE, kUnknownOffsetFromStart) \
916 CASE_STATEMENT(where, how, within, CODE_SPACE) \
917 CASE_BODY(where, how, within, CODE_SPACE, kUnknownOffsetFromStart) \
918 CASE_STATEMENT(where, how, within, CELL_SPACE) \
919 CASE_BODY(where, how, within, CELL_SPACE, kUnknownOffsetFromStart) \
920 CASE_STATEMENT(where, how, within, MAP_SPACE) \
921 CASE_BODY(where, how, within, MAP_SPACE, kUnknownOffsetFromStart) \
922 CASE_STATEMENT(where, how, within, kLargeData) \
923 CASE_STATEMENT(where, how, within, kLargeCode) \
924 CASE_STATEMENT(where, how, within, kLargeFixedArray) \
925 CASE_BODY(where, how, within, kAnyOldSpace, kUnknownOffsetFromStart)
926
927 // This generates a case and a body for the new space (which has to do extra 804 // This generates a case and a body for the new space (which has to do extra
928 // write barrier handling) and handles the other spaces with 8 fall-through 805 // write barrier handling) and handles the other spaces with 8 fall-through
929 // cases and one body. 806 // cases and one body.
930 #define ALL_SPACES(where, how, within) \ 807 #define ALL_SPACES(where, how, within) \
931 CASE_STATEMENT(where, how, within, NEW_SPACE) \ 808 CASE_STATEMENT(where, how, within, NEW_SPACE) \
932 CASE_BODY(where, how, within, NEW_SPACE, kUnknownOffsetFromStart) \ 809 CASE_BODY(where, how, within, NEW_SPACE) \
933 CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \ 810 CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \
934 CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \ 811 CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \
935 CASE_STATEMENT(where, how, within, CODE_SPACE) \ 812 CASE_STATEMENT(where, how, within, CODE_SPACE) \
936 CASE_STATEMENT(where, how, within, CELL_SPACE) \ 813 CASE_STATEMENT(where, how, within, CELL_SPACE) \
937 CASE_STATEMENT(where, how, within, MAP_SPACE) \ 814 CASE_STATEMENT(where, how, within, MAP_SPACE) \
938 CASE_STATEMENT(where, how, within, kLargeData) \ 815 CASE_BODY(where, how, within, kAnyOldSpace)
939 CASE_STATEMENT(where, how, within, kLargeCode) \
940 CASE_STATEMENT(where, how, within, kLargeFixedArray) \
941 CASE_BODY(where, how, within, kAnyOldSpace, kUnknownOffsetFromStart)
942
943 #define ONE_PER_CODE_SPACE(where, how, within) \
944 CASE_STATEMENT(where, how, within, CODE_SPACE) \
945 CASE_BODY(where, how, within, CODE_SPACE, kUnknownOffsetFromStart) \
946 CASE_STATEMENT(where, how, within, kLargeCode) \
947 CASE_BODY(where, how, within, kLargeCode, kUnknownOffsetFromStart)
948 816
949 #define FOUR_CASES(byte_code) \ 817 #define FOUR_CASES(byte_code) \
950 case byte_code: \ 818 case byte_code: \
951 case byte_code + 1: \ 819 case byte_code + 1: \
952 case byte_code + 2: \ 820 case byte_code + 2: \
953 case byte_code + 3: 821 case byte_code + 3:
954 822
955 #define SIXTEEN_CASES(byte_code) \ 823 #define SIXTEEN_CASES(byte_code) \
956 FOUR_CASES(byte_code) \ 824 FOUR_CASES(byte_code) \
957 FOUR_CASES(byte_code + 4) \ 825 FOUR_CASES(byte_code + 4) \
958 FOUR_CASES(byte_code + 8) \ 826 FOUR_CASES(byte_code + 8) \
959 FOUR_CASES(byte_code + 12) 827 FOUR_CASES(byte_code + 12)
960 828
829 #define COMMON_RAW_LENGTHS(f) \
830 f(1) \
831 f(2) \
832 f(3) \
833 f(4) \
834 f(5) \
835 f(6) \
836 f(7) \
837 f(8) \
838 f(9) \
839 f(10) \
840 f(11) \
841 f(12) \
842 f(13) \
843 f(14) \
844 f(15) \
845 f(16) \
846 f(17) \
847 f(18) \
848 f(19) \
849 f(20) \
850 f(21) \
851 f(22) \
852 f(23) \
853 f(24) \
854 f(25) \
855 f(26) \
856 f(27) \
857 f(28) \
858 f(29) \
859 f(30) \
860 f(31)
861
961 // We generate 15 cases and bodies that process special tags that combine 862 // We generate 15 cases and bodies that process special tags that combine
962 // the raw data tag and the length into one byte. 863 // the raw data tag and the length into one byte.
963 #define RAW_CASE(index, size) \ 864 #define RAW_CASE(index) \
964 case kRawData + index: { \ 865 case kRawData + index: { \
965 byte* raw_data_out = reinterpret_cast<byte*>(current); \ 866 byte* raw_data_out = reinterpret_cast<byte*>(current); \
966 source_->CopyRaw(raw_data_out, size); \ 867 source_->CopyRaw(raw_data_out, index * kPointerSize); \
967 current = reinterpret_cast<Object**>(raw_data_out + size); \ 868 current = \
968 break; \ 869 reinterpret_cast<Object**>(raw_data_out + index * kPointerSize); \
870 break; \
969 } 871 }
970 COMMON_RAW_LENGTHS(RAW_CASE) 872 COMMON_RAW_LENGTHS(RAW_CASE)
971 #undef RAW_CASE 873 #undef RAW_CASE
972 874
973 // Deserialize a chunk of raw data that doesn't have one of the popular 875 // Deserialize a chunk of raw data that doesn't have one of the popular
974 // lengths. 876 // lengths.
975 case kRawData: { 877 case kRawData: {
976 int size = source_->GetInt(); 878 int size = source_->GetInt();
977 byte* raw_data_out = reinterpret_cast<byte*>(current); 879 byte* raw_data_out = reinterpret_cast<byte*>(current);
978 source_->CopyRaw(raw_data_out, size); 880 source_->CopyRaw(raw_data_out, size);
979 current = reinterpret_cast<Object**>(raw_data_out + size);
980 break; 881 break;
981 } 882 }
982 883
983 SIXTEEN_CASES(kRootArrayLowConstants) 884 SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance)
984 SIXTEEN_CASES(kRootArrayHighConstants) { 885 SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance + 16) {
985 int root_id = RootArrayConstantFromByteCode(data); 886 int root_id = RootArrayConstantFromByteCode(data);
986 Object* object = isolate->heap()->roots_array_start()[root_id]; 887 Object* object = isolate->heap()->roots_array_start()[root_id];
987 ASSERT(!isolate->heap()->InNewSpace(object)); 888 ASSERT(!isolate->heap()->InNewSpace(object));
988 *current++ = object; 889 *current++ = object;
989 break; 890 break;
990 } 891 }
991 892
893 SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance)
894 SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance + 16) {
895 int root_id = RootArrayConstantFromByteCode(data);
896 int skip = source_->GetInt();
897 current = reinterpret_cast<Object**>(
898 reinterpret_cast<intptr_t>(current) + skip);
899 Object* object = isolate->heap()->roots_array_start()[root_id];
900 ASSERT(!isolate->heap()->InNewSpace(object));
901 *current++ = object;
902 break;
903 }
904
992 case kRepeat: { 905 case kRepeat: {
993 int repeats = source_->GetInt(); 906 int repeats = source_->GetInt();
994 Object* object = current[-1]; 907 Object* object = current[-1];
995 ASSERT(!isolate->heap()->InNewSpace(object)); 908 ASSERT(!isolate->heap()->InNewSpace(object));
996 for (int i = 0; i < repeats; i++) current[i] = object; 909 for (int i = 0; i < repeats; i++) current[i] = object;
997 current += repeats; 910 current += repeats;
998 break; 911 break;
999 } 912 }
1000 913
1001 STATIC_ASSERT(kRootArrayNumberOfConstantEncodings == 914 STATIC_ASSERT(kRootArrayNumberOfConstantEncodings ==
1002 Heap::kOldSpaceRoots); 915 Heap::kOldSpaceRoots);
1003 STATIC_ASSERT(kMaxRepeats == 12); 916 STATIC_ASSERT(kMaxRepeats == 13);
1004 FOUR_CASES(kConstantRepeat) 917 case kConstantRepeat:
1005 FOUR_CASES(kConstantRepeat + 4) 918 FOUR_CASES(kConstantRepeat + 1)
1006 FOUR_CASES(kConstantRepeat + 8) { 919 FOUR_CASES(kConstantRepeat + 5)
920 FOUR_CASES(kConstantRepeat + 9) {
1007 int repeats = RepeatsForCode(data); 921 int repeats = RepeatsForCode(data);
1008 Object* object = current[-1]; 922 Object* object = current[-1];
1009 ASSERT(!isolate->heap()->InNewSpace(object)); 923 ASSERT(!isolate->heap()->InNewSpace(object));
1010 for (int i = 0; i < repeats; i++) current[i] = object; 924 for (int i = 0; i < repeats; i++) current[i] = object;
1011 current += repeats; 925 current += repeats;
1012 break; 926 break;
1013 } 927 }
1014 928
1015 // Deserialize a new object and write a pointer to it to the current 929 // Deserialize a new object and write a pointer to it to the current
1016 // object. 930 // object.
1017 ONE_PER_SPACE(kNewObject, kPlain, kStartOfObject) 931 ALL_SPACES(kNewObject, kPlain, kStartOfObject)
1018 // Support for direct instruction pointers in functions. It's an inner 932 // Support for direct instruction pointers in functions. It's an inner
1019 // pointer because it points at the entry point, not at the start of the 933 // pointer because it points at the entry point, not at the start of the
1020 // code object. 934 // code object.
1021 ONE_PER_CODE_SPACE(kNewObject, kPlain, kInnerPointer) 935 CASE_STATEMENT(kNewObject, kPlain, kInnerPointer, CODE_SPACE)
936 CASE_BODY(kNewObject, kPlain, kInnerPointer, CODE_SPACE)
1022 // Deserialize a new code object and write a pointer to its first 937 // Deserialize a new code object and write a pointer to its first
1023 // instruction to the current code object. 938 // instruction to the current code object.
1024 ONE_PER_SPACE(kNewObject, kFromCode, kInnerPointer) 939 ALL_SPACES(kNewObject, kFromCode, kInnerPointer)
1025 // Find a recently deserialized object using its offset from the current 940 // Find a recently deserialized object using its offset from the current
1026 // allocation point and write a pointer to it to the current object. 941 // allocation point and write a pointer to it to the current object.
1027 ALL_SPACES(kBackref, kPlain, kStartOfObject) 942 ALL_SPACES(kBackref, kPlain, kStartOfObject)
943 ALL_SPACES(kBackrefWithSkip, kPlain, kStartOfObject)
1028 #if V8_TARGET_ARCH_MIPS 944 #if V8_TARGET_ARCH_MIPS
1029 // Deserialize a new object from pointer found in code and write 945 // Deserialize a new object from pointer found in code and write
1030 // a pointer to it to the current object. Required only for MIPS, and 946 // a pointer to it to the current object. Required only for MIPS, and
1031 // omitted on the other architectures because it is fully unrolled and 947 // omitted on the other architectures because it is fully unrolled and
1032 // would cause bloat. 948 // would cause bloat.
1033 ONE_PER_SPACE(kNewObject, kFromCode, kStartOfObject) 949 ALL_SPACES(kNewObject, kFromCode, kStartOfObject)
1034 // Find a recently deserialized code object using its offset from the 950 // Find a recently deserialized code object using its offset from the
1035 // current allocation point and write a pointer to it to the current 951 // current allocation point and write a pointer to it to the current
1036 // object. Required only for MIPS. 952 // object. Required only for MIPS.
1037 ALL_SPACES(kBackref, kFromCode, kStartOfObject) 953 ALL_SPACES(kBackref, kFromCode, kStartOfObject)
1038 // Find an already deserialized code object using its offset from 954 ALL_SPACES(kBackrefWithSkip, kFromCode, kStartOfObject)
1039 // the start and write a pointer to it to the current object.
1040 // Required only for MIPS.
1041 ALL_SPACES(kFromStart, kFromCode, kStartOfObject)
1042 #endif 955 #endif
1043 // Find a recently deserialized code object using its offset from the 956 // Find a recently deserialized code object using its offset from the
1044 // current allocation point and write a pointer to its first instruction 957 // current allocation point and write a pointer to its first instruction
1045 // to the current code object or the instruction pointer in a function 958 // to the current code object or the instruction pointer in a function
1046 // object. 959 // object.
1047 ALL_SPACES(kBackref, kFromCode, kInnerPointer) 960 ALL_SPACES(kBackref, kFromCode, kInnerPointer)
961 ALL_SPACES(kBackrefWithSkip, kFromCode, kInnerPointer)
1048 ALL_SPACES(kBackref, kPlain, kInnerPointer) 962 ALL_SPACES(kBackref, kPlain, kInnerPointer)
1049 // Find an already deserialized object using its offset from the start 963 ALL_SPACES(kBackrefWithSkip, kPlain, kInnerPointer)
1050 // and write a pointer to it to the current object.
1051 ALL_SPACES(kFromStart, kPlain, kStartOfObject)
1052 ALL_SPACES(kFromStart, kPlain, kInnerPointer)
1053 // Find an already deserialized code object using its offset from the
1054 // start and write a pointer to its first instruction to the current code
1055 // object.
1056 ALL_SPACES(kFromStart, kFromCode, kInnerPointer)
1057 // Find an object in the roots array and write a pointer to it to the 964 // Find an object in the roots array and write a pointer to it to the
1058 // current object. 965 // current object.
1059 CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0) 966 CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0)
1060 CASE_BODY(kRootArray, kPlain, kStartOfObject, 0, kUnknownOffsetFromStart) 967 CASE_BODY(kRootArray, kPlain, kStartOfObject, 0)
1061 // Find an object in the partial snapshots cache and write a pointer to it 968 // Find an object in the partial snapshots cache and write a pointer to it
1062 // to the current object. 969 // to the current object.
1063 CASE_STATEMENT(kPartialSnapshotCache, kPlain, kStartOfObject, 0) 970 CASE_STATEMENT(kPartialSnapshotCache, kPlain, kStartOfObject, 0)
1064 CASE_BODY(kPartialSnapshotCache, 971 CASE_BODY(kPartialSnapshotCache,
1065 kPlain, 972 kPlain,
1066 kStartOfObject, 973 kStartOfObject,
1067 0, 974 0)
1068 kUnknownOffsetFromStart)
1069 // Find an code entry in the partial snapshots cache and 975 // Find an code entry in the partial snapshots cache and
1070 // write a pointer to it to the current object. 976 // write a pointer to it to the current object.
1071 CASE_STATEMENT(kPartialSnapshotCache, kPlain, kInnerPointer, 0) 977 CASE_STATEMENT(kPartialSnapshotCache, kPlain, kInnerPointer, 0)
1072 CASE_BODY(kPartialSnapshotCache, 978 CASE_BODY(kPartialSnapshotCache,
1073 kPlain, 979 kPlain,
1074 kInnerPointer, 980 kInnerPointer,
1075 0, 981 0)
1076 kUnknownOffsetFromStart)
1077 // Find an external reference and write a pointer to it to the current 982 // Find an external reference and write a pointer to it to the current
1078 // object. 983 // object.
1079 CASE_STATEMENT(kExternalReference, kPlain, kStartOfObject, 0) 984 CASE_STATEMENT(kExternalReference, kPlain, kStartOfObject, 0)
1080 CASE_BODY(kExternalReference, 985 CASE_BODY(kExternalReference,
1081 kPlain, 986 kPlain,
1082 kStartOfObject, 987 kStartOfObject,
1083 0, 988 0)
1084 kUnknownOffsetFromStart)
1085 // Find an external reference and write a pointer to it in the current 989 // Find an external reference and write a pointer to it in the current
1086 // code object. 990 // code object.
1087 CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0) 991 CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0)
1088 CASE_BODY(kExternalReference, 992 CASE_BODY(kExternalReference,
1089 kFromCode, 993 kFromCode,
1090 kStartOfObject, 994 kStartOfObject,
1091 0, 995 0)
1092 kUnknownOffsetFromStart)
1093 996
1094 #undef CASE_STATEMENT 997 #undef CASE_STATEMENT
1095 #undef CASE_BODY 998 #undef CASE_BODY
1096 #undef ONE_PER_SPACE
1097 #undef ALL_SPACES 999 #undef ALL_SPACES
1098 #undef ASSIGN_DEST_SPACE
1099 1000
1100 case kNewPage: { 1001 case kSkip: {
1101 int space = source_->Get(); 1002 int size = source_->GetInt();
1102 pages_[space].Add(last_object_address_); 1003 current = reinterpret_cast<Object**>(
1103 if (space == CODE_SPACE) { 1004 reinterpret_cast<intptr_t>(current) + size);
1104 CPU::FlushICache(last_object_address_, Page::kPageSize);
1105 }
1106 break; 1005 break;
1107 } 1006 }
1108 1007
1109 case kSkip: {
1110 current++;
1111 break;
1112 }
1113
1114 case kNativesStringResource: { 1008 case kNativesStringResource: {
1115 int index = source_->Get(); 1009 int index = source_->Get();
1116 Vector<const char> source_vector = Natives::GetRawScriptSource(index); 1010 Vector<const char> source_vector = Natives::GetRawScriptSource(index);
1117 NativesExternalStringResource* resource = 1011 NativesExternalStringResource* resource =
1118 new NativesExternalStringResource(isolate->bootstrapper(), 1012 new NativesExternalStringResource(isolate->bootstrapper(),
1119 source_vector.start(), 1013 source_vector.start(),
1120 source_vector.length()); 1014 source_vector.length());
1121 *current++ = reinterpret_cast<Object*>(resource); 1015 *current++ = reinterpret_cast<Object*>(resource);
1122 break; 1016 break;
1123 } 1017 }
1124 1018
1125 case kSynchronize: { 1019 case kSynchronize: {
1126 // If we get here then that indicates that you have a mismatch between 1020 // If we get here then that indicates that you have a mismatch between
1127 // the number of GC roots when serializing and deserializing. 1021 // the number of GC roots when serializing and deserializing.
1128 UNREACHABLE(); 1022 UNREACHABLE();
1129 } 1023 }
1130 1024
1131 default: 1025 default:
1132 UNREACHABLE(); 1026 UNREACHABLE();
1133 } 1027 }
1134 } 1028 }
1135 ASSERT_EQ(current, limit); 1029 ASSERT_EQ(limit, current);
1136 } 1030 }
1137 1031
1138 1032
1139 void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) { 1033 void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) {
1140 const int max_shift = ((kPointerSize * kBitsPerByte) / 7) * 7; 1034 ASSERT(integer < 1 << 22);
1141 for (int shift = max_shift; shift > 0; shift -= 7) { 1035 integer <<= 2;
1142 if (integer >= static_cast<uintptr_t>(1u) << shift) { 1036 int bytes = 1;
1143 Put((static_cast<int>((integer >> shift)) & 0x7f) | 0x80, "IntPart"); 1037 if (integer > 0xff) bytes = 2;
1144 } 1038 if (integer > 0xffff) bytes = 3;
1145 } 1039 integer |= bytes;
1146 PutSection(static_cast<int>(integer & 0x7f), "IntLastPart"); 1040 Put(static_cast<int>(integer & 0xff), "IntPart1");
1041 if (bytes > 1) Put(static_cast<int>((integer >> 8) & 0xff), "IntPart2");
1042 if (bytes > 2) Put(static_cast<int>((integer >> 16) & 0xff), "IntPart3");
1147 } 1043 }
1148 1044
1149 1045
1150 Serializer::Serializer(SnapshotByteSink* sink) 1046 Serializer::Serializer(SnapshotByteSink* sink)
1151 : sink_(sink), 1047 : sink_(sink),
1152 current_root_index_(0), 1048 current_root_index_(0),
1153 external_reference_encoder_(new ExternalReferenceEncoder), 1049 external_reference_encoder_(new ExternalReferenceEncoder),
1154 large_object_total_(0),
1155 root_index_wave_front_(0) { 1050 root_index_wave_front_(0) {
1156 isolate_ = Isolate::Current(); 1051 isolate_ = Isolate::Current();
1157 // The serializer is meant to be used only to generate initial heap images 1052 // The serializer is meant to be used only to generate initial heap images
1158 // from a context in which there is only one isolate. 1053 // from a context in which there is only one isolate.
1159 ASSERT(isolate_->IsDefaultIsolate()); 1054 ASSERT(isolate_->IsDefaultIsolate());
1160 for (int i = 0; i <= LAST_SPACE; i++) { 1055 for (int i = 0; i <= LAST_SPACE; i++) {
1161 fullness_[i] = 0; 1056 fullness_[i] = 0;
1162 } 1057 }
1163 } 1058 }
1164 1059
(...skipping 12 matching lines...) Expand all
1177 CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles()); 1072 CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles());
1178 // We don't support serializing installed extensions. 1073 // We don't support serializing installed extensions.
1179 CHECK(!isolate->has_installed_extensions()); 1074 CHECK(!isolate->has_installed_extensions());
1180 1075
1181 HEAP->IterateStrongRoots(this, VISIT_ONLY_STRONG); 1076 HEAP->IterateStrongRoots(this, VISIT_ONLY_STRONG);
1182 } 1077 }
1183 1078
1184 1079
1185 void PartialSerializer::Serialize(Object** object) { 1080 void PartialSerializer::Serialize(Object** object) {
1186 this->VisitPointer(object); 1081 this->VisitPointer(object);
1082 Pad();
1187 } 1083 }
1188 1084
1189 1085
1190 void Serializer::VisitPointers(Object** start, Object** end) { 1086 void Serializer::VisitPointers(Object** start, Object** end) {
1191 Isolate* isolate = Isolate::Current(); 1087 Isolate* isolate = Isolate::Current();
1192 1088
1193 for (Object** current = start; current < end; current++) { 1089 for (Object** current = start; current < end; current++) {
1194 if (start == isolate->heap()->roots_array_start()) { 1090 if (start == isolate->heap()->roots_array_start()) {
1195 root_index_wave_front_ = 1091 root_index_wave_front_ =
1196 Max(root_index_wave_front_, static_cast<intptr_t>(current - start)); 1092 Max(root_index_wave_front_, static_cast<intptr_t>(current - start));
1197 } 1093 }
1198 if (reinterpret_cast<Address>(current) == 1094 if (reinterpret_cast<Address>(current) ==
1199 isolate->heap()->store_buffer()->TopAddress()) { 1095 isolate->heap()->store_buffer()->TopAddress()) {
1200 sink_->Put(kSkip, "Skip"); 1096 sink_->Put(kSkip, "Skip");
1097 sink_->PutInt(kPointerSize, "SkipOneWord");
1201 } else if ((*current)->IsSmi()) { 1098 } else if ((*current)->IsSmi()) {
1202 sink_->Put(kRawData, "RawData"); 1099 sink_->Put(kRawData + 1, "Smi");
1203 sink_->PutInt(kPointerSize, "length");
1204 for (int i = 0; i < kPointerSize; i++) { 1100 for (int i = 0; i < kPointerSize; i++) {
1205 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); 1101 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte");
1206 } 1102 }
1207 } else { 1103 } else {
1208 SerializeObject(*current, kPlain, kStartOfObject); 1104 SerializeObject(*current, kPlain, kStartOfObject, 0);
1209 } 1105 }
1210 } 1106 }
1211 } 1107 }
1212 1108
1213 1109
1214 // This ensures that the partial snapshot cache keeps things alive during GC and 1110 // This ensures that the partial snapshot cache keeps things alive during GC and
1215 // tracks their movement. When it is called during serialization of the startup 1111 // tracks their movement. When it is called during serialization of the startup
1216 // snapshot nothing happens. When the partial (context) snapshot is created, 1112 // snapshot nothing happens. When the partial (context) snapshot is created,
1217 // this array is populated with the pointers that the partial snapshot will 1113 // this array is populated with the pointers that the partial snapshot will
1218 // need. As that happens we emit serialized objects to the startup snapshot 1114 // need. As that happens we emit serialized objects to the startup snapshot
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 1181
1286 1182
1287 // Encode the location of an already deserialized object in order to write its 1183 // Encode the location of an already deserialized object in order to write its
1288 // location into a later object. We can encode the location as an offset from 1184 // location into a later object. We can encode the location as an offset from
1289 // the start of the deserialized objects or as an offset backwards from the 1185 // the start of the deserialized objects or as an offset backwards from the
1290 // current allocation pointer. 1186 // current allocation pointer.
1291 void Serializer::SerializeReferenceToPreviousObject( 1187 void Serializer::SerializeReferenceToPreviousObject(
1292 int space, 1188 int space,
1293 int address, 1189 int address,
1294 HowToCode how_to_code, 1190 HowToCode how_to_code,
1295 WhereToPoint where_to_point) { 1191 WhereToPoint where_to_point,
1192 int skip) {
1296 int offset = CurrentAllocationAddress(space) - address; 1193 int offset = CurrentAllocationAddress(space) - address;
1297 bool from_start = true; 1194 // Shift out the bits that are always 0.
1298 if (SpaceIsPaged(space)) { 1195 offset >>= kObjectAlignmentBits;
1299 // For paged space it is simple to encode back from current allocation if 1196 if (skip == 0) {
1300 // the object is on the same page as the current allocation pointer. 1197 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer");
1301 if ((CurrentAllocationAddress(space) >> kPageSizeBits) == 1198 } else {
1302 (address >> kPageSizeBits)) { 1199 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space,
1303 from_start = false; 1200 "BackRefSerWithSkip");
1304 address = offset; 1201 sink_->PutInt(skip, "BackRefSkipDistance");
1305 }
1306 } else if (space == NEW_SPACE) {
1307 // For new space it is always simple to encode back from current allocation.
1308 if (offset < address) {
1309 from_start = false;
1310 address = offset;
1311 }
1312 } 1202 }
1313 // If we are actually dealing with real offsets (and not a numbering of 1203 sink_->PutInt(offset, "offset");
1314 // all objects) then we should shift out the bits that are always 0.
1315 if (!SpaceIsLarge(space)) address >>= kObjectAlignmentBits;
1316 if (from_start) {
1317 sink_->Put(kFromStart + how_to_code + where_to_point + space, "RefSer");
1318 sink_->PutInt(address, "address");
1319 } else {
1320 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer");
1321 sink_->PutInt(address, "address");
1322 }
1323 } 1204 }
1324 1205
1325 1206
1326 void StartupSerializer::SerializeObject( 1207 void StartupSerializer::SerializeObject(
1327 Object* o, 1208 Object* o,
1328 HowToCode how_to_code, 1209 HowToCode how_to_code,
1329 WhereToPoint where_to_point) { 1210 WhereToPoint where_to_point,
1211 int skip) {
1330 CHECK(o->IsHeapObject()); 1212 CHECK(o->IsHeapObject());
1331 HeapObject* heap_object = HeapObject::cast(o); 1213 HeapObject* heap_object = HeapObject::cast(o);
1332 1214
1333 int root_index; 1215 int root_index;
1334 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { 1216 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
1335 PutRoot(root_index, heap_object, how_to_code, where_to_point); 1217 PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
1336 return; 1218 return;
1337 } 1219 }
1338 1220
1339 if (address_mapper_.IsMapped(heap_object)) { 1221 if (address_mapper_.IsMapped(heap_object)) {
1340 int space = SpaceOfAlreadySerializedObject(heap_object); 1222 int space = SpaceOfObject(heap_object);
1341 int address = address_mapper_.MappedTo(heap_object); 1223 int address = address_mapper_.MappedTo(heap_object);
1342 SerializeReferenceToPreviousObject(space, 1224 SerializeReferenceToPreviousObject(space,
1343 address, 1225 address,
1344 how_to_code, 1226 how_to_code,
1345 where_to_point); 1227 where_to_point,
1228 skip);
1346 } else { 1229 } else {
1230 if (skip != 0) {
1231 sink_->Put(kSkip, "FlushPendingSkip");
1232 sink_->PutInt(skip, "SkipDistance");
1233 }
1234
1347 // Object has not yet been serialized. Serialize it here. 1235 // Object has not yet been serialized. Serialize it here.
1348 ObjectSerializer object_serializer(this, 1236 ObjectSerializer object_serializer(this,
1349 heap_object, 1237 heap_object,
1350 sink_, 1238 sink_,
1351 how_to_code, 1239 how_to_code,
1352 where_to_point); 1240 where_to_point);
1353 object_serializer.Serialize(); 1241 object_serializer.Serialize();
1354 } 1242 }
1355 } 1243 }
1356 1244
1357 1245
1358 void StartupSerializer::SerializeWeakReferences() { 1246 void StartupSerializer::SerializeWeakReferences() {
1359 // This phase comes right after the partial serialization (of the snapshot). 1247 // This phase comes right after the partial serialization (of the snapshot).
1360 // After we have done the partial serialization the partial snapshot cache 1248 // After we have done the partial serialization the partial snapshot cache
1361 // will contain some references needed to decode the partial snapshot. We 1249 // will contain some references needed to decode the partial snapshot. We
1362 // add one entry with 'undefined' which is the sentinel that the deserializer 1250 // add one entry with 'undefined' which is the sentinel that the deserializer
1363 // uses to know it is done deserializing the array. 1251 // uses to know it is done deserializing the array.
1364 Isolate* isolate = Isolate::Current(); 1252 Isolate* isolate = Isolate::Current();
1365 Object* undefined = isolate->heap()->undefined_value(); 1253 Object* undefined = isolate->heap()->undefined_value();
1366 VisitPointer(&undefined); 1254 VisitPointer(&undefined);
1367 HEAP->IterateWeakRoots(this, VISIT_ALL); 1255 HEAP->IterateWeakRoots(this, VISIT_ALL);
1256 Pad();
1368 } 1257 }
1369 1258
1370 1259
1371 void Serializer::PutRoot(int root_index, 1260 void Serializer::PutRoot(int root_index,
1372 HeapObject* object, 1261 HeapObject* object,
1373 SerializerDeserializer::HowToCode how_to_code, 1262 SerializerDeserializer::HowToCode how_to_code,
1374 SerializerDeserializer::WhereToPoint where_to_point) { 1263 SerializerDeserializer::WhereToPoint where_to_point,
1264 int skip) {
1375 if (how_to_code == kPlain && 1265 if (how_to_code == kPlain &&
1376 where_to_point == kStartOfObject && 1266 where_to_point == kStartOfObject &&
1377 root_index < kRootArrayNumberOfConstantEncodings && 1267 root_index < kRootArrayNumberOfConstantEncodings &&
1378 !HEAP->InNewSpace(object)) { 1268 !HEAP->InNewSpace(object)) {
1379 if (root_index < kRootArrayNumberOfLowConstantEncodings) { 1269 if (skip == 0) {
1380 sink_->Put(kRootArrayLowConstants + root_index, "RootLoConstant"); 1270 sink_->Put(kRootArrayConstants + kNoSkipDistance + root_index,
1271 "RootConstant");
1381 } else { 1272 } else {
1382 sink_->Put(kRootArrayHighConstants + root_index - 1273 sink_->Put(kRootArrayConstants + kHasSkipDistance + root_index,
1383 kRootArrayNumberOfLowConstantEncodings, 1274 "RootConstant");
1384 "RootHiConstant"); 1275 sink_->PutInt(skip, "SkipInPutRoot");
1385 } 1276 }
1386 } else { 1277 } else {
1278 if (skip != 0) {
1279 sink_->Put(kSkip, "SkipFromPutRoot");
1280 sink_->PutInt(skip, "SkipFromPutRootDistance");
1281 }
1387 sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization"); 1282 sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization");
1388 sink_->PutInt(root_index, "root_index"); 1283 sink_->PutInt(root_index, "root_index");
1389 } 1284 }
1390 } 1285 }
1391 1286
1392 1287
1393 void PartialSerializer::SerializeObject( 1288 void PartialSerializer::SerializeObject(
1394 Object* o, 1289 Object* o,
1395 HowToCode how_to_code, 1290 HowToCode how_to_code,
1396 WhereToPoint where_to_point) { 1291 WhereToPoint where_to_point,
1292 int skip) {
1397 CHECK(o->IsHeapObject()); 1293 CHECK(o->IsHeapObject());
1398 HeapObject* heap_object = HeapObject::cast(o); 1294 HeapObject* heap_object = HeapObject::cast(o);
1399 1295
1400 if (heap_object->IsMap()) { 1296 if (heap_object->IsMap()) {
1401 // The code-caches link to context-specific code objects, which 1297 // The code-caches link to context-specific code objects, which
1402 // the startup and context serializes cannot currently handle. 1298 // the startup and context serializes cannot currently handle.
1403 ASSERT(Map::cast(heap_object)->code_cache() == 1299 ASSERT(Map::cast(heap_object)->code_cache() ==
1404 heap_object->GetHeap()->raw_unchecked_empty_fixed_array()); 1300 heap_object->GetHeap()->raw_unchecked_empty_fixed_array());
1405 } 1301 }
1406 1302
1407 int root_index; 1303 int root_index;
1408 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { 1304 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
1409 PutRoot(root_index, heap_object, how_to_code, where_to_point); 1305 PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
1410 return; 1306 return;
1411 } 1307 }
1412 1308
1413 if (ShouldBeInThePartialSnapshotCache(heap_object)) { 1309 if (ShouldBeInThePartialSnapshotCache(heap_object)) {
1310 if (skip != 0) {
1311 sink_->Put(kSkip, "SkipFromSerializeObject");
1312 sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
1313 }
1314
1414 int cache_index = PartialSnapshotCacheIndex(heap_object); 1315 int cache_index = PartialSnapshotCacheIndex(heap_object);
1415 sink_->Put(kPartialSnapshotCache + how_to_code + where_to_point, 1316 sink_->Put(kPartialSnapshotCache + how_to_code + where_to_point,
1416 "PartialSnapshotCache"); 1317 "PartialSnapshotCache");
1417 sink_->PutInt(cache_index, "partial_snapshot_cache_index"); 1318 sink_->PutInt(cache_index, "partial_snapshot_cache_index");
1418 return; 1319 return;
1419 } 1320 }
1420 1321
1421 // Pointers from the partial snapshot to the objects in the startup snapshot 1322 // Pointers from the partial snapshot to the objects in the startup snapshot
1422 // should go through the root array or through the partial snapshot cache. 1323 // should go through the root array or through the partial snapshot cache.
1423 // If this is not the case you may have to add something to the root array. 1324 // If this is not the case you may have to add something to the root array.
1424 ASSERT(!startup_serializer_->address_mapper()->IsMapped(heap_object)); 1325 ASSERT(!startup_serializer_->address_mapper()->IsMapped(heap_object));
1425 // All the symbols that the partial snapshot needs should be either in the 1326 // All the symbols that the partial snapshot needs should be either in the
1426 // root table or in the partial snapshot cache. 1327 // root table or in the partial snapshot cache.
1427 ASSERT(!heap_object->IsSymbol()); 1328 ASSERT(!heap_object->IsSymbol());
1428 1329
1429 if (address_mapper_.IsMapped(heap_object)) { 1330 if (address_mapper_.IsMapped(heap_object)) {
1430 int space = SpaceOfAlreadySerializedObject(heap_object); 1331 int space = SpaceOfObject(heap_object);
1431 int address = address_mapper_.MappedTo(heap_object); 1332 int address = address_mapper_.MappedTo(heap_object);
1432 SerializeReferenceToPreviousObject(space, 1333 SerializeReferenceToPreviousObject(space,
1433 address, 1334 address,
1434 how_to_code, 1335 how_to_code,
1435 where_to_point); 1336 where_to_point,
1337 skip);
1436 } else { 1338 } else {
1339 if (skip != 0) {
1340 sink_->Put(kSkip, "SkipFromSerializeObject");
1341 sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
1342 }
1437 // Object has not yet been serialized. Serialize it here. 1343 // Object has not yet been serialized. Serialize it here.
1438 ObjectSerializer serializer(this, 1344 ObjectSerializer serializer(this,
1439 heap_object, 1345 heap_object,
1440 sink_, 1346 sink_,
1441 how_to_code, 1347 how_to_code,
1442 where_to_point); 1348 where_to_point);
1443 serializer.Serialize(); 1349 serializer.Serialize();
1444 } 1350 }
1445 } 1351 }
1446 1352
1447 1353
1448 void Serializer::ObjectSerializer::Serialize() { 1354 void Serializer::ObjectSerializer::Serialize() {
1449 int space = Serializer::SpaceOfObject(object_); 1355 int space = Serializer::SpaceOfObject(object_);
1450 int size = object_->Size(); 1356 int size = object_->Size();
1451 1357
1452 sink_->Put(kNewObject + reference_representation_ + space, 1358 sink_->Put(kNewObject + reference_representation_ + space,
1453 "ObjectSerialization"); 1359 "ObjectSerialization");
1454 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words"); 1360 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");
1455 1361
1456 LOG(i::Isolate::Current(), 1362 LOG(i::Isolate::Current(),
1457 SnapshotPositionEvent(object_->address(), sink_->Position())); 1363 SnapshotPositionEvent(object_->address(), sink_->Position()));
1458 1364
1459 // Mark this object as already serialized. 1365 // Mark this object as already serialized.
1460 bool start_new_page; 1366 int offset = serializer_->Allocate(space, size);
1461 int offset = serializer_->Allocate(space, size, &start_new_page);
1462 serializer_->address_mapper()->AddMapping(object_, offset); 1367 serializer_->address_mapper()->AddMapping(object_, offset);
1463 if (start_new_page) {
1464 sink_->Put(kNewPage, "NewPage");
1465 sink_->PutSection(space, "NewPageSpace");
1466 }
1467 1368
1468 // Serialize the map (first word of the object). 1369 // Serialize the map (first word of the object).
1469 serializer_->SerializeObject(object_->map(), kPlain, kStartOfObject); 1370 serializer_->SerializeObject(object_->map(), kPlain, kStartOfObject, 0);
1470 1371
1471 // Serialize the rest of the object. 1372 // Serialize the rest of the object.
1472 CHECK_EQ(0, bytes_processed_so_far_); 1373 CHECK_EQ(0, bytes_processed_so_far_);
1473 bytes_processed_so_far_ = kPointerSize; 1374 bytes_processed_so_far_ = kPointerSize;
1474 object_->IterateBody(object_->map()->instance_type(), size, this); 1375 object_->IterateBody(object_->map()->instance_type(), size, this);
1475 OutputRawData(object_->address() + size); 1376 OutputRawData(object_->address() + size);
1476 } 1377 }
1477 1378
1478 1379
1479 void Serializer::ObjectSerializer::VisitPointers(Object** start, 1380 void Serializer::ObjectSerializer::VisitPointers(Object** start,
(...skipping 20 matching lines...) Expand all
1500 } 1401 }
1501 current += repeat_count; 1402 current += repeat_count;
1502 bytes_processed_so_far_ += repeat_count * kPointerSize; 1403 bytes_processed_so_far_ += repeat_count * kPointerSize;
1503 if (repeat_count > kMaxRepeats) { 1404 if (repeat_count > kMaxRepeats) {
1504 sink_->Put(kRepeat, "SerializeRepeats"); 1405 sink_->Put(kRepeat, "SerializeRepeats");
1505 sink_->PutInt(repeat_count, "SerializeRepeats"); 1406 sink_->PutInt(repeat_count, "SerializeRepeats");
1506 } else { 1407 } else {
1507 sink_->Put(CodeForRepeats(repeat_count), "SerializeRepeats"); 1408 sink_->Put(CodeForRepeats(repeat_count), "SerializeRepeats");
1508 } 1409 }
1509 } else { 1410 } else {
1510 serializer_->SerializeObject(current_contents, kPlain, kStartOfObject); 1411 serializer_->SerializeObject(
1412 current_contents, kPlain, kStartOfObject, 0);
1511 bytes_processed_so_far_ += kPointerSize; 1413 bytes_processed_so_far_ += kPointerSize;
1512 current++; 1414 current++;
1513 } 1415 }
1514 } 1416 }
1515 } 1417 }
1516 } 1418 }
1517 1419
1518 1420
1519 void Serializer::ObjectSerializer::VisitEmbeddedPointer(RelocInfo* rinfo) { 1421 void Serializer::ObjectSerializer::VisitEmbeddedPointer(RelocInfo* rinfo) {
1520 Object** current = rinfo->target_object_address(); 1422 Object** current = rinfo->target_object_address();
1521 1423
1522 OutputRawData(rinfo->target_address_address()); 1424 int skip = OutputRawData(rinfo->target_address_address(),
1425 kCanReturnSkipInsteadOfSkipping);
1523 HowToCode representation = rinfo->IsCodedSpecially() ? kFromCode : kPlain; 1426 HowToCode representation = rinfo->IsCodedSpecially() ? kFromCode : kPlain;
1524 serializer_->SerializeObject(*current, representation, kStartOfObject); 1427 serializer_->SerializeObject(*current, representation, kStartOfObject, skip);
1525 bytes_processed_so_far_ += rinfo->target_address_size(); 1428 bytes_processed_so_far_ += rinfo->target_address_size();
1526 } 1429 }
1527 1430
1528 1431
1529 void Serializer::ObjectSerializer::VisitExternalReferences(Address* start, 1432 void Serializer::ObjectSerializer::VisitExternalReferences(Address* start,
1530 Address* end) { 1433 Address* end) {
1531 Address references_start = reinterpret_cast<Address>(start); 1434 Address references_start = reinterpret_cast<Address>(start);
1532 OutputRawData(references_start); 1435 int skip = OutputRawData(references_start, kCanReturnSkipInsteadOfSkipping);
1533 1436
1534 for (Address* current = start; current < end; current++) { 1437 for (Address* current = start; current < end; current++) {
1535 sink_->Put(kExternalReference + kPlain + kStartOfObject, "ExternalRef"); 1438 sink_->Put(kExternalReference + kPlain + kStartOfObject, "ExternalRef");
1439 sink_->PutInt(skip, "SkipB4ExternalRef");
1440 skip = 0;
1536 int reference_id = serializer_->EncodeExternalReference(*current); 1441 int reference_id = serializer_->EncodeExternalReference(*current);
1537 sink_->PutInt(reference_id, "reference id"); 1442 sink_->PutInt(reference_id, "reference id");
1538 } 1443 }
1539 bytes_processed_so_far_ += static_cast<int>((end - start) * kPointerSize); 1444 bytes_processed_so_far_ += static_cast<int>((end - start) * kPointerSize);
1540 } 1445 }
1541 1446
1542 1447
1543 void Serializer::ObjectSerializer::VisitExternalReference(RelocInfo* rinfo) { 1448 void Serializer::ObjectSerializer::VisitExternalReference(RelocInfo* rinfo) {
1544 Address references_start = rinfo->target_address_address(); 1449 Address references_start = rinfo->target_address_address();
1545 OutputRawData(references_start); 1450 int skip = OutputRawData(references_start, kCanReturnSkipInsteadOfSkipping);
1546 1451
1547 Address* current = rinfo->target_reference_address(); 1452 Address* current = rinfo->target_reference_address();
1548 int representation = rinfo->IsCodedSpecially() ? 1453 int representation = rinfo->IsCodedSpecially() ?
1549 kFromCode + kStartOfObject : kPlain + kStartOfObject; 1454 kFromCode + kStartOfObject : kPlain + kStartOfObject;
1550 sink_->Put(kExternalReference + representation, "ExternalRef"); 1455 sink_->Put(kExternalReference + representation, "ExternalRef");
1456 sink_->PutInt(skip, "SkipB4ExternalRef");
1551 int reference_id = serializer_->EncodeExternalReference(*current); 1457 int reference_id = serializer_->EncodeExternalReference(*current);
1552 sink_->PutInt(reference_id, "reference id"); 1458 sink_->PutInt(reference_id, "reference id");
1553 bytes_processed_so_far_ += rinfo->target_address_size(); 1459 bytes_processed_so_far_ += rinfo->target_address_size();
1554 } 1460 }
1555 1461
1556 1462
1557 void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) { 1463 void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) {
1558 Address target_start = rinfo->target_address_address(); 1464 Address target_start = rinfo->target_address_address();
1559 OutputRawData(target_start); 1465 int skip = OutputRawData(target_start, kCanReturnSkipInsteadOfSkipping);
1560 Address target = rinfo->target_address(); 1466 Address target = rinfo->target_address();
1561 uint32_t encoding = serializer_->EncodeExternalReference(target); 1467 uint32_t encoding = serializer_->EncodeExternalReference(target);
1562 CHECK(target == NULL ? encoding == 0 : encoding != 0); 1468 CHECK(target == NULL ? encoding == 0 : encoding != 0);
1563 int representation; 1469 int representation;
1564 // Can't use a ternary operator because of gcc. 1470 // Can't use a ternary operator because of gcc.
1565 if (rinfo->IsCodedSpecially()) { 1471 if (rinfo->IsCodedSpecially()) {
1566 representation = kStartOfObject + kFromCode; 1472 representation = kStartOfObject + kFromCode;
1567 } else { 1473 } else {
1568 representation = kStartOfObject + kPlain; 1474 representation = kStartOfObject + kPlain;
1569 } 1475 }
1570 sink_->Put(kExternalReference + representation, "ExternalReference"); 1476 sink_->Put(kExternalReference + representation, "ExternalReference");
1477 sink_->PutInt(skip, "SkipB4ExternalRef");
1571 sink_->PutInt(encoding, "reference id"); 1478 sink_->PutInt(encoding, "reference id");
1572 bytes_processed_so_far_ += rinfo->target_address_size(); 1479 bytes_processed_so_far_ += rinfo->target_address_size();
1573 } 1480 }
1574 1481
1575 1482
1576 void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) { 1483 void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) {
1577 CHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); 1484 CHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
1578 Address target_start = rinfo->target_address_address(); 1485 Address target_start = rinfo->target_address_address();
1579 OutputRawData(target_start); 1486 int skip = OutputRawData(target_start, kCanReturnSkipInsteadOfSkipping);
1580 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); 1487 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
1581 serializer_->SerializeObject(target, kFromCode, kInnerPointer); 1488 serializer_->SerializeObject(target, kFromCode, kInnerPointer, skip);
1582 bytes_processed_so_far_ += rinfo->target_address_size(); 1489 bytes_processed_so_far_ += rinfo->target_address_size();
1583 } 1490 }
1584 1491
1585 1492
1586 void Serializer::ObjectSerializer::VisitCodeEntry(Address entry_address) { 1493 void Serializer::ObjectSerializer::VisitCodeEntry(Address entry_address) {
1587 Code* target = Code::cast(Code::GetObjectFromEntryAddress(entry_address)); 1494 Code* target = Code::cast(Code::GetObjectFromEntryAddress(entry_address));
1588 OutputRawData(entry_address); 1495 int skip = OutputRawData(entry_address, kCanReturnSkipInsteadOfSkipping);
1589 serializer_->SerializeObject(target, kPlain, kInnerPointer); 1496 serializer_->SerializeObject(target, kPlain, kInnerPointer, skip);
1590 bytes_processed_so_far_ += kPointerSize; 1497 bytes_processed_so_far_ += kPointerSize;
1591 } 1498 }
1592 1499
1593 1500
1594 void Serializer::ObjectSerializer::VisitGlobalPropertyCell(RelocInfo* rinfo) { 1501 void Serializer::ObjectSerializer::VisitGlobalPropertyCell(RelocInfo* rinfo) {
1595 ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL); 1502 ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
1596 JSGlobalPropertyCell* cell = 1503 JSGlobalPropertyCell* cell =
1597 JSGlobalPropertyCell::cast(rinfo->target_cell()); 1504 JSGlobalPropertyCell::cast(rinfo->target_cell());
1598 OutputRawData(rinfo->pc()); 1505 int skip = OutputRawData(rinfo->pc(), kCanReturnSkipInsteadOfSkipping);
1599 serializer_->SerializeObject(cell, kPlain, kInnerPointer); 1506 serializer_->SerializeObject(cell, kPlain, kInnerPointer, skip);
1600 } 1507 }
1601 1508
1602 1509
1603 void Serializer::ObjectSerializer::VisitExternalAsciiString( 1510 void Serializer::ObjectSerializer::VisitExternalAsciiString(
1604 v8::String::ExternalAsciiStringResource** resource_pointer) { 1511 v8::String::ExternalAsciiStringResource** resource_pointer) {
1605 Address references_start = reinterpret_cast<Address>(resource_pointer); 1512 Address references_start = reinterpret_cast<Address>(resource_pointer);
1606 OutputRawData(references_start); 1513 OutputRawData(references_start);
1607 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { 1514 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
1608 Object* source = HEAP->natives_source_cache()->get(i); 1515 Object* source = HEAP->natives_source_cache()->get(i);
1609 if (!source->IsUndefined()) { 1516 if (!source->IsUndefined()) {
1610 ExternalAsciiString* string = ExternalAsciiString::cast(source); 1517 ExternalAsciiString* string = ExternalAsciiString::cast(source);
1611 typedef v8::String::ExternalAsciiStringResource Resource; 1518 typedef v8::String::ExternalAsciiStringResource Resource;
1612 const Resource* resource = string->resource(); 1519 const Resource* resource = string->resource();
1613 if (resource == *resource_pointer) { 1520 if (resource == *resource_pointer) {
1614 sink_->Put(kNativesStringResource, "NativesStringResource"); 1521 sink_->Put(kNativesStringResource, "NativesStringResource");
1615 sink_->PutSection(i, "NativesStringResourceEnd"); 1522 sink_->PutSection(i, "NativesStringResourceEnd");
1616 bytes_processed_so_far_ += sizeof(resource); 1523 bytes_processed_so_far_ += sizeof(resource);
1617 return; 1524 return;
1618 } 1525 }
1619 } 1526 }
1620 } 1527 }
1621 // One of the strings in the natives cache should match the resource. We 1528 // One of the strings in the natives cache should match the resource. We
1622 // can't serialize any other kinds of external strings. 1529 // can't serialize any other kinds of external strings.
1623 UNREACHABLE(); 1530 UNREACHABLE();
1624 } 1531 }
1625 1532
1626 1533
1627 void Serializer::ObjectSerializer::OutputRawData(Address up_to) { 1534 int Serializer::ObjectSerializer::OutputRawData(
1535 Address up_to, Serializer::ObjectSerializer::ReturnSkip return_skip) {
1628 Address object_start = object_->address(); 1536 Address object_start = object_->address();
1537 Address base = object_start + bytes_processed_so_far_;
1629 int up_to_offset = static_cast<int>(up_to - object_start); 1538 int up_to_offset = static_cast<int>(up_to - object_start);
1630 int skipped = up_to_offset - bytes_processed_so_far_; 1539 int to_skip = up_to_offset - bytes_processed_so_far_;
1540 int bytes_to_output = to_skip;
1541 bytes_processed_so_far_ += to_skip;
1631 // This assert will fail if the reloc info gives us the target_address_address 1542 // This assert will fail if the reloc info gives us the target_address_address
1632 // locations in a non-ascending order. Luckily that doesn't happen. 1543 // locations in a non-ascending order. Luckily that doesn't happen.
1633 ASSERT(skipped >= 0); 1544 ASSERT(to_skip >= 0);
1634 if (skipped != 0) { 1545 bool outputting_code = false;
1635 Address base = object_start + bytes_processed_so_far_; 1546 if (to_skip != 0 && code_object_ && !code_has_been_output_) {
1636 #define RAW_CASE(index, length) \ 1547 // Output the code all at once and fix later.
1637 if (skipped == length) { \ 1548 bytes_to_output = object_->Size() + to_skip - bytes_processed_so_far_;
1549 outputting_code = true;
1550 code_has_been_output_ = true;
1551 }
1552 if (bytes_to_output != 0 &&
1553 (!code_object_ || outputting_code)) {
1554 #define RAW_CASE(index) \
1555 if (!outputting_code && bytes_to_output == index * kPointerSize && \
1556 index * kPointerSize == to_skip) { \
1638 sink_->PutSection(kRawData + index, "RawDataFixed"); \ 1557 sink_->PutSection(kRawData + index, "RawDataFixed"); \
1558 to_skip = 0; /* This insn already skips. */ \
1639 } else /* NOLINT */ 1559 } else /* NOLINT */
1640 COMMON_RAW_LENGTHS(RAW_CASE) 1560 COMMON_RAW_LENGTHS(RAW_CASE)
1641 #undef RAW_CASE 1561 #undef RAW_CASE
1642 { /* NOLINT */ 1562 { /* NOLINT */
1563 // We always end up here if we are outputting the code of a code object.
1643 sink_->Put(kRawData, "RawData"); 1564 sink_->Put(kRawData, "RawData");
1644 sink_->PutInt(skipped, "length"); 1565 sink_->PutInt(bytes_to_output, "length");
1645 } 1566 }
1646 for (int i = 0; i < skipped; i++) { 1567 for (int i = 0; i < bytes_to_output; i++) {
1647 unsigned int data = base[i]; 1568 unsigned int data = base[i];
1648 sink_->PutSection(data, "Byte"); 1569 sink_->PutSection(data, "Byte");
1649 } 1570 }
1650 bytes_processed_so_far_ += skipped;
1651 } 1571 }
1572 if (to_skip != 0 && return_skip == kIgnoringReturn) {
1573 sink_->Put(kSkip, "Skip");
1574 sink_->PutInt(to_skip, "SkipDistance");
1575 to_skip = 0;
1576 }
1577 return to_skip;
1652 } 1578 }
1653 1579
1654 1580
1655 int Serializer::SpaceOfObject(HeapObject* object) { 1581 int Serializer::SpaceOfObject(HeapObject* object) {
1656 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) { 1582 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
1657 AllocationSpace s = static_cast<AllocationSpace>(i); 1583 AllocationSpace s = static_cast<AllocationSpace>(i);
1658 if (HEAP->InSpace(object, s)) { 1584 if (HEAP->InSpace(object, s)) {
1659 if (i == LO_SPACE) { 1585 ASSERT(i < kNumberOfSpaces);
1660 if (object->IsCode()) {
1661 return kLargeCode;
1662 } else if (object->IsFixedArray()) {
1663 return kLargeFixedArray;
1664 } else {
1665 return kLargeData;
1666 }
1667 }
1668 return i; 1586 return i;
1669 } 1587 }
1670 } 1588 }
1671 UNREACHABLE(); 1589 UNREACHABLE();
1672 return 0; 1590 return 0;
1673 } 1591 }
1674 1592
1675 1593
1676 int Serializer::SpaceOfAlreadySerializedObject(HeapObject* object) { 1594 int Serializer::Allocate(int space, int size) {
1677 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
1678 AllocationSpace s = static_cast<AllocationSpace>(i);
1679 if (HEAP->InSpace(object, s)) {
1680 return i;
1681 }
1682 }
1683 UNREACHABLE();
1684 return 0;
1685 }
1686
1687
1688 int Serializer::Allocate(int space, int size, bool* new_page) {
1689 CHECK(space >= 0 && space < kNumberOfSpaces); 1595 CHECK(space >= 0 && space < kNumberOfSpaces);
1690 if (SpaceIsLarge(space)) {
1691 // In large object space we merely number the objects instead of trying to
1692 // determine some sort of address.
1693 *new_page = true;
1694 large_object_total_ += size;
1695 return fullness_[LO_SPACE]++;
1696 }
1697 *new_page = false;
1698 if (fullness_[space] == 0) {
1699 *new_page = true;
1700 }
1701 if (SpaceIsPaged(space)) {
1702 // Paged spaces are a little special. We encode their addresses as if the
1703 // pages were all contiguous and each page were filled up in the range
1704 // 0 - Page::kObjectAreaSize. In practice the pages may not be contiguous
1705 // and allocation does not start at offset 0 in the page, but this scheme
1706 // means the deserializer can get the page number quickly by shifting the
1707 // serialized address.
1708 CHECK(IsPowerOf2(Page::kPageSize));
1709 int used_in_this_page = (fullness_[space] & (Page::kPageSize - 1));
1710 CHECK(size <= SpaceAreaSize(space));
1711 if (used_in_this_page + size > SpaceAreaSize(space)) {
1712 *new_page = true;
1713 fullness_[space] = RoundUp(fullness_[space], Page::kPageSize);
1714 }
1715 }
1716 int allocation_address = fullness_[space]; 1596 int allocation_address = fullness_[space];
1717 fullness_[space] = allocation_address + size; 1597 fullness_[space] = allocation_address + size;
1718 return allocation_address; 1598 return allocation_address;
1719 } 1599 }
1720 1600
1721 1601
1722 int Serializer::SpaceAreaSize(int space) { 1602 int Serializer::SpaceAreaSize(int space) {
1723 if (space == CODE_SPACE) { 1603 if (space == CODE_SPACE) {
1724 return isolate_->memory_allocator()->CodePageAreaSize(); 1604 return isolate_->memory_allocator()->CodePageAreaSize();
1725 } else { 1605 } else {
1726 return Page::kPageSize - Page::kObjectStartOffset; 1606 return Page::kPageSize - Page::kObjectStartOffset;
1727 } 1607 }
1728 } 1608 }
1729 1609
1730 1610
1611 void Serializer::Pad() {
1612 // The non-branching GetInt will read up to 3 bytes too far, so we need
1613 // to pad the snapshot to make sure we don't read over the end.
1614 for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) {
1615 sink_->Put(kNop, "Padding");
1616 }
1617 }
1618
1619
1620 bool SnapshotByteSource::AtEOF() {
1621 if (0u + length_ - position_ > sizeof(uint32_t)) return false;
1622 for (int x = position_; x < length_; x++) {
1623 if (data_[x] != SerializerDeserializer::nop()) return false;
1624 }
1625 return true;
1626 }
1627
1731 } } // namespace v8::internal 1628 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/serialize.h ('k') | src/snapshot.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698