Fix and optimize verify object.
VerifyObject no longer resides in heap. You can now enable
VerifyObject for non-debug builds. VerifyStack is still slow, so it
is now guarded by its own flag.
Fixed the image writer to not use verification at places where
verification fails due to invalid reads.
Fixed RosAlloc to use SizeOf which doesn't call verify object.
Added a flag paremeter to some of the mirror getters / setters to
be able to selectively disable VerifyObject on certain calls.
Optimized the GC to not verify each object multiple times during
object scanning if verify object is enabled.
Added 3 verification options: verify reads, verify this, and verify
writes so that you can select how much verification you want for
mirror getters and setters.
Removed some useless DCHECKs which would slow debug builds without
providing any benefits.
TODO: RosAlloc verification doesn't currently work with verify
objects.
Bug: 12934910
Bug: 12879358
Change-Id: Ic61033104dfc334543f89b0fc0ad8cd4f4015d69
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 7c5de5e..90aaccd 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -27,10 +27,13 @@
namespace art {
namespace mirror {
+template<VerifyObjectFlags kVerifyFlags>
inline size_t Array::SizeOf() {
// This is safe from overflow because the array was already allocated, so we know it's sane.
- size_t component_size = GetClass()->GetComponentSize();
- int32_t component_count = GetLength();
+ size_t component_size = GetClass<kVerifyFlags>()->GetComponentSize();
+ // Don't need to check this since we already check this in GetClass.
+ int32_t component_count =
+ GetLength<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>();
size_t header_size = sizeof(Object) + (component_size == sizeof(int64_t) ? 8 : 4);
size_t data_size = component_count * component_size;
return header_size + data_size;
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 7555975..c4f9a75 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -53,17 +53,18 @@
const SirtRef<IntArray>& dimensions)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
int32_t GetLength() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), false);
+ return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Array, length_), false);
}
void SetLength(int32_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CHECK_GE(length, 0);
// We use non transactional version since we can't undo this write. We also disable checking
// since it would fail during a transaction.
- SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false, false);
+ SetField32<false, false, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false);
}
static MemberOffset LengthOffset() {
@@ -94,8 +95,10 @@
// Returns true if the index is valid. If not, throws an ArrayIndexOutOfBoundsException and
// returns false.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool CheckIsValidIndex(int32_t index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (UNLIKELY(static_cast<uint32_t>(index) >= static_cast<uint32_t>(GetLength()))) {
+ if (UNLIKELY(static_cast<uint32_t>(index) >=
+ static_cast<uint32_t>(GetLength<kVerifyFlags>()))) {
ThrowArrayIndexOutOfBoundsException(index);
return false;
}
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index d347724..d5eccaf 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -215,6 +215,13 @@
DCHECK(!result || IsRuntimeMethod());
return result;
}
+
+template<VerifyObjectFlags kVerifyFlags>
+inline void ArtMethod::SetNativeMethod(const void* native_method) {
+ SetFieldPtr<false, true, kVerifyFlags>(
+ OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_), native_method, false);
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 20d2b18..fe27992 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -360,10 +360,5 @@
RegisterNative(self, GetJniDlsymLookupStub(), false);
}
-void ArtMethod::SetNativeMethod(const void* native_method) {
- SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_),
- native_method, false);
-}
-
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 86f5348..e17dc5f 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -214,40 +214,48 @@
void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result,
const char* shorty) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
EntryPointFromInterpreter* GetEntryPointFromInterpreter() {
- return GetFieldPtr<EntryPointFromInterpreter*>(
+ return GetFieldPtr<EntryPointFromInterpreter*, kVerifyFlags>(
OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_), false);
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetEntryPointFromInterpreter(EntryPointFromInterpreter* entry_point_from_interpreter) {
- SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_),
- entry_point_from_interpreter, false);
+ SetFieldPtr<false, true, kVerifyFlags>(
+ OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_interpreter_),
+ entry_point_from_interpreter, false);
}
static MemberOffset EntryPointFromPortableCompiledCodeOffset() {
return MemberOffset(OFFSETOF_MEMBER(ArtMethod, entry_point_from_portable_compiled_code_));
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
const void* GetEntryPointFromPortableCompiledCode() {
- return GetFieldPtr<const void*>(EntryPointFromPortableCompiledCodeOffset(), false);
+ return GetFieldPtr<const void*, kVerifyFlags>(
+ EntryPointFromPortableCompiledCodeOffset(), false);
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetEntryPointFromPortableCompiledCode(const void* entry_point_from_portable_compiled_code) {
- SetFieldPtr<false>(EntryPointFromPortableCompiledCodeOffset(),
- entry_point_from_portable_compiled_code, false);
+ SetFieldPtr<false, true, kVerifyFlags>(
+ EntryPointFromPortableCompiledCodeOffset(), entry_point_from_portable_compiled_code, false);
}
static MemberOffset EntryPointFromQuickCompiledCodeOffset() {
return MemberOffset(OFFSETOF_MEMBER(ArtMethod, entry_point_from_quick_compiled_code_));
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
const void* GetEntryPointFromQuickCompiledCode() {
- return GetFieldPtr<const void*>(EntryPointFromQuickCompiledCodeOffset(), false);
+ return GetFieldPtr<const void*, kVerifyFlags>(EntryPointFromQuickCompiledCodeOffset(), false);
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetEntryPointFromQuickCompiledCode(const void* entry_point_from_quick_compiled_code) {
- SetFieldPtr<false>(EntryPointFromQuickCompiledCodeOffset(),
- entry_point_from_quick_compiled_code, false);
+ SetFieldPtr<false, true, kVerifyFlags>(
+ EntryPointFromQuickCompiledCodeOffset(), entry_point_from_quick_compiled_code, false);
}
@@ -279,9 +287,10 @@
false);
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetMappingTable(const uint8_t* mapping_table) {
- SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_),
- mapping_table, false);
+ SetFieldPtr<false, true, kVerifyFlags>(
+ OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_), mapping_table, false);
}
uint32_t GetOatMappingTableOffset();
@@ -294,8 +303,10 @@
false);
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetVmapTable(const uint8_t* vmap_table) {
- SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_), vmap_table, false);
+ SetFieldPtr<false, true, kVerifyFlags>(
+ OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_), vmap_table, false);
}
uint32_t GetOatVmapTableOffset();
@@ -305,8 +316,10 @@
const uint8_t* GetNativeGcMap() {
return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, gc_map_), false);
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetNativeGcMap(const uint8_t* data) {
- SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, gc_map_), data, false);
+ SetFieldPtr<false, true, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, gc_map_), data,
+ false);
}
// When building the oat need a convenient place to stuff the offset of the native GC map.
@@ -350,6 +363,7 @@
return reinterpret_cast<const void*>(GetField32(NativeMethodOffset(), false));
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetNativeMethod(const void*);
static MemberOffset GetMethodIndexOffset() {
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index cba221d..e82c393 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -85,6 +85,7 @@
return (GetDirectMethods() != NULL) ? GetDirectMethods()->GetLength() : 0;
}
+template<VerifyObjectFlags kVerifyFlags>
inline ObjectArray<ArtMethod>* Class::GetVirtualMethods() {
DCHECK(IsLoaded() || IsErroneous());
return GetFieldObject<ObjectArray<ArtMethod> >(
@@ -103,8 +104,9 @@
return (GetVirtualMethods() != NULL) ? GetVirtualMethods()->GetLength() : 0;
}
+template<VerifyObjectFlags kVerifyFlags>
inline ArtMethod* Class::GetVirtualMethod(uint32_t i) {
- DCHECK(IsResolved() || IsErroneous());
+ DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>());
return GetVirtualMethods()->Get(i);
}
@@ -415,14 +417,16 @@
}
}
+template<VerifyObjectFlags kVerifyFlags>
inline uint32_t Class::GetAccessFlags() {
// Check class is loaded or this is java.lang.String that has a
// circularity issue during loading the names of its members
- DCHECK(IsLoaded() || IsErroneous() ||
+ DCHECK(IsLoaded<kVerifyFlags>() ||
+ IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ||
this == String::GetJavaLangString() ||
this == ArtField::GetJavaLangReflectArtField() ||
this == ArtMethod::GetJavaLangReflectArtMethod());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
+ return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
}
inline String* Class::GetName() {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index cd8504b..43db996 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -120,9 +120,11 @@
kStatusMax = 10,
};
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Status GetStatus() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK_EQ(sizeof(Status), sizeof(uint32_t));
- return static_cast<Status>(GetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), true));
+ COMPILE_ASSERT(sizeof(Status) == sizeof(uint32_t), size_of_status_not_uint32);
+ return static_cast<Status>(GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, status_),
+ true));
}
void SetStatus(Status new_status, Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -132,45 +134,54 @@
}
// Returns true if the class has failed to link.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsErroneous() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetStatus() == kStatusError;
+ return GetStatus<kVerifyFlags>() == kStatusError;
}
// Returns true if the class has been loaded.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsIdxLoaded() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetStatus() >= kStatusIdx;
+ return GetStatus<kVerifyFlags>() >= kStatusIdx;
}
// Returns true if the class has been loaded.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsLoaded() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetStatus() >= kStatusLoaded;
+ return GetStatus<kVerifyFlags>() >= kStatusLoaded;
}
// Returns true if the class has been linked.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsResolved() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetStatus() >= kStatusResolved;
+ return GetStatus<kVerifyFlags>() >= kStatusResolved;
}
// Returns true if the class was compile-time verified.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsCompileTimeVerified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetStatus() >= kStatusRetryVerificationAtRuntime;
+ return GetStatus<kVerifyFlags>() >= kStatusRetryVerificationAtRuntime;
}
// Returns true if the class has been verified.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsVerified() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetStatus() >= kStatusVerified;
+ return GetStatus<kVerifyFlags>() >= kStatusVerified;
}
// Returns true if the class is initializing.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsInitializing() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetStatus() >= kStatusInitializing;
+ return GetStatus<kVerifyFlags>() >= kStatusInitializing;
}
// Returns true if the class is initialized.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsInitialized() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetStatus() == kStatusInitialized;
+ return GetStatus<kVerifyFlags>() == kStatusInitialized;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
uint32_t GetAccessFlags() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetAccessFlags(uint32_t new_access_flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -217,24 +228,29 @@
return (GetAccessFlags() & kAccSynthetic) != 0;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return (GetAccessFlags() & kAccClassIsReference) != 0;
+ return (GetAccessFlags<kVerifyFlags>() & kAccClassIsReference) != 0;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsWeakReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return (GetAccessFlags() & kAccClassIsWeakReference) != 0;
+ return (GetAccessFlags<kVerifyFlags>() & kAccClassIsWeakReference) != 0;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsSoftReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return (GetAccessFlags() & kAccReferenceFlagsMask) == kAccClassIsReference;
+ return (GetAccessFlags<kVerifyFlags>() & kAccReferenceFlagsMask) == kAccClassIsReference;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsFinalizerReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return (GetAccessFlags() & kAccClassIsFinalizerReference) != 0;
+ return (GetAccessFlags<kVerifyFlags>() & kAccClassIsFinalizerReference) != 0;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPhantomReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return (GetAccessFlags() & kAccClassIsPhantomReference) != 0;
+ return (GetAccessFlags<kVerifyFlags>() & kAccClassIsPhantomReference) != 0;
}
// Can references of this type be assigned to by things of another type? For non-array types
@@ -260,7 +276,7 @@
// Computes the name, then sets the cached value.
String* ComputeName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsProxyClass() {
+ bool IsProxyClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Read access flags without using getter as whether something is a proxy can be check in
// any loaded state
// TODO: switch to a check if the super class is java.lang.reflect.Proxy?
@@ -268,10 +284,11 @@
return (access_flags & kAccClassIsProxy) != 0;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Primitive::Type GetPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
return static_cast<Primitive::Type>(
- GetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), false));
+ GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), false));
}
void SetPrimitiveType(Primitive::Type new_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -280,48 +297,61 @@
}
// Returns true if the class is a primitive type.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPrimitive() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetPrimitiveType() != Primitive::kPrimNot;
+ return GetPrimitiveType<kVerifyFlags>() != Primitive::kPrimNot;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPrimitiveBoolean() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetPrimitiveType() == Primitive::kPrimBoolean;
+ return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimBoolean;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPrimitiveByte() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetPrimitiveType() == Primitive::kPrimByte;
+ return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimByte;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPrimitiveChar() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetPrimitiveType() == Primitive::kPrimChar;
+ return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimChar;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPrimitiveShort() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetPrimitiveType() == Primitive::kPrimShort;
+ return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimShort;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPrimitiveInt() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetPrimitiveType() == Primitive::kPrimInt;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPrimitiveLong() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetPrimitiveType() == Primitive::kPrimLong;
+ return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimLong;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPrimitiveFloat() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetPrimitiveType() == Primitive::kPrimFloat;
+ return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimFloat;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPrimitiveDouble() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetPrimitiveType() == Primitive::kPrimDouble;
+ return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimDouble;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPrimitiveVoid() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetPrimitiveType() == Primitive::kPrimVoid;
+ return GetPrimitiveType<kVerifyFlags>() == Primitive::kPrimVoid;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPrimitiveArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return IsArrayClass() && GetComponentType()->IsPrimitive();
+ return IsArrayClass<kVerifyFlags>() &&
+ GetComponentType<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>()->
+ IsPrimitive();
}
// Depth of class from java.lang.Object
@@ -333,8 +363,9 @@
return depth;
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetComponentType() != NULL;
+ return GetComponentType<kVerifyFlags>() != NULL;
}
bool IsClassClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -351,8 +382,9 @@
return OFFSET_OF_OBJECT_MEMBER(Class, component_type_);
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Class* GetComponentType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetFieldObject<Class>(ComponentTypeOffset(), false);
+ return GetFieldObject<Class, kVerifyFlags>(ComponentTypeOffset(), false);
}
void SetComponentType(Class* new_component_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -376,8 +408,9 @@
return (!IsPrimitive() && !IsInterface() && !IsAbstract()) || ((IsAbstract()) && IsArrayClass());
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsObjectArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetComponentType() != NULL && !GetComponentType()->IsPrimitive();
+ return GetComponentType<kVerifyFlags>() != nullptr && !GetComponentType<kVerifyFlags>()->IsPrimitive();
}
// Creates a raw object instance but does not invoke the default constructor.
@@ -396,12 +429,14 @@
return IsClassClass() || IsArrayClass();
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
uint32_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
+ return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
uint32_t GetClassSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
+ return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
}
void SetClassSize(uint32_t new_class_size)
@@ -549,6 +584,7 @@
// Returns the number of static, private, and constructor methods.
uint32_t NumDirectMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ObjectArray<ArtMethod>* GetVirtualMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetVirtualMethods(ObjectArray<ArtMethod>* new_virtual_methods)
@@ -557,6 +593,7 @@
// Returns the number of non-inherited virtual methods.
uint32_t NumVirtualMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ArtMethod* GetVirtualMethod(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
ArtMethod* GetVirtualMethodDuringLinking(uint32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -683,9 +720,11 @@
false);
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
uint32_t GetReferenceInstanceOffsets() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(IsResolved() || IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), false);
+ DCHECK(IsResolved<kVerifyFlags>() || IsErroneous<kVerifyFlags>());
+ return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_),
+ false);
}
void SetReferenceInstanceOffsets(uint32_t new_reference_offsets)
@@ -725,8 +764,10 @@
// TODO: uint16_t
void SetStaticField(uint32_t i, ArtField* f) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
uint32_t GetReferenceStaticOffsets() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_), false);
+ return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_),
+ false);
}
void SetReferenceStaticOffsets(uint32_t new_reference_offsets)
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 70291c1..df8104d 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -32,18 +32,21 @@
namespace art {
namespace mirror {
+template<VerifyObjectFlags kVerifyFlags>
inline Class* Object::GetClass() {
- return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
+ return GetFieldObject<Class, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
}
+template<VerifyObjectFlags kVerifyFlags>
inline void Object::SetClass(Class* new_klass) {
// new_klass may be NULL prior to class linker initialization.
// We don't mark the card as this occurs as part of object allocation. Not all objects have
// backing cards, such as large objects.
// We use non transactional version since we can't undo this write. We also disable checking as
// we may run in transaction mode here.
- SetFieldObjectWithoutWriteBarrier<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, klass_),
- new_klass, false, false);
+ SetFieldObjectWithoutWriteBarrier<false, false,
+ static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(
+ OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false);
}
inline LockWord Object::GetLockWord() {
@@ -89,176 +92,222 @@
Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
}
+template<VerifyObjectFlags kVerifyFlags>
inline bool Object::VerifierInstanceOf(Class* klass) {
DCHECK(klass != NULL);
- DCHECK(GetClass() != NULL);
+ DCHECK(GetClass<kVerifyFlags>() != NULL);
return klass->IsInterface() || InstanceOf(klass);
}
+template<VerifyObjectFlags kVerifyFlags>
inline bool Object::InstanceOf(Class* klass) {
DCHECK(klass != NULL);
- DCHECK(GetClass() != NULL);
- return klass->IsAssignableFrom(GetClass());
+ DCHECK(GetClass<kVerifyNone>() != NULL);
+ return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
}
+template<VerifyObjectFlags kVerifyFlags>
inline bool Object::IsClass() {
- Class* java_lang_Class = GetClass()->GetClass();
- return GetClass() == java_lang_Class;
+ Class* java_lang_Class = GetClass<kVerifyFlags>()->GetClass();
+ return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ==
+ java_lang_Class;
}
+template<VerifyObjectFlags kVerifyFlags>
inline Class* Object::AsClass() {
- DCHECK(IsClass());
+ DCHECK(IsClass<kVerifyFlags>());
return down_cast<Class*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline bool Object::IsObjectArray() {
- return IsArrayInstance() && !GetClass()->GetComponentType()->IsPrimitive();
+ constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+ return IsArrayInstance<kVerifyFlags>() &&
+ !GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitive();
}
-template<class T>
+template<class T, VerifyObjectFlags kVerifyFlags>
inline ObjectArray<T>* Object::AsObjectArray() {
- DCHECK(IsObjectArray());
+ DCHECK(IsObjectArray<kVerifyFlags>());
return down_cast<ObjectArray<T>*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline bool Object::IsArrayInstance() {
- return GetClass()->IsArrayClass();
+ return GetClass<kVerifyFlags>()->IsArrayClass();
}
+template<VerifyObjectFlags kVerifyFlags>
inline bool Object::IsArtField() {
- return GetClass()->IsArtFieldClass();
+ return GetClass<kVerifyFlags>()->IsArtFieldClass();
}
-inline ArtField* Object::AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(IsArtField());
+template<VerifyObjectFlags kVerifyFlags>
+inline ArtField* Object::AsArtField() {
+ DCHECK(IsArtField<kVerifyFlags>());
return down_cast<ArtField*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline bool Object::IsArtMethod() {
- return GetClass()->IsArtMethodClass();
+ return GetClass<kVerifyFlags>()->IsArtMethodClass();
}
+template<VerifyObjectFlags kVerifyFlags>
inline ArtMethod* Object::AsArtMethod() {
- DCHECK(IsArtMethod());
+ DCHECK(IsArtMethod<kVerifyFlags>());
return down_cast<ArtMethod*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline bool Object::IsReferenceInstance() {
- return GetClass()->IsReferenceClass();
+ return GetClass<kVerifyFlags>()->IsReferenceClass();
}
+template<VerifyObjectFlags kVerifyFlags>
inline Array* Object::AsArray() {
- DCHECK(IsArrayInstance());
+ DCHECK(IsArrayInstance<kVerifyFlags>());
return down_cast<Array*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline BooleanArray* Object::AsBooleanArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveBoolean());
+ constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+ DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+ DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean());
return down_cast<BooleanArray*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline ByteArray* Object::AsByteArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte());
+ static const VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+ DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+ DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte());
return down_cast<ByteArray*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline ByteArray* Object::AsByteSizedArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte() ||
- GetClass()->GetComponentType()->IsPrimitiveBoolean());
+ constexpr VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+ DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+ DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() ||
+ GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean());
return down_cast<ByteArray*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline CharArray* Object::AsCharArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveChar());
+ constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+ DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+ DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
return down_cast<CharArray*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline ShortArray* Object::AsShortArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort());
+ constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+ DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+ DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort());
return down_cast<ShortArray*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline ShortArray* Object::AsShortSizedArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort() ||
- GetClass()->GetComponentType()->IsPrimitiveChar());
+ constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+ DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+ DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() ||
+ GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
return down_cast<ShortArray*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline IntArray* Object::AsIntArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveInt() ||
- GetClass()->GetComponentType()->IsPrimitiveFloat());
+ constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+ DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+ DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() ||
+ GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
return down_cast<IntArray*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline LongArray* Object::AsLongArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveLong() ||
- GetClass()->GetComponentType()->IsPrimitiveDouble());
+ constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+ DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+ DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() ||
+ GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
return down_cast<LongArray*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline FloatArray* Object::AsFloatArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveFloat());
+ constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+ DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+ DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
return down_cast<FloatArray*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline DoubleArray* Object::AsDoubleArray() {
- DCHECK(GetClass()->IsArrayClass());
- DCHECK(GetClass()->GetComponentType()->IsPrimitiveDouble());
+ constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+ DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
+ DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
return down_cast<DoubleArray*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline String* Object::AsString() {
- DCHECK(GetClass()->IsStringClass());
+ DCHECK(GetClass<kVerifyFlags>()->IsStringClass());
return down_cast<String*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline Throwable* Object::AsThrowable() {
- DCHECK(GetClass()->IsThrowableClass());
+ DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
return down_cast<Throwable*>(this);
}
+template<VerifyObjectFlags kVerifyFlags>
inline bool Object::IsWeakReferenceInstance() {
- return GetClass()->IsWeakReferenceClass();
+ return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
}
+template<VerifyObjectFlags kVerifyFlags>
inline bool Object::IsSoftReferenceInstance() {
- return GetClass()->IsSoftReferenceClass();
+ return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
}
+template<VerifyObjectFlags kVerifyFlags>
inline bool Object::IsFinalizerReferenceInstance() {
- return GetClass()->IsFinalizerReferenceClass();
+ return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
}
+template<VerifyObjectFlags kVerifyFlags>
inline bool Object::IsPhantomReferenceInstance() {
- return GetClass()->IsPhantomReferenceClass();
+ return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
}
+template<VerifyObjectFlags kVerifyFlags>
inline size_t Object::SizeOf() {
size_t result;
- if (IsArrayInstance()) {
- result = AsArray()->SizeOf();
- } else if (IsClass()) {
- result = AsClass()->SizeOf();
+ constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
+ if (IsArrayInstance<kVerifyFlags>()) {
+ result = AsArray<kNewFlags>()->SizeOf<>();
+ } else if (IsClass<kNewFlags>()) {
+ result = AsClass<kNewFlags>()->SizeOf<kNewFlags>();
} else {
- result = GetClass()->GetObjectSize();
+ result = GetClass<kNewFlags>()->GetObjectSize();
}
- DCHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(GetClass());
- DCHECK(!IsArtField() || result == sizeof(ArtField));
- DCHECK(!IsArtMethod() || result == sizeof(ArtMethod));
+ DCHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(GetClass<kNewFlags>());
+ DCHECK(!IsArtField<kNewFlags>() || result == sizeof(ArtField));
+ DCHECK(!IsArtMethod<kNewFlags>() || result == sizeof(ArtMethod));
return result;
}
+template<VerifyObjectFlags kVerifyFlags>
inline int32_t Object::GetField32(MemberOffset field_offset, bool is_volatile) {
- VerifyObject(this);
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
@@ -270,9 +319,8 @@
}
}
-template<bool kTransactionActive, bool kCheckTransaction>
-inline void Object::SetField32(MemberOffset field_offset, int32_t new_value, bool is_volatile,
- bool this_is_valid) {
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline void Object::SetField32(MemberOffset field_offset, int32_t new_value, bool is_volatile) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
@@ -280,7 +328,7 @@
Runtime::Current()->RecordWriteField32(this, field_offset, GetField32(field_offset, is_volatile),
is_volatile);
}
- if (this_is_valid) {
+ if (kVerifyFlags & kVerifyThis) {
VerifyObject(this);
}
byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
@@ -294,7 +342,7 @@
}
}
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline bool Object::CasField32(MemberOffset field_offset, int32_t old_value, int32_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
@@ -302,14 +350,19 @@
if (kTransactionActive) {
Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
}
- VerifyObject(this);
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr);
return __sync_bool_compare_and_swap(addr, old_value, new_value);
}
+template<VerifyObjectFlags kVerifyFlags>
inline int64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) {
- VerifyObject(this);
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
@@ -321,9 +374,8 @@
}
}
-template<bool kTransactionActive, bool kCheckTransaction>
-inline void Object::SetField64(MemberOffset field_offset, int64_t new_value, bool is_volatile,
- bool this_is_valid) {
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline void Object::SetField64(MemberOffset field_offset, int64_t new_value, bool is_volatile) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
@@ -331,7 +383,7 @@
Runtime::Current()->RecordWriteField64(this, field_offset, GetField64(field_offset, is_volatile),
is_volatile);
}
- if (this_is_valid) {
+ if (kVerifyFlags & kVerifyThis) {
VerifyObject(this);
}
byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
@@ -349,7 +401,7 @@
}
}
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline bool Object::CasField64(MemberOffset field_offset, int64_t old_value, int64_t new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
@@ -357,15 +409,19 @@
if (kTransactionActive) {
Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
}
- VerifyObject(this);
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
volatile int64_t* addr = reinterpret_cast<volatile int64_t*>(raw_addr);
return QuasiAtomic::Cas64(old_value, new_value, addr);
}
-template<class T>
+template<class T, VerifyObjectFlags kVerifyFlags>
inline T* Object::GetFieldObject(MemberOffset field_offset, bool is_volatile) {
- VerifyObject(this);
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
HeapReference<T> objref = *objref_addr;
@@ -374,13 +430,15 @@
QuasiAtomic::MembarLoadLoad(); // Ensure loads don't re-order.
}
T* result = objref.AsMirrorPtr();
- VerifyObject(result);
+ if (kVerifyFlags & kVerifyReads) {
+ VerifyObject(result);
+ }
return result;
}
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, Object* new_value,
- bool is_volatile, bool this_is_valid) {
+ bool is_volatile) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
@@ -389,10 +447,12 @@
GetFieldObject<Object>(field_offset, is_volatile),
true);
}
- if (this_is_valid) {
+ if (kVerifyFlags & kVerifyThis) {
VerifyObject(this);
}
- VerifyObject(new_value);
+ if (kVerifyFlags & kVerifyWrites) {
+ VerifyObject(new_value);
+ }
HeapReference<Object> objref(HeapReference<Object>::FromMirrorPtr(new_value));
byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
@@ -405,27 +465,43 @@
}
}
-template<bool kTransactionActive, bool kCheckTransaction>
-inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile,
- bool this_is_valid) {
- SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction>(field_offset, new_value,
- is_volatile,
- this_is_valid);
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile) {
+ SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags>(
+ field_offset, new_value, is_volatile);
if (new_value != nullptr) {
CheckFieldAssignment(field_offset, new_value);
Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
}
}
-template<bool kTransactionActive, bool kCheckTransaction>
-inline bool Object::CasFieldObject(MemberOffset field_offset, Object* old_value, Object* new_value) {
+template <VerifyObjectFlags kVerifyFlags>
+inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<byte*>(this) +
+ field_offset.Int32Value());
+}
+
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
+inline bool Object::CasFieldObject(MemberOffset field_offset, Object* old_value,
+ Object* new_value) {
if (kCheckTransaction) {
DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
}
+ if (kVerifyFlags & kVerifyThis) {
+ VerifyObject(this);
+ }
+ if (kVerifyFlags & kVerifyWrites) {
+ VerifyObject(new_value);
+ }
+ if (kVerifyFlags & kVerifyReads) {
+ VerifyObject(old_value);
+ }
if (kTransactionActive) {
Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
}
- VerifyObject(this);
byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr);
HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
@@ -437,12 +513,6 @@
return success;
}
-inline void Object::VerifyObject(Object* obj) {
- if (kIsDebugBuild) {
- Runtime::Current()->GetHeap()->VerifyObject(obj);
- }
-}
-
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 1251852..f1485e5 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -141,10 +141,9 @@
void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_value) {
Class* c = GetClass();
- if (Runtime::Current()->GetClassLinker() == NULL ||
- !Runtime::Current()->IsStarted() ||
- !Runtime::Current()->GetHeap()->IsObjectValidationEnabled() ||
- !c->IsResolved()) {
+ Runtime* runtime = Runtime::Current();
+ if (runtime->GetClassLinker() == nullptr || !runtime->IsStarted() ||
+ !runtime->GetHeap()->IsObjectValidationEnabled() || !c->IsResolved()) {
return;
}
for (Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) {
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index eb118c7..7487dd2 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -24,6 +24,7 @@
#include "object_reference.h"
#include "offsets.h"
#include "runtime.h"
+#include "verify_object.h"
namespace art {
@@ -59,7 +60,8 @@
#define OFFSET_OF_OBJECT_MEMBER(type, field) \
MemberOffset(OFFSETOF_MEMBER(type, field))
-constexpr bool kCheckFieldAssignments = false;
+// Checks that we don't do field assignments which violate the typing system.
+static constexpr bool kCheckFieldAssignments = false;
// C++ mirror of java.lang.Object
class MANAGED Object {
@@ -68,16 +70,20 @@
return OFFSET_OF_OBJECT_MEMBER(Object, klass_);
}
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Class* GetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetClass(Class* new_klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// The verifier treats all interfaces as java.lang.Object and relies on runtime checks in
// invoke-interface to detect incompatible interface types.
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool VerifierInstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool InstanceOf(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
size_t SizeOf() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -95,135 +101,147 @@
mirror::Object* MonitorEnter(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCK_FUNCTION(monitor_lock_);
-
bool MonitorExit(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
UNLOCK_FUNCTION(monitor_lock_);
-
void Notify(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
void NotifyAll(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
void Wait(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
void Wait(Thread* self, int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Class* AsClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsObjectArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- template<class T>
+ template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ObjectArray<T>* AsObjectArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsArrayInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Array* AsArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
BooleanArray* AsBooleanArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ByteArray* AsByteArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ByteArray* AsByteSizedArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
CharArray* AsCharArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ShortArray* AsShortArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ShortArray* AsShortSizedArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
IntArray* AsIntArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
LongArray* AsLongArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
FloatArray* AsFloatArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
DoubleArray* AsDoubleArray() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
String* AsString() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
Throwable* AsThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ArtMethod* AsArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ArtField* AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsWeakReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsSoftReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsFinalizerReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsPhantomReferenceInstance() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Accessor for Java type fields.
- template<class T> T* GetFieldObject(MemberOffset field_offset, bool is_volatile)
+ template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ T* GetFieldObject(MemberOffset field_offset, bool is_volatile)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true>
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, Object* new_value,
- bool is_volatile, bool this_is_valid = true)
+ bool is_volatile)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true>
- void SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile,
- bool this_is_valid = true)
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ void SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true>
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool CasFieldObject(MemberOffset field_offset, Object* old_value, Object* new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- HeapReference<Object>* GetFieldObjectReferenceAddr(MemberOffset field_offset) ALWAYS_INLINE {
- VerifyObject(this);
- return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<byte*>(this) +
- field_offset.Int32Value());
- }
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ HeapReference<Object>* GetFieldObjectReferenceAddr(MemberOffset field_offset);
- int32_t GetField32(MemberOffset field_offset, bool is_volatile);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ int32_t GetField32(MemberOffset field_offset, bool is_volatile)
+ NO_THREAD_SAFETY_ANALYSIS;
- template<bool kTransactionActive, bool kCheckTransaction = true>
- void SetField32(MemberOffset field_offset, int32_t new_value, bool is_volatile,
- bool this_is_valid = true);
-
- template<bool kTransactionActive, bool kCheckTransaction = true>
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ void SetField32(MemberOffset field_offset, int32_t new_value, bool is_volatile);
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool CasField32(MemberOffset field_offset, int32_t old_value, int32_t new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
int64_t GetField64(MemberOffset field_offset, bool is_volatile);
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ void SetField64(MemberOffset field_offset, int64_t new_value, bool is_volatile);
- template<bool kTransactionActive, bool kCheckTransaction = true>
- void SetField64(MemberOffset field_offset, int64_t new_value, bool is_volatile,
- bool this_is_valid = true);
-
- template<bool kTransactionActive, bool kCheckTransaction = true>
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool CasField64(MemberOffset field_offset, int64_t old_value, int64_t new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- template<bool kTransactionActive, bool kCheckTransaction = true, typename T>
- void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile,
- bool this_is_valid = true) {
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, typename T>
+ void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile) {
#ifndef __LP64__
- SetField32<kTransactionActive, kCheckTransaction>(field_offset,
- reinterpret_cast<int32_t>(new_value),
- is_volatile, this_is_valid);
+ SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags>(
+ field_offset, reinterpret_cast<int32_t>(new_value), is_volatile);
#else
- SetField64<kTransactionActive, kCheckTransaction>(field_offset,
- reinterpret_cast<int64_t>(new_value),
- is_volatile, this_is_valid);
+ SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags>(
+ field_offset, reinterpret_cast<int64_t>(new_value), is_volatile);
#endif
}
protected:
// Accessors for non-Java type fields
- template<class T>
- T GetFieldPtr(MemberOffset field_offset, bool is_volatile) {
+ template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ T GetFieldPtr(MemberOffset field_offset, bool is_volatile) NO_THREAD_SAFETY_ANALYSIS {
#ifndef __LP64__
- return reinterpret_cast<T>(GetField32(field_offset, is_volatile));
+ return reinterpret_cast<T>(GetField32<kVerifyFlags>(field_offset, is_volatile));
#else
- return reinterpret_cast<T>(GetField64(field_offset, is_volatile));
+ return reinterpret_cast<T>(GetField64<kVerifyFlags>(field_offset, is_volatile));
#endif
}
private:
- static void VerifyObject(Object* obj) ALWAYS_INLINE;
// Verify the type correctness of stores to fields.
void CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_value)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 521b6ce..a427957 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -58,10 +58,10 @@
return GetFieldObject<T>(OffsetOfElement(i), false);
}
-template<class T>
+template<class T> template<VerifyObjectFlags kVerifyFlags>
inline bool ObjectArray<T>::CheckAssignable(T* object) {
if (object != NULL) {
- Class* element_class = GetClass()->GetComponentType();
+ Class* element_class = GetClass<kVerifyFlags>()->GetComponentType();
if (UNLIKELY(!object->InstanceOf(element_class))) {
ThrowArrayStoreException(object);
return false;
@@ -80,31 +80,33 @@
}
template<class T>
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline void ObjectArray<T>::Set(int32_t i, T* object) {
- if (LIKELY(CheckIsValidIndex(i) && CheckAssignable(object))) {
- SetFieldObject<kTransactionActive, kCheckTransaction>(OffsetOfElement(i), object, false);
+ if (LIKELY(CheckIsValidIndex(i) && CheckAssignable<kVerifyFlags>(object))) {
+ SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object,
+ false);
} else {
DCHECK(Thread::Current()->IsExceptionPending());
}
}
template<class T>
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline void ObjectArray<T>::SetWithoutChecks(int32_t i, T* object) {
- DCHECK(CheckIsValidIndex(i));
- DCHECK(CheckAssignable(object));
- SetFieldObject<kTransactionActive, kCheckTransaction>(OffsetOfElement(i), object, false);
+ DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
+ DCHECK(CheckAssignable<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(object));
+ SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object,
+ false);
}
template<class T>
-template<bool kTransactionActive, bool kCheckTransaction>
+template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
inline void ObjectArray<T>::SetWithoutChecksAndWriteBarrier(int32_t i, T* object) {
- DCHECK(CheckIsValidIndex(i));
+ DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
// TODO: enable this check. It fails when writing the image in ImageWriter::FixupObjectArray.
// DCHECK(CheckAssignable(object));
- SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction>(OffsetOfElement(i),
- object, false);
+ SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags>(
+ OffsetOfElement(i), object, false);
}
template<class T>
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index 668b276..7f9e716 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -37,22 +37,27 @@
// Returns true if the object can be stored into the array. If not, throws
// an ArrayStoreException and returns false.
- bool CheckAssignable(T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // TODO fix thread safety analysis: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ bool CheckAssignable(T* object) NO_THREAD_SAFETY_ANALYSIS;
void Set(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// TODO fix thread safety analysis: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
- template<bool kTransactionActive, bool kCheckTransaction = true>
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void Set(int32_t i, T* object) NO_THREAD_SAFETY_ANALYSIS;
// Set element without bound and element type checks, to be used in limited
// circumstances, such as during boot image writing.
// TODO fix thread safety analysis broken by the use of template. This should be
// SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
- template<bool kTransactionActive, bool kCheckTransaction = true>
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetWithoutChecks(int32_t i, T* object) NO_THREAD_SAFETY_ANALYSIS;
// TODO fix thread safety analysis broken by the use of template. This should be
// SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
- template<bool kTransactionActive, bool kCheckTransaction = true>
+ template<bool kTransactionActive, bool kCheckTransaction = true,
+ VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
void SetWithoutChecksAndWriteBarrier(int32_t i, T* object) NO_THREAD_SAFETY_ANALYSIS;
T* GetWithoutChecks(int32_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);