Merge "x86_64: Use RegClassBySize() for field accesses"
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index dd9f414..de0e3bd 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -117,7 +117,6 @@
   runtime/monitor_pool_test.cc \
   runtime/monitor_test.cc \
   runtime/parsed_options_test.cc \
-  runtime/proxy_test.cc \
   runtime/reference_table_test.cc \
   runtime/thread_pool_test.cc \
   runtime/transaction_test.cc \
@@ -128,6 +127,7 @@
 
 COMPILER_GTEST_COMMON_SRC_FILES := \
   runtime/jni_internal_test.cc \
+  runtime/proxy_test.cc \
   runtime/reflection_test.cc \
   compiler/dex/global_value_numbering_test.cc \
   compiler/dex/local_value_numbering_test.cc \
diff --git a/runtime/Android.mk b/runtime/Android.mk
index f55d3fb..1f2f86e 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -106,7 +106,7 @@
   mirror/string.cc \
   mirror/throwable.cc \
   monitor.cc \
-  native_bridge.cc \
+  native_bridge_art_interface.cc \
   native/dalvik_system_DexFile.cc \
   native/dalvik_system_VMDebug.cc \
   native/dalvik_system_VMRuntime.cc \
@@ -417,7 +417,7 @@
   LOCAL_C_INCLUDES += $$(ART_C_INCLUDES)
   LOCAL_C_INCLUDES += art/sigchainlib
 
-  LOCAL_SHARED_LIBRARIES += liblog libnativehelper
+  LOCAL_SHARED_LIBRARIES += liblog libnativehelper libnativebridge
   include external/libcxx/libcxx.mk
   LOCAL_SHARED_LIBRARIES += libbacktrace_libc++
   ifeq ($$(art_target_or_host),target)
diff --git a/runtime/arch/mips/asm_support_mips.h b/runtime/arch/mips/asm_support_mips.h
index 4db5ea6..6add93b 100644
--- a/runtime/arch/mips/asm_support_mips.h
+++ b/runtime/arch/mips/asm_support_mips.h
@@ -22,9 +22,9 @@
 // Offset of field Thread::tls32_.state_and_flags verified in InitCpu
 #define THREAD_FLAGS_OFFSET 0
 // Offset of field Thread::tlsPtr_.card_table verified in InitCpu
-#define THREAD_CARD_TABLE_OFFSET 112
+#define THREAD_CARD_TABLE_OFFSET 120
 // Offset of field Thread::tlsPtr_.exception verified in InitCpu
-#define THREAD_EXCEPTION_OFFSET 116
+#define THREAD_EXCEPTION_OFFSET 124
 
 #define FRAME_SIZE_SAVE_ALL_CALLEE_SAVE 64
 #define FRAME_SIZE_REFS_ONLY_CALLEE_SAVE 64
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 1e91145..3ab4ef8 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3567,19 +3567,13 @@
       proxy_class->GetDirectMethods();
   CHECK_EQ(proxy_direct_methods->GetLength(), 16);
   mirror::ArtMethod* proxy_constructor = proxy_direct_methods->Get(2);
+  // Clone the existing constructor of Proxy (our constructor would just invoke it so steal its
+  // code_ too)
   mirror::ArtMethod* constructor = down_cast<mirror::ArtMethod*>(proxy_constructor->Clone(self));
   if (constructor == nullptr) {
     CHECK(self->IsExceptionPending());  // OOME.
     return nullptr;
   }
-  // Make the proxy constructor's code always point to the uninstrumented code. This avoids
-  // getting a method enter event for the proxy constructor as the proxy constructor doesn't
-  // have an activation.
-  bool have_portable_code;
-  constructor->SetEntryPointFromQuickCompiledCode(GetQuickOatCodeFor(proxy_constructor));
-  constructor->SetEntryPointFromPortableCompiledCode(GetPortableOatCodeFor(proxy_constructor,
-                                                                           &have_portable_code));
-
   // Make this constructor public and fix the class to be our Proxy version
   constructor->SetAccessFlags((constructor->GetAccessFlags() & ~kAccProtected) | kAccPublic);
   constructor->SetDeclaringClass(klass.Get());
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index ab4a2bb..eed6f71 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -285,19 +285,6 @@
   return StringPrintf("%s/framework/%s.jar", GetAndroidRoot(), jar_prefix.c_str());
 }
 
