diff --git a/include/v8config.h b/include/v8config.h index aa24eebff5..25eb480eb1 100644 --- a/include/v8config.h +++ b/include/v8config.h @@ -97,6 +97,7 @@ // C++11 feature detection // // V8_HAS_CXX11_ALIGNAS - alignas specifier supported +// V8_HAS_CXX11_ALIGNOF - alignof(type) operator supported // V8_HAS_CXX11_STATIC_ASSERT - static_assert() supported // V8_HAS_CXX11_DELETE - deleted functions supported // V8_HAS_CXX11_FINAL - final marker supported @@ -104,7 +105,9 @@ // // Compiler-specific feature detection // -// V8_HAS_ATTRIBUTE___ALIGNED__ - __attribute__((__aligned__(n))) supported +// V8_HAS___ALIGNOF - __alignof(type) operator supported +// V8_HAS___ALIGNOF__ - __alignof__(type) operator supported +// V8_HAS_ATTRIBUTE_ALIGNED - __attribute__((aligned(n))) supported // V8_HAS_ATTRIBUTE_ALWAYS_INLINE - __attribute__((always_inline)) supported // V8_HAS_ATTRIBUTE_DEPRECATED - __attribute__((deprecated)) supported // V8_HAS_ATTRIBUTE_VISIBILITY - __attribute__((visibility)) supported @@ -122,7 +125,11 @@ # define V8_CC_CLANG 1 -# define V8_HAS_ATTRIBUTE___ALIGNED__ (__has_attribute(__aligned__)) +// Clang defines __alignof__ as alias for __alignof +# define V8_HAS___ALIGNOF 1 +# define V8_HAS___ALIGNOF__ V8_HAS___ALIGNOF + +# define V8_HAS_ATTRIBUTE_ALIGNED (__has_attribute(aligned)) # define V8_HAS_ATTRIBUTE_ALWAYS_INLINE (__has_attribute(always_inline)) # define V8_HAS_ATTRIBUTE_DEPRECATED (__has_attribute(deprecated)) # define V8_HAS_ATTRIBUTE_VISIBILITY (__has_attribute(visibility)) @@ -146,7 +153,9 @@ # define V8_CC_MINGW 1 # endif -# define V8_HAS_ATTRIBUTE___ALIGNED__ (V8_GNUC_PREREQ(2, 95, 0)) +# define V8_HAS___ALIGNOF__ (V8_GNUC_PREREQ(4, 3, 0)) + +# define V8_HAS_ATTRIBUTE_ALIGNED (V8_GNUC_PREREQ(2, 95, 0)) // always_inline is available in gcc 4.0 but not very reliable until 4.4. // Works around "sorry, unimplemented: inlining failed" build errors with // older compilers. @@ -164,6 +173,7 @@ // both for forward compatibility. # if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L # define V8_HAS_CXX11_ALIGNAS (V8_GNUC_PREREQ(4, 8, 0)) +# define V8_HAS_CXX11_ALIGNOF (V8_GNUC_PREREQ(4, 8, 0)) # define V8_HAS_CXX11_STATIC_ASSERT (V8_GNUC_PREREQ(4, 3, 0)) # define V8_HAS_CXX11_DELETE (V8_GNUC_PREREQ(4, 4, 0)) # define V8_HAS_CXX11_OVERRIDE (V8_GNUC_PREREQ(4, 7, 0)) @@ -179,6 +189,8 @@ # define V8_CC_MSVC 1 +# define V8_HAS___ALIGNOF 1 + // Override control was added with Visual Studio 2005, but // Visual Studio 2010 and earlier spell "final" as "sealed". # define V8_HAS_CXX11_FINAL (_MSC_VER >= 1700) @@ -275,16 +287,54 @@ // This macro allows to specify memory alignment for structs, classes, etc. // Use like: -// class V8_ALIGNAS(16) MyClass { ... }; -// V8_ALIGNAS(32) int array[42]; +// class V8_ALIGNED(16) MyClass { ... }; +// V8_ALIGNED(32) int array[42]; #if V8_HAS_CXX11_ALIGNAS -# define V8_ALIGNAS(n) alignas(n) -#elif V8_HAS_ATTRIBUTE___ALIGNED__ -# define V8_ALIGNAS(n) __attribute__((__aligned__(n))) +# define V8_ALIGNED(n) alignas(n) +#elif V8_HAS_ATTRIBUTE_ALIGNED +# define V8_ALIGNED(n) __attribute__((aligned(n))) #elif V8_HAS_DECLSPEC_ALIGN -# define V8_ALIGNAS(n) __declspec(align(n)) +# define V8_ALIGNED(n) __declspec(align(n)) #else -# define V8_ALIGNAS(n) /* NOT SUPPORTED */ +# define V8_ALIGNED(n) /* NOT SUPPORTED */ +#endif + + +// This macro is similar to V8_ALIGNED(), but takes a type instead of size +// in bytes. If the compiler does not supports using the alignment of the +// |type|, it will align according to the |alignment| instead. For example, +// Visual Studio C++ cannot combine __declspec(align) and __alignof. The +// |alignment| must be a literal that is used as a kind of worst-case fallback +// alignment. +// Use like: +// struct V8_ALIGNAS(AnotherClass, 16) NewClass { ... }; +// V8_ALIGNAS(double, 8) int array[100]; +#if V8_HAS_CXX11_ALIGNAS +# define V8_ALIGNAS(type, alignment) alignas(type) +#elif V8_HAS___ALIGNOF__ && V8_HAS_ATTRIBUTE_ALIGNED +# define V8_ALIGNAS(type, alignment) __attribute__((aligned(__alignof__(type)))) +#else +# define V8_ALIGNAS(type, alignment) V8_ALIGNED(alignment) +#endif + + +// This macro returns alignment in bytes (an integer power of two) required for +// any instance of the given type, which is either complete type, an array type, +// or a reference type. +// Use like: +// size_t alignment = V8_ALIGNOF(double); +#if V8_HAS_CXX11_ALIGNOF +# define V8_ALIGNOF(type) alignof(type) +#elif V8_HAS___ALIGNOF +# define V8_ALIGNOF(type) __alignof(type) +#elif V8_HAS___ALIGNOF__ +# define V8_ALIGNOF(type) __alignof__(type) +#else +// Note that alignment of a type within a struct can be less than the +// alignment of the type stand-alone (because of ancient ABIs), so this +// should only be used as a last resort. +namespace v8 { template class AlignOfHelper { char c; T t; }; } +# define V8_ALIGNOF(type) (sizeof(::v8::AlignOfHelper) - sizeof(type)) #endif #endif // V8CONFIG_H_ diff --git a/src/circular-queue.h b/src/circular-queue.h index efbacd5b70..c7797b3801 100644 --- a/src/circular-queue.h +++ b/src/circular-queue.h @@ -70,7 +70,7 @@ class SamplingCircularQueue { // completely processed by the consumer. }; - struct V8_ALIGNAS(PROCESSOR_CACHE_LINE_SIZE) Entry { + struct V8_ALIGNED(PROCESSOR_CACHE_LINE_SIZE) Entry { Entry() : marker(kEmpty) {} T record; Atomic32 marker; @@ -79,8 +79,8 @@ class SamplingCircularQueue { Entry* Next(Entry* entry); Entry buffer_[Length]; - V8_ALIGNAS(PROCESSOR_CACHE_LINE_SIZE) Entry* enqueue_pos_; - V8_ALIGNAS(PROCESSOR_CACHE_LINE_SIZE) Entry* dequeue_pos_; + V8_ALIGNED(PROCESSOR_CACHE_LINE_SIZE) Entry* enqueue_pos_; + V8_ALIGNED(PROCESSOR_CACHE_LINE_SIZE) Entry* dequeue_pos_; DISALLOW_COPY_AND_ASSIGN(SamplingCircularQueue); }; diff --git a/src/lazy-instance.h b/src/lazy-instance.h index 9d68b8cacc..fc03f4d126 100644 --- a/src/lazy-instance.h +++ b/src/lazy-instance.h @@ -91,12 +91,13 @@ #ifndef V8_LAZY_INSTANCE_H_ #define V8_LAZY_INSTANCE_H_ +#include "checks.h" #include "once.h" namespace v8 { namespace internal { -#define LAZY_STATIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, {} } +#define LAZY_STATIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, { {} } } #define LAZY_DYNAMIC_INSTANCE_INITIALIZER { V8_ONCE_INIT, 0 } // Default to static mode. @@ -111,17 +112,15 @@ struct LeakyInstanceTrait { // Traits that define how an instance is allocated and accessed. -// TODO(kalmard): __alignof__ is only defined for GCC > 4.2. Fix alignment issue -// on MIPS with other compilers. -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) -#define LAZY_ALIGN(x) __attribute__((aligned(__alignof__(x)))) -#else -#define LAZY_ALIGN(x) -#endif template struct StaticallyAllocatedInstanceTrait { - typedef char StorageType[sizeof(T)] LAZY_ALIGN(T); + // 16-byte alignment fallback to be on the safe side here. + struct V8_ALIGNAS(T, 16) StorageType { + char x[sizeof(T)]; + }; + + STATIC_ASSERT(V8_ALIGNOF(StorageType) >= V8_ALIGNOF(T)); static T* MutableInstance(StorageType* storage) { return reinterpret_cast(storage); @@ -133,8 +132,6 @@ struct StaticallyAllocatedInstanceTrait { } }; -#undef LAZY_ALIGN - template struct DynamicallyAllocatedInstanceTrait {