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