Use DlMallocSpace for the JIT code cache.

- Also tidy up some code in the JIT compiler.
- And mprotect code space to be writable only when allocating.

Change-Id: I46ea5c029aec489f2af63452de31db3736aebc20
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index b6a40a2..cd49202 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -126,61 +126,66 @@
   StackHandleScope<2> hs(self);
   self->AssertNoPendingException();
   Runtime* runtime = Runtime::Current();
+
+  // Check if the method is already compiled.
   if (runtime->GetJit()->GetCodeCache()->ContainsMethod(method)) {
     VLOG(jit) << "Already compiled " << PrettyMethod(method);
-    return true;  // Already compiled
+    return true;
   }
+
+  // Don't compile the method if we are supposed to be deoptimized.
+  if (runtime->GetInstrumentation()->AreAllMethodsDeoptimized()) {
+    return false;
+  }
+
+  // Ensure the class is initialized.
   Handle<mirror::Class> h_class(hs.NewHandle(method->GetDeclaringClass()));
-  {
-    TimingLogger::ScopedTiming t2("Initializing", &logger);
-    if (!runtime->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) {
-      VLOG(jit) << "JIT failed to initialize " << PrettyMethod(method);
-      return false;
-    }
+  if (!runtime->GetClassLinker()->EnsureInitialized(self, h_class, true, true)) {
+    VLOG(jit) << "JIT failed to initialize " << PrettyMethod(method);
+    return false;
   }
-  const DexFile* dex_file = h_class->GetDexCache()->GetDexFile();
-  MethodReference method_ref(dex_file, method->GetDexMethodIndex());
-  // Only verify if we don't already have verification results.
-  if (verification_results_->GetVerifiedMethod(method_ref) == nullptr) {
-    TimingLogger::ScopedTiming t2("Verifying", &logger);
-    std::string error;
-    if (verifier::MethodVerifier::VerifyMethod(method, true, &error) ==
-        verifier::MethodVerifier::kHardFailure) {
-      VLOG(jit) << "Not compile method " << PrettyMethod(method)
-          << " due to verification failure " << error;
-      return false;
-    }
-  }
+
+  // Do the compilation.
   CompiledMethod* compiled_method = nullptr;
   {
     TimingLogger::ScopedTiming t2("Compiling", &logger);
     compiled_method = compiler_driver_->CompileArtMethod(self, method);
   }
+
+  // Trim maps to reduce memory usage.
+  // TODO: measure how much this increases compile time.
   {
     TimingLogger::ScopedTiming t2("TrimMaps", &logger);
-    // Trim maps to reduce memory usage, TODO: measure how much this increases compile time.
     runtime->GetArenaPool()->TrimMaps();
   }
+
+  // Check if we failed compiling.
   if (compiled_method == nullptr) {
     return false;
   }
+
   total_time_ += NanoTime() - start_time;
-  // Don't add the method if we are supposed to be deoptimized.
   bool result = false;
-  if (!runtime->GetInstrumentation()->AreAllMethodsDeoptimized()) {
-    const void* code = runtime->GetClassLinker()->GetOatMethodQuickCodeFor(method);
-    if (code != nullptr) {
-      // Already have some compiled code, just use this instead of linking.
-      // TODO: Fix recompilation.
-      method->SetEntryPointFromQuickCompiledCode(code);
+  const void* code = runtime->GetClassLinker()->GetOatMethodQuickCodeFor(method);
+
+  if (code != nullptr) {
+    // Already have some compiled code, just use this instead of linking.
+    // TODO: Fix recompilation.
+    method->SetEntryPointFromQuickCompiledCode(code);
+    result = true;
+  } else {
+    TimingLogger::ScopedTiming t2("LinkCode", &logger);
+    OatFile::OatMethod oat_method(nullptr, 0);
+    if (AddToCodeCache(method, compiled_method, &oat_method)) {
+      oat_method.LinkMethod(method);
+      CHECK(runtime->GetJit()->GetCodeCache()->ContainsMethod(method)) << PrettyMethod(method);
       result = true;
-    } else {
-      TimingLogger::ScopedTiming t2("MakeExecutable", &logger);
-      result = MakeExecutable(compiled_method, method);
     }
   }
+
   // Remove the compiled method to save memory.
-  compiler_driver_->RemoveCompiledMethod(method_ref);
+  compiler_driver_->RemoveCompiledMethod(
+      MethodReference(h_class->GetDexCache()->GetDexFile(), method->GetDexMethodIndex()));
   runtime->GetJit()->AddTimingLogger(logger);
   return result;
 }
@@ -189,41 +194,8 @@
   return callbacks_.get();
 }
 
-uint8_t* JitCompiler::WriteMethodHeaderAndCode(const CompiledMethod* compiled_method,
-                                               uint8_t* reserve_begin, uint8_t* reserve_end,
-                                               const uint8_t* mapping_table,
-                                               const uint8_t* vmap_table,
-                                               const uint8_t* gc_map) {
-  reserve_begin += sizeof(OatQuickMethodHeader);
-  reserve_begin = reinterpret_cast<uint8_t*>(
-      compiled_method->AlignCode(reinterpret_cast<uintptr_t>(reserve_begin)));
-  const auto* quick_code = compiled_method->GetQuickCode();
-  CHECK_LE(reserve_begin, reserve_end);
-  CHECK_LE(quick_code->size(), static_cast<size_t>(reserve_end - reserve_begin));
-  auto* code_ptr = reserve_begin;
-  OatQuickMethodHeader* method_header = reinterpret_cast<OatQuickMethodHeader*>(code_ptr) - 1;
-  // Construct the header last.
-  const auto frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
-  const auto core_spill_mask = compiled_method->GetCoreSpillMask();
-  const auto fp_spill_mask = compiled_method->GetFpSpillMask();
-  const auto code_size = quick_code->size();
-  CHECK_NE(code_size, 0U);
-  std::copy(quick_code->data(), quick_code->data() + code_size, code_ptr);
-  // After we are done writing we need to update the method header.
-  // Write out the method header last.
-  method_header = new(method_header) OatQuickMethodHeader(
-      (mapping_table == nullptr) ? 0 : code_ptr - mapping_table,
-      (vmap_table == nullptr) ? 0 : code_ptr - vmap_table,
-      (gc_map == nullptr) ? 0 : code_ptr - gc_map,
-      frame_size_in_bytes,
-      core_spill_mask,
-      fp_spill_mask,
-      code_size);
-  // Return the code ptr.
-  return code_ptr;
-}
-
-bool JitCompiler::AddToCodeCache(ArtMethod* method, const CompiledMethod* compiled_method,
+bool JitCompiler::AddToCodeCache(ArtMethod* method,
+                                 const CompiledMethod* compiled_method,
                                  OatFile::OatMethod* out_method) {
   Runtime* runtime = Runtime::Current();
   JitCodeCache* const code_cache = runtime->GetJit()->GetCodeCache();
@@ -233,7 +205,6 @@
   }
   const auto code_size = quick_code->size();
   Thread* const self = Thread::Current();
-  const uint8_t* base = code_cache->CodeCachePtr();
   auto* const mapping_table = compiled_method->GetMappingTable();
   auto* const vmap_table = compiled_method->GetVmapTable();
   auto* const gc_map = compiled_method->GetGcMap();
@@ -266,45 +237,35 @@
     }
   }
 
