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