Index: tools/llvm-rtdyld/llvm-rtdyld.cpp =================================================================== --- tools/llvm-rtdyld/llvm-rtdyld.cpp +++ tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -94,6 +94,11 @@ cl::ZeroOrMore); static cl::opt +PreallocMemory("preallocate", + cl::desc("Allocate memory upfront rather than on-demand"), + cl::init(0)); + +static cl::opt TargetAddrStart("target-addr-start", cl::desc("For -verify only: start of phony target address " "range."), @@ -173,14 +178,42 @@ size_t Size) override {} void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override {} + + void preallocateSlab(uint64_t Size) { + std::string Err; + sys::MemoryBlock MB = sys::Memory::AllocateRWX(PreallocMemory, nullptr, &Err); + if (!MB.base()) + report_fatal_error("Can't allocate enough memory: " + Err); + + PreallocSlab = MB; + UsePreallocation = true; + SlabSize = Size; + } + + uint8_t *allocateFromSlab(uintptr_t Size) { + if (CurrentSlabOffset + Size > SlabSize) + report_fatal_error("Can't allocate enough memory. Tune --preallocate"); + + uintptr_t OldSlabOffset = CurrentSlabOffset; + CurrentSlabOffset += Size; + return (uint8_t*)OldSlabOffset; + } + private: std::map DummyExterns; + sys::MemoryBlock PreallocSlab; + bool UsePreallocation = false; + uintptr_t SlabSize = 0; + uintptr_t CurrentSlabOffset = 0; }; uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) { + if (UsePreallocation) + return allocateFromSlab(Size); + sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, nullptr); FunctionMemory.push_back(MB); return (uint8_t*)MB.base(); @@ -191,6 +224,9 @@ unsigned SectionID, StringRef SectionName, bool IsReadOnly) { + if (UsePreallocation) + return allocateFromSlab(Size); + sys::MemoryBlock MB = sys::Memory::AllocateRWX(Size, nullptr, nullptr); DataMemory.push_back(MB); return (uint8_t*)MB.base(); @@ -338,6 +374,14 @@ TrivialMemoryManager MemMgr; RuntimeDyld Dyld(MemMgr, MemMgr); + // Allocate a slab of memory upfront, if required. This is used if + // we want to test small code models. + if (PreallocMemory <= 0) + return Error("Pre-allocated bytes of memory must be a positive integer."); + + // FIXME: Limit the amount of memory that can be preallocated? + MemMgr.preallocateSlab(PreallocMemory); + // FIXME: Preserve buffers until resolveRelocations time to work around a bug // in RuntimeDyldELF. // This fixme should be fixed ASAP. This is a very brittle workaround.