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
Change-Id: I1379f30ed8b06758dd1cc76b80833ac8589afa50
This commit is contained in:
Dmitriy Ivanov 2014-08-12 21:02:13 -07:00
parent 6e3823d37e
commit 042426ba63
2 changed files with 17 additions and 0 deletions

View File

@ -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:
LinkedListEntry<T>* head_;
LinkedListEntry<T>* tail_;

View File

@ -607,17 +607,24 @@ class SoinfoListAllocatorRW {
// specified soinfo object and its dependencies in breadth first order.
ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name, soinfo* caller) {
LinkedList<soinfo, SoinfoListAllocatorRW> visit_list;
LinkedList<soinfo, SoinfoListAllocatorRW> visited;
visit_list.push_back(si);
soinfo* current_soinfo;
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,
caller == current_soinfo ? SymbolLookupScope::kAllowLocal : SymbolLookupScope::kExcludeLocal);
if (result != nullptr) {
*found = current_soinfo;
visit_list.clear();
visited.clear();
return result;
}
visited.push_back(current_soinfo);
current_soinfo->get_children().for_each([&](soinfo* 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();
visited.clear();
return nullptr;
}