xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/MapperJITLinkMemoryManagerTest.cpp (revision d3d9f7caf96680dad4ef0fd108e64ca044a0a113)
1 //===---------------- MapperJITLinkMemoryManagerTest.cpp ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "OrcTestCommon.h"
10 
11 #include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
12 
13 #include "llvm/ExecutionEngine/Orc/MemoryMapper.h"
14 #include "llvm/Testing/Support/Error.h"
15 
16 #include <vector>
17 
18 using namespace llvm;
19 using namespace llvm::jitlink;
20 using namespace llvm::orc;
21 using namespace llvm::orc::shared;
22 
23 namespace {
24 
25 class CounterMapper final : public MemoryMapper {
26 public:
27   CounterMapper(std::unique_ptr<MemoryMapper> Mapper)
28       : Mapper(std::move(Mapper)) {}
29 
30   unsigned int getPageSize() override { return Mapper->getPageSize(); }
31 
32   void reserve(size_t NumBytes, OnReservedFunction OnReserved) override {
33     ++ReserveCount;
34     return Mapper->reserve(NumBytes, std::move(OnReserved));
35   }
36 
37   void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override {
38     ++InitCount;
39     return Mapper->initialize(AI, std::move(OnInitialized));
40   }
41 
42   char *prepare(ExecutorAddr Addr, size_t ContentSize) override {
43     return Mapper->prepare(Addr, ContentSize);
44   }
45 
46   void deinitialize(ArrayRef<ExecutorAddr> Allocations,
47                     OnDeinitializedFunction OnDeInitialized) override {
48     ++DeinitCount;
49     return Mapper->deinitialize(Allocations, std::move(OnDeInitialized));
50   }
51 
52   void release(ArrayRef<ExecutorAddr> Reservations,
53                OnReleasedFunction OnRelease) override {
54     ++ReleaseCount;
55 
56     return Mapper->release(Reservations, std::move(OnRelease));
57   }
58 
59   int ReserveCount = 0, InitCount = 0, DeinitCount = 0, ReleaseCount = 0;
60 
61 private:
62   std::unique_ptr<MemoryMapper> Mapper;
63 };
64 
65 TEST(MapperJITLinkMemoryManagerTest, InProcess) {
66   auto Mapper = std::make_unique<CounterMapper>(
67       cantFail(InProcessMemoryMapper::Create()));
68 
69   auto *Counter = static_cast<CounterMapper *>(Mapper.get());
70 
71   auto MemMgr = std::make_unique<MapperJITLinkMemoryManager>(16 * 1024 * 1024,
72                                                              std::move(Mapper));
73 
74   EXPECT_EQ(Counter->ReserveCount, 0);
75   EXPECT_EQ(Counter->InitCount, 0);
76 
77   StringRef Hello = "hello";
78   auto SSA1 = jitlink::SimpleSegmentAlloc::Create(
79       *MemMgr, nullptr, {{MemProt::Read, {Hello.size(), Align(1)}}});
80   EXPECT_THAT_EXPECTED(SSA1, Succeeded());
81 
82   EXPECT_EQ(Counter->ReserveCount, 1);
83   EXPECT_EQ(Counter->InitCount, 0);
84 
85   auto SegInfo1 = SSA1->getSegInfo(MemProt::Read);
86   memcpy(SegInfo1.WorkingMem.data(), Hello.data(), Hello.size());
87 
88   auto FA1 = SSA1->finalize();
89   EXPECT_THAT_EXPECTED(FA1, Succeeded());
90 
91   EXPECT_EQ(Counter->ReserveCount, 1);
92   EXPECT_EQ(Counter->InitCount, 1);
93 
94   auto SSA2 = jitlink::SimpleSegmentAlloc::Create(
95       *MemMgr, nullptr, {{MemProt::Read, {Hello.size(), Align(1)}}});
96   EXPECT_THAT_EXPECTED(SSA2, Succeeded());
97 
98   // last reservation should be reused
99   EXPECT_EQ(Counter->ReserveCount, 1);
100   EXPECT_EQ(Counter->InitCount, 1);
101 
102   auto SegInfo2 = SSA2->getSegInfo(MemProt::Read);
103   memcpy(SegInfo2.WorkingMem.data(), Hello.data(), Hello.size());
104   auto FA2 = SSA2->finalize();
105   EXPECT_THAT_EXPECTED(FA2, Succeeded());
106 
107   EXPECT_EQ(Counter->ReserveCount, 1);
108   EXPECT_EQ(Counter->InitCount, 2);
109 
110   ExecutorAddr TargetAddr1(SegInfo1.Addr);
111   ExecutorAddr TargetAddr2(SegInfo2.Addr);
112 
113   const char *TargetMem1 = TargetAddr1.toPtr<const char *>();
114   StringRef TargetHello1(TargetMem1, Hello.size());
115   EXPECT_EQ(Hello, TargetHello1);
116 
117   const char *TargetMem2 = TargetAddr2.toPtr<const char *>();
118   StringRef TargetHello2(TargetMem2, Hello.size());
119   EXPECT_EQ(Hello, TargetHello2);
120 
121   EXPECT_EQ(Counter->DeinitCount, 0);
122 
123   auto Err2 = MemMgr->deallocate(std::move(*FA1));
124   EXPECT_THAT_ERROR(std::move(Err2), Succeeded());
125 
126   EXPECT_EQ(Counter->DeinitCount, 1);
127 
128   auto Err3 = MemMgr->deallocate(std::move(*FA2));
129   EXPECT_THAT_ERROR(std::move(Err3), Succeeded());
130 
131   EXPECT_EQ(Counter->DeinitCount, 2);
132 }
133 
134 TEST(MapperJITLinkMemoryManagerTest, Coalescing) {
135   auto Mapper = cantFail(InProcessMemoryMapper::Create());
136   auto MemMgr = std::make_unique<MapperJITLinkMemoryManager>(16 * 1024 * 1024,
137                                                              std::move(Mapper));
138 
139   auto SSA1 = jitlink::SimpleSegmentAlloc::Create(
140       *MemMgr, nullptr, {{MemProt::Read, {1024, Align(1)}}});
141   EXPECT_THAT_EXPECTED(SSA1, Succeeded());
142   auto SegInfo1 = SSA1->getSegInfo(MemProt::Read);
143   ExecutorAddr TargetAddr1(SegInfo1.Addr);
144   auto FA1 = SSA1->finalize();
145   EXPECT_THAT_EXPECTED(FA1, Succeeded());
146 
147   auto SSA2 = jitlink::SimpleSegmentAlloc::Create(
148       *MemMgr, nullptr, {{MemProt::Read, {1024, Align(1)}}});
149   EXPECT_THAT_EXPECTED(SSA2, Succeeded());
150   auto FA2 = SSA2->finalize();
151   EXPECT_THAT_EXPECTED(FA2, Succeeded());
152 
153   auto Err2 = MemMgr->deallocate(std::move(*FA1));
154   EXPECT_THAT_ERROR(std::move(Err2), Succeeded());
155 
156   auto Err3 = MemMgr->deallocate(std::move(*FA2));
157   EXPECT_THAT_ERROR(std::move(Err3), Succeeded());
158 
159   auto SSA3 = jitlink::SimpleSegmentAlloc::Create(
160       *MemMgr, nullptr, {{MemProt::Read, {2048, Align(1)}}});
161   EXPECT_THAT_EXPECTED(SSA3, Succeeded());
162 
163   auto SegInfo3 = SSA3->getSegInfo(MemProt::Read);
164   ExecutorAddr TargetAddr3(SegInfo3.Addr);
165 
166   auto FA3 = SSA3->finalize();
167   EXPECT_THAT_EXPECTED(FA3, Succeeded());
168 
169   // previous two freed 1024 blocks should be fused to form a 2048 block
170   EXPECT_EQ(TargetAddr1, TargetAddr3);
171 
172   auto Err4 = MemMgr->deallocate(std::move(*FA3));
173   EXPECT_THAT_ERROR(std::move(Err4), Succeeded());
174 }
175 
176 } // namespace
177