scott.smith created this revision.
The Timer destructor would grab a global mutex in order to update execution
time. Add a class to define a category once, statically; the class adds itself
to an atomic singly linked list, and thus subsequent updates only need to use
an atomic rather than grab a lock and perform a hashtable lookup.
Repository:
rL LLVM
https://reviews.llvm.org/D32823
Files:
include/lldb/Core/Timer.h
source/API/SystemInitializerFull.cpp
source/Commands/CommandObjectTarget.cpp
source/Core/Disassembler.cpp
source/Core/Mangled.cpp
source/Core/Module.cpp
source/Core/Timer.cpp
source/Host/common/Symbols.cpp
source/Initialization/SystemInitializerCommon.cpp
source/Interpreter/CommandInterpreter.cpp
source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
source/Symbol/DWARFCallFrameInfo.cpp
source/Symbol/ObjectFile.cpp
source/Symbol/Symtab.cpp
source/Target/Target.cpp
source/Target/TargetList.cpp
Index: source/Target/TargetList.cpp
===================================================================
--- source/Target/TargetList.cpp
+++ source/Target/TargetList.cpp
@@ -325,7 +325,8 @@
lldb::PlatformSP &platform_sp,
lldb::TargetSP &target_sp,
bool is_dummy_target) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"TargetList::CreateTarget (file = '%s', arch = '%s')",
user_exe_path.str().c_str(),
specified_arch.GetArchitectureName());
Index: source/Target/Target.cpp
===================================================================
--- source/Target/Target.cpp
+++ source/Target/Target.cpp
@@ -1235,7 +1235,8 @@
ClearModules(false);
if (executable_sp) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"Target::SetExecutableModule (executable = '%s')",
executable_sp->GetFileSpec().GetPath().c_str());
Index: source/Symbol/Symtab.cpp
===================================================================
--- source/Symbol/Symtab.cpp
+++ source/Symbol/Symtab.cpp
@@ -220,7 +220,8 @@
// Protected function, no need to lock mutex...
if (!m_name_indexes_computed) {
m_name_indexes_computed = true;
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
// Create the name index vector to be able to quickly search by name
const size_t num_symbols = m_symbols.size();
#if 1
@@ -433,7 +434,8 @@
bool add_demangled, bool add_mangled,
NameToIndexMap &name_to_index_map) const {
if (add_demangled || add_mangled) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
std::lock_guard<std::recursive_mutex> guard(m_mutex);
// Create the name index vector to be able to quickly search by name
@@ -595,7 +597,8 @@
bool remove_duplicates) const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
// No need to sort if we have zero or one items...
if (indexes.size() <= 1)
return;
@@ -621,7 +624,8 @@
std::vector<uint32_t> &indexes) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
if (symbol_name) {
if (!m_name_indexes_computed)
InitNameIndexes();
@@ -637,7 +641,8 @@
std::vector<uint32_t> &indexes) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
if (symbol_name) {
const size_t old_size = indexes.size();
if (!m_name_indexes_computed)
@@ -766,7 +771,8 @@
std::vector<uint32_t> &symbol_indexes) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
// Initialize all of the lookup by name indexes before converting NAME
// to a uniqued string NAME_STR below.
if (!m_name_indexes_computed)
@@ -785,7 +791,8 @@
Visibility symbol_visibility, std::vector<uint32_t> &symbol_indexes) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
// Initialize all of the lookup by name indexes before converting NAME
// to a uniqued string NAME_STR below.
if (!m_name_indexes_computed)
@@ -817,7 +824,8 @@
Visibility symbol_visibility) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s", LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%s", LLVM_PRETTY_FUNCTION);
if (!m_name_indexes_computed)
InitNameIndexes();
Index: source/Symbol/ObjectFile.cpp
===================================================================
--- source/Symbol/ObjectFile.cpp
+++ source/Symbol/ObjectFile.cpp
@@ -37,8 +37,9 @@
ObjectFileSP object_file_sp;
if (module_sp) {
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(
- LLVM_PRETTY_FUNCTION,
+ func_cat,
"ObjectFile::FindPlugin (module = %s, file = %p, file_offset = "
"0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")",
module_sp->GetFileSpec().GetPath().c_str(),
@@ -176,9 +177,10 @@
ObjectFileSP object_file_sp;
if (module_sp) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "ObjectFile::FindPlugin (module = "
- "%s, process = %p, header_addr = "
- "0x%" PRIx64 ")",
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "ObjectFile::FindPlugin (module = "
+ "%s, process = %p, header_addr = "
+ "0x%" PRIx64 ")",
module_sp->GetFileSpec().GetPath().c_str(),
static_cast<void *>(process_sp.get()), header_addr);
uint32_t idx;
Index: source/Symbol/DWARFCallFrameInfo.cpp
===================================================================
--- source/Symbol/DWARFCallFrameInfo.cpp
+++ source/Symbol/DWARFCallFrameInfo.cpp
@@ -419,7 +419,8 @@
if (m_fde_index_initialized) // if two threads hit the locker
return;
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s - %s", LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%s - %s", LLVM_PRETTY_FUNCTION,
m_objfile.GetFileSpec().GetFilename().AsCString(""));
bool clear_address_zeroth_bit = false;
Index: source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
===================================================================
--- source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -92,7 +92,8 @@
if (file_spec_list.IsEmpty())
return NULL;
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"SymbolVendorELF::CreateInstance (module = %s)",
module_sp->GetFileSpec().GetPath().c_str());
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -991,7 +991,8 @@
const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
uint32_t name_type_mask, bool include_inlines, bool append,
SymbolContextList &sc_list) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"SymbolFileDWARFDebugMap::FindFunctions (name = %s)",
name.GetCString());
@@ -1018,7 +1019,8 @@
bool include_inlines,
bool append,
SymbolContextList &sc_list) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"SymbolFileDWARFDebugMap::FindFunctions (regex = '%s')",
regex.GetText().str().c_str());
@@ -1044,7 +1046,8 @@
size_t SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope,
uint32_t type_mask,
TypeList &type_list) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)",
type_mask);
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -666,7 +666,8 @@
DWARFDebugInfo *SymbolFileDWARF::DebugInfo() {
if (m_info.get() == NULL) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s this = %p",
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%s this = %p",
LLVM_PRETTY_FUNCTION, static_cast<void *>(this));
if (get_debug_info_data().GetByteSize() > 0) {
m_info.reset(new DWARFDebugInfo());
@@ -703,7 +704,8 @@
DWARFDebugRanges *SymbolFileDWARF::DebugRanges() {
if (m_ranges.get() == NULL) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s this = %p",
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%s this = %p",
LLVM_PRETTY_FUNCTION, static_cast<void *>(this));
if (get_debug_ranges_data().GetByteSize() > 0) {
m_ranges.reset(new DWARFDebugRanges());
@@ -1666,7 +1668,8 @@
uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
uint32_t resolve_scope,
SymbolContext &sc) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "SymbolFileDWARF::"
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "SymbolFileDWARF::"
"ResolveSymbolContext (so_addr = { "
"section = %p, offset = 0x%" PRIx64
" }, resolve_scope = 0x%8.8x)",
@@ -1927,8 +1930,9 @@
if (m_indexed)
return;
m_indexed = true;
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(
- LLVM_PRETTY_FUNCTION, "SymbolFileDWARF::Index (%s)",
+ func_cat, "SymbolFileDWARF::Index (%s)",
GetObjectFile()->GetFileSpec().GetFilename().AsCString("<Unknown>"));
DWARFDebugInfo *debug_info = DebugInfo();
@@ -2385,7 +2389,8 @@
const CompilerDeclContext *parent_decl_ctx,
uint32_t name_type_mask, bool include_inlines,
bool append, SymbolContextList &sc_list) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"SymbolFileDWARF::FindFunctions (name = '%s')",
name.AsCString());
@@ -2665,7 +2670,8 @@
uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression ®ex,
bool include_inlines, bool append,
SymbolContextList &sc_list) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"SymbolFileDWARF::FindFunctions (regex = '%s')",
regex.GetText().str().c_str());
Index: source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
@@ -25,7 +25,8 @@
DWARFDebugPubnames::DWARFDebugPubnames() : m_sets() {}
bool DWARFDebugPubnames::Extract(const DWARFDataExtractor &data) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
(uint64_t)data.GetByteSize());
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
@@ -52,7 +53,8 @@
}
bool DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF *dwarf2Data) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"DWARFDebugPubnames::GeneratePubnames (data = %p)",
static_cast<void *>(dwarf2Data));
Index: source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
@@ -484,8 +484,9 @@
const dw_offset_t debug_line_offset = *offset_ptr;
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(
- LLVM_PRETTY_FUNCTION,
+ func_cat,
"DWARFDebugLine::ParseStatementTable (.debug_line[0x%8.8x])",
debug_line_offset);
Index: source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
@@ -110,7 +110,8 @@
}
void DWARFDebugAranges::Sort(bool minimize) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "%s this = %p", LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION,
static_cast<void *>(this));
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -135,8 +135,9 @@
if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1)
return 0; // Already parsed
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(
- LLVM_PRETTY_FUNCTION,
+ func_cat,
"%8.8x: DWARFCompileUnit::ExtractDIEsIfNeeded( cu_die_only = %i )",
m_offset, cu_die_only);
Index: source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
===================================================================
--- source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -928,7 +928,8 @@
};
void ScriptInterpreterPython::ExecuteInterpreterLoop() {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
Debugger &debugger = GetCommandInterpreter().GetDebugger();
@@ -1995,7 +1996,8 @@
StructuredData::ObjectSP &callee_wrapper_sp,
const TypeSummaryOptions &options, std::string &retval) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
if (!valobj.get()) {
retval.assign("<no object>");
@@ -2019,7 +2021,8 @@
{
TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options));
- Timer scoped_timer("g_swig_typescript_callback",
+ static TimerCategory func_cat("g_swig_typescript_callback");
+ Timer scoped_timer(func_cat,
"g_swig_typescript_callback");
ret_val = g_swig_typescript_callback(
python_function_name, GetSessionDictionary().get(), valobj,
@@ -3102,7 +3105,8 @@
g_initialized = true;
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
// RAII-based initialization which correctly handles multiple-initialization,
// version-
Index: source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
===================================================================
--- source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -2121,7 +2121,8 @@
}
size_t ObjectFileMachO::ParseSymtab() {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"ObjectFileMachO::ParseSymtab () module = %s",
m_file.GetFilename().AsCString(""));
ModuleSP module_sp(GetModule());
@@ -5081,9 +5082,9 @@
if (path[0] == '@') {
if (strncmp(path, "@rpath", strlen("@rpath")) == 0)
rpath_relative_paths.push_back(path + strlen("@rpath"));
- else if (strncmp(path, "@executable_path",
+ else if (strncmp(path, "@executable_path",
strlen("@executable_path")) == 0)
- at_exec_relative_paths.push_back(path
+ at_exec_relative_paths.push_back(path
+ strlen("@executable_path"));
} else {
FileSpec file_spec(path, resolve_path);
@@ -5102,7 +5103,7 @@
FileSpec this_file_spec(m_file);
this_file_spec.ResolvePath();
-
+
if (!rpath_paths.empty()) {
// Fixup all LC_RPATH values to be absolute paths
std::string loader_path("@loader_path");
@@ -5142,7 +5143,7 @@
if (!at_exec_relative_paths.empty() && CalculateType() == eTypeExecutable) {
FileSpec exec_dir = this_file_spec.CopyByRemovingLastPathComponent();
for (const auto &at_exec_relative_path : at_exec_relative_paths) {
- FileSpec file_spec =
+ FileSpec file_spec =
exec_dir.CopyByAppendingPathComponent(at_exec_relative_path);
file_spec = file_spec.GetNormalizedPath();
if (file_spec.Exists() && files.AppendIfUnique(file_spec)) {
@@ -5417,7 +5418,7 @@
break;
if (ident_command.cmd == LC_IDENT && ident_command.cmdsize != 0) {
char *buf = (char *) malloc (ident_command.cmdsize);
- if (buf != nullptr
+ if (buf != nullptr
&& m_data.CopyData (offset, ident_command.cmdsize, buf) == ident_command.cmdsize) {
buf[ident_command.cmdsize - 1] = '\0';
result = buf;
Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
===================================================================
--- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -294,7 +294,7 @@
uint32_t arch_variant = ArchSpec::eMIPSSubType_unknown;
uint32_t fileclass = header.e_ident[EI_CLASS];
- // If there aren't any elf flags available (e.g core elf file) then return default
+ // If there aren't any elf flags available (e.g core elf file) then return default
// 32 or 64 bit arch (without any architecture revision) based on object file's class.
if (header.e_type == ET_CORE) {
switch (fileclass) {
@@ -727,8 +727,9 @@
uint32_t core_notes_crc = 0;
if (!gnu_debuglink_crc) {
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
lldb_private::Timer scoped_timer(
- LLVM_PRETTY_FUNCTION,
+ func_cat,
"Calculating module crc32 %s with size %" PRIu64 " KiB",
file.GetLastPathComponent().AsCString(),
(file.GetByteSize() - file_offset) / 1024);
@@ -1475,7 +1476,7 @@
// In case of MIPSR6, the LLDB_NT_OWNER_GNU note is missing
// for some cases (e.g. compile with -nostdlib)
// Hence set OS to Linux
- arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
}
}
@@ -1579,7 +1580,7 @@
const uint32_t sub_type = subTypeFromElfHeader(header);
arch_spec.SetArchitecture(eArchTypeELF, header.e_machine, sub_type,
header.e_ident[EI_OSABI]);
-
+
// Validate if it is ok to remove GetOsFromOSABI.
// Note, that now the OS is determined based on EI_OSABI flag and
// the info extracted from ELF notes (see RefineModuleDetailsFromNote).
Index: source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
===================================================================
--- source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -301,8 +301,9 @@
DataExtractor data;
data.SetData(data_sp, data_offset, length);
if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data)) {
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(
- LLVM_PRETTY_FUNCTION,
+ func_cat,
"ObjectContainerBSDArchive::CreateInstance (module = %s, file = "
"%p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")",
module_sp->GetFileSpec().GetPath().c_str(),
Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
===================================================================
--- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -122,7 +122,7 @@
const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
BucketInfo *buckets = (BucketInfo *)grc->buckets;
-
+
uint32_t idx = 0;
for (unsigned i=0; i<=grc->num_buckets_minus_one; ++i)
{
@@ -279,7 +279,7 @@
DEBUG_PRINTF("clsOffset == invalidEntryOffset\n");
continue; // invalid offset
}
-
+
if (class_infos && idx < max_class_infos)
{
class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
@@ -298,7 +298,7 @@
}
++idx;
}
-
+
const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
const uint32_t duplicate_count = *duplicate_count_ptr;
const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]);
@@ -311,7 +311,7 @@
continue; // duplicate
else if (clsOffset == invalidEntryOffset)
continue; // invalid offset
-
+
if (class_infos && idx < max_class_infos)
{
class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
@@ -1395,12 +1395,12 @@
arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress();
arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
-
+
// Only dump the runtime classes from the expression evaluation if the
// log is verbose:
Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
bool dump_log = type_log && type_log->GetVerbose();
-
+
arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0;
bool success = false;
@@ -1648,7 +1648,7 @@
// log is verbose:
Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
bool dump_log = type_log && type_log->GetVerbose();
-
+
arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0;
bool success = false;
@@ -1803,7 +1803,8 @@
void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
// Else we need to check with our process to see when the map was updated.
Process *process = GetProcess();
Index: source/Interpreter/CommandInterpreter.cpp
===================================================================
--- source/Interpreter/CommandInterpreter.cpp
+++ source/Interpreter/CommandInterpreter.cpp
@@ -169,7 +169,8 @@
}
void CommandInterpreter::Initialize() {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
CommandReturnObject result;
@@ -391,7 +392,8 @@
}
void CommandInterpreter::LoadCommandDictionary() {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
@@ -1533,7 +1535,8 @@
if (log)
log->Printf("Processing command: %s", command_line);
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "Handling command: %s.",
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "Handling command: %s.",
command_line);
if (!no_context_switching)
Index: source/Initialization/SystemInitializerCommon.cpp
===================================================================
--- source/Initialization/SystemInitializerCommon.cpp
+++ source/Initialization/SystemInitializerCommon.cpp
@@ -72,7 +72,8 @@
llvm::EnablePrettyStackTrace();
InitializeLog();
HostInfo::Initialize();
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
process_gdb_remote::ProcessGDBRemoteLog::Initialize();
@@ -102,7 +103,8 @@
}
void SystemInitializerCommon::Terminate() {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
ObjectContainerBSDArchive::Terminate();
ObjectFileELF::Terminate();
ObjectFilePECOFF::Terminate();
Index: source/Host/common/Symbols.cpp
===================================================================
--- source/Host/common/Symbols.cpp
+++ source/Host/common/Symbols.cpp
@@ -151,8 +151,9 @@
const ArchSpec *arch = module_spec.GetArchitecturePtr();
const UUID *uuid = module_spec.GetUUIDPtr();
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(
- LLVM_PRETTY_FUNCTION,
+ func_cat,
"LocateExecutableSymbolFileDsym (file = %s, arch = %s, uuid = %p)",
exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>",
arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid);
@@ -175,8 +176,9 @@
const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
const ArchSpec *arch = module_spec.GetArchitecturePtr();
const UUID *uuid = module_spec.GetUUIDPtr();
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(
- LLVM_PRETTY_FUNCTION,
+ func_cat,
"LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
exec_fspec ? exec_fspec->GetFilename().AsCString("<NULL>") : "<NULL>",
arch ? arch->GetArchitectureName() : "<NULL>", (const void *)uuid);
Index: source/Core/Timer.cpp
===================================================================
--- source/Core/Timer.cpp
+++ source/Core/Timer.cpp
@@ -27,8 +27,8 @@
#define TIMER_INDENT_AMOUNT 2
namespace {
-typedef std::map<const char *, std::chrono::nanoseconds> TimerCategoryMap;
typedef std::vector<Timer *> TimerStack;
+static std::atomic<TimerCategory *> g_categories;
} // end of anonymous namespace
std::atomic<bool> Timer::g_quiet(true);
@@ -38,16 +38,6 @@
return *g_file_mutex_ptr;
}
-static std::mutex &GetCategoryMutex() {
- static std::mutex g_category_mutex;
- return g_category_mutex;
-}
-
-static TimerCategoryMap &GetCategoryMap() {
- static TimerCategoryMap g_category_map;
- return g_category_map;
-}
-
static void ThreadSpecificCleanup(void *p) {
delete static_cast<TimerStack *>(p);
}
@@ -64,9 +54,19 @@
return (TimerStack *)timer_stack;
}
+TimerCategory::TimerCategory(const char * cat)
+ : m_name(cat)
+{
+ m_nanos.store(0, std::memory_order_release);
+ TimerCategory * expected = g_categories;
+ do {
+ m_next = expected;
+ } while (!g_categories.compare_exchange_weak(expected, this));
+}
+
void Timer::SetQuiet(bool value) { g_quiet = value; }
-Timer::Timer(const char *category, const char *format, ...)
+Timer::Timer(TimerCategory & category, const char *format, ...)
: m_category(category), m_total_start(std::chrono::steady_clock::now()) {
TimerStack *stack = GetTimerStackForCurrentThread();
if (!stack)
@@ -114,45 +114,39 @@
stack->back()->ChildDuration(total_dur);
// Keep total results for each category so we can dump results.
- {
- std::lock_guard<std::mutex> guard(GetCategoryMutex());
- TimerCategoryMap &category_map = GetCategoryMap();
- category_map[m_category] += timer_dur;
- }
+ m_category.m_nanos += std::chrono::nanoseconds(timer_dur).count();
}
void Timer::SetDisplayDepth(uint32_t depth) { g_display_depth = depth; }
/* binary function predicate:
* - returns whether a person is less than another person
*/
+
+typedef std::pair<const char *, uint64_t> TimerEntry;
+
static bool
-CategoryMapIteratorSortCriterion(const TimerCategoryMap::const_iterator &lhs,
- const TimerCategoryMap::const_iterator &rhs) {
- return lhs->second > rhs->second;
+CategoryMapIteratorSortCriterion(const TimerEntry &lhs, const TimerEntry &rhs) {
+ return lhs.second > rhs.second;
}
void Timer::ResetCategoryTimes() {
- std::lock_guard<std::mutex> guard(GetCategoryMutex());
- TimerCategoryMap &category_map = GetCategoryMap();
- category_map.clear();
+ for (TimerCategory * i = g_categories; i; i = i->m_next)
+ i->m_nanos.store(0, std::memory_order_release);
}
void Timer::DumpCategoryTimes(Stream *s) {
- std::lock_guard<std::mutex> guard(GetCategoryMutex());
- TimerCategoryMap &category_map = GetCategoryMap();
- std::vector<TimerCategoryMap::const_iterator> sorted_iterators;
- TimerCategoryMap::const_iterator pos, end = category_map.end();
- for (pos = category_map.begin(); pos != end; ++pos) {
- sorted_iterators.push_back(pos);
+ std::vector<TimerEntry> sorted;
+ for (TimerCategory * i = g_categories; i; i = i->m_next) {
+ uint64_t nanos = i->m_nanos.load(std::memory_order_acquire);
+ if (nanos)
+ sorted.push_back(std::make_pair(i->m_name, nanos));
}
- std::sort(sorted_iterators.begin(), sorted_iterators.end(),
- CategoryMapIteratorSortCriterion);
+ std::sort(sorted.begin(), sorted.end(), CategoryMapIteratorSortCriterion);
- const size_t count = sorted_iterators.size();
+ const size_t count = sorted.size();
for (size_t i = 0; i < count; ++i) {
- const auto timer = sorted_iterators[i]->second;
- s->Printf("%.9f sec for %s\n", std::chrono::duration<double>(timer).count(),
- sorted_iterators[i]->first);
+ const auto & timer = sorted[i];
+ s->Printf("%.9f sec for %s\n", timer.second / 1000000000., timer.first);
}
}
Index: source/Core/Module.cpp
===================================================================
--- source/Core/Module.cpp
+++ source/Core/Module.cpp
@@ -140,7 +140,7 @@
const bool mandatory = true;
ModuleList::RemoveOrphanSharedModules(mandatory);
}
-
+
void
DumpModuleInfo (void)
{
@@ -150,15 +150,15 @@
printf ("%s: %" PRIu64 " modules:\n", LLVM_PRETTY_FUNCTION, (uint64_t)count);
for (size_t i = 0; i < count; ++i)
{
-
+
StreamString strm;
Module *module = modules[i];
const bool in_shared_module_list = ModuleList::ModuleIsInCache (module);
module->GetDescription(&strm, eDescriptionLevelFull);
- printf ("%p: shared = %i, ref_count = %3u, module = %s\n",
- module,
+ printf ("%p: shared = %i, ref_count = %3u, module = %s\n",
+ module,
in_shared_module_list,
- (uint32_t)module->use_count(),
+ (uint32_t)module->use_count(),
strm.GetString().c_str());
}
}
@@ -429,7 +429,8 @@
size_t Module::GetNumCompileUnits() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"Module::GetNumCompileUnits (module = %p)",
static_cast<void *>(this));
SymbolVendor *symbols = GetSymbolVendor();
@@ -453,7 +454,8 @@
bool Module::ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"Module::ResolveFileAddress (vm_addr = 0x%" PRIx64 ")",
vm_addr);
SectionList *section_list = GetSectionList();
@@ -616,7 +618,8 @@
uint32_t resolve_scope,
SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"Module::ResolveSymbolContextForFilePath (%s:%u, "
"check_inlines = %s, resolve_scope = 0x%8.8x)",
file_spec.GetPath().c_str(), line,
@@ -987,7 +990,8 @@
const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
if (!sc.module_sp || sc.module_sp.get() == this) {
SymbolVendor *symbols = GetSymbolVendor();
if (symbols)
@@ -1078,7 +1082,8 @@
if (!m_did_load_symbol_vendor.load() && can_create) {
ObjectFile *obj_file = GetObjectFile();
if (obj_file != nullptr) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
m_symfile_ap.reset(
SymbolVendor::FindPlugin(shared_from_this(), feedback_strm));
m_did_load_symbol_vendor = true;
@@ -1278,7 +1283,8 @@
if (!m_did_load_objfile.load()) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (!m_did_load_objfile.load()) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"Module::GetObjectFile () module = %s",
GetFileSpec().GetFilename().AsCString(""));
DataBufferSP data_sp;
@@ -1338,8 +1344,9 @@
const Symbol *Module::FindFirstSymbolWithNameAndType(const ConstString &name,
SymbolType symbol_type) {
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(
- LLVM_PRETTY_FUNCTION,
+ func_cat,
"Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)",
name.AsCString(), symbol_type);
SymbolVendor *sym_vendor = GetSymbolVendor();
@@ -1372,7 +1379,8 @@
size_t Module::FindFunctionSymbols(const ConstString &name,
uint32_t name_type_mask,
SymbolContextList &sc_list) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"Module::FindSymbolsFunctions (name = %s, mask = 0x%8.8x)",
name.AsCString(), name_type_mask);
SymbolVendor *sym_vendor = GetSymbolVendor();
@@ -1390,8 +1398,9 @@
// No need to protect this call using m_mutex all other method calls are
// already thread safe.
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(
- LLVM_PRETTY_FUNCTION,
+ func_cat,
"Module::FindSymbolsWithNameAndType (name = %s, type = %i)",
name.AsCString(), symbol_type);
const size_t initial_size = sc_list.GetSize();
@@ -1413,8 +1422,9 @@
// No need to protect this call using m_mutex all other method calls are
// already thread safe.
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(
- LLVM_PRETTY_FUNCTION,
+ func_cat,
"Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)",
regex.GetText().str().c_str(), symbol_type);
const size_t initial_size = sc_list.GetSize();
Index: source/Core/Mangled.cpp
===================================================================
--- source/Core/Mangled.cpp
+++ source/Core/Mangled.cpp
@@ -258,7 +258,8 @@
// haven't already decoded our mangled name.
if (m_mangled && !m_demangled) {
// We need to generate and cache the demangled name.
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"Mangled::GetDemangledName (m_mangled = %s)",
m_mangled.GetCString());
@@ -433,13 +434,13 @@
return lldb::eLanguageTypeObjC;
}
} else {
- // ObjC names aren't really mangled, so they won't necessarily be in the
+ // ObjC names aren't really mangled, so they won't necessarily be in the
// mangled name slot.
ConstString demangled_name = GetDemangledName(lldb::eLanguageTypeUnknown);
- if (demangled_name
+ if (demangled_name
&& ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString()))
return lldb::eLanguageTypeObjC;
-
+
}
return lldb::eLanguageTypeUnknown;
}
Index: source/Core/Disassembler.cpp
===================================================================
--- source/Core/Disassembler.cpp
+++ source/Core/Disassembler.cpp
@@ -59,7 +59,8 @@
DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch,
const char *flavor,
const char *plugin_name) {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION,
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
"Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
arch.GetArchitectureName(), plugin_name);
@@ -1456,4 +1457,3 @@
lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) {
return [type](const Instruction::Operand &op) { return op.m_type == type; };
}
-
Index: source/Commands/CommandObjectTarget.cpp
===================================================================
--- source/Commands/CommandObjectTarget.cpp
+++ source/Commands/CommandObjectTarget.cpp
@@ -269,7 +269,8 @@
}
const char *file_path = command.GetArgumentAtIndex(0);
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, "(lldb) target create '%s'",
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "(lldb) target create '%s'",
file_path);
FileSpec file_spec;
Index: source/API/SystemInitializerFull.cpp
===================================================================
--- source/API/SystemInitializerFull.cpp
+++ source/API/SystemInitializerFull.cpp
@@ -400,7 +400,8 @@
}
void SystemInitializerFull::Terminate() {
- Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION);
+ static TimerCategory func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
Debugger::SettingsTerminate();
Index: include/lldb/Core/Timer.h
===================================================================
--- include/lldb/Core/Timer.h
+++ include/lldb/Core/Timer.h
@@ -23,6 +23,19 @@
namespace lldb_private {
+class TimerCategory {
+public:
+ explicit TimerCategory(const char * category_name);
+
+private:
+ friend class Timer;
+ const char * m_name;
+ std::atomic<uint64_t> m_nanos;
+ std::atomic<TimerCategory *> m_next;
+
+ DISALLOW_COPY_AND_ASSIGN(TimerCategory);
+};
+
//----------------------------------------------------------------------
/// @class Timer Timer.h "lldb/Core/Timer.h"
/// @brief A timer class that simplifies common timing metrics.
@@ -40,7 +53,7 @@
//--------------------------------------------------------------
/// Default constructor.
//--------------------------------------------------------------
- Timer(const char *category, const char *format, ...)
+ Timer(TimerCategory & category, const char *format, ...)
__attribute__((format(printf, 3, 4)));
//--------------------------------------------------------------
@@ -62,7 +75,7 @@
using TimePoint = std::chrono::steady_clock::time_point;
void ChildDuration(TimePoint::duration dur) { m_child_duration += dur; }
- const char *m_category;
+ TimerCategory & m_category;
TimePoint m_total_start;
TimePoint::duration m_child_duration{0};
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits