Cache uwnind frame headers as they are found.
Summary:
This improves unwind performance quite substantially, and follows
a somewhat similar approach used in libgcc_s as described in the
thread here:
https://gcc.gnu.org/ml/gcc/2005-02/msg00625.html
On certain extremely exception heavy internal tests, the time
drops from about 80 minutes to about five minutes.
Subscribers: libcxx-commits
Tags: #libc
Differential Revision: https://reviews.llvm.org/D75954
Cr-Mirrored-From: https://chromium.googlesource.com/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: c53c2058ffb8ff877702bb2dded31c85c1dfe66d
diff --git a/src/AddressSpace.hpp b/src/AddressSpace.hpp
index 83af9ae..a4564cb 100644
--- a/src/AddressSpace.hpp
+++ b/src/AddressSpace.hpp
@@ -452,6 +452,11 @@
#error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
#endif
+#include "FrameHeaderCache.hpp"
+
+// There should be just one of these per process.
+static FrameHeaderCache ProcessFrameHeaderCache;
+
static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base,
dl_iterate_cb_data *cbdata) {
if (phdr->p_type == PT_LOAD) {
@@ -466,10 +471,13 @@
return false;
}
-int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t, void *data) {
+int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t pinfo_size,
+ void *data) {
auto cbdata = static_cast<dl_iterate_cb_data *>(data);
if (pinfo->dlpi_phnum == 0 || cbdata->targetAddr < pinfo->dlpi_addr)
return 0;
+ if (ProcessFrameHeaderCache.find(pinfo, pinfo_size, data))
+ return 1;
Elf_Addr image_base = calculateImageBase(pinfo);
bool found_obj = false;
@@ -496,8 +504,10 @@
} else if (!found_obj) {
found_obj = checkAddrInSegment(phdr, image_base, cbdata);
}
- if (found_obj && found_hdr)
+ if (found_obj && found_hdr) {
+ ProcessFrameHeaderCache.add(cbdata->sects);
return 1;
+ }
}
cbdata->sects->dwarf_section_length = 0;
return 0;