================
@@ -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