Home | History | Annotate | Line # | Download | only in JITLink
      1 //===-- JITLinkMemoryManager.h - JITLink mem manager interface --*- C++ -*-===//
      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 // Contains the JITLinkMemoryManager interface.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H
     14 #define LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H
     15 
     16 #include "llvm/ADT/DenseMap.h"
     17 #include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
     18 #include "llvm/ExecutionEngine/JITSymbol.h"
     19 #include "llvm/Support/Error.h"
     20 #include "llvm/Support/MSVCErrorWorkarounds.h"
     21 #include "llvm/Support/Memory.h"
     22 
     23 #include <cstdint>
     24 #include <future>
     25 
     26 namespace llvm {
     27 namespace jitlink {
     28 
     29 /// Manages allocations of JIT memory.
     30 ///
     31 /// Instances of this class may be accessed concurrently from multiple threads
     32 /// and their implemetations should include any necessary synchronization.
     33 class JITLinkMemoryManager {
     34 public:
     35   using ProtectionFlags = sys::Memory::ProtectionFlags;
     36 
     37   class SegmentRequest {
     38   public:
     39     SegmentRequest() = default;
     40     SegmentRequest(uint64_t Alignment, size_t ContentSize,
     41                    uint64_t ZeroFillSize)
     42         : Alignment(Alignment), ContentSize(ContentSize),
     43           ZeroFillSize(ZeroFillSize) {
     44       assert(isPowerOf2_32(Alignment) && "Alignment must be power of 2");
     45     }
     46     uint64_t getAlignment() const { return Alignment; }
     47     size_t getContentSize() const { return ContentSize; }
     48     uint64_t getZeroFillSize() const { return ZeroFillSize; }
     49   private:
     50     uint64_t Alignment = 0;
     51     size_t ContentSize = 0;
     52     uint64_t ZeroFillSize = 0;
     53   };
     54 
     55   using SegmentsRequestMap = DenseMap<unsigned, SegmentRequest>;
     56 
     57   /// Represents an allocation created by the memory manager.
     58   ///
     59   /// An allocation object is responsible for allocating and owning jit-linker
     60   /// working and target memory, and for transfering from working to target
     61   /// memory.
     62   ///
     63   class Allocation {
     64   public:
     65     using FinalizeContinuation = std::function<void(Error)>;
     66 
     67     virtual ~Allocation();
     68 
     69     /// Should return the address of linker working memory for the segment with
     70     /// the given protection flags.
     71     virtual MutableArrayRef<char> getWorkingMemory(ProtectionFlags Seg) = 0;
     72 
     73     /// Should return the final address in the target process where the segment
     74     /// will reside.
     75     virtual JITTargetAddress getTargetMemory(ProtectionFlags Seg) = 0;
     76 
     77     /// Should transfer from working memory to target memory, and release
     78     /// working memory.
     79     virtual void finalizeAsync(FinalizeContinuation OnFinalize) = 0;
     80 
     81     /// Calls finalizeAsync and waits for completion.
     82     Error finalize() {
     83       std::promise<MSVCPError> FinalizeResultP;
     84       auto FinalizeResultF = FinalizeResultP.get_future();
     85       finalizeAsync(
     86           [&](Error Err) { FinalizeResultP.set_value(std::move(Err)); });
     87       return FinalizeResultF.get();
     88     }
     89 
     90     /// Should deallocate target memory.
     91     virtual Error deallocate() = 0;
     92   };
     93 
     94   virtual ~JITLinkMemoryManager();
     95 
     96   /// Create an Allocation object.
     97   ///
     98   /// The JD argument represents the target JITLinkDylib, and can be used by
     99   /// JITLinkMemoryManager implementers to manage per-dylib allocation pools
    100   /// (e.g. one pre-reserved address space slab per dylib to ensure that all
    101   /// allocations for the dylib are within a certain range). The JD argument
    102   /// may be null (representing an allocation not associated with any
    103   /// JITDylib.
    104   ///
    105   /// The request argument describes the segment sizes and permisssions being
    106   /// requested.
    107   virtual Expected<std::unique_ptr<Allocation>>
    108   allocate(const JITLinkDylib *JD, const SegmentsRequestMap &Request) = 0;
    109 };
    110 
    111 /// A JITLinkMemoryManager that allocates in-process memory.
    112 class InProcessMemoryManager : public JITLinkMemoryManager {
    113 public:
    114   Expected<std::unique_ptr<Allocation>>
    115   allocate(const JITLinkDylib *JD, const SegmentsRequestMap &Request) override;
    116 };
    117 
    118 } // end namespace jitlink
    119 } // end namespace llvm
    120 
    121 #endif // LLVM_EXECUTIONENGINE_JITLINK_JITLINKMEMORYMANAGER_H
    122