Implemenation a section level allocator in cling's RTDyldMemoryManager (Azog).

This allow for a single allocation at the beginning of the module and insure that
all the section of the module with be contiguous in memory.

This is a better fix for Fix ROOT-8523 and replace commit
3f7418269714e12d9fc4f17d197fde7199dbae7d (see more detail about
the problem it the log of that commit)
This commit is contained in:
Philippe Canal 2017-01-31 12:23:14 -06:00 committed by sftnight
parent e7c289878a
commit aad9a7a391

View File

@ -61,6 +61,64 @@ namespace cling {
class Azog: public RTDyldMemoryManager {
cling::IncrementalJIT& m_jit;
struct AllocInfo {
uint8_t *m_Start = nullptr;
uint8_t *m_End = nullptr;
uint8_t *m_Current = nullptr;
void allocate(RTDyldMemoryManager *exeMM,
uintptr_t Size, uint32_t Align,
bool code, bool isReadOnly) {
uintptr_t RequiredSize = 2*Size; // Space for internal alignment.
if (code)
m_Start = exeMM->allocateCodeSection(RequiredSize, Align,
0 /* SectionID */,
"codeReserve");
else if (isReadOnly)
m_Start = exeMM->allocateDataSection(RequiredSize, Align,
0 /* SectionID */,
"rodataReserve",isReadOnly);
else
m_Start = exeMM->allocateDataSection(RequiredSize, Align,
0 /* SectionID */,
"rwataReserve",isReadOnly);
m_Current = m_Start;
m_End = m_Start + RequiredSize;
}
uint8_t* getNextAddr(uintptr_t Size, unsigned Alignment) {
if (!Alignment)
Alignment = 16;
assert(!(Alignment & (Alignment - 1)) && "Alignment must be a power of two.");
uintptr_t RequiredSize = Alignment * ((Size + Alignment - 1)/Alignment + 1);
if ( (m_Current + RequiredSize) > m_End ) {
fprintf(stderr,"Error ... did not reserved enough memory: need %ld(%ld) and have %ld\n",
Size,RequiredSize,(m_End - m_Current));
return nullptr;
}
uintptr_t Addr = (uintptr_t)m_Current;
// Align the address.
Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
m_Current = (uint8_t*)(Addr + Size);
return (uint8_t*)Addr;
}
operator bool() {
return m_Current != nullptr;
}
};
AllocInfo m_Code;
AllocInfo m_ROData;
AllocInfo m_RWData;
public:
Azog(cling::IncrementalJIT& Jit): m_jit(Jit) {}
@ -69,31 +127,50 @@ public:
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID,
StringRef SectionName) override {
uint8_t *Addr =
getExeMM()->allocateCodeSection(Size, Alignment, SectionID, SectionName);
m_jit.m_SectionsAllocatedSinceLastLoad.insert(Addr);
uint8_t *Addr = nullptr;
if (m_Code) {
Addr = m_Code.getNextAddr(Size, Alignment);
}
if (!Addr) {
Addr = getExeMM()->allocateCodeSection(Size, Alignment, SectionID, SectionName);
m_jit.m_SectionsAllocatedSinceLastLoad.insert(Addr);
}
return Addr;
}
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName,
bool IsReadOnly) override {
uint8_t *Addr = getExeMM()->allocateDataSection(Size, Alignment, SectionID,
SectionName, IsReadOnly);
m_jit.m_SectionsAllocatedSinceLastLoad.insert(Addr);
uint8_t *Addr = nullptr;
if (IsReadOnly && m_ROData) {
Addr = m_ROData.getNextAddr(Size,Alignment);
} else if (m_RWData) {
Addr = m_RWData.getNextAddr(Size,Alignment);
}
if (!Addr) {
Addr = getExeMM()->allocateDataSection(Size, Alignment, SectionID,
SectionName, IsReadOnly);
m_jit.m_SectionsAllocatedSinceLastLoad.insert(Addr);
}
return Addr;
}
void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
uintptr_t RODataSize, uint32_t RODataAlign,
uintptr_t RWDataSize, uint32_t RWDataAlign) override {
return getExeMM()->reserveAllocationSpace(CodeSize, CodeAlign, RODataSize,
RODataAlign, RWDataSize,
RWDataAlign);
m_Code.allocate(getExeMM(),CodeSize, CodeAlign, true, false);
m_ROData.allocate(getExeMM(),RODataSize, RODataAlign, false, true);
m_RWData.allocate(getExeMM(),RWDataSize, RWDataAlign, false, false);
m_jit.m_SectionsAllocatedSinceLastLoad.insert(m_Code.m_Start);
m_jit.m_SectionsAllocatedSinceLastLoad.insert(m_ROData.m_Start);
m_jit.m_SectionsAllocatedSinceLastLoad.insert(m_RWData.m_Start);
}
bool needsToReserveAllocationSpace() override {
return getExeMM()->needsToReserveAllocationSpace();
return true; // getExeMM()->needsToReserveAllocationSpace();
}
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,