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