Assignability checks for SetFieldObject.

Adds check to SetFieldObject that is enabled with VERIFY_OBJECT_ENABLED.
The check verifies that the object being set to the field is assignable
to that field.

Fix bug that iftable was typed to be Object[][] but being assigned a
Object[].

Change-Id: I3d3744347f2dd142ca90db321ed876eaebfe7f7f
diff --git a/src/class_linker.cc b/src/class_linker.cc
index c7c3a33..26af575 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -165,6 +165,7 @@
   "Ljava/lang/Object;",
   "[Ljava/lang/Class;",
   "[Ljava/lang/Object;",
+  "[[Ljava/lang/Object;",
   "Ljava/lang/String;",
   "Ljava/lang/DexCache;",
   "Ljava/lang/ref/Reference;",
@@ -242,39 +243,43 @@
   SirtRef<Class> class_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
   class_array_class->SetComponentType(java_lang_Class.get());
 
-  // java_lang_Object comes next so that object_array_class can be created
+  // java_lang_Object comes next so that object_array_class can be created.
   SirtRef<Class> java_lang_Object(AllocClass(java_lang_Class.get(), sizeof(Class)));
   CHECK(java_lang_Object.get() != NULL);
-  // backfill Object as the super class of Class
+  // backfill Object as the super class of Class.
   java_lang_Class->SetSuperClass(java_lang_Object.get());
   java_lang_Object->SetStatus(Class::kStatusLoaded);
 
-  // Object[] next to hold class roots
+  // Object[] next to hold class roots.
   SirtRef<Class> object_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
   object_array_class->SetComponentType(java_lang_Object.get());
 
-  // Setup the char class to be used for char[]
+  // Object[][] needed for iftables.
+  SirtRef<Class> object_array_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  object_array_array_class->SetComponentType(object_array_class.get());
+
+  // Setup the char class to be used for char[].
   SirtRef<Class> char_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
 
-  // Setup the char[] class to be used for String
+  // Setup the char[] class to be used for String.
   SirtRef<Class> char_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
   char_array_class->SetComponentType(char_class.get());
   CharArray::SetArrayClass(char_array_class.get());
 
-  // Setup String
+  // Setup String.
   SirtRef<Class> java_lang_String(AllocClass(java_lang_Class.get(), sizeof(StringClass)));
   String::SetClass(java_lang_String.get());
   java_lang_String->SetObjectSize(sizeof(String));
   java_lang_String->SetStatus(Class::kStatusResolved);
 
-  // Create storage for root classes, save away our work so far (requires
-  // descriptors)
+  // Create storage for root classes, save away our work so far (requires descriptors).
   class_roots_ = ObjectArray<Class>::Alloc(object_array_class.get(), kClassRootsMax);
   CHECK(class_roots_ != NULL);
   SetClassRoot(kJavaLangClass, java_lang_Class.get());
   SetClassRoot(kJavaLangObject, java_lang_Object.get());
   SetClassRoot(kClassArrayClass, class_array_class.get());
   SetClassRoot(kObjectArrayClass, object_array_class.get());
+  SetClassRoot(kObjectArrayArrayClass, object_array_array_class.get());
   SetClassRoot(kCharArrayClass, char_array_class.get());
   SetClassRoot(kJavaLangString, java_lang_String.get());
 
@@ -288,10 +293,10 @@
   SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass(Primitive::kPrimDouble));
   SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass(Primitive::kPrimVoid));
 
-  // Create array interface entries to populate once we can load system classes
-  array_iftable_ = AllocObjectArray<InterfaceEntry>(2);
+  // Create array interface entries to populate once we can load system classes.
+  array_iftable_ = AllocIfTable(2);
 
-  // Create int array type for AllocDexCache (done in AppendToBootClassPath)
+  // Create int array type for AllocDexCache (done in AppendToBootClassPath).
   SirtRef<Class> int_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
   int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt));
   IntArray::SetArrayClass(int_array_class.get());
