================
@@ -489,6 +496,188 @@ TEST_F(MemoryTest, TestReadStopsAtAnInvalidRange) {
   EXPECT_TRUE(process->m_reads.empty());
 }
 
+TEST_F(MemoryTest, TestReadRangesFromCaches) {
+  CacheTestProcess proc;
+  ASSERT_TRUE(proc.GetProcess());
+  DummyProcess *process = proc.GetProcess();
+  const lldb::addr_t line = proc.GetLine();
+
+  { // An entry serves a range only if it covers it all.  A short fetch is all
+    // the caller sees and all L1 keeps of the range it was for.
+    TestMemoryCache cache(*process);
+    AddCacheChunk(cache, 0xB000, 40, 0xAA);
+    AddCacheChunk(cache, 0xC000, 8, 0xCC);
+    process->SetMaxReadSize(20);
+    process->SetFiller(0xBB);
+    process->m_reads.clear();
+    llvm::SmallVector<uint8_t, 0> buffer(72, 0);
+    llvm::SmallVector<Range<addr_t, size_t>> ranges = {{0xB000, 64},
+                                                       {0xC000, 8}};
+    llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> results =
+        cache.ReadRanges(ranges, buffer);
+    ASSERT_EQ(results.size(), 2u);
+    ASSERT_EQ(results[0].size(), 20u);
+    EXPECT_TRUE(AllBytesAre(results[0], 0xBB));
+    ASSERT_EQ(results[1].size(), 8u);
+    EXPECT_TRUE(AllBytesAre(results[1], 0xCC));
+    // A short reply is retried for the remainder, here with no bytes left.
+    ASSERT_EQ(process->m_reads.size(), 2u);
+    EXPECT_EQ(process->m_reads[0].first, 0xB000u);
+    EXPECT_EQ(process->m_reads[0].second, 64u);
+    EXPECT_EQ(process->m_reads[1].first, 0xB000u + 20u);
+    EXPECT_EQ(process->m_reads[1].second, 64u - 20u);
+
+    ASSERT_EQ(cache.GetL1Cache().size(), 2u);
+    EXPECT_EQ(cache.GetL1Cache().count(0xB000), 1u);
+    EXPECT_EQ(cache.GetL1Cache().count(0xC000), 1u);
+
+    auto l1cache_line = cache.GetL1Cache().at(0xB000);
+    // was 40 bytes of 0xAA
+    EXPECT_EQ(l1cache_line->GetByteSize(), 20u);
+    EXPECT_TRUE(AllBytesAre(l1cache_line->GetData(), 0xBB));
+    l1cache_line = cache.GetL1Cache().at(0xC000);
+    EXPECT_EQ(l1cache_line->GetByteSize(), 8u);
+    EXPECT_TRUE(AllBytesAre(l1cache_line->GetData(), 0xCC));
+  }
+
+  { // A range ReadRanges fetched is cached, so asking for it again serves it
+    // without going to the inferior.
+    TestMemoryCache cache(*process);
+    process->SetMaxReadSize(4 * line);
+    process->SetFiller(0xBB);
+    process->m_reads.clear();
+    llvm::SmallVector<uint8_t, 0> buffer(24, 0);
+    llvm::SmallVector<Range<addr_t, size_t>> ranges = {{0x16000, 24}};
+    llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> results =
+        cache.ReadRanges(ranges, buffer);
+    ASSERT_EQ(results.size(), 1u);
+    ASSERT_EQ(results[0].size(), 24u);
+    EXPECT_TRUE(AllBytesAre(results[0], 0xBB));
+    ASSERT_FALSE(process->m_reads.empty());
+
+    process->SetMaxReadSize(0);
+    process->m_reads.clear();
+    llvm::SmallVector<uint8_t, 0> again(24, 0);
+    llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> second =
+        cache.ReadRanges(ranges, again);
+    ASSERT_EQ(second.size(), 1u);
+    ASSERT_EQ(second[0].size(), 24u);
+    EXPECT_TRUE(AllBytesAre(second[0], 0xBB));
+    EXPECT_TRUE(process->m_reads.empty());
+  }
+
+  { // A range inside an invalid range gets an empty result without reaching 
the
+    // inferior, and leaves the ranges on either side of it alone.
+    TestMemoryCache cache(*process);
+    AddCacheChunk(cache, 0x17000, 8, 0xAA);
+    cache.AddInvalidRange(0x17100, 8);
+    process->SetMaxReadSize(4 * line);
+    process->SetFiller(0xBB);
+    process->m_reads.clear();
+    llvm::SmallVector<uint8_t, 0> buffer(24, 0);
+    llvm::SmallVector<Range<addr_t, size_t>> ranges = {
+        {0x17000, 8}, {0x17100, 8}, {0x17200, 8}};
+    llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> results =
+        cache.ReadRanges(ranges, buffer);
+    ASSERT_EQ(results.size(), 3u);
+    ASSERT_EQ(results[0].size(), 8u); // a cache hit
+    EXPECT_TRUE(AllBytesAre(results[0], 0xAA));
+    EXPECT_TRUE(results[1].empty());  // the invalid range
+    ASSERT_EQ(results[2].size(), 8u); // a miss, fetched
+    EXPECT_TRUE(AllBytesAre(results[2], 0xBB));
+    // Only the miss reached the inferior.
+    ASSERT_EQ(process->m_reads.size(), 1u);
+    EXPECT_EQ(process->m_reads[0].first, 0x17200u);
+    EXPECT_EQ(process->m_reads[0].second, 8u);
+  }
+}
+
+TEST_F(MemoryTest, TestReadRequestShape) {
+  CacheTestProcess proc;
+  ASSERT_TRUE(proc.GetProcess());
+  DummyProcess *process = proc.GetProcess();
+  const lldb::addr_t line = proc.GetLine();
----------------
qiyao wrote:

That makes sense to me.  I made the change `lldb::addr_t GetLine()` -> 
`uint64_t GetLineSize()` in the follow up commit.

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

Reply via email to