mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user