@@ -347,9 +352,9 @@
   object_array_abstract_method->SetComponentType(java_lang_reflect_AbstractMethod.get());
   SetClassRoot(kJavaLangReflectAbstractMethodArrayClass, object_array_abstract_method.get());
 
-  // setup boot_class_path_ and register class_path now that we can
-  // use AllocObjectArray to create DexCache instances
-  // Needs to be after String, Field, Method arrays since AllocDexCache uses these roots.
+  // Setup boot_class_path_ and register class_path now that we can use AllocObjectArray to create
+  // DexCache instances. Needs to be after String, Field, Method arrays since AllocDexCache uses
+  // these roots.
   CHECK_NE(0U, boot_class_path.size());
   for (size_t i = 0; i != boot_class_path.size(); ++i) {
     const DexFile* dex_file = boot_class_path[i];
@@ -378,7 +383,7 @@
   CHECK_EQ(java_lang_DexCache.get(), DexCache_class);
   CHECK_EQ(java_lang_DexCache->GetObjectSize(), sizeof(DexCache));
 
-  // Setup the primitive array type classes - can't be done until Object has a vtable
+  // Setup the primitive array type classes - can't be done until Object has a vtable.
   SetClassRoot(kBooleanArrayClass, FindSystemClass("[Z"));
   BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
 
@@ -409,26 +414,28 @@
   Class* found_object_array_class = FindSystemClass("[Ljava/lang/Object;");
   CHECK_EQ(object_array_class.get(), found_object_array_class);
 
-  // Setup the single, global copies of "interfaces" and "iftable"
+  Class* found_object_array_array_class = FindSystemClass("[[Ljava/lang/Object;");
+  CHECK_EQ(object_array_array_class.get(), found_object_array_array_class);
+
+  // Setup the single, global copy of "iftable".
   Class* java_lang_Cloneable = FindSystemClass("Ljava/lang/Cloneable;");
   CHECK(java_lang_Cloneable != NULL);
   Class* java_io_Serializable = FindSystemClass("Ljava/io/Serializable;");
   CHECK(java_io_Serializable != NULL);
-  // We assume that Cloneable/Serializable don't have superinterfaces --
-  // normally we'd have to crawl up and explicitly list all of the
-  // supers as well.
+  // We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to
+  // crawl up and explicitly list all of the supers as well.
   array_iftable_->Set(0, AllocInterfaceEntry(java_lang_Cloneable));
   array_iftable_->Set(1, AllocInterfaceEntry(java_io_Serializable));
 
-  // Sanity check Class[] and Object[]'s interfaces
+  // Sanity check Class[] and Object[]'s interfaces.
   ClassHelper kh(class_array_class.get(), this);
   CHECK_EQ(java_lang_Cloneable, kh.GetDirectInterface(0));
   CHECK_EQ(java_io_Serializable, kh.GetDirectInterface(1));
   kh.ChangeClass(object_array_class.get());
   CHECK_EQ(java_lang_Cloneable, kh.GetDirectInterface(0));
   CHECK_EQ(java_io_Serializable, kh.GetDirectInterface(1));
-  // run Class, Constructor, Field, and Method through FindSystemClass.
-  // this initializes their dex_cache_ fields and register them in classes_.
+  // Run Class, Constructor, Field, and Method through FindSystemClass. This initializes their
+  // dex_cache_ fields and register them in classes_.
   Class* Class_class = FindSystemClass("Ljava/lang/Class;");
   CHECK_EQ(java_lang_Class.get(), Class_class);
 
@@ -460,9 +467,9 @@
       FindSystemClass(class_roots_descriptors_[kJavaLangReflectAbstractMethodArrayClass]);
   CHECK_EQ(object_array_abstract_method.get(), Abstract_method_array_class);
 
-  // End of special init trickery, subsequent classes may be loaded via FindSystemClass
+  // End of special init trickery, subsequent classes may be loaded via FindSystemClass.
 
-  // Create java.lang.reflect.Proxy root
+  // Create java.lang.reflect.Proxy root.
   Class* java_lang_reflect_Proxy = FindSystemClass("Ljava/lang/reflect/Proxy;");
   SetClassRoot(kJavaLangReflectProxy, java_lang_reflect_Proxy);
 
@@ -485,13 +492,13 @@
       java_lang_ref_WeakReference->GetAccessFlags() |
           kAccClassIsReference | kAccClassIsWeakReference);
 
