Merge "Relocate DWARF using .oat_patches."
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 6d79248..ef47377 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -30,7 +30,7 @@
 #include "art_field-inl.h"
 #include "base/stl_util.h"
 #include "base/timing_logger.h"
-#include "class_linker.h"
+#include "class_linker-inl.h"
 #include "compiled_class.h"
 #include "compiled_method.h"
 #include "compiler.h"
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index 7200cda..e78ff90 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -20,7 +20,7 @@
 #include <stdio.h>
 #include <memory>
 
-#include "class_linker.h"
+#include "class_linker-inl.h"
 #include "common_compiler_test.h"
 #include "dex_file.h"
 #include "gc/heap.h"
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index 627a42e..cfd525c 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -21,7 +21,7 @@
 #include <vector>
 
 #include "base/unix_file/fd_file.h"
-#include "class_linker.h"
+#include "class_linker-inl.h"
 #include "common_compiler_test.h"
 #include "elf_writer.h"
 #include "gc/space/image_space.h"
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 6f8884a..2420254 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -25,7 +25,7 @@
 #include "art_field-inl.h"
 #include "base/logging.h"
 #include "base/unix_file/fd_file.h"
-#include "class_linker.h"
+#include "class_linker-inl.h"
 #include "compiled_method.h"
 #include "dex_file-inl.h"
 #include "driver/compiler_driver.h"
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index 70bfb81..4186891 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -164,6 +164,7 @@
   void CheckParameterAlignImpl();
   void MaxParamNumberImpl();
   void WithoutImplementationImpl();
+  void WithoutImplementationRefReturnImpl();
   void StackArgsIntsFirstImpl();
   void StackArgsFloatsFirstImpl();
   void StackArgsMixedImpl();
@@ -1494,6 +1495,20 @@
 
 JNI_TEST(WithoutImplementation)
 
+void JniCompilerTest::WithoutImplementationRefReturnImpl() {
+  // This will lead to error messages in the log.
+  ScopedLogSeverity sls(LogSeverity::FATAL);
+
+  SetUpForTest(false, "withoutImplementationRefReturn", "()Ljava/lang/Object;", nullptr);
+
+  env_->CallObjectMethod(jobj_, jmethod_);
+
+  EXPECT_TRUE(Thread::Current()->IsExceptionPending());
+  EXPECT_TRUE(env_->ExceptionCheck() == JNI_TRUE);
+}
+
+JNI_TEST(WithoutImplementationRefReturn)
+
 void Java_MyClassNatives_stackArgsIntsFirst(JNIEnv*, jclass, jint i1, jint i2, jint i3,
                                             jint i4, jint i5, jint i6, jint i7, jint i8, jint i9,
                                             jint i10, jfloat f1, jfloat f2, jfloat f3, jfloat f4,
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 62c9836..4de287e 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -36,6 +36,7 @@
 #include "mirror/art_method-inl.h"
 #include "mirror/array.h"
 #include "mirror/class_loader.h"
+#include "mirror/dex_cache-inl.h"
 #include "mirror/object-inl.h"
 #include "os.h"
 #include "output_stream.h"
diff --git a/compiler/utils/arena_bit_vector.cc b/compiler/utils/arena_bit_vector.cc
index ddc0c81..fbbfd84 100644
--- a/compiler/utils/arena_bit_vector.cc
+++ b/compiler/utils/arena_bit_vector.cc
@@ -16,6 +16,7 @@
 
 #include "arena_bit_vector.h"
 
+#include "base/allocator.h"
 #include "base/arena_allocator.h"
 
 namespace art {
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index 51cc7ac..329698c 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -883,6 +883,13 @@
 }
 
 
+void X86Assembler::filds(const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xDB);
+  EmitOperand(0, src);
+}
+
+
 void X86Assembler::fincstp() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xD9);
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index f3675ae..a933474 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -349,6 +349,7 @@
   void fistpl(const Address& dst);
   void fistps(const Address& dst);
   void fildl(const Address& src);
+  void filds(const Address& src);
 
   void fincstp();
   void ffree(const Immediate& index);
diff --git a/compiler/utils/x86/assembler_x86_test.cc b/compiler/utils/x86/assembler_x86_test.cc
index dba3b6b..f326e49 100644
--- a/compiler/utils/x86/assembler_x86_test.cc
+++ b/compiler/utils/x86/assembler_x86_test.cc
@@ -172,4 +172,22 @@
   DriverStr(expected, "lock_cmpxchg8b");
 }
 
+TEST_F(AssemblerX86Test, FPUIntegerLoad) {
+  GetAssembler()->filds(x86::Address(x86::Register(x86::ESP), 4));
+  GetAssembler()->fildl(x86::Address(x86::Register(x86::ESP), 12));
+  const char* expected =
+      "fildl 0x4(%ESP)\n"
+      "fildll 0xc(%ESP)\n";
+  DriverStr(expected, "FPUIntegerLoad");
+}
+
+TEST_F(AssemblerX86Test, FPUIntegerStore) {
+  GetAssembler()->fistps(x86::Address(x86::Register(x86::ESP), 16));
+  GetAssembler()->fistpl(x86::Address(x86::Register(x86::ESP), 24));
+  const char* expected =
+      "fistpl 0x10(%ESP)\n"
+      "fistpll 0x18(%ESP)\n";
+  DriverStr(expected, "FPUIntegerStore");
+}
+
 }  // namespace art
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index 638659d..32204a9 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -988,6 +988,13 @@
 }
 
 
