JIT mini-debug-info: Allocate entries in the JIT data space.

Test: test.py -b --host --jit
Test: device boots
Bug: 119800099
Change-Id: I7efa1e6e6660239cbd6438b829e08dd9cd079343
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index f01554a..0bdab0b 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -123,8 +123,7 @@
   return jit_compiler;
 }
 
-void JitCompiler::TypesLoaded(mirror::Class** types, size_t count)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
+void JitCompiler::TypesLoaded(mirror::Class** types, size_t count) {
   const CompilerOptions& compiler_options = GetCompilerOptions();
   if (compiler_options.GetGenerateDebugInfo()) {
     InstructionSet isa = compiler_options.GetInstructionSet();
@@ -134,6 +133,7 @@
         debug::WriteDebugElfFileForClasses(isa, features, types_array);
 
     // NB: Don't allow packing since it would remove non-backtrace data.
+    MutexLock mu(Thread::Current(), *Locks::jit_lock_);
     AddNativeDebugInfoForJit(/*code_ptr=*/ nullptr, elf_file, /*allow_packing=*/ false);
   }
 }
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 5d06969..8ef1b55 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -1486,6 +1486,7 @@
     std::vector<uint8_t> elf = debug::MakeElfFileForJIT(isa, features, mini_debug_info, info);
 
     // NB: Don't allow packing of full info since it would remove non-backtrace data.
+    MutexLock mu(Thread::Current(), *Locks::jit_lock_);
     const void* code_ptr = reinterpret_cast<const void*>(info.code_address);
     AddNativeDebugInfoForJit(code_ptr, elf, /*allow_packing=*/ mini_debug_info);
   }
diff --git a/runtime/gc/space/dlmalloc_space.cc b/runtime/gc/space/dlmalloc_space.cc
index 3fa4c3c..f3fccbb 100644
--- a/runtime/gc/space/dlmalloc_space.cc
+++ b/runtime/gc/space/dlmalloc_space.cc
@@ -384,8 +384,8 @@
   ::art::gc::space::DlMallocSpace* dlmalloc_space = heap->GetDlMallocSpace();
   // Support for multiple DlMalloc provided by a slow path.
   if (UNLIKELY(dlmalloc_space == nullptr || dlmalloc_space->GetMspace() != mspace)) {
-    if (LIKELY(runtime->GetJit() != nullptr)) {
-      jit::JitCodeCache* code_cache = runtime->GetJit()->GetCodeCache();
+    if (LIKELY(runtime->GetJitCodeCache() != nullptr)) {
+      jit::JitCodeCache* code_cache = runtime->GetJitCodeCache();
       if (code_cache->OwnsSpace(mspace)) {
         return code_cache->MoreCore(mspace, increment);
       }
diff --git a/runtime/jit/debugger_interface.cc b/runtime/jit/debugger_interface.cc
index 2446a44..a33b6df 100644
--- a/runtime/jit/debugger_interface.cc
+++ b/runtime/jit/debugger_interface.cc
@@ -26,6 +26,8 @@
 #include "base/utils.h"
 #include "dex/dex_file.h"
 #include "jit/jit.h"
+#include "jit/jit_code_cache.h"
+#include "jit/jit_memory_region.h"
 #include "runtime.h"
 #include "thread-current-inl.h"
 #include "thread.h"
@@ -158,6 +160,31 @@
   JITDescriptor __dex_debug_descriptor GUARDED_BY(g_dex_debug_lock) {};
 }
 
+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); }
+};
+
+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 jit::JitMemoryRegion* JitMemory() ASSERT_CAPABILITY(Locks::jit_lock_) {
+    Locks::jit_lock_->AssertHeld(Thread::Current());
+    jit::JitCodeCache* jit_code_cache = Runtime::Current()->GetJitCodeCache();
+    CHECK(jit_code_cache != nullptr);
+    jit::JitMemoryRegion* memory = jit_code_cache->GetCurrentRegion();
+    CHECK(memory->IsValid());
+    return memory;
+  }
+};
+
 ArrayRef<const uint8_t> GetJITCodeEntrySymFile(JITCodeEntry* entry) {
   return ArrayRef<const uint8_t>(entry->symfile_addr_, entry->symfile_size_);
 }
@@ -178,18 +205,22 @@
   descriptor.action_seqlock_.fetch_add(1, std::memory_order_relaxed);
 }
 