-  // Setup the ClassLoader, verifying the object_size_
+  // Setup the ClassLoader, verifying the object_size_.
   Class* java_lang_ClassLoader = FindSystemClass("Ljava/lang/ClassLoader;");
   CHECK_EQ(java_lang_ClassLoader->GetObjectSize(), sizeof(ClassLoader));
   SetClassRoot(kJavaLangClassLoader, java_lang_ClassLoader);
 
   // Set up java.lang.Throwable, java.lang.ClassNotFoundException, and
-  // java.lang.StackTraceElement as a convenience
+  // java.lang.StackTraceElement as a convenience.
   SetClassRoot(kJavaLangThrowable, FindSystemClass("Ljava/lang/Throwable;"));
   Throwable::SetClass(GetClassRoot(kJavaLangThrowable));
   SetClassRoot(kJavaLangClassNotFoundException, FindSystemClass("Ljava/lang/ClassNotFoundException;"));
@@ -1862,6 +1869,8 @@
       new_class.reset(GetClassRoot(kClassArrayClass));
     } else if (descriptor == "[Ljava/lang/Object;") {
       new_class.reset(GetClassRoot(kObjectArrayClass));
+    } else if (descriptor == "[[Ljava/lang/Object;") {
+      new_class.reset(GetClassRoot(kObjectArrayArrayClass));
     } else if (descriptor == class_roots_descriptors_[kJavaLangStringArrayClass]) {
       new_class.reset(GetClassRoot(kJavaLangStringArrayClass));
     } else if (descriptor == class_roots_descriptors_[kJavaLangReflectFieldArrayClass]) {
@@ -3037,7 +3046,7 @@
     // DCHECK(klass->GetIfTable() == NULL);
     return true;
   }
-  SirtRef<ObjectArray<InterfaceEntry> > iftable(AllocObjectArray<InterfaceEntry>(ifcount));
+  SirtRef<ObjectArray<InterfaceEntry> > iftable(AllocIfTable(ifcount));
   if (super_ifcount != 0) {
     ObjectArray<InterfaceEntry>* super_iftable = klass->GetSuperClass()->GetIfTable();
     for (size_t i = 0; i < super_ifcount; i++) {
diff --git a/src/class_linker.h b/src/class_linker.h
index 67c2fbe..d75e1b2 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -334,6 +334,11 @@
         GetClassRoot(kJavaLangReflectAbstractMethodArrayClass), length);
   }
 
+  ObjectArray<InterfaceEntry>* AllocIfTable(size_t length)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return ObjectArray<InterfaceEntry>::Alloc(GetClassRoot(kObjectArrayArrayClass), length);
+  }
+
   ObjectArray<Field>* AllocFieldArray(size_t length)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     return ObjectArray<Field>::Alloc(GetClassRoot(kJavaLangReflectFieldArrayClass), length);
@@ -437,14 +442,12 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void LoadField(const DexFile& dex_file, const ClassDataItemIterator& it, SirtRef<Class>& klass,
-                 SirtRef<Field>& dst);
+                 SirtRef<Field>& dst) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   AbstractMethod* LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& dex_method,
-                  SirtRef<Class>& klass)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+                  SirtRef<Class>& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  void FixupStaticTrampolines(Class* klass)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void FixupStaticTrampolines(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Finds the associated oat class for a dex_file and descriptor
   const OatFile::OatClass* GetOatClass(const DexFile& dex_file, const char* descriptor);
@@ -566,6 +569,7 @@
     kJavaLangObject,
     kClassArrayClass,
     kObjectArrayClass,
+    kObjectArrayArrayClass,
     kJavaLangString,
     kJavaLangDexCache,
     kJavaLangRefReference,
diff --git a/src/heap.h b/src/heap.h
index 1f9ac86..d3127de 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -170,13 +170,14 @@
                            MemberOffset finalizer_reference_zombie_offset);
 
   Object* GetReferenceReferent(Object* reference);
