| Index: cc/base/contiguous_container.h
|
| diff --git a/cc/base/contiguous_container.h b/cc/base/contiguous_container.h
|
| index d032aa7f8c3bda9c36eb377c2308c02e8059b8be..a5830091a0f0d7a74369a99fad6d7cc6117d4ffd 100644
|
| --- a/cc/base/contiguous_container.h
|
| +++ b/cc/base/contiguous_container.h
|
| @@ -11,6 +11,7 @@
|
| #include <utility>
|
|
|
| #include "base/compiler_specific.h"
|
| +#include "base/gtest_prod_util.h"
|
| #include "base/logging.h"
|
| #include "base/macros.h"
|
| #include "base/stl_util.h"
|
| @@ -18,6 +19,36 @@
|
|
|
| namespace cc {
|
|
|
| +namespace internal {
|
| +template <size_t input>
|
| +struct Log2 {};
|
| +template <>
|
| +struct Log2<1> {
|
| + static const unsigned value = 0;
|
| +};
|
| +template <>
|
| +struct Log2<2> {
|
| + static const unsigned value = 1;
|
| +};
|
| +template <>
|
| +struct Log2<4> {
|
| + static const unsigned value = 2;
|
| +};
|
| +template <>
|
| +struct Log2<8> {
|
| + static const unsigned value = 3;
|
| +};
|
| +template <>
|
| +struct Log2<16> {
|
| + static const unsigned value = 4;
|
| +};
|
| +} // namespace internal
|
| +
|
| +template <typename T>
|
| +unsigned Log2Alignment() {
|
| + return internal::Log2<ALIGNOF(T)>::value;
|
| +}
|
| +
|
| // ContiguousContainer is a container which stores a list of heterogeneous
|
| // objects (in particular, of varying sizes), packed next to one another in
|
| // memory. Objects are never relocated, so it is safe to store pointers to them
|
| @@ -49,7 +80,7 @@ class CC_EXPORT ContiguousContainerBase {
|
| size_t MemoryUsageInBytes() const;
|
|
|
| // These do not invoke constructors or destructors.
|
| - void* Allocate(size_t object_size);
|
| + void* Allocate(size_t object_size, unsigned log2_alignment);
|
| void Clear();
|
| void RemoveLast();
|
| void Swap(ContiguousContainerBase& other);
|
| @@ -68,15 +99,11 @@ class CC_EXPORT ContiguousContainerBase {
|
| DISALLOW_COPY_AND_ASSIGN(ContiguousContainerBase);
|
| };
|
|
|
| -// For most cases, no alignment stricter than pointer alignment is required. If
|
| -// one of the derived classes has stronger alignment requirements (and the
|
| -// static_assert fires), set alignment to the least common multiple of the
|
| -// derived class alignments. For small structs without pointers, it may be
|
| -// possible to reduce alignment for tighter packing.
|
| -
|
| -template <class BaseElementType, unsigned alignment = sizeof(void*)>
|
| +template <class BaseElementType>
|
| class ContiguousContainer : public ContiguousContainerBase {
|
| private:
|
| + FRIEND_TEST_ALL_PREFIXES(ContiguousContainerTest, Alignment);
|
| +
|
| // Declares itself as a forward iterator, but also supports a few more
|
| // things. The whole random access iterator interface is a bit much.
|
| template <typename BaseIterator, typename ValueType>
|
| @@ -126,9 +153,9 @@ class ContiguousContainer : public ContiguousContainerBase {
|
| const BaseElementType>;
|
|
|
| explicit ContiguousContainer(size_t max_object_size)
|
| - : ContiguousContainerBase(Align(max_object_size)) {}
|
| + : ContiguousContainerBase(max_object_size) {}
|
| ContiguousContainer(size_t max_object_size, size_t initial_size_bytes)
|
| - : ContiguousContainerBase(Align(max_object_size), initial_size_bytes) {}
|
| + : ContiguousContainerBase(max_object_size, initial_size_bytes) {}
|
|
|
| ~ContiguousContainer() {
|
| for (auto& element : *this) {
|
| @@ -168,10 +195,8 @@ class ContiguousContainer : public ContiguousContainerBase {
|
|
|
| template <class DerivedElementType, typename... Args>
|
| DerivedElementType& AllocateAndConstruct(Args&&... args) {
|
| - static_assert(alignment % ALIGNOF(DerivedElementType) == 0,
|
| - "Derived type requires stronger alignment.");
|
| - size_t alloc_size = Align(sizeof(DerivedElementType));
|
| - return *new (Allocate(alloc_size))
|
| + size_t alloc_size = sizeof(DerivedElementType);
|
| + return *new (Allocate(alloc_size, Log2Alignment<DerivedElementType>()))
|
| DerivedElementType(std::forward<Args>(args)...);
|
| }
|
|
|
| @@ -196,22 +221,15 @@ class ContiguousContainer : public ContiguousContainerBase {
|
|
|
| // Appends a new element using memcpy, then default-constructs a base
|
| // element in its place. Use with care.
|
| - BaseElementType& AppendByMoving(BaseElementType* item, size_t size) {
|
| + BaseElementType& AppendByMoving(BaseElementType* item,
|
| + size_t size,
|
| + unsigned log2_alignment) {
|
| DCHECK_GE(size, sizeof(BaseElementType));
|
| - void* new_item = Allocate(size);
|
| + void* new_item = Allocate(size, log2_alignment);
|
| memcpy(new_item, static_cast<void*>(item), size);
|
| new (item) BaseElementType;
|
| return *static_cast<BaseElementType*>(new_item);
|
| }
|
| -
|
| - private:
|
| - static size_t Align(size_t size) {
|
| - size_t aligned_size = alignment * ((size + alignment - 1) / alignment);
|
| - DCHECK_EQ(aligned_size % alignment, 0u);
|
| - DCHECK_GE(aligned_size, size);
|
| - DCHECK_LT(aligned_size, size + alignment);
|
| - return aligned_size;
|
| - }
|
| };
|
|
|
| } // namespace cc
|
|
|