The 64bit primary allocator has a unique failure mode where it can exhaust the entire region for a given size class in the initial pre-allocated address range. This can happen if the region size happens to be relatively small and we allocate a bunch of objects that fit into the largest size class. It's still possible though for there to be some space outside of this initial address range. For this, we can rely on the secondary allocator to mmap to find some space.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
We have unittests, check TestCombinedAllocator. Can you please extend some of them?
compiler-rt/lib/sanitizer_common/sanitizer_allocator_combined.h | ||
---|---|---|
68 | maybe it's more efficient to increase size and go larger class sizes? | |
76 | I afraid this is not enough. bool from_primary = PrimaryAllocator::CanAllocate(needed_size, alignment); So every sanitizers needs to be investigated on implication from this change. |
This can happen if the region size happens to be relatively small and we allocate a bunch of objects that fit into the largest size class.
Can you elaborate? RISC-V?
When getting chunks from the freearray via PopulateFreeArray, the primary allocator will attempt to remap more space in a sizeclass's region. Before that, it calls IsRegionExhausted to see if there's any space left in the region to make the allocation. The check is essentially requested_size < kRegionSize - kFreeArraySize. If the region has no more user-allocatable space, it'll fail with The process has exhausted %zuMB for size class %zu. The max space per region (kRegionSize) is determined by the overall space provided for the primary allocator divided by the number of sizeclasses. So if, if we happen to allocate a lot of objects for a given sizeclass, we'll fail in this way. The frequency of this failure mode can be reduced by increasing kRegionSize (or alternatively decreasing kFreeArraySize).
For a 39bit VMA for RISCV, we don't have a lot of overall space for the primary allocator and the default size class map has a bunch of size classes, so the region size tended to be small. I think I found a size class map though that seems to work for us and reduce the number of sizeclasses (rounded) to 32. Abandoning this revision for now (unless I run into this again).
compiler-rt/lib/sanitizer_common/sanitizer_allocator_combined.h | ||
---|---|---|
68 | Ok, I found a good enough SizeClassMap config that helps prevent this for now. |
maybe it's more efficient to increase size and go larger class sizes?