1 //===---------------- MapperJITLinkMemoryManagerTest.cpp ------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "OrcTestCommon.h"
11 #include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
13 #include "llvm/ExecutionEngine/Orc/MemoryMapper.h"
14 #include "llvm/Testing/Support/Error.h"
19 using namespace llvm::jitlink
;
20 using namespace llvm::orc
;
21 using namespace llvm::orc::shared
;
25 class CounterMapper final
: public MemoryMapper
{
27 CounterMapper(std::unique_ptr
<MemoryMapper
> Mapper
)
28 : Mapper(std::move(Mapper
)) {}
30 unsigned int getPageSize() override
{ return Mapper
->getPageSize(); }
32 void reserve(size_t NumBytes
, OnReservedFunction OnReserved
) override
{
34 return Mapper
->reserve(NumBytes
, std::move(OnReserved
));
37 void initialize(AllocInfo
&AI
, OnInitializedFunction OnInitialized
) override
{
39 return Mapper
->initialize(AI
, std::move(OnInitialized
));
42 char *prepare(ExecutorAddr Addr
, size_t ContentSize
) override
{
43 return Mapper
->prepare(Addr
, ContentSize
);
46 void deinitialize(ArrayRef
<ExecutorAddr
> Allocations
,
47 OnDeinitializedFunction OnDeInitialized
) override
{
49 return Mapper
->deinitialize(Allocations
, std::move(OnDeInitialized
));
52 void release(ArrayRef
<ExecutorAddr
> Reservations
,
53 OnReleasedFunction OnRelease
) override
{
56 return Mapper
->release(Reservations
, std::move(OnRelease
));
59 int ReserveCount
= 0, InitCount
= 0, DeinitCount
= 0, ReleaseCount
= 0;
62 std::unique_ptr
<MemoryMapper
> Mapper
;
65 TEST(MapperJITLinkMemoryManagerTest
, InProcess
) {
66 auto Mapper
= std::make_unique
<CounterMapper
>(
67 cantFail(InProcessMemoryMapper::Create()));
69 auto *Counter
= static_cast<CounterMapper
*>(Mapper
.get());
71 auto MemMgr
= std::make_unique
<MapperJITLinkMemoryManager
>(16 * 1024 * 1024,
74 EXPECT_EQ(Counter
->ReserveCount
, 0);
75 EXPECT_EQ(Counter
->InitCount
, 0);
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());
82 EXPECT_EQ(Counter
->ReserveCount
, 1);
83 EXPECT_EQ(Counter
->InitCount
, 0);
85 auto SegInfo1
= SSA1
->getSegInfo(MemProt::Read
);
86 memcpy(SegInfo1
.WorkingMem
.data(), Hello
.data(), Hello
.size());
88 auto FA1
= SSA1
->finalize();
89 EXPECT_THAT_EXPECTED(FA1
, Succeeded());
91 EXPECT_EQ(Counter
->ReserveCount
, 1);
92 EXPECT_EQ(Counter
->InitCount
, 1);
94 auto SSA2
= jitlink::SimpleSegmentAlloc::Create(
95 *MemMgr
, nullptr, {{MemProt::Read
, {Hello
.size(), Align(1)}}});
96 EXPECT_THAT_EXPECTED(SSA2
, Succeeded());
98 // last reservation should be reused
99 EXPECT_EQ(Counter
->ReserveCount
, 1);
100 EXPECT_EQ(Counter
->InitCount
, 1);
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());
107 EXPECT_EQ(Counter
->ReserveCount
, 1);
108 EXPECT_EQ(Counter
->InitCount
, 2);
110 ExecutorAddr
TargetAddr1(SegInfo1
.Addr
);
111 ExecutorAddr
TargetAddr2(SegInfo2
.Addr
);
113 const char *TargetMem1
= TargetAddr1
.toPtr
<const char *>();
114 StringRef
TargetHello1(TargetMem1
, Hello
.size());
115 EXPECT_EQ(Hello
, TargetHello1
);
117 const char *TargetMem2
= TargetAddr2
.toPtr
<const char *>();
118 StringRef
TargetHello2(TargetMem2
, Hello
.size());
119 EXPECT_EQ(Hello
, TargetHello2
);
121 EXPECT_EQ(Counter
->DeinitCount
, 0);
123 auto Err2
= MemMgr
->deallocate(std::move(*FA1
));
124 EXPECT_THAT_ERROR(std::move(Err2
), Succeeded());
126 EXPECT_EQ(Counter
->DeinitCount
, 1);
128 auto Err3
= MemMgr
->deallocate(std::move(*FA2
));
129 EXPECT_THAT_ERROR(std::move(Err3
), Succeeded());
131 EXPECT_EQ(Counter
->DeinitCount
, 2);
134 TEST(MapperJITLinkMemoryManagerTest
, Coalescing
) {
135 auto Mapper
= cantFail(InProcessMemoryMapper::Create());
136 auto MemMgr
= std::make_unique
<MapperJITLinkMemoryManager
>(16 * 1024 * 1024,
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());
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());
153 auto Err2
= MemMgr
->deallocate(std::move(*FA1
));
154 EXPECT_THAT_ERROR(std::move(Err2
), Succeeded());
156 auto Err3
= MemMgr
->deallocate(std::move(*FA2
));
157 EXPECT_THAT_ERROR(std::move(Err3
), Succeeded());
159 auto SSA3
= jitlink::SimpleSegmentAlloc::Create(
160 *MemMgr
, nullptr, {{MemProt::Read
, {2048, Align(1)}}});
161 EXPECT_THAT_EXPECTED(SSA3
, Succeeded());
163 auto SegInfo3
= SSA3
->getSegInfo(MemProt::Read
);
164 ExecutorAddr
TargetAddr3(SegInfo3
.Addr
);
166 auto FA3
= SSA3
->finalize();
167 EXPECT_THAT_EXPECTED(FA3
, Succeeded());
169 // previous two freed 1024 blocks should be fused to form a 2048 block
170 EXPECT_EQ(TargetAddr1
, TargetAddr3
);
172 auto Err4
= MemMgr
->deallocate(std::move(*FA3
));
173 EXPECT_THAT_ERROR(std::move(Err4
), Succeeded());