-std::string CommonRuntimeTest::GetLibCoreOatFileName() {
-  return GetOatFileName("core");
-}
-
-std::string CommonRuntimeTest::GetOatFileName(const std::string& oat_prefix) {
-  if (IsHost()) {
-    const char* host_dir = getenv("ANDROID_HOST_OUT");
-    CHECK(host_dir != nullptr);
-    return StringPrintf("%s/framework/%s.art", host_dir, oat_prefix.c_str());
-  }
-  return StringPrintf("%s/framework/%s.art", GetAndroidRoot(), oat_prefix.c_str());
-}
-
 std::string CommonRuntimeTest::GetTestAndroidRoot() {
   if (IsHost()) {
     const char* host_dir = getenv("ANDROID_HOST_OUT");
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index ddb6c81..1ca6eb3 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -97,12 +97,6 @@
   // Gets the path of the specified dex file for host or target.
   std::string GetDexFileName(const std::string& jar_prefix);
 
-  // Gets the path of the libcore oat file.
-  std::string GetLibCoreOatFileName();
-
-  // Gets the path of the specified oat file for host or target.
-  std::string GetOatFileName(const std::string& oat_prefix);
-
   std::string GetTestAndroidRoot();
 
   std::vector<const DexFile*> OpenTestDexFiles(const char* name)
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 6179b5e..35294d4 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1189,20 +1189,29 @@
  public:
   ~DebugAbbrev() {}
   static DebugAbbrev* Create(const byte* dbg_abbrev, size_t dbg_abbrev_size) {
-    std::unique_ptr<DebugAbbrev> abbrev(new DebugAbbrev);
-    const byte* last = dbg_abbrev + dbg_abbrev_size;
-    while (dbg_abbrev < last) {
-      std::unique_ptr<DebugTag> tag(DebugTag::Create(&dbg_abbrev));
-      if (tag.get() == nullptr) {
-        return nullptr;
-      } else {
-        abbrev->tags_.insert(std::pair<uint32_t, uint32_t>(tag->index_, abbrev->tag_list_.size()));
-        abbrev->tag_list_.push_back(std::move(tag));
-      }
+    std::unique_ptr<DebugAbbrev> abbrev(new DebugAbbrev(dbg_abbrev, dbg_abbrev + dbg_abbrev_size));
+    if (!abbrev->ReadAtOffset(0)) {
+      return nullptr;
     }
     return abbrev.release();
   }
 
+  bool ReadAtOffset(uint32_t abbrev_offset) {
+    tags_.clear();
+    tag_list_.clear();
+    const byte* dbg_abbrev = begin_ + abbrev_offset;
+    while (dbg_abbrev < end_ && *dbg_abbrev != 0) {
+      std::unique_ptr<DebugTag> tag(DebugTag::Create(&dbg_abbrev));
+      if (tag.get() == nullptr) {
+        return false;
+      } else {
+        tags_.insert(std::pair<uint32_t, uint32_t>(tag->index_, tag_list_.size()));
+        tag_list_.push_back(std::move(tag));
+      }
+    }
+    return true;
+  }
+
   DebugTag* ReadTag(const byte* entry) {
     uint32_t tag_num = DecodeUnsignedLeb128(&entry);
     auto it = tags_.find(tag_num);
@@ -1215,7 +1224,9 @@
   }
 
  private:
-  DebugAbbrev() {}
+  DebugAbbrev(const byte* begin, const byte* end) : begin_(begin), end_(end) {}
+  const byte* begin_;
+  const byte* end_;
   std::map<uint32_t, uint32_t> tags_;
   std::vector<std::unique_ptr<DebugTag>> tag_list_;
 };
@@ -1239,11 +1250,21 @@
     if (current_entry_ == nullptr || current_tag_ == nullptr) {
       return false;
     }
+    bool reread_abbrev = false;
     current_entry_ += current_tag_->GetSize();
+    if (reinterpret_cast<DebugInfoHeader*>(current_entry_) >= next_cu_) {
+      current_cu_ = next_cu_;
+      next_cu_ = GetNextCu(current_cu_);
+      current_entry_ = reinterpret_cast<byte*>(current_cu_) + sizeof(DebugInfoHeader);
+      reread_abbrev = true;
+    }
     if (current_entry_ >= last_entry_) {
       current_entry_ = nullptr;
       return false;
     }
+    if (reread_abbrev) {
+      abbrev_->ReadAtOffset(current_cu_->debug_abbrev_offset);
+    }
     current_tag_ = abbrev_->ReadTag(current_entry_);
     if (current_tag_ == nullptr) {
       current_entry_ = nullptr;
@@ -1271,12 +1292,21 @@
   }
 
  private:
+  static DebugInfoHeader* GetNextCu(DebugInfoHeader* hdr) {
+    byte* hdr_byte = reinterpret_cast<byte*>(hdr);
+    return reinterpret_cast<DebugInfoHeader*>(hdr_byte + sizeof(uint32_t) + hdr->unit_length);
+  }
+
   DebugInfoIterator(DebugInfoHeader* header, size_t frame_size, DebugAbbrev* abbrev)
       : abbrev_(abbrev),
+        current_cu_(header),
+        next_cu_(GetNextCu(header)),
         last_entry_(reinterpret_cast<byte*>(header) + frame_size),
         current_entry_(reinterpret_cast<byte*>(header) + sizeof(DebugInfoHeader)),
         current_tag_(abbrev_->ReadTag(current_entry_)) {}
   DebugAbbrev* abbrev_;
+  DebugInfoHeader* current_cu_;
+  DebugInfoHeader* next_cu_;
   byte* last_entry_;
   byte* current_entry_;
   DebugTag* current_tag_;
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index ae42284..9c6f8c4 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -121,6 +121,13 @@
     // Do not change stubs for these methods.
     return;
   }
+  std::string temp;
+  // Note that the Proxy class itself is not a proxy class.
+  if (strcmp(method->GetDeclaringClass()->GetDescriptor(&temp), "Ljava/lang/reflect/Proxy;") == 0 &&
+      method->IsConstructor()) {
+    // Do not stub Proxy.<init>.
+    return;
+  }
   const void* new_portable_code;
   const void* new_quick_code;
   bool uninstall = !entry_exit_stubs_installed_ && !interpreter_stubs_installed_;
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index 9eab3fd..e085ac2 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -25,7 +25,7 @@
 #include "mirror/art_method.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
-#include "native_bridge.h"
+#include "nativebridge/native_bridge.h"
 #include "java_vm_ext.h"
 #include "parsed_options.h"
 #include "ScopedLocalRef.h"
@@ -135,7 +135,7 @@
     CHECK(NeedsNativeBridge());
 
     uint32_t len = 0;
-    return NativeBridgeGetTrampoline(handle_, symbol_name.c_str(), shorty, len);
+    return android::NativeBridgeGetTrampoline(handle_, symbol_name.c_str(), shorty, len);
   }
 
  private:
