Merge "Fix ScopedArenaAllocator::Reset() for Create()d allocators."
diff --git a/build/Android.common_build.mk b/build/Android.common_build.mk
index d2d6d23..14edb71 100644
--- a/build/Android.common_build.mk
+++ b/build/Android.common_build.mk
@@ -196,7 +196,7 @@
   -fno-vectorize
 
 art_debug_cflags := \
-  -O1 \
+  -O2 \
   -DDYNAMIC_ANNOTATIONS_ENABLED=1 \
   -UNDEBUG
 
@@ -236,6 +236,9 @@
 # Warn if switch fallthroughs aren't annotated.
 art_clang_cflags += -Wimplicit-fallthrough
 
+# Enable float equality warnings.
+art_clang_cflags += -Wfloat-equal
+
 ifeq ($(ART_HOST_CLANG),true)
   ART_HOST_CFLAGS += $(art_clang_cflags)
 endif
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc
index a21004c..fd7d350 100644
--- a/compiler/jni/jni_compiler_test.cc
+++ b/compiler/jni/jni_compiler_test.cc
@@ -365,12 +365,12 @@
   EXPECT_EQ(0, gJava_MyClassNatives_fooDD_calls);
   jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
                                                     99.0, 10.0);
-  EXPECT_EQ(99.0 - 10.0, result);
+  EXPECT_DOUBLE_EQ(99.0 - 10.0, result);
   EXPECT_EQ(1, gJava_MyClassNatives_fooDD_calls);
   jdouble a = 3.14159265358979323846;
   jdouble b = 0.69314718055994530942;
   result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
-  EXPECT_EQ(a - b, result);
+  EXPECT_DOUBLE_EQ(a - b, result);
   EXPECT_EQ(2, gJava_MyClassNatives_fooDD_calls);
 
   gJava_MyClassNatives_fooDD_calls = 0;
@@ -513,13 +513,13 @@
 
   EXPECT_EQ(0, gJava_MyClassNatives_fooSDD_calls);
   jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
-  EXPECT_EQ(99.0 - 10.0, result);
+  EXPECT_DOUBLE_EQ(99.0 - 10.0, result);
   EXPECT_EQ(1, gJava_MyClassNatives_fooSDD_calls);
   jdouble a = 3.14159265358979323846;
   jdouble b = 0.69314718055994530942;
   result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
-  EXPECT_EQ(a - b, result);
-  EXPECT_EQ(2, gJava_MyClassNatives_fooSDD_calls);
+  EXPECT_DOUBLE_EQ(a - b, result);
+  EXPECT_DOUBLE_EQ(2, gJava_MyClassNatives_fooSDD_calls);
 
   gJava_MyClassNatives_fooSDD_calls = 0;
 }
@@ -539,7 +539,7 @@
   SetUpForTest(true, "logD", "(D)D", reinterpret_cast<void*>(&Java_MyClassNatives_logD));
 
   jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 2.0);
-  EXPECT_EQ(log(2.0), result);
+  EXPECT_DOUBLE_EQ(log(2.0), result);
 }
 
 JNI_TEST(RunStaticLogDoubleMethod)
@@ -553,7 +553,7 @@
   SetUpForTest(true, "logF", "(F)F", reinterpret_cast<void*>(&Java_MyClassNatives_logF));
 
   jfloat result = env_->CallStaticFloatMethod(jklass_, jmethod_, 2.0);
-  EXPECT_EQ(logf(2.0), result);
+  EXPECT_FLOAT_EQ(logf(2.0), result);
 }
 
 JNI_TEST(RunStaticLogFloatMethod)
@@ -1047,11 +1047,11 @@
 
   jfloat result = env_->CallNonvirtualFloatMethod(jobj_, jklass_, jmethod_,
                                                     99.0F, 10.0F);
-  EXPECT_EQ(99.0F - 10.0F, result);
+  EXPECT_FLOAT_EQ(99.0F - 10.0F, result);
   jfloat a = 3.14159F;
   jfloat b = 0.69314F;
   result = env_->CallNonvirtualFloatMethod(jobj_, jklass_, jmethod_, a, b);
-  EXPECT_EQ(a - b, result);
+  EXPECT_FLOAT_EQ(a - b, result);
 }
 
 JNI_TEST(CompileAndRunFloatFloatMethod)
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index e1f513d..7be4349 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -90,7 +90,7 @@
   va_end(ap);
 }
 
-static void Usage(const char* fmt, ...) {
+[[noreturn]] static void Usage(const char* fmt, ...) {
   va_list ap;
   va_start(ap, fmt);
   UsageErrorV(fmt, ap);
@@ -662,7 +662,7 @@
     Message('W', message);
   }
 
-  static void Fatal(const std::string& message) {
+  [[noreturn]] static void Fatal(const std::string& message) {
     Message('F', message);
     exit(1);
   }
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index fbb36f3..4ed428c 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -644,7 +644,7 @@
   va_end(ap);
 }
 
-static void Usage(const char *fmt, ...) {
+[[noreturn]] static void Usage(const char *fmt, ...) {
   va_list ap;
   va_start(ap, fmt);
   UsageErrorV(fmt, ap);
diff --git a/runtime/arch/x86/fault_handler_x86.cc b/runtime/arch/x86/fault_handler_x86.cc
index 6715fd3..9d74ef5 100644
--- a/runtime/arch/x86/fault_handler_x86.cc
+++ b/runtime/arch/x86/fault_handler_x86.cc
@@ -184,6 +184,7 @@
 
       case 0x80:        // group 1, byte immediate.
       case 0x83:
+      case 0xc6:
         modrm = *pc++;
         has_modrm = true;
         immediate_size = 1;
diff --git a/runtime/base/histogram-inl.h b/runtime/base/histogram-inl.h
index 4c18ce4..b329a31 100644
--- a/runtime/base/histogram-inl.h
+++ b/runtime/base/histogram-inl.h
@@ -195,6 +195,11 @@
   DCHECK_LE(std::abs(out_data->perc_.back() - 1.0), 0.001);
 }
 
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wfloat-equal"
+#endif
+
 template <class Value>
 inline double Histogram<Value>::Percentile(double per, const CumulativeData& data) const {
   DCHECK_GT(data.perc_.size(), 0ull);
@@ -235,6 +240,10 @@
   return value;
 }
 
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
 }  // namespace art
 #endif  // ART_RUNTIME_BASE_HISTOGRAM_INL_H_
 
diff --git a/runtime/base/histogram_test.cc b/runtime/base/histogram_test.cc
index 454f2ab..7aa5f90 100644
--- a/runtime/base/histogram_test.cc
+++ b/runtime/base/histogram_test.cc
@@ -41,14 +41,14 @@
     hist->AddValue(static_cast<uint64_t>(50));
   }
   mean = hist->Mean();
-  EXPECT_EQ(mean, 50);
+  EXPECT_DOUBLE_EQ(mean, 50.0);
   hist->Reset();
   hist->AddValue(9);
   hist->AddValue(17);
   hist->AddValue(28);
   hist->AddValue(28);
   mean = hist->Mean();
-  EXPECT_EQ(20.5, mean);
+  EXPECT_DOUBLE_EQ(20.5, mean);
 }
 
 TEST(Histtest, VarianceTest) {
@@ -60,7 +60,7 @@
   hist->AddValue(28);
   hist->AddValue(28);
   variance = hist->Variance();
-  EXPECT_EQ(64.25, variance);
+  EXPECT_DOUBLE_EQ(64.25, variance);
 }
 
 TEST(Histtest, Percentile) {
@@ -236,7 +236,7 @@
   }
   hist->CreateHistogram(&data);
   per_995 = hist->Percentile(0.995, data);
