aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitriy Ivanov <dimitry@google.com>2014-08-13 16:28:06 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-08-13 01:32:01 +0000
commitdb0785cbf9ee6cc0ace5c89496d7e9f12c288a83 (patch)
tree1bb60c12cee9972a1cc86cd3e43b63ad2d0dbc33
parent6e3823d37e54929558990d7c475bc30d381098fe (diff)
parent042426ba6375f5c145379e598486ec6d675533c9 (diff)
downloadandroid_bionic-db0785cbf9ee6cc0ace5c89496d7e9f12c288a83.tar.gz
android_bionic-db0785cbf9ee6cc0ace5c89496d7e9f12c288a83.tar.bz2
android_bionic-db0785cbf9ee6cc0ace5c89496d7e9f12c288a83.zip
Merge "Optimize symbol lookup"
-rw-r--r--linker/linked_list.h9
-rw-r--r--linker/linker.cpp8
2 files changed, 17 insertions, 0 deletions
diff --git a/linker/linked_list.h b/linker/linked_list.h
index 7f8c90160..8096e623d 100644
--- a/linker/linked_list.h
+++ b/linker/linked_list.h
@@ -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_;
diff --git a/linker/linker.cpp b/linker/linker.cpp
index f8b35d7a8..77fb70c29 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -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;
}