From: Philip Pronin Date: Tue, 8 Apr 2014 18:38:55 +0000 (-0700) Subject: configurable alignment for Arena X-Git-Tag: v0.22.0~611 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=970c79617bdb988f7f69c3db483a9188382af541;p=folly.git configurable alignment for Arena Summary: Allow specifying custom alignment. Test Plan: fbconfig -r folly/test && fbmake opt -j32 @override-unit-failures Reviewed By: lucian@fb.com FB internal diff: D1264851 --- diff --git a/folly/Arena-inl.h b/folly/Arena-inl.h index 1326cca7..a45fa3da 100644 --- a/folly/Arena-inl.h +++ b/folly/Arena-inl.h @@ -31,7 +31,6 @@ Arena::Block::allocate(Alloc& alloc, size_t size, bool allowSlack) { } void* mem = alloc.allocate(allocSize); - assert(isAligned(mem)); return std::make_pair(new (mem) Block(), allocSize - sizeof(Block)); } @@ -46,9 +45,9 @@ void* Arena::allocateSlow(size_t size) { std::pair p; char* start; - size_t allocSize = std::max(size, minBlockSize()) + sizeof(Block); - if(sizeLimit_ && allocSize > sizeLimit_ - totalAllocatedSize_) { + if (sizeLimit_ != kNoSizeLimit && + allocSize > sizeLimit_ - totalAllocatedSize_) { throw std::bad_alloc(); } diff --git a/folly/Arena.h b/folly/Arena.h index 9798dc81..5ea7552f 100644 --- a/folly/Arena.h +++ b/folly/Arena.h @@ -19,9 +19,11 @@ #include #include +#include #include #include +#include "folly/Conv.h" #include "folly/Likely.h" #include "folly/Malloc.h" #include "folly/Memory.h" @@ -61,13 +63,19 @@ class Arena { public: explicit Arena(const Alloc& alloc, size_t minBlockSize = kDefaultMinBlockSize, - size_t sizeLimit = 0) + size_t sizeLimit = kNoSizeLimit, + size_t maxAlign = kDefaultMaxAlign) : allocAndSize_(alloc, minBlockSize) , ptr_(nullptr) , end_(nullptr) , totalAllocatedSize_(0) , bytesUsed_(0) - , sizeLimit_(sizeLimit) { + , sizeLimit_(sizeLimit) + , maxAlign_(maxAlign) { + if ((maxAlign_ & (maxAlign_ - 1)) || maxAlign_ > alignof(Block)) { + throw std::invalid_argument( + folly::to("Invalid maxAlign: ", maxAlign_)); + } } ~Arena(); @@ -147,19 +155,20 @@ class Arena { public: static constexpr size_t kDefaultMinBlockSize = 4096 - sizeof(Block); + static constexpr size_t kNoSizeLimit = 0; + static constexpr size_t kDefaultMaxAlign = alignof(Block); private: - static constexpr size_t maxAlign = alignof(Block); - static constexpr bool isAligned(uintptr_t address) { - return (address & (maxAlign - 1)) == 0; + bool isAligned(uintptr_t address) const { + return (address & (maxAlign_ - 1)) == 0; } - static bool isAligned(void* p) { + bool isAligned(void* p) const { return isAligned(reinterpret_cast(p)); } // Round up size so it's properly aligned - static constexpr size_t roundUp(size_t size) { - return (size + maxAlign - 1) & ~(maxAlign - 1); + size_t roundUp(size_t size) const { + return (size + maxAlign_ - 1) & ~(maxAlign_ - 1); } // cache_last makes the list keep a pointer to the last element, so we @@ -194,7 +203,8 @@ class Arena { char* end_; size_t totalAllocatedSize_; size_t bytesUsed_; - size_t sizeLimit_; + const size_t sizeLimit_; + const size_t maxAlign_; }; template @@ -223,8 +233,9 @@ struct ArenaAllocatorTraits { class SysArena : public Arena { public: explicit SysArena(size_t minBlockSize = kDefaultMinBlockSize, - size_t sizeLimit = 0) - : Arena(SysAlloc(), minBlockSize, sizeLimit) { + size_t sizeLimit = kNoSizeLimit, + size_t maxAlign = kDefaultMaxAlign) + : Arena(SysAlloc(), minBlockSize, sizeLimit, maxAlign) { } }; diff --git a/folly/ThreadCachedArena.cpp b/folly/ThreadCachedArena.cpp index 64485575..107bf99d 100644 --- a/folly/ThreadCachedArena.cpp +++ b/folly/ThreadCachedArena.cpp @@ -18,12 +18,13 @@ namespace folly { -ThreadCachedArena::ThreadCachedArena(size_t minBlockSize) - : minBlockSize_(minBlockSize) { +ThreadCachedArena::ThreadCachedArena(size_t minBlockSize, size_t maxAlign) + : minBlockSize_(minBlockSize), maxAlign_(maxAlign) { } SysArena* ThreadCachedArena::allocateThreadLocalArena() { - SysArena* arena = new SysArena(minBlockSize_); + SysArena* arena = + new SysArena(minBlockSize_, SysArena::kNoSizeLimit, maxAlign_); auto disposer = [this] (SysArena* t, TLPDestructionMode mode) { std::unique_ptr tp(t); // ensure it gets deleted if (mode == TLPDestructionMode::THIS_THREAD) { diff --git a/folly/ThreadCachedArena.h b/folly/ThreadCachedArena.h index 469413b1..efc54bd6 100644 --- a/folly/ThreadCachedArena.h +++ b/folly/ThreadCachedArena.h @@ -42,7 +42,8 @@ namespace folly { class ThreadCachedArena { public: explicit ThreadCachedArena( - size_t minBlockSize = SysArena::kDefaultMinBlockSize); + size_t minBlockSize = SysArena::kDefaultMinBlockSize, + size_t maxAlign = SysArena::kDefaultMaxAlign); void* allocate(size_t size) { SysArena* arena = arena_.get(); @@ -69,12 +70,16 @@ class ThreadCachedArena { // the ThreadCachedArena is destroyed. void zombify(SysArena&& arena); - size_t minBlockSize_; + const size_t minBlockSize_; + const size_t maxAlign_; SysArena zombies_; // allocated from threads that are now dead std::mutex zombiesMutex_; ThreadLocalPtr arena_; // per-thread arena }; +template <> +struct IsArenaAllocator : std::true_type { }; + } // namespace folly #endif /* FOLLY_THREADCACHEDARENA_H_ */