scott.smith created this revision.

Use TaskMapOverInt to demangle the symbols in parallel.  Defer categorization 
of C++ symbols until later, when it can be determined what contexts are 
definitely classes, and what might not be.


Repository:
  rL LLVM

https://reviews.llvm.org/D32820

Files:
  include/lldb/Utility/ConstString.h
  source/Symbol/Symtab.cpp

Index: source/Symbol/Symtab.cpp
===================================================================
--- source/Symbol/Symtab.cpp
+++ source/Symbol/Symtab.cpp
@@ -22,6 +22,7 @@
 #include "lldb/Symbol/Symtab.h"
 #include "lldb/Utility/RegularExpression.h"
 #include "lldb/Utility/Stream.h"
+#include "lldb/Utility/TaskPool.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -243,42 +244,44 @@
     m_name_to_index.Reserve(actual_count);
 #endif
 
-    NameToIndexMap::Entry entry;
-
-    // The "const char *" in "class_contexts" must come from a
-    // ConstString::GetCString()
-    std::set<const char *> class_contexts;
-    UniqueCStringMap<uint32_t> mangled_name_to_index;
-    std::vector<const char *> symbol_contexts(num_symbols, nullptr);
+    struct demangle_state {
+      ConstString name_to_index[5];
+      ConstString selector_to_index[1];
+      ConstString const_context;
+      ConstString cxx_basename;
+      bool is_definitely_class_context = false;
+    };
+    std::vector<demangle_state> states(num_symbols);
 
