From 6641d29b70993bce6dbd7e0e0f1040753d38842f Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Mon, 11 Oct 2021 19:23:41 -0700 Subject: Revert "[JITLink][ORC] Major JITLinkMemoryManager refactor." This reverts commit e50aea58d59c8cfae807a7fee21c4227472c0678 while I investigate bot failures. --- .../Orc/DebugObjectManagerPlugin.cpp | 135 ++++++++++----------- 1 file changed, 63 insertions(+), 72 deletions(-) (limited to 'llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp') diff --git a/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp index fcfe389..36efc744 100644 --- a/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp +++ b/llvm/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp @@ -1,15 +1,10 @@ -//===------- DebugObjectManagerPlugin.cpp - JITLink debug objects ---------===// +//===---- DebugObjectManagerPlugin.h - JITLink debug objects ---*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// -// -// FIXME: Update Plugin to poke the debug object into a new JITLink section, -// rather than creating a new allocation. -// -//===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h" @@ -113,77 +108,70 @@ void ELFDebugObjectSection::dump(raw_ostream &OS, StringRef Name) { } } +static constexpr sys::Memory::ProtectionFlags ReadOnly = + static_cast(sys::Memory::MF_READ); + enum class Requirement { // Request final target memory load-addresses for all sections. ReportFinalSectionLoadAddresses, }; -/// The plugin creates a debug object from when JITLink starts processing the -/// corresponding LinkGraph. It provides access to the pass configuration of -/// the LinkGraph and calls the finalization function, once the resulting link -/// artifact was emitted. +/// The plugin creates a debug object from JITLinkContext when JITLink starts +/// processing the corresponding LinkGraph. It provides access to the pass +/// configuration of the LinkGraph and calls the finalization function, once +/// the resulting link artifact was emitted. /// class DebugObject { public: - DebugObject(JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD, - ExecutionSession &ES) - : MemMgr(MemMgr), JD(JD), ES(ES) {} + DebugObject(JITLinkContext &Ctx, ExecutionSession &ES) : Ctx(Ctx), ES(ES) {} void set(Requirement Req) { Reqs.insert(Req); } bool has(Requirement Req) const { return Reqs.count(Req) > 0; } - using FinalizeContinuation = std::function)>; - + using FinalizeContinuation = std::function)>; void finalizeAsync(FinalizeContinuation OnFinalize); virtual ~DebugObject() { - if (Alloc) { - std::vector Allocs; - Allocs.push_back(std::move(Alloc)); - if (Error Err = MemMgr.deallocate(std::move(Allocs))) + if (Alloc) + if (Error Err = Alloc->deallocate()) ES.reportError(std::move(Err)); - } } virtual void reportSectionTargetMemoryRange(StringRef Name, SectionRange TargetMem) {} protected: - using InFlightAlloc = JITLinkMemoryManager::InFlightAlloc; - using FinalizedAlloc = JITLinkMemoryManager::FinalizedAlloc; + using Allocation = JITLinkMemoryManager::Allocation; - virtual Expected finalizeWorkingMemory() = 0; - - JITLinkMemoryManager &MemMgr; - const JITLinkDylib *JD = nullptr; + virtual Expected> + finalizeWorkingMemory(JITLinkContext &Ctx) = 0; private: + JITLinkContext &Ctx; ExecutionSession &ES; std::set Reqs; - FinalizedAlloc Alloc; + std::unique_ptr Alloc{nullptr}; }; // Finalize working memory and take ownership of the resulting allocation. Start // copying memory over to the target and pass on the result once we're done. // Ownership of the allocation remains with us for the rest of our lifetime. void DebugObject::finalizeAsync(FinalizeContinuation OnFinalize) { - assert(!Alloc && "Cannot finalize more than once"); - - if (auto SimpleSegAlloc = finalizeWorkingMemory()) { - auto ROSeg = SimpleSegAlloc->getSegInfo(MemProt::Read); - ExecutorAddrRange DebugObjRange(ExecutorAddr(ROSeg.Addr), - ExecutorAddrDiff(ROSeg.WorkingMem.size())); - SimpleSegAlloc->finalize( - [this, DebugObjRange, - OnFinalize = std::move(OnFinalize)](Expected FA) { - if (FA) { - Alloc = std::move(*FA); - OnFinalize(DebugObjRange); - } else - OnFinalize(FA.takeError()); - }); - } else - OnFinalize(SimpleSegAlloc.takeError()); + assert(Alloc == nullptr && "Cannot finalize more than once"); + + auto AllocOrErr = finalizeWorkingMemory(Ctx); + if (!AllocOrErr) + OnFinalize(AllocOrErr.takeError()); + Alloc = std::move(*AllocOrErr); + + Alloc->finalizeAsync([this, OnFinalize](Error Err) { + if (Err) + OnFinalize(std::move(Err)); + else + OnFinalize(sys::MemoryBlock( + jitTargetAddressToPointer(Alloc->getTargetMemory(ReadOnly)), + Alloc->getWorkingMemory(ReadOnly).size())); + }); } /// The current implementation of ELFDebugObject replicates the approach used in @@ -202,7 +190,8 @@ public: StringRef getBuffer() const { return Buffer->getMemBufferRef().getBuffer(); } protected: - Expected finalizeWorkingMemory() override; + Expected> + finalizeWorkingMemory(JITLinkContext &Ctx) override; template Error recordSection(StringRef Name, @@ -212,16 +201,15 @@ protected: private: template static Expected> - CreateArchType(MemoryBufferRef Buffer, JITLinkMemoryManager &MemMgr, - const JITLinkDylib *JD, ExecutionSession &ES); + CreateArchType(MemoryBufferRef Buffer, JITLinkContext &Ctx, + ExecutionSession &ES); static std::unique_ptr CopyBuffer(MemoryBufferRef Buffer, Error &Err); ELFDebugObject(std::unique_ptr Buffer, - JITLinkMemoryManager &MemMgr, const JITLinkDylib *JD, - ExecutionSession &ES) - : DebugObject(MemMgr, JD, ES), Buffer(std::move(Buffer)) { + JITLinkContext &Ctx, ExecutionSession &ES) + : DebugObject(Ctx, ES), Buffer(std::move(Buffer)) { set(Requirement::ReportFinalSectionLoadAddresses); } @@ -256,14 +244,13 @@ ELFDebugObject::CopyBuffer(MemoryBufferRef Buffer, Error &Err) { template Expected> -ELFDebugObject::CreateArchType(MemoryBufferRef Buffer, - JITLinkMemoryManager &MemMgr, - const JITLinkDylib *JD, ExecutionSession &ES) { +ELFDebugObject::CreateArchType(MemoryBufferRef Buffer, JITLinkContext &Ctx, + ExecutionSession &ES) { using SectionHeader = typename ELFT::Shdr; Error Err = Error::success(); std::unique_ptr DebugObj( - new ELFDebugObject(CopyBuffer(Buffer, Err), MemMgr, JD, ES)); + new ELFDebugObject(CopyBuffer(Buffer, Err), Ctx, ES)); if (Err) return std::move(Err); @@ -312,26 +299,23 @@ ELFDebugObject::Create(MemoryBufferRef Buffer, JITLinkContext &Ctx, if (Class == ELF::ELFCLASS32) { if (Endian == ELF::ELFDATA2LSB) - return CreateArchType(Buffer, Ctx.getMemoryManager(), - Ctx.getJITLinkDylib(), ES); + return CreateArchType(Buffer, Ctx, ES); if (Endian == ELF::ELFDATA2MSB) - return CreateArchType(Buffer, Ctx.getMemoryManager(), - Ctx.getJITLinkDylib(), ES); + return CreateArchType(Buffer, Ctx, ES); return nullptr; } if (Class == ELF::ELFCLASS64) { if (Endian == ELF::ELFDATA2LSB) - return CreateArchType(Buffer, Ctx.getMemoryManager(), - Ctx.getJITLinkDylib(), ES); + return CreateArchType(Buffer, Ctx, ES); if (Endian == ELF::ELFDATA2MSB) - return CreateArchType(Buffer, Ctx.getMemoryManager(), - Ctx.getJITLinkDylib(), ES); + return CreateArchType(Buffer, Ctx, ES); return nullptr; } return nullptr; } -Expected ELFDebugObject::finalizeWorkingMemory() { +Expected> +ELFDebugObject::finalizeWorkingMemory(JITLinkContext &Ctx) { LLVM_DEBUG({ dbgs() << "Section load-addresses in debug object for \"" << Buffer->getBufferIdentifier() << "\":\n"; @@ -340,21 +324,28 @@ Expected ELFDebugObject::finalizeWorkingMemory() { }); // TODO: This works, but what actual alignment requirements do we have? - unsigned PageSize = sys::Process::getPageSizeEstimate(); + unsigned Alignment = sys::Process::getPageSizeEstimate(); + JITLinkMemoryManager &MemMgr = Ctx.getMemoryManager(); + const JITLinkDylib *JD = Ctx.getJITLinkDylib(); size_t Size = Buffer->getBufferSize(); // Allocate working memory for debug object in read-only segment. - auto Alloc = SimpleSegmentAlloc::Create( - MemMgr, JD, {{MemProt::Read, {Size, Align(PageSize)}}}); - if (!Alloc) - return Alloc; + JITLinkMemoryManager::SegmentsRequestMap SingleReadOnlySegment; + SingleReadOnlySegment[ReadOnly] = + JITLinkMemoryManager::SegmentRequest(Alignment, Size, 0); + + auto AllocOrErr = MemMgr.allocate(JD, SingleReadOnlySegment); + if (!AllocOrErr) + return AllocOrErr.takeError(); // Initialize working memory with a copy of our object buffer. - auto SegInfo = Alloc->getSegInfo(MemProt::Read); - memcpy(SegInfo.WorkingMem.data(), Buffer->getBufferStart(), Size); + // TODO: Use our buffer as working memory directly. + std::unique_ptr Alloc = std::move(*AllocOrErr); + MutableArrayRef WorkingMem = Alloc->getWorkingMemory(ReadOnly); + memcpy(WorkingMem.data(), Buffer->getBufferStart(), Size); Buffer.reset(); - return Alloc; + return std::move(Alloc); } void ELFDebugObject::reportSectionTargetMemoryRange(StringRef Name, @@ -456,7 +447,7 @@ Error DebugObjectManagerPlugin::notifyEmitted( std::future FinalizeErr = FinalizePromise.get_future(); It->second->finalizeAsync( - [this, &FinalizePromise, &MR](Expected TargetMem) { + [this, &FinalizePromise, &MR](Expected TargetMem) { // Any failure here will fail materialization. if (!TargetMem) { FinalizePromise.set_value(TargetMem.takeError()); -- cgit v1.1