183 lines · cpp
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-exception6//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 16using namespace llvm;17using namespace llvm::jitlink;18using namespace llvm::orc;19using namespace llvm::orc::shared;20 21namespace {22 23class CounterMapper final : public MemoryMapper {24public:25 CounterMapper(std::unique_ptr<MemoryMapper> Mapper)26 : Mapper(std::move(Mapper)) {}27 28 unsigned int getPageSize() override { return Mapper->getPageSize(); }29 30 void reserve(size_t NumBytes, OnReservedFunction OnReserved) override {31 ++ReserveCount;32 return Mapper->reserve(NumBytes, std::move(OnReserved));33 }34 35 void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override {36 ++InitCount;37 return Mapper->initialize(AI, std::move(OnInitialized));38 }39 40 char *prepare(LinkGraph &G, ExecutorAddr Addr, size_t ContentSize) override {41 return Mapper->prepare(G, Addr, ContentSize);42 }43 44 void deinitialize(ArrayRef<ExecutorAddr> Allocations,45 OnDeinitializedFunction OnDeInitialized) override {46 ++DeinitCount;47 return Mapper->deinitialize(Allocations, std::move(OnDeInitialized));48 }49 50 void release(ArrayRef<ExecutorAddr> Reservations,51 OnReleasedFunction OnRelease) override {52 ++ReleaseCount;53 54 return Mapper->release(Reservations, std::move(OnRelease));55 }56 57 int ReserveCount = 0, InitCount = 0, DeinitCount = 0, ReleaseCount = 0;58 59private:60 std::unique_ptr<MemoryMapper> Mapper;61};62 63TEST(MapperJITLinkMemoryManagerTest, InProcess) {64 auto Mapper = std::make_unique<CounterMapper>(65 cantFail(InProcessMemoryMapper::Create()));66 67 auto *Counter = static_cast<CounterMapper *>(Mapper.get());68 69 auto MemMgr = std::make_unique<MapperJITLinkMemoryManager>(16 * 1024 * 1024,70 std::move(Mapper));71 72 EXPECT_EQ(Counter->ReserveCount, 0);73 EXPECT_EQ(Counter->InitCount, 0);74 75 StringRef Hello = "hello";76 auto SSA1 = jitlink::SimpleSegmentAlloc::Create(77 *MemMgr, std::make_shared<SymbolStringPool>(),78 Triple("x86_64-apple-darwin"), nullptr,79 {{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, std::make_shared<SymbolStringPool>(),96 Triple("x86_64-apple-darwin"), nullptr,97 {{MemProt::Read, {Hello.size(), Align(1)}}});98 EXPECT_THAT_EXPECTED(SSA2, Succeeded());99 100 // last reservation should be reused101 EXPECT_EQ(Counter->ReserveCount, 1);102 EXPECT_EQ(Counter->InitCount, 1);103 104 auto SegInfo2 = SSA2->getSegInfo(MemProt::Read);105 memcpy(SegInfo2.WorkingMem.data(), Hello.data(), Hello.size());106 auto FA2 = SSA2->finalize();107 EXPECT_THAT_EXPECTED(FA2, Succeeded());108 109 EXPECT_EQ(Counter->ReserveCount, 1);110 EXPECT_EQ(Counter->InitCount, 2);111 112 ExecutorAddr TargetAddr1(SegInfo1.Addr);113 ExecutorAddr TargetAddr2(SegInfo2.Addr);114 115 const char *TargetMem1 = TargetAddr1.toPtr<const char *>();116 StringRef TargetHello1(TargetMem1, Hello.size());117 EXPECT_EQ(Hello, TargetHello1);118 119 const char *TargetMem2 = TargetAddr2.toPtr<const char *>();120 StringRef TargetHello2(TargetMem2, Hello.size());121 EXPECT_EQ(Hello, TargetHello2);122 123 EXPECT_EQ(Counter->DeinitCount, 0);124 125 auto Err2 = MemMgr->deallocate(std::move(*FA1));126 EXPECT_THAT_ERROR(std::move(Err2), Succeeded());127 128 EXPECT_EQ(Counter->DeinitCount, 1);129 130 auto Err3 = MemMgr->deallocate(std::move(*FA2));131 EXPECT_THAT_ERROR(std::move(Err3), Succeeded());132 133 EXPECT_EQ(Counter->DeinitCount, 2);134}135 136TEST(MapperJITLinkMemoryManagerTest, Coalescing) {137 auto Mapper = cantFail(InProcessMemoryMapper::Create());138 auto MemMgr = std::make_unique<MapperJITLinkMemoryManager>(16 * 1024 * 1024,139 std::move(Mapper));140 auto SSP = std::make_shared<SymbolStringPool>();141 142 auto SSA1 = jitlink::SimpleSegmentAlloc::Create(143 *MemMgr, SSP, Triple("x86_64-apple-darwin"), nullptr,144 {{MemProt::Read, {1024, Align(1)}}});145 EXPECT_THAT_EXPECTED(SSA1, Succeeded());146 auto SegInfo1 = SSA1->getSegInfo(MemProt::Read);147 ExecutorAddr TargetAddr1(SegInfo1.Addr);148 auto FA1 = SSA1->finalize();149 EXPECT_THAT_EXPECTED(FA1, Succeeded());150 151 auto SSA2 = jitlink::SimpleSegmentAlloc::Create(152 *MemMgr, SSP, Triple("x86_64-apple-darwin"), nullptr,153 {{MemProt::Read, {1024, Align(1)}}});154 EXPECT_THAT_EXPECTED(SSA2, Succeeded());155 auto FA2 = SSA2->finalize();156 EXPECT_THAT_EXPECTED(FA2, Succeeded());157 158 auto Err2 = MemMgr->deallocate(std::move(*FA1));159 EXPECT_THAT_ERROR(std::move(Err2), Succeeded());160 161 auto Err3 = MemMgr->deallocate(std::move(*FA2));162 EXPECT_THAT_ERROR(std::move(Err3), Succeeded());163 164 auto SSA3 = jitlink::SimpleSegmentAlloc::Create(165 *MemMgr, SSP, Triple("x86_64-apple-darwin"), nullptr,166 {{MemProt::Read, {2048, Align(1)}}});167 EXPECT_THAT_EXPECTED(SSA3, Succeeded());168 169 auto SegInfo3 = SSA3->getSegInfo(MemProt::Read);170 ExecutorAddr TargetAddr3(SegInfo3.Addr);171 172 auto FA3 = SSA3->finalize();173 EXPECT_THAT_EXPECTED(FA3, Succeeded());174 175 // previous two freed 1024 blocks should be fused to form a 2048 block176 EXPECT_EQ(TargetAddr1, TargetAddr3);177 178 auto Err4 = MemMgr->deallocate(std::move(*FA3));179 EXPECT_THAT_ERROR(std::move(Err4), Succeeded());180}181 182} // namespace183