Support null-filled HandleScopes without mutator_lock_

Creating a HandleScope used to always require (via assert) the
mutator_lock_ be held. When the scope is filled with null (as it
normally is) this is not needed however.

Test: ./test.py --host
Change-Id: I47acbcaeafc7617f264233a5ab869eded6a22473
diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h
index 90cf597..0539059 100644
--- a/runtime/handle_scope-inl.h
+++ b/runtime/handle_scope-inl.h
@@ -44,6 +44,16 @@
 }
 
 template<size_t kNumReferences>
+inline FixedSizeHandleScope<kNumReferences>::FixedSizeHandleScope(BaseHandleScope* link)
+    : HandleScope(link, kNumReferences) {
+  static_assert(kNumReferences >= 1, "FixedSizeHandleScope must contain at least 1 reference");
+  DCHECK_EQ(&storage_[0], GetReferences());  // TODO: Figure out how to use a compile assert.
+  for (size_t i = 0; i < kNumReferences; ++i) {
+    SetReferenceToNull(i);
+  }
+}
+
+template<size_t kNumReferences>
 inline StackHandleScope<kNumReferences>::StackHandleScope(Thread* self,
                                                           ObjPtr<mirror::Object> fill_value)
     : FixedSizeHandleScope<kNumReferences>(self->GetTopHandleScope(), fill_value),
@@ -56,9 +66,6 @@
 inline StackHandleScope<kNumReferences>::~StackHandleScope() {
   BaseHandleScope* top_handle_scope = self_->PopHandleScope();
   DCHECK_EQ(top_handle_scope, this);
-  if (kDebugLocking) {
-    Locks::mutator_lock_->AssertSharedHeld(self_);
-  }
 }
 
 inline size_t HandleScope::SizeOf(uint32_t num_references) {
@@ -154,6 +161,11 @@
   GetReferences()[i].Assign(object);
 }
 
+template<size_t kNumReferences>
+inline void FixedSizeHandleScope<kNumReferences>::SetReferenceToNull(size_t i) {
+  DCHECK_LT(i, kNumReferences);
+  GetReferences()[i].Assign(nullptr);
+}
 // Number of references contained within this handle scope.
 inline uint32_t BaseHandleScope::NumberOfReferences() const {
   return LIKELY(!IsVariableSized())
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index b173453..ed77e19 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -195,10 +195,16 @@
   }
 
  private:
+  explicit ALWAYS_INLINE FixedSizeHandleScope(BaseHandleScope* link);
   explicit ALWAYS_INLINE FixedSizeHandleScope(BaseHandleScope* link,
-                                              ObjPtr<mirror::Object> fill_value = nullptr);
+                                              ObjPtr<mirror::Object> fill_value)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+
   ALWAYS_INLINE ~FixedSizeHandleScope() {}
 
+  // Helper to set references to null without any mutator-locks.
+  ALWAYS_INLINE void SetReferenceToNull(size_t i);
+
   template<class T>
   ALWAYS_INLINE MutableHandle<T> GetHandle(size_t i) REQUIRES_SHARED(Locks::mutator_lock_) {
     DCHECK_LT(i, kNumReferences);