brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.1 KiB · 1174493 Raw
207 lines · cpp
1//===------------------------ MemoryMapperTest.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 "llvm/ExecutionEngine/Orc/MemoryMapper.h"10#include "llvm/ExecutionEngine/JITLink/JITLink.h"11#include "llvm/Support/Process.h"12#include "llvm/Testing/Support/Error.h"13#include "gtest/gtest.h"14 15using namespace llvm;16using namespace llvm::orc;17using namespace llvm::orc::shared;18 19namespace {20 21Expected<ExecutorAddrRange> reserve(MemoryMapper &M, size_t NumBytes) {22  std::promise<MSVCPExpected<ExecutorAddrRange>> P;23  auto F = P.get_future();24  M.reserve(NumBytes, [&](auto R) { P.set_value(std::move(R)); });25  return F.get();26}27 28Expected<ExecutorAddr> initialize(MemoryMapper &M,29                                  MemoryMapper::AllocInfo &AI) {30  std::promise<MSVCPExpected<ExecutorAddr>> P;31  auto F = P.get_future();32  M.initialize(AI, [&](auto R) { P.set_value(std::move(R)); });33  return F.get();34}35 36Error deinitialize(MemoryMapper &M,37                   const std::vector<ExecutorAddr> &Allocations) {38  std::promise<MSVCPError> P;39  auto F = P.get_future();40  M.deinitialize(Allocations, [&](auto R) { P.set_value(std::move(R)); });41  return F.get();42}43 44Error release(MemoryMapper &M, const std::vector<ExecutorAddr> &Reservations) {45  std::promise<MSVCPError> P;46  auto F = P.get_future();47  M.release(Reservations, [&](auto R) { P.set_value(std::move(R)); });48  return F.get();49}50 51// A basic function to be used as both initializer/deinitializer52CWrapperFunctionResult incrementWrapper(const char *ArgData, size_t ArgSize) {53  return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(54             ArgData, ArgSize,55             [](ExecutorAddr A) -> Error {56               *A.toPtr<int *>() += 1;57               return Error::success();58             })59      .release();60}61 62TEST(MemoryMapperTest, InitializeDeinitialize) {63  // These counters are used to track how many times the initializer and64  // deinitializer functions are called65  int InitializeCounter = 0;66  int DeinitializeCounter = 0;67  {68    std::unique_ptr<MemoryMapper> Mapper =69        cantFail(InProcessMemoryMapper::Create());70    jitlink::LinkGraph G("G", std::make_shared<SymbolStringPool>(),71                         Triple("x86_64-apple-darwin"), SubtargetFeatures(),72                         jitlink::getGenericEdgeKindName);73 74    // We will do two separate allocations75    auto PageSize = Mapper->getPageSize();76    auto TotalSize = PageSize * 2;77 78    // Reserve address space79    auto Mem1 = reserve(*Mapper, TotalSize);80    EXPECT_THAT_ERROR(Mem1.takeError(), Succeeded());81 82    // Test string for memory transfer83    std::string HW = "Hello, world!";84 85    {86      // Provide working memory87      char *WA1 = Mapper->prepare(G, Mem1->Start, HW.size() + 1);88      std::strcpy(WA1, HW.c_str());89    }90 91    // A structure to be passed to initialize92    MemoryMapper::AllocInfo Alloc1;93    {94      MemoryMapper::AllocInfo::SegInfo Seg1;95      Seg1.Offset = 0;96      Seg1.ContentSize = HW.size();97      Seg1.ZeroFillSize = PageSize - Seg1.ContentSize;98      Seg1.AG = MemProt::Read | MemProt::Write;99 100      Alloc1.MappingBase = Mem1->Start;101      Alloc1.Segments.push_back(Seg1);102      Alloc1.Actions.push_back(103          {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(104               ExecutorAddr::fromPtr(incrementWrapper),105               ExecutorAddr::fromPtr(&InitializeCounter))),106           cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(107               ExecutorAddr::fromPtr(incrementWrapper),108               ExecutorAddr::fromPtr(&DeinitializeCounter)))});109    }110 111    {112      char *WA2 = Mapper->prepare(G, Mem1->Start + PageSize, HW.size() + 1);113      std::strcpy(WA2, HW.c_str());114    }115 116    MemoryMapper::AllocInfo Alloc2;117    {118      MemoryMapper::AllocInfo::SegInfo Seg2;119      Seg2.Offset = PageSize;120      Seg2.ContentSize = HW.size();121      Seg2.ZeroFillSize = PageSize - Seg2.ContentSize;122      Seg2.AG = MemProt::Read | MemProt::Write;123 124      Alloc2.MappingBase = Mem1->Start;125      Alloc2.Segments.push_back(Seg2);126      Alloc2.Actions.push_back(127          {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(128               ExecutorAddr::fromPtr(incrementWrapper),129               ExecutorAddr::fromPtr(&InitializeCounter))),130           cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(131               ExecutorAddr::fromPtr(incrementWrapper),132               ExecutorAddr::fromPtr(&DeinitializeCounter)))});133    }134 135    EXPECT_EQ(InitializeCounter, 0);136    EXPECT_EQ(DeinitializeCounter, 0);137 138    // Set memory protections and run initializers139    auto Init1 = initialize(*Mapper, Alloc1);140    EXPECT_THAT_ERROR(Init1.takeError(), Succeeded());141    EXPECT_EQ(HW, std::string(static_cast<char *>(Init1->toPtr<char *>())));142 143    EXPECT_EQ(InitializeCounter, 1);144    EXPECT_EQ(DeinitializeCounter, 0);145 146    auto Init2 = initialize(*Mapper, Alloc2);147    EXPECT_THAT_ERROR(Init2.takeError(), Succeeded());148    EXPECT_EQ(HW, std::string(static_cast<char *>(Init2->toPtr<char *>())));149 150    EXPECT_EQ(InitializeCounter, 2);151    EXPECT_EQ(DeinitializeCounter, 0);152 153    // Explicit deinitialization of first allocation154    std::vector<ExecutorAddr> DeinitAddr = {*Init1};155    EXPECT_THAT_ERROR(deinitialize(*Mapper, DeinitAddr), Succeeded());156 157    EXPECT_EQ(InitializeCounter, 2);158    EXPECT_EQ(DeinitializeCounter, 1);159 160    // Test explicit release161    {162      auto Mem2 = reserve(*Mapper, PageSize);163      EXPECT_THAT_ERROR(Mem2.takeError(), Succeeded());164 165      char *WA = Mapper->prepare(G, Mem2->Start, HW.size() + 1);166      std::strcpy(WA, HW.c_str());167 168      MemoryMapper::AllocInfo Alloc3;169      {170        MemoryMapper::AllocInfo::SegInfo Seg3;171        Seg3.Offset = 0;172        Seg3.ContentSize = HW.size();173        Seg3.ZeroFillSize = PageSize - Seg3.ContentSize;174        Seg3.AG = MemProt::Read | MemProt::Write;175 176        Alloc3.MappingBase = Mem2->Start;177        Alloc3.Segments.push_back(Seg3);178        Alloc3.Actions.push_back(179            {cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(180                 ExecutorAddr::fromPtr(incrementWrapper),181                 ExecutorAddr::fromPtr(&InitializeCounter))),182             cantFail(WrapperFunctionCall::Create<SPSArgList<SPSExecutorAddr>>(183                 ExecutorAddr::fromPtr(incrementWrapper),184                 ExecutorAddr::fromPtr(&DeinitializeCounter)))});185      }186      auto Init3 = initialize(*Mapper, Alloc3);187      EXPECT_THAT_ERROR(Init3.takeError(), Succeeded());188      EXPECT_EQ(HW, std::string(static_cast<char *>(Init3->toPtr<char *>())));189 190      EXPECT_EQ(InitializeCounter, 3);191      EXPECT_EQ(DeinitializeCounter, 1);192 193      std::vector<ExecutorAddr> ReleaseAddrs = {Mem2->Start};194      EXPECT_THAT_ERROR(release(*Mapper, ReleaseAddrs), Succeeded());195 196      EXPECT_EQ(InitializeCounter, 3);197      EXPECT_EQ(DeinitializeCounter, 2);198    }199  }200 201  // Implicit deinitialization by the destructor202  EXPECT_EQ(InitializeCounter, 3);203  EXPECT_EQ(DeinitializeCounter, 3);204}205 206} // namespace207