diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp index 6b3e8ec652a91..2ee3f25efc1ab 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp @@ -18,6 +18,7 @@ #include "swift/Demangling/Demangle.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" using namespace lldb; using namespace lldb_private; @@ -416,16 +417,27 @@ bool LLDBMemoryReader::readString(swift::remote::RemoteAddress address, Log *log = GetLog(LLDBLog::Types); auto format_string = [](const std::string &dest) { - StreamString stream; - for (auto c : dest) { - if (c >= 32 && c <= 127) { - stream << c; - } else { - stream << "\\0"; - stream.PutHex8(c); - } + std::string result; + llvm::raw_string_ostream s(result); + llvm::printEscapedString(dest, s); + return result; + }; + /// Very quickly (this is a high-firing event), copy a few + /// human-readable bytes usable as detail in the progress update. + auto short_string = [](const std::string &dest) { + std::string result; + result.reserve(24); + size_t end = std::min(dest.size(), 24); + for (size_t i = 0; i < end; ++i) { + signed char c = dest[i]; + result.append(1, c > 32 ? c : '.'); } - return std::string(stream.GetData()); + if (end < dest.size()) { + result[21] = '.'; + result[22] = '.'; + result[23] = '.'; + } + return result; }; LLDB_LOGV(log, "[MemoryReader] asked to read string data at address {0:x}", address.getRawAddress()); @@ -463,6 +475,8 @@ bool LLDBMemoryReader::readString(swift::remote::RemoteAddress address, !readMetadataFromFileCacheEnabled() || !addr.IsSectionOffset(); target.ReadCStringFromMemory(addr, dest, error, force_live_memory); if (error.Success()) { + if (m_progress_callback) + m_progress_callback(short_string(dest)); LLDB_LOGV(log, "[MemoryReader] memory read returned string: \"{0}\"", format_string(dest)); return true; diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h index a42f503ad07cc..6d37b7f18c820 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h +++ b/lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h @@ -105,6 +105,12 @@ class LLDBMemoryReader : public swift::remote::MemoryReader { /// Returns whether the filecache optimization is enabled or not. bool readMetadataFromFileCacheEnabled() const; + /// Set or clear the progress callback. + void SetProgressCallback( + std::function progress_callback = {}) { + m_progress_callback = progress_callback; + } + protected: bool readRemoteAddressImpl(swift::remote::RemoteAddress address, swift::remote::RemoteAddress &out, @@ -166,6 +172,8 @@ class LLDBMemoryReader : public swift::remote::MemoryReader { /// The set of modules where we should read memory from the symbol file's /// object file instead of the main object file. llvm::SmallSet m_modules_with_metadata_in_symbol_obj_file; + /// A callback to update a progress event. + std::function m_progress_callback; }; } // namespace lldb_private #endif diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp index d89b3821a5225..f3ad5a2008c61 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp @@ -608,6 +608,22 @@ std::optional SwiftLanguageRuntime::GetMemberVariableOffset( namespace { +class ProgressRAII { + Progress m_progress; + LLDBMemoryReader &m_memory_reader; +public: + ProgressRAII(std::string title, Debugger *debugger, + LLDBMemoryReader &memory_reader) + : m_progress(title, {}, {}, debugger, + Progress::kDefaultHighFrequencyReportTime), + m_memory_reader(memory_reader) { + m_memory_reader.SetProgressCallback([&](StringRef message) { + m_progress.Increment(1, message.str()); + }); + } + ~ProgressRAII() { m_memory_reader.SetProgressCallback(); }; +}; + CompilerType GetTypeFromTypeRef(TypeSystemSwiftTypeRef &ts, const swift::reflection::TypeRef *type_ref, swift::Mangle::ManglingFlavor flavor) { @@ -3480,6 +3496,14 @@ SwiftLanguageRuntime::GetSwiftRuntimeTypeInfo( if (!reflection_ctx) return llvm::createStringError("no reflection context"); + // On remove connections downloading reflection metadata can be a bottleneck. + auto flavor = GetManglingFlavor(type.GetMangledTypeName()); + static std::string g_debuginfo = "Loading debug info"; + static std::string g_reflection = "Loading reflection metadata"; + ProgressRAII progress( + flavor == swift::Mangle::ManglingFlavor::Embedded ? g_debuginfo + : g_reflection, + &GetProcess().GetTarget().GetDebugger(), *GetMemoryReader()); LLDBTypeInfoProvider provider(*this, ts); return reflection_ctx->GetTypeInfo(*type_ref_or_err, &provider, ts.GetDescriptorFinder()); diff --git a/lldb/test/API/functionalities/progress_reporting/swift_progress_reporting/TestSwiftProgressReporting.py b/lldb/test/API/functionalities/progress_reporting/swift_progress_reporting/TestSwiftProgressReporting.py index 1cca761bf5a14..3ab9abcf135c0 100644 --- a/lldb/test/API/functionalities/progress_reporting/swift_progress_reporting/TestSwiftProgressReporting.py +++ b/lldb/test/API/functionalities/progress_reporting/swift_progress_reporting/TestSwiftProgressReporting.py @@ -41,6 +41,7 @@ def test_swift_progress_report(self): "Importing dependencies for main.swift", "Importing dependencies for main.swift: Foundation", "Importing Swift standard library", + "Loading reflection metadata", ] importing_swift_reports = []