Use type lookup tables in compiler
This recently regressed and stopped happening, the fix creates fake
OatDexFiles so that the compiler uses the type lookup tables instead
of slow FindClassDef and FindTypeId.
Perf on host compile Facebook:
Before:
2.49%: art::DexFile::FindClassDef(unsigned short) const
1.59%: art::DexFile::FindTypeId(char const*) const
After:
0.42%: art::OatDexFile::FindClassDef(art::DexFile const&, char const*, unsigned long)
0%: art::DexFile::FindTypeId(char const*) const
0%: art::DexFile::FindClassDef(unsigned short) const
Average install (N6P 960 mhz average of 40 samples): 38.2s -> 35.64s
Bug: 32641252
Test: test-art-host, adb install.
Change-Id: I34df21dc2c155bc2579c5cafdd91f9cb0fead1a9
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index c550a1b..17c5959 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -476,7 +476,11 @@
}
// The table is in the .vdex file.
const OatFile::OatDexFile* oat_dex_file = GetDexCache()->GetDexFile()->GetOatDexFile();
- return oat_dex_file->GetOatFile()->DexBegin() + header->vmap_table_offset_;
+ const OatFile* oat_file = oat_dex_file->GetOatFile();
+ if (oat_file == nullptr) {
+ return nullptr;
+ }
+ return oat_file->DexBegin() + header->vmap_table_offset_;
} else {
return oat_method.GetVmapTable();
}
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 4905514..9fdfc92 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4000,7 +4000,7 @@
const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
// In case we run without an image there won't be a backing oat file.
- if (oat_dex_file == nullptr) {
+ if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
return false;
}
diff --git a/runtime/class_table.cc b/runtime/class_table.cc
index b44104e..0fcce6b 100644
--- a/runtime/class_table.cc
+++ b/runtime/class_table.cc
@@ -170,7 +170,7 @@
const DexFile* dex_file = ObjPtr<mirror::DexCache>::DownCast(obj)->GetDexFile();
if (dex_file != nullptr && dex_file->GetOatDexFile() != nullptr) {
const OatFile* oat_file = dex_file->GetOatDexFile()->GetOatFile();
- if (!oat_file->GetBssGcRoots().empty()) {
+ if (oat_file != nullptr && !oat_file->GetBssGcRoots().empty()) {
InsertOatFileLocked(oat_file); // Ignore return value.
}
}
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index da9fa50..bd236f6 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -1010,6 +1010,11 @@
return oat_dex_file_;
}
+ // Used by oat writer.
+ void SetOatDexFile(OatDexFile* oat_dex_file) const {
+ oat_dex_file_ = oat_dex_file;
+ }
+
// Utility methods for reading integral values from a buffer.
static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth);
static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right);
@@ -1138,9 +1143,10 @@
// If this dex file was loaded from an oat file, oat_dex_file_ contains a
// pointer to the OatDexFile it was loaded from. Otherwise oat_dex_file_ is
// null.
- const OatDexFile* oat_dex_file_;
+ mutable const OatDexFile* oat_dex_file_;
friend class DexFileVerifierTest;
+ friend class OatWriter;
ART_FRIEND_TEST(ClassLinkerTest, RegisterDexFileName); // for constructor
};
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index c14b616..61979c7 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -1252,13 +1252,14 @@
if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) > GetOatFile()->End()) {
LOG(WARNING) << "found truncated lookup table in " << dex_file_location_;
} else {
- lookup_table_.reset(TypeLookupTable::Open(dex_file_pointer_,
- lookup_table_data_,
- num_class_defs));
+ lookup_table_ = TypeLookupTable::Open(dex_file_pointer_, lookup_table_data_, num_class_defs);
}
}
}
+OatFile::OatDexFile::OatDexFile(std::unique_ptr<TypeLookupTable>&& lookup_table)
+ : lookup_table_(std::move(lookup_table)) {}
+
OatFile::OatDexFile::~OatDexFile() {}
size_t OatFile::OatDexFile::FileSize() const {
@@ -1540,7 +1541,7 @@
bool* found) {
DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16);
const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile();
- if (oat_dex_file == nullptr) {
+ if (oat_dex_file == nullptr || oat_dex_file->GetOatFile() == nullptr) {
*found = false;
return OatFile::OatClass::Invalid();
}
@@ -1548,4 +1549,8 @@
return oat_dex_file->GetOatClass(class_def_idx);
}
+void OatFile::OatDexFile::AssertAotCompiler() {
+ CHECK(Runtime::Current()->IsAotCompiler());
+}
+
} // namespace art
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 63a0e14..29add5b 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -384,7 +384,13 @@
// Opens the DexFile referred to by this OatDexFile from within the containing OatFile.
std::unique_ptr<const DexFile> OpenDexFile(std::string* error_msg) const;
+ // May return null if the OatDexFile only contains a type lookup table. This case only happens
+ // for the compiler to speed up compilation.
const OatFile* GetOatFile() const {
+ // Avoid pulling in runtime.h in the header file.
+ if (kIsDebugBuild && oat_file_ == nullptr) {
+ AssertAotCompiler();
+ }
return oat_file_;
}
@@ -436,6 +442,9 @@
~OatDexFile();
+ // Create only with a type lookup table, used by the compiler to speed up compilation.
+ explicit OatDexFile(std::unique_ptr<TypeLookupTable>&& lookup_table);
+
private:
OatDexFile(const OatFile* oat_file,
const std::string& dex_file_location,
@@ -446,14 +455,16 @@
const uint32_t* oat_class_offsets_pointer,
uint8_t* dex_cache_arrays);
- const OatFile* const oat_file_;
+ static void AssertAotCompiler();
+
+ const OatFile* const oat_file_ = nullptr;
const std::string dex_file_location_;
const std::string canonical_dex_file_location_;
- const uint32_t dex_file_location_checksum_;
- const uint8_t* const dex_file_pointer_;
- const uint8_t* lookup_table_data_;
- const uint32_t* const oat_class_offsets_pointer_;
- uint8_t* const dex_cache_arrays_;
+ const uint32_t dex_file_location_checksum_ = 0u;
+ const uint8_t* const dex_file_pointer_ = nullptr;
+ const uint8_t* lookup_table_data_ = nullptr;
+ const uint32_t* const oat_class_offsets_pointer_ = 0u;
+ uint8_t* const dex_cache_arrays_ = nullptr;
mutable std::unique_ptr<TypeLookupTable> lookup_table_;
friend class OatFile;
diff --git a/runtime/type_lookup_table.cc b/runtime/type_lookup_table.cc
index 56e9262..16cd722 100644
--- a/runtime/type_lookup_table.cc
+++ b/runtime/type_lookup_table.cc
@@ -50,17 +50,19 @@
return num_class_defs != 0u && num_class_defs <= std::numeric_limits<uint16_t>::max();
}
-TypeLookupTable* TypeLookupTable::Create(const DexFile& dex_file, uint8_t* storage) {
+std::unique_ptr<TypeLookupTable> TypeLookupTable::Create(const DexFile& dex_file,
+ uint8_t* storage) {
const uint32_t num_class_defs = dex_file.NumClassDefs();
- return SupportedSize(num_class_defs)
+ return std::unique_ptr<TypeLookupTable>(SupportedSize(num_class_defs)
? new TypeLookupTable(dex_file, storage)
- : nullptr;
+ : nullptr);
}
-TypeLookupTable* TypeLookupTable::Open(const uint8_t* dex_file_pointer,
- const uint8_t* raw_data,
- uint32_t num_class_defs) {
- return new TypeLookupTable(dex_file_pointer, raw_data, num_class_defs);
+std::unique_ptr<TypeLookupTable> TypeLookupTable::Open(const uint8_t* dex_file_pointer,
+ const uint8_t* raw_data,
+ uint32_t num_class_defs) {
+ return std::unique_ptr<TypeLookupTable>(
+ new TypeLookupTable(dex_file_pointer, raw_data, num_class_defs));
}
TypeLookupTable::TypeLookupTable(const DexFile& dex_file, uint8_t* storage)
diff --git a/runtime/type_lookup_table.h b/runtime/type_lookup_table.h
index 9595743..3f6f76f 100644
--- a/runtime/type_lookup_table.h
+++ b/runtime/type_lookup_table.h
@@ -60,13 +60,14 @@
}
// Method creates lookup table for dex file
- static TypeLookupTable* Create(const DexFile& dex_file, uint8_t* storage = nullptr);
+ static std::unique_ptr<TypeLookupTable> Create(const DexFile& dex_file,
+ uint8_t* storage = nullptr);
// Method opens lookup table from binary data. Lookups will traverse strings and other
// data contained in dex_file as well. Lookup table does not own raw_data or dex_file.
- static TypeLookupTable* Open(const uint8_t* dex_file_pointer,
- const uint8_t* raw_data,
- uint32_t num_class_defs);
+ static std::unique_ptr<TypeLookupTable> Open(const uint8_t* dex_file_pointer,
+ const uint8_t* raw_data,
+ uint32_t num_class_defs);
// Method returns pointer to binary data of lookup table. Used by the oat writer.
const uint8_t* RawData() const {