Avoid allocating OatFile::OatClass on the heap.
Avoid allocating a BitVector for OatFile::OatClass::bitmap_
with kOatClassSomeCompiled methods. That makes the OatClass
copy-constructible as it doesn't own any memory. We use that
in OatFile::OatDexFile::GetOatClass() to return the result
by value thus avoiding one or two heap allocations per call.
Change-Id: Ic7098109028a5b49e39ef626f877de86e732ed18
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index e690b30..d89ba55 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1523,7 +1523,7 @@
return size;
}
-const OatFile::OatClass* ClassLinker::GetOatClass(const DexFile& dex_file, uint16_t class_def_idx) {
+OatFile::OatClass ClassLinker::GetOatClass(const DexFile& dex_file, uint16_t class_def_idx) {
DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
const OatFile* oat_file = FindOpenedOatFileForDexFile(dex_file);
CHECK(oat_file != NULL) << dex_file.GetLocation();
@@ -1531,9 +1531,7 @@
const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation().c_str(),
&dex_location_checksum);
CHECK(oat_dex_file != NULL) << dex_file.GetLocation();
- const OatFile::OatClass* oat_class = oat_dex_file->GetOatClass(class_def_idx);
- CHECK(oat_class != NULL) << dex_file.GetLocation() << " " << class_def_idx;
- return oat_class;
+ return oat_dex_file->GetOatClass(class_def_idx);
}
static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, uint16_t class_def_idx,
@@ -1593,16 +1591,14 @@
}
CHECK(found) << "Didn't find oat method index for virtual method: " << PrettyMethod(method);
}
- UniquePtr<const OatFile::OatClass>
- oat_class(GetOatClass(*declaring_class->GetDexCache()->GetDexFile(),
- declaring_class->GetDexClassDefIndex()));
- CHECK(oat_class.get() != NULL);
DCHECK_EQ(oat_method_index,
GetOatMethodIndexFromMethodIndex(*declaring_class->GetDexCache()->GetDexFile(),
method->GetDeclaringClass()->GetDexClassDefIndex(),
method->GetDexMethodIndex()));
+ const OatFile::OatClass oat_class = GetOatClass(*declaring_class->GetDexCache()->GetDexFile(),
+ declaring_class->GetDexClassDefIndex());
- return oat_class->GetOatMethod(oat_method_index);
+ return oat_class.GetOatMethod(oat_method_index);
}
// Special case to get oat code without overwriting a trampoline.
@@ -1651,18 +1647,16 @@
const void* ClassLinker::GetQuickOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx,
uint32_t method_idx) {
- UniquePtr<const OatFile::OatClass> oat_class(GetOatClass(dex_file, class_def_idx));
- CHECK(oat_class.get() != nullptr);
+ const OatFile::OatClass oat_class = GetOatClass(dex_file, class_def_idx);
uint32_t oat_method_idx = GetOatMethodIndexFromMethodIndex(dex_file, class_def_idx, method_idx);
- return oat_class->GetOatMethod(oat_method_idx).GetQuickCode();
+ return oat_class.GetOatMethod(oat_method_idx).GetQuickCode();
}
const void* ClassLinker::GetPortableOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx,
uint32_t method_idx) {
- UniquePtr<const OatFile::OatClass> oat_class(GetOatClass(dex_file, class_def_idx));
- CHECK(oat_class.get() != nullptr);
+ const OatFile::OatClass oat_class = GetOatClass(dex_file, class_def_idx);
uint32_t oat_method_idx = GetOatMethodIndexFromMethodIndex(dex_file, class_def_idx, method_idx);
- return oat_class->GetOatMethod(oat_method_idx).GetPortableCode();
+ return oat_class.GetOatMethod(oat_method_idx).GetPortableCode();
}
// Returns true if the method must run with interpreter, false otherwise.
@@ -1703,8 +1697,7 @@
const byte* class_data = dex_file.GetClassData(*dex_class_def);
// There should always be class data if there were direct methods.
CHECK(class_data != nullptr) << PrettyDescriptor(klass);
- UniquePtr<const OatFile::OatClass> oat_class(GetOatClass(dex_file, klass->GetDexClassDefIndex()));
- CHECK(oat_class.get() != nullptr);
+ const OatFile::OatClass oat_class = GetOatClass(dex_file, klass->GetDexClassDefIndex());
ClassDataItemIterator it(dex_file, class_data);
// Skip fields
while (it.HasNextStaticField()) {
@@ -1720,8 +1713,8 @@
// Only update static methods.
continue;
}
- const void* portable_code = oat_class->GetOatMethod(method_index).GetPortableCode();
- const void* quick_code = oat_class->GetOatMethod(method_index).GetQuickCode();
+ const void* portable_code = oat_class.GetOatMethod(method_index).GetPortableCode();
+ const void* quick_code = oat_class.GetOatMethod(method_index).GetQuickCode();
const bool enter_interpreter = NeedsInterpreter(method, quick_code, portable_code);
bool have_portable_code = false;
if (enter_interpreter) {
@@ -1869,11 +1862,25 @@
klass->SetDexClassDefIndex(dex_file.GetIndexForClassDef(dex_class_def));
klass->SetDexTypeIndex(dex_class_def.class_idx_);
- // Load fields fields.
const byte* class_data = dex_file.GetClassData(dex_class_def);
if (class_data == NULL) {
return; // no fields or methods - for example a marker interface
}
+
+ if (Runtime::Current()->IsStarted() && !Runtime::Current()->UseCompileTimeClassPath()) {
+ const OatFile::OatClass oat_class = GetOatClass(dex_file, klass->GetDexClassDefIndex());
+ LoadClassMembers(dex_file, class_data, klass, class_loader, &oat_class);
+ } else {
+ LoadClassMembers(dex_file, class_data, klass, class_loader, nullptr);
+ }
+}
+
+void ClassLinker::LoadClassMembers(const DexFile& dex_file,
+ const byte* class_data,
+ const SirtRef<mirror::Class>& klass,
+ mirror::ClassLoader* class_loader,
+ const OatFile::OatClass* oat_class) {
+ // Load fields.
ClassDataItemIterator it(dex_file, class_data);
Thread* self = Thread::Current();
if (it.NumStaticFields() != 0) {
@@ -1912,11 +1919,6 @@
LoadField(dex_file, it, klass, ifield);
}
- UniquePtr<const OatFile::OatClass> oat_class;
- if (Runtime::Current()->IsStarted() && !Runtime::Current()->UseCompileTimeClassPath()) {
- oat_class.reset(GetOatClass(dex_file, klass->GetDexClassDefIndex()));
- }
-
// Load methods.
if (it.NumDirectMethods() != 0) {
// TODO: append direct methods to class object
@@ -1946,8 +1948,8 @@
return;
}
klass->SetDirectMethod(i, method.get());
- if (oat_class.get() != NULL) {
- LinkCode(method, oat_class.get(), dex_file, it.GetMemberIndex(), class_def_method_index);
+ if (oat_class != nullptr) {
+ LinkCode(method, oat_class, dex_file, it.GetMemberIndex(), class_def_method_index);
}
method->SetMethodIndex(class_def_method_index);
class_def_method_index++;
@@ -1960,8 +1962,8 @@
}
klass->SetVirtualMethod(i, method.get());
DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
- if (oat_class.get() != NULL) {
- LinkCode(method, oat_class.get(), dex_file, it.GetMemberIndex(), class_def_method_index);
+ if (oat_class != nullptr) {
+ LinkCode(method, oat_class, dex_file, it.GetMemberIndex(), class_def_method_index);
}
class_def_method_index++;
}
@@ -2691,11 +2693,7 @@
&dex_location_checksum);
CHECK(oat_dex_file != NULL) << dex_file.GetLocation() << " " << PrettyClass(klass);
uint16_t class_def_index = klass->GetDexClassDefIndex();
- UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(class_def_index));
- CHECK(oat_class.get() != NULL)
- << dex_file.GetLocation() << " " << PrettyClass(klass) << " "
- << ClassHelper(klass).GetDescriptor();
- oat_file_class_status = oat_class->GetStatus();
+ 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) {
return true;