+void X86_64Assembler::filds(const Address& src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0xDB);
+  EmitOperand(0, src);
+}
+
+
 void X86_64Assembler::fincstp() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xD9);
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 15b8b15..16ef70b 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -448,6 +448,7 @@
   void fistpl(const Address& dst);
   void fistps(const Address& dst);
   void fildl(const Address& src);
+  void filds(const Address& src);
 
   void fincstp();
   void ffree(const Immediate& index);
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 116190a..5ca0373 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -849,6 +849,24 @@
   DriverFn(&x87_fn, "x87");
 }
 
+TEST_F(AssemblerX86_64Test, FPUIntegerLoad) {
+  GetAssembler()->filds(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 4));
+  GetAssembler()->fildl(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 12));
+  const char* expected =
+      "fildl 0x4(%RSP)\n"
+      "fildll 0xc(%RSP)\n";
+  DriverStr(expected, "FPUIntegerLoad");
+}
+
+TEST_F(AssemblerX86_64Test, FPUIntegerStore) {
+  GetAssembler()->fistps(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 16));
+  GetAssembler()->fistpl(x86_64::Address(x86_64::CpuRegister(x86_64::RSP), 24));
+  const char* expected =
+      "fistpl 0x10(%RSP)\n"
+      "fistpll 0x18(%RSP)\n";
+  DriverStr(expected, "FPUIntegerStore");
+}
+
 ////////////////
 // CALL / JMP //
 ////////////////
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 10949e4..6af6f18 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -109,6 +109,11 @@
 
   UsageError("Usage: dex2oat [options]...");
   UsageError("");
+  UsageError("  -j<number>: specifies the number of threads used for compilation.");
+  UsageError("       Default is the number of detected hardware threads available on the");
+  UsageError("       host system.");
+  UsageError("      Example: -j12");
+  UsageError("");
   UsageError("  --dex-file=<dex-file>: specifies a .dex, .jar, or .apk file to compile.");
   UsageError("      Example: --dex-file=/system/framework/core.jar");
   UsageError("");
@@ -188,11 +193,6 @@
   UsageError("      Example: --compiler-filter=everything");
   UsageError("      Default: speed");
   UsageError("");
-  UsageError("  --huge-method-max=<method-instruction-count>: the threshold size for a huge");
-  UsageError("      method for compiler filter tuning.");
-  UsageError("      Example: --huge-method-max=%d", CompilerOptions::kDefaultHugeMethodThreshold);
-  UsageError("      Default: %d", CompilerOptions::kDefaultHugeMethodThreshold);
-  UsageError("");
   UsageError("  --huge-method-max=<method-instruction-count>: threshold size for a huge");
   UsageError("      method for compiler filter tuning.");
   UsageError("      Example: --huge-method-max=%d", CompilerOptions::kDefaultHugeMethodThreshold);
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index d7de119..9cccf7c 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -17,6 +17,7 @@
 #include <cstdio>
 
 #include "art_field-inl.h"
+#include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "entrypoints/quick/quick_entrypoints_enum.h"
 #include "mirror/art_method-inl.h"
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index aeb1273..a2625e2 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -21,6 +21,7 @@
 
 #include "base/logging.h"
 #include "class_linker.h"
+#include "gc_root-inl.h"
 #include "gc/accounting/card_table-inl.h"
 #include "jvalue.h"
 #include "mirror/dex_cache.h"
@@ -289,15 +290,14 @@
   const uint32_t field_index = GetDexFieldIndex();
   auto* declaring_class = GetDeclaringClass();
   if (UNLIKELY(declaring_class->IsProxyClass())) {
-    return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(),
-                                                                 GetTypeDescriptor());
+    return ProxyFindSystemClass(GetTypeDescriptor());
   }
   auto* dex_cache = declaring_class->GetDexCache();
   const DexFile* const dex_file = dex_cache->GetDexFile();
   const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index);
   mirror::Class* type = dex_cache->GetResolvedType(field_id.type_idx_);
   if (kResolve && UNLIKELY(type == nullptr)) {
-    type = Runtime::Current()->GetClassLinker()->ResolveType(field_id.type_idx_, this);
+    type = ResolveGetType(field_id.type_idx_);
     CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
   }
   return type;
@@ -323,9 +323,7 @@
   const auto& field_id = dex_file->GetFieldId(dex_field_index);
   auto* name = dex_cache->GetResolvedString(field_id.name_idx_);
   if (resolve && name == nullptr) {
-    StackHandleScope<1> hs(self);
-    name = Runtime::Current()->GetClassLinker()->ResolveString(
-        *dex_file, field_id.name_idx_, hs.NewHandle(dex_cache));
+    name = ResolveGetStringName(self, *dex_file, field_id.name_idx_, dex_cache);
   }
   return name;
 }
diff --git a/runtime/art_field.cc b/runtime/art_field.cc
index cdf8967..2aed440 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -17,7 +17,9 @@
 #include "art_field.h"
 
 #include "art_field-inl.h"
+#include "class_linker-inl.h"
 #include "gc/accounting/card_table-inl.h"
+#include "handle_scope.h"
 #include "mirror/object-inl.h"
 #include "mirror/object_array-inl.h"
 #include "runtime.h"
@@ -61,4 +63,20 @@
       FindInstanceFieldWithOffset(klass->GetSuperClass(), field_offset) : nullptr;
 }
 
