[LLVMdev] JITMemoryManager

Kaylor, Andrew andrew.kaylor at intel.com
Wed Oct 2 09:59:35 PDT 2013


Hi Frank,

The default memory manager for MCJIT (SectionMemoryManager) isn't hidden in the way that the DefaultJITMemoryManager is, so you should be able to derive from it as needed.  Also, because MCJIT emits code in sections, it should be fairly straightforward to customize the memory manager to release ownership of the memory before it is deleted.

Take a look and let me know if it has any shortcomings that prevent you from doing what you want to do.

Thanks,
Andy

-----Original Message-----
From: Frank Henigman [mailto:fjhenigman at google.com] 
Sent: Wednesday, October 02, 2013 9:13 AM
To: Jim Grosbach
Cc: llvmdev at cs.uiuc.edu; Dirkjan Bussink; Kaylor, Andrew
Subject: Re: [LLVMdev] JITMemoryManager

I'll try to find out, or get someone to explain, why Mesa selects MCJIT with LLVM 3.1 only and JIT for other LLVM versions.  I'm not keen to code a fourth attempt (1: copy JIT code, 2: delegating manger,
3: derive from DefaultJITMemoryManager, 4: copy MCJIT code) but I'll try copying code with MCJIT.  Is that the usual route for people who want to delete all LLVM engines, etc. while keeping the generated code?
In any case, my points on the difficulty of creating a JITMemoryManager apply equally to JIT or MCJIT.  Maybe few people care because most are happy with the default manager?  I might be too if I could change the allocation unit (down from 512KB) and if I could delete the engine without losing the code.  So there's a third proposal - to sum up:
1) delegating memory manager (code provided in my previous post)
2) de-anonymize default memory manager (I've written this patch too)
3) make default memory manager more flexible

