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
18using namespace llvm;
19using namespace llvm::jitlink;
20using namespace llvm::orc;
21using namespace llvm::orc::shared;
22
23namespace {
24
25class CounterMapper final : public MemoryMapper {
26public:
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, OnReserved: std::move(OnReserved));
35 }
36
37 void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override {
38 ++InitCount;
39 return Mapper->initialize(AI, OnInitialized: 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, OnDeInitialized: std::move(OnDeInitialized));
50 }
51
52 void release(ArrayRef<ExecutorAddr> Reservations,
53 OnReleasedFunction OnRelease) override {
54 ++ReleaseCount;
55
56 return Mapper->release(Reservations, OnRelease: std::move(OnRelease));
57 }
58
59 int ReserveCount = 0, InitCount = 0, DeinitCount = 0, ReleaseCount = 0;
60
61private:
62 std::unique_ptr<MemoryMapper> Mapper;
63};
64
65TEST(MapperJITLinkMemoryManagerTest, InProcess) {
66 auto Mapper = std::make_unique<CounterMapper>(
67 args: cantFail(ValOrErr: InProcessMemoryMapper::Create()));
68
69 auto *Counter = static_cast<CounterMapper *>(Mapper.get());
70
71 auto MemMgr = std::make_unique<MapperJITLinkMemoryManager>(args: 16 * 1024 * 1024,
72 args: 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&: *MemMgr, JD: nullptr, Segments: {{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(AG: MemProt::Read);
86 memcpy(dest: SegInfo1.WorkingMem.data(), src: Hello.data(), n: 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&: *MemMgr, JD: nullptr, Segments: {{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(AG: MemProt::Read);
103 memcpy(dest: SegInfo2.WorkingMem.data(), src: Hello.data(), n: 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(Alloc: std::move(*FA1));
124 EXPECT_THAT_ERROR(std::move(Err2), Succeeded());
125
126 EXPECT_EQ(Counter->DeinitCount, 1);
127
128 auto Err3 = MemMgr->deallocate(Alloc: std::move(*FA2));
129 EXPECT_THAT_ERROR(std::move(Err3), Succeeded());
130
131 EXPECT_EQ(Counter->DeinitCount, 2);
132}
133
134TEST(MapperJITLinkMemoryManagerTest, Coalescing) {
135 auto Mapper = cantFail(ValOrErr: InProcessMemoryMapper::Create());
136 auto MemMgr = std::make_unique<MapperJITLinkMemoryManager>(args: 16 * 1024 * 1024,
137 args: std::move(Mapper));
138
139 auto SSA1 = jitlink::SimpleSegmentAlloc::Create(
140 MemMgr&: *MemMgr, JD: nullptr, Segments: {{MemProt::Read, {1024, Align(1)}}});
141 EXPECT_THAT_EXPECTED(SSA1, Succeeded());
142 auto SegInfo1 = SSA1->getSegInfo(AG: 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&: *MemMgr, JD: nullptr, Segments: {{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(Alloc: std::move(*FA1));
154 EXPECT_THAT_ERROR(std::move(Err2), Succeeded());
155
156 auto Err3 = MemMgr->deallocate(Alloc: std::move(*FA2));
157 EXPECT_THAT_ERROR(std::move(Err3), Succeeded());
158
159 auto SSA3 = jitlink::SimpleSegmentAlloc::Create(
160 MemMgr&: *MemMgr, JD: nullptr, Segments: {{MemProt::Read, {2048, Align(1)}}});
161 EXPECT_THAT_EXPECTED(SSA3, Succeeded());
162
163 auto SegInfo3 = SSA3->getSegInfo(AG: 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(Alloc: std::move(*FA3));
173 EXPECT_THAT_ERROR(std::move(Err4), Succeeded());
174}
175
176} // namespace
177

source code of llvm/unittests/ExecutionEngine/Orc/MapperJITLinkMemoryManagerTest.cpp