Files
TheRock/compiler/amd-llvm/llvm/lib/ExecutionEngine/Orc/MapperJITLinkMemoryManager.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

189 lines
5.6 KiB
C++

//=== MapperJITLinkMemoryManager.cpp - Memory management with MemoryMapper ===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/Support/Process.h"
using namespace llvm::jitlink;
namespace llvm {
namespace orc {
class MapperJITLinkMemoryManager::InFlightAlloc
: public JITLinkMemoryManager::InFlightAlloc {
public:
InFlightAlloc(MapperJITLinkMemoryManager &Parent, LinkGraph &G,
ExecutorAddr AllocAddr,
std::vector<MemoryMapper::AllocInfo::SegInfo> Segs)
: Parent(Parent), G(G), AllocAddr(AllocAddr), Segs(std::move(Segs)) {}
void finalize(OnFinalizedFunction OnFinalize) override {
MemoryMapper::AllocInfo AI;
AI.MappingBase = AllocAddr;
std::swap(AI.Segments, Segs);
std::swap(AI.Actions, G.allocActions());
Parent.Mapper->initialize(AI, [OnFinalize = std::move(OnFinalize)](
Expected<ExecutorAddr> Result) mutable {
if (!Result) {
OnFinalize(Result.takeError());
return;
}
OnFinalize(FinalizedAlloc(*Result));
});
}
void abandon(OnAbandonedFunction OnFinalize) override {
Parent.Mapper->deinitialize({AllocAddr}, std::move(OnFinalize));
}
private:
MapperJITLinkMemoryManager &Parent;
LinkGraph &G;
ExecutorAddr AllocAddr;
std::vector<MemoryMapper::AllocInfo::SegInfo> Segs;
};
MapperJITLinkMemoryManager::MapperJITLinkMemoryManager(
size_t ReservationGranularity, std::unique_ptr<MemoryMapper> Mapper)
: ReservationUnits(ReservationGranularity), AvailableMemory(AMAllocator),
Mapper(std::move(Mapper)) {}
void MapperJITLinkMemoryManager::allocate(const JITLinkDylib *JD, LinkGraph &G,
OnAllocatedFunction OnAllocated) {
BasicLayout BL(G);
// find required address space
auto SegsSizes = BL.getContiguousPageBasedLayoutSizes(Mapper->getPageSize());
if (!SegsSizes) {
OnAllocated(SegsSizes.takeError());
return;
}
auto TotalSize = SegsSizes->total();
auto CompleteAllocation = [this, &G, BL = std::move(BL),
OnAllocated = std::move(OnAllocated)](
Expected<ExecutorAddrRange> Result) mutable {
if (!Result) {
Mutex.unlock();
return OnAllocated(Result.takeError());
}
auto NextSegAddr = Result->Start;
std::vector<MemoryMapper::AllocInfo::SegInfo> SegInfos;
for (auto &KV : BL.segments()) {
auto &AG = KV.first;
auto &Seg = KV.second;
auto TotalSize = Seg.ContentSize + Seg.ZeroFillSize;
Seg.Addr = NextSegAddr;
Seg.WorkingMem = Mapper->prepare(G, NextSegAddr, TotalSize);
NextSegAddr += alignTo(TotalSize, Mapper->getPageSize());
MemoryMapper::AllocInfo::SegInfo SI;
SI.Offset = Seg.Addr - Result->Start;
SI.ContentSize = Seg.ContentSize;
SI.ZeroFillSize = Seg.ZeroFillSize;
SI.AG = AG;
SI.WorkingMem = Seg.WorkingMem;
SegInfos.push_back(SI);
}
UsedMemory.insert({Result->Start, NextSegAddr - Result->Start});
if (NextSegAddr < Result->End) {
// Save the remaining memory for reuse in next allocation(s)
AvailableMemory.insert(NextSegAddr, Result->End - 1, true);
}
Mutex.unlock();
if (auto Err = BL.apply()) {
OnAllocated(std::move(Err));
return;
}
OnAllocated(std::make_unique<InFlightAlloc>(*this, G, Result->Start,
std::move(SegInfos)));
};
Mutex.lock();
// find an already reserved range that is large enough
ExecutorAddrRange SelectedRange{};
for (AvailableMemoryMap::iterator It = AvailableMemory.begin();
It != AvailableMemory.end(); It++) {
if (It.stop() - It.start() + 1 >= TotalSize) {
SelectedRange = ExecutorAddrRange(It.start(), It.stop() + 1);
It.erase();
break;
}
}
if (SelectedRange.empty()) { // no already reserved range was found
auto TotalAllocation = alignTo(TotalSize, ReservationUnits);
Mapper->reserve(TotalAllocation, std::move(CompleteAllocation));
} else {
CompleteAllocation(SelectedRange);
}
}
void MapperJITLinkMemoryManager::deallocate(
std::vector<FinalizedAlloc> Allocs, OnDeallocatedFunction OnDeallocated) {
std::vector<ExecutorAddr> Bases;
Bases.reserve(Allocs.size());
for (auto &FA : Allocs) {
ExecutorAddr Addr = FA.getAddress();
Bases.push_back(Addr);
}
Mapper->deinitialize(Bases, [this, Allocs = std::move(Allocs),
OnDeallocated = std::move(OnDeallocated)](
llvm::Error Err) mutable {
// TODO: How should we treat memory that we fail to deinitialize?
// We're currently bailing out and treating it as "burned" -- should we
// require that a failure to deinitialize still reset the memory so that
// we can reclaim it?
if (Err) {
for (auto &FA : Allocs)
FA.release();
OnDeallocated(std::move(Err));
return;
}
{
std::lock_guard<std::mutex> Lock(Mutex);
for (auto &FA : Allocs) {
ExecutorAddr Addr = FA.getAddress();
ExecutorAddrDiff Size = UsedMemory[Addr];
UsedMemory.erase(Addr);
AvailableMemory.insert(Addr, Addr + Size - 1, true);
FA.release();
}
}
OnDeallocated(Error::success());
});
}
} // end namespace orc
} // end namespace llvm