@@ -645,8 +645,8 @@
   void* handle = dlopen(path_str, RTLD_LAZY);
   bool needs_native_bridge = false;
   if (handle == nullptr) {
-    if (NativeBridgeIsSupported(path_str)) {
-      handle = NativeBridgeLoadLibrary(path_str, RTLD_LAZY);
+    if (android::NativeBridgeIsSupported(path_str)) {
+      handle = android::NativeBridgeLoadLibrary(path_str, RTLD_LAZY);
       needs_native_bridge = true;
     }
   }
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index b7d485e..1c870cd 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -43,7 +43,6 @@
 #include "mirror/object_array-inl.h"
 #include "mirror/string-inl.h"
 #include "mirror/throwable.h"
-#include "native_bridge.h"
 #include "parsed_options.h"
 #include "reflection.h"
 #include "runtime.h"
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 3543654..a1177d6 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -162,7 +162,8 @@
         break;
       }
       case LockWord::kThinLocked: {
-        // Inflate the thin lock to a monitor and stick the hash code inside of the monitor.
+        // Inflate the thin lock to a monitor and stick the hash code inside of the monitor. May
+        // fail spuriously.
         Thread* self = Thread::Current();
         StackHandleScope<1> hs(self);
         Handle<mirror::Object> h_this(hs.NewHandle(current_this));
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 433c1b2..8f5ae54 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -176,10 +176,6 @@
   // Deflated monitors have a null object.
 }
 
-/*
- * Links a thread into a monitor's wait set.  The monitor lock must be
- * held by the caller of this routine.
- */
 void Monitor::AppendToWaitSet(Thread* thread) {
   DCHECK(owner_ == Thread::Current());
   DCHECK(thread != NULL);
@@ -197,10 +193,6 @@
   t->SetWaitNext(thread);
 }
 
-/*
- * Unlinks a thread from a monitor's wait set.  The monitor lock must
- * be held by the caller of this routine.
- */
 void Monitor::RemoveFromWaitSet(Thread *thread) {
   DCHECK(owner_ == Thread::Current());
   DCHECK(thread != NULL);
@@ -395,29 +387,6 @@
   return true;
 }
 
-/*
- * Wait on a monitor until timeout, interrupt, or notification.  Used for
- * Object.wait() and (somewhat indirectly) Thread.sleep() and Thread.join().
- *
- * If another thread calls Thread.interrupt(), we throw InterruptedException
- * and return immediately if one of the following are true:
- *  - blocked in wait(), wait(long), or wait(long, int) methods of Object
- *  - blocked in join(), join(long), or join(long, int) methods of Thread
- *  - blocked in sleep(long), or sleep(long, int) methods of Thread
- * Otherwise, we set the "interrupted" flag.
- *
- * Checks to make sure that "ns" is in the range 0-999999
- * (i.e. fractions of a millisecond) and throws the appropriate
- * exception if it isn't.
- *
- * The spec allows "spurious wakeups", and recommends that all code using
- * Object.wait() do so in a loop.  This appears to derive from concerns
- * about pthread_cond_wait() on multiprocessor systems.  Some commentary
- * on the web casts doubt on whether these can/should occur.
- *
- * Since we're allowed to wake up "early", we clamp extremely long durations
- * to return at the end of the 32-bit time epoch.
- */
 void Monitor::Wait(Thread* self, int64_t ms, int32_t ns,
                    bool interruptShouldThrow, ThreadState why) {
   DCHECK(self != NULL);
@@ -641,11 +610,6 @@
   return true;
 }
 
-/*
- * Changes the shape of a monitor from thin to fat, preserving the internal lock state. The calling
- * thread must own the lock or the owner must be suspended. There's a race with other threads
- * inflating the lock and so the caller should read the monitor following the call.
- */
 void Monitor::Inflate(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code) {
   DCHECK(self != nullptr);
   DCHECK(obj != nullptr);
@@ -823,38 +787,37 @@
   }
 }
 
