Implementation of fast lookup table to search class_def by descriptor
Lookup table is a hash table which built at compile time and stored
into oat file. At runtime the table is restored and used in the
method DexFile::FindClassDef(const char*) to perform fast search of
the class_def_idx by class descriptor. Advantages of the lookup table
over the HashSet (runtime/base/hash_set.h) are:
1. Lookup table is built at compile time and uses read-only memory at
runtime
2. Lookup table uses less memory then DexFile::Index (less by 80% for
/system/framework/framework.jar on Nexus5)
3. Lookup table does less string comparisons compared with HashSet
(less by 70% for zygote process on Nexus5)
The disadvantage of the lookup table is it increased boot.oat size by
0.2% on Nexus5 and application .oat file by 0.3% in average on Nexus5.
mathieuc changes:
Create lookup table in dex2oat to speed up compilation. Clean up code
to follow style guide and use less static functions. Added
performance measurements.
Compile ~100 APKs 5 times with filter interpret-only:
Before:
real 1m8.989s
user 0m59.318s
sys 0m7.773s
After:
real 1m1.493s
user 0m52.055s
sys 0m7.581s
App launch (AOSP N5 maps, average of 45 runs):
Before: 966.84ms
After: 923.733ms
Launch speedup is 4.7%
Memory usage compared to HashSet index on 50 various APK:
32 bit: HashSet ~625694b vs TypeLookupTable ~404268b
64 bit: HashSet ~1251390b vs TypeLookupTable ~404268b
Bug: 10921004
Bug: 20269715
Change-Id: I7246c1d9ad9fe81fe5c5907a4bf70396d8f9242a
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index a162a4e..680f4ac 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -547,6 +547,25 @@
return false;
}
const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(dex_file_pointer);
+
+ if (UNLIKELY(oat > End())) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with truncated "
+ "lookup table offset", GetLocation().c_str(), i,
+ dex_file_location.c_str());
+ return false;
+ }
+ uint32_t lookup_table_offset = *reinterpret_cast<const uint32_t*>(oat);
+ oat += sizeof(lookup_table_offset);
+ if (Begin() + lookup_table_offset > End()) {
+ *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd for '%s' with truncated "
+ "lookup table", GetLocation().c_str(), i,
+ dex_file_location.c_str());
+ return false;
+ }
+ const uint8_t* lookup_table_data = lookup_table_offset != 0u
+ ? Begin() + lookup_table_offset
+ : nullptr;
+
const uint32_t* methods_offsets_pointer = reinterpret_cast<const uint32_t*>(oat);
oat += (sizeof(*methods_offsets_pointer) * header->class_defs_size_);
@@ -586,6 +605,7 @@
canonical_location,
dex_file_checksum,
dex_file_pointer,
+ lookup_table_data,
methods_offsets_pointer,
current_dex_cache_arrays);
oat_dex_files_storage_.push_back(oat_dex_file);
@@ -709,6 +729,7 @@
const std::string& canonical_dex_file_location,
uint32_t dex_file_location_checksum,
const uint8_t* dex_file_pointer,
+ const uint8_t* lookup_table_data,
const uint32_t* oat_class_offsets_pointer,
uint8_t* dex_cache_arrays)
: oat_file_(oat_file),
@@ -716,6 +737,7 @@
canonical_dex_file_location_(canonical_dex_file_location),
dex_file_location_checksum_(dex_file_location_checksum),
dex_file_pointer_(dex_file_pointer),
+ lookup_table_data_(lookup_table_data),
oat_class_offsets_pointer_(oat_class_offsets_pointer),
dex_cache_arrays_(dex_cache_arrays) {}