-  EXPECT_EQ(per_995, 0);
+  EXPECT_DOUBLE_EQ(per_995, 0.0);
   hist->Reset();
   for (size_t idx = 0; idx < 200; idx++) {
     for (uint64_t val = 1ull; val <= 4ull; val++) {
@@ -246,8 +246,8 @@
   hist->CreateHistogram(&data);
   per_005 = hist->Percentile(0.005, data);
   per_995 = hist->Percentile(0.995, data);
-  EXPECT_EQ(1, per_005);
-  EXPECT_EQ(4, per_995);
+  EXPECT_DOUBLE_EQ(1.0, per_005);
+  EXPECT_DOUBLE_EQ(4.0, per_995);
 }
 
 TEST(Histtest, SpikyValues) {
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index e990181..88e6265 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -907,12 +907,12 @@
 
   mirror::ArtField* s6 = mirror::Class::FindStaticField(soa.Self(), statics, "s6", "F");
   EXPECT_EQ(s6->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
-  EXPECT_EQ(0.5, s6->GetFloat(statics.Get()));
+  EXPECT_DOUBLE_EQ(0.5, s6->GetFloat(statics.Get()));
   s6->SetFloat<false>(statics.Get(), 0.75);
 
   mirror::ArtField* s7 = mirror::Class::FindStaticField(soa.Self(), statics, "s7", "D");
   EXPECT_EQ(s7->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
-  EXPECT_EQ(16777217, s7->GetDouble(statics.Get()));
+  EXPECT_DOUBLE_EQ(16777217.0, s7->GetDouble(statics.Get()));
   s7->SetDouble<false>(statics.Get(), 16777219);
 
   mirror::ArtField* s8 = mirror::Class::FindStaticField(soa.Self(), statics, "s8",
@@ -930,8 +930,8 @@
   EXPECT_EQ(-535, s3->GetShort(statics.Get()));
   EXPECT_EQ(2000000001, s4->GetInt(statics.Get()));
   EXPECT_EQ(INT64_C(0x34567890abcdef12), s5->GetLong(statics.Get()));
-  EXPECT_EQ(0.75, s6->GetFloat(statics.Get()));
-  EXPECT_EQ(16777219, s7->GetDouble(statics.Get()));
+  EXPECT_FLOAT_EQ(0.75, s6->GetFloat(statics.Get()));
+  EXPECT_DOUBLE_EQ(16777219.0, s7->GetDouble(statics.Get()));
   EXPECT_TRUE(s8->GetObject(statics.Get())->AsString()->Equals("robot"));
 }
 
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index c53f6b2..971ff89 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -4365,11 +4365,7 @@
 
   Thread* self = Thread::Current();
 
-  // To allow the Walk/InspectAll() below to exclusively-lock the
-  // mutator lock, temporarily release the shared access to the
-  // mutator lock here by transitioning to the suspended state.
   Locks::mutator_lock_->AssertSharedHeld(self);
-  self->TransitionFromRunnableToSuspended(kSuspended);
 
   // Send a series of heap segment chunks.
   HeapChunkContext context((what == HPSG_WHAT_MERGED_OBJECTS), native);
@@ -4383,32 +4379,39 @@
     gc::Heap* heap = Runtime::Current()->GetHeap();
     for (const auto& space : heap->GetContinuousSpaces()) {
       if (space->IsDlMallocSpace()) {
+        ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
         // dlmalloc's chunk header is 2 * sizeof(size_t), but if the previous chunk is in use for an
         // allocation then the first sizeof(size_t) may belong to it.
         context.SetChunkOverhead(sizeof(size_t));
         space->AsDlMallocSpace()->Walk(HeapChunkContext::HeapChunkCallback, &context);
       } else if (space->IsRosAllocSpace()) {
         context.SetChunkOverhead(0);
-        space->AsRosAllocSpace()->Walk(HeapChunkContext::HeapChunkCallback, &context);
+        // Need to acquire the mutator lock before the heap bitmap lock with exclusive access since
+        // RosAlloc's internal logic doesn't know to release and reacquire the heap bitmap lock.
+        self->TransitionFromRunnableToSuspended(kSuspended);
+        ThreadList* tl = Runtime::Current()->GetThreadList();
+        tl->SuspendAll();
+        {
+          ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
+          space->AsRosAllocSpace()->Walk(HeapChunkContext::HeapChunkCallback, &context);
+        }
+        tl->ResumeAll();
+        self->TransitionFromSuspendedToRunnable();
       } else if (space->IsBumpPointerSpace()) {
+        ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
         context.SetChunkOverhead(0);
-        ReaderMutexLock mu(self, *Locks::mutator_lock_);
-        WriterMutexLock mu2(self, *Locks::heap_bitmap_lock_);
         space->AsBumpPointerSpace()->Walk(BumpPointerSpaceCallback, &context);
       } else {
         UNIMPLEMENTED(WARNING) << "Not counting objects in space " << *space;
       }
       context.ResetStartOfNextChunk();
     }
+    ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
     // Walk the large objects, these are not in the AllocSpace.
     context.SetChunkOverhead(0);
     heap->GetLargeObjectsSpace()->Walk(HeapChunkContext::HeapChunkCallback, &context);
   }
 
-  // Shared-lock the mutator lock back.
-  self->TransitionFromSuspendedToRunnable();
-  Locks::mutator_lock_->AssertSharedHeld(self);
-
   // Finally, send a heap end chunk.
   Dbg::DdmSendChunk(native ? CHUNK_TYPE("NHEN") : CHUNK_TYPE("HPEN"), sizeof(heap_id), heap_id);
 }
diff --git a/runtime/entrypoints/quick/quick_math_entrypoints.cc b/runtime/entrypoints/quick/quick_math_entrypoints.cc
index 014aad3..1c658b7 100644
--- a/runtime/entrypoints/quick/quick_math_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_math_entrypoints.cc
@@ -18,6 +18,11 @@
 
 namespace art {
 
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wfloat-equal"
+#endif
+
 int CmplFloat(float a, float b) {
   if (a == b) {
     return 0;
@@ -62,6 +67,10 @@
   return -1;
 }
 
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
 extern "C" int64_t artLmul(int64_t a, int64_t b) {
   return a * b;
 }
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 054dd46..96903db 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1275,8 +1275,8 @@
   // is at *m = sp. Will update to point to the bottom of the save frame.
   //
   // Note: assumes ComputeAll() has been run before.
-  void LayoutCalleeSaveFrame(StackReference<mirror::ArtMethod>** m, void* sp, HandleScope** table,
-                             uint32_t* handle_scope_entries)
+  void LayoutCalleeSaveFrame(Thread* self, StackReference<mirror::ArtMethod>** m, void* sp,
+                             HandleScope** handle_scope)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     mirror::ArtMethod* method = (*m)->AsMirrorPtr();
 
@@ -1289,8 +1289,6 @@
     sp8 += sizeof(void*);  // In the callee-save frame we use a full pointer.
 
     // Under the callee saves put handle scope and new method stack reference.
-    *handle_scope_entries = num_handle_scope_references_;
-
     size_t handle_scope_size = HandleScope::SizeOf(num_handle_scope_references_);
     size_t scope_and_method = handle_scope_size + sizeof(StackReference<mirror::ArtMethod>);
 
@@ -1300,8 +1298,8 @@
         reinterpret_cast<uintptr_t>(sp8), kStackAlignment));
 
     uint8_t* sp8_table = sp8 + sizeof(StackReference<mirror::ArtMethod>);
-    *table = reinterpret_cast<HandleScope*>(sp8_table);
-    (*table)->SetNumberOfReferences(num_handle_scope_references_);
+    *handle_scope = HandleScope::Create(sp8_table, self->GetTopHandleScope(),
+                                        num_handle_scope_references_);
 
     // Add a slot for the method pointer, and fill it. Fix the pointer-pointer given to us.
     uint8_t* method_pointer = sp8;
@@ -1319,12 +1317,12 @@
 
   // Re-layout the callee-save frame (insert a handle-scope). Then add space for the cookie.
   // Returns the new bottom. Note: this may be unaligned.
-  uint8_t* LayoutJNISaveFrame(StackReference<mirror::ArtMethod>** m, void* sp, HandleScope** table,
-                              uint32_t* handle_scope_entries)
+  uint8_t* LayoutJNISaveFrame(Thread* self, StackReference<mirror::ArtMethod>** m, void* sp,
+                              HandleScope** handle_scope)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     // First, fix up the layout of the callee-save frame.
     // We have to squeeze in the HandleScope, and relocate the method pointer.
-    LayoutCalleeSaveFrame(m, sp, table, handle_scope_entries);
+    LayoutCalleeSaveFrame(self, m, sp, handle_scope);
 
     // The bottom of the callee-save frame is now where the method is, *m.
     uint8_t* sp8 = reinterpret_cast<uint8_t*>(*m);
@@ -1336,14 +1334,15 @@
   }
 
   // WARNING: After this, *sp won't be pointing to the method anymore!
-  uint8_t* ComputeLayout(StackReference<mirror::ArtMethod>** m, bool is_static, const char* shorty,
-                         uint32_t shorty_len, HandleScope** table, uint32_t* handle_scope_entries,
+  uint8_t* ComputeLayout(Thread* self, StackReference<mirror::ArtMethod>** m,
+                         bool is_static, const char* shorty, uint32_t shorty_len,
+                         HandleScope** handle_scope,
                          uintptr_t** start_stack, uintptr_t** start_gpr, uint32_t** start_fpr)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Walk(shorty, shorty_len);
 
     // JNI part.
-    uint8_t* sp8 = LayoutJNISaveFrame(m, reinterpret_cast<void*>(*m), table, handle_scope_entries);
+    uint8_t* sp8 = LayoutJNISaveFrame(self, m, reinterpret_cast<void*>(*m), handle_scope);
 
     sp8 = LayoutNativeCall(sp8, start_stack, start_gpr, start_fpr);
 
@@ -1426,20 +1425,19 @@
 // of transitioning into native code.
 class BuildGenericJniFrameVisitor FINAL : public QuickArgumentVisitor {
  public:
-  BuildGenericJniFrameVisitor(StackReference<mirror::ArtMethod>** sp, bool is_static,
-                              const char* shorty, uint32_t shorty_len, Thread* self)
+  BuildGenericJniFrameVisitor(Thread* self, bool is_static, const char* shorty, uint32_t shorty_len,
+                              StackReference<mirror::ArtMethod>** sp)
      : QuickArgumentVisitor(*sp, is_static, shorty, shorty_len),
        jni_call_(nullptr, nullptr, nullptr, nullptr), sm_(&jni_call_) {
     ComputeGenericJniFrameSize fsc;
     uintptr_t* start_gpr_reg;
     uint32_t* start_fpr_reg;
     uintptr_t* start_stack_arg;
-    uint32_t handle_scope_entries;
-    bottom_of_used_area_ = fsc.ComputeLayout(sp, is_static, shorty, shorty_len, &handle_scope_,
-                                             &handle_scope_entries, &start_stack_arg,
+    bottom_of_used_area_ = fsc.ComputeLayout(self, sp, is_static, shorty, shorty_len,
+                                             &handle_scope_,
+                                             &start_stack_arg,
                                              &start_gpr_reg, &start_fpr_reg);
 
-    handle_scope_->SetNumberOfReferences(handle_scope_entries);
     jni_call_.Reset(start_gpr_reg, start_fpr_reg, start_stack_arg, handle_scope_);
 
     // jni environment is always first argument
@@ -1611,7 +1609,7 @@
   const char* shorty = called->GetShorty(&shorty_len);
 
   // Run the visitor.
-  BuildGenericJniFrameVisitor visitor(&sp, called->IsStatic(), shorty, shorty_len, self);
+  BuildGenericJniFrameVisitor visitor(self, called->IsStatic(), shorty, shorty_len, &sp);
   visitor.VisitArguments();
   visitor.FinalizeHandleScope(self);
 
diff --git a/runtime/gc/allocator/rosalloc.h b/runtime/gc/allocator/rosalloc.h
index 8374ff7..ad7f901 100644
--- a/runtime/gc/allocator/rosalloc.h
+++ b/runtime/gc/allocator/rosalloc.h
@@ -285,7 +285,7 @@
 
   // Returns the byte size of the bracket size from the index.
   static size_t IndexToBracketSize(size_t idx) {
-    DCHECK(idx < kNumOfSizeBrackets);
+    DCHECK_LT(idx, kNumOfSizeBrackets);
     return bracketSizes[idx];
   }
   // Returns the index of the size bracket from the bracket size.
diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h
index 7bc811d..2717180 100644
--- a/runtime/handle_scope-inl.h
+++ b/runtime/handle_scope-inl.h
@@ -26,9 +26,10 @@
 
 template<size_t kNumReferences>
 inline StackHandleScope<kNumReferences>::StackHandleScope(Thread* self)
-    : HandleScope(kNumReferences), self_(self), pos_(0) {
+    : HandleScope(self->GetTopHandleScope(), kNumReferences), self_(self), pos_(0) {
+  COMPILE_ASSERT(kNumReferences >= 1, stack_handle_scope_must_contain_at_least_1_reference);
   // TODO: Figure out how to use a compile assert.
-  DCHECK_EQ(&references_[0], &references_storage_[0]);
+  CHECK_EQ(&storage_[0], GetReferences());
   for (size_t i = 0; i < kNumReferences; ++i) {
     SetReference(i, nullptr);
   }
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index 99059f9..f795e38 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -66,39 +66,28 @@
     return link_;
   }
 
-  void SetLink(HandleScope* link) {
-    DCHECK_NE(this, link);
-    link_ = link;
-  }
-
-  // Sets the number_of_references_ field for constructing tables out of raw memory. Warning: will
-  // not resize anything.
-  void SetNumberOfReferences(uint32_t num_references) {
-    number_of_references_ = num_references;
-  }
-
-  mirror::Object* GetReference(size_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      ALWAYS_INLINE {
+  ALWAYS_INLINE mirror::Object* GetReference(size_t i) const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK_LT(i, number_of_references_);
-    return references_[i].AsMirrorPtr();
+    return GetReferences()[i].AsMirrorPtr();
   }
 
-  Handle<mirror::Object> GetHandle(size_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      ALWAYS_INLINE {
+  ALWAYS_INLINE Handle<mirror::Object> GetHandle(size_t i)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK_LT(i, number_of_references_);
-    return Handle<mirror::Object>(&references_[i]);
+    return Handle<mirror::Object>(&GetReferences()[i]);
   }
 
-  MutableHandle<mirror::Object> GetMutableHandle(size_t i)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
+  ALWAYS_INLINE MutableHandle<mirror::Object> GetMutableHandle(size_t i)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK_LT(i, number_of_references_);
-    return MutableHandle<mirror::Object>(&references_[i]);
+    return MutableHandle<mirror::Object>(&GetReferences()[i]);
   }
 
-  void SetReference(size_t i, mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      ALWAYS_INLINE {
+  ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK_LT(i, number_of_references_);
-    references_[i].Assign(object);
+    GetReferences()[i].Assign(object);
   }
 
   bool Contains(StackReference<mirror::Object>* handle_scope_entry) const {
@@ -106,39 +95,53 @@
     // jni_compiler should have a jobject/jclass as a native method is
     // passed in a this pointer or a class
     DCHECK_GT(number_of_references_, 0U);
-    return &references_[0] <= handle_scope_entry &&
-        handle_scope_entry <= &references_[number_of_references_ - 1];
+    return &GetReferences()[0] <= handle_scope_entry &&
+        handle_scope_entry <= &GetReferences()[number_of_references_ - 1];
   }
 
-  // Offset of link within HandleScope, used by generated code
+  // Offset of link within HandleScope, used by generated code.
   static size_t LinkOffset(size_t pointer_size) {
     return 0;
   }
 
-  // Offset of length within handle scope, used by generated code
+  // Offset of length within handle scope, used by generated code.
   static size_t NumberOfReferencesOffset(size_t pointer_size) {
     return pointer_size;
   }
 
-  // Offset of link within handle scope, used by generated code
+  // Offset of link within handle scope, used by generated code.
   static size_t ReferencesOffset(size_t pointer_size) {
     return pointer_size + sizeof(number_of_references_);
   }
 
- protected:
-  explicit HandleScope(size_t number_of_references) :
-      link_(nullptr), number_of_references_(number_of_references) {
+  // Placement new creation.
+  static HandleScope* Create(void* storage, HandleScope* link, uint32_t num_references)
+      WARN_UNUSED {
+    return new (storage) HandleScope(link, num_references);
   }
 
-  HandleScope* link_;
-  uint32_t number_of_references_;
+ protected:
+  // Return backing storage used for references.
+  ALWAYS_INLINE StackReference<mirror::Object>* GetReferences() const {
+    uintptr_t address = reinterpret_cast<uintptr_t>(this) + ReferencesOffset(sizeof(void*));
+    return reinterpret_cast<StackReference<mirror::Object>*>(address);
+  }
 
-  // number_of_references_ are available if this is allocated and filled in by jni_compiler.
-  StackReference<mirror::Object> references_[0];
+  // Semi-hidden constructor. Construction expected by generated code and StackHandleScope.
+  explicit HandleScope(HandleScope* link, uint32_t num_references) :
+      link_(link), number_of_references_(num_references) {
+  }
+
+  // Link-list of handle scopes. The root is held by a Thread.
+  HandleScope* const link_;
+
+  // Number of handlerized references.
+  const uint32_t number_of_references_;
+
+  // Storage for references.
+  // StackReference<mirror::Object> references_[number_of_references_]
 
  private:
-  template<size_t kNumReferences> friend class StackHandleScope;
-
   DISALLOW_COPY_AND_ASSIGN(HandleScope);
 };
 
@@ -169,22 +172,22 @@
   // Currently unused, using this GetReference instead of the one in HandleScope is preferred to
   // avoid compiler optimizations incorrectly optimizing out of bound array accesses.
   // TODO: Remove this when it is un-necessary.
-  mirror::Object* GetReference(size_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      ALWAYS_INLINE {
-    DCHECK_LT(i, number_of_references_);
-    return references_storage_[i].AsMirrorPtr();
+  ALWAYS_INLINE mirror::Object* GetReference(size_t i) const
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    DCHECK_LT(i, kNumReferences);
+    return GetReferences()[i].AsMirrorPtr();
   }
 
-  MutableHandle<mirror::Object> GetHandle(size_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      ALWAYS_INLINE {
-    DCHECK_LT(i, number_of_references_);
-    return MutableHandle<mirror::Object>(&references_storage_[i]);
+  ALWAYS_INLINE MutableHandle<mirror::Object> GetHandle(size_t i)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    DCHECK_LT(i, kNumReferences);
+    return MutableHandle<mirror::Object>(&GetReferences()[i]);
   }
 
-  void SetReference(size_t i, mirror::Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      ALWAYS_INLINE {
-    DCHECK_LT(i, number_of_references_);
-    references_storage_[i].Assign(object);
+  ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    DCHECK_LT(i, kNumReferences);
+    GetReferences()[i].Assign(object);
   }
 
   template<class T>
@@ -204,9 +207,8 @@
   }
 
  private:
-  // References_storage_ needs to be first so that it appears in the same location as
-  // HandleScope::references_.
-  StackReference<mirror::Object> references_storage_[kNumReferences];
+  // Reference storage needs to be first as expected by the HandleScope layout.
+  StackReference<mirror::Object> storage_[kNumReferences];
 
   // The thread that the stack handle scope is a linked list upon. The stack handle scope will
   // push and pop itself from this thread.
diff --git a/runtime/handle_scope_test.cc b/runtime/handle_scope_test.cc
index 7afd279..dc99987 100644
--- a/runtime/handle_scope_test.cc
+++ b/runtime/handle_scope_test.cc
@@ -25,7 +25,7 @@
 template<size_t kNumReferences>
 class NoThreadStackHandleScope : public HandleScope {
  public:
-  explicit NoThreadStackHandleScope() : HandleScope(kNumReferences) {
+  explicit NoThreadStackHandleScope(HandleScope* link) : HandleScope(link, kNumReferences) {
   }
   ~NoThreadStackHandleScope() {
   }
@@ -41,10 +41,8 @@
 TEST(HandleScopeTest, Offsets) NO_THREAD_SAFETY_ANALYSIS {
   // As the members of HandleScope are private, we cannot use OFFSETOF_MEMBER
   // here. So do the inverse: set some data, and access it through pointers created from the offsets.
-  NoThreadStackHandleScope<1> test_table;
+  NoThreadStackHandleScope<0x9ABC> test_table(reinterpret_cast<HandleScope*>(0x5678));
   test_table.SetReference(0, reinterpret_cast<mirror::Object*>(0x1234));
-  test_table.SetLink(reinterpret_cast<HandleScope*>(0x5678));
-  test_table.SetNumberOfReferences(0x9ABC);
 
   uint8_t* table_base_ptr = reinterpret_cast<uint8_t*>(&test_table);
 
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index db7c452..88d6544 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -662,6 +662,11 @@
   }
   HANDLE_INSTRUCTION_END();
 
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wfloat-equal"
+#endif
+
   HANDLE_INSTRUCTION_START(CMPL_FLOAT) {
     float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
     float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
@@ -726,6 +731,10 @@
   }
   HANDLE_INSTRUCTION_END();
 
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
   HANDLE_INSTRUCTION_START(CMP_LONG) {
     int64_t val1 = shadow_frame.GetVRegLong(inst->VRegB_23x());
     int64_t val2 = shadow_frame.GetVRegLong(inst->VRegC_23x());
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index fe0af27..14e8a52 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -562,6 +562,12 @@
         inst = inst->RelativeAt(offset);
         break;
       }
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wfloat-equal"
+#endif
+
       case Instruction::CMPL_FLOAT: {
         PREAMBLE();
         float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
@@ -627,6 +633,11 @@
         inst = inst->Next_2xx();
         break;
       }
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
       case Instruction::CMP_LONG: {
         PREAMBLE();
         int64_t val1 = shadow_frame.GetVRegLong(inst->VRegB_23x());
diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc
index 20d031c..cab907c 100644
--- a/runtime/jni_internal_test.cc
+++ b/runtime/jni_internal_test.cc
@@ -1527,14 +1527,14 @@
   EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni));
 }
 
-#define EXPECT_STATIC_PRIMITIVE_FIELD(type, field_name, sig, value1, value2) \
+#define EXPECT_STATIC_PRIMITIVE_FIELD(expect_eq, type, field_name, sig, value1, value2) \
   do { \
     jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
     EXPECT_NE(fid, nullptr); \
     env_->SetStatic ## type ## Field(c, fid, value1); \
-    EXPECT_EQ(value1, env_->GetStatic ## type ## Field(c, fid)); \
+    expect_eq(value1, env_->GetStatic ## type ## Field(c, fid)); \
     env_->SetStatic ## type ## Field(c, fid, value2); \
-    EXPECT_EQ(value2, env_->GetStatic ## type ## Field(c, fid)); \
+    expect_eq(value2, env_->GetStatic ## type ## Field(c, fid)); \
     \
     bool old_check_jni = vm_->SetCheckJniEnabled(false); \
     { \
@@ -1560,14 +1560,14 @@
     EXPECT_TRUE(vm_->SetCheckJniEnabled(old_check_jni)); \
   } while (false)
 
-#define EXPECT_PRIMITIVE_FIELD(instance, type, field_name, sig, value1, value2) \
+#define EXPECT_PRIMITIVE_FIELD(expect_eq, instance, type, field_name, sig, value1, value2) \
   do { \
     jfieldID fid = env_->GetFieldID(c, field_name, sig); \
     EXPECT_NE(fid, nullptr); \
     env_->Set ## type ## Field(instance, fid, value1); \
-    EXPECT_EQ(value1, env_->Get ## type ## Field(instance, fid)); \
+    expect_eq(value1, env_->Get ## type ## Field(instance, fid)); \
     env_->Set ## type ## Field(instance, fid, value2); \
-    EXPECT_EQ(value2, env_->Get ## type ## Field(instance, fid)); \
+    expect_eq(value2, env_->Get ## type ## Field(instance, fid)); \
     \
     bool old_check_jni = vm_->SetCheckJniEnabled(false); \
     CheckJniAbortCatcher jni_abort_catcher; \
@@ -1604,23 +1604,23 @@
   jobject o = env_->AllocObject(c);
   ASSERT_NE(o, nullptr);
 
-  EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", JNI_TRUE, JNI_FALSE);
-  EXPECT_STATIC_PRIMITIVE_FIELD(Byte, "sB", "B", 1, 2);
-  EXPECT_STATIC_PRIMITIVE_FIELD(Char, "sC", "C", 'a', 'b');
-  EXPECT_STATIC_PRIMITIVE_FIELD(Double, "sD", "D", 1.0, 2.0);
-  EXPECT_STATIC_PRIMITIVE_FIELD(Float, "sF", "F", 1.0, 2.0);
-  EXPECT_STATIC_PRIMITIVE_FIELD(Int, "sI", "I", 1, 2);
-  EXPECT_STATIC_PRIMITIVE_FIELD(Long, "sJ", "J", 1, 2);
-  EXPECT_STATIC_PRIMITIVE_FIELD(Short, "sS", "S", 1, 2);
+  EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Boolean, "sZ", "Z", JNI_TRUE, JNI_FALSE);
+  EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Byte, "sB", "B", 1, 2);
+  EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Char, "sC", "C", 'a', 'b');
+  EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_DOUBLE_EQ, Double, "sD", "D", 1.0, 2.0);
+  EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_FLOAT_EQ, Float, "sF", "F", 1.0, 2.0);
+  EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Int, "sI", "I", 1, 2);
+  EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Long, "sJ", "J", 1, 2);
+  EXPECT_STATIC_PRIMITIVE_FIELD(EXPECT_EQ, Short, "sS", "S", 1, 2);
 
-  EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", JNI_TRUE, JNI_FALSE);
-  EXPECT_PRIMITIVE_FIELD(o, Byte, "iB", "B", 1, 2);
-  EXPECT_PRIMITIVE_FIELD(o, Char, "iC", "C", 'a', 'b');
-  EXPECT_PRIMITIVE_FIELD(o, Double, "iD", "D", 1.0, 2.0);
-  EXPECT_PRIMITIVE_FIELD(o, Float, "iF", "F", 1.0, 2.0);
-  EXPECT_PRIMITIVE_FIELD(o, Int, "iI", "I", 1, 2);
-  EXPECT_PRIMITIVE_FIELD(o, Long, "iJ", "J", 1, 2);
-  EXPECT_PRIMITIVE_FIELD(o, Short, "iS", "S", 1, 2);
+  EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Boolean, "iZ", "Z", JNI_TRUE, JNI_FALSE);
+  EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Byte, "iB", "B", 1, 2);
+  EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Char, "iC", "C", 'a', 'b');
+  EXPECT_PRIMITIVE_FIELD(EXPECT_DOUBLE_EQ, o, Double, "iD", "D", 1.0, 2.0);
+  EXPECT_PRIMITIVE_FIELD(EXPECT_FLOAT_EQ, o, Float, "iF", "F", 1.0, 2.0);
+  EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Int, "iI", "I", 1, 2);
+  EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Long, "iJ", "J", 1, 2);
+  EXPECT_PRIMITIVE_FIELD(EXPECT_EQ, o, Short, "iS", "S", 1, 2);
 }
 
 TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 1aeba74..a2a0626 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -248,12 +248,6 @@
 TEST_F(ObjectTest, PrimitiveArray_Char_Alloc) {
   TestPrimitiveArray<CharArray>(class_linker_);
 }
-TEST_F(ObjectTest, PrimitiveArray_Double_Alloc) {
-  TestPrimitiveArray<DoubleArray>(class_linker_);
-}
-TEST_F(ObjectTest, PrimitiveArray_Float_Alloc) {
-  TestPrimitiveArray<FloatArray>(class_linker_);
-}
 TEST_F(ObjectTest, PrimitiveArray_Int_Alloc) {
   TestPrimitiveArray<IntArray>(class_linker_);
 }
@@ -264,6 +258,67 @@
   TestPrimitiveArray<ShortArray>(class_linker_);
 }
 
+TEST_F(ObjectTest, PrimitiveArray_Double_Alloc) {
+  typedef DoubleArray ArrayT;
+  ScopedObjectAccess soa(Thread::Current());
+  typedef typename ArrayT::ElementType T;
+
+  ArrayT* a = ArrayT::Alloc(soa.Self(), 2);
+  EXPECT_EQ(2, a->GetLength());
+  EXPECT_DOUBLE_EQ(0, a->Get(0));
+  EXPECT_DOUBLE_EQ(0, a->Get(1));
+  a->Set(0, T(123));
+  EXPECT_DOUBLE_EQ(T(123), a->Get(0));
+  EXPECT_DOUBLE_EQ(0, a->Get(1));
+  a->Set(1, T(321));
+  EXPECT_DOUBLE_EQ(T(123), a->Get(0));
+  EXPECT_DOUBLE_EQ(T(321), a->Get(1));
+
+  Class* aioobe = class_linker_->FindSystemClass(soa.Self(),
+                                                 "Ljava/lang/ArrayIndexOutOfBoundsException;");
+
+  EXPECT_DOUBLE_EQ(0, a->Get(-1));
+  EXPECT_TRUE(soa.Self()->IsExceptionPending());
+  EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
+  soa.Self()->ClearException();
+
+  EXPECT_DOUBLE_EQ(0, a->Get(2));
+  EXPECT_TRUE(soa.Self()->IsExceptionPending());
+  EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
+  soa.Self()->ClearException();
+}
+
+TEST_F(ObjectTest, PrimitiveArray_Float_Alloc) {
+  typedef FloatArray ArrayT;
+  ScopedObjectAccess soa(Thread::Current());
+  typedef typename ArrayT::ElementType T;
+
+  ArrayT* a = ArrayT::Alloc(soa.Self(), 2);
+  EXPECT_FLOAT_EQ(2, a->GetLength());
+  EXPECT_FLOAT_EQ(0, a->Get(0));
+  EXPECT_FLOAT_EQ(0, a->Get(1));
+  a->Set(0, T(123));
+  EXPECT_FLOAT_EQ(T(123), a->Get(0));
+  EXPECT_FLOAT_EQ(0, a->Get(1));
+  a->Set(1, T(321));
+  EXPECT_FLOAT_EQ(T(123), a->Get(0));
+  EXPECT_FLOAT_EQ(T(321), a->Get(1));
+
+  Class* aioobe = class_linker_->FindSystemClass(soa.Self(),
+                                                 "Ljava/lang/ArrayIndexOutOfBoundsException;");
+
+  EXPECT_FLOAT_EQ(0, a->Get(-1));
+  EXPECT_TRUE(soa.Self()->IsExceptionPending());
+  EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
+  soa.Self()->ClearException();
+
+  EXPECT_FLOAT_EQ(0, a->Get(2));
+  EXPECT_TRUE(soa.Self()->IsExceptionPending());
+  EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
+  soa.Self()->ClearException();
+}
+
+
 TEST_F(ObjectTest, CheckAndAllocArrayFromCode) {
   // pretend we are trying to call 'new char[3]' from String.toCharArray
   ScopedObjectAccess soa(Thread::Current());
diff --git a/runtime/native/java_lang_Runtime.cc b/runtime/native/java_lang_Runtime.cc
index a85eec7..f9a1cee 100644
--- a/runtime/native/java_lang_Runtime.cc
+++ b/runtime/native/java_lang_Runtime.cc
@@ -37,7 +37,7 @@
   Runtime::Current()->GetHeap()->CollectGarbage(false);
 }
 
-static void Runtime_nativeExit(JNIEnv*, jclass, jint status) {
+[[noreturn]] static void Runtime_nativeExit(JNIEnv*, jclass, jint status) {
   LOG(INFO) << "System.exit called, status: " << status;
   Runtime::Current()->CallExitHook(status);
   exit(status);
diff --git a/runtime/parsed_options_test.cc b/runtime/parsed_options_test.cc
index 5154d69..61481b1 100644
--- a/runtime/parsed_options_test.cc
+++ b/runtime/parsed_options_test.cc
@@ -64,7 +64,7 @@
   EXPECT_EQ(2048U, parsed->heap_initial_size_);
   EXPECT_EQ(4 * KB, parsed->heap_maximum_size_);
   EXPECT_EQ(1 * MB, parsed->stack_size_);
-  EXPECT_EQ(0.75, parsed->heap_target_utilization_);
+  EXPECT_DOUBLE_EQ(0.75, parsed->heap_target_utilization_);
   EXPECT_TRUE(test_vfprintf == parsed->hook_vfprintf_);
   EXPECT_TRUE(test_exit == parsed->hook_exit_);
   EXPECT_TRUE(test_abort == parsed->hook_abort_);
diff --git a/runtime/reflection_test.cc b/runtime/reflection_test.cc
index 75211e0..f8e0f47 100644
--- a/runtime/reflection_test.cc
+++ b/runtime/reflection_test.cc
@@ -193,19 +193,19 @@
 
     args[0].d = 0.0;
     JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(0.0, result.GetD());
+    EXPECT_DOUBLE_EQ(0.0, result.GetD());
 
     args[0].d = -1.0;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(-1.0, result.GetD());
+    EXPECT_DOUBLE_EQ(-1.0, result.GetD());
 
     args[0].d = DBL_MAX;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(DBL_MAX, result.GetD());
+    EXPECT_DOUBLE_EQ(DBL_MAX, result.GetD());
 
     args[0].d = DBL_MIN;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(DBL_MIN, result.GetD());
+    EXPECT_DOUBLE_EQ(DBL_MIN, result.GetD());
   }
 
   void InvokeSumIntIntMethod(bool is_static) {
@@ -375,27 +375,27 @@
     args[0].d = 0.0;
     args[1].d = 0.0;
     JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(0.0, result.GetD());
+    EXPECT_DOUBLE_EQ(0.0, result.GetD());
 
     args[0].d = 1.0;
     args[1].d = 2.0;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(3.0, result.GetD());
+    EXPECT_DOUBLE_EQ(3.0, result.GetD());
 
     args[0].d = 1.0;
     args[1].d = -2.0;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(-1.0, result.GetD());
+    EXPECT_DOUBLE_EQ(-1.0, result.GetD());
 
     args[0].d = DBL_MAX;
     args[1].d = DBL_MIN;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(1.7976931348623157e308, result.GetD());
+    EXPECT_DOUBLE_EQ(1.7976931348623157e308, result.GetD());
 
     args[0].d = DBL_MAX;
     args[1].d = DBL_MAX;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(INFINITY, result.GetD());
+    EXPECT_DOUBLE_EQ(INFINITY, result.GetD());
   }
 
   void InvokeSumDoubleDoubleDoubleMethod(bool is_static) {
@@ -409,19 +409,19 @@
     args[1].d = 0.0;
     args[2].d = 0.0;
     JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(0.0, result.GetD());
+    EXPECT_DOUBLE_EQ(0.0, result.GetD());
 
     args[0].d = 1.0;
     args[1].d = 2.0;
     args[2].d = 3.0;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(6.0, result.GetD());
+    EXPECT_DOUBLE_EQ(6.0, result.GetD());
 
     args[0].d = 1.0;
     args[1].d = -2.0;
     args[2].d = 3.0;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(2.0, result.GetD());
+    EXPECT_DOUBLE_EQ(2.0, result.GetD());
   }
 
   void InvokeSumDoubleDoubleDoubleDoubleMethod(bool is_static) {
@@ -436,21 +436,21 @@
     args[2].d = 0.0;
     args[3].d = 0.0;
     JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(0.0, result.GetD());
+    EXPECT_DOUBLE_EQ(0.0, result.GetD());
 
     args[0].d = 1.0;
     args[1].d = 2.0;
     args[2].d = 3.0;
     args[3].d = 4.0;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(10.0, result.GetD());
+    EXPECT_DOUBLE_EQ(10.0, result.GetD());
 
     args[0].d = 1.0;
     args[1].d = -2.0;
     args[2].d = 3.0;
     args[3].d = -4.0;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(-2.0, result.GetD());
+    EXPECT_DOUBLE_EQ(-2.0, result.GetD());
   }
 
   void InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(bool is_static) {
@@ -466,7 +466,7 @@
     args[3].d = 0.0;
     args[4].d = 0.0;
     JValue result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(0.0, result.GetD());
+    EXPECT_DOUBLE_EQ(0.0, result.GetD());
 
     args[0].d = 1.0;
     args[1].d = 2.0;
@@ -474,7 +474,7 @@
     args[3].d = 4.0;
     args[4].d = 5.0;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(15.0, result.GetD());
+    EXPECT_DOUBLE_EQ(15.0, result.GetD());
 
     args[0].d = 1.0;
     args[1].d = -2.0;
@@ -482,7 +482,7 @@
     args[3].d = -4.0;
     args[4].d = 5.0;
     result = InvokeWithJValues(soa, receiver, soa.EncodeMethod(method), args);
-    EXPECT_EQ(3.0, result.GetD());
+    EXPECT_DOUBLE_EQ(3.0, result.GetD());
   }
 
   JavaVMExt* vm_;
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 1a6c6e0..7bffc33 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -177,10 +177,7 @@
 
   // Aborts semi-cleanly. Used in the implementation of LOG(FATAL), which most
   // callers should prefer.
-  // This isn't marked ((noreturn)) because then gcc will merge multiple calls
-  // in a single function together. This reduces code size slightly, but means
-  // that the native stack trace we get may point at the wrong call site.
-  static void Abort() LOCKS_EXCLUDED(Locks::abort_lock_);
+  [[noreturn]] static void Abort() LOCKS_EXCLUDED(Locks::abort_lock_);
 
   // Returns the "main" ThreadGroup, used when attaching user threads.
   jobject GetMainThreadGroup() const;
diff --git a/runtime/thread.h b/runtime/thread.h
index 998e472..b0be841 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -692,7 +692,7 @@
   }
 
   void PushHandleScope(HandleScope* handle_scope) {
-    handle_scope->SetLink(tlsPtr_.top_handle_scope);
+    DCHECK_EQ(handle_scope->GetLink(), tlsPtr_.top_handle_scope);
     tlsPtr_.top_handle_scope = handle_scope;
   }
 
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index a14889c..8c4b90d 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -147,12 +147,12 @@
   mirror::ArtField* floatField = h_klass->FindDeclaredStaticField("floatField", "F");
   ASSERT_TRUE(floatField != nullptr);
   ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
-  ASSERT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
+  ASSERT_FLOAT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
 
   mirror::ArtField* doubleField = h_klass->FindDeclaredStaticField("doubleField", "D");
   ASSERT_TRUE(doubleField != nullptr);
   ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
-  ASSERT_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
+  ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
 
   mirror::ArtField* objectField = h_klass->FindDeclaredStaticField("objectField",
                                                                       "Ljava/lang/Object;");
@@ -190,8 +190,8 @@
   EXPECT_EQ(shortField->GetShort(h_klass.Get()), 0);
   EXPECT_EQ(intField->GetInt(h_klass.Get()), 0);
   EXPECT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0));
-  EXPECT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
-  EXPECT_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
+  EXPECT_FLOAT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
+  EXPECT_DOUBLE_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
   EXPECT_EQ(objectField->GetObject(h_klass.Get()), nullptr);
 }
 
@@ -246,12 +246,12 @@
   mirror::ArtField* floatField = h_klass->FindDeclaredInstanceField("floatField", "F");
   ASSERT_TRUE(floatField != nullptr);
   ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
-  ASSERT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
+  ASSERT_FLOAT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
 
   mirror::ArtField* doubleField = h_klass->FindDeclaredInstanceField("doubleField", "D");
   ASSERT_TRUE(doubleField != nullptr);
   ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
-  ASSERT_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
+  ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
 
   mirror::ArtField* objectField = h_klass->FindDeclaredInstanceField("objectField",
                                                                         "Ljava/lang/Object;");
@@ -289,8 +289,8 @@
   EXPECT_EQ(shortField->GetShort(h_instance.Get()), 0);
   EXPECT_EQ(intField->GetInt(h_instance.Get()), 0);
   EXPECT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0));
-  EXPECT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
-  EXPECT_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
+  EXPECT_FLOAT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
+  EXPECT_DOUBLE_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
   EXPECT_EQ(objectField->GetObject(h_instance.Get()), nullptr);
 }
 
