summaryrefslogtreecommitdiff
path: root/runtime/mirror/class-inl.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/mirror/class-inl.h')
-rw-r--r--runtime/mirror/class-inl.h36
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,