-    for (entry.value = 0; entry.value < num_symbols; ++entry.value) {
-      const Symbol *symbol = &m_symbols[entry.value];
+    auto symbol_fn = [&states, this](size_t value) {
+      const Symbol *symbol = &m_symbols[value];
 
       // Don't let trampolines get into the lookup by name map
       // If we ever need the trampoline symbols to be searchable by name
       // we can remove this and then possibly add a new bool to any of the
       // Symtab functions that lookup symbols by name to indicate if they
       // want trampolines.
       if (symbol->IsTrampoline())
-        continue;
+        return;
 
+      demangle_state &state = states[value];
       const Mangled &mangled = symbol->GetMangled();
-      entry.cstring = mangled.GetMangledName();
-      if (entry.cstring) {
-        m_name_to_index.Append(entry);
+      ConstString cstring = mangled.GetMangledName();
+      if (cstring) {
+        state.name_to_index[0] = cstring;
 
         if (symbol->ContainsLinkerAnnotations()) {
           // If the symbol has linker annotations, also add the version without
           // the annotations.
-          entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(
-                                        entry.cstring.GetStringRef()));
-          m_name_to_index.Append(entry);
+          cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(
+                                        cstring.GetStringRef()));
+          state.name_to_index[1] = cstring;
         }
 
         const SymbolType symbol_type = symbol->GetType();
         if (symbol_type == eSymbolTypeCode ||
             symbol_type == eSymbolTypeResolver) {
-          llvm::StringRef entry_ref(entry.cstring.GetStringRef());
+          llvm::StringRef entry_ref(cstring.GetStringRef());
           if (entry_ref[0] == '_' && entry_ref[1] == 'Z' &&
               (entry_ref[2] != 'T' && // avoid virtual table, VTT structure,
                                       // typeinfo structure, and typeinfo
@@ -290,103 +293,92 @@
           {
             CPlusPlusLanguage::MethodName cxx_method(
                 mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus));
-            entry.cstring = ConstString(cxx_method.GetBasename());
-            if (entry.cstring) {
+            cstring = ConstString(cxx_method.GetBasename());
+            if (cstring) {
               // ConstString objects permanently store the string in the pool so
               // calling
               // GetCString() on the value gets us a const char * that will
               // never go away
-              const char *const_context =
-                  ConstString(cxx_method.GetContext()).GetCString();
-
-              if (!const_context || const_context[0] == 0) {
-                // No context for this function so this has to be a basename
-                m_basename_to_index.Append(entry);
-                // If there is no context (no namespaces or class scopes that
-                // come before the function name) then this also could be a
-                // fullname.
-                m_name_to_index.Append(entry);
-              } else {
-                entry_ref = entry.cstring.GetStringRef();
-                if (entry_ref[0] == '~' ||
-                    !cxx_method.GetQualifiers().empty()) {
-                  // The first character of the demangled basename is '~' which
-                  // means we have a class destructor. We can use this information
-                  // to help us know what is a class and what isn't.
-                  if (class_contexts.find(const_context) == class_contexts.end())
-                    class_contexts.insert(const_context);
-                  m_method_to_index.Append(entry);
-                } else {
-                  if (class_contexts.find(const_context) !=
-                      class_contexts.end()) {
-                    // The current decl context is in our "class_contexts" which
-                    // means
-                    // this is a method on a class
-                    m_method_to_index.Append(entry);
-                  } else {
-                    // We don't know if this is a function basename or a method,
-                    // so put it into a temporary collection so once we are done
-                    // we can look in class_contexts to see if each entry is a
-                    // class
-                    // or just a function and will put any remaining items into
-                    // m_method_to_index or m_basename_to_index as needed
-                    mangled_name_to_index.Append(entry);
-                    symbol_contexts[entry.value] = const_context;
-                  }
-                }
-              }
+              entry_ref = cstring.GetStringRef();
+              ConstString const_context = ConstString(cxx_method.GetContext());
+
+              state.const_context = const_context;
+              state.cxx_basename = cstring;
+              state.is_definitely_class_context = entry_ref[0] == '~' ||
+                !cxx_method.GetQualifiers().empty();
             }
           }
         }
       }
 
-      entry.cstring = mangled.GetDemangledName(symbol->GetLanguage());
-      if (entry.cstring) {
-        m_name_to_index.Append(entry);
+      cstring = mangled.GetDemangledName(symbol->GetLanguage());
+      if (cstring) {
+        state.name_to_index[2] = cstring;
 
         if (symbol->ContainsLinkerAnnotations()) {
           // If the symbol has linker annotations, also add the version without
           // the annotations.
-          entry.cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(
-                                        entry.cstring.GetStringRef()));
-          m_name_to_index.Append(entry);
+          cstring = ConstString(m_objfile->StripLinkerSymbolAnnotations(
+                                        cstring.GetStringRef()));
+          state.name_to_index[3] = cstring;
         }
       }
 
       // If the demangled name turns out to be an ObjC name, and
       // is a category name, add the version without categories to the index
       // too.
-      ObjCLanguage::MethodName objc_method(entry.cstring.GetStringRef(), true);
+      ObjCLanguage::MethodName objc_method(cstring.GetStringRef(), true);
       if (objc_method.IsValid(true)) {
-        entry.cstring = objc_method.GetSelector();
-        m_selector_to_index.Append(entry);
+        cstring = objc_method.GetSelector();
+        state.selector_to_index[0] = cstring;
 
         ConstString objc_method_no_category(
             objc_method.GetFullNameWithoutCategory(true));
         if (objc_method_no_category) {
-          entry.cstring = objc_method_no_category;
-          m_name_to_index.Append(entry);
+          cstring = objc_method_no_category;
+          state.name_to_index[4] = cstring;
+        }
+      }
+    };
+
+    TaskMapOverInt(num_symbols, 16, symbol_fn);
+
+    std::unordered_set<ConstString> class_contexts;
+    for (size_t i = 0; i < num_symbols; i++) {
+      demangle_state const & state = states[i];
+      for (auto name : state.name_to_index) {
+        if (name) {
+          m_name_to_index.Append(name, i);
+        }
+      }
+      for (auto name : state.selector_to_index) {
+        if (name) {
+          m_selector_to_index.Append(name, i);
         }
       }
+      if (state.is_definitely_class_context) {
+        class_contexts.insert(state.const_context);
+      }
     }
 
-    size_t count;
-    if (!mangled_name_to_index.IsEmpty()) {
-      count = mangled_name_to_index.GetSize();
-      for (size_t i = 0; i < count; ++i) {
-        if (mangled_name_to_index.GetValueAtIndex(i, entry.value)) {
-          entry.cstring = mangled_name_to_index.GetCStringAtIndex(i);
-          if (symbol_contexts[entry.value] &&
-              class_contexts.find(symbol_contexts[entry.value]) !=
-                  class_contexts.end()) {
-            m_method_to_index.Append(entry);
-          } else {
-            // If we got here, we have something that had a context (was inside
-            // a namespace or class)
-            // yet we don't know if the entry
-            m_method_to_index.Append(entry);
-            m_basename_to_index.Append(entry);
-          }
+    for (size_t i = 0; i < num_symbols; i++) {
+      demangle_state const & state = states[i];
+      if (!state.cxx_basename)
+        continue;
+      if (!state.const_context) {
+        // No context for this function so this has to be a basename
+        m_basename_to_index.Append(state.cxx_basename, i);
+        // If there is no context (no namespaces or class scopes that
+        // come before the function name) then this also could be a
+        // fullname.
+        m_name_to_index.Append(state.cxx_basename, i);
+      } else {
+        m_method_to_index.Append(state.cxx_basename, i);
+        if (!state.is_definitely_class_context &&
+            class_contexts.find(state.const_context) == class_contexts.end()) {
+          // If we got here, we have something that had a context (was inside
+          // a namespace or class) yet we don't know if the entry
+          m_basename_to_index.Append(state.cxx_basename, i);
         }
       }
     }
Index: include/lldb/Utility/ConstString.h
===================================================================
--- include/lldb/Utility/ConstString.h
+++ include/lldb/Utility/ConstString.h
@@ -480,6 +480,18 @@
 
 } // namespace lldb_private
 
+namespace std {
+template<>
+struct hash<lldb_private::ConstString> {
+  size_t operator()(const lldb_private::ConstString & str) const {
+    return m_substr_hash(str.GetCString());
+  }
+
+private:
+  std::hash<const void *> m_substr_hash;
+};
+} // namespace std
+
 namespace llvm {
 template <> struct format_provider<lldb_private::ConstString> {
   static void format(const lldb_private::ConstString &CS, llvm::raw_ostream &OS,
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to