jankratochvil created this revision. Herald added subscribers: JDevlieghere, aprantl.
Multiple DW_TAG_compile_unit being indexed in a multithreaded way can request reading of the same DW_TAG_partial_unit. Unfortunately one cannot detect DWZ file ahead of time to disable such locking overhead as DWARFCompileUnit::Extract does not read the first DIE which is the only place one could find early enough if the DWARF file is using any DW_TAG_partial_unit. All DWZ patches are also applied in: git clone -b dwz git://git.jankratochvil.net/lldb https://reviews.llvm.org/D40470 Files: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -70,6 +70,9 @@ dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET; dw_offset_t m_file_offset; + std::mutex m_extractdies_mutex; + bool m_die_array_finished; + private: static uint8_t g_default_addr_size; Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -91,6 +91,8 @@ void DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die) { if (m_data->m_die_array.size() > 1) { + std::lock_guard<std::mutex> guard(m_data->m_extractdies_mutex); + // std::vectors never get any smaller when resized to a smaller size, // or when clear() or erase() are called, the size will report that it // is smaller, but the memory allocated remains intact (call capacity() @@ -118,9 +120,21 @@ // done. //---------------------------------------------------------------------- size_t DWARFCompileUnit::ExtractDIEsIfNeeded(bool cu_die_only) { - const size_t initial_die_array_size = m_data->m_die_array.size(); - if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1) - return 0; // Already parsed + size_t initial_die_array_size; + auto already_parsed = [cu_die_only, &initial_die_array_size]() -> bool { + return (cu_die_only && initial_die_array_size > 0) + || initial_die_array_size > 1; + }; + if (already_parsed() && m_data->m_die_array_finished) + return 0; + std::lock_guard<std::mutex> guard(m_data->m_extractdies_mutex); + if (already_parsed()) { + lldbassert(m_data->m_die_array_finished); + return 0; + } + m_data->m_die_array_finished = false; + std::shared_ptr<void> m_die_array_finished_set(nullptr, + [&](void*){ m_data->m_die_array_finished = true; }); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(
Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -70,6 +70,9 @@ dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET; dw_offset_t m_file_offset; + std::mutex m_extractdies_mutex; + bool m_die_array_finished; + private: static uint8_t g_default_addr_size; Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -91,6 +91,8 @@ void DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die) { if (m_data->m_die_array.size() > 1) { + std::lock_guard<std::mutex> guard(m_data->m_extractdies_mutex); + // std::vectors never get any smaller when resized to a smaller size, // or when clear() or erase() are called, the size will report that it // is smaller, but the memory allocated remains intact (call capacity() @@ -118,9 +120,21 @@ // done. //---------------------------------------------------------------------- size_t DWARFCompileUnit::ExtractDIEsIfNeeded(bool cu_die_only) { - const size_t initial_die_array_size = m_data->m_die_array.size(); - if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1) - return 0; // Already parsed + size_t initial_die_array_size; + auto already_parsed = [cu_die_only, &initial_die_array_size]() -> bool { + return (cu_die_only && initial_die_array_size > 0) + || initial_die_array_size > 1; + }; + if (already_parsed() && m_data->m_die_array_finished) + return 0; + std::lock_guard<std::mutex> guard(m_data->m_extractdies_mutex); + if (already_parsed()) { + lldbassert(m_data->m_die_array_finished); + return 0; + } + m_data->m_die_array_finished = false; + std::shared_ptr<void> m_die_array_finished_set(nullptr, + [&](void*){ m_data->m_die_array_finished = true; }); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits