================
@@ -48,7 +49,66 @@ void MemoryCache::AddL1CacheData(lldb::addr_t addr, const
void *src,
void MemoryCache::AddL1CacheData(lldb::addr_t addr,
const DataBufferSP &data_buffer_sp) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- m_L1_cache[addr] = data_buffer_sp;
+ // The L1 cache is kept as a set of non-overlapping chunks: both Flush() and
+ // FindL1CacheEntry() only inspect the single chunk whose start is closest to
+ // a given address, so they assume no two chunks cover the same address.
+ //
+ // A new chunk can overlap ones that are already cached. Merge the new chunk
+ // with every chunk it intersects into a single chunk spanning their union,
so
+ // the coverage of all of them is kept while the invariant holds. The
process
+ // is stopped while the cache is populated, so overlapping chunks hold
+ // identical bytes; where they might differ, the just fetched data wins.
+ const size_t data_byte_size = data_buffer_sp->GetByteSize();
+ // A zero-length chunk can never satisfy a read and would never be flushed,
so
+ // there is nothing to cache.
+ if (data_byte_size == 0)
+ return;
+
+ AddrRange new_range(addr, data_byte_size);
+ addr_t merged_base = new_range.GetRangeBase();
+ addr_t merged_end = new_range.GetRangeEnd();
+
+ // Chunks are ordered by start address and do not overlap, so the chunks that
+ // intersect the new one form a contiguous run. The first one that can
+ // intersect is the chunk starting at or immediately below addr; start there
+ // and walk forward while a chunk still intersects the new range.
+ BlockMap::iterator pos = m_L1_cache.upper_bound(addr);
+ if (pos != m_L1_cache.begin())
+ --pos;
+ BlockMap::iterator merge_first = m_L1_cache.end();
+ BlockMap::iterator merge_end = m_L1_cache.end();
+ while (pos != m_L1_cache.end() && pos->first < new_range.GetRangeEnd()) {
+ AddrRange chunk_range(pos->first, pos->second->GetByteSize());
+ if (chunk_range.DoesIntersect(new_range)) {
+ merged_base = std::min(merged_base, chunk_range.GetRangeBase());
+ merged_end = std::max(merged_end, chunk_range.GetRangeEnd());
+ if (merge_first == m_L1_cache.end())
+ merge_first = pos;
+ merge_end = std::next(pos);
----------------
felipepiovezan wrote:
I think you can initialize both `merge_first` and `merge_end` to the original
value of `pos` (after the decrement), and only advance `merge_end` here.
Then, at the end, you only compare `merge_first != merge_pos`.
It's a bit less branchy this way,
https://github.com/llvm/llvm-project/pull/208347
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits