diff --git a/dtool/src/dtoolbase/deletedBufferChain.cxx b/dtool/src/dtoolbase/deletedBufferChain.cxx index 557b6ce9d8..0451ada7d3 100644 --- a/dtool/src/dtoolbase/deletedBufferChain.cxx +++ b/dtool/src/dtoolbase/deletedBufferChain.cxx @@ -39,7 +39,7 @@ allocate(size_t size, TypeHandle type_handle) { assert(size <= _buffer_size); // Determine how much space to allocate. - const size_t alloc_size = _buffer_size + flag_reserved_bytes + MemoryHook::get_memory_alignment() - 1; + const size_t alloc_size = _buffer_size + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1; ObjectNode *obj; @@ -71,8 +71,8 @@ allocate(size_t size, TypeHandle type_handle) { // Allocate memory, and make sure the object starts at the proper alignment. void *mem = NeverFreeMemory::alloc(alloc_size); - intptr_t pad = (-(intptr_t)flag_reserved_bytes - (intptr_t)mem) % MemoryHook::get_memory_alignment(); - obj = (ObjectNode *)((uintptr_t)mem + pad); + uintptr_t aligned = ((uintptr_t)mem + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1); + obj = (ObjectNode *)(aligned - flag_reserved_bytes); #ifdef USE_DELETEDCHAINFLAG obj->_flag = DCF_alive; @@ -81,7 +81,7 @@ allocate(size_t size, TypeHandle type_handle) { void *ptr = node_to_buffer(obj); #ifndef NDEBUG - assert(((uintptr_t)ptr % MemoryHook::get_memory_alignment()) == 0); + assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0); #endif #ifdef DO_MEMORY_USAGE diff --git a/dtool/src/dtoolbase/deletedChain.T b/dtool/src/dtoolbase/deletedChain.T index 5f50c9a36e..96e800ba3b 100644 --- a/dtool/src/dtoolbase/deletedChain.T +++ b/dtool/src/dtoolbase/deletedChain.T @@ -1,25 +1,22 @@ -// Filename: deletedChain.T -// Created by: drose (01Apr06) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file deletedChain.T + * @author drose + * @date 2006-04-01 + */ template DeletedChain StaticDeletedChain::_chain; -//////////////////////////////////////////////////////////////////// -// Function: DeletedChain::allocate -// Access: Public -// Description: Allocates the memory for a new object of Type. -//////////////////////////////////////////////////////////////////// +/** + * Allocates the memory for a new object of Type. + */ template INLINE Type *DeletedChain:: allocate(size_t size, TypeHandle type_handle) { @@ -31,14 +28,12 @@ allocate(size_t size, TypeHandle type_handle) { memory_hook->mark_pointer(ptr, _chain->get_buffer_size(), make_ref_ptr(ptr)); #endif // DO_MEMORY_USAGE - return (Type *)ptr; + return (Type *)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT); } -//////////////////////////////////////////////////////////////////// -// Function: DeletedChain::deallocate -// Access: Public -// Description: Frees the memory for an object of Type. -//////////////////////////////////////////////////////////////////// +/** + * Frees the memory for an object of Type. + */ template INLINE void DeletedChain:: deallocate(Type *ptr, TypeHandle type_handle) { @@ -57,16 +52,13 @@ deallocate(Type *ptr, TypeHandle type_handle) { _chain->deallocate(ptr, type_handle); } -//////////////////////////////////////////////////////////////////// -// Function: DeletedChain::validate -// Access: Public -// Description: Returns true if the pointer is valid, false if it has -// been deleted or if it was never a valid pointer. -// -// This is only meaningful in debug mode, where -// USE_DELETEDCHAINFLAG is defined. If not, this -// trivially returns true. -//////////////////////////////////////////////////////////////////// +/** + * Returns true if the pointer is valid, false if it has been deleted or if it + * was never a valid pointer. + * + * This is only meaningful in debug mode, where USE_DELETEDCHAINFLAG is + * defined. If not, this trivially returns true. + */ template INLINE bool DeletedChain:: validate(const Type *ptr) { @@ -80,48 +72,37 @@ validate(const Type *ptr) { #endif // USE_DELETEDCHAINFLAG } -//////////////////////////////////////////////////////////////////// -// Function: DeletedChain::make_ref_ptr -// Access: Public, Static -// Description: This method has two overloads: one that accepts a -// void *, and one that accepts a ReferenceCount *. We -// rely on the C++ compiler to select the most -// appropriate one for a given type to return the -// ReferenceCount pointer that corresponds to a -// particular type, or NULL if the type does not inherit -// from ReferenceCount. -//////////////////////////////////////////////////////////////////// +/** + * This method has two overloads: one that accepts a void *, and one that + * accepts a ReferenceCount *. We rely on the C++ compiler to select the most + * appropriate one for a given type to return the ReferenceCount pointer that + * corresponds to a particular type, or NULL if the type does not inherit from + * ReferenceCount. + */ template INLINE ReferenceCount *DeletedChain:: make_ref_ptr(void *) { return NULL; } -//////////////////////////////////////////////////////////////////// -// Function: DeletedChain::make_ref_ptr -// Access: Public, Static -// Description: This method has two overloads: one that accepts a -// void *, and one that accepts a ReferenceCount *. We -// rely on the C++ compiler to select the most -// appropriate one for a given type to return the -// ReferenceCount pointer that corresponds to a -// particular type, or NULL if the type does not inherit -// from ReferenceCount. -//////////////////////////////////////////////////////////////////// +/** + * This method has two overloads: one that accepts a void *, and one that + * accepts a ReferenceCount *. We rely on the C++ compiler to select the most + * appropriate one for a given type to return the ReferenceCount pointer that + * corresponds to a particular type, or NULL if the type does not inherit from + * ReferenceCount. + */ template INLINE ReferenceCount *DeletedChain:: make_ref_ptr(ReferenceCount *ptr) { return ptr; } -//////////////////////////////////////////////////////////////////// -// Function: DeletedChain::init_deleted_chain -// Access: Private -// Description: Assigns the _chain pointer if it is not already -// assigned. This can't be done by a constructor, since -// often the DeletedChain instance is used before its -// static construct has had a chance to be called. -//////////////////////////////////////////////////////////////////// +/** + * Assigns the _chain pointer if it is not already assigned. This can't be + * done by a constructor, since often the DeletedChain instance is used before + * its static construct has had a chance to be called. + */ template void DeletedChain:: init_deleted_chain() { @@ -131,38 +112,32 @@ init_deleted_chain() { } } -//////////////////////////////////////////////////////////////////// -// Function: StaticDeletedChain::allocate -// Access: Public, Static -// Description: Allocates the memory for a new object of Type. -//////////////////////////////////////////////////////////////////// +/** + * Allocates the memory for a new object of Type. + */ template INLINE Type *StaticDeletedChain:: allocate(size_t size, TypeHandle type_handle) { - return _chain.allocate(size, type_handle); + Type *ptr = _chain.allocate(size, type_handle); + return (Type *)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT); } -//////////////////////////////////////////////////////////////////// -// Function: StaticDeletedChain::deallocate -// Access: Public -// Description: Frees the memory for an object of Type. -//////////////////////////////////////////////////////////////////// +/** + * Frees the memory for an object of Type. + */ template INLINE void StaticDeletedChain:: deallocate(Type *ptr, TypeHandle type_handle) { _chain.deallocate(ptr, type_handle); } -//////////////////////////////////////////////////////////////////// -// Function: StaticDeletedChain::validate -// Access: Public -// Description: Returns true if the pointer is valid, false if it has -// been deleted or if it was never a valid pointer. -// -// This is only meaningful in debug mode, where -// USE_DELETEDCHAINFLAG is defined. If not, this -// trivially returns true. -//////////////////////////////////////////////////////////////////// +/** + * Returns true if the pointer is valid, false if it has been deleted or if it + * was never a valid pointer. + * + * This is only meaningful in debug mode, where USE_DELETEDCHAINFLAG is + * defined. If not, this trivially returns true. + */ template INLINE bool StaticDeletedChain:: validate(const Type *ptr) { diff --git a/dtool/src/dtoolbase/dtoolbase.h b/dtool/src/dtoolbase/dtoolbase.h index c6cbbd7f46..8dd2ec3cf6 100644 --- a/dtool/src/dtoolbase/dtoolbase.h +++ b/dtool/src/dtoolbase/dtoolbase.h @@ -89,6 +89,12 @@ #define NODEFAULT #endif +// Use this to hint the compiler that a memory address is aligned. +#if __has_builtin(__builtin_assume_aligned) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) +#define ASSUME_ALIGNED(x, y) (__builtin_assume_aligned(x, y)) +#else +#define ASSUME_ALIGNED(x, y) (x) +#endif /* include win32 defns for everything up to WinServer2003, and assume diff --git a/dtool/src/dtoolbase/dtoolbase_cc.h b/dtool/src/dtoolbase/dtoolbase_cc.h index 3d374748b6..88d4244af6 100644 --- a/dtool/src/dtoolbase/dtoolbase_cc.h +++ b/dtool/src/dtoolbase/dtoolbase_cc.h @@ -290,10 +290,10 @@ EXPCL_DTOOL void init_memory_hook(); // Now redefine some handy macros to hook into the above MemoryHook object. #ifndef USE_MEMORY_NOWRAPPERS -#define PANDA_MALLOC_SINGLE(size) (memory_hook->heap_alloc_single(size)) +#define PANDA_MALLOC_SINGLE(size) (ASSUME_ALIGNED(memory_hook->heap_alloc_single(size), MEMORY_HOOK_ALIGNMENT)) #define PANDA_FREE_SINGLE(ptr) memory_hook->heap_free_single(ptr) -#define PANDA_MALLOC_ARRAY(size) (memory_hook->heap_alloc_array(size)) -#define PANDA_REALLOC_ARRAY(ptr, size) (memory_hook->heap_realloc_array(ptr, size)) +#define PANDA_MALLOC_ARRAY(size) (ASSUME_ALIGNED(memory_hook->heap_alloc_array(size), MEMORY_HOOK_ALIGNMENT)) +#define PANDA_REALLOC_ARRAY(ptr, size) (ASSUME_ALIGNED(memory_hook->heap_realloc_array(ptr, size), MEMORY_HOOK_ALIGNMENT)) #define PANDA_FREE_ARRAY(ptr) memory_hook->heap_free_array(ptr) #else #define PANDA_MALLOC_SINGLE(size) ::malloc(size) diff --git a/dtool/src/dtoolbase/memoryHook.I b/dtool/src/dtoolbase/memoryHook.I index 3d2be05097..c89fe1908b 100644 --- a/dtool/src/dtoolbase/memoryHook.I +++ b/dtool/src/dtoolbase/memoryHook.I @@ -38,57 +38,9 @@ dec_heap(size_t size) { * Returns the global memory alignment. This is the number of bytes at which * each allocated memory pointer will be aligned. */ -INLINE size_t MemoryHook:: +CONSTEXPR size_t MemoryHook:: get_memory_alignment() { -#ifdef LINMATH_ALIGN - // We require 16-byte alignment of certain structures, to support SSE2. We - // don't strictly have to align *everything*, but it's just easier to do so. -#ifdef __AVX__ - // Eigen requires 32-byte alignment when using AVX instructions. - const size_t alignment_size = 32; -#else - const size_t alignment_size = 16; -#endif -#else - // Otherwise, align to two words. This seems to be pretty standard to the - // point where some code may rely on this being the case. - const size_t alignment_size = sizeof(void *) * 2; -#endif - return alignment_size; -} - -/** - * Returns the number of additional bytes that are reserved at the beginning - * of every allocated block to store a size_t. - */ -INLINE size_t MemoryHook:: -get_header_reserved_bytes() { - // We need to figure out the minimum amount of additional space we need in - // order to place a single word at the start of each allocated block, to - // store the size of the block. - -#ifdef LINMATH_ALIGN - // If we're doing SSE2 alignment, we must reserve a full 16-byte block, - // since anything less than that will spoil the alignment. -#ifdef __AVX__ - // Eigen requires 32-byte alignment when using AVX instructions. - static const size_t header_reserved_bytes = 32; -#else - static const size_t header_reserved_bytes = 16; -#endif - -#elif defined(MEMORY_HOOK_DO_ALIGN) - // If we're just aligning to words, we reserve a block as big as two words, - // to allow us wiggle room to align the word precisely within that block. - static const size_t header_reserved_bytes = sizeof(size_t) + sizeof(size_t); - -#else - // Virtually all allocators align to two words, so we make sure we preserve - // that alignment for the benefit of anyone who relies upon that. - static const size_t header_reserved_bytes = sizeof(void *) * 2; -#endif - - return header_reserved_bytes; + return MEMORY_HOOK_ALIGNMENT; } /** @@ -109,6 +61,24 @@ round_up_to_page_size(size_t size) const { return ((size + _page_size - 1) / _page_size) * _page_size; } +/** + * Given a pointer that was returned by a MemoryHook allocation, returns the + * number of bytes that were allocated for it. Returns 0 if not compiling + * with DO_MEMORY_USAGE. + */ +INLINE size_t MemoryHook:: +get_ptr_size(void *ptr) { +#if defined(MEMORY_HOOK_DO_ALIGN) + uintptr_t *root = (uintptr_t *)ptr; + return (size_t)root[-2]; +#elif defined(DO_MEMORY_USAGE) + size_t *root = (size_t *)((char *)ptr - MEMORY_HOOK_ALIGNMENT); + return *root; +#else + return 0; +#endif // DO_MEMORY_USAGE +} + /** * Increments the amount of requested size as necessary to accommodate the * extra data we might piggyback on each allocated block. @@ -118,12 +88,13 @@ inflate_size(size_t size) { #if defined(MEMORY_HOOK_DO_ALIGN) // If we're aligning, we need to request the header size, plus extra bytes // to give us wiggle room to adjust the pointer. - return size + get_header_reserved_bytes() + get_memory_alignment() - 1; + return size + sizeof(uintptr_t) * 2 + MEMORY_HOOK_ALIGNMENT - 1; #elif defined(DO_MEMORY_USAGE) // If we're not aligning, but we're tracking memory allocations, we just // need the header size extra (this gives us a place to store the size of - // the allocated block). - return size + get_header_reserved_bytes(); + // the allocated block). However, we do need to make sure that any + // alignment guarantee is kept. + return size + MEMORY_HOOK_ALIGNMENT; #else // If we're not doing any of that, we can just allocate the precise // requested amount. @@ -138,17 +109,17 @@ inflate_size(size_t size) { INLINE void *MemoryHook:: alloc_to_ptr(void *alloc, size_t size) { #if defined(MEMORY_HOOK_DO_ALIGN) - size_t alignment = get_memory_alignment(); - // Move the allocated pointer up to the next even alignment. - size_t *root = (size_t *)((((size_t)alloc + alignment - 1) / alignment) * alignment); - assert(alloc <= root && (size_t)((char *)root - (char *)alloc) < alignment); - root[0] = size; - root[1] = (size_t)alloc; // Save the pointer we originally allocated. - return (void *)((char *)root + get_header_reserved_bytes()); + // Add room for two uintptr_t values. + uintptr_t *root = (uintptr_t *)((char *)alloc + sizeof(uintptr_t) * 2); + // Align this to the requested boundary. + root = (uintptr_t *)(((uintptr_t)root + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1)); + root[-2] = size; + root[-1] = (uintptr_t)alloc; // Save the pointer we originally allocated. + return (void *)root; #elif defined(DO_MEMORY_USAGE) size_t *root = (size_t *)alloc; root[0] = size; - return (void *)((char *)root + get_header_reserved_bytes()); + return (void *)((char *)root + MEMORY_HOOK_ALIGNMENT); #else return alloc; #endif // DO_MEMORY_USAGE @@ -161,13 +132,11 @@ alloc_to_ptr(void *alloc, size_t size) { INLINE void *MemoryHook:: ptr_to_alloc(void *ptr, size_t &size) { #if defined(MEMORY_HOOK_DO_ALIGN) - size_t *root = (size_t *)((char *)ptr - get_header_reserved_bytes()); - size = root[0]; - void *alloc = (void *)root[1]; // Get the pointer we originally allocated. - assert(alloc <= root && (size_t)((char *)root - (char *)alloc) < get_memory_alignment()); - return alloc; + uintptr_t *root = (uintptr_t *)ptr; + size = root[-2]; + return (void *)root[-1]; // Get the pointer we originally allocated. #elif defined(DO_MEMORY_USAGE) - size_t *root = (size_t *)((char *)ptr - get_header_reserved_bytes()); + size_t *root = (size_t *)((char *)ptr - MEMORY_HOOK_ALIGNMENT); size = root[0]; return (void *)root; #else diff --git a/dtool/src/dtoolbase/memoryHook.cxx b/dtool/src/dtoolbase/memoryHook.cxx index e6131a5266..506ff51005 100644 --- a/dtool/src/dtoolbase/memoryHook.cxx +++ b/dtool/src/dtoolbase/memoryHook.cxx @@ -36,6 +36,15 @@ #endif // WIN32 +// Ensure we made the right decisions about the alignment size. +static_assert(MEMORY_HOOK_ALIGNMENT >= sizeof(size_t), + "MEMORY_HOOK_ALIGNMENT should at least be sizeof(size_t)"); +static_assert(MEMORY_HOOK_ALIGNMENT >= sizeof(void *), + "MEMORY_HOOK_ALIGNMENT should at least be sizeof(void *)"); +static_assert(MEMORY_HOOK_ALIGNMENT * 8 >= NATIVE_WORDSIZE, + "MEMORY_HOOK_ALIGNMENT * 8 should at least be NATIVE_WORDSIZE"); +static_assert((MEMORY_HOOK_ALIGNMENT & (MEMORY_HOOK_ALIGNMENT - 1)) == 0, + "MEMORY_HOOK_ALIGNMENT should be a power of two"); #if defined(USE_MEMORY_DLMALLOC) @@ -49,17 +58,8 @@ #ifdef _DEBUG #define DEBUG 1 #endif -#ifdef LINMATH_ALIGN -// drose: We require 16-byte alignment of certain structures, to -// support SSE2. We don't strictly have to align *everything*, but -// it's just easier to do so. -#ifdef __AVX__ -// Eigen requires 32-byte alignment when using AVX instructions. -#define MALLOC_ALIGNMENT ((size_t)32U) -#else -#define MALLOC_ALIGNMENT ((size_t)16U) -#endif -#endif +// dlmalloc can do the alignment we ask for. +#define MALLOC_ALIGNMENT MEMORY_HOOK_ALIGNMENT #include "dlmalloc_src.cxx" @@ -204,6 +204,7 @@ heap_alloc_single(size_t size) { #endif // DO_MEMORY_USAGE void *ptr = alloc_to_ptr(alloc, size); + assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0); assert(ptr >= alloc && (char *)ptr + size <= (char *)alloc + inflated_size); return ptr; } @@ -273,6 +274,7 @@ heap_alloc_array(size_t size) { #endif // DO_MEMORY_USAGE void *ptr = alloc_to_ptr(alloc, size); + assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0); assert(ptr >= alloc && (char *)ptr + size <= (char *)alloc + inflated_size); return ptr; } @@ -316,17 +318,27 @@ heap_realloc_array(void *ptr, size_t size) { #endif } - void *ptr1 = alloc_to_ptr(alloc1, size); - assert(ptr1 >= alloc1 && (char *)ptr1 + size <= (char *)alloc1 + inflated_size); -#if defined(MEMORY_HOOK_DO_ALIGN) - // We might have to shift the memory to account for the new offset due to - // the alignment. + // Align this to the requested boundary. +#ifdef MEMORY_HOOK_DO_ALIGN + // This copies the code from alloc_to_ptr, since we can't write the size and + // pointer until after we have done the memmove. + uintptr_t *root = (uintptr_t *)((char *)alloc1 + sizeof(uintptr_t) * 2); + root = (uintptr_t *)(((uintptr_t)root + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1)); + void *ptr1 = (void *)root; + size_t orig_delta = (char *)ptr - (char *)alloc; size_t new_delta = (char *)ptr1 - (char *)alloc1; if (orig_delta != new_delta) { memmove((char *)alloc1 + new_delta, (char *)alloc1 + orig_delta, min(size, orig_size)); } -#endif // MEMORY_HOOK_DO_ALIGN + + root[-2] = size; + root[-1] = (uintptr_t)alloc1; // Save the pointer we originally allocated. +#else + void *ptr1 = alloc_to_ptr(alloc1, size); +#endif + assert(ptr1 >= alloc1 && (char *)ptr1 + size <= (char *)alloc1 + inflated_size); + assert(((uintptr_t)ptr1 % MEMORY_HOOK_ALIGNMENT) == 0); return ptr1; } diff --git a/dtool/src/dtoolbase/memoryHook.h b/dtool/src/dtoolbase/memoryHook.h index d53e03ba2e..b8eac26f54 100644 --- a/dtool/src/dtoolbase/memoryHook.h +++ b/dtool/src/dtoolbase/memoryHook.h @@ -20,6 +20,22 @@ #include "mutexImpl.h" #include +#ifdef LINMATH_ALIGN +// We require 16-byte alignment of certain structures, to support SSE2. We +// don't strictly have to align *everything*, but it's just easier to do so. +#ifdef __AVX__ +#define MEMORY_HOOK_ALIGNMENT 32 +#else +#define MEMORY_HOOK_ALIGNMENT 16 +#endif +// Otherwise, align to two words. This seems to be pretty standard to the +// point where some code may rely on this being the case. +#elif defined(IS_OSX) || NATIVE_WORDSIZE >= 64 +#define MEMORY_HOOK_ALIGNMENT 16 +#else +#define MEMORY_HOOK_ALIGNMENT 8 +#endif + class DeletedBufferChain; /** @@ -52,8 +68,7 @@ public: bool heap_trim(size_t pad); - INLINE static size_t get_memory_alignment(); - INLINE static size_t get_header_reserved_bytes(); + CONSTEXPR static size_t get_memory_alignment(); virtual void *mmap_alloc(size_t size, bool allow_exec); virtual void mmap_free(void *ptr, size_t size); @@ -66,6 +81,8 @@ public: virtual void alloc_fail(size_t attempted_size); + INLINE static size_t get_ptr_size(void *ptr); + private: INLINE static size_t inflate_size(size_t size); INLINE static void *alloc_to_ptr(void *alloc, size_t size); diff --git a/dtool/src/dtoolbase/pallocator.T b/dtool/src/dtoolbase/pallocator.T index ebfb8dbafd..38bc87135c 100644 --- a/dtool/src/dtoolbase/pallocator.T +++ b/dtool/src/dtoolbase/pallocator.T @@ -1,16 +1,15 @@ -// Filename: pallocator.T -// Created by: drose (05Jun01) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) Carnegie Mellon University. All rights reserved. -// -// All use of this software is subject to the terms of the revised BSD -// license. You should have received a copy of this license along -// with this source code in a file named "LICENSE." -// -//////////////////////////////////////////////////////////////////// +/** + * PANDA 3D SOFTWARE + * Copyright (c) Carnegie Mellon University. All rights reserved. + * + * All use of this software is subject to the terms of the revised BSD + * license. You should have received a copy of this license along + * with this source code in a file named "LICENSE." + * + * @file pallocator.T + * @author drose + * @date 2001-06-05 + */ template INLINE pallocator_single:: @@ -25,7 +24,8 @@ allocate(TYPENAME pallocator_single::size_type n, TYPENAME allocator TAU_PROFILE("pallocator_single:allocate()", " ", TAU_USER); // This doesn't support allocating arrays. assert(n == 1); - return StaticDeletedChain::allocate(sizeof(Type), _type_handle); + return (Type *)ASSUME_ALIGNED(StaticDeletedChain::allocate(sizeof(Type), _type_handle), + MEMORY_HOOK_ALIGNMENT); } template @@ -47,14 +47,13 @@ INLINE TYPENAME pallocator_array::pointer pallocator_array:: allocate(TYPENAME pallocator_array::size_type n, TYPENAME allocator::const_pointer) { TAU_PROFILE("pallocator_array:allocate()", " ", TAU_USER); #ifdef DO_MEMORY_USAGE - const size_t header_reserved_bytes = MemoryHook::get_header_reserved_bytes(); size_t alloc_size = n * sizeof(Type); - // We also need to store the total number of bytes we allocated. - alloc_size += header_reserved_bytes; - _type_handle.inc_memory_usage(TypeHandle::MC_array, alloc_size); void *ptr = (TYPENAME pallocator_array::pointer)PANDA_MALLOC_ARRAY(alloc_size); - *((size_t *)ptr) = alloc_size; - return (TYPENAME pallocator_array::pointer)(((char *)ptr) + header_reserved_bytes); +#ifdef _DEBUG + assert(alloc_size == MemoryHook::get_ptr_size(ptr)); +#endif + _type_handle.inc_memory_usage(TypeHandle::MC_array, alloc_size); + return (TYPENAME pallocator_array::pointer)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT); #else return (TYPENAME pallocator_array::pointer)PANDA_MALLOC_ARRAY(n * sizeof(Type)); #endif // DO_MEMORY_USAGE @@ -65,10 +64,10 @@ INLINE void pallocator_array:: deallocate(TYPENAME pallocator_array::pointer p, TYPENAME pallocator_array::size_type) { TAU_PROFILE("pallocator_array:deallocate()", " ", TAU_USER); #ifdef DO_MEMORY_USAGE - // Now we need to recover the total number of bytes. - const size_t header_reserved_bytes = MemoryHook::get_header_reserved_bytes(); - void *ptr = (void *)((char *)p - header_reserved_bytes); - size_t alloc_size = *((size_t *)ptr); + // Now we need to recover the total number of bytes. Fortunately, in the + // case of DO_MEMORY_USAGE, MemoryHook already keeps track of this. + void *ptr = (void *)p; + size_t alloc_size = MemoryHook::get_ptr_size(ptr); _type_handle.dec_memory_usage(TypeHandle::MC_array, alloc_size); PANDA_FREE_ARRAY(ptr); #else diff --git a/panda/src/gobj/vertexDataBuffer.I b/panda/src/gobj/vertexDataBuffer.I index 3652bae864..3bc1f85b80 100644 --- a/panda/src/gobj/vertexDataBuffer.I +++ b/panda/src/gobj/vertexDataBuffer.I @@ -67,17 +67,22 @@ INLINE const unsigned char *VertexDataBuffer:: get_read_pointer(bool force) const { LightMutexHolder holder(_lock); + const unsigned char *ptr; if (_resident_data != (unsigned char *)NULL || _size == 0) { - return _resident_data; + ptr = _resident_data; + } else { + nassertr(_block != (VertexDataBlock *)NULL, NULL); + nassertr(_reserved_size >= _size, NULL); + + // We don't necessarily need to page the buffer all the way into independent + // status; it's sufficient just to return the block's pointer, which will + // force its page to resident status. + ptr = _block->get_pointer(force); } - - nassertr(_block != (VertexDataBlock *)NULL, NULL); - nassertr(_reserved_size >= _size, NULL); - - // We don't necessarily need to page the buffer all the way into independent - // status; it's sufficient just to return the block's pointer, which will - // force its page to resident status. - return _block->get_pointer(force); +#ifdef _DEBUG + assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0); +#endif + return (const unsigned char *)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT); } /** @@ -91,7 +96,10 @@ get_write_pointer() { do_page_in(); } nassertr(_reserved_size >= _size, NULL); - return _resident_data; +#ifdef _DEBUG + assert(((uintptr_t)_resident_data % MEMORY_HOOK_ALIGNMENT) == 0); +#endif + return (unsigned char *)ASSUME_ALIGNED(_resident_data, MEMORY_HOOK_ALIGNMENT); } /**