Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2027)

Unified Diff: cc/base/contiguous_container.h

Issue 2119033003: Fix alignment issue of ContiguousContainer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
« no previous file with comments | « no previous file | cc/base/contiguous_container.cc » ('j') | third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698