[MCJIT] Why does it allocate function by function?

I am implementing ELFObject class for MCJIT to be able to run ELFs on ELF-platforms.

One thing bothers me: I see that the RTDyldMemoryManager-based allocator is always passed to MCJIT and to RuntimeDyld classes from outside. This enforces the approach that memory will be allocated function by function with startFunctionBody/endFunctionBody. This maybe was good for the old JIT, but not for MCJIT.

For ELF for example this isn't right. ELF is designed to be loaded into memory as a whole. I don't know much about MachO, but most likely it should be normally loaded into memory by OS in one block too, as a consequence of efficiency considerations.

So is this a design flaw that should be fixed? Or am I missing something?

I think I can lower the allocator from MCJIT into inside of RuntimeDyld. So at least ELF will be able to use the bulk allocator. But I though I ask here first.

Thank you,
Yuri

Hi Yuri,

You're correct that the current JITMemoryManager interface isn't a very good fit for the MCJIT. For the time being though, the intent is to work with it as much as possible so that the MCJIT can be a drop-in replacement for the old JIT. If we change the JITMemoryManager API right off the bat, we'll make it that much harder for clients to migrate to the new JIT, slowing adoption and reducing testing. If we run into situations where it's just unreasonable to do that, we'll need to re-evaluate, but at least for basic things, it should be reasonably feasible.

Regards,
-Jim

I see your point about MCJIT adoption.
But instead of simply fulfilling relocations and finding exported symbol locations, now we have to copy each function into the separate location? What if it they have the hardcoded assumptions that they are located with particular offsets against each other? This is quite clumsy and unreasonably complex approach.

I think the right and simple solution would be to make the allocators an internal affair of JIT, so that old JIT defines and uses JITMemoryManager inside as it needs, and MCJIT doesn't, and clients don't see any of this.

Yuri

Hi Yuri, You're correct that the current JITMemoryManager interface isn't a very good fit for the MCJIT. For the time being though, the intent is to work with it as much as possible so that the MCJIT can be a drop-in replacement for the old JIT. If we change the JITMemoryManager API right off the bat, we'll make it that much harder for clients to migrate to the new JIT, slowing adoption and reducing testing. If we run into situations where it's just unreasonable to do that, we'll need to re-evaluate, but at least for basic things, it should be reasonably feasible. Regards, -Jim

I see your point about MCJIT adoption.
But instead of simply fulfilling relocations and finding exported symbol locations, now we have to copy each function into the separate location? What if it they have the hardcoded assumptions that they are located with particular offsets against each other? This is quite clumsy and unreasonably complex approach.

That would be malformed input to the JIT. It's a requirement, as it currently stands, that functions be locatable individually. If a back end doesn't support that, then each function should be split into a separate Module (and thus object file) and submitted to the JIT separately. I fully acknowledge this is not always possible for all objects for arbitrary bitcode input (string tables and static functions come to mind). We're

I agree the approach is not optimal. If we were designing completely from scratch, I would absolutely do it differently. We're not, however, and can't simply throw away what we have and start over without significant pain. It's better to instead work incrementally. The first step is to implement with the current interfaces and get the MCJIT non-trivially functional. There are a lot of problems we can solve without needing to tackle the memory manager right off the bat. Doing so will also give us better insight into what the eventual design of the memory manager should be. That way we improve our chances of getting the design done more cleanly and not having to refactor it yet again later.

I think the right and simple solution would be to make the allocators an internal affair of JIT, so that old JIT defines and uses JITMemoryManager inside as it needs, and MCJIT doesn't, and clients don't see any of this.

I don't follow. How can the clients not see it? They define their own memory managers and pass them into the JIT. See LLDB for an example.

-Jim

I agree the approach is not optimal. If we were designing completely from scratch, I would absolutely do it differently. We're not, however, and can't simply throw away what we have and start over without significant pain. It's better to instead work incrementally. The first step is to implement with the current interfaces and get the MCJIT non-trivially functional. There are a lot of problems we can solve without needing to tackle the memory manager right off the bat. Doing so will also give us better insight into what the eventual design of the memory manager should be. That way we improve our chances of getting the design done more cleanly and not having to refactor it yet again later.

But this requires a lot of extra-coding and ugly result just to satisfy the 100% API back compatibility of function by function allocation.

> I think the right and simple solution would be to make the allocators an internal affair of JIT, so that old JIT defines and uses JITMemoryManager inside as it needs, and MCJIT doesn't, and clients don't see any of this.

I don't follow. How can the clients not see it? They define their own memory managers and pass them into the JIT. See LLDB for an example.

Unfortunately I don't use Mac for development and can't see the benefits of lldb. I think building on linux might be a good idea for it.

My suggestion was to not pass the memory allocator to JIT/MCJIT at all and let them allocate themselves as they need, everywhere including lldb assuming it's applicable.
The next suggestion is amending the existing JITMemoryManager interface with the bulk allocation method that will allocate RWX memory block.
And yet next suggestion will be to ignore the passed from outside allocator for MCJIT ELF object for now since lldb doesn't run on ELF platforms anyway.

Yuri

There are people that do just that.

Also, for another JIT case that works on linux check out the IcedTea Shark project:

http://icedtea.classpath.org/wiki/ZeroSharkFaq

It uses custom allocators (or at least did last I looked) and JITs on various platforms.

-eric