OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
653 *write_back = HeapObject::FromAddress(address); | 653 *write_back = HeapObject::FromAddress(address); |
654 Object** current = reinterpret_cast<Object**>(address); | 654 Object** current = reinterpret_cast<Object**>(address); |
655 Object** limit = current + (size >> kPointerSizeLog2); | 655 Object** limit = current + (size >> kPointerSizeLog2); |
656 if (FLAG_log_snapshot_positions) { | 656 if (FLAG_log_snapshot_positions) { |
657 LOG(SnapshotPositionEvent(address, source_->position())); | 657 LOG(SnapshotPositionEvent(address, source_->position())); |
658 } | 658 } |
659 ReadChunk(current, limit, space_number, address); | 659 ReadChunk(current, limit, space_number, address); |
660 } | 660 } |
661 | 661 |
662 | 662 |
663 #define ONE_CASE_PER_SPACE(base_tag) \ | 663 // This macro is always used with a constant argument so it should all fold |
664 case (base_tag) + NEW_SPACE: /* NOLINT */ \ | 664 // away to almost nothing in the generated code. It might be nicer to do this |
665 case (base_tag) + OLD_POINTER_SPACE: /* NOLINT */ \ | 665 // with the ternary operator but there are type issues with that. |
666 case (base_tag) + OLD_DATA_SPACE: /* NOLINT */ \ | 666 #define ASSIGN_DEST_SPACE(space_number) \ |
667 case (base_tag) + CODE_SPACE: /* NOLINT */ \ | 667 Space* dest_space; \ |
668 case (base_tag) + MAP_SPACE: /* NOLINT */ \ | 668 if (space_number == NEW_SPACE) { \ |
669 case (base_tag) + CELL_SPACE: /* NOLINT */ \ | 669 dest_space = Heap::new_space(); \ |
670 case (base_tag) + kLargeData: /* NOLINT */ \ | 670 } else if (space_number == OLD_POINTER_SPACE) { \ |
671 case (base_tag) + kLargeCode: /* NOLINT */ \ | 671 dest_space = Heap::old_pointer_space(); \ |
672 case (base_tag) + kLargeFixedArray: /* NOLINT */ | 672 } else if (space_number == OLD_DATA_SPACE) { \ |
| 673 dest_space = Heap::old_data_space(); \ |
| 674 } else if (space_number == CODE_SPACE) { \ |
| 675 dest_space = Heap::code_space(); \ |
| 676 } else if (space_number == MAP_SPACE) { \ |
| 677 dest_space = Heap::map_space(); \ |
| 678 } else if (space_number == CELL_SPACE) { \ |
| 679 dest_space = Heap::cell_space(); \ |
| 680 } else { \ |
| 681 ASSERT(space_number >= LO_SPACE); \ |
| 682 dest_space = Heap::lo_space(); \ |
| 683 } |
| 684 |
| 685 |
| 686 static const int kUnknownOffsetFromStart = -1; |
673 | 687 |
674 | 688 |
675 void Deserializer::ReadChunk(Object** current, | 689 void Deserializer::ReadChunk(Object** current, |
676 Object** limit, | 690 Object** limit, |
677 int space, | 691 int source_space, |
678 Address address) { | 692 Address address) { |
679 while (current < limit) { | 693 while (current < limit) { |
680 int data = source_->Get(); | 694 int data = source_->Get(); |
681 switch (data) { | 695 switch (data) { |
| 696 #define CASE_STATEMENT(where, how, within, space_number) \ |
| 697 case where + how + within + space_number: \ |
| 698 ASSERT((where & ~kPointedToMask) == 0); \ |
| 699 ASSERT((how & ~kHowToCodeMask) == 0); \ |
| 700 ASSERT((within & ~kWhereToPointMask) == 0); \ |
| 701 ASSERT((space_number & ~kSpaceMask) == 0); |
| 702 |
| 703 #define CASE_BODY(where, how, within, space_number_if_any, offset_from_start) \ |
| 704 { \ |
| 705 bool emit_write_barrier = false; \ |
| 706 bool current_was_incremented = false; \ |
| 707 int space_number = space_number_if_any == kAnyOldSpace ? \ |
| 708 (data & kSpaceMask) : space_number_if_any; \ |
| 709 if (where == kNewObject && how == kPlain && within == kStartOfObject) {\ |
| 710 ASSIGN_DEST_SPACE(space_number) \ |
| 711 ReadObject(space_number, dest_space, current); \ |
| 712 emit_write_barrier = \ |
| 713 (space_number == NEW_SPACE && source_space != NEW_SPACE); \ |
| 714 } else { \ |
| 715 Object* new_object = NULL; /* May not be a real Object pointer. */ \ |
| 716 if (where == kNewObject) { \ |
| 717 ASSIGN_DEST_SPACE(space_number) \ |
| 718 ReadObject(space_number, dest_space, &new_object); \ |
| 719 } else if (where == kRootArray) { \ |
| 720 int root_id = source_->GetInt(); \ |
| 721 new_object = Heap::roots_address()[root_id]; \ |
| 722 } else if (where == kPartialSnapshotCache) { \ |
| 723 int cache_index = source_->GetInt(); \ |
| 724 new_object = partial_snapshot_cache_[cache_index]; \ |
| 725 } else if (where == kExternalReference) { \ |
| 726 int reference_id = source_->GetInt(); \ |
| 727 Address address = \ |
| 728 external_reference_decoder_->Decode(reference_id); \ |
| 729 new_object = reinterpret_cast<Object*>(address); \ |
| 730 } else if (where == kBackref) { \ |
| 731 emit_write_barrier = \ |
| 732 (space_number == NEW_SPACE && source_space != NEW_SPACE); \ |
| 733 new_object = GetAddressFromEnd(data & kSpaceMask); \ |
| 734 } else { \ |
| 735 ASSERT(where == kFromStart); \ |
| 736 if (offset_from_start == kUnknownOffsetFromStart) { \ |
| 737 emit_write_barrier = \ |
| 738 (space_number == NEW_SPACE && source_space != NEW_SPACE); \ |
| 739 new_object = GetAddressFromStart(data & kSpaceMask); \ |
| 740 } else { \ |
| 741 Address object_address = pages_[space_number][0] + \ |
| 742 (offset_from_start << kObjectAlignmentBits); \ |
| 743 new_object = HeapObject::FromAddress(object_address); \ |
| 744 } \ |
| 745 } \ |
| 746 if (within == kFirstInstruction) { \ |
| 747 Code* new_code_object = reinterpret_cast<Code*>(new_object); \ |
| 748 new_object = reinterpret_cast<Object*>( \ |
| 749 new_code_object->instruction_start()); \ |
| 750 } \ |
| 751 if (how == kFromCode) { \ |
| 752 Address location_of_branch_data = \ |
| 753 reinterpret_cast<Address>(current); \ |
| 754 Assembler::set_target_at(location_of_branch_data, \ |
| 755 reinterpret_cast<Address>(new_object)); \ |
| 756 if (within == kFirstInstruction) { \ |
| 757 location_of_branch_data += Assembler::kCallTargetSize; \ |
| 758 current = reinterpret_cast<Object**>(location_of_branch_data); \ |
| 759 current_was_incremented = true; \ |
| 760 } \ |
| 761 } else { \ |
| 762 *current = new_object; \ |
| 763 } \ |
| 764 } \ |
| 765 if (emit_write_barrier) { \ |
| 766 Heap::RecordWrite(address, static_cast<int>( \ |
| 767 reinterpret_cast<Address>(current) - address)); \ |
| 768 } \ |
| 769 if (!current_was_incremented) { \ |
| 770 current++; /* Increment current if it wasn't done above. */ \ |
| 771 } \ |
| 772 break; \ |
| 773 } \ |
| 774 |
| 775 // This generates a case and a body for each space. The large object spaces are |
| 776 // very rare in snapshots so they are grouped in one body. |
| 777 #define ONE_PER_SPACE(where, how, within) \ |
| 778 CASE_STATEMENT(where, how, within, NEW_SPACE) \ |
| 779 CASE_BODY(where, how, within, NEW_SPACE, kUnknownOffsetFromStart) \ |
| 780 CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \ |
| 781 CASE_BODY(where, how, within, OLD_DATA_SPACE, kUnknownOffsetFromStart) \ |
| 782 CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \ |
| 783 CASE_BODY(where, how, within, OLD_POINTER_SPACE, kUnknownOffsetFromStart) \ |
| 784 CASE_STATEMENT(where, how, within, CODE_SPACE) \ |
| 785 CASE_BODY(where, how, within, CODE_SPACE, kUnknownOffsetFromStart) \ |
| 786 CASE_STATEMENT(where, how, within, CELL_SPACE) \ |
| 787 CASE_BODY(where, how, within, CELL_SPACE, kUnknownOffsetFromStart) \ |
| 788 CASE_STATEMENT(where, how, within, MAP_SPACE) \ |
| 789 CASE_BODY(where, how, within, MAP_SPACE, kUnknownOffsetFromStart) \ |
| 790 CASE_STATEMENT(where, how, within, kLargeData) \ |
| 791 CASE_STATEMENT(where, how, within, kLargeCode) \ |
| 792 CASE_STATEMENT(where, how, within, kLargeFixedArray) \ |
| 793 CASE_BODY(where, how, within, kAnyOldSpace, kUnknownOffsetFromStart) |
| 794 |
| 795 // This generates a case and a body for the new space (which has to do extra |
| 796 // write barrier handling) and handles the other spaces with 8 fall-through |
| 797 // cases and one body. |
| 798 #define ALL_SPACES(where, how, within) \ |
| 799 CASE_STATEMENT(where, how, within, NEW_SPACE) \ |
| 800 CASE_BODY(where, how, within, NEW_SPACE, kUnknownOffsetFromStart) \ |
| 801 CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \ |
| 802 CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \ |
| 803 CASE_STATEMENT(where, how, within, CODE_SPACE) \ |
| 804 CASE_STATEMENT(where, how, within, CELL_SPACE) \ |
| 805 CASE_STATEMENT(where, how, within, MAP_SPACE) \ |
| 806 CASE_STATEMENT(where, how, within, kLargeData) \ |
| 807 CASE_STATEMENT(where, how, within, kLargeCode) \ |
| 808 CASE_STATEMENT(where, how, within, kLargeFixedArray) \ |
| 809 CASE_BODY(where, how, within, kAnyOldSpace, kUnknownOffsetFromStart) |
| 810 |
| 811 #define EMIT_COMMON_REFERENCE_PATTERNS(pseudo_space_number, \ |
| 812 space_number, \ |
| 813 offset_from_start) \ |
| 814 CASE_STATEMENT(kFromStart, kPlain, kStartOfObject, pseudo_space_number) \ |
| 815 CASE_BODY(kFromStart, kPlain, kStartOfObject, space_number, offset_from_start) |
| 816 |
| 817 // We generate 15 cases and bodies that process special tags that combine |
| 818 // the raw data tag and the length into one byte. |
682 #define RAW_CASE(index, size) \ | 819 #define RAW_CASE(index, size) \ |
683 case RAW_DATA_SERIALIZATION + index: { \ | 820 case kRawData + index: { \ |
684 byte* raw_data_out = reinterpret_cast<byte*>(current); \ | 821 byte* raw_data_out = reinterpret_cast<byte*>(current); \ |
685 source_->CopyRaw(raw_data_out, size); \ | 822 source_->CopyRaw(raw_data_out, size); \ |
686 current = reinterpret_cast<Object**>(raw_data_out + size); \ | 823 current = reinterpret_cast<Object**>(raw_data_out + size); \ |
687 break; \ | 824 break; \ |
688 } | 825 } |
689 COMMON_RAW_LENGTHS(RAW_CASE) | 826 COMMON_RAW_LENGTHS(RAW_CASE) |
690 #undef RAW_CASE | 827 #undef RAW_CASE |
691 case RAW_DATA_SERIALIZATION: { | 828 |
| 829 // Deserialize a chunk of raw data that doesn't have one of the popular |
| 830 // lengths. |
| 831 case kRawData: { |
692 int size = source_->GetInt(); | 832 int size = source_->GetInt(); |
693 byte* raw_data_out = reinterpret_cast<byte*>(current); | 833 byte* raw_data_out = reinterpret_cast<byte*>(current); |
694 source_->CopyRaw(raw_data_out, size); | 834 source_->CopyRaw(raw_data_out, size); |
695 current = reinterpret_cast<Object**>(raw_data_out + size); | 835 current = reinterpret_cast<Object**>(raw_data_out + size); |
696 break; | 836 break; |
697 } | 837 } |
698 case OBJECT_SERIALIZATION + NEW_SPACE: { | 838 |
699 ReadObject(NEW_SPACE, Heap::new_space(), current); | 839 // Deserialize a new object and write a pointer to it to the current |
700 if (space != NEW_SPACE) { | 840 // object. |
701 Heap::RecordWrite(address, static_cast<int>( | 841 ONE_PER_SPACE(kNewObject, kPlain, kStartOfObject) |
702 reinterpret_cast<Address>(current) - address)); | 842 // Deserialize a new code object and write a pointer to its first |
703 } | 843 // instruction to the current code object. |
704 current++; | 844 ONE_PER_SPACE(kNewObject, kFromCode, kFirstInstruction) |
705 break; | 845 // Find a recently deserialized object using its offset from the current |
706 } | 846 // allocation point and write a pointer to it to the current object. |
707 case OBJECT_SERIALIZATION + OLD_DATA_SPACE: | 847 ALL_SPACES(kBackref, kPlain, kStartOfObject) |
708 ReadObject(OLD_DATA_SPACE, Heap::old_data_space(), current++); | 848 // Find a recently deserialized code object using its offset from the |
709 break; | 849 // current allocation point and write a pointer to its first instruction |
710 case OBJECT_SERIALIZATION + OLD_POINTER_SPACE: | 850 // to the current code object. |
711 ReadObject(OLD_POINTER_SPACE, Heap::old_pointer_space(), current++); | 851 ALL_SPACES(kBackref, kFromCode, kFirstInstruction) |
712 break; | 852 // Find an already deserialized object using its offset from the start |
713 case OBJECT_SERIALIZATION + MAP_SPACE: | 853 // and write a pointer to it to the current object. |
714 ReadObject(MAP_SPACE, Heap::map_space(), current++); | 854 ALL_SPACES(kFromStart, kPlain, kStartOfObject) |
715 break; | 855 // Find an already deserialized code object using its offset from the |
716 case OBJECT_SERIALIZATION + CODE_SPACE: | 856 // start and write a pointer to its first instruction to the current code |
717 ReadObject(CODE_SPACE, Heap::code_space(), current++); | 857 // object. |
718 break; | 858 ALL_SPACES(kFromStart, kFromCode, kFirstInstruction) |
719 case OBJECT_SERIALIZATION + CELL_SPACE: | 859 // Find an already deserialized object at one of the predetermined popular |
720 ReadObject(CELL_SPACE, Heap::cell_space(), current++); | 860 // offsets from the start and write a pointer to it in the current object. |
721 break; | 861 COMMON_REFERENCE_PATTERNS(EMIT_COMMON_REFERENCE_PATTERNS) |
722 case OBJECT_SERIALIZATION + kLargeData: | 862 // Find an object in the roots array and write a pointer to it to the |
723 ReadObject(kLargeData, Heap::lo_space(), current++); | 863 // current object. |
724 break; | 864 CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0) |
725 case OBJECT_SERIALIZATION + kLargeCode: | 865 CASE_BODY(kRootArray, kPlain, kStartOfObject, 0, kUnknownOffsetFromStart) |
726 ReadObject(kLargeCode, Heap::lo_space(), current++); | 866 // Find an object in the partial snapshots cache and write a pointer to it |
727 break; | 867 // to the current object. |
728 case OBJECT_SERIALIZATION + kLargeFixedArray: | 868 CASE_STATEMENT(kPartialSnapshotCache, kPlain, kStartOfObject, 0) |
729 ReadObject(kLargeFixedArray, Heap::lo_space(), current++); | 869 CASE_BODY(kPartialSnapshotCache, |
730 break; | 870 kPlain, |
731 case CODE_OBJECT_SERIALIZATION + kLargeCode: { | 871 kStartOfObject, |
732 Object* new_code_object = NULL; | 872 0, |
733 ReadObject(kLargeCode, Heap::lo_space(), &new_code_object); | 873 kUnknownOffsetFromStart) |
734 Code* code_object = reinterpret_cast<Code*>(new_code_object); | 874 // Find an external reference and write a pointer to it to the current |
735 // Setting a branch/call to another code object from code. | 875 // object. |
736 Address location_of_branch_data = reinterpret_cast<Address>(current); | 876 CASE_STATEMENT(kExternalReference, kPlain, kStartOfObject, 0) |
737 Assembler::set_target_at(location_of_branch_data, | 877 CASE_BODY(kExternalReference, |
738 code_object->instruction_start()); | 878 kPlain, |
739 location_of_branch_data += Assembler::kCallTargetSize; | 879 kStartOfObject, |
740 current = reinterpret_cast<Object**>(location_of_branch_data); | 880 0, |
741 break; | 881 kUnknownOffsetFromStart) |
742 } | 882 // Find an external reference and write a pointer to it in the current |
743 case CODE_OBJECT_SERIALIZATION + CODE_SPACE: { | 883 // code object. |
744 Object* new_code_object = NULL; | 884 CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0) |
745 ReadObject(CODE_SPACE, Heap::code_space(), &new_code_object); | 885 CASE_BODY(kExternalReference, |
746 Code* code_object = reinterpret_cast<Code*>(new_code_object); | 886 kFromCode, |
747 // Setting a branch/call to another code object from code. | 887 kStartOfObject, |
748 Address location_of_branch_data = reinterpret_cast<Address>(current); | 888 0, |
749 Assembler::set_target_at(location_of_branch_data, | 889 kUnknownOffsetFromStart) |
750 code_object->instruction_start()); | 890 |
751 location_of_branch_data += Assembler::kCallTargetSize; | 891 #undef CASE_STATEMENT |
752 current = reinterpret_cast<Object**>(location_of_branch_data); | 892 #undef CASE_BODY |
753 break; | 893 #undef ONE_PER_SPACE |
754 } | 894 #undef ALL_SPACES |
755 ONE_CASE_PER_SPACE(BACKREF_SERIALIZATION) { | 895 #undef EMIT_COMMON_REFERENCE_PATTERNS |
756 // Write a backreference to an object we unpacked earlier. | 896 #undef ASSIGN_DEST_SPACE |
757 int backref_space = (data & kSpaceMask); | 897 |
758 if (backref_space == NEW_SPACE && space != NEW_SPACE) { | 898 case kNewPage: { |
759 Heap::RecordWrite(address, static_cast<int>( | |
760 reinterpret_cast<Address>(current) - address)); | |
761 } | |
762 *current++ = GetAddressFromEnd(backref_space); | |
763 break; | |
764 } | |
765 ONE_CASE_PER_SPACE(REFERENCE_SERIALIZATION) { | |
766 // Write a reference to an object we unpacked earlier. | |
767 int reference_space = (data & kSpaceMask); | |
768 if (reference_space == NEW_SPACE && space != NEW_SPACE) { | |
769 Heap::RecordWrite(address, static_cast<int>( | |
770 reinterpret_cast<Address>(current) - address)); | |
771 } | |
772 *current++ = GetAddressFromStart(reference_space); | |
773 break; | |
774 } | |
775 #define COMMON_REFS_CASE(index, reference_space, address) \ | |
776 case REFERENCE_SERIALIZATION + index: { \ | |
777 ASSERT(SpaceIsPaged(reference_space)); \ | |
778 Address object_address = \ | |
779 pages_[reference_space][0] + (address << kObjectAlignmentBits); \ | |
780 *current++ = HeapObject::FromAddress(object_address); \ | |
781 break; \ | |
782 } | |
783 COMMON_REFERENCE_PATTERNS(COMMON_REFS_CASE) | |
784 #undef COMMON_REFS_CASE | |
785 ONE_CASE_PER_SPACE(CODE_BACKREF_SERIALIZATION) { | |
786 int backref_space = (data & kSpaceMask); | |
787 // Can't use Code::cast because heap is not set up yet and assertions | |
788 // will fail. | |
789 Code* code_object = | |
790 reinterpret_cast<Code*>(GetAddressFromEnd(backref_space)); | |
791 // Setting a branch/call to previously decoded code object from code. | |
792 Address location_of_branch_data = reinterpret_cast<Address>(current); | |
793 Assembler::set_target_at(location_of_branch_data, | |
794 code_object->instruction_start()); | |
795 location_of_branch_data += Assembler::kCallTargetSize; | |
796 current = reinterpret_cast<Object**>(location_of_branch_data); | |
797 break; | |
798 } | |
799 ONE_CASE_PER_SPACE(CODE_REFERENCE_SERIALIZATION) { | |
800 int backref_space = (data & kSpaceMask); | |
801 // Can't use Code::cast because heap is not set up yet and assertions | |
802 // will fail. | |
803 Code* code_object = | |
804 reinterpret_cast<Code*>(GetAddressFromStart(backref_space)); | |
805 // Setting a branch/call to previously decoded code object from code. | |
806 Address location_of_branch_data = reinterpret_cast<Address>(current); | |
807 Assembler::set_target_at(location_of_branch_data, | |
808 code_object->instruction_start()); | |
809 location_of_branch_data += Assembler::kCallTargetSize; | |
810 current = reinterpret_cast<Object**>(location_of_branch_data); | |
811 break; | |
812 } | |
813 case EXTERNAL_REFERENCE_SERIALIZATION: { | |
814 int reference_id = source_->GetInt(); | |
815 Address address = external_reference_decoder_->Decode(reference_id); | |
816 *current++ = reinterpret_cast<Object*>(address); | |
817 break; | |
818 } | |
819 case EXTERNAL_BRANCH_TARGET_SERIALIZATION: { | |
820 int reference_id = source_->GetInt(); | |
821 Address address = external_reference_decoder_->Decode(reference_id); | |
822 Address location_of_branch_data = reinterpret_cast<Address>(current); | |
823 Assembler::set_external_target_at(location_of_branch_data, address); | |
824 location_of_branch_data += Assembler::kExternalTargetSize; | |
825 current = reinterpret_cast<Object**>(location_of_branch_data); | |
826 break; | |
827 } | |
828 case START_NEW_PAGE_SERIALIZATION: { | |
829 int space = source_->Get(); | 899 int space = source_->Get(); |
830 pages_[space].Add(last_object_address_); | 900 pages_[space].Add(last_object_address_); |
831 if (space == CODE_SPACE) { | 901 if (space == CODE_SPACE) { |
832 CPU::FlushICache(last_object_address_, Page::kPageSize); | 902 CPU::FlushICache(last_object_address_, Page::kPageSize); |
833 } | 903 } |
834 break; | 904 break; |
835 } | 905 } |
836 case NATIVES_STRING_RESOURCE: { | 906 |
| 907 case kNativesStringResource: { |
837 int index = source_->Get(); | 908 int index = source_->Get(); |
838 Vector<const char> source_vector = Natives::GetScriptSource(index); | 909 Vector<const char> source_vector = Natives::GetScriptSource(index); |
839 NativesExternalStringResource* resource = | 910 NativesExternalStringResource* resource = |
840 new NativesExternalStringResource(source_vector.start()); | 911 new NativesExternalStringResource(source_vector.start()); |
841 *current++ = reinterpret_cast<Object*>(resource); | 912 *current++ = reinterpret_cast<Object*>(resource); |
842 break; | 913 break; |
843 } | 914 } |
844 case ROOT_SERIALIZATION: { | 915 |
845 int root_id = source_->GetInt(); | 916 case kSynchronize: { |
846 *current++ = Heap::roots_address()[root_id]; | |
847 break; | |
848 } | |
849 case PARTIAL_SNAPSHOT_CACHE_ENTRY: { | |
850 int cache_index = source_->GetInt(); | |
851 *current++ = partial_snapshot_cache_[cache_index]; | |
852 break; | |
853 } | |
854 case SYNCHRONIZE: { | |
855 // If we get here then that indicates that you have a mismatch between | 917 // If we get here then that indicates that you have a mismatch between |
856 // the number of GC roots when serializing and deserializing. | 918 // the number of GC roots when serializing and deserializing. |
857 UNREACHABLE(); | 919 UNREACHABLE(); |
858 } | 920 } |
| 921 |
859 default: | 922 default: |
860 UNREACHABLE(); | 923 UNREACHABLE(); |
861 } | 924 } |
862 } | 925 } |
863 ASSERT_EQ(current, limit); | 926 ASSERT_EQ(current, limit); |
864 } | 927 } |
865 | 928 |
866 | 929 |
867 void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) { | 930 void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) { |
868 const int max_shift = ((kPointerSize * kBitsPerByte) / 7) * 7; | 931 const int max_shift = ((kPointerSize * kBitsPerByte) / 7) * 7; |
869 for (int shift = max_shift; shift > 0; shift -= 7) { | 932 for (int shift = max_shift; shift > 0; shift -= 7) { |
870 if (integer >= static_cast<uintptr_t>(1u) << shift) { | 933 if (integer >= static_cast<uintptr_t>(1u) << shift) { |
871 Put((static_cast<int>((integer >> shift)) & 0x7f) | 0x80, "IntPart"); | 934 Put((static_cast<int>((integer >> shift)) & 0x7f) | 0x80, "IntPart"); |
872 } | 935 } |
873 } | 936 } |
874 PutSection(static_cast<int>(integer & 0x7f), "IntLastPart"); | 937 PutSection(static_cast<int>(integer & 0x7f), "IntLastPart"); |
875 } | 938 } |
876 | 939 |
877 #ifdef DEBUG | 940 #ifdef DEBUG |
878 | 941 |
879 void Deserializer::Synchronize(const char* tag) { | 942 void Deserializer::Synchronize(const char* tag) { |
880 int data = source_->Get(); | 943 int data = source_->Get(); |
881 // If this assert fails then that indicates that you have a mismatch between | 944 // If this assert fails then that indicates that you have a mismatch between |
882 // the number of GC roots when serializing and deserializing. | 945 // the number of GC roots when serializing and deserializing. |
883 ASSERT_EQ(SYNCHRONIZE, data); | 946 ASSERT_EQ(kSynchronize, data); |
884 do { | 947 do { |
885 int character = source_->Get(); | 948 int character = source_->Get(); |
886 if (character == 0) break; | 949 if (character == 0) break; |
887 if (FLAG_debug_serialization) { | 950 if (FLAG_debug_serialization) { |
888 PrintF("%c", character); | 951 PrintF("%c", character); |
889 } | 952 } |
890 } while (true); | 953 } while (true); |
891 if (FLAG_debug_serialization) { | 954 if (FLAG_debug_serialization) { |
892 PrintF("\n"); | 955 PrintF("\n"); |
893 } | 956 } |
894 } | 957 } |
895 | 958 |
896 | 959 |
897 void Serializer::Synchronize(const char* tag) { | 960 void Serializer::Synchronize(const char* tag) { |
898 sink_->Put(SYNCHRONIZE, tag); | 961 sink_->Put(kSynchronize, tag); |
899 int character; | 962 int character; |
900 do { | 963 do { |
901 character = *tag++; | 964 character = *tag++; |
902 sink_->PutSection(character, "TagCharacter"); | 965 sink_->PutSection(character, "TagCharacter"); |
903 } while (character != 0); | 966 } while (character != 0); |
904 } | 967 } |
905 | 968 |
906 #endif | 969 #endif |
907 | 970 |
908 Serializer::Serializer(SnapshotByteSink* sink) | 971 Serializer::Serializer(SnapshotByteSink* sink) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 partial_snapshot_cache_[index] = Heap::undefined_value(); | 1013 partial_snapshot_cache_[index] = Heap::undefined_value(); |
951 startup_serializer_->VisitPointer(&partial_snapshot_cache_[index]); | 1014 startup_serializer_->VisitPointer(&partial_snapshot_cache_[index]); |
952 } | 1015 } |
953 partial_snapshot_cache_length_ = kPartialSnapshotCacheCapacity; | 1016 partial_snapshot_cache_length_ = kPartialSnapshotCacheCapacity; |
954 } | 1017 } |
955 | 1018 |
956 | 1019 |
957 void Serializer::VisitPointers(Object** start, Object** end) { | 1020 void Serializer::VisitPointers(Object** start, Object** end) { |
958 for (Object** current = start; current < end; current++) { | 1021 for (Object** current = start; current < end; current++) { |
959 if ((*current)->IsSmi()) { | 1022 if ((*current)->IsSmi()) { |
960 sink_->Put(RAW_DATA_SERIALIZATION, "RawData"); | 1023 sink_->Put(kRawData, "RawData"); |
961 sink_->PutInt(kPointerSize, "length"); | 1024 sink_->PutInt(kPointerSize, "length"); |
962 for (int i = 0; i < kPointerSize; i++) { | 1025 for (int i = 0; i < kPointerSize; i++) { |
963 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); | 1026 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); |
964 } | 1027 } |
965 } else { | 1028 } else { |
966 SerializeObject(*current, TAGGED_REPRESENTATION); | 1029 SerializeObject(*current, kPlain, kStartOfObject); |
967 } | 1030 } |
968 } | 1031 } |
969 } | 1032 } |
970 | 1033 |
971 | 1034 |
972 Object* SerializerDeserializer::partial_snapshot_cache_[ | 1035 Object* SerializerDeserializer::partial_snapshot_cache_[ |
973 kPartialSnapshotCacheCapacity]; | 1036 kPartialSnapshotCacheCapacity]; |
974 int SerializerDeserializer::partial_snapshot_cache_length_ = 0; | 1037 int SerializerDeserializer::partial_snapshot_cache_length_ = 0; |
975 | 1038 |
976 | 1039 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1026 } | 1089 } |
1027 | 1090 |
1028 | 1091 |
1029 // Encode the location of an already deserialized object in order to write its | 1092 // Encode the location of an already deserialized object in order to write its |
1030 // location into a later object. We can encode the location as an offset from | 1093 // location into a later object. We can encode the location as an offset from |
1031 // the start of the deserialized objects or as an offset backwards from the | 1094 // the start of the deserialized objects or as an offset backwards from the |
1032 // current allocation pointer. | 1095 // current allocation pointer. |
1033 void Serializer::SerializeReferenceToPreviousObject( | 1096 void Serializer::SerializeReferenceToPreviousObject( |
1034 int space, | 1097 int space, |
1035 int address, | 1098 int address, |
1036 ReferenceRepresentation reference_representation) { | 1099 HowToCode how_to_code, |
| 1100 WhereToPoint where_to_point) { |
1037 int offset = CurrentAllocationAddress(space) - address; | 1101 int offset = CurrentAllocationAddress(space) - address; |
1038 bool from_start = true; | 1102 bool from_start = true; |
1039 if (SpaceIsPaged(space)) { | 1103 if (SpaceIsPaged(space)) { |
1040 // For paged space it is simple to encode back from current allocation if | 1104 // For paged space it is simple to encode back from current allocation if |
1041 // the object is on the same page as the current allocation pointer. | 1105 // the object is on the same page as the current allocation pointer. |
1042 if ((CurrentAllocationAddress(space) >> kPageSizeBits) == | 1106 if ((CurrentAllocationAddress(space) >> kPageSizeBits) == |
1043 (address >> kPageSizeBits)) { | 1107 (address >> kPageSizeBits)) { |
1044 from_start = false; | 1108 from_start = false; |
1045 address = offset; | 1109 address = offset; |
1046 } | 1110 } |
1047 } else if (space == NEW_SPACE) { | 1111 } else if (space == NEW_SPACE) { |
1048 // For new space it is always simple to encode back from current allocation. | 1112 // For new space it is always simple to encode back from current allocation. |
1049 if (offset < address) { | 1113 if (offset < address) { |
1050 from_start = false; | 1114 from_start = false; |
1051 address = offset; | 1115 address = offset; |
1052 } | 1116 } |
1053 } | 1117 } |
1054 // If we are actually dealing with real offsets (and not a numbering of | 1118 // If we are actually dealing with real offsets (and not a numbering of |
1055 // all objects) then we should shift out the bits that are always 0. | 1119 // all objects) then we should shift out the bits that are always 0. |
1056 if (!SpaceIsLarge(space)) address >>= kObjectAlignmentBits; | 1120 if (!SpaceIsLarge(space)) address >>= kObjectAlignmentBits; |
1057 // On some architectures references between code objects are encoded | 1121 if (from_start) { |
1058 // specially (as relative offsets). Such references have their own | 1122 #define COMMON_REFS_CASE(pseudo_space, actual_space, offset) \ |
1059 // special tags to simplify the deserializer. | 1123 if (space == actual_space && address == offset && \ |
1060 if (reference_representation == CODE_TARGET_REPRESENTATION) { | 1124 how_to_code == kPlain && where_to_point == kStartOfObject) { \ |
1061 if (from_start) { | 1125 sink_->Put(kFromStart + how_to_code + where_to_point + \ |
1062 sink_->Put(CODE_REFERENCE_SERIALIZATION + space, "RefCodeSer"); | 1126 pseudo_space, "RefSer"); \ |
1063 sink_->PutInt(address, "address"); | 1127 } else /* NOLINT */ |
1064 } else { | 1128 COMMON_REFERENCE_PATTERNS(COMMON_REFS_CASE) |
1065 sink_->Put(CODE_BACKREF_SERIALIZATION + space, "BackRefCodeSer"); | 1129 #undef COMMON_REFS_CASE |
| 1130 { /* NOLINT */ |
| 1131 sink_->Put(kFromStart + how_to_code + where_to_point + space, "RefSer"); |
1066 sink_->PutInt(address, "address"); | 1132 sink_->PutInt(address, "address"); |
1067 } | 1133 } |
1068 } else { | 1134 } else { |
1069 // Regular absolute references. | 1135 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer"); |
1070 CHECK_EQ(TAGGED_REPRESENTATION, reference_representation); | 1136 sink_->PutInt(address, "address"); |
1071 if (from_start) { | |
1072 // There are some common offsets that have their own specialized encoding. | |
1073 #define COMMON_REFS_CASE(tag, common_space, common_offset) \ | |
1074 if (space == common_space && address == common_offset) { \ | |
1075 sink_->PutSection(tag + REFERENCE_SERIALIZATION, "RefSer"); \ | |
1076 } else /* NOLINT */ | |
1077 COMMON_REFERENCE_PATTERNS(COMMON_REFS_CASE) | |
1078 #undef COMMON_REFS_CASE | |
1079 { /* NOLINT */ | |
1080 sink_->Put(REFERENCE_SERIALIZATION + space, "RefSer"); | |
1081 sink_->PutInt(address, "address"); | |
1082 } | |
1083 } else { | |
1084 sink_->Put(BACKREF_SERIALIZATION + space, "BackRefSer"); | |
1085 sink_->PutInt(address, "address"); | |
1086 } | |
1087 } | 1137 } |
1088 } | 1138 } |
1089 | 1139 |
1090 | 1140 |
1091 void StartupSerializer::SerializeObject( | 1141 void StartupSerializer::SerializeObject( |
1092 Object* o, | 1142 Object* o, |
1093 ReferenceRepresentation reference_representation) { | 1143 HowToCode how_to_code, |
| 1144 WhereToPoint where_to_point) { |
1094 CHECK(o->IsHeapObject()); | 1145 CHECK(o->IsHeapObject()); |
1095 HeapObject* heap_object = HeapObject::cast(o); | 1146 HeapObject* heap_object = HeapObject::cast(o); |
1096 | 1147 |
1097 if (address_mapper_.IsMapped(heap_object)) { | 1148 if (address_mapper_.IsMapped(heap_object)) { |
1098 int space = SpaceOfAlreadySerializedObject(heap_object); | 1149 int space = SpaceOfAlreadySerializedObject(heap_object); |
1099 int address = address_mapper_.MappedTo(heap_object); | 1150 int address = address_mapper_.MappedTo(heap_object); |
1100 SerializeReferenceToPreviousObject(space, | 1151 SerializeReferenceToPreviousObject(space, |
1101 address, | 1152 address, |
1102 reference_representation); | 1153 how_to_code, |
| 1154 where_to_point); |
1103 } else { | 1155 } else { |
1104 // Object has not yet been serialized. Serialize it here. | 1156 // Object has not yet been serialized. Serialize it here. |
1105 ObjectSerializer object_serializer(this, | 1157 ObjectSerializer object_serializer(this, |
1106 heap_object, | 1158 heap_object, |
1107 sink_, | 1159 sink_, |
1108 reference_representation); | 1160 how_to_code, |
| 1161 where_to_point); |
1109 object_serializer.Serialize(); | 1162 object_serializer.Serialize(); |
1110 } | 1163 } |
1111 } | 1164 } |
1112 | 1165 |
1113 | 1166 |
1114 void StartupSerializer::SerializeWeakReferences() { | 1167 void StartupSerializer::SerializeWeakReferences() { |
1115 for (int i = partial_snapshot_cache_length_; | 1168 for (int i = partial_snapshot_cache_length_; |
1116 i < kPartialSnapshotCacheCapacity; | 1169 i < kPartialSnapshotCacheCapacity; |
1117 i++) { | 1170 i++) { |
1118 sink_->Put(ROOT_SERIALIZATION, "RootSerialization"); | 1171 sink_->Put(kRootArray + kPlain + kStartOfObject, "RootSerialization"); |
1119 sink_->PutInt(Heap::kUndefinedValueRootIndex, "root_index"); | 1172 sink_->PutInt(Heap::kUndefinedValueRootIndex, "root_index"); |
1120 } | 1173 } |
1121 Heap::IterateWeakRoots(this, VISIT_ALL); | 1174 Heap::IterateWeakRoots(this, VISIT_ALL); |
1122 } | 1175 } |
1123 | 1176 |
1124 | 1177 |
1125 void PartialSerializer::SerializeObject( | 1178 void PartialSerializer::SerializeObject( |
1126 Object* o, | 1179 Object* o, |
1127 ReferenceRepresentation reference_representation) { | 1180 HowToCode how_to_code, |
| 1181 WhereToPoint where_to_point) { |
1128 CHECK(o->IsHeapObject()); | 1182 CHECK(o->IsHeapObject()); |
1129 HeapObject* heap_object = HeapObject::cast(o); | 1183 HeapObject* heap_object = HeapObject::cast(o); |
1130 | 1184 |
1131 int root_index; | 1185 int root_index; |
1132 if ((root_index = RootIndex(heap_object)) != kInvalidRootIndex) { | 1186 if ((root_index = RootIndex(heap_object)) != kInvalidRootIndex) { |
1133 sink_->Put(ROOT_SERIALIZATION, "RootSerialization"); | 1187 sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization"); |
1134 sink_->PutInt(root_index, "root_index"); | 1188 sink_->PutInt(root_index, "root_index"); |
1135 return; | 1189 return; |
1136 } | 1190 } |
1137 | 1191 |
1138 if (ShouldBeInThePartialSnapshotCache(heap_object)) { | 1192 if (ShouldBeInThePartialSnapshotCache(heap_object)) { |
1139 int cache_index = PartialSnapshotCacheIndex(heap_object); | 1193 int cache_index = PartialSnapshotCacheIndex(heap_object); |
1140 sink_->Put(PARTIAL_SNAPSHOT_CACHE_ENTRY, "PartialSnapshotCache"); | 1194 sink_->Put(kPartialSnapshotCache + how_to_code + where_to_point, |
| 1195 "PartialSnapshotCache"); |
1141 sink_->PutInt(cache_index, "partial_snapshot_cache_index"); | 1196 sink_->PutInt(cache_index, "partial_snapshot_cache_index"); |
1142 return; | 1197 return; |
1143 } | 1198 } |
1144 | 1199 |
1145 // Pointers from the partial snapshot to the objects in the startup snapshot | 1200 // Pointers from the partial snapshot to the objects in the startup snapshot |
1146 // should go through the root array or through the partial snapshot cache. | 1201 // should go through the root array or through the partial snapshot cache. |
1147 // If this is not the case you may have to add something to the root array. | 1202 // If this is not the case you may have to add something to the root array. |
1148 ASSERT(!startup_serializer_->address_mapper()->IsMapped(heap_object)); | 1203 ASSERT(!startup_serializer_->address_mapper()->IsMapped(heap_object)); |
1149 // All the symbols that the partial snapshot needs should be either in the | 1204 // All the symbols that the partial snapshot needs should be either in the |
1150 // root table or in the partial snapshot cache. | 1205 // root table or in the partial snapshot cache. |
1151 ASSERT(!heap_object->IsSymbol()); | 1206 ASSERT(!heap_object->IsSymbol()); |
1152 | 1207 |
1153 if (address_mapper_.IsMapped(heap_object)) { | 1208 if (address_mapper_.IsMapped(heap_object)) { |
1154 int space = SpaceOfAlreadySerializedObject(heap_object); | 1209 int space = SpaceOfAlreadySerializedObject(heap_object); |
1155 int address = address_mapper_.MappedTo(heap_object); | 1210 int address = address_mapper_.MappedTo(heap_object); |
1156 SerializeReferenceToPreviousObject(space, | 1211 SerializeReferenceToPreviousObject(space, |
1157 address, | 1212 address, |
1158 reference_representation); | 1213 how_to_code, |
| 1214 where_to_point); |
1159 } else { | 1215 } else { |
1160 // Object has not yet been serialized. Serialize it here. | 1216 // Object has not yet been serialized. Serialize it here. |
1161 ObjectSerializer serializer(this, | 1217 ObjectSerializer serializer(this, |
1162 heap_object, | 1218 heap_object, |
1163 sink_, | 1219 sink_, |
1164 reference_representation); | 1220 how_to_code, |
| 1221 where_to_point); |
1165 serializer.Serialize(); | 1222 serializer.Serialize(); |
1166 } | 1223 } |
1167 } | 1224 } |
1168 | 1225 |
1169 | 1226 |
1170 void Serializer::ObjectSerializer::Serialize() { | 1227 void Serializer::ObjectSerializer::Serialize() { |
1171 int space = Serializer::SpaceOfObject(object_); | 1228 int space = Serializer::SpaceOfObject(object_); |
1172 int size = object_->Size(); | 1229 int size = object_->Size(); |
1173 | 1230 |
1174 if (reference_representation_ == TAGGED_REPRESENTATION) { | 1231 sink_->Put(kNewObject + reference_representation_ + space, |
1175 sink_->Put(OBJECT_SERIALIZATION + space, "ObjectSerialization"); | 1232 "ObjectSerialization"); |
1176 } else { | |
1177 CHECK_EQ(CODE_TARGET_REPRESENTATION, reference_representation_); | |
1178 sink_->Put(CODE_OBJECT_SERIALIZATION + space, "ObjectSerialization"); | |
1179 } | |
1180 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words"); | 1233 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words"); |
1181 | 1234 |
1182 LOG(SnapshotPositionEvent(object_->address(), sink_->Position())); | 1235 LOG(SnapshotPositionEvent(object_->address(), sink_->Position())); |
1183 | 1236 |
1184 // Mark this object as already serialized. | 1237 // Mark this object as already serialized. |
1185 bool start_new_page; | 1238 bool start_new_page; |
1186 int offset = serializer_->Allocate(space, size, &start_new_page); | 1239 int offset = serializer_->Allocate(space, size, &start_new_page); |
1187 serializer_->address_mapper()->AddMapping(object_, offset); | 1240 serializer_->address_mapper()->AddMapping(object_, offset); |
1188 if (start_new_page) { | 1241 if (start_new_page) { |
1189 sink_->Put(START_NEW_PAGE_SERIALIZATION, "NewPage"); | 1242 sink_->Put(kNewPage, "NewPage"); |
1190 sink_->PutSection(space, "NewPageSpace"); | 1243 sink_->PutSection(space, "NewPageSpace"); |
1191 } | 1244 } |
1192 | 1245 |
1193 // Serialize the map (first word of the object). | 1246 // Serialize the map (first word of the object). |
1194 serializer_->SerializeObject(object_->map(), TAGGED_REPRESENTATION); | 1247 serializer_->SerializeObject(object_->map(), kPlain, kStartOfObject); |
1195 | 1248 |
1196 // Serialize the rest of the object. | 1249 // Serialize the rest of the object. |
1197 CHECK_EQ(0, bytes_processed_so_far_); | 1250 CHECK_EQ(0, bytes_processed_so_far_); |
1198 bytes_processed_so_far_ = kPointerSize; | 1251 bytes_processed_so_far_ = kPointerSize; |
1199 object_->IterateBody(object_->map()->instance_type(), size, this); | 1252 object_->IterateBody(object_->map()->instance_type(), size, this); |
1200 OutputRawData(object_->address() + size); | 1253 OutputRawData(object_->address() + size); |
1201 } | 1254 } |
1202 | 1255 |
1203 | 1256 |
1204 void Serializer::ObjectSerializer::VisitPointers(Object** start, | 1257 void Serializer::ObjectSerializer::VisitPointers(Object** start, |
1205 Object** end) { | 1258 Object** end) { |
1206 Object** current = start; | 1259 Object** current = start; |
1207 while (current < end) { | 1260 while (current < end) { |
1208 while (current < end && (*current)->IsSmi()) current++; | 1261 while (current < end && (*current)->IsSmi()) current++; |
1209 if (current < end) OutputRawData(reinterpret_cast<Address>(current)); | 1262 if (current < end) OutputRawData(reinterpret_cast<Address>(current)); |
1210 | 1263 |
1211 while (current < end && !(*current)->IsSmi()) { | 1264 while (current < end && !(*current)->IsSmi()) { |
1212 serializer_->SerializeObject(*current, TAGGED_REPRESENTATION); | 1265 serializer_->SerializeObject(*current, kPlain, kStartOfObject); |
1213 bytes_processed_so_far_ += kPointerSize; | 1266 bytes_processed_so_far_ += kPointerSize; |
1214 current++; | 1267 current++; |
1215 } | 1268 } |
1216 } | 1269 } |
1217 } | 1270 } |
1218 | 1271 |
1219 | 1272 |
1220 void Serializer::ObjectSerializer::VisitExternalReferences(Address* start, | 1273 void Serializer::ObjectSerializer::VisitExternalReferences(Address* start, |
1221 Address* end) { | 1274 Address* end) { |
1222 Address references_start = reinterpret_cast<Address>(start); | 1275 Address references_start = reinterpret_cast<Address>(start); |
1223 OutputRawData(references_start); | 1276 OutputRawData(references_start); |
1224 | 1277 |
1225 for (Address* current = start; current < end; current++) { | 1278 for (Address* current = start; current < end; current++) { |
1226 sink_->Put(EXTERNAL_REFERENCE_SERIALIZATION, "ExternalReference"); | 1279 sink_->Put(kExternalReference + kPlain + kStartOfObject, "ExternalRef"); |
1227 int reference_id = serializer_->EncodeExternalReference(*current); | 1280 int reference_id = serializer_->EncodeExternalReference(*current); |
1228 sink_->PutInt(reference_id, "reference id"); | 1281 sink_->PutInt(reference_id, "reference id"); |
1229 } | 1282 } |
1230 bytes_processed_so_far_ += static_cast<int>((end - start) * kPointerSize); | 1283 bytes_processed_so_far_ += static_cast<int>((end - start) * kPointerSize); |
1231 } | 1284 } |
1232 | 1285 |
1233 | 1286 |
1234 void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) { | 1287 void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) { |
1235 Address target_start = rinfo->target_address_address(); | 1288 Address target_start = rinfo->target_address_address(); |
1236 OutputRawData(target_start); | 1289 OutputRawData(target_start); |
1237 Address target = rinfo->target_address(); | 1290 Address target = rinfo->target_address(); |
1238 uint32_t encoding = serializer_->EncodeExternalReference(target); | 1291 uint32_t encoding = serializer_->EncodeExternalReference(target); |
1239 CHECK(target == NULL ? encoding == 0 : encoding != 0); | 1292 CHECK(target == NULL ? encoding == 0 : encoding != 0); |
1240 sink_->Put(EXTERNAL_BRANCH_TARGET_SERIALIZATION, "ExternalReference"); | 1293 int representation; |
| 1294 // Can't use a ternary operator because of gcc. |
| 1295 if (rinfo->IsCodedSpecially()) { |
| 1296 representation = kStartOfObject + kFromCode; |
| 1297 } else { |
| 1298 representation = kStartOfObject + kPlain; |
| 1299 } |
| 1300 sink_->Put(kExternalReference + representation, "ExternalReference"); |
1241 sink_->PutInt(encoding, "reference id"); | 1301 sink_->PutInt(encoding, "reference id"); |
1242 bytes_processed_so_far_ += Assembler::kExternalTargetSize; | 1302 bytes_processed_so_far_ += Assembler::kExternalTargetSize; |
1243 } | 1303 } |
1244 | 1304 |
1245 | 1305 |
1246 void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) { | 1306 void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) { |
1247 CHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); | 1307 CHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); |
1248 Address target_start = rinfo->target_address_address(); | 1308 Address target_start = rinfo->target_address_address(); |
1249 OutputRawData(target_start); | 1309 OutputRawData(target_start); |
1250 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 1310 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
1251 serializer_->SerializeObject(target, CODE_TARGET_REPRESENTATION); | 1311 serializer_->SerializeObject(target, kFromCode, kFirstInstruction); |
1252 bytes_processed_so_far_ += Assembler::kCallTargetSize; | 1312 bytes_processed_so_far_ += Assembler::kCallTargetSize; |
1253 } | 1313 } |
1254 | 1314 |
1255 | 1315 |
1256 void Serializer::ObjectSerializer::VisitExternalAsciiString( | 1316 void Serializer::ObjectSerializer::VisitExternalAsciiString( |
1257 v8::String::ExternalAsciiStringResource** resource_pointer) { | 1317 v8::String::ExternalAsciiStringResource** resource_pointer) { |
1258 Address references_start = reinterpret_cast<Address>(resource_pointer); | 1318 Address references_start = reinterpret_cast<Address>(resource_pointer); |
1259 OutputRawData(references_start); | 1319 OutputRawData(references_start); |
1260 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { | 1320 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { |
1261 Object* source = Heap::natives_source_cache()->get(i); | 1321 Object* source = Heap::natives_source_cache()->get(i); |
1262 if (!source->IsUndefined()) { | 1322 if (!source->IsUndefined()) { |
1263 ExternalAsciiString* string = ExternalAsciiString::cast(source); | 1323 ExternalAsciiString* string = ExternalAsciiString::cast(source); |
1264 typedef v8::String::ExternalAsciiStringResource Resource; | 1324 typedef v8::String::ExternalAsciiStringResource Resource; |
1265 Resource* resource = string->resource(); | 1325 Resource* resource = string->resource(); |
1266 if (resource == *resource_pointer) { | 1326 if (resource == *resource_pointer) { |
1267 sink_->Put(NATIVES_STRING_RESOURCE, "NativesStringResource"); | 1327 sink_->Put(kNativesStringResource, "NativesStringResource"); |
1268 sink_->PutSection(i, "NativesStringResourceEnd"); | 1328 sink_->PutSection(i, "NativesStringResourceEnd"); |
1269 bytes_processed_so_far_ += sizeof(resource); | 1329 bytes_processed_so_far_ += sizeof(resource); |
1270 return; | 1330 return; |
1271 } | 1331 } |
1272 } | 1332 } |
1273 } | 1333 } |
1274 // One of the strings in the natives cache should match the resource. We | 1334 // One of the strings in the natives cache should match the resource. We |
1275 // can't serialize any other kinds of external strings. | 1335 // can't serialize any other kinds of external strings. |
1276 UNREACHABLE(); | 1336 UNREACHABLE(); |
1277 } | 1337 } |
1278 | 1338 |
1279 | 1339 |
1280 void Serializer::ObjectSerializer::OutputRawData(Address up_to) { | 1340 void Serializer::ObjectSerializer::OutputRawData(Address up_to) { |
1281 Address object_start = object_->address(); | 1341 Address object_start = object_->address(); |
1282 int up_to_offset = static_cast<int>(up_to - object_start); | 1342 int up_to_offset = static_cast<int>(up_to - object_start); |
1283 int skipped = up_to_offset - bytes_processed_so_far_; | 1343 int skipped = up_to_offset - bytes_processed_so_far_; |
1284 // This assert will fail if the reloc info gives us the target_address_address | 1344 // This assert will fail if the reloc info gives us the target_address_address |
1285 // locations in a non-ascending order. Luckily that doesn't happen. | 1345 // locations in a non-ascending order. Luckily that doesn't happen. |
1286 ASSERT(skipped >= 0); | 1346 ASSERT(skipped >= 0); |
1287 if (skipped != 0) { | 1347 if (skipped != 0) { |
1288 Address base = object_start + bytes_processed_so_far_; | 1348 Address base = object_start + bytes_processed_so_far_; |
1289 #define RAW_CASE(index, length) \ | 1349 #define RAW_CASE(index, length) \ |
1290 if (skipped == length) { \ | 1350 if (skipped == length) { \ |
1291 sink_->PutSection(RAW_DATA_SERIALIZATION + index, "RawDataFixed"); \ | 1351 sink_->PutSection(kRawData + index, "RawDataFixed"); \ |
1292 } else /* NOLINT */ | 1352 } else /* NOLINT */ |
1293 COMMON_RAW_LENGTHS(RAW_CASE) | 1353 COMMON_RAW_LENGTHS(RAW_CASE) |
1294 #undef RAW_CASE | 1354 #undef RAW_CASE |
1295 { /* NOLINT */ | 1355 { /* NOLINT */ |
1296 sink_->Put(RAW_DATA_SERIALIZATION, "RawData"); | 1356 sink_->Put(kRawData, "RawData"); |
1297 sink_->PutInt(skipped, "length"); | 1357 sink_->PutInt(skipped, "length"); |
1298 } | 1358 } |
1299 for (int i = 0; i < skipped; i++) { | 1359 for (int i = 0; i < skipped; i++) { |
1300 unsigned int data = base[i]; | 1360 unsigned int data = base[i]; |
1301 sink_->PutSection(data, "Byte"); | 1361 sink_->PutSection(data, "Byte"); |
1302 } | 1362 } |
1303 bytes_processed_so_far_ += skipped; | 1363 bytes_processed_so_far_ += skipped; |
1304 } | 1364 } |
1305 } | 1365 } |
1306 | 1366 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1366 fullness_[space] = RoundUp(fullness_[space], Page::kPageSize); | 1426 fullness_[space] = RoundUp(fullness_[space], Page::kPageSize); |
1367 } | 1427 } |
1368 } | 1428 } |
1369 int allocation_address = fullness_[space]; | 1429 int allocation_address = fullness_[space]; |
1370 fullness_[space] = allocation_address + size; | 1430 fullness_[space] = allocation_address + size; |
1371 return allocation_address; | 1431 return allocation_address; |
1372 } | 1432 } |
1373 | 1433 |
1374 | 1434 |
1375 } } // namespace v8::internal | 1435 } } // namespace v8::internal |
OLD | NEW |