| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/snapshot.h" | 5 #include "vm/snapshot.h" |
| 6 | 6 |
| 7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
| 8 #include "vm/bootstrap.h" | 8 #include "vm/bootstrap.h" |
| 9 #include "vm/class_finalizer.h" | 9 #include "vm/class_finalizer.h" |
| 10 #include "vm/dart.h" | 10 #include "vm/dart.h" |
| (...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 | 702 |
| 703 int32_t InstructionsWriter::GetObjectOffsetFor(RawObject* raw_object) { | 703 int32_t InstructionsWriter::GetObjectOffsetFor(RawObject* raw_object) { |
| 704 intptr_t heap_size = raw_object->Size(); | 704 intptr_t heap_size = raw_object->Size(); |
| 705 intptr_t offset = next_object_offset_; | 705 intptr_t offset = next_object_offset_; |
| 706 next_object_offset_ += heap_size; | 706 next_object_offset_ += heap_size; |
| 707 objects_.Add(ObjectData(raw_object)); | 707 objects_.Add(ObjectData(raw_object)); |
| 708 return offset; | 708 return offset; |
| 709 } | 709 } |
| 710 | 710 |
| 711 | 711 |
| 712 static void EnsureIdentifier(char* label) { | 712 void InstructionsWriter::Write(WriteStream* clustered_stream, bool vm) { |
| 713 for (char c = *label; c != '\0'; c = *++label) { | |
| 714 if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || | |
| 715 ((c >= '0') && (c <= '9'))) { | |
| 716 continue; | |
| 717 } | |
| 718 *label = '_'; | |
| 719 } | |
| 720 } | |
| 721 | |
| 722 | |
| 723 void AssemblyInstructionsWriter::Write(uint8_t* vmisolate_buffer, | |
| 724 intptr_t vmisolate_length, | |
| 725 uint8_t* isolate_buffer, | |
| 726 intptr_t isolate_length) { | |
| 727 Thread* thread = Thread::Current(); | 713 Thread* thread = Thread::Current(); |
| 728 Zone* zone = thread->zone(); | 714 Zone* zone = thread->zone(); |
| 729 NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(), | 715 NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(), |
| 730 "WriteInstructions")); | 716 "WriteInstructions")); |
| 731 | 717 |
| 732 // Handlify collected raw pointers as building the names below | 718 // Handlify collected raw pointers as building the names below |
| 733 // will allocate on the Dart heap. | 719 // will allocate on the Dart heap. |
| 734 for (intptr_t i = 0; i < instructions_.length(); i++) { | 720 for (intptr_t i = 0; i < instructions_.length(); i++) { |
| 735 InstructionsData& data = instructions_[i]; | 721 InstructionsData& data = instructions_[i]; |
| 736 data.insns_ = &Instructions::Handle(zone, data.raw_insns_); | 722 data.insns_ = &Instructions::Handle(zone, data.raw_insns_); |
| 737 ASSERT(data.raw_code_ != NULL); | 723 ASSERT(data.raw_code_ != NULL); |
| 738 data.code_ = &Code::Handle(zone, data.raw_code_); | 724 data.code_ = &Code::Handle(zone, data.raw_code_); |
| 739 } | 725 } |
| 740 for (intptr_t i = 0; i < objects_.length(); i++) { | 726 for (intptr_t i = 0; i < objects_.length(); i++) { |
| 741 ObjectData& data = objects_[i]; | 727 ObjectData& data = objects_[i]; |
| 742 data.obj_ = &Object::Handle(zone, data.raw_obj_); | 728 data.obj_ = &Object::Handle(zone, data.raw_obj_); |
| 743 } | 729 } |
| 744 | 730 |
| 731 // Append the direct-mapped RO data objects after the clustered snapshot. |
| 732 WriteROData(clustered_stream); |
| 733 |
| 734 WriteText(clustered_stream, vm); |
| 735 } |
| 736 |
| 737 |
| 738 void InstructionsWriter::WriteROData(WriteStream* stream) { |
| 739 stream->Align(OS::kMaxPreferredCodeAlignment); |
| 740 |
| 741 // Heap page starts here. |
| 742 |
| 743 stream->WriteWord(next_object_offset_); // Data length. |
| 744 COMPILE_ASSERT(OS::kMaxPreferredCodeAlignment >= kObjectAlignment); |
| 745 stream->Align(OS::kMaxPreferredCodeAlignment); |
| 746 |
| 747 // Heap page objects start here. |
| 748 |
| 749 for (intptr_t i = 0; i < objects_.length(); i++) { |
| 750 const Object& obj = *objects_[i].obj_; |
| 751 |
| 752 NoSafepointScope no_safepoint; |
| 753 uword start = reinterpret_cast<uword>(obj.raw()) - kHeapObjectTag; |
| 754 uword end = start + obj.raw()->Size(); |
| 755 |
| 756 // Write object header with the mark and VM heap bits set. |
| 757 uword marked_tags = obj.raw()->ptr()->tags_; |
| 758 marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags); |
| 759 marked_tags = RawObject::MarkBit::update(true, marked_tags); |
| 760 stream->WriteWord(marked_tags); |
| 761 start += sizeof(uword); |
| 762 for (uword* cursor = reinterpret_cast<uword*>(start); |
| 763 cursor < reinterpret_cast<uword*>(end); cursor++) { |
| 764 stream->WriteWord(*cursor); |
| 765 } |
| 766 } |
| 767 } |
| 768 |
| 769 |
| 770 static void EnsureIdentifier(char* label) { |
| 771 for (char c = *label; c != '\0'; c = *++label) { |
| 772 if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || |
| 773 ((c >= '0') && (c <= '9'))) { |
| 774 continue; |
| 775 } |
| 776 *label = '_'; |
| 777 } |
| 778 } |
| 779 |
| 780 |
| 781 void AssemblyInstructionsWriter::WriteText(WriteStream* clustered_stream, |
| 782 bool vm) { |
| 783 Zone* zone = Thread::Current()->zone(); |
| 784 |
| 785 const char* instructions_symbol = |
| 786 vm ? "_kDartVmSnapshotInstructions" : "_kDartIsolateSnapshotInstructions"; |
| 745 assembly_stream_.Print(".text\n"); | 787 assembly_stream_.Print(".text\n"); |
| 746 assembly_stream_.Print(".globl _kInstructionsSnapshot\n"); | 788 assembly_stream_.Print(".globl %s\n", instructions_symbol); |
| 747 // Start snapshot at page boundary. | 789 // Start snapshot at page boundary. |
| 748 ASSERT(VirtualMemory::PageSize() >= OS::kMaxPreferredCodeAlignment); | 790 ASSERT(VirtualMemory::PageSize() >= OS::kMaxPreferredCodeAlignment); |
| 749 assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize()); | 791 assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize()); |
| 750 assembly_stream_.Print("_kInstructionsSnapshot:\n"); | 792 assembly_stream_.Print("%s:\n", instructions_symbol); |
| 751 | 793 |
| 752 // This head also provides the gap to make the instructions snapshot | 794 // This head also provides the gap to make the instructions snapshot |
| 753 // look like a HeapPage. | 795 // look like a HeapPage. |
| 754 intptr_t instructions_length = next_offset_; | 796 intptr_t instructions_length = next_offset_; |
| 755 WriteWordLiteralText(instructions_length); | 797 WriteWordLiteralText(instructions_length); |
| 756 intptr_t header_words = InstructionsSnapshot::kHeaderSize / sizeof(uword); | 798 intptr_t header_words = InstructionsSnapshot::kHeaderSize / sizeof(uword); |
| 757 for (intptr_t i = 1; i < header_words; i++) { | 799 for (intptr_t i = 1; i < header_words; i++) { |
| 758 WriteWordLiteralText(0); | 800 WriteWordLiteralText(0); |
| 759 } | 801 } |
| 760 | 802 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 822 ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t))); | 864 ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t))); |
| 823 ASSERT(Utils::IsAligned(entry, sizeof(uint64_t))); | 865 ASSERT(Utils::IsAligned(entry, sizeof(uint64_t))); |
| 824 ASSERT(Utils::IsAligned(end, sizeof(uint64_t))); | 866 ASSERT(Utils::IsAligned(end, sizeof(uint64_t))); |
| 825 | 867 |
| 826 for (uword* cursor = reinterpret_cast<uword*>(entry); | 868 for (uword* cursor = reinterpret_cast<uword*>(entry); |
| 827 cursor < reinterpret_cast<uword*>(end); cursor++) { | 869 cursor < reinterpret_cast<uword*>(end); cursor++) { |
| 828 WriteWordLiteralText(*cursor); | 870 WriteWordLiteralText(*cursor); |
| 829 } | 871 } |
| 830 } | 872 } |
| 831 } | 873 } |
| 874 |
| 875 |
| 832 #if defined(TARGET_OS_LINUX) | 876 #if defined(TARGET_OS_LINUX) |
| 833 assembly_stream_.Print(".section .rodata\n"); | 877 assembly_stream_.Print(".section .rodata\n"); |
| 834 #elif defined(TARGET_OS_MACOS) | 878 #elif defined(TARGET_OS_MACOS) |
| 835 assembly_stream_.Print(".const\n"); | 879 assembly_stream_.Print(".const\n"); |
| 836 #else | 880 #else |
| 837 // Unsupported platform. | 881 // Unsupported platform. |
| 838 UNREACHABLE(); | 882 UNREACHABLE(); |
| 839 #endif | 883 #endif |
| 840 assembly_stream_.Print(".globl _kDataSnapshot\n"); | 884 |
| 841 // Start snapshot at page boundary. | 885 const char* data_symbol = |
| 842 assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize()); | 886 vm ? "_kDartVmSnapshotData" : "_kDartIsolateSnapshotData"; |
| 843 assembly_stream_.Print("_kDataSnapshot:\n"); | 887 assembly_stream_.Print(".globl %s\n", data_symbol); |
| 844 WriteWordLiteralData(next_object_offset_); // Data length. | |
| 845 COMPILE_ASSERT(OS::kMaxPreferredCodeAlignment >= kObjectAlignment); | |
| 846 assembly_stream_.Print(".balign %" Pd ", 0\n", | 888 assembly_stream_.Print(".balign %" Pd ", 0\n", |
| 847 OS::kMaxPreferredCodeAlignment); | 889 OS::kMaxPreferredCodeAlignment); |
| 848 | 890 assembly_stream_.Print("%s:\n", data_symbol); |
| 849 for (intptr_t i = 0; i < objects_.length(); i++) { | 891 uint8_t* buffer = clustered_stream->buffer(); |
| 850 const Object& obj = *objects_[i].obj_; | 892 intptr_t length = clustered_stream->bytes_written(); |
| 851 assembly_stream_.Print("Precompiled_Obj_%d:\n", i); | 893 for (intptr_t i = 0; i < length; i++) { |
| 852 | 894 assembly_stream_.Print(".byte %" Pd "\n", buffer[i]); |
| 853 NoSafepointScope no_safepoint; | |
| 854 uword start = reinterpret_cast<uword>(obj.raw()) - kHeapObjectTag; | |
| 855 uword end = start + obj.raw()->Size(); | |
| 856 | |
| 857 // Write object header with the mark and VM heap bits set. | |
| 858 uword marked_tags = obj.raw()->ptr()->tags_; | |
| 859 marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags); | |
| 860 marked_tags = RawObject::MarkBit::update(true, marked_tags); | |
| 861 WriteWordLiteralData(marked_tags); | |
| 862 start += sizeof(uword); | |
| 863 for (uword* cursor = reinterpret_cast<uword*>(start); | |
| 864 cursor < reinterpret_cast<uword*>(end); cursor++) { | |
| 865 WriteWordLiteralData(*cursor); | |
| 866 } | |
| 867 } | |
| 868 | |
| 869 | |
| 870 assembly_stream_.Print(".globl _kVmIsolateSnapshot\n"); | |
| 871 assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize()); | |
| 872 assembly_stream_.Print("_kVmIsolateSnapshot:\n"); | |
| 873 for (intptr_t i = 0; i < vmisolate_length; i++) { | |
| 874 assembly_stream_.Print(".byte %" Pd "\n", vmisolate_buffer[i]); | |
| 875 } | |
| 876 | |
| 877 assembly_stream_.Print(".globl _kIsolateSnapshot\n"); | |
| 878 assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize()); | |
| 879 assembly_stream_.Print("_kIsolateSnapshot:\n"); | |
| 880 for (intptr_t i = 0; i < isolate_length; i++) { | |
| 881 assembly_stream_.Print(".byte %" Pd "\n", isolate_buffer[i]); | |
| 882 } | 895 } |
| 883 } | 896 } |
| 884 | 897 |
| 885 | 898 |
| 886 void BlobInstructionsWriter::Write(uint8_t* vmisolate_buffer, | 899 void BlobInstructionsWriter::WriteText(WriteStream* clustered_stream, bool vm) { |
| 887 intptr_t vmisolate_len, | 900 // This header provides the gap to make the instructions snapshot look like a |
| 888 uint8_t* isolate_buffer, | 901 // HeapPage. |
| 889 intptr_t isolate_length) { | |
| 890 Thread* thread = Thread::Current(); | |
| 891 Zone* zone = thread->zone(); | |
| 892 NOT_IN_PRODUCT(TimelineDurationScope tds(thread, Timeline::GetIsolateStream(), | |
| 893 "WriteInstructions")); | |
| 894 | |
| 895 // Handlify collected raw pointers as building the names below | |
| 896 // will allocate on the Dart heap. | |
| 897 for (intptr_t i = 0; i < instructions_.length(); i++) { | |
| 898 InstructionsData& data = instructions_[i]; | |
| 899 data.insns_ = &Instructions::Handle(zone, data.raw_insns_); | |
| 900 ASSERT(data.raw_code_ != NULL); | |
| 901 data.code_ = &Code::Handle(zone, data.raw_code_); | |
| 902 } | |
| 903 for (intptr_t i = 0; i < objects_.length(); i++) { | |
| 904 ObjectData& data = objects_[i]; | |
| 905 data.obj_ = &Object::Handle(zone, data.raw_obj_); | |
| 906 } | |
| 907 | |
| 908 // This head also provides the gap to make the instructions snapshot | |
| 909 // look like a HeapPage. | |
| 910 intptr_t instructions_length = next_offset_; | 902 intptr_t instructions_length = next_offset_; |
| 911 instructions_blob_stream_.WriteWord(instructions_length); | 903 instructions_blob_stream_.WriteWord(instructions_length); |
| 912 intptr_t header_words = InstructionsSnapshot::kHeaderSize / sizeof(uword); | 904 intptr_t header_words = InstructionsSnapshot::kHeaderSize / sizeof(uword); |
| 913 for (intptr_t i = 1; i < header_words; i++) { | 905 for (intptr_t i = 1; i < header_words; i++) { |
| 914 instructions_blob_stream_.WriteWord(0); | 906 instructions_blob_stream_.WriteWord(0); |
| 915 } | 907 } |
| 916 | 908 |
| 917 for (intptr_t i = 0; i < instructions_.length(); i++) { | 909 for (intptr_t i = 0; i < instructions_.length(); i++) { |
| 918 const Instructions& insns = *instructions_[i].insns_; | 910 const Instructions& insns = *instructions_[i].insns_; |
| 919 | 911 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 953 ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t))); | 945 ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t))); |
| 954 ASSERT(Utils::IsAligned(entry, sizeof(uint64_t))); | 946 ASSERT(Utils::IsAligned(entry, sizeof(uint64_t))); |
| 955 ASSERT(Utils::IsAligned(end, sizeof(uint64_t))); | 947 ASSERT(Utils::IsAligned(end, sizeof(uint64_t))); |
| 956 | 948 |
| 957 for (uword* cursor = reinterpret_cast<uword*>(entry); | 949 for (uword* cursor = reinterpret_cast<uword*>(entry); |
| 958 cursor < reinterpret_cast<uword*>(end); cursor++) { | 950 cursor < reinterpret_cast<uword*>(end); cursor++) { |
| 959 instructions_blob_stream_.WriteWord(*cursor); | 951 instructions_blob_stream_.WriteWord(*cursor); |
| 960 } | 952 } |
| 961 } | 953 } |
| 962 } | 954 } |
| 963 | |
| 964 rodata_blob_stream_.WriteWord(next_object_offset_); // Data length. | |
| 965 COMPILE_ASSERT(OS::kMaxPreferredCodeAlignment >= kObjectAlignment); | |
| 966 while (!Utils::IsAligned(rodata_blob_stream_.bytes_written(), | |
| 967 OS::kMaxPreferredCodeAlignment)) { | |
| 968 rodata_blob_stream_.WriteWord(0); | |
| 969 } | |
| 970 | |
| 971 for (intptr_t i = 0; i < objects_.length(); i++) { | |
| 972 const Object& obj = *objects_[i].obj_; | |
| 973 | |
| 974 NoSafepointScope no_safepoint; | |
| 975 uword start = reinterpret_cast<uword>(obj.raw()) - kHeapObjectTag; | |
| 976 uword end = start + obj.raw()->Size(); | |
| 977 | |
| 978 // Write object header with the mark and VM heap bits set. | |
| 979 uword marked_tags = obj.raw()->ptr()->tags_; | |
| 980 marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags); | |
| 981 marked_tags = RawObject::MarkBit::update(true, marked_tags); | |
| 982 rodata_blob_stream_.WriteWord(marked_tags); | |
| 983 start += sizeof(uword); | |
| 984 for (uword* cursor = reinterpret_cast<uword*>(start); | |
| 985 cursor < reinterpret_cast<uword*>(end); cursor++) { | |
| 986 rodata_blob_stream_.WriteWord(*cursor); | |
| 987 } | |
| 988 } | |
| 989 } | 955 } |
| 990 | 956 |
| 991 | 957 |
| 992 uword InstructionsReader::GetInstructionsAt(int32_t offset) { | 958 RawInstructions* InstructionsReader::GetInstructionsAt(int32_t offset) { |
| 993 ASSERT(Utils::IsAligned(offset, OS::PreferredCodeAlignment())); | 959 ASSERT(Utils::IsAligned(offset, OS::PreferredCodeAlignment())); |
| 994 return reinterpret_cast<uword>(instructions_buffer_) + offset; | 960 |
| 961 RawInstructions* result = reinterpret_cast<RawInstructions*>( |
| 962 reinterpret_cast<uword>(instructions_buffer_) + offset + kHeapObjectTag); |
| 963 ASSERT(result->IsInstructions()); |
| 964 ASSERT(result->IsMarked()); |
| 965 |
| 966 return result; |
| 995 } | 967 } |
| 996 | 968 |
| 997 | 969 |
| 998 RawObject* InstructionsReader::GetObjectAt(int32_t offset) { | 970 RawObject* InstructionsReader::GetObjectAt(int32_t offset) { |
| 999 ASSERT(Utils::IsAligned(offset, kWordSize)); | 971 ASSERT(Utils::IsAligned(offset, kWordSize)); |
| 1000 | 972 |
| 1001 RawObject* result = reinterpret_cast<RawObject*>( | 973 RawObject* result = reinterpret_cast<RawObject*>( |
| 1002 reinterpret_cast<uword>(data_buffer_) + offset + kHeapObjectTag); | 974 reinterpret_cast<uword>(data_buffer_) + offset + kHeapObjectTag); |
| 1003 ASSERT(result->IsMarked()); | 975 ASSERT(result->IsMarked()); |
| 1004 | 976 |
| (...skipping 957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1962 NoSafepointScope no_safepoint; | 1934 NoSafepointScope no_safepoint; |
| 1963 WriteObject(obj.raw()); | 1935 WriteObject(obj.raw()); |
| 1964 } else { | 1936 } else { |
| 1965 FreeBuffer(); | 1937 FreeBuffer(); |
| 1966 ThrowException(exception_type(), exception_msg()); | 1938 ThrowException(exception_type(), exception_msg()); |
| 1967 } | 1939 } |
| 1968 } | 1940 } |
| 1969 | 1941 |
| 1970 | 1942 |
| 1971 } // namespace dart | 1943 } // namespace dart |
| OLD | NEW |