-  void ClearReferenceReferent(Object* reference);
+  void ClearReferenceReferent(Object* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Returns true if the reference object has not yet been enqueued.
   bool IsEnqueuable(const Object* ref);
-  void EnqueueReference(Object* ref, Object** list);
-  void EnqueuePendingReference(Object* ref, Object** list);
-  Object* DequeuePendingReference(Object** list);
+  void EnqueueReference(Object* ref, Object** list) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void EnqueuePendingReference(Object* ref, Object** list)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  Object* DequeuePendingReference(Object** list) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   MemberOffset GetReferencePendingNextOffset() {
     DCHECK_NE(reference_pendingNext_offset_.Uint32Value(), 0U);
@@ -199,6 +200,10 @@
     verify_objects_ = false;
   }
 
+  bool IsObjectValidationEnabled() const {
+    return verify_objects_;
+  }
+
   void RecordFree(size_t freed_objects, size_t freed_bytes);
 
   // Must be called if a field of an Object in the heap changes, and before any GC safe-point.
diff --git a/src/mark_sweep.h b/src/mark_sweep.h
index aaeb0ff..d6218dc 100644
--- a/src/mark_sweep.h
+++ b/src/mark_sweep.h
@@ -339,7 +339,7 @@
 
   // Schedules an unmarked object for reference processing.
   void DelayReferenceReferent(Object* reference)
-      SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
 
   // Recursively blackens objects on the mark stack.
   void ProcessMarkStack()
@@ -355,7 +355,7 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void ClearWhiteReferences(Object** list)
-      SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+      SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_);
 
   void ProcessReferences(Object** soft_references, bool clear_soft_references,
                          Object** weak_references,
diff --git a/src/object.cc b/src/object.cc
index e4b5f98..eb11469 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -115,6 +115,51 @@
   Monitor::Wait(Thread::Current(), this, ms, ns, true);
 }
 
+#if VERIFY_OBJECT_ENABLED
+void Object::CheckFieldAssignment(MemberOffset field_offset, const Object* new_value) {
+  const Class* c = GetClass();
+  if (Runtime::Current()->GetClassLinker() == NULL ||
+      !Runtime::Current()->GetHeap()->IsObjectValidationEnabled() ||
+      !c->IsResolved()) {
+    return;
+  }
+  for (const Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) {
+    ObjectArray<Field>* fields = cur->GetIFields();
+    if (fields != NULL) {
+      size_t num_ref_ifields = cur->NumReferenceInstanceFields();
+      for (size_t i = 0; i < num_ref_ifields; ++i) {
+        Field* field = fields->Get(i);
+        if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
+          FieldHelper fh(field);
+          CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass()));
+          return;
+        }
+      }
+    }
+  }
+  if (c->IsArrayClass()) {
+    // Bounds and assign-ability done in the array setter.
+    return;
+  }
+  if (IsClass()) {
+    ObjectArray<Field>* fields = AsClass()->GetSFields();
+    if (fields != NULL) {
+      size_t num_ref_sfields = AsClass()->NumReferenceStaticFields();
+      for (size_t i = 0; i < num_ref_sfields; ++i) {
+        Field* field = fields->Get(i);
+        if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
+          FieldHelper fh(field);
+          CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass()));
+          return;
+        }
+      }
+    }
+  }
+  LOG(FATAL) << "Failed to find field for assignment to " << reinterpret_cast<void*>(this)
+      << " of type " << PrettyDescriptor(c) << " at offset " << field_offset;
+}
+#endif
+
 // TODO: get global references for these
 Class* Field::java_lang_reflect_Field_ = NULL;
 
