llvm.org GIT mirror llvm / 812ac4e
[JITLink] Switch to slab allocation for InProcessMemoryManager, re-enable test. InProcessMemoryManager used to make separate memory allocation calls for each permission level (RW, RX, RO), which could lead to target-out-of-range errors if data and code were placed too far apart (this was the source of failures in the JITLink/AArch64 testcase when it was first landed). This patch updates InProcessMemoryManager to allocate a single slab which is subdivided between text and data. This should guarantee that accesses remain in-range provided that individual object files do not exceed 1Mb in size. This patch also re-enables the JITLink/AArch64 testcase. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@374948 91177308-0d34-0410-b5e6-96231b3b80d8 Lang Hames 1 year, 1 month ago
2 changed file(s) with 42 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
3737 OnFinalize(applyProtections());
3838 }
3939 Error deallocate() override {
40 for (auto &KV : SegBlocks)
41 if (auto EC = sys::Memory::releaseMappedMemory(KV.second))
42 return errorCodeToError(EC);
40 if (SegBlocks.empty())
41 return Error::success();
42 void *SlabStart = SegBlocks.begin()->second.base();
43 char *SlabEnd = (char *)SlabStart;
44 for (auto &KV : SegBlocks) {
45 SlabStart = std::min(SlabStart, KV.second.base());
46 SlabEnd = std::max(SlabEnd, (char *)(KV.second.base()) +
47 KV.second.allocatedSize());
48 }
49 size_t SlabSize = SlabEnd - (char *)SlabStart;
50 assert((SlabSize % sys::Process::getPageSizeEstimate()) == 0 &&
51 "Slab size is not a multiple of page size");
52 sys::MemoryBlock Slab(SlabStart, SlabSize);
53 if (auto EC = sys::Memory::releaseMappedMemory(Slab))
54 return errorCodeToError(EC);
4355 return Error::success();
4456 }
4557
6981 static_cast(sys::Memory::MF_READ |
7082 sys::Memory::MF_WRITE);
7183
84 // Compute the total number of pages to allocate.
85 size_t TotalSize = 0;
7286 for (auto &KV : Request) {
73 auto &Seg = KV.second;
87 const auto &Seg = KV.second;
7488
7589 if (Seg.getAlignment() > sys::Process::getPageSizeEstimate())
7690 return make_error("Cannot request higher than page "
7791 "alignment",
7892 inconvertibleErrorCode());
7993
80 uint64_t SegmentSize = Seg.getContentSize() + Seg.getZeroFillSize();
94 TotalSize = alignTo(TotalSize, sys::Process::getPageSizeEstimate());
95 TotalSize += Seg.getContentSize();
96 TotalSize += Seg.getZeroFillSize();
97 }
8198
82 std::error_code EC;
83 auto SegMem =
84 sys::Memory::allocateMappedMemory(SegmentSize, nullptr, ReadWrite, EC);
99 // Allocate one slab to cover all the segments.
100 std::error_code EC;
101 auto SlabRemaining =
102 sys::Memory::allocateMappedMemory(TotalSize, nullptr, ReadWrite, EC);
85103
86 if (EC)
87 return errorCodeToError(EC);
104 if (EC)
105 return errorCodeToError(EC);
106
107 // Allocate segment memory from the slab.
108 for (auto &KV : Request) {
109
110 const auto &Seg = KV.second;
111
112 uint64_t SegmentSize = alignTo(Seg.getContentSize() + Seg.getZeroFillSize(),
113 sys::Process::getPageSizeEstimate());
114
115 sys::MemoryBlock SegMem(SlabRemaining.base(), SegmentSize);
116 SlabRemaining = sys::MemoryBlock((char *)SlabRemaining.base() + SegmentSize,
117 SegmentSize);
88118
89119 // Zero out the zero-fill memory.
90120 memset(static_cast(SegMem.base()) + Seg.getContentSize(), 0,
None # if not 'AArch64' in config.root.targets:
1 config.unsupported = True
0 if not 'AArch64' in config.root.targets:
1 config.unsupported = True