-  // Don't touch this until you protect / unprotect the code.
-  const size_t reserve_size = sizeof(OatQuickMethodHeader) + quick_code->size() + 32;
-  uint8_t* const code_reserve = code_cache->ReserveCode(self, reserve_size);
-  if (code_reserve == nullptr) {
+  uint8_t* const code = code_cache->CommitCode(self,
+                                               mapping_table_ptr,
+                                               vmap_table_ptr,
+                                               gc_map_ptr,
+                                               compiled_method->GetFrameSizeInBytes(),
+                                               compiled_method->GetCoreSpillMask(),
+                                               compiled_method->GetFpSpillMask(),
+                                               compiled_method->GetQuickCode()->data(),
+                                               compiled_method->GetQuickCode()->size());
+
+  if (code == nullptr) {
     return false;
   }
-  auto* code_ptr = WriteMethodHeaderAndCode(
-      compiled_method, code_reserve, code_reserve + reserve_size, mapping_table_ptr,
-      vmap_table_ptr, gc_map_ptr);
-
-  __builtin___clear_cache(reinterpret_cast<char*>(code_ptr),
-                          reinterpret_cast<char*>(code_ptr + quick_code->size()));
 
   const size_t thumb_offset = compiled_method->CodeDelta();
-  const uint32_t code_offset = code_ptr - base + thumb_offset;
-  *out_method = OatFile::OatMethod(base, code_offset);
+  const uint32_t code_offset = sizeof(OatQuickMethodHeader) + thumb_offset;
+  *out_method = OatFile::OatMethod(code, code_offset);
   DCHECK_EQ(out_method->GetGcMap(), gc_map_ptr);
   DCHECK_EQ(out_method->GetMappingTable(), mapping_table_ptr);
   DCHECK_EQ(out_method->GetVmapTable(), vmap_table_ptr);
   DCHECK_EQ(out_method->GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
   DCHECK_EQ(out_method->GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
   DCHECK_EQ(out_method->GetFpSpillMask(), compiled_method->GetFpSpillMask());
-  VLOG(jit)  << "JIT added " << PrettyMethod(method) << "@" << method << " ccache_size="
-      << PrettySize(code_cache->CodeCacheSize()) << ": " << reinterpret_cast<void*>(code_ptr)
-      << "," << reinterpret_cast<void*>(code_ptr + code_size);
-  return true;
-}
-
-bool JitCompiler::MakeExecutable(CompiledMethod* compiled_method, ArtMethod* method) {
-  CHECK(method != nullptr);
-  CHECK(compiled_method != nullptr);
-  OatFile::OatMethod oat_method(nullptr, 0);
-  if (!AddToCodeCache(method, compiled_method, &oat_method)) {
-    return false;
-  }
-  // TODO: Flush instruction cache.
-  oat_method.LinkMethod(method);
-  CHECK(Runtime::Current()->GetJit()->GetCodeCache()->ContainsMethod(method))
-      << PrettyMethod(method);
+  VLOG(jit)
+      << "JIT added "
+      << PrettyMethod(method) << "@" << method
+      << " ccache_size=" << PrettySize(code_cache->CodeCacheSize()) << ": "
+      << reinterpret_cast<void*>(code + code_offset)
+      << "," << reinterpret_cast<void*>(code + code_offset + code_size);
   return true;
 }