Report loaded classes to native debugger.

Change-Id: Iee902a9ed8fa7545ba3e6afc32f285aa350a5383
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index bc51ed6..a4b9c6c 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -28,6 +28,8 @@
 #include "dex/quick_compiler_callbacks.h"
 #include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
+#include "elf_writer_debug.h"
+#include "jit/debugger_interface.h"
 #include "jit/jit.h"
 #include "jit/jit_code_cache.h"
 #include "oat_file-inl.h"
@@ -65,6 +67,16 @@
   return jit_compiler->CompileMethod(self, method);
 }
 
+extern "C" void jit_type_loaded(void* handle, mirror::Class* type)
+    SHARED_REQUIRES(Locks::mutator_lock_) {
+  auto* jit_compiler = reinterpret_cast<JitCompiler*>(handle);
+  DCHECK(jit_compiler != nullptr);
+  if (jit_compiler->GetCompilerOptions()->GetGenerateDebugInfo()) {
+    ArrayRef<const uint8_t> elf_file = dwarf::WriteDebugElfFileForClass(kRuntimeISA, type);
+    CreateJITCodeEntry(std::unique_ptr<const uint8_t[]>(elf_file.data()), elf_file.size());
+  }
+}
+
 // Callers of this method assume it has NO_RETURN.
 NO_RETURN static void Usage(const char* fmt, ...) {
   va_list ap;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 41842e8..1299915 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1879,6 +1879,9 @@
    */
   Dbg::PostClassPrepare(h_new_class.Get());
 
+  // Notify native debugger of the new class and its layout.
+  jit::Jit::NewTypeLoadedIfUsingJit(h_new_class.Get());
+
   return h_new_class.Get();
 }
 
@@ -2765,6 +2768,7 @@
 
   mirror::Class* existing = InsertClass(descriptor, new_class.Get(), hash);
   if (existing == nullptr) {
+    jit::Jit::NewTypeLoadedIfUsingJit(new_class.Get());
     return new_class.Get();
   }
   // Another thread must have loaded the class after we
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 05668a9..2a89077 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -127,6 +127,13 @@
     *error_msg = "JIT couldn't find jit_compile_method entry point";
     return false;
   }
+  jit_type_loaded_ = reinterpret_cast<void (*)(void*, mirror::Class*)>(
+      dlsym(jit_library_handle_, "jit_type_loaded"));
+  if (jit_type_loaded_ == nullptr) {
+    dlclose(jit_library_handle_);
+    *error_msg = "JIT couldn't find jit_type_loaded entry point";
+    return false;
+  }
   CompilerCallbacks* callbacks = nullptr;
   bool will_generate_debug_symbols = false;
   VLOG(jit) << "Calling JitLoad interpreter_only="
@@ -214,5 +221,13 @@
       new jit::JitInstrumentationCache(compile_threshold, warmup_threshold));
 }
 
+void Jit::NewTypeLoadedIfUsingJit(mirror::Class* type) {
+  jit::Jit* jit = Runtime::Current()->GetJit();
+  if (jit != nullptr && jit->generate_debug_info_) {
+    DCHECK(jit->jit_type_loaded_ != nullptr);
+    jit->jit_type_loaded_(jit->jit_compiler_handle_, type);
+  }
+}
+
 }  // namespace jit
 }  // namespace art
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 42bbbe7..443ebe8 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -79,6 +79,9 @@
     DumpInfo(os);
   }
 
+  static void NewTypeLoadedIfUsingJit(mirror::Class* type)
+      SHARED_REQUIRES(Locks::mutator_lock_);
+
  private:
   Jit();
   bool LoadCompiler(std::string* error_msg);
@@ -89,6 +92,7 @@
   void* (*jit_load_)(CompilerCallbacks**, bool*);
   void (*jit_unload_)(void*);
   bool (*jit_compile_method_)(void*, ArtMethod*, Thread*);
+  void (*jit_type_loaded_)(void*, mirror::Class*);
 
   // Performance monitoring.
   bool dump_info_on_shutdown_;