Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 23 additions & 9 deletions lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what this lambda does

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a comment:

  /// Very quickly (this is a high-firing event), copy a few
  /// human-readable bytes usable as detail in the progress update.

std::string result;
result.reserve(24);
size_t end = std::min<size_t>(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());
Expand Down Expand Up @@ -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));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need something similar on readBytesImpl as well?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only picked ReadCString because that reads something we can put into the detail field of the progress event. My understanding is that moving an indefinite progress forward by one, without a message is effectively invisible to the user.

LLDB_LOGV(log, "[MemoryReader] memory read returned string: \"{0}\"",
format_string(dest));
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<void(llvm::StringRef)> progress_callback = {}) {
m_progress_callback = progress_callback;
}

protected:
bool readRemoteAddressImpl(swift::remote::RemoteAddress address,
swift::remote::RemoteAddress &out,
Expand Down Expand Up @@ -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<lldb::ModuleSP, 8> m_modules_with_metadata_in_symbol_obj_file;
/// A callback to update a progress event.
std::function<void(llvm::StringRef)> m_progress_callback;
};
} // namespace lldb_private
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,22 @@ std::optional<uint64_t> 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) {
Expand Down Expand Up @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand Down