-/*
- * Object.wait().  Also called for class init.
- */
 void Monitor::Wait(Thread* self, mirror::Object *obj, int64_t ms, int32_t ns,
                    bool interruptShouldThrow, ThreadState why) {
   DCHECK(self != nullptr);
   DCHECK(obj != nullptr);
   LockWord lock_word = obj->GetLockWord(true);
-  switch (lock_word.GetState()) {
-    case LockWord::kHashCode:
-      // Fall-through.
-    case LockWord::kUnlocked:
-      ThrowIllegalMonitorStateExceptionF("object not locked by thread before wait()");
-      return;  // Failure.
-    case LockWord::kThinLocked: {
-      uint32_t thread_id = self->GetThreadId();
-      uint32_t owner_thread_id = lock_word.ThinLockOwner();
-      if (owner_thread_id != thread_id) {
+  while (lock_word.GetState() != LockWord::kFatLocked) {
+    switch (lock_word.GetState()) {
+      case LockWord::kHashCode:
+        // Fall-through.
+      case LockWord::kUnlocked:
         ThrowIllegalMonitorStateExceptionF("object not locked by thread before wait()");
         return;  // Failure.
-      } else {
-        // We own the lock, inflate to enqueue ourself on the Monitor.
-        Inflate(self, self, obj, 0);
-        lock_word = obj->GetLockWord(true);
+      case LockWord::kThinLocked: {
+        uint32_t thread_id = self->GetThreadId();
+        uint32_t owner_thread_id = lock_word.ThinLockOwner();
+        if (owner_thread_id != thread_id) {
+          ThrowIllegalMonitorStateExceptionF("object not locked by thread before wait()");
+          return;  // Failure.
+        } else {
+          // We own the lock, inflate to enqueue ourself on the Monitor. May fail spuriously so
+          // re-load.
+          Inflate(self, self, obj, 0);
+          lock_word = obj->GetLockWord(true);
+        }
+        break;
       }
-      break;
-    }
-    case LockWord::kFatLocked:
-      break;  // Already set for a wait.
-    default: {
-      LOG(FATAL) << "Invalid monitor state " << lock_word.GetState();
-      return;
+      case LockWord::kFatLocked:  // Unreachable given the loop condition above. Fall-through.
+      default: {
+        LOG(FATAL) << "Invalid monitor state " << lock_word.GetState();
+        return;
+      }
     }
   }
   Monitor* mon = lock_word.FatLockMonitor();
diff --git a/runtime/monitor.h b/runtime/monitor.h
index 26d43c9..16eb1d2 100644
--- a/runtime/monitor.h
+++ b/runtime/monitor.h
@@ -74,6 +74,8 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DoNotify(self, obj, true);
   }
+
+  // Object.wait().  Also called for class init.
   static void Wait(Thread* self, mirror::Object* obj, int64_t ms, int32_t ns,
                    bool interruptShouldThrow, ThreadState why)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -117,6 +119,7 @@
     return monitor_id_;
   }
 
+  // Inflate the lock on obj. May fail to inflate for spurious reasons, always re-check.
   static void InflateThinLocked(Thread* self, Handle<mirror::Object> obj, LockWord lock_word,
                                 uint32_t hash_code) NO_THREAD_SAFETY_ANALYSIS;
 
@@ -135,9 +138,18 @@
       LOCKS_EXCLUDED(monitor_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Links a thread into a monitor's wait set.  The monitor lock must be held by the caller of this
+  // routine.
   void AppendToWaitSet(Thread* thread) EXCLUSIVE_LOCKS_REQUIRED(monitor_lock_);
+
+  // Unlinks a thread from a monitor's wait set.  The monitor lock must be held by the caller of
+  // this routine.
   void RemoveFromWaitSet(Thread* thread) EXCLUSIVE_LOCKS_REQUIRED(monitor_lock_);
 
+  // Changes the shape of a monitor from thin to fat, preserving the internal lock state. The
+  // calling thread must own the lock or the owner must be suspended. There's a race with other
+  // threads inflating the lock, installing hash codes and spurious failures. The caller should
+  // re-read the lock word following the call.
   static void Inflate(Thread* self, Thread* owner, mirror::Object* obj, int32_t hash_code)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -168,6 +180,25 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
 
+  // Wait on a monitor until timeout, interrupt, or notification.  Used for Object.wait() and
+  // (somewhat indirectly) Thread.sleep() and Thread.join().
+  //
+  // If another thread calls Thread.interrupt(), we throw InterruptedException and return
+  // immediately if one of the following are true:
+  //  - blocked in wait(), wait(long), or wait(long, int) methods of Object
+  //  - blocked in join(), join(long), or join(long, int) methods of Thread
+  //  - blocked in sleep(long), or sleep(long, int) methods of Thread
+  // Otherwise, we set the "interrupted" flag.
+  //
+  // Checks to make sure that "ns" is in the range 0-999999 (i.e. fractions of a millisecond) and
+  // throws the appropriate exception if it isn't.
+  //
+  // The spec allows "spurious wakeups", and recommends that all code using Object.wait() do so in
+  // a loop.  This appears to derive from concerns about pthread_cond_wait() on multiprocessor
+  // systems.  Some commentary on the web casts doubt on whether these can/should occur.
+  //
+  // Since we're allowed to wake up "early", we clamp extremely long durations to return at the end
+  // of the 32-bit time epoch.
   void Wait(Thread* self, int64_t msec, int32_t nsec, bool interruptShouldThrow, ThreadState why)
       LOCKS_EXCLUDED(monitor_lock_)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/native_bridge.cc b/runtime/native_bridge.cc
deleted file mode 100644
index d0b516b..0000000
--- a/runtime/native_bridge.cc
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "native_bridge.h"
-
-#include <dlfcn.h>
-#include <stdio.h>
-#include "jni.h"
-
-#include "base/mutex.h"
-#include "mirror/art_method-inl.h"
-#include "mirror/class-inl.h"
-#include "scoped_thread_state_change.h"
-#include "ScopedLocalRef.h"
-#include "thread.h"
-
-#ifdef HAVE_ANDROID_OS
-#include "cutils/properties.h"
-#endif
-
-
-namespace art {
-
-// The symbol name exposed by native-bridge with the type of NativeBridgeCallbacks.
-static constexpr const char* kNativeBridgeInterfaceSymbol = "NativeBridgeItf";
-
-// The library name we are supposed to load.
-static std::string native_bridge_library_string = "";
-
-// Whether a native bridge is available (loaded and ready).
-static bool available = false;
-// Whether we have already initialized (or tried to).
-static bool initialized = false;
-
-struct NativeBridgeCallbacks;
-static NativeBridgeCallbacks* callbacks = nullptr;
-
-// ART interfaces to native-bridge.
-struct NativeBridgeArtCallbacks {
-  // Get shorty of a Java method. The shorty is supposed to be persistent in memory.
-  //
-  // Parameters:
-  //   env [IN] pointer to JNIenv.
-  //   mid [IN] Java methodID.
-  // Returns:
-  //   short descriptor for method.
-  const char* (*getMethodShorty)(JNIEnv* env, jmethodID mid);
-
-  // Get number of native methods for specified class.
-  //
-  // Parameters:
-  //   env [IN] pointer to JNIenv.
-  //   clazz [IN] Java class object.
-  // Returns:
-  //   number of native methods.
-  uint32_t (*getNativeMethodCount)(JNIEnv* env, jclass clazz);
-
-  // Get at most 'method_count' native methods for specified class 'clazz'. Results are outputed
-  // via 'methods' [OUT]. The signature pointer in JNINativeMethod is reused as the method shorty.
-  //
-  // Parameters:
-  //   env [IN] pointer to JNIenv.
-  //   clazz [IN] Java class object.
-  //   methods [OUT] array of method with the name, shorty, and fnPtr.
-  //   method_count [IN] max number of elements in methods.
-  // Returns:
-  //   number of method it actually wrote to methods.
-  uint32_t (*getNativeMethods)(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
-                               uint32_t method_count);
-};
-
-// Native-bridge interfaces to ART
-struct NativeBridgeCallbacks {
-  // Initialize native-bridge. Native-bridge's internal implementation must ensure MT safety and
-  // that the native-bridge is initialized only once. Thus it is OK to call this interface for an
-  // already initialized native-bridge.
-  //
-  // Parameters:
-  //   art_cbs [IN] the pointer to NativeBridgeArtCallbacks.
-  // Returns:
-  //   true iff initialization was successful.
-  bool (*initialize)(NativeBridgeArtCallbacks* art_cbs);
-
-  // Load a shared library that is supported by the native-bridge.
-  //
-  // Parameters:
-  //   libpath [IN] path to the shared library
-  //   flag [IN] the stardard RTLD_XXX defined in bionic dlfcn.h
-  // Returns:
-  //   The opaque handle of the shared library if sucessful, otherwise NULL
-  void* (*loadLibrary)(const char* libpath, int flag);
-
-  // Get a native-bridge trampoline for specified native method. The trampoline has same
-  // sigature as the native method.
-  //
-  // Parameters:
-  //   handle [IN] the handle returned from loadLibrary
-  //   shorty [IN] short descriptor of native method
-  //   len [IN] length of shorty
-  // Returns:
-  //   address of trampoline if successful, otherwise NULL
-  void* (*getTrampoline)(void* handle, const char* name, const char* shorty, uint32_t len);
-
-  // Check whether native library is valid and is for an ABI that is supported by native-bridge.
-  //
-  // Parameters:
-  //   libpath [IN] path to the shared library
-  // Returns:
-  //   TRUE if library is supported by native-bridge, FALSE otherwise
-  bool (*isSupported)(const char* libpath);
-};
-
-static const char* GetMethodShorty(JNIEnv* env, jmethodID mid) {
-  ScopedObjectAccess soa(env);
-  StackHandleScope<1> scope(soa.Self());
-  mirror::ArtMethod* m = soa.DecodeMethod(mid);
-  MethodHelper mh(scope.NewHandle(m));
-  return mh.GetShorty();
-}
-
-static uint32_t GetNativeMethodCount(JNIEnv* env, jclass clazz) {
-  if (clazz == nullptr)
-    return 0;
-
-  ScopedObjectAccess soa(env);
-  mirror::Class* c = soa.Decode<mirror::Class*>(clazz);
-
-  uint32_t native_method_count = 0;
-  for (uint32_t i = 0; i < c->NumDirectMethods(); ++i) {
-    mirror::ArtMethod* m = c->GetDirectMethod(i);
-    if (m->IsNative()) {
-      native_method_count++;
-    }
-  }
-  for (uint32_t i = 0; i < c->NumVirtualMethods(); ++i) {
-    mirror::ArtMethod* m = c->GetVirtualMethod(i);
-    if (m->IsNative()) {
-      native_method_count++;
-    }
-  }
-  return native_method_count;
-}
-
-static uint32_t GetNativeMethods(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
-                               uint32_t method_count) {
-  if ((clazz == nullptr) || (methods == nullptr)) {
-    return 0;
-  }
-  ScopedObjectAccess soa(env);
-  mirror::Class* c = soa.Decode<mirror::Class*>(clazz);
-
-  uint32_t count = 0;
-  for (uint32_t i = 0; i < c->NumDirectMethods(); ++i) {
-    mirror::ArtMethod* m = c->GetDirectMethod(i);
-    if (m->IsNative()) {
-      if (count < method_count) {
-        methods[count].name = m->GetName();
-        methods[count].signature = m->GetShorty();
-        methods[count].fnPtr = const_cast<void*>(m->GetNativeMethod());
-        count++;
-      } else {
-        LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(m);
-      }
-    }
-  }
-  for (uint32_t i = 0; i < c->NumVirtualMethods(); ++i) {
-    mirror::ArtMethod* m = c->GetVirtualMethod(i);
-    if (m->IsNative()) {
-      if (count < method_count) {
-        methods[count].name = m->GetName();
-        methods[count].signature = m->GetShorty();
-        methods[count].fnPtr = const_cast<void*>(m->GetNativeMethod());
-        count++;
-      } else {
-        LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(m);
-      }
-    }
-  }
-  return count;
-}
-
-static NativeBridgeArtCallbacks NativeBridgeArtItf = {
-  GetMethodShorty,
-  GetNativeMethodCount,
-  GetNativeMethods
-};
-
-void SetNativeBridgeLibraryString(const std::string& nb_library_string) {
-  // This is called when the runtime starts and nothing is working concurrently
-  // so we don't need a lock here.
-
-  native_bridge_library_string = nb_library_string;
-
-  if (native_bridge_library_string.empty()) {
-    initialized = true;
-    available = false;
-  }
-}
-
-static bool NativeBridgeInitialize() {
-  // TODO: Missing annotalysis static lock ordering of DEFAULT_MUTEX_ACQUIRED, place lock into
-  // global order or remove.
-  static Mutex lock("native bridge lock");
-  MutexLock mu(Thread::Current(), lock);
-
-  if (initialized) {
-    // Somebody did it before.
-    return available;
-  }
-
-  available = false;
-
-  void* handle = dlopen(native_bridge_library_string.c_str(), RTLD_LAZY);
-  if (handle != nullptr) {
-    callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle,
-                                                               kNativeBridgeInterfaceSymbol));
-
-    if (callbacks != nullptr) {
-      available = callbacks->initialize(&NativeBridgeArtItf);
-    }
-
-    if (!available) {
-      dlclose(handle);
-    }
-  }
-
-  initialized = true;
-
-  return available;
-}
-
-void* NativeBridgeLoadLibrary(const char* libpath, int flag) {
-  if (NativeBridgeInitialize()) {
-    return callbacks->loadLibrary(libpath, flag);
-  }
-  return nullptr;
-}
-
-void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty,
-                                  uint32_t len) {
-  if (NativeBridgeInitialize()) {
-    return callbacks->getTrampoline(handle, name, shorty, len);
-  }
-  return nullptr;
-}
-
-bool NativeBridgeIsSupported(const char* libpath) {
-  if (NativeBridgeInitialize()) {
-    return callbacks->isSupported(libpath);
-  }
-  return false;
-}
-
-};  // namespace art
diff --git a/runtime/native_bridge.h b/runtime/native_bridge.h
deleted file mode 100644
index be647fc..0000000
--- a/runtime/native_bridge.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_NATIVE_BRIDGE_H_
-#define ART_RUNTIME_NATIVE_BRIDGE_H_
-
-#include <string>
-
-namespace art {
-
-// Initialize the native bridge, if any. Should be called by Runtime::Init(). An empty string
-// signals that we do not want to load a native bridge.
-void SetNativeBridgeLibraryString(const std::string& native_bridge_library_string);
-
-// Load a shared library that is supported by the native-bridge.
-void* NativeBridgeLoadLibrary(const char* libpath, int flag);
-
-// Get a native-bridge trampoline for specified native method.
-void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, uint32_t len);
-
-// True if native library is valid and is for an ABI that is supported by native-bridge.
-bool NativeBridgeIsSupported(const char* libpath);
-
-};  // namespace art
-
-#endif  // ART_RUNTIME_NATIVE_BRIDGE_H_
diff --git a/runtime/native_bridge_art_interface.cc b/runtime/native_bridge_art_interface.cc
new file mode 100644
index 0000000..453c92f
--- /dev/null
+++ b/runtime/native_bridge_art_interface.cc
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "native_bridge_art_interface.h"
+
+#include "mirror/art_method-inl.h"
+#include "mirror/class-inl.h"
+#include "scoped_thread_state_change.h"
+
+namespace art {
+
+const char* GetMethodShorty(JNIEnv* env, jmethodID mid) {
+  ScopedObjectAccess soa(env);
+  StackHandleScope<1> scope(soa.Self());
+  mirror::ArtMethod* m = soa.DecodeMethod(mid);
+  MethodHelper mh(scope.NewHandle(m));
+  return mh.GetShorty();
+}
+
+uint32_t GetNativeMethodCount(JNIEnv* env, jclass clazz) {
+  if (clazz == nullptr)
+    return 0;
+
+  ScopedObjectAccess soa(env);
+  mirror::Class* c = soa.Decode<mirror::Class*>(clazz);
+
+  uint32_t native_method_count = 0;
+  for (uint32_t i = 0; i < c->NumDirectMethods(); ++i) {
+    mirror::ArtMethod* m = c->GetDirectMethod(i);
+    if (m->IsNative()) {
+      native_method_count++;
+    }
+  }
+  for (uint32_t i = 0; i < c->NumVirtualMethods(); ++i) {
+    mirror::ArtMethod* m = c->GetVirtualMethod(i);
+    if (m->IsNative()) {
+      native_method_count++;
+    }
+  }
+  return native_method_count;
+}
+
+uint32_t GetNativeMethods(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
+                          uint32_t method_count) {
+  if ((clazz == nullptr) || (methods == nullptr)) {
+    return 0;
+  }
+  ScopedObjectAccess soa(env);
+  mirror::Class* c = soa.Decode<mirror::Class*>(clazz);
+
+  uint32_t count = 0;
+  for (uint32_t i = 0; i < c->NumDirectMethods(); ++i) {
+    mirror::ArtMethod* m = c->GetDirectMethod(i);
+    if (m->IsNative()) {
+      if (count < method_count) {
+        methods[count].name = m->GetName();
+        methods[count].signature = m->GetShorty();
+        methods[count].fnPtr = const_cast<void*>(m->GetNativeMethod());
+        count++;
+      } else {
+        LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(m);
+      }
+    }
+  }
+  for (uint32_t i = 0; i < c->NumVirtualMethods(); ++i) {
+    mirror::ArtMethod* m = c->GetVirtualMethod(i);
+    if (m->IsNative()) {
+      if (count < method_count) {
+        methods[count].name = m->GetName();
+        methods[count].signature = m->GetShorty();
+        methods[count].fnPtr = const_cast<void*>(m->GetNativeMethod());
+        count++;
+      } else {
+        LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(m);
+      }
+    }
+  }
+  return count;
+}
+
+};  // namespace art
diff --git a/runtime/native_bridge_art_interface.h b/runtime/native_bridge_art_interface.h
new file mode 100644
index 0000000..08735c8
--- /dev/null
+++ b/runtime/native_bridge_art_interface.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_NATIVE_BRIDGE_ART_INTERFACE_H_
+#define ART_RUNTIME_NATIVE_BRIDGE_ART_INTERFACE_H_
+
+#include <jni.h>
+#include <stdint.h>
+
+namespace art {
+
+const char* GetMethodShorty(JNIEnv* env, jmethodID mid);
+
+uint32_t GetNativeMethodCount(JNIEnv* env, jclass clazz);
+
+uint32_t GetNativeMethods(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
+                          uint32_t method_count);
+
+};  // namespace art
+
+#endif  // ART_RUNTIME_NATIVE_BRIDGE_ART_INTERFACE_H_
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 27f7765..a023ff1 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -609,7 +609,7 @@
         return false;
       }
     } else if (StartsWith(option, "-XX:NativeBridge=")) {
-      if (!ParseStringAfterChar(option, '=', &native_bridge_library_string_)) {
+      if (!ParseStringAfterChar(option, '=', &native_bridge_library_path_)) {
         return false;
       }
     } else if (StartsWith(option, "-ea") ||
diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h
index aa2c557..1afd610 100644
--- a/runtime/parsed_options.h
+++ b/runtime/parsed_options.h
@@ -46,7 +46,7 @@
   bool check_jni_;
   bool force_copy_;
   std::string jni_trace_;
-  std::string native_bridge_library_string_;
+  std::string native_bridge_library_path_;
   CompilerCallbacks* compiler_callbacks_;
   bool is_zygote_;
   bool must_relocate_;
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 5af26b0..d977ce9 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -17,14 +17,14 @@
 #include <jni.h>
 #include <vector>
 
-#include "common_runtime_test.h"
+#include "common_compiler_test.h"
 #include "field_helper.h"
 #include "mirror/art_field-inl.h"
 #include "scoped_thread_state_change.h"
 
 namespace art {
 
-class ProxyTest : public CommonRuntimeTest {
+class ProxyTest : public CommonCompilerTest {
  public:
   // Generate a proxy class with the given name and interfaces. This is a simplification from what
   // libcore does to fit to our test needs. We do not check for duplicated interfaces or methods and
@@ -103,12 +103,6 @@
     soa.Self()->AssertNoPendingException();
     return proxyClass;
   }
-
- protected:
-  void SetUpRuntimeOptions(RuntimeOptions *options) OVERRIDE {
-    options->push_back(std::make_pair(StringPrintf("-Ximage:%s", GetLibCoreOatFileName().c_str()),
-                                      nullptr));
-  }
 };
 
 // Creates a proxy class and check ClassHelper works correctly.
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index d3957c1..05003cb 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -63,7 +63,7 @@
 #include "mirror/stack_trace_element.h"
 #include "mirror/throwable.h"
 #include "monitor.h"
-#include "native_bridge.h"
+#include "native_bridge_art_interface.h"
 #include "parsed_options.h"
 #include "oat_file.h"
 #include "quick/quick_method_frame_info.h"
@@ -143,7 +143,8 @@
       target_sdk_version_(0),
       implicit_null_checks_(false),
       implicit_so_checks_(false),
-      implicit_suspend_checks_(false) {
+      implicit_suspend_checks_(false),
+      native_bridge_art_callbacks_({GetMethodShorty, GetNativeMethodCount, GetNativeMethods}) {
 }
 
 Runtime::~Runtime() {
@@ -708,8 +709,11 @@
   self->ClearException();
 
   // Look for a native bridge.
-  SetNativeBridgeLibraryString(options->native_bridge_library_string_);
-
+  native_bridge_library_path_ = options->native_bridge_library_path_;
+  if (!native_bridge_library_path_.empty()) {
+    android::SetupNativeBridge(native_bridge_library_path_.c_str(), &native_bridge_art_callbacks_);
+    VLOG(startup) << "Runtime::Setup native bridge library: " << native_bridge_library_path_;
+  }
   VLOG(startup) << "Runtime::Init exiting";
   return true;
 }
diff --git a/runtime/runtime.h b/runtime/runtime.h
index e76280a..34ccdcb 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -31,6 +31,7 @@
 #include "instrumentation.h"
 #include "instruction_set.h"
 #include "jobject_comparator.h"
+#include "nativebridge/native_bridge.h"
 #include "object_callbacks.h"
 #include "offsets.h"
 #include "profiler_options.h"
@@ -616,6 +617,25 @@
   bool implicit_so_checks_;         // StackOverflow checks are implicit.
   bool implicit_suspend_checks_;    // Thread suspension checks are implicit.
 
+  // The path to the native bridge library. If this is not empty the native bridge will be
+  // initialized and loaded from the pointed path.
+  //
+  // The native bridge allows running native code compiled for a foreign ISA. The way it works is,
+  // if standard dlopen fails to load native library associated with native activity, it calls to
+  // the native bridge to load it and then gets the trampoline for the entry to native activity.
+  std::string native_bridge_library_path_;
+
+  // Native bridge library runtime callbacks. They represent the runtime interface to native bridge.
+  //
+  // The interface is expected to expose the following methods:
+  // getMethodShorty(): in the case of native method calling JNI native function CallXXXXMethodY(),
+  //   native bridge calls back to VM for the shorty of the method so that it can prepare based on
+  //   host calling convention.
+  // getNativeMethodCount() and getNativeMethods(): in case of JNI function UnregisterNatives(),
+  //   native bridge can call back to get all native methods of specified class so that all
+  //   corresponding trampolines can be destroyed.
+  android::NativeBridgeRuntimeCallbacks native_bridge_art_callbacks_;
+
   DISALLOW_COPY_AND_ASSIGN(Runtime);
 };
 
diff --git a/test/115-native-bridge/nativebridge.cc b/test/115-native-bridge/nativebridge.cc
index 268f0be..3acc643 100644
--- a/test/115-native-bridge/nativebridge.cc
+++ b/test/115-native-bridge/nativebridge.cc
@@ -22,27 +22,9 @@
 
 #include "jni.h"
 #include "stdio.h"
-#include "string.h"
 #include "unistd.h"
 
-#include "native_bridge.h"
-
-
-// Native bridge interfaces...
-
-struct NativeBridgeArtCallbacks {
-  const char* (*getMethodShorty)(JNIEnv* env, jmethodID mid);
-  uint32_t (*getNativeMethodCount)(JNIEnv* env, jclass clazz);
-  uint32_t (*getNativeMethods)(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
-                               uint32_t method_count);
-};
-
-struct NativeBridgeCallbacks {
-  bool (*initialize)(NativeBridgeArtCallbacks* art_cbs);
-  void* (*loadLibrary)(const char* libpath, int flag);
-  void* (*getTrampoline)(void* handle, const char* name, const char* shorty, uint32_t len);
-  bool (*isSupported)(const char* libpath);
-};
+#include "nativebridge/native_bridge.h"
 
 struct NativeBridgeMethod {
   const char* name;
@@ -53,7 +35,7 @@
 };
 
 static NativeBridgeMethod* find_native_bridge_method(const char *name);
-static NativeBridgeArtCallbacks* gNativeBridgeArtCallbacks;
+static const android::NativeBridgeRuntimeCallbacks* gNativeBridgeArtCallbacks;
 
 static jint trampoline_JNI_OnLoad(JavaVM* vm, void* reserved) {
   JNIEnv* env = nullptr;
@@ -225,7 +207,7 @@
 }
 
 // NativeBridgeCallbacks implementations
-extern "C" bool native_bridge_initialize(NativeBridgeArtCallbacks* art_cbs) {
+extern "C" bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* art_cbs) {
   if (art_cbs != nullptr) {
     gNativeBridgeArtCallbacks = art_cbs;
     printf("Native bridge initialized.\n");
@@ -281,7 +263,9 @@
   return strcmp(libpath, "libjavacore.so") != 0;
 }
 
-NativeBridgeCallbacks NativeBridgeItf {
+// "NativeBridgeItf" is effectively an API (it is the name of the symbol that will be loaded
+// by the native bridge library).
+android::NativeBridgeCallbacks NativeBridgeItf {
   .initialize = &native_bridge_initialize,
   .loadLibrary = &native_bridge_loadLibrary,
   .getTrampoline = &native_bridge_getTrampoline,