Upgrade AlignedMemory to support dynamic allocations.

Adds two new methods: AlignedAlloc and AlignedFree for creating and
destroying dynamic aligned allocations respectively.  Also adds a
helper class, ScopedPtrAlignedFree, for use with scoped_ptr_malloc.

AlignedAlloc uses posix_memalign for OS X (now that we're targeting
10.6), Linux and _aligned_alloc() on Windows.  Android and NaCl use
memalign() since they do not expose posix_memalign() and memalign()
is safe to use with free() on those platforms.

Also hacks around a bug in Visual C++ where __alignof will sometimes
return zero:
http://connect.microsoft.com/VisualStudio/feedback/details/682695/c-alignof-fails-to-properly-evalute-alignment-of-dependent-types

BUG=none
TEST=base_unittests + new test, trybots.

Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=147988

Review URL: https://chromiumcodereview.appspot.com/10796020

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148483 0039d316-1c4b-4281-b951-d872f2087c98
parent 4d14d9c5
......@@ -205,6 +205,8 @@
'mac/scoped_sending_event.mm',
'mach_ipc_mac.h',
'mach_ipc_mac.mm',
'memory/aligned_memory.cc',
'memory/aligned_memory.h',
'memory/linked_ptr.h',
'memory/mru_cache.h',
'memory/raw_scoped_refptr_mismatch_checker.h',
......
......@@ -114,11 +114,13 @@
#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
#endif
// Return the byte alignment of the given type (available at compile time).
// Return the byte alignment of the given type (available at compile time). Use
// sizeof(type) prior to checking __alignof to workaround Visual C++ bug:
// http://goo.gl/isH0C
// Use like:
// ALIGNOF(int32) // this would be 4
#if defined(COMPILER_MSVC)
#define ALIGNOF(type) __alignof(type)
#define ALIGNOF(type) (sizeof(type) - sizeof(type) + __alignof(type))
#elif defined(COMPILER_GCC)
#define ALIGNOF(type) __alignof__(type)
#endif
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/memory/aligned_memory.h"
#include "base/logging.h"
#if defined(OS_ANDROID) || defined(OS_NACL)
#include <malloc.h>
#endif
namespace base {
void* AlignedAlloc(size_t size, size_t alignment) {
DCHECK_GT(size, 0U);
DCHECK_EQ(alignment & (alignment - 1), 0U);
DCHECK_EQ(alignment % sizeof(void*), 0U);
void* ptr = NULL;
#if defined(COMPILER_MSVC)
ptr = _aligned_malloc(size, alignment);
// Both Android and NaCl technically support posix_memalign(), but do not expose
// it in the current version of the library headers used by Chrome. Luckily,
// memalign() on both platforms returns pointers which can safely be used with
// free(), so we can use it instead. Issues filed with each project for docs:
// http://code.google.com/p/android/issues/detail?id=35391
// http://code.google.com/p/chromium/issues/detail?id=138579
#elif defined(OS_ANDROID) || defined(OS_NACL)
ptr = memalign(alignment, size);
#else
if (posix_memalign(&ptr, alignment, size))
ptr = NULL;
#endif
// Since aligned allocations may fail for non-memory related reasons, force a
// crash if we encounter a failed allocation; maintaining consistent behavior
// with a normal allocation failure in Chrome.
if (!ptr) {
DLOG(ERROR) << "If you crashed here, your aligned allocation is incorrect: "
<< "size=" << size << ", alignment=" << alignment;
CHECK(false);
}
// Sanity check alignment just to be safe.
DCHECK_EQ(reinterpret_cast<uintptr_t>(ptr) & (alignment - 1), 0U);
return ptr;
}
} // namespace base
......@@ -18,13 +18,31 @@
//
// // ... later, to destruct my_class:
// my_class.data_as<MyClass>()->MyClass::~MyClass();
//
// Alternatively, a runtime sized aligned allocation can be created:
//
// float* my_array = static_cast<float*>(AlignedAlloc(size, alignment));
//
// // ... later, to release the memory:
// AlignedFree(my_array);
//
// Or using scoped_ptr_malloc:
//
// scoped_ptr_malloc<float, ScopedPtrAlignedFree> my_array(
// static_cast<float*>(AlignedAlloc(size, alignment)));
#ifndef BASE_MEMORY_ALIGNED_MEMORY_H_
#define BASE_MEMORY_ALIGNED_MEMORY_H_
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#if defined(COMPILER_MSVC)
#include <malloc.h>
#else
#include <stdlib.h>
#endif
namespace base {
......@@ -38,15 +56,15 @@ struct AlignedMemory {};
class AlignedMemory<Size, byte_alignment> { \
public: \
ALIGNAS(byte_alignment) uint8 data_[Size]; \
void* void_data() { return reinterpret_cast<void*>(data_); } \
void* void_data() { return static_cast<void*>(data_); } \
const void* void_data() const { \
return reinterpret_cast<const void*>(data_); \
return static_cast<const void*>(data_); \
} \
template<typename Type> \
Type* data_as() { return reinterpret_cast<Type*>(void_data()); } \
Type* data_as() { return static_cast<Type*>(void_data()); } \
template<typename Type> \
const Type* data_as() const { \
return reinterpret_cast<const Type*>(void_data()); \
return static_cast<const Type*>(void_data()); \
} \
private: \
void* operator new(size_t); \
......@@ -71,6 +89,26 @@ BASE_DECL_ALIGNED_MEMORY(1024);
BASE_DECL_ALIGNED_MEMORY(2048);
BASE_DECL_ALIGNED_MEMORY(4096);
} // base
#undef BASE_DECL_ALIGNED_MEMORY
BASE_EXPORT void* AlignedAlloc(size_t size, size_t alignment);
inline void AlignedFree(void* ptr) {
#if defined(COMPILER_MSVC)
_aligned_free(ptr);
#else
free(ptr);
#endif
}
// Helper class for use with scoped_ptr_malloc.
class BASE_EXPORT ScopedPtrAlignedFree {
public:
inline void operator()(void* ptr) const {
AlignedFree(ptr);
}
};
} // namespace base
#endif // BASE_MEMORY_ALIGNED_MEMORY_H_
......@@ -51,4 +51,33 @@ TEST(AlignedMemoryTest, StackAlignment) {
#endif // !(defined(OS_IOS) && defined(ARCH_CPU_ARM_FAMILY))
}
TEST(AlignedMemoryTest, DynamicAllocation) {
void* p = base::AlignedAlloc(8, 8);
EXPECT_TRUE(p);
EXPECT_ALIGNED(p, 8);
base::AlignedFree(p);
p = base::AlignedAlloc(8, 16);
EXPECT_TRUE(p);
EXPECT_ALIGNED(p, 16);
base::AlignedFree(p);
p = base::AlignedAlloc(8, 256);
EXPECT_TRUE(p);
EXPECT_ALIGNED(p, 256);
base::AlignedFree(p);
p = base::AlignedAlloc(8, 4096);
EXPECT_TRUE(p);
EXPECT_ALIGNED(p, 4096);
base::AlignedFree(p);
}
TEST(AlignedMemoryTest, ScopedDynamicAllocation) {
scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> p(
static_cast<float*>(base::AlignedAlloc(8, 8)));
EXPECT_TRUE(p.get());
EXPECT_ALIGNED(p.get(), 8);
}
} // namespace
......@@ -4,6 +4,7 @@
#include "chrome/browser/history/android/android_urls_sql_handler.h"
#include "base/logging.h"
#include "chrome/browser/history/history_database.h"
namespace history {
......
......@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "chrome/browser/ui/find_bar/find_bar.h"
#include "chrome/browser/ui/find_bar/find_bar_state.h"
......
......@@ -4,6 +4,8 @@
#include "chrome/common/extensions/permissions/permissions_info.h"
#include "base/logging.h"
namespace extensions {
// static
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment