Simplify JIT compiler interface usage from the runtime.

Avoid the excessive use of externs and reinterpret_casts.

Test: test.py -b --host --64 --jit
Change-Id: I179656a3a7c4e59d12c8f6d189c937ce07e0f122
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index f19de4e..d84a132 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -115,7 +115,7 @@
   }
 }
 
-extern "C" void* jit_load() {
+extern "C" JitCompilerInterface* jit_load() {
   VLOG(jit) << "Create jit compiler";
   auto* const jit_compiler = JitCompiler::Create();
   CHECK(jit_compiler != nullptr);
@@ -123,24 +123,9 @@
   return jit_compiler;
 }
 
-extern "C" void jit_unload(void* handle) {
-  DCHECK(handle != nullptr);
-  delete reinterpret_cast<JitCompiler*>(handle);
-}
-
-extern "C" bool jit_compile_method(
-    void* handle, JitMemoryRegion* region, ArtMethod* method, Thread* self, bool baseline, bool osr)
+void JitCompiler::TypesLoaded(mirror::Class** types, size_t count)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  auto* jit_compiler = reinterpret_cast<JitCompiler*>(handle);
-  DCHECK(jit_compiler != nullptr);
-  return jit_compiler->CompileMethod(self, region, method, baseline, osr);
-}
-
-extern "C" void jit_types_loaded(void* handle, mirror::Class** types, size_t count)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  auto* jit_compiler = reinterpret_cast<JitCompiler*>(handle);
-  DCHECK(jit_compiler != nullptr);
-  const CompilerOptions& compiler_options = jit_compiler->GetCompilerOptions();
+  const CompilerOptions& compiler_options = GetCompilerOptions();
   if (compiler_options.GetGenerateDebugInfo()) {
     const ArrayRef<mirror::Class*> types_array(types, count);
     std::vector<uint8_t> elf_file = debug::WriteDebugElfFileForClasses(
@@ -156,16 +141,8 @@
   }
 }
 
-extern "C" void jit_update_options(void* handle) {
-  JitCompiler* jit_compiler = reinterpret_cast<JitCompiler*>(handle);
-  DCHECK(jit_compiler != nullptr);
-  jit_compiler->ParseCompilerOptions();
-}
-
-extern "C" bool jit_generate_debug_info(void* handle) {
-  JitCompiler* jit_compiler = reinterpret_cast<JitCompiler*>(handle);
-  DCHECK(jit_compiler != nullptr);
-  return jit_compiler->GetCompilerOptions().GetGenerateDebugInfo();
+bool JitCompiler::GenerateDebugInfo() {
+  return GetCompilerOptions().GetGenerateDebugInfo();
 }
 
 JitCompiler::JitCompiler() {
diff --git a/compiler/jit/jit_compiler.h b/compiler/jit/jit_compiler.h
index 06315a5..737771f 100644
--- a/compiler/jit/jit_compiler.h
+++ b/compiler/jit/jit_compiler.h
@@ -19,6 +19,8 @@
 
 #include "base/mutex.h"
 
+#include "jit/jit.h"
+
 namespace art {
 
 class ArtMethod;
@@ -31,7 +33,7 @@
 class JitLogger;
 class JitMemoryRegion;
 
-class JitCompiler {
+class JitCompiler : public JitCompilerInterface {
  public:
   static JitCompiler* Create();
   virtual ~JitCompiler();
@@ -39,13 +41,17 @@
   // Compilation entrypoint. Returns whether the compilation succeeded.
   bool CompileMethod(
       Thread* self, JitMemoryRegion* region, ArtMethod* method, bool baseline, bool osr)
-      REQUIRES_SHARED(Locks::mutator_lock_);
+      REQUIRES_SHARED(Locks::mutator_lock_) override;
 
   const CompilerOptions& GetCompilerOptions() const {
     return *compiler_options_.get();
   }
 
-  void ParseCompilerOptions();
+  bool GenerateDebugInfo() override;
+
+  void ParseCompilerOptions() override;
+
+  void TypesLoaded(mirror::Class**, size_t count) REQUIRES_SHARED(Locks::mutator_lock_) override;
 
  private:
   std::unique_ptr<CompilerOptions> compiler_options_;
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 902d924..3eeb0fa 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -63,14 +63,8 @@
 
 // JIT compiler
 void* Jit::jit_library_handle_ = nullptr;
-void* Jit::jit_compiler_handle_ = nullptr;
-void* (*Jit::jit_load_)(void) = nullptr;
-void (*Jit::jit_unload_)(void*) = nullptr;
-bool (*Jit::jit_compile_method_)(void*, JitMemoryRegion*, ArtMethod*, Thread*, bool, bool)
-    = nullptr;
-void (*Jit::jit_types_loaded_)(void*, mirror::Class**, size_t count) = nullptr;
-bool (*Jit::jit_generate_debug_info_)(void*) = nullptr;
-void (*Jit::jit_update_options_)(void*) = nullptr;
+JitCompilerInterface* Jit::jit_compiler_ = nullptr;
+JitCompilerInterface* (*Jit::jit_load_)(void) = nullptr;
 
 uint32_t JitOptions::RoundUpThreshold(uint32_t threshold) {
   if (!Jit::kSlowMode) {
@@ -184,8 +178,8 @@
     LOG(WARNING) << "Not creating JIT: library not loaded";
     return nullptr;
   }
-  jit_compiler_handle_ = (jit_load_)();
-  if (jit_compiler_handle_ == nullptr) {
+  jit_compiler_ = (jit_load_)();
+  if (jit_compiler_ == nullptr) {
     LOG(WARNING) << "Not creating JIT: failed to allocate a compiler";
     return nullptr;
   }
@@ -196,7 +190,7 @@
   // We aren't able to keep method pointers live during the instrumentation method entry trampoline
   // so we will just disable jit-gc if we are doing that.
   if (code_cache->GetGarbageCollectCode()) {
-    code_cache->SetGarbageCollectCode(!jit_generate_debug_info_(jit_compiler_handle_) &&
+    code_cache->SetGarbageCollectCode(!jit_compiler_->GenerateDebugInfo() &&
         !Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled());
   }
 
@@ -230,15 +224,7 @@
     *error_msg = oss.str();
     return false;
   }
-  bool all_resolved = true;
-  all_resolved = all_resolved && LoadSymbol(&jit_load_, "jit_load", error_msg);
-  all_resolved = all_resolved && LoadSymbol(&jit_unload_, "jit_unload", error_msg);
-  all_resolved = all_resolved && LoadSymbol(&jit_compile_method_, "jit_compile_method", error_msg);
-  all_resolved = all_resolved && LoadSymbol(&jit_types_loaded_, "jit_types_loaded", error_msg);
-  all_resolved = all_resolved && LoadSymbol(&jit_update_options_, "jit_update_options", error_msg);
-  all_resolved = all_resolved &&
-      LoadSymbol(&jit_generate_debug_info_, "jit_generate_debug_info", error_msg);
-  if (!all_resolved) {
+  if (!LoadSymbol(&jit_load_, "jit_load", error_msg)) {
     dlclose(jit_library_handle_);
     return false;
   }
@@ -283,8 +269,7 @@
   VLOG(jit) << "Compiling method "
             << ArtMethod::PrettyMethod(method_to_compile)
             << " osr=" << std::boolalpha << osr;
-  bool success = jit_compile_method_(
-      jit_compiler_handle_, region, method_to_compile, self, baseline, osr);
+  bool success = jit_compiler_->CompileMethod(self, region, method_to_compile, baseline, osr);
   code_cache_->DoneCompiling(method_to_compile, self, osr);
   if (!success) {
     VLOG(jit) << "Failed to compile method "
@@ -360,9 +345,9 @@
     Runtime::Current()->DumpDeoptimizations(LOG_STREAM(INFO));
   }
   DeleteThreadPool();
-  if (jit_compiler_handle_ != nullptr) {
-    jit_unload_(jit_compiler_handle_);
-    jit_compiler_handle_ = nullptr;
+  if (jit_compiler_ != nullptr) {
+    delete jit_compiler_;
+    jit_compiler_ = nullptr;
   }
   if (jit_library_handle_ != nullptr) {
     dlclose(jit_library_handle_);
@@ -376,9 +361,8 @@
     return;
   }
   jit::Jit* jit = Runtime::Current()->GetJit();
-  if (jit_generate_debug_info_(jit->jit_compiler_handle_)) {
-    DCHECK(jit->jit_types_loaded_ != nullptr);
-    jit->jit_types_loaded_(jit->jit_compiler_handle_, &type, 1);
+  if (jit->jit_compiler_->GenerateDebugInfo()) {
+    jit_compiler_->TypesLoaded(&type, 1);
   }
 }
 
@@ -391,12 +375,12 @@
     std::vector<mirror::Class*> classes_;
   };
 
-  if (jit_generate_debug_info_(jit_compiler_handle_)) {
+  if (jit_compiler_->GenerateDebugInfo()) {
     ScopedObjectAccess so(Thread::Current());
 
     CollectClasses visitor;
     linker->VisitClasses(&visitor);
-    jit_types_loaded_(jit_compiler_handle_, visitor.classes_.data(), visitor.classes_.size());
+    jit_compiler_->TypesLoaded(visitor.classes_.data(), visitor.classes_.size());
   }
 }
 
@@ -1122,10 +1106,10 @@
   }
   // At this point, the compiler options have been adjusted to the particular configuration
   // of the forked child. Parse them again.
-  jit_update_options_(jit_compiler_handle_);
+  jit_compiler_->ParseCompilerOptions();
 
   // Adjust the status of code cache collection: the status from zygote was to not collect.
-  code_cache_->SetGarbageCollectCode(!jit_generate_debug_info_(jit_compiler_handle_) &&
+  code_cache_->SetGarbageCollectCode(!jit_compiler_->GenerateDebugInfo() &&
       !Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled());
 
   if (thread_pool_ != nullptr) {
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 8cf37fb..36a1d3e 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -164,6 +164,19 @@
   DISALLOW_COPY_AND_ASSIGN(JitOptions);
 };
 
+// Implemented and provided by the compiler library.
+class JitCompilerInterface {
+ public:
+  virtual ~JitCompilerInterface() {}
+  virtual bool CompileMethod(
+      Thread* self, JitMemoryRegion* region, ArtMethod* method, bool baseline, bool osr)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  virtual void TypesLoaded(mirror::Class**, size_t count)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  virtual bool GenerateDebugInfo();
+  virtual void ParseCompilerOptions();
+};
+
 class Jit {
  public:
   static constexpr size_t kDefaultPriorityThreadWeightRatio = 1000;
@@ -378,13 +391,8 @@
 
   // JIT compiler
   static void* jit_library_handle_;
-  static void* jit_compiler_handle_;
-  static void* (*jit_load_)(void);
-  static void (*jit_unload_)(void*);
-  static bool (*jit_compile_method_)(void*, JitMemoryRegion*, ArtMethod*, Thread*, bool, bool);
-  static void (*jit_types_loaded_)(void*, mirror::Class**, size_t count);
-  static void (*jit_update_options_)(void*);
-  static bool (*jit_generate_debug_info_)(void*);
+  static JitCompilerInterface* jit_compiler_;
+  static JitCompilerInterface* (*jit_load_)(void);
   template <typename T> static bool LoadSymbol(T*, const char* symbol, std::string* error_msg);
 
   // JIT resources owned by runtime.