xref: /llvm-project/llvm/unittests/ExecutionEngine/Orc/MapperJITLinkMemoryManagerTest.cpp (revision 4eaff6c58ae2f130ac8d63cf2c87bbb483114876)
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, std::make_shared<orc::SymbolStringPool>(),
80       Triple("x86_64-apple-darwin"), nullptr,
81       {{MemProt::Read, {Hello.size(), Align(1)}}});
82   EXPECT_THAT_EXPECTED(SSA1, Succeeded());
83 
84   EXPECT_EQ(Counter->ReserveCount, 1);
85   EXPECT_EQ(Counter->InitCount, 0);
86 
87   auto SegInfo1 = SSA1->getSegInfo(MemProt::Read);
88   memcpy(SegInfo1.WorkingMem.data(), Hello.data(), Hello.size());
89 
90   auto FA1 = SSA1->finalize();
91   EXPECT_THAT_EXPECTED(FA1, Succeeded());
92 
93   EXPECT_EQ(Counter->ReserveCount, 1);
94   EXPECT_EQ(Counter->InitCount, 1);
95 
96   auto SSA2 = jitlink::SimpleSegmentAlloc::Create(
97       *MemMgr, std::make_shared<orc::SymbolStringPool>(),
98       Triple("x86_64-apple-darwin"), nullptr,
99       {{MemProt::Read, {Hello.size(), Align(1)}}});
100   EXPECT_THAT_EXPECTED(SSA2, Succeeded());
101 
102   // last reservation should be reused
103   EXPECT_EQ(Counter->ReserveCount, 1);
104   EXPECT_EQ(Counter->InitCount, 1);
105 
106   auto SegInfo2 = SSA2->getSegInfo(MemProt::Read);
107   memcpy(SegInfo2.WorkingMem.data(), Hello.data(), Hello.size());
108   auto FA2 = SSA2->finalize();
109   EXPECT_THAT_EXPECTED(FA2, Succeeded());
110 
111   EXPECT_EQ(Counter->ReserveCount, 1);
112   EXPECT_EQ(Counter->InitCount, 2);
113 
114   ExecutorAddr TargetAddr1(SegInfo1.Addr);
115   ExecutorAddr TargetAddr2(SegInfo2.Addr);
116 
117   const char *TargetMem1 = TargetAddr1.toPtr<const char *>();
118   StringRef TargetHello1(TargetMem1, Hello.size());
119   EXPECT_EQ(Hello, TargetHello1);
120 
121   const char *TargetMem2 = TargetAddr2.toPtr<const char *>();
122   StringRef TargetHello2(TargetMem2, Hello.size());
123   EXPECT_EQ(Hello, TargetHello2);
124 
125   EXPECT_EQ(Counter->DeinitCount, 0);
126 
127   auto Err2 = MemMgr->deallocate(std::move(*FA1));
128   EXPECT_THAT_ERROR(std::move(Err2), Succeeded());
129 
130   EXPECT_EQ(Counter->DeinitCount, 1);
131 
132   auto Err3 = MemMgr->deallocate(std::move(*FA2));
133   EXPECT_THAT_ERROR(std::move(Err3), Succeeded());
134 
135   EXPECT_EQ(Counter->DeinitCount, 2);
136 }
137 
138 TEST(MapperJITLinkMemoryManagerTest, Coalescing) {
139   auto Mapper = cantFail(InProcessMemoryMapper::Create());
140   auto MemMgr = std::make_unique<MapperJITLinkMemoryManager>(16 * 1024 * 1024,
141                                                              std::move(Mapper));
142   auto SSP = std::make_shared<orc::SymbolStringPool>();
143 
144   auto SSA1 = jitlink::SimpleSegmentAlloc::Create(
145       *MemMgr, SSP, Triple("x86_64-apple-darwin"), nullptr,
146       {{MemProt::Read, {1024, Align(1)}}});
147   EXPECT_THAT_EXPECTED(SSA1, Succeeded());
148   auto SegInfo1 = SSA1->getSegInfo(MemProt::Read);
149   ExecutorAddr TargetAddr1(SegInfo1.Addr);
150   auto FA1 = SSA1->finalize();
151   EXPECT_THAT_EXPECTED(FA1, Succeeded());
152 
153   auto SSA2 = jitlink::SimpleSegmentAlloc::Create(
154       *MemMgr, SSP, Triple("x86_64-apple-darwin"), nullptr,
155       {{MemProt::Read, {1024, Align(1)}}});
156   EXPECT_THAT_EXPECTED(SSA2, Succeeded());
157   auto FA2 = SSA2->finalize();
158   EXPECT_THAT_EXPECTED(FA2, Succeeded());
159 
160   auto Err2 = MemMgr->deallocate(std::move(*FA1));
161   EXPECT_THAT_ERROR(std::move(Err2), Succeeded());
162 
163   auto Err3 = MemMgr->deallocate(std::move(*FA2));
164   EXPECT_THAT_ERROR(std::move(Err3), Succeeded());
165 
166   auto SSA3 = jitlink::SimpleSegmentAlloc::Create(
167       *MemMgr, SSP, Triple("x86_64-apple-darwin"), nullptr,
168       {{MemProt::Read, {2048, Align(1)}}});
169   EXPECT_THAT_EXPECTED(SSA3, Succeeded());
170 
171   auto SegInfo3 = SSA3->getSegInfo(MemProt::Read);
172   ExecutorAddr TargetAddr3(SegInfo3.Addr);
173 
174   auto FA3 = SSA3->finalize();
175   EXPECT_THAT_EXPECTED(FA3, Succeeded());
176 
177   // previous two freed 1024 blocks should be fused to form a 2048 block
178   EXPECT_EQ(TargetAddr1, TargetAddr3);
179 
180   auto Err4 = MemMgr->deallocate(std::move(*FA3));
181   EXPECT_THAT_ERROR(std::move(Err4), Succeeded());
182 }
183 
184 } // namespace
185