How to cache MCJIT compiled object into memory?

Hi, All

I m not sure if this question has been asked or not. I’d like cache the MCJIT compiled object into memory buffer so it can be reused later. I followed the Andy Kaylor’s example wrote an inherited class from ObjectCache and use raw_fd_ostream to save the cache and load the cache from a file. I checked raw_ostream and its subclass, maybe I am wrong but I don’t see one is fit to save to memory buffer. Any suggestions?

Thank you very much

Hi Cheng,

You could use a raw_svector_ostream to write to a memory buffer, but that’s unnecessarily complicated. You just need to clone the memory buffer pointed to by Obj. Something along the lines of:

class MyCache : public ObjectCache {
public:
void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override {
CachedObjs[M] =
MemoryBuffer::getMemBufferCopy(Obj.getBuffer(),
Obj.getBufferIdentifier());
}

std::unique_ptr getObject(const Module *M) override {
MemoryBuffer& B = *CachedObjs[M];
return MemoryBuffer::getMemBufferCopy(B.getBuffer(), B.getBufferIdentifier());
}

private:
std::map<Module*, std::unique_ptr> CachedObjs;
};

Cheers,
Lang.

Thank you Lang. That should work. I was planing to use llvm::StringRef as the value of the CacheObjs map, and use function name string as key earlier. I guess that should work too and less storage use right?

Hi Cheng,

You can’t cache individual functions, so I’m not sure why you would use function names as keys?

Holding StringRefs at the moment seems dangerous. MCJIT instances own the objects that are added to them, so you have two cases:

(1) The object has previously been added to this MCJIT instance, in which case it’s also still part of the JIT’d process, so adding it again is redundant (and probably a bug).

OR

(2) This is a new MCJIT instance to which the object has not been added. If the old MCJIT instance has been deleted (which seems likely) then the memory backing your object cache is also gone and you have a bug.

This is why I used getMemBufferCopy above - it ensures that your objects outlive your JIT instance.

FYI, you should probably have some sort of invalidation test on notifyObjectCompiled, like:

if (isCacheStaleFor(M)) {
CachedObjs[M] = …;
}

Otherwise you’ll end up constantly replacing the object in your cache.

Cheers,
Lang.