Optimize symbol lookup
Do not run symbol lookup on already visited soinfos
Not taking into account already visited libraries
dramatically slows down dlsym in cases when there
are multiple occurrences of a large library in
dependency tree.
Bug: 16977077
(cherry picked from commit 042426ba63
)
Change-Id: I69d59e395e8112f119343e8a4d72fe31cd449f31
This commit is contained in:
@@ -100,6 +100,15 @@ class LinkedList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool contains(const T* el) {
|
||||||
|
for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) {
|
||||||
|
if (e->element != nullptr && e->element == el) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LinkedListEntry<T>* head_;
|
LinkedListEntry<T>* head_;
|
||||||
LinkedListEntry<T>* tail_;
|
LinkedListEntry<T>* tail_;
|
||||||
|
@@ -607,17 +607,24 @@ class SoinfoListAllocatorRW {
|
|||||||
// specified soinfo object and its dependencies in breadth first order.
|
// specified soinfo object and its dependencies in breadth first order.
|
||||||
ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soinfo* caller) {
|
ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soinfo* caller) {
|
||||||
LinkedList<soinfo, SoinfoListAllocatorRW> visit_list;
|
LinkedList<soinfo, SoinfoListAllocatorRW> visit_list;
|
||||||
|
LinkedList<soinfo, SoinfoListAllocatorRW> visited;
|
||||||
visit_list.push_back(si);
|
visit_list.push_back(si);
|
||||||
soinfo* current_soinfo;
|
soinfo* current_soinfo;
|
||||||
while ((current_soinfo = visit_list.pop_front()) != nullptr) {
|
while ((current_soinfo = visit_list.pop_front()) != nullptr) {
|
||||||
|
if (visited.contains(current_soinfo)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ElfW(Sym)* result = soinfo_elf_lookup(current_soinfo, elfhash(name), name,
|
ElfW(Sym)* result = soinfo_elf_lookup(current_soinfo, elfhash(name), name,
|
||||||
caller == current_soinfo ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
|
caller == current_soinfo ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
|
||||||
|
|
||||||
if (result != nullptr) {
|
if (result != nullptr) {
|
||||||
*found = current_soinfo;
|
*found = current_soinfo;
|
||||||
visit_list.clear();
|
visit_list.clear();
|
||||||
|
visited.clear();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
visited.push_back(current_soinfo);
|
||||||
|
|
||||||
current_soinfo->get_children().for_each([&](soinfo* child) {
|
current_soinfo->get_children().for_each([&](soinfo* child) {
|
||||||
visit_list.push_back(child);
|
visit_list.push_back(child);
|
||||||
@@ -625,6 +632,7 @@ ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soi
|
|||||||
}
|
}
|
||||||
|
|
||||||
visit_list.clear();
|
visit_list.clear();
|
||||||
|
visited.clear();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user