diff options
Diffstat (limited to 'runtime/mirror/class-inl.h')
-rw-r--r-- | runtime/mirror/class-inl.h | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 78f6b25649..eb54f7fb1f 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -31,6 +31,7 @@ #include "gc/heap-inl.h" #include "iftable.h" #include "invoke_type.h" +#include "subtype_check.h" #include "object-inl.h" #include "object_array.h" #include "read_barrier-inl.h" @@ -56,7 +57,6 @@ inline uint32_t Class::GetObjectSizeAllocFastPath() { return GetField32(ObjectSizeAllocFastPathOffset()); } - template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> inline Class* Class::GetSuperClass() { // Can only get super class for loaded classes (hack for when runtime is @@ -532,16 +532,46 @@ inline bool Class::CheckResolvedMethodAccess(ObjPtr<Class> access_to, } inline bool Class::IsSubClass(ObjPtr<Class> klass) { + // Since the SubtypeCheck::IsSubtypeOf needs to lookup the Depth, + // it is always O(Depth) in terms of speed to do the check. + // + // So always do the "slow" linear scan in normal release builds. + // + // Future note: If we could have the depth in O(1) we could use the 'fast' + // method instead as it avoids a loop and a read barrier. + bool result = false; DCHECK(!IsInterface()) << PrettyClass(); DCHECK(!IsArrayClass()) << PrettyClass(); ObjPtr<Class> current = this; do { if (current == klass) { - return true; + result = true; + break; } current = current->GetSuperClass(); } while (current != nullptr); - return false; + + if (kIsDebugBuild) { + ObjPtr<mirror::Class> dis(this); + + SubtypeCheckInfo::Result sc_result = SubtypeCheck<ObjPtr<Class>>::IsSubtypeOf(dis, klass); + if (sc_result != SubtypeCheckInfo::kUnknownSubtypeOf) { + // Note: The "kUnknownSubTypeOf" can be avoided if and only if: + // SubtypeCheck::EnsureInitialized(source) + // happens-before source.IsSubClass(target) + // SubtypeCheck::EnsureAssigned(target).GetState() == Assigned + // happens-before source.IsSubClass(target) + // + // When code generated by optimizing compiler executes this operation, both + // happens-before are guaranteed, so there is no fallback code there. + SubtypeCheckInfo::Result expected_result = + result ? SubtypeCheckInfo::kSubtypeOf : SubtypeCheckInfo::kNotSubtypeOf; + DCHECK_EQ(expected_result, sc_result) + << "source: " << PrettyClass() << "target: " << klass->PrettyClass(); + } + } + + return result; } inline ArtMethod* Class::FindVirtualMethodForInterface(ArtMethod* method, |