On Tue, Oct 1, 2013 at 7:41 PM, Jim Grosbach <grosbach at apple.com> wrote:
> Hi Frank,
>
> The project really needs to be looking to move away from the old JIT and to MCJIT. LLVM is actively working to kill the old JIT. It's already unmaintained. MCJIT is the way forward. Can you elaborate on what's blocking its adoption for Mesa?
>
> -Jim
>
> On Oct 1, 2013, at 10:44 AM, Frank Henigman <fjhenigman at google.com> wrote:
>
>> Mesa (http://www.mesa3d.org/) uses LLVM to compile shaders.  These 
>> are typically small bits of code (~10KB) and one application can use 
>> many of them.  Mesa creates an ExecutionEngine with a default JIT 
>> memory manager for each shader it compiles, and keeps the engine 
>> around as long as the shader code is needed.  This results in memory 
>> waste of ~1MB for each shader.  Half the overhead is in the memory 
>> manager which allocates 512KB even if only a few KB is used, and half 
>> is in the engine, which we can't delete because doing so destroys the 
>> memory manager and the code within it.
>> A couple solutions:
>> 1) Get a copy of the code then delete the engine.  This might be 
>> doable with MCJIT, but seemingly not with JIT which Mesa wants to use.
>> 2) A new memory manager with less overhead and which also doesn't 
>> delete the code when killed by the engine.
>> I've got solution 2 working, but LLVM could make it easier.  Deriving 
>> from JITMemoryManager seems complicated - there are a lot of methods 
>> to implement.  Deriving from DefaultJITMemoryManager is not possible 
>> because it's in an anonymous namespace.  So I made a manager that 
>> delegates everything to a shared default memory manager.  This 
>> eliminates overhead by packing everything into one shared manager, 
>> and when a delegating manager gets killed the shared manager 
>> persists, so it's safe to delete the engines.
>> Below is a generic delegating memory manager.  Using this I only 
>> needed to override a couple methods.  Maybe it could be useful to 
>> others.  See the thread starting with 
>> http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-March/060186.html.
>> Note how many ifdefs were needed to work with all versions from 3.1 
>> to now.  If this were added to the LLVM project it could be 
>> maintained in one place with no ifdefs.  If the LLVM maintainers 
>> don't want it, I also have a patch to allow subclassing DefaultJITMemory manager.
>> Would that be more agreeable?  Thanks.
>>
>> class DelegatingJITMemoryManager : public llvm::JITMemoryManager {
>>
>>   protected:
>>      virtual llvm::JITMemoryManager *mgr() const = 0;
>>
>>   public:
>>      /*
>>       * From JITMemoryManager
>>       */
>>      virtual void setMemoryWritable() {
>>         return mgr()->setMemoryWritable();
>>      }
>>      virtual void setMemoryExecutable() {
>>         return mgr()->setMemoryExecutable();
>>      }
>>      virtual void setPoisonMemory(bool poison) {
>>         return mgr()->setPoisonMemory(poison);
>>      }
>>      virtual void AllocateGOT() {
>>         mgr()->AllocateGOT();
>>         /*
>>          * isManagingGOT() is not virtual in base class so we can't delegate.
>>          * Instead we mirror the value of HasGOT in our instance.
>>          */
>>         HasGOT = mgr()->isManagingGOT();
>>      }
>>      virtual uint8_t *getGOTBase() const {
>>         return mgr()->getGOTBase();
>>      }
>>      virtual uint8_t *startFunctionBody(const llvm::Function *F,
>>                                         uintptr_t &ActualSize) {
>>         return mgr()->startFunctionBody(F, ActualSize);
>>      }
>>      virtual uint8_t *allocateStub(const llvm::GlobalValue *F,
>>                                    unsigned StubSize,
>>                                    unsigned Alignment) {
>>         return mgr()->allocateStub(F, StubSize, Alignment);
>>      }
>>      virtual void endFunctionBody(const llvm::Function *F,
>>                                   uint8_t *FunctionStart,
>>                                   uint8_t *FunctionEnd) {
>>         return mgr()->endFunctionBody(F, FunctionStart, FunctionEnd);
>>      }
>>      virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
>>         return mgr()->allocateSpace(Size, Alignment);
>>      }
>>      virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
>>         return mgr()->allocateGlobal(Size, Alignment);
>>      }
>>      virtual void deallocateFunctionBody(void *Body) {
>>         return mgr()->deallocateFunctionBody(Body);
>>      }
>> #if HAVE_LLVM < 0x0304
>>      virtual uint8_t *startExceptionTable(const llvm::Function *F,
>>                                           uintptr_t &ActualSize) {
>>         return mgr()->startExceptionTable(F, ActualSize);
>>      }
>>      virtual void endExceptionTable(const llvm::Function *F,
>>                                     uint8_t *TableStart,
>>                                     uint8_t *TableEnd,
>>                                     uint8_t *FrameRegister) {
>>         return mgr()->endExceptionTable(F, TableStart, TableEnd,
>>                                         FrameRegister);
>>      }
>>      virtual void deallocateExceptionTable(void *ET) {
>>         mgr()->deallocateExceptionTable(ET);
>>      }
>> #endif
>>      virtual bool CheckInvariants(std::string &s) {
>>         return mgr()->CheckInvariants(s);
>>      }
>>      virtual size_t GetDefaultCodeSlabSize() {
>>         return mgr()->GetDefaultCodeSlabSize();
>>      }
>>      virtual size_t GetDefaultDataSlabSize() {
>>         return mgr()->GetDefaultDataSlabSize();
>>      }
>>      virtual size_t GetDefaultStubSlabSize() {
>>         return mgr()->GetDefaultStubSlabSize();
>>      }
>>      virtual unsigned GetNumCodeSlabs() {
>>         return mgr()->GetNumCodeSlabs();
>>      }
>>      virtual unsigned GetNumDataSlabs() {
>>         return mgr()->GetNumDataSlabs();
>>      }
>>      virtual unsigned GetNumStubSlabs() {
>>         return mgr()->GetNumStubSlabs();
>>      }
>>
>>      /*
>>       * From RTDyldMemoryManager
>>       */
>>      virtual uint8_t *allocateCodeSection(uintptr_t Size,
>>                                           unsigned Alignment,
>>                                           unsigned SectionID) {
>>         return mgr()->allocateCodeSection(Size, Alignment, SectionID);
>>      }
>> #if HAVE_LLVM >= 0x0303
>>      virtual uint8_t *allocateDataSection(uintptr_t Size,
>>                                           unsigned Alignment,
>>                                           unsigned SectionID,
>>                                           bool IsReadOnly) {
>>         return mgr()->allocateDataSection(Size, Alignment, SectionID,
>>                                  IsReadOnly);
>>      }
>>      virtual void registerEHFrames(llvm::StringRef SectionData) {
>>         return mgr()->registerEHFrames(SectionData);
>>      }
>> #else
>>      virtual uint8_t *allocateDataSection(uintptr_t Size,
>>                                           unsigned Alignment,
>>                                           unsigned SectionID) {
>>         return mgr()->allocateDataSection(Size, Alignment, SectionID);
>>      }
>> #endif
>>      virtual void *getPointerToNamedFunction(const std::string &Name,
>>                                              bool AbortOnFailure=true) {
>>         return mgr()->getPointerToNamedFunction(Name, AbortOnFailure);
>>      }
>> #if HAVE_LLVM == 0x0303
>>      virtual bool applyPermissions(std::string *ErrMsg = 0) {
>>         return mgr()->applyPermissions(ErrMsg);
>>      }
>> #elif HAVE_LLVM > 0x0303
>>      virtual bool finalizeMemory(std::string *ErrMsg = 0) {
>>         return mgr()->finalizeMemory(ErrMsg);
>>      }
>> #endif
>> };
>> _______________________________________________
>> LLVM Developers mailing list
>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>




More information about the llvm-dev mailing list