[LLVMdev] Question about memory allocation in JIT

Reid Kleckner rnk at mit.edu
Fri Jul 3 07:55:41 PDT 2009


+llvmdev

2009/7/3 Merkulov Aleksey <steel1.0 at mail.ru>:
>> > Hello!  Working with LLVM JIT-compiler I found a small bug and I'd like to correct it.  Namely, on some tests LLVM fails with message "JIT: Ran out of space for generated machine code!"
>>
>> I'm working on a patch to fix this, although I've heard DOE may change
>> the MachineCodeEmitter interface to make this less necessary.
>>
>> http://codereview.appspot.com/71042
>
> Hello!  Thanks a lot for the patch!  I had applied it and my test stopped to break lli, but it worked incorrectly.  So I fixed the patch (see below) and now it seems that my test doesn't break lli and works correctly.
>
> If allocated block is too small for function body and globals, then it is necessary to remove globals allocated in that block from mappings.  So we should backup Relocations before changes in "for (unsigned i = 0, e = Relocations.size(); i != e; ++i) {" loop, and, in case of buffer overflow, we should remove globals from mappings.  Also, we should clear ConstPoolAddresses.  There are only two changes in function JITEmitter::finishFunction:
>
>
> --- lib/ExecutionEngine/JIT/JITEmitter.cpp      (original patch)
> +++ lib/ExecutionEngine/JIT/JITEmitter.cpp      (my changes)
> @@ -946,6 +947,7 @@
>   // FnEnd is the end of the function's machine code.
>   uint8_t *FnEnd = CurBufferPtr;
>
> +  std::vector<MachineRelocation> BackupRelocations = Relocations;
>   if (!Relocations.empty()) {
>     CurFn = F.getFunction();
>     NumRelos += Relocations.size();
> @@ -1028,8 +1030,18 @@
>   MemMgr->endFunctionBody(F.getFunction(), BufferBegin, CurBufferPtr);
>
>   if (CurBufferPtr == BufferEnd) {
> -    retryWithMoreMemory(F);
> -    return true;
> +         for (unsigned i = 0, e = BackupRelocations.size(); i != e; ++i) {
> +                 MachineRelocation &MR = BackupRelocations[i];
> +                 if (MR.isGlobalValue()) {
> +                         void* ResultPtr = TheJIT->getPointerToGlobalIfAvailable(MR.getGlobalValue());
> +                         if (BufferBegin <= ResultPtr && ResultPtr < BufferEnd) {
> +                                 TheJIT->updateGlobalMapping(MR.getGlobalValue(), 0);
> +                         }
> +                 }
> +         }
> +         retryWithMoreMemory(F);
> +         ConstPoolAddresses.clear();
> +         return true;
>   } else {
>     // Now that we've succeeded in emitting the function, reset the
>     // SizeEstimate
>
>

This is a known problem, and the solution I chose was to not emit
global data and code into the same buffer, since it breaks
freeMachineCodeForFunction in general, which is what
retryWithMoreMemory depends on.  When that patch, which I sent to
llvm-commits last night, goes in I'll fix up this patch so that it
allocates more space for code and data.

It might still be worth applying this patch because some clients still
rely on the old behavior where code and data go together, and if they
run out of memory, they're screwed.

Reid




More information about the llvm-dev mailing list