Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use rich mangling information in Symtab::InitNameIndexes()
Summary: I set up a new review, because not all the code I touched was marked as a change in old one anymore. In preparation for this review, there were two earlier ones: * https://reviews.llvm.org/D49612 introduced the ItaniumPartialDemangler to LLDB demangling without conceptual changes * https://reviews.llvm.org/D49909 added a unit test that covers all relevant code paths in the InitNameIndexes() function Primary goals for this patch are: (1) Use ItaniumPartialDemangler's rich mangling info for building LLDB's name index. (2) Provide a uniform interface. (3) Improve indexing performance. The central implementation in this patch is our new function for explicit demangling: ``` const RichManglingInfo * Mangled::DemangleWithRichManglingInfo(RichManglingContext &, SkipMangledNameFn *) ``` It takes a context object and a filter function and provides read-only access to the rich mangling info on success, or otherwise returns null. The two new classes are: * `RichManglingInfo` offers a uniform interface to query symbol properties like `getFunctionDeclContextName()` or `isCtorOrDtor()` that are forwarded to the respective provider internally (`llvm::ItaniumPartialDemangler` or `lldb_private::CPlusPlusLanguage::MethodName`). * `RichManglingContext` works a bit like `LLVMContext`, it the actual `RichManglingInfo` returned from `DemangleWithRichManglingInfo()` and handles lifetime and configuration. It is likely stack-allocated and can be reused for multiple queries during batch processing. The idea here is that `DemangleWithRichManglingInfo()` acts like a gate keeper. It only provides access to `RichManglingInfo` on success, which in turn avoids the need to handle a `NoInfo` state in every single one of its getters. Having it stored within the context, avoids extra heap allocations and aids (3). As instantiations of the IPD the are considered expensive, the context is the ideal place to store it too. An efficient filtering function `SkipMangledNameFn` is another piece in the performance puzzle and it helps to mimic the original behavior of `InitNameIndexes`. Future potential: * `DemangleWithRichManglingInfo()` is thread-safe, IFF using different contexts in different threads. This may be exploited in the future. (It's another thing that it has in common with `LLVMContext`.) * The old implementation only parsed and indexed Itanium mangled names. The new `RichManglingInfo` can be extended for various mangling schemes and languages. One problem with the implementation of RichManglingInfo is the inaccessibility of class `CPlusPlusLanguage::MethodName` (defined in source/Plugins/Language/..), from within any header in the Core components of LLDB. The rather hacky solution is to store a type erased reference and cast it to the correct type on access in the cpp - see `RichManglingInfo::get<ParserT>()`. At the moment there seems to be no better way to do it. IMHO `CPlusPlusLanguage::MethodName` should be a top-level class in order to enable forward delcarations (but that is a rather big change I guess). First simple profiling shows a good speedup. `target create clang` now takes 0.64s on average. Before the change I observed runtimes between 0.76s an 1.01s. This is still no bulletproof data (I only ran it on one machine!), but it's a promising indicator I think. Reviewers: labath, jingham, JDevlieghere, erik.pilkington Subscribers: zturner, clayborg, mgorny, lldb-commits Differential Revision: https://reviews.llvm.org/D50071 llvm-svn: 339291
- Loading branch information
1 parent
f71dd34
commit f1a98df
Showing
11 changed files
with
730 additions
and
147 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
//===-- RichManglingContext.h -----------------------------------*- C++ -*-===// | ||
// | ||
// The LLVM Compiler Infrastructure | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef liblldb_RichManglingContext_h_ | ||
#define liblldb_RichManglingContext_h_ | ||
|
||
#include "lldb/lldb-forward.h" | ||
#include "lldb/lldb-private.h" | ||
|
||
#include "lldb/Utility/ConstString.h" | ||
|
||
#include "llvm/ADT/Any.h" | ||
#include "llvm/ADT/SmallString.h" | ||
#include "llvm/Demangle/Demangle.h" | ||
|
||
namespace lldb_private { | ||
|
||
/// Uniform wrapper for access to rich mangling information from different | ||
/// providers. See Mangled::DemangleWithRichManglingInfo() | ||
class RichManglingContext { | ||
public: | ||
RichManglingContext() | ||
: m_provider(None), m_ipd_buf_size(2048), m_ipd_str_len(0) { | ||
m_ipd_buf = static_cast<char *>(std::malloc(m_ipd_buf_size)); | ||
m_ipd_buf[m_ipd_str_len] = '\0'; | ||
} | ||
|
||
~RichManglingContext() { std::free(m_ipd_buf); } | ||
|
||
/// Use the ItaniumPartialDemangler to obtain rich mangling information from | ||
/// the given mangled name. | ||
bool FromItaniumName(const ConstString &mangled); | ||
|
||
/// Use the legacy language parser implementation to obtain rich mangling | ||
/// information from the given demangled name. | ||
bool FromCxxMethodName(const ConstString &demangled); | ||
|
||
/// If this symbol describes a constructor or destructor. | ||
bool IsCtorOrDtor() const; | ||
|
||
/// If this symbol describes a function. | ||
bool IsFunction() const; | ||
|
||
/// Get the base name of a function. This doesn't include trailing template | ||
/// arguments, ie "a::b<int>" gives "b". The result will overwrite the | ||
/// internal buffer. It can be obtained via GetBufferRef(). | ||
void ParseFunctionBaseName(); | ||
|
||
/// Get the context name for a function. For "a::b::c", this function returns | ||
/// "a::b". The result will overwrite the internal buffer. It can be obtained | ||
/// via GetBufferRef(). | ||
void ParseFunctionDeclContextName(); | ||
|
||
/// Get the entire demangled name. The result will overwrite the internal | ||
/// buffer. It can be obtained via GetBufferRef(). | ||
void ParseFullName(); | ||
|
||
/// Obtain a StringRef to the internal buffer that holds the result of the | ||
/// most recent ParseXy() operation. The next ParseXy() call invalidates it. | ||
llvm::StringRef GetBufferRef() const { | ||
assert(m_provider != None && "Initialize a provider first"); | ||
return m_buffer; | ||
} | ||
|
||
private: | ||
enum InfoProvider { None, ItaniumPartialDemangler, PluginCxxLanguage }; | ||
|
||
/// Selects the rich mangling info provider. | ||
InfoProvider m_provider; | ||
|
||
/// Reference to the buffer used for results of ParseXy() operations. | ||
llvm::StringRef m_buffer; | ||
|
||
/// Members for ItaniumPartialDemangler | ||
llvm::ItaniumPartialDemangler m_ipd; | ||
char *m_ipd_buf; | ||
size_t m_ipd_buf_size; | ||
size_t m_ipd_str_len; | ||
|
||
/// Members for PluginCxxLanguage | ||
/// Cannot forward declare inner class CPlusPlusLanguage::MethodName. The | ||
/// respective header is in Plugins and including it from here causes cyclic | ||
/// dependency. Instead keep a llvm::Any and cast it on-access in the cpp. | ||
llvm::Any m_cxx_method_parser; | ||
|
||
/// Clean up memory and set a new info provider for this instance. | ||
void ResetProvider(InfoProvider new_provider); | ||
|
||
/// Uniform handling of string buffers for ItaniumPartialDemangler. | ||
void processIPDStrResult(char *ipd_res, size_t res_len); | ||
|
||
/// Cast the given parser to the given type. Ideally we would have a type | ||
/// trait to deduce \a ParserT from a given InfoProvider, but unfortunately we | ||
/// can't access CPlusPlusLanguage::MethodName from within the header. | ||
template <class ParserT> static ParserT *get(llvm::Any parser) { | ||
assert(parser.hasValue()); | ||
assert(llvm::any_isa<ParserT *>(parser)); | ||
return llvm::any_cast<ParserT *>(parser); | ||
} | ||
}; | ||
|
||
} // namespace lldb_private | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.