+template<class NativeInfo>
 static JITCodeEntry* CreateJITCodeEntryInternal(
-    JITDescriptor& descriptor,
-    void (*register_code_ptr)(),
     ArrayRef<const uint8_t> symfile,
-    bool copy_symfile,
     const void* addr = nullptr,
     bool allow_packing = false,
     bool is_compressed = false) {
+  JITDescriptor& descriptor = NativeInfo::Descriptor();
+
   // Make a copy of the buffer to shrink it and to pass ownership to JITCodeEntry.
-  if (copy_symfile) {
-    uint8_t* copy = new uint8_t[symfile.size()];
-    CHECK(copy != nullptr);
+  uint8_t* copy = nullptr;
+  if (NativeInfo::kCopySymfileData) {
+    copy = reinterpret_cast<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());
     symfile = ArrayRef<const uint8_t>(copy, symfile.size());
   }
@@ -199,8 +230,15 @@
   uint64_t timestamp = std::max(descriptor.action_timestamp_ + 1, NanoTime());
 
   JITCodeEntry* head = descriptor.head_.load(std::memory_order_relaxed);
-  JITCodeEntry* entry = new JITCodeEntry();
-  CHECK(entry != nullptr);
+  void* memory = NativeInfo::Alloc(sizeof(JITCodeEntry));
+  if (memory == nullptr) {
+    LOG(ERROR) << "Failed to allocate memory for native debug info";
+    if (copy != nullptr) {
+      NativeInfo::Free(copy);
+    }
+    return nullptr;
+  }
+  JITCodeEntry* entry = new (memory) JITCodeEntry();
   entry->symfile_addr_ = symfile.data();
   entry->symfile_size_ = symfile.size();
   entry->prev_ = nullptr;
@@ -221,17 +259,16 @@
   descriptor.action_timestamp_ = timestamp;
   ActionSequnlock(descriptor);
 
-  (*register_code_ptr)();
+  NativeInfo::NotifyNativeDebugger();
+
   return entry;
 }
 
