Merge "Use the asm-generic ucontext.h for arm."
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index b21e37e..ba98225 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -16,6 +16,10 @@
 
 #include <algorithm>
 #include "base/macros.h"
+#include "base/mutex.h"
+#include "base/mutex-inl.h"
+#include "thread.h"
+#include "thread-inl.h"
 #include "dex/mir_graph.h"
 
 #include "dex_file_method_inliner.h"
@@ -228,7 +232,8 @@
 };
 
 DexFileMethodInliner::DexFileMethodInliner()
-    : dex_file_(NULL) {
+    : lock_("DexFileMethodInliner lock", kDexFileMethodInlinerLock),
+      dex_file_(NULL) {
   COMPILE_ASSERT(kClassCacheFirst == 0, kClassCacheFirst_not_0);
   COMPILE_ASSERT(arraysize(kClassCacheNames) == kClassCacheLast, bad_arraysize_kClassCacheNames);
   COMPILE_ASSERT(kNameCacheFirst == 0, kNameCacheFirst_not_0);
@@ -240,16 +245,21 @@
 DexFileMethodInliner::~DexFileMethodInliner() {
 }
 
-bool DexFileMethodInliner::IsIntrinsic(uint32_t method_index) const {
+bool DexFileMethodInliner::IsIntrinsic(uint32_t method_index) {
+  ReaderMutexLock mu(Thread::Current(), lock_);
   return intrinsics_.find(method_index) != intrinsics_.end();
 }
 
-bool DexFileMethodInliner::GenIntrinsic(Mir2Lir* backend, CallInfo* info) const {
-  auto it = intrinsics_.find(info->index);
-  if (it == intrinsics_.end()) {
-    return false;
+bool DexFileMethodInliner::GenIntrinsic(Mir2Lir* backend, CallInfo* info) {
+  Intrinsic intrinsic;
+  {
+    ReaderMutexLock mu(Thread::Current(), lock_);
+    auto it = intrinsics_.find(info->index);
+    if (it == intrinsics_.end()) {
+      return false;
+    }
+    intrinsic = it->second;
   }
-  const Intrinsic& intrinsic = it->second;
   switch (intrinsic.opcode) {
     case kIntrinsicDoubleCvt:
       return backend->GenInlinedDoubleCvt(info);
diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h
index 948f4bb..9198f2a 100644
--- a/compiler/dex/quick/dex_file_method_inliner.h
+++ b/compiler/dex/quick/dex_file_method_inliner.h
@@ -19,6 +19,9 @@
 
 #include <stdint.h>
 #include <map>
+#include "base/mutex.h"
+#include "base/macros.h"
+#include "locks.h"
 
 namespace art {
 
@@ -95,12 +98,12 @@
     /**
      * Check whether a particular method index corresponds to an intrinsic function.
      */
-    bool IsIntrinsic(uint32_t method_index) const;
+    bool IsIntrinsic(uint32_t method_index) LOCKS_EXCLUDED(lock_);
 
     /**
      * Generate code for an intrinsic function invocation.
      */
-    bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) const;
+    bool GenIntrinsic(Mir2Lir* backend, CallInfo* info) LOCKS_EXCLUDED(lock_);
 
   private:
     /**
@@ -300,14 +303,15 @@
      *
      * Only DexFileToMethodInlinerMap may call this function to initialize the inliner.
      */
-    void FindIntrinsics(const DexFile* dex_file);
+    void FindIntrinsics(const DexFile* dex_file) EXCLUSIVE_LOCKS_REQUIRED(lock_);
 
     friend class DexFileToMethodInlinerMap;
 
+    ReaderWriterMutex lock_;
     /*
      * Maps method indexes (for the particular DexFile) to Intrinsic defintions.
      */
-    std::map<uint32_t, Intrinsic> intrinsics_;
+    std::map<uint32_t, Intrinsic> intrinsics_ GUARDED_BY(lock_);
     const DexFile* dex_file_;
 
     DISALLOW_COPY_AND_ASSIGN(DexFileMethodInliner);
diff --git a/compiler/dex/quick/dex_file_to_method_inliner_map.cc b/compiler/dex/quick/dex_file_to_method_inliner_map.cc
index 0107ed3..2fec183 100644
--- a/compiler/dex/quick/dex_file_to_method_inliner_map.cc
+++ b/compiler/dex/quick/dex_file_to_method_inliner_map.cc
@@ -28,7 +28,7 @@
 namespace art {
 
 DexFileToMethodInlinerMap::DexFileToMethodInlinerMap()
-    : lock_("inline_helper_mutex") {
+    : lock_("DexFileToMethodInlinerMap lock", kDexFileToMethodInlinerMapLock) {
 }
 
 DexFileToMethodInlinerMap::~DexFileToMethodInlinerMap() {
@@ -37,26 +37,37 @@
   }
 }
 
-const DexFileMethodInliner& DexFileToMethodInlinerMap::GetMethodInliner(const DexFile* dex_file) {
+DexFileMethodInliner* DexFileToMethodInlinerMap::GetMethodInliner(const DexFile* dex_file) {
   Thread* self = Thread::Current();
   {
-    ReaderMutexLock lock(self, lock_);
+    ReaderMutexLock mu(self, lock_);
     auto it = inliners_.find(dex_file);
     if (it != inliners_.end()) {
-      return *it->second;
+      return it->second;
     }
   }
 
-  WriterMutexLock lock(self, lock_);
-  DexFileMethodInliner** inliner = &inliners_[dex_file];  // inserts new entry if not found
-  if (*inliner) {
-    return **inliner;
+  // We need to acquire our lock_ to modify inliners_ but we want to release it
+  // before we initialize the new inliner. However, we need to acquire the
+  // new inliner's lock_ before we release our lock_ to prevent another thread
+  // from using the uninitialized inliner. This requires explicit calls to
+  // ExclusiveLock()/ExclusiveUnlock() on one of the locks, the other one
+  // can use WriterMutexLock.
+  DexFileMethodInliner* locked_inliner;
+  {
+    WriterMutexLock mu(self, lock_);
+    DexFileMethodInliner** inliner = &inliners_[dex_file];  // inserts new entry if not found
+    if (*inliner) {
+      return *inliner;
+    }
+    *inliner = new DexFileMethodInliner;
+    DCHECK(*inliner != nullptr);
+    locked_inliner = *inliner;
+    locked_inliner->lock_.ExclusiveLock(self);  // Acquire inliner's lock_ before releasing lock_.
   }
-  *inliner = new DexFileMethodInliner();
-  DCHECK(*inliner != nullptr);
-  // TODO: per-dex file locking for the intrinsics container filling.
-  (*inliner)->FindIntrinsics(dex_file);
-  return **inliner;
+  locked_inliner->FindIntrinsics(dex_file);
+  locked_inliner->lock_.ExclusiveUnlock(self);
+  return locked_inliner;
 }
 
 }  // namespace art
diff --git a/compiler/dex/quick/dex_file_to_method_inliner_map.h b/compiler/dex/quick/dex_file_to_method_inliner_map.h
index 476f002..6d5b889 100644
--- a/compiler/dex/quick/dex_file_to_method_inliner_map.h
+++ b/compiler/dex/quick/dex_file_to_method_inliner_map.h
@@ -40,7 +40,7 @@
     DexFileToMethodInlinerMap();
     ~DexFileToMethodInlinerMap();
 
-    const DexFileMethodInliner& GetMethodInliner(const DexFile* dex_file) LOCKS_EXCLUDED(lock_);
+    DexFileMethodInliner* GetMethodInliner(const DexFile* dex_file) LOCKS_EXCLUDED(lock_);
 
   private:
     ReaderWriterMutex lock_;
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index e66d4ea..ee6f9c8 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1242,7 +1242,7 @@
     if (inliner_ == nullptr) {
       QuickCompilerContext* context = reinterpret_cast<QuickCompilerContext*>(
           cu_->compiler_driver->GetCompilerContext());
-      inliner_ = &context->GetInlinerMap()->GetMethodInliner(cu_->dex_file);
+      inliner_ = context->GetInlinerMap()->GetMethodInliner(cu_->dex_file);
     }
     if (inliner_->GenIntrinsic(this, info)) {
       return;
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 2a54eb3..8415cbf 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -827,7 +827,7 @@
     LIR* first_lir_insn_;
     LIR* last_lir_insn_;
     // Lazily retrieved method inliner for intrinsics.
-    const DexFileMethodInliner* inliner_;
+    DexFileMethodInliner* inliner_;
 };  // Class Mir2Lir
 
 }  // namespace art
diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc
index 96dc6ee..0ecc091 100644
--- a/compiler/dex/quick/x86/assemble_x86.cc
+++ b/compiler/dex/quick/x86/assemble_x86.cc
@@ -288,6 +288,8 @@
 
   { kX86PsrlqRI, kRegImm, IS_BINARY_OP | REG_DEF0_USE0, { 0x66, 0, 0x0F, 0x73, 0, 2, 0, 1 }, "PsrlqRI", "!0r,!1d" },
   { kX86PsllqRI, kRegImm, IS_BINARY_OP | REG_DEF0_USE0, { 0x66, 0, 0x0F, 0x73, 0, 6, 0, 1 }, "PsllqRI", "!0r,!1d" },
+  { kX86SqrtsdRR, kRegReg, IS_BINARY_OP | REG_DEF0_USE1, { 0xF2, 0, 0x0F, 0x51, 0, 0, 0, 0 }, "SqrtsdRR", "!0r,!1r" },
+  { kX86FstpdM, kMem, IS_STORE | IS_BINARY_OP | REG_USE0, { 0x0, 0, 0xDD, 0x00, 0, 3, 0, 0 }, "FstpdM", "[!0r,!1d]" },
 
   EXT_0F_ENCODING_MAP(Movdxr,    0x66, 0x6E, REG_DEF0),
   { kX86MovdrxRR, kRegRegStore, IS_BINARY_OP | REG_DEF0   | REG_USE01,  { 0x66, 0, 0x0F, 0x7E, 0, 0, 0, 0 }, "MovdrxRR", "!0r,!1r" },
diff --git a/compiler/dex/quick/x86/fp_x86.cc b/compiler/dex/quick/x86/fp_x86.cc
index c9d6bfc..1731703 100644
--- a/compiler/dex/quick/x86/fp_x86.cc
+++ b/compiler/dex/quick/x86/fp_x86.cc
@@ -369,8 +369,14 @@
 }
 
 bool X86Mir2Lir::GenInlinedSqrt(CallInfo* info) {
-  DCHECK_NE(cu_->instruction_set, kThumb2);
-  return false;
+  RegLocation rl_src = info->args[0];
+  RegLocation rl_dest = InlineTargetWide(info);  // double place for result
+  rl_src = LoadValueWide(rl_src, kFPReg);
+  RegLocation rl_result = EvalLoc(rl_dest, kFPReg, true);
+  NewLIR2(kX86SqrtsdRR, S2d(rl_result.low_reg, rl_result.high_reg),
+          S2d(rl_src.low_reg, rl_src.high_reg));
+  StoreValueWide(rl_dest, rl_result);
+  return true;
 }
 
 
diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h
index 5fe76fe..a2d5c3e 100644
--- a/compiler/dex/quick/x86/x86_lir.h
+++ b/compiler/dex/quick/x86/x86_lir.h
@@ -348,6 +348,8 @@
   Binary0fOpCode(kX86Divss),    // float divide
   kX86PsrlqRI,                  // right shift of floating point registers
   kX86PsllqRI,                  // left shift of floating point registers
+  kX86SqrtsdRR,                 // sqrt of floating point register
+  kX86FstpdM,                   // Store and pop top x87 fp stack
   Binary0fOpCode(kX86Movdxr),   // move into xmm from gpr
   kX86MovdrxRR, kX86MovdrxMR, kX86MovdrxAR,  // move into reg from xmm
   kX86Set8R, kX86Set8M, kX86Set8A,  // set byte depending on condition operand
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 43ed28c..af18c05 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -284,10 +284,10 @@
 };
 
 extern "C" void ArtInitCompilerContext(art::CompilerDriver& driver);
-extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& compiler);
+extern "C" void ArtInitQuickCompilerContext(art::CompilerDriver& driver);
 
 extern "C" void ArtUnInitCompilerContext(art::CompilerDriver& driver);
-extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& compiler);
+extern "C" void ArtUnInitQuickCompilerContext(art::CompilerDriver& driver);
 
 extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver& driver,
                                                  const art::DexFile::CodeItem* code_item,
@@ -1384,11 +1384,9 @@
     self->AssertNoPendingException();
     CHECK_GT(work_units, 0U);
 
-    std::vector<ForAllClosure*> closures(work_units);
     index_ = begin;
     for (size_t i = 0; i < work_units; ++i) {
-      closures[i] = new ForAllClosure(this, end, callback);
-      thread_pool_->AddTask(self, closures[i]);
+      thread_pool_->AddTask(self, new ForAllClosure(this, end, callback));
     }
     thread_pool_->StartWorkers(self);
 
diff --git a/runtime/arch/x86/entrypoints_init_x86.cc b/runtime/arch/x86/entrypoints_init_x86.cc
index 6a67079..589c7d9 100644
--- a/runtime/arch/x86/entrypoints_init_x86.cc
+++ b/runtime/arch/x86/entrypoints_init_x86.cc
@@ -176,6 +176,7 @@
   // points->pCmplDouble = NULL;  // Not needed on x86.
   // points->pCmplFloat = NULL;  // Not needed on x86.
   qpoints->pFmod = art_quick_fmod;
+  // qpoints->pSqrt = NULL;  // Not needed on x86.
   qpoints->pL2d = art_quick_l2d;
   qpoints->pFmodf = art_quick_fmodf;
   qpoints->pL2f = art_quick_l2f;
diff --git a/runtime/locks.h b/runtime/locks.h
index 2308e95..72d4f65 100644
--- a/runtime/locks.h
+++ b/runtime/locks.h
@@ -41,6 +41,8 @@
   kRosAllocBracketLock,
   kRosAllocBulkFreeLock,
   kAllocSpaceLock,
+  kDexFileMethodInlinerLock,
+  kDexFileToMethodInlinerMapLock,
   kMarkSweepMarkStackLock,
   kDefaultMutexLevel,
   kMarkSweepLargeObjectLock,
diff --git a/runtime/native/dalvik_system_Zygote.cc b/runtime/native/dalvik_system_Zygote.cc
index 2e3d6a6..7fa9457 100644
--- a/runtime/native/dalvik_system_Zygote.cc
+++ b/runtime/native/dalvik_system_Zygote.cc
@@ -351,13 +351,14 @@
 
     if (mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
       // Mount entire external storage tree for all users
-      if (mount(source, target, NULL, MS_BIND, NULL) == -1) {
+      if (TEMP_FAILURE_RETRY(mount(source, target, NULL, MS_BIND, NULL)) == -1) {
         PLOG(WARNING) << "Failed to mount " << source << " to " << target;
         return false;
       }
     } else {
       // Only mount user-specific external storage
-      if (mount(source_user.c_str(), target_user.c_str(), NULL, MS_BIND, NULL) == -1) {
+      if (TEMP_FAILURE_RETRY(
+              mount(source_user.c_str(), target_user.c_str(), NULL, MS_BIND, NULL)) == -1) {
         PLOG(WARNING) << "Failed to mount " << source_user << " to " << target_user;
         return false;
       }
@@ -368,7 +369,8 @@
     }
 
     // Finally, mount user-specific path into place for legacy users
-    if (mount(target_user.c_str(), legacy, NULL, MS_BIND | MS_REC, NULL) == -1) {
+    if (TEMP_FAILURE_RETRY(
+            mount(target_user.c_str(), legacy, NULL, MS_BIND | MS_REC, NULL)) == -1) {
       PLOG(WARNING) << "Failed to mount " << target_user << " to " << legacy;
       return false;
     }
@@ -407,7 +409,8 @@
                                      jint debug_flags, jobjectArray javaRlimits,
                                      jlong permittedCapabilities, jlong effectiveCapabilities,
                                      jint mount_external,
-                                     jstring java_se_info, jstring java_se_name, bool is_system_server) {
+                                     jstring java_se_info, jstring java_se_name,
+                                     bool is_system_server) {
   Runtime* runtime = Runtime::Current();
   CHECK(runtime->IsZygote()) << "runtime instance not started with -Xzygote";
   if (!runtime->PreZygoteFork()) {
@@ -527,14 +530,16 @@
 }
 
 static jint Zygote_nativeForkAndSpecialize(JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
-                                           jint debug_flags, jobjectArray rlimits, jint mount_external,
-                                           jstring se_info, jstring se_name) {
-  return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, 0, 0, mount_external, se_info, se_name, false);
+                                           jint debug_flags, jobjectArray rlimits,
+                                           jint mount_external, jstring se_info, jstring se_name) {
+  return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, 0, 0, mount_external,
+                                 se_info, se_name, false);
 }
 
 static jint Zygote_nativeForkSystemServer(JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
                                           jint debug_flags, jobjectArray rlimits,
-                                          jlong permittedCapabilities, jlong effectiveCapabilities) {
+                                          jlong permittedCapabilities,
+                                          jlong effectiveCapabilities) {
   pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                       debug_flags, rlimits,
                                       permittedCapabilities, effectiveCapabilities,
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 9183b5f..59ead89 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -90,28 +90,28 @@
   if (klass->IsVerified()) {
     return kNoFailure;
   }
-  mirror::Class* super = klass->GetSuperClass();
-  if (super == NULL && strcmp("Ljava/lang/Object;", ClassHelper(klass).GetDescriptor()) != 0) {
-    *error = "Verifier rejected class ";
-    *error += PrettyDescriptor(klass);
-    *error += " that has no super class";
-    return kHardFailure;
-  }
-  if (super != NULL && super->IsFinal()) {
-    *error = "Verifier rejected class ";
-    *error += PrettyDescriptor(klass);
-    *error += " that attempts to sub-class final class ";
-    *error += PrettyDescriptor(super);
-    return kHardFailure;
-  }
+  bool early_failure = false;
+  std::string failure_message;
   ClassHelper kh(klass);
   const DexFile& dex_file = kh.GetDexFile();
   const DexFile::ClassDef* class_def = kh.GetClassDef();
-  if (class_def == NULL) {
-    *error = "Verifier rejected class ";
-    *error += PrettyDescriptor(klass);
-    *error += " that isn't present in dex file ";
-    *error += dex_file.GetLocation();
+  mirror::Class* super = klass->GetSuperClass();
+  if (super == NULL && strcmp("Ljava/lang/Object;", kh.GetDescriptor()) != 0) {
+    early_failure = true;
+    failure_message = " that has no super class";
+  } else if (super != NULL && super->IsFinal()) {
+    early_failure = true;
+    failure_message = " that attempts to sub-class final class " + PrettyDescriptor(super);
+  } else if (class_def == NULL) {
+    early_failure = true;
+    failure_message = " that isn't present in dex file " + dex_file.GetLocation();
+  }
+  if (early_failure) {
+    *error = "Verifier rejected class " + PrettyDescriptor(klass) + failure_message;
+    if (Runtime::Current()->IsCompiler()) {
+      ClassReference ref(&dex_file, klass->GetDexClassDefIndex());
+      AddRejectedClass(ref);
+    }
     return kHardFailure;
   }
   Thread* self = Thread::Current();