@@ -356,14 +356,14 @@
   mirror::FloatArray* floatArray = floatArrayField->GetObject(h_klass.Get())->AsFloatArray();
   ASSERT_TRUE(floatArray != nullptr);
   ASSERT_EQ(floatArray->GetLength(), 1);
-  ASSERT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
+  ASSERT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
 
   mirror::ArtField* doubleArrayField = h_klass->FindDeclaredStaticField("doubleArrayField", "[D");
   ASSERT_TRUE(doubleArrayField != nullptr);
   mirror::DoubleArray* doubleArray = doubleArrayField->GetObject(h_klass.Get())->AsDoubleArray();
   ASSERT_TRUE(doubleArray != nullptr);
   ASSERT_EQ(doubleArray->GetLength(), 1);
-  ASSERT_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
+  ASSERT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
 
   mirror::ArtField* objectArrayField = h_klass->FindDeclaredStaticField("objectArrayField",
                                                                            "[Ljava/lang/Object;");
@@ -404,8 +404,8 @@
   EXPECT_EQ(shortArray->GetWithoutChecks(0), 0);
   EXPECT_EQ(intArray->GetWithoutChecks(0), 0);
   EXPECT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
-  EXPECT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
-  EXPECT_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
+  EXPECT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
+  EXPECT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
   EXPECT_EQ(objectArray->GetWithoutChecks(0), nullptr);
 }
 
