Reinstate "SIL: add a StackList data structure with zero cost operations."

... with a fix for a non-assert build crash: I used the wrong ilist type for SlabList. This does not explain the crash, though. What I think happened here is that llvm miscompiled and put the llvm_unreachable from the Slab's deleteNode function unconditionally into the SILModule destructor.
Now by using simple_ilist, there is no need for a deleteNode at all.
This commit is contained in:
Erik Eckstein
2021-04-13 13:41:24 +02:00
parent 4d69559c79
commit b3a7792d1d
20 changed files with 392 additions and 137 deletions

View File

@@ -57,6 +57,37 @@ class Output;
namespace swift {
/// A fixed size slab of memory, which can be allocated and freed by the
/// SILModule at (basically) zero cost.
class FixedSizeSlab : public llvm::ilist_node<FixedSizeSlab>,
public SILAllocated<FixedSizeSlab> {
public:
/// The capacity of the payload.
static constexpr size_t capacity = 64 * sizeof(uintptr_t);
private:
friend class SILModule;
/// The magic number which is stored in overflowGuard.
static constexpr uintptr_t magicNumber = (uintptr_t)0xdeadbeafdeadbeafull;
/// The payload.
char data[capacity];
/// Used for a cheap buffer overflow check - in the spirit of libgmalloc.
uintptr_t overflowGuard = magicNumber;
public:
void operator=(const FixedSizeSlab &) = delete;
void operator delete(void *Ptr, size_t) = delete;
/// Returns the payload pointing to \p T.
template<typename T> T *dataFor() { return (T *)(&data[0]); }
/// Returns the payload pointing to const \p T
template<typename T> const T *dataFor() const { return (const T *)(&data[0]); }
};
class AnyFunctionType;
class ASTContext;
class FileUnit;
@@ -129,6 +160,7 @@ public:
};
using ActionCallback = std::function<void()>;
using SlabList = llvm::simple_ilist<FixedSizeSlab>;
private:
friend KeyPathPattern;
@@ -151,6 +183,12 @@ private:
/// Allocator that manages the memory of all the pieces of the SILModule.
mutable llvm::BumpPtrAllocator BPA;
/// The list of freed slabs, which can be reused.
SlabList freeSlabs;
/// For consistency checking.
size_t numAllocatedSlabs = 0;
/// The swift Module associated with this SILModule.
ModuleDecl *TheSwiftModule;
@@ -733,6 +771,22 @@ public:
return static_cast<T *>(allocate(sizeof(T) * Count, alignof(T)));
}
/// Allocates a slab of memory.
///
/// This has (almost) zero cost, because for the first time, the allocation is
/// done with the BPA.
/// Subsequent allocations are reusing the already freed slabs.
FixedSizeSlab *allocSlab();
/// Frees a slab.
///
/// This has (almost) zero cost, because the slab is just put into the
/// freeSlabs list.
void freeSlab(FixedSizeSlab *slab);
/// Frees all slabs of a list.
void freeAllSlabs(SlabList &slabs);
template <typename T>
MutableArrayRef<T> allocateCopy(ArrayRef<T> Array) const {
MutableArrayRef<T> result(allocate<T>(Array.size()), Array.size());