diff options
-rw-r--r-- | compiler/debug/elf_debug_writer.cc | 4 | ||||
-rw-r--r-- | compiler/debug/elf_debug_writer.h | 2 | ||||
-rw-r--r-- | compiler/jit/jit_compiler.cc | 2 | ||||
-rw-r--r-- | compiler/jit/jit_compiler.h | 2 | ||||
-rw-r--r-- | runtime/jit/debugger_interface.cc | 92 | ||||
-rw-r--r-- | runtime/jit/debugger_interface.h | 2 | ||||
-rw-r--r-- | runtime/jit/jit.h | 2 | ||||
-rw-r--r-- | runtime/jit/jit_memory_region.h | 3 |
8 files changed, 60 insertions, 49 deletions
diff --git a/compiler/debug/elf_debug_writer.cc b/compiler/debug/elf_debug_writer.cc index cf7254b105..79d11982ab 100644 --- a/compiler/debug/elf_debug_writer.cc +++ b/compiler/debug/elf_debug_writer.cc @@ -228,7 +228,7 @@ std::vector<uint8_t> MakeElfFileForJIT( // Combine several mini-debug-info ELF files into one, while filtering some symbols. std::vector<uint8_t> PackElfFileForJIT( - ArrayRef<JITCodeEntry*> jit_entries, + ArrayRef<const JITCodeEntry*> jit_entries, ArrayRef<const void*> removed_symbols, bool compress, /*out*/ size_t* num_symbols) { @@ -260,7 +260,7 @@ std::vector<uint8_t> PackElfFileForJIT( using Reader = ElfDebugReader<ElfTypes>; std::deque<Reader> readers; - for (JITCodeEntry* it : jit_entries) { + for (const JITCodeEntry* it : jit_entries) { readers.emplace_back(GetJITCodeEntrySymFile(it)); } diff --git a/compiler/debug/elf_debug_writer.h b/compiler/debug/elf_debug_writer.h index ed43a0b702..1ce3c6f6f8 100644 --- a/compiler/debug/elf_debug_writer.h +++ b/compiler/debug/elf_debug_writer.h @@ -57,7 +57,7 @@ std::vector<uint8_t> MakeElfFileForJIT( const MethodDebugInfo& method_info); std::vector<uint8_t> PackElfFileForJIT( - ArrayRef<JITCodeEntry*> jit_entries, + ArrayRef<const JITCodeEntry*> jit_entries, ArrayRef<const void*> removed_symbols, bool compress, /*out*/ size_t* num_symbols); diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc index 0bdab0b797..9af61e0dea 100644 --- a/compiler/jit/jit_compiler.cc +++ b/compiler/jit/jit_compiler.cc @@ -142,7 +142,7 @@ bool JitCompiler::GenerateDebugInfo() { return GetCompilerOptions().GetGenerateDebugInfo(); } -std::vector<uint8_t> JitCompiler::PackElfFileForJIT(ArrayRef<JITCodeEntry*> elf_files, +std::vector<uint8_t> JitCompiler::PackElfFileForJIT(ArrayRef<const JITCodeEntry*> elf_files, ArrayRef<const void*> removed_symbols, bool compress, /*out*/ size_t* num_symbols) { diff --git a/compiler/jit/jit_compiler.h b/compiler/jit/jit_compiler.h index c69a376abb..09de1f8681 100644 --- a/compiler/jit/jit_compiler.h +++ b/compiler/jit/jit_compiler.h @@ -53,7 +53,7 @@ class JitCompiler : public JitCompilerInterface { void TypesLoaded(mirror::Class**, size_t count) REQUIRES_SHARED(Locks::mutator_lock_) override; - std::vector<uint8_t> PackElfFileForJIT(ArrayRef<JITCodeEntry*> elf_files, + std::vector<uint8_t> PackElfFileForJIT(ArrayRef<const JITCodeEntry*> elf_files, ArrayRef<const void*> removed_symbols, bool compress, /*out*/ size_t* num_symbols) override; diff --git a/runtime/jit/debugger_interface.cc b/runtime/jit/debugger_interface.cc index a33b6df236..fd1d9a69a0 100644 --- a/runtime/jit/debugger_interface.cc +++ b/runtime/jit/debugger_interface.cc @@ -98,8 +98,8 @@ extern "C" { struct JITCodeEntryPublic { // Atomic to ensure the reader can always iterate over the linked list // (e.g. the process could crash in the middle of writing this field). - std::atomic<JITCodeEntry*> next_; - JITCodeEntry* prev_; // For linked list deletion. Unused in readers. + std::atomic<const JITCodeEntry*> next_; + const JITCodeEntry* prev_; // For linked list deletion. Unused in readers. const uint8_t* symfile_addr_; // Address of the in-memory ELF file. uint64_t symfile_size_; // Beware of the offset (12 on x86; but 16 on ARM32). @@ -121,10 +121,10 @@ extern "C" { }; struct JITDescriptor { - uint32_t version_ = 1; // NB: GDB supports only version 1. - uint32_t action_flag_ = JIT_NOACTION; // One of the JITAction enum values. - JITCodeEntry* relevant_entry_ = nullptr; // The entry affected by the action. - std::atomic<JITCodeEntry*> head_{nullptr}; // Head of link list of all entries. + uint32_t version_ = 1; // NB: GDB supports only version 1. + uint32_t action_flag_ = JIT_NOACTION; // One of the JITAction enum values. + const JITCodeEntry* relevant_entry_ = nullptr; // The entry affected by the action. + std::atomic<const JITCodeEntry*> head_{nullptr}; // Head of link list of all entries. // Android-specific fields: uint8_t magic_[8] = {'A', 'n', 'd', 'r', 'o', 'i', 'd', '1'}; @@ -164,18 +164,25 @@ struct DexNativeInfo { static constexpr bool kCopySymfileData = false; // Just reference DEX files. static JITDescriptor& Descriptor() { return __dex_debug_descriptor; } static void NotifyNativeDebugger() { __dex_debug_register_code_ptr(); } - static void* Alloc(size_t size) { return malloc(size); } - static void Free(void* ptr) { free(ptr); } + static const void* Alloc(size_t size) { return malloc(size); } + static void Free(const void* ptr) { free(const_cast<void*>(ptr)); } + template<class T> static T* Writable(const T* v) { return const_cast<T*>(v); } }; struct JitNativeInfo { static constexpr bool kCopySymfileData = true; // Copy debug info to JIT memory. static JITDescriptor& Descriptor() { return __jit_debug_descriptor; } static void NotifyNativeDebugger() { __jit_debug_register_code_ptr(); } - static void* Alloc(size_t size) { return JitMemory()->AllocateData(size); } - static void Free(void* ptr) { JitMemory()->FreeData(reinterpret_cast<uint8_t*>(ptr)); } + static const void* Alloc(size_t size) { return Memory()->AllocateData(size); } + static void Free(const void* ptr) { + Memory()->FreeData(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(ptr))); + } + static void Free(void* ptr) = delete; + template<class T> static T* Writable(const T* v) { + return const_cast<T*>(Memory()->GetWritableDataAddress(v)); + } - static jit::JitMemoryRegion* JitMemory() ASSERT_CAPABILITY(Locks::jit_lock_) { + static jit::JitMemoryRegion* Memory() ASSERT_CAPABILITY(Locks::jit_lock_) { Locks::jit_lock_->AssertHeld(Thread::Current()); jit::JitCodeCache* jit_code_cache = Runtime::Current()->GetJitCodeCache(); CHECK(jit_code_cache != nullptr); @@ -185,7 +192,7 @@ struct JitNativeInfo { } }; -ArrayRef<const uint8_t> GetJITCodeEntrySymFile(JITCodeEntry* entry) { +ArrayRef<const uint8_t> GetJITCodeEntrySymFile(const JITCodeEntry* entry) { return ArrayRef<const uint8_t>(entry->symfile_addr_, entry->symfile_size_); } @@ -206,7 +213,7 @@ static void ActionSequnlock(JITDescriptor& descriptor) { } template<class NativeInfo> -static JITCodeEntry* CreateJITCodeEntryInternal( +static const JITCodeEntry* CreateJITCodeEntryInternal( ArrayRef<const uint8_t> symfile, const void* addr = nullptr, bool allow_packing = false, @@ -214,14 +221,14 @@ static JITCodeEntry* CreateJITCodeEntryInternal( JITDescriptor& descriptor = NativeInfo::Descriptor(); // Make a copy of the buffer to shrink it and to pass ownership to JITCodeEntry. - uint8_t* copy = nullptr; + const uint8_t* copy = nullptr; if (NativeInfo::kCopySymfileData) { - copy = reinterpret_cast<uint8_t*>(NativeInfo::Alloc(symfile.size())); + copy = reinterpret_cast<const uint8_t*>(NativeInfo::Alloc(symfile.size())); if (copy == nullptr) { LOG(ERROR) << "Failed to allocate memory for native debug info"; return nullptr; } - memcpy(copy, symfile.data(), symfile.size()); + memcpy(NativeInfo::Writable(copy), symfile.data(), symfile.size()); symfile = ArrayRef<const uint8_t>(copy, symfile.size()); } @@ -229,8 +236,8 @@ static JITCodeEntry* CreateJITCodeEntryInternal( // granularity system timer. This ensures each entry has unique timestamp. uint64_t timestamp = std::max(descriptor.action_timestamp_ + 1, NanoTime()); - JITCodeEntry* head = descriptor.head_.load(std::memory_order_relaxed); - void* memory = NativeInfo::Alloc(sizeof(JITCodeEntry)); + const JITCodeEntry* head = descriptor.head_.load(std::memory_order_relaxed); + const void* memory = NativeInfo::Alloc(sizeof(JITCodeEntry)); if (memory == nullptr) { LOG(ERROR) << "Failed to allocate memory for native debug info"; if (copy != nullptr) { @@ -238,20 +245,21 @@ static JITCodeEntry* CreateJITCodeEntryInternal( } return nullptr; } - JITCodeEntry* entry = new (memory) JITCodeEntry(); - entry->symfile_addr_ = symfile.data(); - entry->symfile_size_ = symfile.size(); - entry->prev_ = nullptr; - entry->next_.store(head, std::memory_order_relaxed); - entry->register_timestamp_ = timestamp; - entry->addr_ = addr; - entry->allow_packing_ = allow_packing; - entry->is_compressed_ = is_compressed; + const JITCodeEntry* entry = reinterpret_cast<const JITCodeEntry*>(memory); + JITCodeEntry* writable_entry = NativeInfo::Writable(entry); + writable_entry->symfile_addr_ = symfile.data(); + writable_entry->symfile_size_ = symfile.size(); + writable_entry->prev_ = nullptr; + writable_entry->next_.store(head, std::memory_order_relaxed); + writable_entry->register_timestamp_ = timestamp; + writable_entry->addr_ = addr; + writable_entry->allow_packing_ = allow_packing; + writable_entry->is_compressed_ = is_compressed; // We are going to modify the linked list, so take the seqlock. ActionSeqlock(descriptor); if (head != nullptr) { - head->prev_ = entry; + NativeInfo::Writable(head)->prev_ = entry; } descriptor.head_.store(entry, std::memory_order_relaxed); descriptor.relevant_entry_ = entry; @@ -265,7 +273,7 @@ static JITCodeEntry* CreateJITCodeEntryInternal( } template<class NativeInfo> -static void DeleteJITCodeEntryInternal(JITCodeEntry* entry) { +static void DeleteJITCodeEntryInternal(const JITCodeEntry* entry) { CHECK(entry != nullptr); const uint8_t* symfile = entry->symfile_addr_; JITDescriptor& descriptor = NativeInfo::Descriptor(); @@ -276,14 +284,14 @@ static void DeleteJITCodeEntryInternal(JITCodeEntry* entry) { // We are going to modify the linked list, so take the seqlock. ActionSeqlock(descriptor); - JITCodeEntry* next = entry->next_.load(std::memory_order_relaxed); + const JITCodeEntry* next = entry->next_.load(std::memory_order_relaxed); if (entry->prev_ != nullptr) { - entry->prev_->next_.store(next, std::memory_order_relaxed); + NativeInfo::Writable(entry->prev_)->next_.store(next, std::memory_order_relaxed); } else { descriptor.head_.store(next, std::memory_order_relaxed); } if (next != nullptr) { - next->prev_ = entry->prev_; + NativeInfo::Writable(next)->prev_ = entry->prev_; } descriptor.relevant_entry_ = entry; descriptor.action_flag_ = JIT_UNREGISTER_FN; @@ -296,11 +304,11 @@ static void DeleteJITCodeEntryInternal(JITCodeEntry* entry) { std::atomic_thread_fence(std::memory_order_release); // Aggressively clear the entry as an extra check of the synchronisation. - memset(entry, 0, sizeof(*entry)); + memset(NativeInfo::Writable(entry), 0, sizeof(*entry)); NativeInfo::Free(entry); if (NativeInfo::kCopySymfileData) { - NativeInfo::Free(const_cast<uint8_t*>(symfile)); + NativeInfo::Free(symfile); } } @@ -317,8 +325,8 @@ void RemoveNativeDebugInfoForDex(Thread* self, const DexFile* dexfile) { // We register dex files in the class linker and free them in DexFile_closeDexFile, but // there might be cases where we load the dex file without using it in the class linker. // On the other hand, single dex file might also be used with different class-loaders. - for (JITCodeEntry* entry = __dex_debug_descriptor.head_; entry != nullptr; ) { - JITCodeEntry* next = entry->next_; // Save next pointer before we free the memory. + for (const JITCodeEntry* entry = __dex_debug_descriptor.head_; entry != nullptr; ) { + const JITCodeEntry* next = entry->next_; // Save next pointer before we free the memory. if (entry->symfile_addr_ == dexfile->Begin()) { DeleteJITCodeEntryInternal<DexNativeInfo>(entry); } @@ -345,9 +353,9 @@ static void RepackEntries(bool compress, ArrayRef<const void*> removed) } // Collect entries that we want to pack. - std::vector<JITCodeEntry*> entries; + std::vector<const JITCodeEntry*> entries; entries.reserve(2 * kJitRepackFrequency); - for (JITCodeEntry* it = __jit_debug_descriptor.head_; it != nullptr; it = it->next_) { + for (const JITCodeEntry* it = __jit_debug_descriptor.head_; it != nullptr; it = it->next_) { if (it->allow_packing_) { if (!compress && it->is_compressed_ && removed.empty()) { continue; // If we are not compressing, also avoid decompressing. @@ -355,7 +363,7 @@ static void RepackEntries(bool compress, ArrayRef<const void*> removed) entries.push_back(it); } } - auto cmp = [](JITCodeEntry* lhs, JITCodeEntry* rhs) { return lhs->addr_ < rhs->addr_; }; + auto cmp = [](const JITCodeEntry* l, const JITCodeEntry* r) { return l->addr_ < r->addr_; }; std::sort(entries.begin(), entries.end(), cmp); // Sort by address. // Process the entries in groups (each spanning memory range of size kJitRepackGroupSize). @@ -367,7 +375,7 @@ static void RepackEntries(bool compress, ArrayRef<const void*> removed) auto begin = group_it; auto end = std::find_if(begin, entries.end(), [=](auto* e) { return e->addr_ >= group_end; }); CHECK(end > begin); - ArrayRef<JITCodeEntry*> elfs(&*begin, end - begin); + ArrayRef<const JITCodeEntry*> elfs(&*begin, end - begin); // Find all symbols that have been removed in this memory range. auto removed_begin = std::lower_bound(removed.begin(), removed.end(), group_ptr); @@ -441,7 +449,7 @@ void RemoveNativeDebugInfoForJit(ArrayRef<const void*> removed) { RepackEntries(/*compress=*/ true, removed); // Remove entries which are not allowed to be packed (containing single method each). - for (JITCodeEntry* it = __jit_debug_descriptor.head_; it != nullptr; it = it->next_) { + for (const JITCodeEntry* it = __jit_debug_descriptor.head_; it != nullptr; it = it->next_) { if (!it->allow_packing_ && std::binary_search(removed.begin(), removed.end(), it->addr_)) { DeleteJITCodeEntryInternal<JitNativeInfo>(/*entry=*/ it); } @@ -451,7 +459,7 @@ void RemoveNativeDebugInfoForJit(ArrayRef<const void*> removed) { size_t GetJitMiniDebugInfoMemUsage() { MutexLock mu(Thread::Current(), g_jit_debug_lock); size_t size = 0; - for (JITCodeEntry* it = __jit_debug_descriptor.head_; it != nullptr; it = it->next_) { + for (const JITCodeEntry* it = __jit_debug_descriptor.head_; it != nullptr; it = it->next_) { size += sizeof(JITCodeEntry) + it->symfile_size_; } return size; diff --git a/runtime/jit/debugger_interface.h b/runtime/jit/debugger_interface.h index 55a9137e1f..0bb3236870 100644 --- a/runtime/jit/debugger_interface.h +++ b/runtime/jit/debugger_interface.h @@ -32,7 +32,7 @@ class Mutex; class Thread; struct JITCodeEntry; -ArrayRef<const uint8_t> GetJITCodeEntrySymFile(JITCodeEntry*); +ArrayRef<const uint8_t> GetJITCodeEntrySymFile(const JITCodeEntry*); // Notify native tools (e.g. libunwind) that DEX file has been opened. void AddNativeDebugInfoForDex(Thread* self, const DexFile* dexfile); diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h index 3a103f5fd2..13a9c7b728 100644 --- a/runtime/jit/jit.h +++ b/runtime/jit/jit.h @@ -177,7 +177,7 @@ class JitCompilerInterface { virtual bool GenerateDebugInfo() = 0; virtual void ParseCompilerOptions() = 0; - virtual std::vector<uint8_t> PackElfFileForJIT(ArrayRef<JITCodeEntry*> elf_files, + virtual std::vector<uint8_t> PackElfFileForJIT(ArrayRef<const JITCodeEntry*> elf_files, ArrayRef<const void*> removed_symbols, bool compress, /*out*/ size_t* num_symbols) = 0; diff --git a/runtime/jit/jit_memory_region.h b/runtime/jit/jit_memory_region.h index a5e3ef3e08..bc05cb6253 100644 --- a/runtime/jit/jit_memory_region.h +++ b/runtime/jit/jit_memory_region.h @@ -28,6 +28,8 @@ namespace art { +struct JitNativeInfo; + namespace mirror { class Object; } @@ -277,6 +279,7 @@ class JitMemoryRegion { friend class ScopedCodeCacheWrite; // For GetUpdatableCodeMapping friend class TestZygoteMemory; + friend struct art::JitNativeInfo; // For GetWritableDataAddress. }; } // namespace jit |