diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/Makefile b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/Makefile new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/Makefile @@ -0,0 +1,7 @@ +# There is no guaranteed order in which the linker will order these +# files, so we just have a lot of them to make it unlikely that we hit +# the right one first by pure luck. + +CXX_SOURCES := main.cpp a.cpp b.cpp c.cpp d.cpp e.cpp f.cpp g.cpp + +include Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/TestCPPAccelerator.py b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/TestCPPAccelerator.py new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/TestCPPAccelerator.py @@ -0,0 +1,31 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class CPPAcceleratorTableTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + """Test that type lookups fail early (performance)""" + self.build() + logfile = self.getBuildArtifact('dwarf.log') + self.expect('log enable dwarf lookups -f' + logfile) + target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + self, 'break here', lldb.SBFileSpec('main.cpp')) + # Pick one from the middle of the list to have a high chance + # of it not being in the first file looked at. + self.expect('frame variable inner_d') + + log = open(logfile, 'r') + n = 0 + for line in log: + if re.findall(r'[abcdefg]\.o: FindByNameAndTag\(\)', line): + self.assertTrue("d.o" in line) + n += 1 + + self.assertEqual(n, 1, log) diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/a.cpp b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/a.cpp new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/a.cpp @@ -0,0 +1,2 @@ +#include "source.h" +CLASS(A) diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/b.cpp b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/b.cpp new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/b.cpp @@ -0,0 +1,2 @@ +#include "source.h" +CLASS(B) diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/c.cpp b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/c.cpp new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/c.cpp @@ -0,0 +1,2 @@ +#include "source.h" +CLASS(C) diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/d.cpp b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/d.cpp new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/d.cpp @@ -0,0 +1,2 @@ +#include "source.h" +CLASS(D) diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/e.cpp b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/e.cpp new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/e.cpp @@ -0,0 +1,2 @@ +#include "source.h" +CLASS(E) diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/f.cpp b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/f.cpp new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/f.cpp @@ -0,0 +1,2 @@ +#include "source.h" +CLASS(F) diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/g.cpp b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/g.cpp new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/g.cpp @@ -0,0 +1,2 @@ +#include "source.h" +CLASS(G) diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/main.cpp b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/main.cpp @@ -0,0 +1,28 @@ +#define CLASS(NAME) \ + class NAME { \ + public: \ + struct Inner; \ + Inner *i = nullptr; \ + }; \ +NAME::Inner &getInner##NAME(); + +CLASS(A) +CLASS(B) +CLASS(C) +CLASS(D) +CLASS(E) +CLASS(F) +CLASS(G) + +int main() +{ + A::Inner &inner_a = getInnerA(); + B::Inner &inner_b = getInnerB(); + C::Inner &inner_c = getInnerC(); + D::Inner &inner_d = getInnerD(); + E::Inner &inner_e = getInnerE(); + F::Inner &inner_f = getInnerF(); + G::Inner &inner_g = getInnerG(); + + return 0; // break here +} diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/source.h b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/source.h new file mode 100644 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/accelerator-table/source.h @@ -0,0 +1,12 @@ +#define CLASS(NAME) \ + class NAME { \ + public: \ + class Inner { \ + int j = #NAME[0]; \ + }; \ + Inner *i = nullptr; \ + }; \ + \ + static NAME::Inner inner; \ + static NAME obj; \ + NAME::Inner &getInner##NAME() { return inner; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp @@ -110,6 +110,7 @@ const bool has_qualified_name_hash = m_apple_types_up->GetHeader().header_data.ContainsAtom( DWARFMappedHash::eAtomTypeQualNameHash); + const ConstString type_name(context[0].name); const dw_tag_t tag = context[0].tag; if (has_tag && has_qualified_name_hash) { @@ -119,12 +120,32 @@ m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()"); m_apple_types_up->FindByNameAndTagAndQualifiedNameHash( type_name.GetStringRef(), tag, qualified_name_hash, offsets); - } else if (has_tag) { + return; + } + + if (has_tag) { + // When searching for a scoped type (for example, + // "std::vector::const_iterator") searching for the innermost + // name alone ("const_iterator") could yield many false + // positives. By searching for the parent type ("vector") + // first we can avoid extracting type DIEs from object files that + // would fail the filter anyway. + if (!has_qualified_name_hash && (context.GetSize() > 1) && + (context[1].tag == DW_TAG_class_type || + context[1].tag == DW_TAG_structure_type)) { + DIEArray class_matches; + m_apple_types_up->FindByName(context[1].name, class_matches); + if (class_matches.empty()) + return; + } + if (log) m_module.LogMessage(log, "FindByNameAndTag()"); m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, offsets); - } else - m_apple_types_up->FindByName(type_name.GetStringRef(), offsets); + return; + } + + m_apple_types_up->FindByName(type_name.GetStringRef(), offsets); } void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {