https://github.com/felipepiovezan updated 
https://github.com/llvm/llvm-project/pull/201166

>From 59ab98f0d5dfa3d563dcf191c4954abcd1906e98 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <[email protected]>
Date: Tue, 2 Jun 2026 16:06:58 +0100
Subject: [PATCH 1/3] [lldb] Use MemoryCache in Process::ReadRangesFromMemory

There are scenarios (especially in the ObjectiveC metadata reading) in
which multiple strings are read over and over again, but through
different code paths. In order to make that part of the code use
MultiMemRead effectively, the memory cache must be integrated into
ReadRangesFromMemory before we can migrate the string reading to
vectorized version.
---
 lldb/include/lldb/Target/Memory.h  | 14 ++++++++
 lldb/include/lldb/Target/Process.h |  1 +
 lldb/source/Target/Memory.cpp      | 53 ++++++++++++++++++++++++++++++
 lldb/source/Target/Process.cpp     |  2 ++
 4 files changed, 70 insertions(+)

diff --git a/lldb/include/lldb/Target/Memory.h 
b/lldb/include/lldb/Target/Memory.h
index 85584f29ec7e7..2b8655e277a29 100644
--- a/lldb/include/lldb/Target/Memory.h
+++ b/lldb/include/lldb/Target/Memory.h
@@ -11,6 +11,8 @@
 
 #include "lldb/Utility/RangeMap.h"
 #include "lldb/lldb-private.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
 #include <map>
 #include <mutex>
 #include <vector>
@@ -31,6 +33,13 @@ class MemoryCache {
 
   size_t Read(lldb::addr_t addr, void *dst, size_t dst_len, Status &error);
 
+  /// Reads multiple memory ranges, serving cache hits from L1 and batching all
+  /// misses through Process::DoReadMemoryRanges. The semantics of the return
+  /// value match Process::ReadMemoryRanges.
+  llvm::SmallVector<llvm::MutableArrayRef<uint8_t>>
+  ReadRanges(llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges,
+             llvm::MutableArrayRef<uint8_t> buffer);
+
   uint32_t GetMemoryCacheLineSize() const { return m_L2_cache_line_byte_size; }
 
   void AddInvalidRange(lldb::addr_t base_addr, lldb::addr_t byte_size);
@@ -40,6 +49,11 @@ class MemoryCache {
   // Allow external sources to populate data into the L1 memory cache
   void AddL1CacheData(lldb::addr_t addr, const void *src, size_t src_len);
 
+  void AddL1CacheData(lldb::addr_t addr, llvm::ArrayRef<uint8_t> src) {
+    if (!src.empty())
+      AddL1CacheData(addr, src.data(), src.size());
+  }
+
   void AddL1CacheData(lldb::addr_t addr,
                       const lldb::DataBufferSP &data_buffer_sp);
 
diff --git a/lldb/include/lldb/Target/Process.h 
b/lldb/include/lldb/Target/Process.h
index f68ea3b639e93..8432c326d3281 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -362,6 +362,7 @@ class Process : public 
std::enable_shared_from_this<Process>,
   friend class StopInfo;
   friend class Target;
   friend class ThreadList;
+  friend class MemoryCache;
 
 public:
   /// Broadcaster event bits definitions.
diff --git a/lldb/source/Target/Memory.cpp b/lldb/source/Target/Memory.cpp
index 6c4650f1eb2d7..bb563be7090d9 100644
--- a/lldb/source/Target/Memory.cpp
+++ b/lldb/source/Target/Memory.cpp
@@ -14,6 +14,8 @@
 #include "lldb/Utility/RangeMap.h"
 #include "lldb/Utility/State.h"
 
+#include "llvm/ADT/STLExtras.h"
+
 #include <cinttypes>
 #include <memory>
 
@@ -270,6 +272,57 @@ size_t MemoryCache::Read(addr_t addr, void *dst, size_t 
dst_len,
   return dst_len;
 }
 
+llvm::SmallVector<llvm::MutableArrayRef<uint8_t>>
+MemoryCache::ReadRanges(llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges,
+                        llvm::MutableArrayRef<uint8_t> buffer) {
+  std::lock_guard<std::recursive_mutex> guard(m_mutex);
+
+  llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> results;
+  results.reserve(ranges.size());
+  llvm::SmallVector<Range<lldb::addr_t, size_t>> missed_ranges;
+
+  // Iterate once serving requests from L1.
+  for (auto range : ranges) {
+    const lldb::addr_t addr = range.GetRangeBase();
+    const size_t len = range.GetByteSize();
+
+    if (m_invalid_ranges.FindEntryThatContains(addr)) {
+      results.push_back(buffer.take_front(0));
+      continue;
+    }
+
+    if (const uint8_t *l1_data = FindL1CacheEntry(addr, len)) {
+      results.push_back(buffer.take_front(len));
+      buffer = buffer.drop_front(len);
+      memcpy(results.back().data(), l1_data, len);
+      continue;
+    }
+
+    // Use a nullptr to denote this needs fetching.
+    results.emplace_back(nullptr, nullptr);
+    missed_ranges.push_back(range);
+  }
+
+  if (missed_ranges.empty())
+    return results;
+
+  auto fetched_buffers = m_process.DoReadMemoryRanges(missed_ranges, buffer);
+
+  for (auto [missed_range, fetched] : llvm::zip(missed_ranges, 
fetched_buffers))
+    AddL1CacheData(missed_range.GetRangeBase(), fetched);
+
+  auto *results_it = results.begin();
+  auto *end = results.end();
+  for (auto fetched : fetched_buffers) {
+    results_it = std::find_if(
+        results_it, end, [](auto result) { return result.data() == nullptr; });
+    assert(results_it != end);
+    *results_it = fetched;
+  }
+
+  return results;
+}
+
 AllocatedBlock::AllocatedBlock(lldb::addr_t addr, uint32_t byte_size,
                                uint32_t permissions, uint32_t chunk_size)
     : m_range(addr, byte_size), m_permissions(permissions),
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index e77cb0b0835e1..ac1357f7d00a1 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -2077,6 +2077,8 @@ 
Process::ReadMemoryRanges(llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges,
   for (const Range<lldb::addr_t, size_t> &range : ranges)
     fixed_ranges.emplace_back(FixAnyAddress(range.GetRangeBase()),
                               range.GetByteSize());
+  if (!GetDisableMemoryCache())
+    return m_memory_cache.ReadRanges(fixed_ranges, buffer);
   return DoReadMemoryRanges(fixed_ranges, buffer);
 }
 

>From 44770a294592554b1c52f9361573301661b65290 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <[email protected]>
Date: Wed, 3 Jun 2026 08:15:36 +0100
Subject: [PATCH 2/3] fixup! dont reuse address is tesst

---
 lldb/unittests/Target/MemoryTest.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/unittests/Target/MemoryTest.cpp 
b/lldb/unittests/Target/MemoryTest.cpp
index e2a125e7e10a9..9d04376b4fd5b 100644
--- a/lldb/unittests/Target/MemoryTest.cpp
+++ b/lldb/unittests/Target/MemoryTest.cpp
@@ -407,7 +407,7 @@ TEST_F(MemoryTest, TestReadMemoryRanges) {
   {
     llvm::SmallVector<uint8_t, 0> buffer(1024, 0);
     llvm::SmallVector<Range<addr_t, size_t>> ranges = {
-        {0x12345, 128}, {0x11112222, 128}, {0x77777777, 128}};
+        {0x6789, 128}, {0x333344444, 128}, {0x99999999, 128}};
     llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> read_results =
         dummy_process.ReadMemoryRanges(ranges, buffer);
     for (auto [range, memory] : llvm::zip(ranges, read_results)) {

>From 4028ab86a3e2a6a4f54489d5fcffcd5cca13b4a1 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <[email protected]>
Date: Wed, 3 Jun 2026 08:35:32 +0100
Subject: [PATCH 3/3] fixup! avoid find_if

---
 lldb/source/Target/Memory.cpp | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/lldb/source/Target/Memory.cpp b/lldb/source/Target/Memory.cpp
index bb563be7090d9..3684d9410b64a 100644
--- a/lldb/source/Target/Memory.cpp
+++ b/lldb/source/Target/Memory.cpp
@@ -306,19 +306,17 @@ 
MemoryCache::ReadRanges(llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges,
   if (missed_ranges.empty())
     return results;
 
-  auto fetched_buffers = m_process.DoReadMemoryRanges(missed_ranges, buffer);
+  llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> fetched_buffers_vec =
+      m_process.DoReadMemoryRanges(missed_ranges, buffer);
+  auto fetched_buffers = llvm::ArrayRef(fetched_buffers_vec);
 
   for (auto [missed_range, fetched] : llvm::zip(missed_ranges, 
fetched_buffers))
     AddL1CacheData(missed_range.GetRangeBase(), fetched);
 
-  auto *results_it = results.begin();
-  auto *end = results.end();
-  for (auto fetched : fetched_buffers) {
-    results_it = std::find_if(
-        results_it, end, [](auto result) { return result.data() == nullptr; });
-    assert(results_it != end);
-    *results_it = fetched;
-  }
+  // Use the just-fetched memory to fill in the gaps left by the cache.
+  for (auto &result : results)
+    if (result.data() == nullptr)
+      result = fetched_buffers.consume_front();
 
   return results;
 }

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to