From 9b2b633c860eebda93c28ae387c50f1f81e29211 Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Wed, 13 Dec 2017 16:29:37 -0800 Subject: [PATCH] Move max_align_v and max_align_t to folly/lang/Align.h Summary: [Folly] Move `max_align_v` and `max_align_t` to `folly/lang/Align.h`. And drop the macro `FOLLY_ALIGNED_MAX` - just use `alignas(max_align_v)` instead. Reviewed By: Orvid Differential Revision: D6554677 fbshipit-source-id: cacb335b141623506a41e95e0740613374279c6f --- folly/CachelinePadded.h | 3 +- folly/Makefile.am | 1 + folly/MicroSpinLock.h | 8 +- folly/Portability.h | 69 ---------------- folly/concurrency/CacheLocality.cpp | 5 +- folly/concurrency/CacheLocality.h | 3 +- folly/experimental/hazptr/memory_resource.cpp | 7 +- folly/experimental/hazptr/memory_resource.h | 8 +- folly/io/IOBuf.cpp | 1 + folly/lang/Align.h | 79 +++++++++++++++++++ folly/memory/Arena.h | 3 +- folly/memory/test/ThreadCachedArenaTest.cpp | 3 +- folly/test/CachelinePaddedTest.cpp | 1 + 13 files changed, 104 insertions(+), 87 deletions(-) create mode 100644 folly/lang/Align.h diff --git a/folly/CachelinePadded.h b/folly/CachelinePadded.h index 233d4bd7..cf10ecb7 100644 --- a/folly/CachelinePadded.h +++ b/folly/CachelinePadded.h @@ -20,6 +20,7 @@ #include #include +#include namespace folly { @@ -33,7 +34,7 @@ namespace folly { template class CachelinePadded { static_assert( - alignof(T) <= folly::max_align_v, + alignof(T) <= max_align_v, "CachelinePadded does not support over-aligned types."); public: diff --git a/folly/Makefile.am b/folly/Makefile.am index 2b077c75..46832090 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -324,6 +324,7 @@ nobase_follyinclude_HEADERS = \ io/async/test/UndelayedDestruction.h \ io/async/test/Util.h \ json.h \ + lang/Align.h \ lang/Assume.h \ lang/Bits.h \ lang/ColdClass.h \ diff --git a/folly/MicroSpinLock.h b/folly/MicroSpinLock.h index b36998a7..dab80c67 100644 --- a/folly/MicroSpinLock.h +++ b/folly/MicroSpinLock.h @@ -46,6 +46,7 @@ #include #include +#include namespace folly { @@ -118,7 +119,7 @@ static_assert( #define FOLLY_CACHE_LINE_SIZE 64 template -struct FOLLY_ALIGNED_MAX SpinLockArray { +struct alignas(max_align_v) SpinLockArray { T& operator[](size_t i) { return data_[i].lock; } @@ -140,9 +141,8 @@ struct FOLLY_ALIGNED_MAX SpinLockArray { // Check if T can theoretically cross a cache line. static_assert( - folly::max_align_v > 0 && - FOLLY_CACHE_LINE_SIZE % folly::max_align_v == 0 && - sizeof(T) <= folly::max_align_v, + max_align_v > 0 && FOLLY_CACHE_LINE_SIZE % max_align_v == 0 && + sizeof(T) <= max_align_v, "T can cross cache line boundaries"); char padding_[FOLLY_CACHE_LINE_SIZE]; diff --git a/folly/Portability.h b/folly/Portability.h index da1fff85..1498db30 100644 --- a/folly/Portability.h +++ b/folly/Portability.h @@ -17,7 +17,6 @@ #pragma once #include -#include #include @@ -30,73 +29,6 @@ constexpr bool kHasUnalignedAccess = true; #else constexpr bool kHasUnalignedAccess = false; #endif - -namespace portability_detail { - -template -using integral_max = std::integral_constant; - -template -struct integral_sequence_max - : integral_max::value> {}; - -template -struct integral_sequence_max : std::integral_constant {}; - -template -using max_alignment = integral_sequence_max; - -using max_basic_alignment = max_alignment< - std::max_align_t, - long double, - double, - float, - long long int, - long int, - int, - short int, - bool, - char, - char16_t, - char32_t, - wchar_t, - std::nullptr_t>; -} // namespace portability_detail - -constexpr size_t max_align_v = portability_detail::max_basic_alignment::value; - -// max_align_t is a type which is aligned at least as strictly as the -// most-aligned basic type (see the specification of std::max_align_t). This -// implementation exists because 32-bit iOS platforms have a broken -// std::max_align_t (see below). -// -// You should refer to this as `::folly::max_align_t` in portable code, even if -// you have `using namespace folly;` because C11 defines a global namespace -// `max_align_t` type. -// -// To be certain, we consider every non-void fundamental type specified by the -// standard. On most platforms `long double` would be enough, but iOS 32-bit -// has an 8-byte aligned `double` and `long long int` and a 4-byte aligned -// `long double`. -// -// So far we've covered locals and other non-allocated storage, but we also need -// confidence that allocated storage from `malloc`, `new`, etc will also be -// suitable for objects with this alignment reuirement. -// -// Apple document that their implementation of malloc will issue 16-byte -// granularity chunks for small allocations (large allocations are page-size -// granularity and page-aligned). We think that allocated storage will be -// suitable for these objects based on the following assumptions: -// -// 1. 16-byte granularity also means 16-byte aligned. -// 2. `new` and other allocators follow the `malloc` rules. -// -// We also have some anecdotal evidence: we don't see lots of misaligned-storage -// crashes on 32-bit iOS apps that use `double`. -// -// Apple's allocation reference: http://bit.ly/malloc-small -struct alignas(max_align_v) max_align_t {}; - } // namespace folly // compiler specific attribute translation @@ -109,7 +41,6 @@ struct alignas(max_align_v) max_align_t {}; #else # error Cannot define FOLLY_ALIGNED on this platform #endif -#define FOLLY_ALIGNED_MAX FOLLY_ALIGNED(::folly::max_align_v) // NOTE: this will only do checking in msvc with versions that support /analyze #if _MSC_VER diff --git a/folly/concurrency/CacheLocality.cpp b/folly/concurrency/CacheLocality.cpp index 7f1253d1..d400ddb2 100644 --- a/folly/concurrency/CacheLocality.cpp +++ b/folly/concurrency/CacheLocality.cpp @@ -256,9 +256,8 @@ void* SimpleAllocator::allocateHard() { // Install a pointer to ourselves as the allocator. *reinterpret_cast(mem_) = this; - static_assert( - folly::max_align_v >= sizeof(SimpleAllocator*), "alignment too small"); - mem_ += std::min(sz_, folly::max_align_v); + static_assert(max_align_v >= sizeof(SimpleAllocator*), "alignment too small"); + mem_ += std::min(sz_, max_align_v); // New allocation. auto mem = mem_; diff --git a/folly/concurrency/CacheLocality.h b/folly/concurrency/CacheLocality.h index caae2395..7751b7dc 100644 --- a/folly/concurrency/CacheLocality.h +++ b/folly/concurrency/CacheLocality.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -390,7 +391,7 @@ class SimpleAllocator { if (intptr_t(mem_) % 128 == 0) { // Avoid allocating pointers that may look like malloc // pointers. - mem_ += std::min(sz_, folly::max_align_v); + mem_ += std::min(sz_, max_align_v); } if (mem_ && (mem_ + sz_ <= end_)) { auto mem = mem_; diff --git a/folly/experimental/hazptr/memory_resource.cpp b/folly/experimental/hazptr/memory_resource.cpp index 4c8da83d..7d702e68 100644 --- a/folly/experimental/hazptr/memory_resource.cpp +++ b/folly/experimental/hazptr/memory_resource.cpp @@ -39,9 +39,8 @@ void set_default_resource(memory_resource* mr) { memory_resource* new_delete_resource() { class new_delete : public memory_resource { public: - void* allocate( - const size_t bytes, - const size_t alignment = folly::max_align_v) override { + void* allocate(const size_t bytes, const size_t alignment = max_align_v) + override { (void)alignment; void* p = static_cast(new char[bytes]); DEBUG_PRINT(this << " " << p << " " << bytes); @@ -50,7 +49,7 @@ memory_resource* new_delete_resource() { void deallocate( void* p, const size_t bytes, - const size_t alignment = folly::max_align_v) override { + const size_t alignment = max_align_v) override { (void)alignment; (void)bytes; DEBUG_PRINT(p << " " << bytes); diff --git a/folly/experimental/hazptr/memory_resource.h b/folly/experimental/hazptr/memory_resource.h index c9759ae8..f75e2ac9 100644 --- a/folly/experimental/hazptr/memory_resource.h +++ b/folly/experimental/hazptr/memory_resource.h @@ -23,9 +23,11 @@ /// hazptr prototype. //////////////////////////////////////////////////////////////////////////////// -#include #include +#include +#include + namespace folly { namespace hazptr { @@ -34,11 +36,11 @@ class memory_resource { virtual ~memory_resource() = default; virtual void* allocate( const size_t bytes, - const size_t alignment = folly::max_align_v) = 0; + const size_t alignment = max_align_v) = 0; virtual void deallocate( void* p, const size_t bytes, - const size_t alignment = folly::max_align_v) = 0; + const size_t alignment = max_align_v) = 0; }; memory_resource* get_default_resource(); diff --git a/folly/io/IOBuf.cpp b/folly/io/IOBuf.cpp index 7206fc46..87df7f8b 100644 --- a/folly/io/IOBuf.cpp +++ b/folly/io/IOBuf.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include using std::unique_ptr; diff --git a/folly/lang/Align.h b/folly/lang/Align.h new file mode 100644 index 00000000..8b878d40 --- /dev/null +++ b/folly/lang/Align.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017-present Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace folly { + +namespace detail { + +union max_align_ { + std::max_align_t mat; + long double ld; + double d; + float f; + long long int lli; + long int li; + int i; + short int si; + bool b; + char c; + char16_t c16; + char32_t c32; + wchar_t wc; + std::nullptr_t n; +}; + +} // namespace detail + +// max_align_v is the alignment of max_align_t. +// +// max_align_t is a type which is aligned at least as strictly as the +// most-aligned basic type (see the specification of std::max_align_t). This +// implementation exists because 32-bit iOS platforms have a broken +// std::max_align_t (see below). +// +// You should refer to this as `::folly::max_align_t` in portable code, even if +// you have `using namespace folly;` because C11 defines a global namespace +// `max_align_t` type. +// +// To be certain, we consider every non-void fundamental type specified by the +// standard. On most platforms `long double` would be enough, but iOS 32-bit +// has an 8-byte aligned `double` and `long long int` and a 4-byte aligned +// `long double`. +// +// So far we've covered locals and other non-allocated storage, but we also need +// confidence that allocated storage from `malloc`, `new`, etc will also be +// suitable for objects with this alignment requirement. +// +// Apple document that their implementation of malloc will issue 16-byte +// granularity chunks for small allocations (large allocations are page-size +// granularity and page-aligned). We think that allocated storage will be +// suitable for these objects based on the following assumptions: +// +// 1. 16-byte granularity also means 16-byte aligned. +// 2. `new` and other allocators follow the `malloc` rules. +// +// We also have some anecdotal evidence: we don't see lots of misaligned-storage +// crashes on 32-bit iOS apps that use `double`. +// +// Apple's allocation reference: http://bit.ly/malloc-small +constexpr std::size_t max_align_v = alignof(detail::max_align_); +struct alignas(max_align_v) max_align_t {}; + +} // namespace folly diff --git a/folly/memory/Arena.h b/folly/memory/Arena.h index ffe9f38b..81a33967 100644 --- a/folly/memory/Arena.h +++ b/folly/memory/Arena.h @@ -27,6 +27,7 @@ #include #include #include +#include #include namespace folly { @@ -133,7 +134,7 @@ class Arena { typedef boost::intrusive::slist_member_hook< boost::intrusive::tag> BlockLink; - struct FOLLY_ALIGNED_MAX Block { + struct alignas(max_align_v) Block { BlockLink link; // Allocate a block with at least size bytes of storage. diff --git a/folly/memory/test/ThreadCachedArenaTest.cpp b/folly/memory/test/ThreadCachedArenaTest.cpp index 4401ae0a..f34f81ea 100644 --- a/folly/memory/test/ThreadCachedArenaTest.cpp +++ b/folly/memory/test/ThreadCachedArenaTest.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include using namespace folly; @@ -92,7 +93,7 @@ void ArenaTester::merge(ArenaTester&& other) { } // namespace TEST(ThreadCachedArena, BlockSize) { - static const size_t alignment = folly::max_align_v; + static const size_t alignment = max_align_v; static const size_t requestedBlockSize = 64; ThreadCachedArena arena(requestedBlockSize); diff --git a/folly/test/CachelinePaddedTest.cpp b/folly/test/CachelinePaddedTest.cpp index 9c125301..148493e3 100644 --- a/folly/test/CachelinePaddedTest.cpp +++ b/folly/test/CachelinePaddedTest.cpp @@ -18,6 +18,7 @@ #include +#include #include using folly::CachelinePadded; -- 2.34.1