-static void DeleteJITCodeEntryInternal(
-    JITDescriptor& descriptor,
-    void (*register_code_ptr)(),
-    JITCodeEntry* entry,
-    bool free_symfile) {
+template<class NativeInfo>
+static void DeleteJITCodeEntryInternal(JITCodeEntry* entry) {
   CHECK(entry != nullptr);
   const uint8_t* symfile = entry->symfile_addr_;
+  JITDescriptor& descriptor = NativeInfo::Descriptor();
 
   // Ensure the timestamp is monotonically increasing even in presence of low
   // granularity system timer.  This ensures each entry has unique timestamp.
@@ -253,7 +290,7 @@
   descriptor.action_timestamp_ = timestamp;
   ActionSequnlock(descriptor);
 
-  (*register_code_ptr)();
+  NativeInfo::NotifyNativeDebugger();
 
   // Ensure that clear below can not be reordered above the unlock above.
   std::atomic_thread_fence(std::memory_order_release);
@@ -261,9 +298,9 @@
   // Aggressively clear the entry as an extra check of the synchronisation.
   memset(entry, 0, sizeof(*entry));
 
-  delete entry;
-  if (free_symfile) {
-    delete[] symfile;
+  NativeInfo::Free(entry);
+  if (NativeInfo::kCopySymfileData) {
+    NativeInfo::Free(const_cast<uint8_t*>(symfile));
   }
 }
 
@@ -271,10 +308,7 @@
   MutexLock mu(self, g_dex_debug_lock);
   DCHECK(dexfile != nullptr);
   const ArrayRef<const uint8_t> symfile(dexfile->Begin(), dexfile->Size());
-  CreateJITCodeEntryInternal(__dex_debug_descriptor,
-                             __dex_debug_register_code_ptr,
-                             symfile,
-                             /*copy_symfile=*/ false);
+  CreateJITCodeEntryInternal<DexNativeInfo>(symfile);
 }
 
 void RemoveNativeDebugInfoForDex(Thread* self, const DexFile* dexfile) {
@@ -286,10 +320,7 @@
   for (JITCodeEntry* entry = __dex_debug_descriptor.head_; entry != nullptr; ) {
     JITCodeEntry* next = entry->next_;  // Save next pointer before we free the memory.
     if (entry->symfile_addr_ == dexfile->Begin()) {
-      DeleteJITCodeEntryInternal(__dex_debug_descriptor,
-                                 __dex_debug_register_code_ptr,
-                                 entry,
-                                 /*free_symfile=*/ false);
+      DeleteJITCodeEntryInternal<DexNativeInfo>(entry);
     }
     entry = next;
   }
@@ -365,19 +396,12 @@
         << " size=" << packed.size() << (compress ? "(lzma)" : "");
 
     // Replace the old entries with the new one (with their lifetime temporally overlapping).
-    CreateJITCodeEntryInternal(
-        __jit_debug_descriptor,
-        __jit_debug_register_code_ptr,
-        ArrayRef<const uint8_t>(packed),
-        /*copy_symfile=*/ true,
-        /*addr_=*/ group_ptr,
-        /*allow_packing_=*/ true,
-        /*is_compressed_=*/ compress);
+    CreateJITCodeEntryInternal<JitNativeInfo>(ArrayRef<const uint8_t>(packed),
+                                              /*addr_=*/ group_ptr,
+                                              /*allow_packing_=*/ true,
+                                              /*is_compressed_=*/ compress);
     for (auto it : elfs) {
-      DeleteJITCodeEntryInternal(__jit_debug_descriptor,
-                                 __jit_debug_register_code_ptr,
-                                 /*entry=*/ it,
-                                 /*free_symfile=*/ true);
+      DeleteJITCodeEntryInternal<JitNativeInfo>(/*entry=*/ it);
     }
     group_it = end;  // Go to next group.
   }
@@ -390,14 +414,14 @@
   MutexLock mu(Thread::Current(), g_jit_debug_lock);
   DCHECK_NE(symfile.size(), 0u);
 
-  CreateJITCodeEntryInternal(
-      __jit_debug_descriptor,
-      __jit_debug_register_code_ptr,
-      ArrayRef<const uint8_t>(symfile),
-      /*copy_symfile=*/ true,
-      /*addr=*/ code_ptr,
-      /*allow_packing=*/ allow_packing,
-      /*is_compressed=*/ false);
+  if (Runtime::Current()->IsZygote()) {
+    return;  // TODO: Implement memory sharing with the zygote process.
+  }
+
+  CreateJITCodeEntryInternal<JitNativeInfo>(ArrayRef<const uint8_t>(symfile),
+                                            /*addr=*/ code_ptr,
+                                            /*allow_packing=*/ allow_packing,
+                                            /*is_compressed=*/ false);
 
   VLOG(jit)
       << "JIT mini-debug-info added"
@@ -419,10 +443,7 @@
   // 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_) {
     if (!it->allow_packing_ && std::binary_search(removed.begin(), removed.end(), it->addr_)) {
-      DeleteJITCodeEntryInternal(__jit_debug_descriptor,
-                                 __jit_debug_register_code_ptr,
-                                 /*entry=*/ it,
-                                 /*free_symfile=*/ true);
+      DeleteJITCodeEntryInternal<JitNativeInfo>(/*entry=*/ it);
     }
   }
 }
diff --git a/runtime/jit/debugger_interface.h b/runtime/jit/debugger_interface.h
index be5e5ac..55a9137 100644
--- a/runtime/jit/debugger_interface.h
+++ b/runtime/jit/debugger_interface.h
@@ -46,10 +46,12 @@
 // (however, this drops all ELF sections other than symbols names and unwinding info).
 void AddNativeDebugInfoForJit(const void* code_ptr,
                               const std::vector<uint8_t>& symfile,
-                              bool allow_packing);
+                              bool allow_packing)
+    REQUIRES_SHARED(Locks::jit_lock_);  // Might need JIT code cache to allocate memory.
 
 // Notify native tools (e.g. libunwind) that JIT code has been garbage collected.
-void RemoveNativeDebugInfoForJit(ArrayRef<const void*> removed_code_ptrs);
+void RemoveNativeDebugInfoForJit(ArrayRef<const void*> removed_code_ptrs)
+    REQUIRES_SHARED(Locks::jit_lock_);  // Might need JIT code cache to allocate memory.
 
 // Returns approximate memory used by debug info for JIT code.
 size_t GetJitMiniDebugInfoMemUsage();
diff --git a/runtime/runtime.h b/runtime/runtime.h
index ea516cd..6735216 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -484,6 +484,10 @@
     return jit_.get();
   }
 
+  jit::JitCodeCache* GetJitCodeCache() const {
+    return jit_code_cache_.get();
+  }
+
   // Returns true if JIT compilations are enabled. GetJit() will be not null in this case.
   bool UseJitCompilation() const;