diff --git a/test/800-smali/build b/test/800-smali/build
new file mode 100644
index 0000000..1b5a4e3
--- /dev/null
+++ b/test/800-smali/build
@@ -0,0 +1,32 @@
+#!/bin/bash
+#
+# 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.
+
+# Stop if something fails.
+set -e
+
+# Compile Java classes
+mkdir classes
+${JAVAC} -d classes `find src -name '*.java'`
+${DX} -JXmx256m --debug --dex --output=java_classes.dex classes
+
+# Compile Smali classes
+${SMALI} -JXmx256m --output smali_classes.dex `find src -name '*.smali'`
+
+# Combine files.
+${DXMERGER} classes.dex java_classes.dex smali_classes.dex
+
+# Zip up output.
+zip $TEST_NAME.jar classes.dex
diff --git a/test/800-smali/expected.txt b/test/800-smali/expected.txt
new file mode 100644
index 0000000..468e7a6
--- /dev/null
+++ b/test/800-smali/expected.txt
@@ -0,0 +1,2 @@
+b/17790197
+Done!
diff --git a/test/800-smali/info.txt b/test/800-smali/info.txt
new file mode 100644
index 0000000..cfcc230
--- /dev/null
+++ b/test/800-smali/info.txt
@@ -0,0 +1,4 @@
+Smali-based tests.
+Will compile and run all the smali files in src/ and run the test cases mentioned in src/Main.java.
+
+Obviously needs to run under Dalvik or ART.
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
new file mode 100644
index 0000000..0ef3a9d
--- /dev/null
+++ b/test/800-smali/src/Main.java
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Smali excercise.
+ */
+public class Main {
+
+    private static class TestCase {
+        public TestCase(String testName, String testClass, String testMethodName, Object[] values,
+                        Throwable expectedException, Object expectedReturn) {
+            this.testName = testName;
+            this.testClass = testClass;
+            this.testMethodName = testMethodName;
+            this.values = values;
+            this.expectedException = expectedException;
+            this.expectedReturn = expectedReturn;
+        }
+
+        String testName;
+        String testClass;
+        String testMethodName;
+        Object[] values;
+        Throwable expectedException;
+        Object expectedReturn;
+    }
+
+    private List<TestCase> testCases;
+
+    public Main() {
+        // Create the test cases.
+        testCases = new LinkedList<TestCase>();
+
+        testCases.add(new TestCase("b/17790197", "B17790197", "getInt", null, null, 100));
+    }
+
+    public void runTests() {
+        for (TestCase tc : testCases) {
+            System.out.println(tc.testName);
+            try {
+                runTest(tc);
+            } catch (Exception exc) {
+                exc.printStackTrace(System.out);
+            }
+        }
+    }
+
+    private void runTest(TestCase tc) throws Exception {
+        Class<?> c = Class.forName(tc.testClass);
+
+        Method[] methods = c.getDeclaredMethods();
+
+        // For simplicity we assume that test methods are not overloaded. So searching by name
+        // will give us the method we need to run.
+        Method method = null;
+        for (Method m : methods) {
+            if (m.getName().equals(tc.testMethodName)) {
+                method = m;
+                break;
+            }
+        }
+
+        if (method == null) {
+            throw new IllegalArgumentException("Could not find test method " + tc.testMethodName +
+                    " in class " + tc.testClass + " for test " + tc.testName);
+        }
+
+        Exception errorReturn = null;
+        try {
+            Object retValue = method.invoke(null, tc.values);
+            if (tc.expectedException != null) {
+                errorReturn = new IllegalStateException("Expected an exception in test " +
+                                                        tc.testName);
+            }
+            if (tc.expectedReturn == null && retValue != null) {
+                errorReturn = new IllegalStateException("Expected a null result in test " +
+                                                        tc.testName);
+            } else if (tc.expectedReturn != null &&
+                       (retValue == null || !tc.expectedReturn.equals(retValue))) {
+                errorReturn = new IllegalStateException("Expected return " + tc.expectedReturn +
+                                                        ", but got " + retValue);
+            }
+        } catch (Exception exc) {
+            if (tc.expectedException == null) {
+                errorReturn = new IllegalStateException("Did not expect exception", exc);
+            } else if (!tc.expectedException.getClass().equals(exc.getClass())) {
+                errorReturn = new IllegalStateException("Expected " +
+                                                tc.expectedException.getClass().getName() +
+                                                ", but got " + exc.getClass(), exc);
+            }
+        } finally {
+            if (errorReturn != null) {
+                throw errorReturn;
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        Main main = new Main();
+
+        main.runTests();
+
+        System.out.println("Done!");
+    }
+}
diff --git a/test/800-smali/src/b_17790197.smali b/test/800-smali/src/b_17790197.smali
new file mode 100644
index 0000000..7560fcf
--- /dev/null
+++ b/test/800-smali/src/b_17790197.smali
@@ -0,0 +1,17 @@
+.class public LB17790197;
+
+.super Ljava/lang/Object;
+
+.method public static getInt()I
+    .registers 4
+    const/16 v0, 100
+    const/4 v1, 1
+    const/4 v2, 7
+    :loop
+    if-eq v2, v0, :done
+    add-int v2, v2, v1
+    goto :loop
+    :done
+    add-float v3, v0, v1
+    return v2
+.end method
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 5ca8bec..9082b47 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -36,9 +36,11 @@
 # $(1): the test number
 define define-build-art-run-test
   dmart_target := $(art_run_tests_dir)/art-run-tests/$(1)/touch
-$$(dmart_target): $(DX) $(HOST_OUT_EXECUTABLES)/jasmin
+$$(dmart_target): $(DX) $(HOST_OUT_EXECUTABLES)/jasmin $(HOST_OUT_EXECUTABLES)/smali $(HOST_OUT_EXECUTABLES)/dexmerger
 	$(hide) rm -rf $$(dir $$@) && mkdir -p $$(dir $$@)
 	$(hide) DX=$(abspath $(DX)) JASMIN=$(abspath $(HOST_OUT_EXECUTABLES)/jasmin) \
+	  SMALI=$(abspath $(HOST_OUT_EXECUTABLES)/smali) \
+	  DXMERGER=$(abspath $(HOST_OUT_EXECUTABLES)/dexmerger) \
 	  $(LOCAL_PATH)/run-test --build-only --output-path $$(abspath $$(dir $$@)) $(1)
 	$(hide) touch $$@
 
@@ -50,7 +52,7 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE := art-run-tests
-LOCAL_ADDITIONAL_DEPENDENCIES := $(TEST_ART_RUN_TEST_BUILD_RULES)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TEST_ART_RUN_TEST_BUILD_RULES) smali dexmerger
 # The build system use this flag to pick up files generated by declare-make-art-run-test.
 LOCAL_PICKUP_FILES := $(art_run_tests_dir)
 
@@ -204,7 +206,8 @@
 
 # Tests that are broken with GC stress.
 TEST_ART_BROKEN_GCSTRESS_RUN_TESTS := \
-  004-SignalTest
+  004-SignalTest \
+  114-ParallelGC
 
 ifneq (,$(filter gcstress,$(GC_TYPES)))
   ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(PREBUILD_TYPES), \
@@ -454,9 +457,11 @@
       $$(run_test_options)
 $$(run_test_rule_name): PRIVATE_RUN_TEST_OPTIONS := $$(run_test_options)
 .PHONY: $$(run_test_rule_name)
-$$(run_test_rule_name): $(DX) $(HOST_OUT_EXECUTABLES)/jasmin $$(prereq_rule)
+$$(run_test_rule_name): $(DX) $(HOST_OUT_EXECUTABLES)/jasmin $(HOST_OUT_EXECUTABLES)/smali $(HOST_OUT_EXECUTABLES)/dexmerger $$(prereq_rule)
 	$(hide) $$(call ART_TEST_SKIP,$$@) && \
 	  DX=$(abspath $(DX)) JASMIN=$(abspath $(HOST_OUT_EXECUTABLES)/jasmin) \
+	    SMALI=$(abspath $(HOST_OUT_EXECUTABLES)/smali) \
+	    DXMERGER=$(abspath $(HOST_OUT_EXECUTABLES)/dexmerger) \
 	    art/test/run-test $$(PRIVATE_RUN_TEST_OPTIONS) $(9) \
 	      && $$(call ART_TEST_PASSED,$$@) || $$(call ART_TEST_FAILED,$$@)
 	$$(hide) (echo $(MAKECMDGOALS) | grep -q $$@ && \
diff --git a/test/run-test b/test/run-test
index 3b5df0d..3e98d6d 100755
--- a/test/run-test
+++ b/test/run-test
@@ -55,6 +55,16 @@
   export JASMIN="jasmin"
 fi
 
+# If smali was not set by the environment variable, assume it is in the path.
+if [ -z "$SMALI" ]; then
+  export SMALI="smali"
+fi
+
+# If dexmerger was not set by the environment variable, assume it is in the path.
+if [ -z "$DXMERGER" ]; then
+  export DXMERGER="dexmerger"
+fi
+
 
 info="info.txt"
 build="build"