+mirror::Class* ArtField::ProxyFindSystemClass(const char* descriptor) {
+  DCHECK(GetDeclaringClass()->IsProxyClass());
+  return Runtime::Current()->GetClassLinker()->FindSystemClass(Thread::Current(), descriptor);
+}
+
+mirror::Class* ArtField::ResolveGetType(uint32_t type_idx) {
+  return Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this);
+}
+
+mirror::String* ArtField::ResolveGetStringName(Thread* self, const DexFile& dex_file,
+                                               uint32_t string_idx, mirror::DexCache* dex_cache) {
+  StackHandleScope<1> hs(self);
+  return Runtime::Current()->GetClassLinker()->ResolveString(
+      dex_file, string_idx, hs.NewHandle(dex_cache));
+}
+
 }  // namespace art
diff --git a/runtime/art_field.h b/runtime/art_field.h
index 5bdbe71..16c46f0 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -188,6 +188,13 @@
   }
 
  private:
+  mirror::Class* ProxyFindSystemClass(const char* descriptor)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  mirror::Class* ResolveGetType(uint32_t type_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  mirror::String* ResolveGetStringName(Thread* self, const DexFile& dex_file, uint32_t string_idx,
+                                       mirror::DexCache* dex_cache)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   GcRoot<mirror::Class> declaring_class_;
 
   uint32_t access_flags_;
diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc
index 59d38ad..b53fa84 100644
--- a/runtime/base/arena_allocator.cc
+++ b/runtime/base/arena_allocator.cc
@@ -20,6 +20,7 @@
 
 #include "arena_allocator.h"
 #include "logging.h"
+#include "mem_map.h"
 #include "mutex.h"
 #include "thread-inl.h"
 #include <memcheck/memcheck.h>
@@ -141,6 +142,10 @@
   size_ = map_->Size();
 }
 
+MemMapArena::~MemMapArena() {
+  // Destroys MemMap via std::unique_ptr<>.
+}
+
 void MemMapArena::Release() {
   if (bytes_allocated_ > 0) {
     map_->MadviseDontNeedAndZero();
diff --git a/runtime/base/arena_allocator.h b/runtime/base/arena_allocator.h
index 3a86b61..ab5968c 100644
--- a/runtime/base/arena_allocator.h
+++ b/runtime/base/arena_allocator.h
@@ -22,7 +22,6 @@
 
 #include "debug_stack.h"
 #include "macros.h"
-#include "mem_map.h"
 #include "mutex.h"
 #include "utils.h"
 
@@ -33,6 +32,7 @@
 class ArenaAllocator;
 class ArenaStack;
 class ScopedArenaAllocator;
+class MemMap;
 class MemStats;
 
 template <typename T>
@@ -166,7 +166,7 @@
 class MemMapArena FINAL : public Arena {
  public:
   explicit MemMapArena(size_t size, bool low_4gb);
-  virtual ~MemMapArena() { }
+  virtual ~MemMapArena();
   void Release() OVERRIDE;
 
  private:
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 12fe863..c074b54 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -415,9 +415,8 @@
 
 static Thread* DecodeThread(ScopedObjectAccessUnchecked& soa, JDWP::ObjectId thread_id,
                             JDWP::JdwpError* error)
-    EXCLUSIVE_LOCKS_REQUIRED(Locks::thread_list_lock_)
-    LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+    LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::thread_suspend_count_lock_) {
   mirror::Object* thread_peer = Dbg::GetObjectRegistry()->Get<mirror::Object*>(thread_id, error);
   if (thread_peer == nullptr) {
     // This isn't even an object.
@@ -432,6 +431,7 @@
     return nullptr;
   }
 
+  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
   Thread* thread = Thread::FromManagedThread(soa, thread_peer);
   // If thread is null then this a java.lang.Thread without a Thread*. Must be a un-started or a
   // zombie.
@@ -856,17 +856,13 @@
   };
 
   ScopedObjectAccessUnchecked soa(Thread::Current());
-  Thread* thread;
-  {
-    MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
-    JDWP::JdwpError error;
-    thread = DecodeThread(soa, thread_id, &error);
-    if (thread == nullptr) {
-      return error;
-    }
-    if (!IsSuspendedForDebugger(soa, thread)) {
-      return JDWP::ERR_THREAD_NOT_SUSPENDED;
-    }
+  JDWP::JdwpError error;
+  Thread* thread = DecodeThread(soa, thread_id, &error);
+  if (thread == nullptr) {
+    return error;
+  }
+  if (!IsSuspendedForDebugger(soa, thread)) {
+    return JDWP::ERR_THREAD_NOT_SUSPENDED;
   }
   std::unique_ptr<Context> context(Context::Create());
   OwnedMonitorVisitor visitor(thread, context.get(), monitors, stack_depths);
@@ -876,21 +872,17 @@
 
 JDWP::JdwpError Dbg::GetContendedMonitor(JDWP::ObjectId thread_id,
                                          JDWP::ObjectId* contended_monitor) {
-  mirror::Object* contended_monitor_obj;
   ScopedObjectAccessUnchecked soa(Thread::Current());
   *contended_monitor = 0;
-  {
-    MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
-    JDWP::JdwpError error;
-    Thread* thread = DecodeThread(soa, thread_id, &error);
-    if (thread == nullptr) {
-      return error;
-    }
-    if (!IsSuspendedForDebugger(soa, thread)) {
-      return JDWP::ERR_THREAD_NOT_SUSPENDED;
-    }
-    contended_monitor_obj = Monitor::GetContendedMonitor(thread);
+  JDWP::JdwpError error;
+  Thread* thread = DecodeThread(soa, thread_id, &error);
+  if (thread == nullptr) {
+    return error;
   }
+  if (!IsSuspendedForDebugger(soa, thread)) {
+    return JDWP::ERR_THREAD_NOT_SUSPENDED;
+  }
+  mirror::Object* contended_monitor_obj = Monitor::GetContendedMonitor(thread);
   // Add() requires the thread_list_lock_ not held to avoid the lock
   // level violation.
   *contended_monitor = gRegistry->Add(contended_monitor_obj);
@@ -1400,7 +1392,9 @@
 }
 
 void Dbg::SetJdwpLocation(JDWP::JdwpLocation* location, mirror::ArtMethod* m, uint32_t dex_pc)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+    LOCKS_EXCLUDED(Locks::thread_list_lock_,
+                   Locks::thread_suspend_count_lock_) {
   if (m == nullptr) {
     memset(location, 0, sizeof(*location));
   } else {
@@ -1890,7 +1884,6 @@
 
 JDWP::JdwpError Dbg::GetThreadName(JDWP::ObjectId thread_id, std::string* name) {
   ScopedObjectAccessUnchecked soa(Thread::Current());
-  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
   JDWP::JdwpError error;
   Thread* thread = DecodeThread(soa, thread_id, &error);
   UNUSED(thread);
@@ -1920,11 +1913,8 @@
   }
   ScopedAssertNoThreadSuspension ants(soa.Self(), "Debugger: GetThreadGroup");
   // Okay, so it's an object, but is it actually a thread?
-  {
-    MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
-    Thread* thread = DecodeThread(soa, thread_id, &error);
-    UNUSED(thread);
-  }
+  Thread* thread = DecodeThread(soa, thread_id, &error);
+  UNUSED(thread);
   if (error == JDWP::ERR_THREAD_NOT_ALIVE) {
     // Zombie threads are in the null group.
     expandBufAddObjectId(pReply, JDWP::ObjectId(0));
@@ -2112,7 +2102,6 @@
 
   *pSuspendStatus = JDWP::SUSPEND_STATUS_NOT_SUSPENDED;
 
-  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
   JDWP::JdwpError error;
   Thread* thread = DecodeThread(soa, thread_id, &error);
   if (error != JDWP::ERR_NONE) {
@@ -2133,7 +2122,6 @@
 
 JDWP::JdwpError Dbg::GetThreadDebugSuspendCount(JDWP::ObjectId thread_id, JDWP::ExpandBuf* pReply) {
   ScopedObjectAccess soa(Thread::Current());
-  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
   JDWP::JdwpError error;
   Thread* thread = DecodeThread(soa, thread_id, &error);
   if (error != JDWP::ERR_NONE) {
@@ -2146,7 +2134,6 @@
 
 JDWP::JdwpError Dbg::Interrupt(JDWP::ObjectId thread_id) {
   ScopedObjectAccess soa(Thread::Current());
-  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
   JDWP::JdwpError error;
   Thread* thread = DecodeThread(soa, thread_id, &error);
   if (error != JDWP::ERR_NONE) {
@@ -2225,7 +2212,6 @@
 
 JDWP::JdwpError Dbg::GetThreadFrameCount(JDWP::ObjectId thread_id, size_t* result) {
   ScopedObjectAccess soa(Thread::Current());
-  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
   JDWP::JdwpError error;
   *result = 0;
   Thread* thread = DecodeThread(soa, thread_id, &error);
@@ -2251,9 +2237,7 @@
       expandBufAdd4BE(buf_, frame_count_);
     }
 
-    // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
-    // annotalysis.
-    virtual bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS {
+    bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
       if (GetMethod()->IsRuntimeMethod()) {
         return true;  // The debugger can't do anything useful with a frame that has no Method*.
       }
@@ -2280,7 +2264,6 @@
   };
 
   ScopedObjectAccessUnchecked soa(Thread::Current());
-  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
   JDWP::JdwpError error;
   Thread* thread = DecodeThread(soa, thread_id, &error);
   if (error != JDWP::ERR_NONE) {
@@ -2387,17 +2370,13 @@
 JDWP::JdwpError Dbg::GetThisObject(JDWP::ObjectId thread_id, JDWP::FrameId frame_id,
                                    JDWP::ObjectId* result) {
   ScopedObjectAccessUnchecked soa(Thread::Current());
-  Thread* thread;
-  {
-    MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
-    JDWP::JdwpError error;
-    thread = DecodeThread(soa, thread_id, &error);
-    if (error != JDWP::ERR_NONE) {
-      return error;
-    }
-    if (!IsSuspendedForDebugger(soa, thread)) {
-      return JDWP::ERR_THREAD_NOT_SUSPENDED;
-    }
+  JDWP::JdwpError error;
+  Thread* thread = DecodeThread(soa, thread_id, &error);
+  if (error != JDWP::ERR_NONE) {
+    return error;
+  }
+  if (!IsSuspendedForDebugger(soa, thread)) {
+    return JDWP::ERR_THREAD_NOT_SUSPENDED;
   }
   std::unique_ptr<Context> context(Context::Create());
   GetThisVisitor visitor(thread, context.get(), frame_id);
@@ -2444,17 +2423,13 @@
   JDWP::FrameId frame_id = request->ReadFrameId();
 
   ScopedObjectAccessUnchecked soa(Thread::Current());
-  Thread* thread;
-  {
-    MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
-    JDWP::JdwpError error;
-    thread = DecodeThread(soa, thread_id, &error);
-    if (error != JDWP::ERR_NONE) {
-      return error;
-    }
-    if (!IsSuspendedForDebugger(soa, thread)) {
-      return JDWP::ERR_THREAD_NOT_SUSPENDED;
-    }
+  JDWP::JdwpError error;
+  Thread* thread = DecodeThread(soa, thread_id, &error);
+  if (error != JDWP::ERR_NONE) {
+    return error;
+  }
+  if (!IsSuspendedForDebugger(soa, thread)) {
+    return JDWP::ERR_THREAD_NOT_SUSPENDED;
   }
   // Find the frame with the given frame_id.
   std::unique_ptr<Context> context(Context::Create());
@@ -2475,7 +2450,7 @@
 
     size_t width = Dbg::GetTagWidth(reqSigByte);
     uint8_t* ptr = expandBufAddSpace(pReply, width + 1);
-    JDWP::JdwpError error = Dbg::GetLocalValue(visitor, soa, slot, reqSigByte, ptr, width);
+    error = Dbg::GetLocalValue(visitor, soa, slot, reqSigByte, ptr, width);
     if (error != JDWP::ERR_NONE) {
       return error;
     }
@@ -2619,17 +2594,13 @@
   JDWP::FrameId frame_id = request->ReadFrameId();
 
   ScopedObjectAccessUnchecked soa(Thread::Current());
-  Thread* thread;
-  {
-    MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
-    JDWP::JdwpError error;
-    thread = DecodeThread(soa, thread_id, &error);
-    if (error != JDWP::ERR_NONE) {
-      return error;
-    }
-    if (!IsSuspendedForDebugger(soa, thread)) {
-      return JDWP::ERR_THREAD_NOT_SUSPENDED;
-    }
+  JDWP::JdwpError error;
+  Thread* thread = DecodeThread(soa, thread_id, &error);
+  if (error != JDWP::ERR_NONE) {
+    return error;
+  }
+  if (!IsSuspendedForDebugger(soa, thread)) {
+    return JDWP::ERR_THREAD_NOT_SUSPENDED;
   }
   // Find the frame with the given frame_id.
   std::unique_ptr<Context> context(Context::Create());
@@ -2648,7 +2619,7 @@
     uint64_t value = request->ReadValue(width);
 
     VLOG(jdwp) << "    --> slot " << slot << " " << sigByte << " " << value;
-    JDWP::JdwpError error = Dbg::SetLocalValue(visitor, slot, sigByte, value, width);
+    error = Dbg::SetLocalValue(visitor, slot, sigByte, value, width);
     if (error != JDWP::ERR_NONE) {
       return error;
     }
@@ -3495,10 +3466,7 @@
       self_suspend_(false),
       other_suspend_(false) {
     ScopedObjectAccessUnchecked soa(self);
-    {
-      MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
-      thread_ = DecodeThread(soa, thread_id, &error_);
-    }
+    thread_ = DecodeThread(soa, thread_id, &error_);
     if (error_ == JDWP::ERR_NONE) {
       if (thread_ == soa.Self()) {
         self_suspend_ = true;
@@ -3668,7 +3636,6 @@
 
 void Dbg::UnconfigureStep(JDWP::ObjectId thread_id) {
   ScopedObjectAccessUnchecked soa(Thread::Current());
-  MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
   JDWP::JdwpError error;
   Thread* thread = DecodeThread(soa, thread_id, &error);
   if (error == JDWP::ERR_NONE) {
@@ -3718,7 +3685,6 @@
   Thread* self = Thread::Current();
   {
     ScopedObjectAccessUnchecked soa(self);
-    MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
     JDWP::JdwpError error;
     targetThread = DecodeThread(soa, thread_id, &error);
     if (error != JDWP::ERR_NONE) {
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index c1276b5..e478d2a 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -68,7 +68,6 @@
   PopLocalReferences(saved_local_ref_cookie, self);
 }
 
-
 extern void JniMethodEndSynchronized(uint32_t saved_local_ref_cookie, jobject locked,
                                      Thread* self) {
   GoToRunnable(self);
@@ -76,38 +75,34 @@
   PopLocalReferences(saved_local_ref_cookie, self);
 }
 
-extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie,
-                                                 Thread* self) {
-  GoToRunnable(self);
-  mirror::Object* o = self->DecodeJObject(result);  // Must decode before pop.
+// Common result handling for EndWithReference.
+static mirror::Object* JniMethodEndWithReferenceHandleResult(jobject result,
+                                                             uint32_t saved_local_ref_cookie,
+                                                             Thread* self)
+    NO_THREAD_SAFETY_ANALYSIS {
+  // Must decode before pop. The 'result' may not be valid in case of an exception, though.
+  mirror::Object* o = self->IsExceptionPending() ? nullptr : self->DecodeJObject(result);
   PopLocalReferences(saved_local_ref_cookie, self);
   // Process result.
   if (UNLIKELY(self->GetJniEnv()->check_jni)) {
-    if (self->IsExceptionPending()) {
-      return NULL;
-    }
     CheckReferenceResult(o, self);
   }
   VerifyObject(o);
   return o;
 }
 
+extern mirror::Object* JniMethodEndWithReference(jobject result, uint32_t saved_local_ref_cookie,
+                                                 Thread* self) {
+  GoToRunnable(self);
+  return JniMethodEndWithReferenceHandleResult(result, saved_local_ref_cookie, self);
+}
+
 extern mirror::Object* JniMethodEndWithReferenceSynchronized(jobject result,
                                                              uint32_t saved_local_ref_cookie,
                                                              jobject locked, Thread* self) {
   GoToRunnable(self);
-  UnlockJniSynchronizedMethod(locked, self);  // Must decode before pop.
-  mirror::Object* o = self->DecodeJObject(result);
-  PopLocalReferences(saved_local_ref_cookie, self);
-  // Process result.
-  if (UNLIKELY(self->GetJniEnv()->check_jni)) {
-    if (self->IsExceptionPending()) {
-      return NULL;
-    }
-    CheckReferenceResult(o, self);
-  }
-  VerifyObject(o);
-  return o;
+  UnlockJniSynchronizedMethod(locked, self);
+  return JniMethodEndWithReferenceHandleResult(result, saved_local_ref_cookie, self);
 }
 
 }  // namespace art
diff --git a/runtime/gc/accounting/bitmap.cc b/runtime/gc/accounting/bitmap.cc
index 20984fd..13fcdb3 100644
--- a/runtime/gc/accounting/bitmap.cc
+++ b/runtime/gc/accounting/bitmap.cc
@@ -35,6 +35,10 @@
   CHECK_NE(bitmap_size, 0U);
 }
 
+Bitmap::~Bitmap() {
+  // Destroys MemMap via std::unique_ptr<>.
+}
+
 MemMap* Bitmap::AllocateMemMap(const std::string& name, size_t num_bits) {
   const size_t bitmap_size = RoundUp(
       RoundUp(num_bits, kBitsPerBitmapWord) / kBitsPerBitmapWord * sizeof(uintptr_t), kPageSize);
diff --git a/runtime/gc/accounting/bitmap.h b/runtime/gc/accounting/bitmap.h
index cf2c293..b294d49 100644
--- a/runtime/gc/accounting/bitmap.h
+++ b/runtime/gc/accounting/bitmap.h
@@ -103,6 +103,7 @@
   static constexpr size_t kBitsPerBitmapWord = sizeof(uintptr_t) * kBitsPerByte;
 
   Bitmap(MemMap* mem_map, size_t bitmap_size);
+  ~Bitmap();
 
   // Allocate the mem-map for a bitmap based on how many bits are required.
   static MemMap* AllocateMemMap(const std::string& name, size_t num_bits);
diff --git a/runtime/gc/accounting/card_table-inl.h b/runtime/gc/accounting/card_table-inl.h
index 83ad33e..b936d93 100644
--- a/runtime/gc/accounting/card_table-inl.h
+++ b/runtime/gc/accounting/card_table-inl.h
@@ -20,6 +20,7 @@
 #include "atomic.h"
 #include "base/logging.h"
 #include "card_table.h"
+#include "mem_map.h"
 #include "space_bitmap.h"
 #include "utils.h"
 
@@ -223,6 +224,12 @@
   return card_addr;
 }
 
+inline bool CardTable::IsValidCard(const uint8_t* card_addr) const {
+  uint8_t* begin = mem_map_->Begin() + offset_;
+  uint8_t* end = mem_map_->End();
+  return card_addr >= begin && card_addr < end;
+}
+
 inline void CardTable::CheckCardValid(uint8_t* card) const {
   DCHECK(IsValidCard(card))
       << " card_addr: " << reinterpret_cast<const void*>(card)
diff --git a/runtime/gc/accounting/card_table.cc b/runtime/gc/accounting/card_table.cc
index ad1f192..7879632 100644
--- a/runtime/gc/accounting/card_table.cc
+++ b/runtime/gc/accounting/card_table.cc
@@ -21,6 +21,7 @@
 #include "gc/heap.h"
 #include "gc/space/space.h"
 #include "heap_bitmap.h"
+#include "mem_map.h"
 #include "runtime.h"
 #include "utils.h"
 
@@ -90,6 +91,10 @@
     : mem_map_(mem_map), biased_begin_(biased_begin), offset_(offset) {
 }
 
+CardTable::~CardTable() {
+  // Destroys MemMap via std::unique_ptr<>.
+}
+
 void CardTable::ClearSpaceCards(space::ContinuousSpace* space) {
   // TODO: clear just the range of the table that has been modified
   uint8_t* card_start = CardFromAddr(space->Begin());
diff --git a/runtime/gc/accounting/card_table.h b/runtime/gc/accounting/card_table.h
index 3ea7651..896cce5 100644
--- a/runtime/gc/accounting/card_table.h
+++ b/runtime/gc/accounting/card_table.h
@@ -21,10 +21,11 @@
 
 #include "base/mutex.h"
 #include "globals.h"
-#include "mem_map.h"
 
 namespace art {
 
+class MemMap;
+
 namespace mirror {
   class Object;
 }  // namespace mirror
@@ -52,6 +53,7 @@
   static constexpr uint8_t kCardDirty = 0x70;
 
   static CardTable* Create(const uint8_t* heap_begin, size_t heap_capacity);
+  ~CardTable();
 
   // Set the card associated with the given address to GC_CARD_DIRTY.
   ALWAYS_INLINE void MarkCard(const void *addr) {
@@ -130,11 +132,7 @@
   CardTable(MemMap* begin, uint8_t* biased_begin, size_t offset);
 
   // Returns true iff the card table address is within the bounds of the card table.
-  bool IsValidCard(const uint8_t* card_addr) const {
-    uint8_t* begin = mem_map_->Begin() + offset_;
-    uint8_t* end = mem_map_->End();
-    return card_addr >= begin && card_addr < end;
-  }
+  bool IsValidCard(const uint8_t* card_addr) const ALWAYS_INLINE;
 
   void CheckCardValid(uint8_t* card) const ALWAYS_INLINE;
 
diff --git a/runtime/gc/accounting/mod_union_table_test.cc b/runtime/gc/accounting/mod_union_table_test.cc
index 94bb3f5..043b558 100644
--- a/runtime/gc/accounting/mod_union_table_test.cc
+++ b/runtime/gc/accounting/mod_union_table_test.cc
@@ -16,6 +16,7 @@
 
 #include "mod_union_table-inl.h"
 
+#include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "gc/space/space-inl.h"
 #include "mirror/array-inl.h"
diff --git a/runtime/gc/allocator/rosalloc.cc b/runtime/gc/allocator/rosalloc.cc
index f64a4ff..515f124 100644
--- a/runtime/gc/allocator/rosalloc.cc
+++ b/runtime/gc/allocator/rosalloc.cc
@@ -18,6 +18,7 @@
 
 #include "base/mutex-inl.h"
 #include "gc/space/valgrind_settings.h"
+#include "mem_map.h"
 #include "mirror/class-inl.h"
 #include "mirror/object.h"
 #include "mirror/object-inl.h"
diff --git a/runtime/gc/allocator/rosalloc.h b/runtime/gc/allocator/rosalloc.h
index d1e7ad9..a54edcc 100644
--- a/runtime/gc/allocator/rosalloc.h
+++ b/runtime/gc/allocator/rosalloc.h
@@ -30,11 +30,13 @@
 #include "base/mutex.h"
 #include "base/logging.h"
 #include "globals.h"
-#include "mem_map.h"
 #include "thread.h"
 #include "utils.h"
 
 namespace art {
+
+class MemMap;
+
 namespace gc {
 namespace allocator {
 
diff --git a/runtime/gc/heap_test.cc b/runtime/gc/heap_test.cc
index 14d78d8..a3cefd9 100644
--- a/runtime/gc/heap_test.cc
+++ b/runtime/gc/heap_test.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "gc/accounting/card_table-inl.h"
 #include "gc/accounting/space_bitmap-inl.h"
diff --git a/runtime/indirect_reference_table_test.cc b/runtime/indirect_reference_table_test.cc
index 1156cf5..fe1b8f0 100644
--- a/runtime/indirect_reference_table_test.cc
+++ b/runtime/indirect_reference_table_test.cc
@@ -16,6 +16,7 @@
 
 #include "indirect_reference_table-inl.h"
 
+#include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "mirror/object-inl.h"
 #include "scoped_thread_state_change.h"
diff --git a/runtime/jdwp/object_registry.cc b/runtime/jdwp/object_registry.cc
index 99a005d..a42a58f 100644
--- a/runtime/jdwp/object_registry.cc
+++ b/runtime/jdwp/object_registry.cc
@@ -50,6 +50,10 @@
 
   Thread* const self = Thread::Current();
   self->AssertNoPendingException();
+  // Object::IdentityHashCode may cause these locks to be held so check we do not already
+  // hold them.
+  Locks::thread_list_lock_->AssertNotHeld(self);
+  Locks::thread_suspend_count_lock_->AssertNotHeld(self);
 
   StackHandleScope<1> hs(self);
   Handle<mirror::Object> obj_h(hs.NewHandle(o));
diff --git a/runtime/jdwp/object_registry.h b/runtime/jdwp/object_registry.h
index 0693f33..27a4e55 100644
--- a/runtime/jdwp/object_registry.h
+++ b/runtime/jdwp/object_registry.h
@@ -62,9 +62,13 @@
   ObjectRegistry();
 
   JDWP::ObjectId Add(mirror::Object* o)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(Locks::thread_list_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      LOCKS_EXCLUDED(Locks::thread_list_lock_,
+                     Locks::thread_suspend_count_lock_);
   JDWP::RefTypeId AddRefType(mirror::Class* c)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(Locks::thread_list_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      LOCKS_EXCLUDED(Locks::thread_list_lock_,
+                     Locks::thread_suspend_count_lock_);
 
   template<typename T> T Get(JDWP::ObjectId id, JDWP::JdwpError* error)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -96,7 +100,9 @@
  private:
   JDWP::ObjectId InternalAdd(mirror::Object* o)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      LOCKS_EXCLUDED(lock_, Locks::thread_list_lock_);
+      LOCKS_EXCLUDED(lock_,
+                     Locks::thread_list_lock_,
+                     Locks::thread_suspend_count_lock_);
 
   mirror::Object* InternalGet(JDWP::ObjectId id, JDWP::JdwpError* error)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 5b72e5a..f4656ec 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -21,7 +21,6 @@
 
 #include "art_field-inl.h"
 #include "art_method-inl.h"
-#include "class_linker-inl.h"
 #include "class_loader.h"
 #include "common_throws.h"
 #include "dex_cache.h"
@@ -39,12 +38,8 @@
 
 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
 inline uint32_t Class::GetObjectSize() {
-  if (kIsDebugBuild) {
-    // Use a local variable as (D)CHECK can't handle the space between
-    // the two template params.
-    bool is_variable_size = IsVariableSize<kVerifyFlags, kReadBarrierOption>();
-    CHECK(!is_variable_size) << " class=" << PrettyTypeOf(this);
-  }
+  // Note: Extra parentheses to avoid the comma being interpreted as macro parameter separator.
+  DCHECK((!IsVariableSize<kVerifyFlags, kReadBarrierOption>())) << " class=" << PrettyTypeOf(this);
   return GetField32(ObjectSizeOffset());
 }
 
@@ -706,7 +701,7 @@
   } else if (IsPrimitive()) {
     return strcmp(Primitive::Descriptor(GetPrimitiveType()), match) == 0;
   } else if (IsProxyClass()) {
-    return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this) == match;
+    return ProxyDescriptorEquals(match);
   } else {
     const DexFile& dex_file = GetDexFile();
     const DexFile::TypeId& type_id = dex_file.GetTypeId(GetClassDef()->class_idx_);
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 8fb8147..2afb4af 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -18,7 +18,7 @@
 
 #include "art_field-inl.h"
 #include "art_method-inl.h"
-#include "class_linker.h"
+#include "class_linker-inl.h"
 #include "class_loader.h"
 #include "class-inl.h"
 #include "dex_cache.h"
@@ -871,5 +871,10 @@
   return new_class->AsClass();
 }
 
+bool Class::ProxyDescriptorEquals(const char* match) {
+  DCHECK(IsProxyClass());
+  return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this) == match;
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 92493bc..20f2387 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1095,6 +1095,8 @@
   ArtField* GetSFieldsUnchecked() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   ArtField* GetIFieldsUnchecked() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  bool ProxyDescriptorEquals(const char* match) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   // defining class loader, or NULL for the "bootstrap" system loader
   HeapReference<ClassLoader> class_loader_;
 
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
index 7db1811..9820db7 100644
--- a/runtime/mirror/field-inl.h
+++ b/runtime/mirror/field-inl.h
@@ -20,6 +20,7 @@
 #include "field.h"
 
 #include "art_field-inl.h"
+#include "mirror/dex_cache-inl.h"
 #include "runtime-inl.h"
 
 namespace art {
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index bfd5d4d..343c9bc 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -111,7 +111,10 @@
 
   Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  int32_t IdentityHashCode() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  int32_t IdentityHashCode() const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      LOCKS_EXCLUDED(Locks::thread_list_lock_,
+                     Locks::thread_suspend_count_lock_);
 
   static MemberOffset MonitorOffset() {
     return OFFSET_OF_OBJECT_MEMBER(Object, monitor_);
diff --git a/runtime/monitor_test.cc b/runtime/monitor_test.cc
index 6d1e721..2351463 100644
--- a/runtime/monitor_test.cc
+++ b/runtime/monitor_test.cc
@@ -20,6 +20,7 @@
 #include <string>
 
 #include "atomic.h"
+#include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "handle_scope-inl.h"
 #include "mirror/class-inl.h"
diff --git a/runtime/native/java_lang_DexCache.cc b/runtime/native/java_lang_DexCache.cc
index 8944270..1198c2e 100644
--- a/runtime/native/java_lang_DexCache.cc
+++ b/runtime/native/java_lang_DexCache.cc
@@ -18,7 +18,7 @@
 
 #include "dex_file.h"
 #include "jni_internal.h"
-#include "mirror/dex_cache.h"
+#include "mirror/dex_cache-inl.h"
 #include "mirror/object-inl.h"
 #include "scoped_fast_native_object_access.h"
 #include "well_known_classes.h"
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 37c6353..0c942d2 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -26,7 +26,7 @@
 #include <gtest/gtest.h>
 
 #include "art_field-inl.h"
-#include "class_linker.h"
+#include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "compiler_callbacks.h"
 #include "mem_map.h"
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index a3156b4..6061f73 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -18,6 +18,7 @@
 #include <vector>
 
 #include "art_field-inl.h"
+#include "class_linker-inl.h"
 #include "common_compiler_test.h"
 #include "scoped_thread_state_change.h"
 
diff --git a/runtime/quick/inline_method_analyser.cc b/runtime/quick/inline_method_analyser.cc
index efaa0ac..9cf4b16 100644
--- a/runtime/quick/inline_method_analyser.cc
+++ b/runtime/quick/inline_method_analyser.cc
@@ -17,6 +17,7 @@
 #include "inline_method_analyser.h"
 
 #include "art_field-inl.h"
+#include "class_linker-inl.h"
 #include "dex_file-inl.h"
 #include "dex_instruction.h"
 #include "dex_instruction-inl.h"
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 66d38ce..543b9dc 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -54,7 +54,7 @@
 #include "base/arena_allocator.h"
 #include "base/dumpable.h"
 #include "base/unix_file/fd_file.h"
-#include "class_linker.h"
+#include "class_linker-inl.h"
 #include "compiler_callbacks.h"
 #include "debugger.h"
 #include "elf_file.h"
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index 9792eca..aee2c54 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -17,6 +17,7 @@
 #include "transaction.h"
 
 #include "art_field-inl.h"
+#include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "mirror/array-inl.h"
 #include "mirror/art_method-inl.h"
diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc
index 623a3ec..aa7bc64 100644
--- a/runtime/utils_test.cc
+++ b/runtime/utils_test.cc
@@ -16,6 +16,7 @@
 
 #include "utils.h"
 
+#include "class_linker-inl.h"
 #include "common_runtime_test.h"
 #include "mirror/array.h"
 #include "mirror/array-inl.h"
diff --git a/test/MyClassNatives/MyClassNatives.java b/test/MyClassNatives/MyClassNatives.java
index fab153b..8b4a9a4 100644
--- a/test/MyClassNatives/MyClassNatives.java
+++ b/test/MyClassNatives/MyClassNatives.java
@@ -80,6 +80,7 @@
         Object o248, Object o249, Object o250, Object o251, Object o252, Object o253);
 
     native void withoutImplementation();
+    native Object withoutImplementationRefReturn();
 
     native static void stackArgsIntsFirst(int i1, int i2, int i3, int i4, int i5, int i6, int i7,
         int i8, int i9, int i10, float f1, float f2, float f3, float f4, float f5, float f6,