Do superclass validation at compile time and log with new class status.
Tries to perform superclass validation for classes that are resolved,
but not initialized at runtime. If successful, saves the result in the
oat file with a new class status. At runtime, the superclass validation
can be skipped during class initialization, saving some time and
reducing string accesses.
Results show savings of 50kB PSS in maps on startup, with slight
decrease in startup time.
Maps (average of 100 runs)
Before: dex 9941.3 odex 15159.8 total 25101.1 launch 908
After: dex 9897.4 odex 15155.7 total 25053.1 launch 906.6
Bug: 63456114
Test: mm test-art-host
Change-Id: If67a4a49d61781b6d561c26118d7e0c6b9cc0d6f
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index a5d4540..1c3375c 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4405,8 +4405,7 @@
uint16_t class_def_index = klass->GetDexClassDefIndex();
oat_file_class_status = oat_dex_file->GetOatClass(class_def_index).GetStatus();
- if (oat_file_class_status == mirror::Class::kStatusVerified ||
- oat_file_class_status == mirror::Class::kStatusInitialized) {
+ if (oat_file_class_status >= mirror::Class::kStatusVerified) {
return true;
}
// If we only verified a subset of the classes at compile time, we can end up with classes that
@@ -4885,7 +4884,13 @@
return WaitForInitializeClass(klass, self, lock);
}
- if (!ValidateSuperClassDescriptors(klass)) {
+ bool has_oat_class = false;
+ const OatFile::OatClass oat_class =
+ (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler())
+ ? OatFile::FindOatClass(klass->GetDexFile(), klass->GetDexClassDefIndex(), &has_oat_class)
+ : OatFile::OatClass::Invalid();
+ if (oat_class.GetStatus() < mirror::Class::kStatusSuperclassValidated &&
+ !ValidateSuperClassDescriptors(klass)) {
mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorResolved, self);
return false;
}