diff --git a/src/object.h b/src/object.h
index 5a9a825..a1e1032 100644
--- a/src/object.h
+++ b/src/object.h
@@ -292,10 +292,12 @@
     return result;
   }
 
-  void SetFieldObject(MemberOffset field_offset, const Object* new_value, bool is_volatile, bool this_is_valid = true) {
+  void SetFieldObject(MemberOffset field_offset, const Object* new_value, bool is_volatile,
+                      bool this_is_valid = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     Runtime::Current()->GetHeap()->VerifyObject(new_value);
     SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid);
     if (new_value != NULL) {
+      CheckFieldAssignment(field_offset, new_value);
       Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
     }
   }
@@ -370,6 +372,14 @@
   }
 
  private:
+#if VERIFY_OBJECT_ENABLED
+  void CheckFieldAssignment(MemberOffset field_offset, const Object* new_value)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+#else
+  void CheckFieldAssignment(MemberOffset, const Object*)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {}
+#endif
+
   Class* klass_;
 
   uint32_t monitor_;
@@ -384,7 +394,7 @@
  public:
   Class* GetDeclaringClass() const;
 
-  void SetDeclaringClass(Class *new_declaring_class);
+  void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   uint32_t GetAccessFlags() const;
 
@@ -518,7 +528,7 @@
 
   Class* GetDeclaringClass() const;
 
-  void SetDeclaringClass(Class *new_declaring_class);
+  void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static MemberOffset DeclaringClassOffset() {
     return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_));
@@ -624,7 +634,8 @@
   }
 
   ObjectArray<String>* GetDexCacheStrings() const;
-  void SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings);
+  void SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static MemberOffset DexCacheStringsOffset() {
     return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_strings_);
@@ -644,13 +655,16 @@
   }
 
   ObjectArray<AbstractMethod>* GetDexCacheResolvedMethods() const;
-  void SetDexCacheResolvedMethods(ObjectArray<AbstractMethod>* new_dex_cache_methods);
+  void SetDexCacheResolvedMethods(ObjectArray<AbstractMethod>* new_dex_cache_methods)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   ObjectArray<Class>* GetDexCacheResolvedTypes() const;
-  void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types);
+  void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   ObjectArray<StaticStorageBase>* GetDexCacheInitializedStaticStorage() const;
-  void SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value);
+  void SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Find the method that this method overrides
   AbstractMethod* FindOverriddenMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -1087,8 +1101,7 @@
 
   // Set element without bound and element type checks, to be used in limited
   // circumstances, such as during boot image writing
-  void SetWithoutChecks(int32_t i, T* object)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void SetWithoutChecks(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   T* GetWithoutChecks(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
@@ -1298,10 +1311,10 @@
   }
 
 
-  String* GetName() const; // Returns the cached name
-  void SetName(String* name);  // Sets the cached name
-  String* ComputeName()  // Computes the name, then sets the cached value
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  String* GetName() const;  // Returns the cached name.
+  void SetName(String* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);  // Sets the cached name.
+  // Computes the name, then sets the cached value.
+  String* ComputeName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsProxyClass() const {
     // Read access flags without using getter as whether something is a proxy can be check in
@@ -1386,7 +1399,7 @@
     return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, component_type_), false);
   }
 
-  void SetComponentType(Class* new_component_type) {
+  void SetComponentType(Class* new_component_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(GetComponentType() == NULL);
     DCHECK(new_component_type != NULL);
     SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, component_type_), new_component_type, false);
@@ -1510,7 +1523,7 @@
     return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
   }
 
