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() {