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" |
11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
12 #include "vm/dwarf.h" | |
13 #include "vm/exceptions.h" | 12 #include "vm/exceptions.h" |
14 #include "vm/heap.h" | 13 #include "vm/heap.h" |
15 #include "vm/lockers.h" | 14 #include "vm/lockers.h" |
16 #include "vm/longjump.h" | 15 #include "vm/longjump.h" |
17 #include "vm/object.h" | 16 #include "vm/object.h" |
18 #include "vm/object_store.h" | 17 #include "vm/object_store.h" |
19 #include "vm/snapshot_ids.h" | 18 #include "vm/snapshot_ids.h" |
20 #include "vm/stub_code.h" | 19 #include "vm/stub_code.h" |
21 #include "vm/symbols.h" | 20 #include "vm/symbols.h" |
22 #include "vm/timeline.h" | 21 #include "vm/timeline.h" |
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 stream->WriteWord(marked_tags); | 765 stream->WriteWord(marked_tags); |
767 start += sizeof(uword); | 766 start += sizeof(uword); |
768 for (uword* cursor = reinterpret_cast<uword*>(start); | 767 for (uword* cursor = reinterpret_cast<uword*>(start); |
769 cursor < reinterpret_cast<uword*>(end); cursor++) { | 768 cursor < reinterpret_cast<uword*>(end); cursor++) { |
770 stream->WriteWord(*cursor); | 769 stream->WriteWord(*cursor); |
771 } | 770 } |
772 } | 771 } |
773 } | 772 } |
774 | 773 |
775 | 774 |
776 AssemblyImageWriter::AssemblyImageWriter(uint8_t** assembly_buffer, | |
777 ReAlloc alloc, | |
778 intptr_t initial_size) | |
779 : ImageWriter(), | |
780 assembly_stream_(assembly_buffer, alloc, initial_size), | |
781 text_size_(0), | |
782 dwarf_(NULL) { | |
783 #if defined(DART_PRECOMPILER) | |
784 Zone* zone = Thread::Current()->zone(); | |
785 dwarf_ = new (zone) Dwarf(zone, &assembly_stream_); | |
786 #endif | |
787 } | |
788 | |
789 | |
790 void AssemblyImageWriter::Finalize() { | |
791 #ifdef DART_PRECOMPILER | |
792 dwarf_->Write(); | |
793 #endif | |
794 } | |
795 | |
796 | |
797 static void EnsureIdentifier(char* label) { | 775 static void EnsureIdentifier(char* label) { |
798 for (char c = *label; c != '\0'; c = *++label) { | 776 for (char c = *label; c != '\0'; c = *++label) { |
799 if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || | 777 if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || |
800 ((c >= '0') && (c <= '9'))) { | 778 ((c >= '0') && (c <= '9'))) { |
801 continue; | 779 continue; |
802 } | 780 } |
803 *label = '_'; | 781 *label = '_'; |
804 } | 782 } |
805 } | 783 } |
806 | 784 |
807 | 785 |
808 void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { | 786 void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { |
809 Zone* zone = Thread::Current()->zone(); | 787 Zone* zone = Thread::Current()->zone(); |
810 | 788 |
811 const char* instructions_symbol = | 789 const char* instructions_symbol = |
812 vm ? "_kDartVmSnapshotInstructions" : "_kDartIsolateSnapshotInstructions"; | 790 vm ? "_kDartVmSnapshotInstructions" : "_kDartIsolateSnapshotInstructions"; |
813 assembly_stream_.Print(".text\n"); | 791 assembly_stream_.Print(".text\n"); |
814 assembly_stream_.Print(".globl %s\n", instructions_symbol); | 792 assembly_stream_.Print(".globl %s\n", instructions_symbol); |
815 | |
816 // Start snapshot at page boundary. | 793 // Start snapshot at page boundary. |
817 ASSERT(VirtualMemory::PageSize() >= OS::kMaxPreferredCodeAlignment); | 794 ASSERT(VirtualMemory::PageSize() >= OS::kMaxPreferredCodeAlignment); |
818 assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize()); | 795 assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize()); |
819 assembly_stream_.Print("%s:\n", instructions_symbol); | 796 assembly_stream_.Print("%s:\n", instructions_symbol); |
820 | 797 |
821 // This head also provides the gap to make the instructions snapshot | 798 // This head also provides the gap to make the instructions snapshot |
822 // look like a HeapPage. | 799 // look like a HeapPage. |
823 intptr_t instructions_length = next_offset_; | 800 intptr_t instructions_length = next_offset_; |
824 WriteWordLiteralText(instructions_length); | 801 WriteWordLiteralText(instructions_length); |
825 intptr_t header_words = Image::kHeaderSize / sizeof(uword); | 802 intptr_t header_words = Image::kHeaderSize / sizeof(uword); |
826 for (intptr_t i = 1; i < header_words; i++) { | 803 for (intptr_t i = 1; i < header_words; i++) { |
827 WriteWordLiteralText(0); | 804 WriteWordLiteralText(0); |
828 } | 805 } |
829 | 806 |
830 FrameUnwindPrologue(); | |
831 | |
832 Object& owner = Object::Handle(zone); | 807 Object& owner = Object::Handle(zone); |
833 String& str = String::Handle(zone); | 808 String& str = String::Handle(zone); |
834 | 809 |
835 for (intptr_t i = 0; i < instructions_.length(); i++) { | 810 for (intptr_t i = 0; i < instructions_.length(); i++) { |
836 const Instructions& insns = *instructions_[i].insns_; | 811 const Instructions& insns = *instructions_[i].insns_; |
837 const Code& code = *instructions_[i].code_; | 812 const Code& code = *instructions_[i].code_; |
838 | 813 |
839 ASSERT(insns.raw()->Size() % sizeof(uint64_t) == 0); | 814 ASSERT(insns.raw()->Size() % sizeof(uint64_t) == 0); |
840 | 815 |
841 // 1. Write from the header to the entry point. | 816 // 1. Write from the header to the entry point. |
842 { | 817 { |
843 NoSafepointScope no_safepoint; | 818 NoSafepointScope no_safepoint; |
844 | 819 |
845 uword beginning = reinterpret_cast<uword>(insns.raw_ptr()); | 820 uword beginning = reinterpret_cast<uword>(insns.raw_ptr()); |
846 uword entry = beginning + Instructions::HeaderSize(); | 821 uword entry = beginning + Instructions::HeaderSize(); |
847 | 822 |
| 823 ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t))); |
| 824 ASSERT(Utils::IsAligned(entry, sizeof(uint64_t))); |
| 825 |
848 // Write Instructions with the mark and VM heap bits set. | 826 // Write Instructions with the mark and VM heap bits set. |
849 uword marked_tags = insns.raw_ptr()->tags_; | 827 uword marked_tags = insns.raw_ptr()->tags_; |
850 marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags); | 828 marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags); |
851 marked_tags = RawObject::MarkBit::update(true, marked_tags); | 829 marked_tags = RawObject::MarkBit::update(true, marked_tags); |
852 | 830 |
853 WriteWordLiteralText(marked_tags); | 831 WriteWordLiteralText(marked_tags); |
854 beginning += sizeof(uword); | 832 beginning += sizeof(uword); |
855 | 833 |
856 WriteByteSequence(beginning, entry); | 834 for (uword* cursor = reinterpret_cast<uword*>(beginning); |
| 835 cursor < reinterpret_cast<uword*>(entry); cursor++) { |
| 836 WriteWordLiteralText(*cursor); |
| 837 } |
857 } | 838 } |
858 | 839 |
859 // 2. Write a label at the entry point. | 840 // 2. Write a label at the entry point. |
860 // Linux's perf uses these labels. | |
861 owner = code.owner(); | 841 owner = code.owner(); |
862 if (owner.IsNull()) { | 842 if (owner.IsNull()) { |
863 const char* name = StubCode::NameOfStub(insns.UncheckedEntryPoint()); | 843 const char* name = StubCode::NameOfStub(insns.UncheckedEntryPoint()); |
864 assembly_stream_.Print("Precompiled_Stub_%s:\n", name); | 844 assembly_stream_.Print("Precompiled_Stub_%s:\n", name); |
865 } else if (owner.IsClass()) { | 845 } else if (owner.IsClass()) { |
866 str = Class::Cast(owner).Name(); | 846 str = Class::Cast(owner).Name(); |
867 const char* name = str.ToCString(); | 847 const char* name = str.ToCString(); |
868 EnsureIdentifier(const_cast<char*>(name)); | 848 EnsureIdentifier(const_cast<char*>(name)); |
869 assembly_stream_.Print("Precompiled_AllocationStub_%s_%" Pd ":\n", name, | 849 assembly_stream_.Print("Precompiled_AllocationStub_%s_%" Pd ":\n", name, |
870 i); | 850 i); |
871 } else if (owner.IsFunction()) { | 851 } else if (owner.IsFunction()) { |
872 const char* name = Function::Cast(owner).ToQualifiedCString(); | 852 const char* name = Function::Cast(owner).ToQualifiedCString(); |
873 EnsureIdentifier(const_cast<char*>(name)); | 853 EnsureIdentifier(const_cast<char*>(name)); |
874 assembly_stream_.Print("Precompiled_%s_%" Pd ":\n", name, i); | 854 assembly_stream_.Print("Precompiled_%s_%" Pd ":\n", name, i); |
875 } else { | 855 } else { |
876 UNREACHABLE(); | 856 UNREACHABLE(); |
877 } | 857 } |
878 | 858 |
879 #ifdef DART_PRECOMPILER | |
880 // Create a label for use by DWARF. | |
881 intptr_t dwarf_index = dwarf_->AddCode(code); | |
882 assembly_stream_.Print(".Lcode%" Pd ":\n", dwarf_index); | |
883 #endif | |
884 | |
885 { | 859 { |
886 // 3. Write from the entry point to the end. | 860 // 3. Write from the entry point to the end. |
887 NoSafepointScope no_safepoint; | 861 NoSafepointScope no_safepoint; |
888 uword beginning = reinterpret_cast<uword>(insns.raw()) - kHeapObjectTag; | 862 uword beginning = reinterpret_cast<uword>(insns.raw()) - kHeapObjectTag; |
889 uword entry = beginning + Instructions::HeaderSize(); | 863 uword entry = beginning + Instructions::HeaderSize(); |
890 uword payload_size = insns.Size(); | 864 uword payload_size = insns.Size(); |
891 payload_size = Utils::RoundUp(payload_size, OS::PreferredCodeAlignment()); | 865 payload_size = Utils::RoundUp(payload_size, OS::PreferredCodeAlignment()); |
892 uword end = entry + payload_size; | 866 uword end = entry + payload_size; |
893 | 867 |
894 ASSERT(Utils::IsAligned(beginning, sizeof(uword))); | 868 ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t))); |
895 ASSERT(Utils::IsAligned(entry, sizeof(uword))); | 869 ASSERT(Utils::IsAligned(entry, sizeof(uint64_t))); |
896 ASSERT(Utils::IsAligned(end, sizeof(uword))); | 870 ASSERT(Utils::IsAligned(end, sizeof(uint64_t))); |
897 | 871 |
898 WriteByteSequence(entry, end); | 872 for (uword* cursor = reinterpret_cast<uword*>(entry); |
| 873 cursor < reinterpret_cast<uword*>(end); cursor++) { |
| 874 WriteWordLiteralText(*cursor); |
| 875 } |
899 } | 876 } |
900 } | 877 } |
901 | 878 |
902 FrameUnwindEpilogue(); | |
903 | 879 |
904 #if defined(HOST_OS_LINUX) | 880 #if defined(HOST_OS_LINUX) |
905 assembly_stream_.Print(".section .rodata\n"); | 881 assembly_stream_.Print(".section .rodata\n"); |
906 #elif defined(HOST_OS_MACOS) | 882 #elif defined(HOST_OS_MACOS) |
907 assembly_stream_.Print(".const\n"); | 883 assembly_stream_.Print(".const\n"); |
908 #else | 884 #else |
909 // Unsupported platform. | 885 // Unsupported platform. |
910 UNREACHABLE(); | 886 UNREACHABLE(); |
911 #endif | 887 #endif |
912 | 888 |
913 const char* data_symbol = | 889 const char* data_symbol = |
914 vm ? "_kDartVmSnapshotData" : "_kDartIsolateSnapshotData"; | 890 vm ? "_kDartVmSnapshotData" : "_kDartIsolateSnapshotData"; |
915 assembly_stream_.Print(".globl %s\n", data_symbol); | 891 assembly_stream_.Print(".globl %s\n", data_symbol); |
916 assembly_stream_.Print(".balign %" Pd ", 0\n", | 892 assembly_stream_.Print(".balign %" Pd ", 0\n", |
917 OS::kMaxPreferredCodeAlignment); | 893 OS::kMaxPreferredCodeAlignment); |
918 assembly_stream_.Print("%s:\n", data_symbol); | 894 assembly_stream_.Print("%s:\n", data_symbol); |
919 uword buffer = reinterpret_cast<uword>(clustered_stream->buffer()); | 895 uint8_t* buffer = clustered_stream->buffer(); |
920 intptr_t length = clustered_stream->bytes_written(); | 896 intptr_t length = clustered_stream->bytes_written(); |
921 WriteByteSequence(buffer, buffer + length); | 897 for (intptr_t i = 0; i < length; i++) { |
922 } | 898 assembly_stream_.Print(".byte %" Pd "\n", buffer[i]); |
923 | |
924 | |
925 void AssemblyImageWriter::FrameUnwindPrologue() { | |
926 // Creates DWARF's .debug_frame | |
927 // CFI = Call frame information | |
928 // CFA = Canonical frame address | |
929 assembly_stream_.Print(".cfi_startproc\n"); | |
930 | |
931 #if defined(TARGET_ARCH_X64) | |
932 assembly_stream_.Print(".cfi_def_cfa rbp, 0\n"); // CFA is fp+0 | |
933 assembly_stream_.Print(".cfi_offset rbp, 0\n"); // saved fp is *(CFA+0) | |
934 assembly_stream_.Print(".cfi_offset rip, 8\n"); // saved pc is *(CFA+8) | |
935 // saved sp is CFA+16 | |
936 // Should be ".cfi_value_offset rsp, 16", but requires gcc newer than late | |
937 // 2016 and not supported by Android's libunwind. | |
938 // DW_CFA_expression 0x10 | |
939 // uleb128 register (rsp) 7 (DWARF register number) | |
940 // uleb128 size of operation 2 | |
941 // DW_OP_plus_uconst 0x23 | |
942 // uleb128 addend 16 | |
943 assembly_stream_.Print(".cfi_escape 0x10, 31, 2, 0x23, 16\n"); | |
944 | |
945 #elif defined(TARGET_ARCH_ARM64) | |
946 COMPILE_ASSERT(FP == R29); | |
947 COMPILE_ASSERT(LR == R30); | |
948 assembly_stream_.Print(".cfi_def_cfa x29, 0\n"); // CFA is fp+0 | |
949 assembly_stream_.Print(".cfi_offset x29, 0\n"); // saved fp is *(CFA+0) | |
950 assembly_stream_.Print(".cfi_offset x30, 8\n"); // saved pc is *(CFA+8) | |
951 // saved sp is CFA+16 | |
952 // Should be ".cfi_value_offset sp, 16", but requires gcc newer than late | |
953 // 2016 and not supported by Android's libunwind. | |
954 // DW_CFA_expression 0x10 | |
955 // uleb128 register (x31) 31 | |
956 // uleb128 size of operation 2 | |
957 // DW_OP_plus_uconst 0x23 | |
958 // uleb128 addend 16 | |
959 assembly_stream_.Print(".cfi_escape 0x10, 31, 2, 0x23, 16\n"); | |
960 | |
961 #elif defined(TARGET_ARCH_ARM) | |
962 #if defined(TARGET_ABI_EABI) | |
963 COMPILE_ASSERT(FP == R11); | |
964 assembly_stream_.Print(".cfi_def_cfa r11, 0\n"); // CFA is fp+0 | |
965 assembly_stream_.Print(".cfi_offset r11, 0\n"); // saved fp is *(CFA+0) | |
966 #elif defined(TARGET_ABI_IOS) | |
967 COMPILE_ASSERT(FP == R7); | |
968 assembly_stream_.Print(".cfi_def_cfa r7, 0\n"); // CFA is fp+0 | |
969 assembly_stream_.Print(".cfi_offset r7, 0\n"); // saved fp is *(CFA+0) | |
970 #endif | |
971 assembly_stream_.Print(".cfi_offset lr, 4\n"); // saved pc is *(CFA+4) | |
972 // saved sp is CFA+8 | |
973 // Should be ".cfi_value_offset sp, 8", but requires gcc newer than late | |
974 // 2016 and not supported by Android's libunwind. | |
975 // DW_CFA_expression 0x10 | |
976 // uleb128 register (sp) 13 | |
977 // uleb128 size of operation 2 | |
978 // DW_OP_plus_uconst 0x23 | |
979 // uleb128 addend 8 | |
980 assembly_stream_.Print(".cfi_escape 0x10, 13, 2, 0x23, 8\n"); | |
981 | |
982 // libunwind on ARM may use .ARM.exidx instead of .debug_frame | |
983 #if defined(TARGET_ABI_EABI) | |
984 COMPILE_ASSERT(FP == R11); | |
985 assembly_stream_.Print(".fnstart\n"); | |
986 assembly_stream_.Print(".save {r11, lr}\n"); | |
987 assembly_stream_.Print(".setfp r11, sp, #0\n"); | |
988 #elif defined(TARGET_ABI_IOS) | |
989 COMPILE_ASSERT(FP == R7); | |
990 assembly_stream_.Print(".fnstart\n"); | |
991 assembly_stream_.Print(".save {r7, lr}\n"); | |
992 assembly_stream_.Print(".setfp r7, sp, #0\n"); | |
993 #endif | |
994 | |
995 #elif defined(TARGET_ARCH_MIPS) | |
996 COMPILE_ASSERT(FP == R30); | |
997 COMPILE_ASSERT(RA == R31); | |
998 assembly_stream_.Print(".cfi_def_cfa r30, 0\n"); // CFA is fp+0 | |
999 assembly_stream_.Print(".cfi_offset r30, 0\n"); // saved fp is *(CFA+0) | |
1000 assembly_stream_.Print(".cfi_offset r31, 4\n"); // saved pc is *(CFA+4) | |
1001 // saved sp is CFA+16 | |
1002 // Should be ".cfi_value_offset sp, 8", but requires gcc newer than late | |
1003 // 2016 and not supported by Android's libunwind. | |
1004 // DW_CFA_expression 0x10 | |
1005 // uleb128 register (sp) 29 | |
1006 // uleb128 size of operation 2 | |
1007 // DW_OP_plus_uconst 0x23 | |
1008 // uleb128 addend 8 | |
1009 assembly_stream_.Print(".cfi_escape 0x10, 29, 2, 0x23, 8\n"); | |
1010 #endif | |
1011 } | |
1012 | |
1013 | |
1014 void AssemblyImageWriter::FrameUnwindEpilogue() { | |
1015 #if defined(TARGET_ARCH_ARM) | |
1016 assembly_stream_.Print(".fnend\n"); | |
1017 #endif | |
1018 assembly_stream_.Print(".cfi_endproc\n"); | |
1019 } | |
1020 | |
1021 | |
1022 void AssemblyImageWriter::WriteByteSequence(uword start, uword end) { | |
1023 for (uword* cursor = reinterpret_cast<uword*>(start); | |
1024 cursor < reinterpret_cast<uword*>(end); cursor++) { | |
1025 WriteWordLiteralText(*cursor); | |
1026 } | 899 } |
1027 } | 900 } |
1028 | 901 |
1029 | 902 |
1030 void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { | 903 void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) { |
1031 // This header provides the gap to make the instructions snapshot look like a | 904 // This header provides the gap to make the instructions snapshot look like a |
1032 // HeapPage. | 905 // HeapPage. |
1033 intptr_t instructions_length = next_offset_; | 906 intptr_t instructions_length = next_offset_; |
1034 instructions_blob_stream_.WriteWord(instructions_length); | 907 instructions_blob_stream_.WriteWord(instructions_length); |
1035 intptr_t header_words = Image::kHeaderSize / sizeof(uword); | 908 intptr_t header_words = Image::kHeaderSize / sizeof(uword); |
1036 for (intptr_t i = 1; i < header_words; i++) { | 909 for (intptr_t i = 1; i < header_words; i++) { |
1037 instructions_blob_stream_.WriteWord(0); | 910 instructions_blob_stream_.WriteWord(0); |
1038 } | 911 } |
1039 | 912 |
1040 NoSafepointScope no_safepoint; | |
1041 for (intptr_t i = 0; i < instructions_.length(); i++) { | 913 for (intptr_t i = 0; i < instructions_.length(); i++) { |
1042 const Instructions& insns = *instructions_[i].insns_; | 914 const Instructions& insns = *instructions_[i].insns_; |
1043 | 915 |
1044 uword beginning = reinterpret_cast<uword>(insns.raw_ptr()); | 916 // 1. Write from the header to the entry point. |
1045 uword entry = beginning + Instructions::HeaderSize(); | 917 { |
1046 uword payload_size = insns.Size(); | 918 NoSafepointScope no_safepoint; |
1047 payload_size = Utils::RoundUp(payload_size, OS::PreferredCodeAlignment()); | |
1048 uword end = entry + payload_size; | |
1049 | 919 |
1050 ASSERT(Utils::IsAligned(beginning, sizeof(uword))); | 920 uword beginning = reinterpret_cast<uword>(insns.raw_ptr()); |
1051 ASSERT(Utils::IsAligned(entry, sizeof(uword))); | 921 uword entry = beginning + Instructions::HeaderSize(); |
1052 | 922 |
1053 // Write Instructions with the mark and VM heap bits set. | 923 ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t))); |
1054 uword marked_tags = insns.raw_ptr()->tags_; | 924 ASSERT(Utils::IsAligned(entry, sizeof(uint64_t))); |
1055 marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags); | |
1056 marked_tags = RawObject::MarkBit::update(true, marked_tags); | |
1057 | 925 |
1058 instructions_blob_stream_.WriteWord(marked_tags); | 926 // Write Instructions with the mark and VM heap bits set. |
1059 beginning += sizeof(uword); | 927 uword marked_tags = insns.raw_ptr()->tags_; |
| 928 marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags); |
| 929 marked_tags = RawObject::MarkBit::update(true, marked_tags); |
1060 | 930 |
1061 for (uword* cursor = reinterpret_cast<uword*>(beginning); | 931 instructions_blob_stream_.WriteWord(marked_tags); |
1062 cursor < reinterpret_cast<uword*>(end); cursor++) { | 932 beginning += sizeof(uword); |
1063 instructions_blob_stream_.WriteWord(*cursor); | 933 |
| 934 for (uword* cursor = reinterpret_cast<uword*>(beginning); |
| 935 cursor < reinterpret_cast<uword*>(entry); cursor++) { |
| 936 instructions_blob_stream_.WriteWord(*cursor); |
| 937 } |
| 938 } |
| 939 |
| 940 // 2. Write from the entry point to the end. |
| 941 { |
| 942 NoSafepointScope no_safepoint; |
| 943 uword beginning = reinterpret_cast<uword>(insns.raw()) - kHeapObjectTag; |
| 944 uword entry = beginning + Instructions::HeaderSize(); |
| 945 uword payload_size = insns.Size(); |
| 946 payload_size = Utils::RoundUp(payload_size, OS::PreferredCodeAlignment()); |
| 947 uword end = entry + payload_size; |
| 948 |
| 949 ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t))); |
| 950 ASSERT(Utils::IsAligned(entry, sizeof(uint64_t))); |
| 951 ASSERT(Utils::IsAligned(end, sizeof(uint64_t))); |
| 952 |
| 953 for (uword* cursor = reinterpret_cast<uword*>(entry); |
| 954 cursor < reinterpret_cast<uword*>(end); cursor++) { |
| 955 instructions_blob_stream_.WriteWord(*cursor); |
| 956 } |
1064 } | 957 } |
1065 } | 958 } |
1066 } | 959 } |
1067 | 960 |
1068 | 961 |
1069 RawInstructions* InstructionsReader::GetInstructionsAt(int32_t offset) { | 962 RawInstructions* InstructionsReader::GetInstructionsAt(int32_t offset) { |
1070 ASSERT(Utils::IsAligned(offset, OS::PreferredCodeAlignment())); | 963 ASSERT(Utils::IsAligned(offset, OS::PreferredCodeAlignment())); |
1071 | 964 |
1072 RawInstructions* result = reinterpret_cast<RawInstructions*>( | 965 RawInstructions* result = reinterpret_cast<RawInstructions*>( |
1073 reinterpret_cast<uword>(instructions_buffer_) + offset + kHeapObjectTag); | 966 reinterpret_cast<uword>(instructions_buffer_) + offset + kHeapObjectTag); |
(...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2052 *buffer_len_ = BytesWritten(); | 1945 *buffer_len_ = BytesWritten(); |
2053 } | 1946 } |
2054 } else { | 1947 } else { |
2055 FreeBuffer(); | 1948 FreeBuffer(); |
2056 ThrowException(exception_type(), exception_msg()); | 1949 ThrowException(exception_type(), exception_msg()); |
2057 } | 1950 } |
2058 } | 1951 } |
2059 | 1952 |
2060 | 1953 |
2061 } // namespace dart | 1954 } // namespace dart |
OLD | NEW |