-  void SetSuperClass(Class *new_super_class) {
+  void SetSuperClass(Class *new_super_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     // super class is assigned once, except during class linker initialization
     Class* old_super_class = GetFieldObject<Class*>(
         OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
@@ -1529,7 +1542,7 @@
 
   ClassLoader* GetClassLoader() const;
 
-  void SetClassLoader(ClassLoader* new_cl);
+  void SetClassLoader(ClassLoader* new_cl) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static MemberOffset DexCacheOffset() {
     return MemberOffset(OFFSETOF_MEMBER(Class, dex_cache_));
@@ -1546,7 +1559,7 @@
 
   DexCache* GetDexCache() const;
 
-  void SetDexCache(DexCache* new_dex_cache);
+  void SetDexCache(DexCache* new_dex_cache) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   ObjectArray<AbstractMethod>* GetDirectMethods() const {
     DCHECK(IsLoaded() || IsErroneous());
@@ -1554,7 +1567,8 @@
         OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
   }
 
-  void SetDirectMethods(ObjectArray<AbstractMethod>* new_direct_methods) {
+  void SetDirectMethods(ObjectArray<AbstractMethod>* new_direct_methods)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(NULL == GetFieldObject<ObjectArray<AbstractMethod>*>(
         OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false));
     DCHECK_NE(0, new_direct_methods->GetLength());
@@ -1586,7 +1600,8 @@
         OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
   }
 
-  void SetVirtualMethods(ObjectArray<AbstractMethod>* new_virtual_methods) {
+  void SetVirtualMethods(ObjectArray<AbstractMethod>* new_virtual_methods)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     // TODO: we reassign virtual methods to grow the table for miranda
     // methods.. they should really just be assigned once
     DCHECK_NE(0, new_virtual_methods->GetLength());
@@ -1629,7 +1644,8 @@
     return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
   }
 
-  void SetVTable(ObjectArray<AbstractMethod>* new_vtable) {
+  void SetVTable(ObjectArray<AbstractMethod>* new_vtable)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable, false);
   }
 
@@ -1709,7 +1725,8 @@
         OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false);
   }
 
-  void SetIfTable(ObjectArray<InterfaceEntry>* new_iftable) {
+  void SetIfTable(ObjectArray<InterfaceEntry>* new_iftable)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable, false);
   }
 
@@ -1719,7 +1736,7 @@
     return GetFieldObject<ObjectArray<Field>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
   }
 
-  void SetIFields(ObjectArray<Field>* new_ifields) {
+  void SetIFields(ObjectArray<Field>* new_ifields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(NULL == GetFieldObject<ObjectArray<Field>*>(
         OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false));
     SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields, false);
@@ -1796,7 +1813,7 @@
     return GetFieldObject<ObjectArray<Field>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
   }
 
-  void SetSFields(ObjectArray<Field>* new_sfields) {
+  void SetSFields(ObjectArray<Field>* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(NULL == GetFieldObject<ObjectArray<Field>*>(
         OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false));
     SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields, false);
@@ -1881,8 +1898,7 @@
   }
 
  private:
-  void SetVerifyErrorClass(Class* klass)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  void SetVerifyErrorClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     CHECK(klass != NULL) << PrettyClass(this);
     SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass, false);
   }
@@ -2386,7 +2402,7 @@
     SetField32(OFFSET_OF_OBJECT_MEMBER(String, offset_), new_offset, false);
   }
 
-  void SetArray(CharArray* new_array) {
+  void SetArray(CharArray* new_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     DCHECK(new_array != NULL);
     SetFieldObject(OFFSET_OF_OBJECT_MEMBER(String, array_), new_array, false);
   }
@@ -2505,9 +2521,8 @@
 // C++ mirror of java.lang.Throwable
 class MANAGED Throwable : public Object {
  public:
-  void SetDetailMessage(String* new_detail_message) {
-    SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_),
-                   new_detail_message, false);
+  void SetDetailMessage(String* new_detail_message) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), new_detail_message, false);
   }
   String* GetDetailMessage() const {
     return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), false);
@@ -2517,7 +2532,7 @@
   // This is a runtime version of initCause, you shouldn't use it if initCause may have been
   // overridden. Also it asserts rather than throwing exceptions. Currently this is only used
   // in cases like the verifier where the checks cannot fail and initCause isn't overridden.
-  void SetCause(Throwable* cause);
+  void SetCause(Throwable* cause) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   bool IsCheckedException() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static Class* GetJavaLangThrowable() {