New alignment code to hopefully fix the alignment issues

This commit is contained in:
rdb 2017-02-10 02:57:47 +01:00
parent fdffcc280b
commit 2acde88695
9 changed files with 198 additions and 212 deletions

View File

@ -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

View File

@ -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<class Type>
DeletedChain<Type> StaticDeletedChain<Type>::_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<class Type>
INLINE Type *DeletedChain<Type>::
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<class Type>
INLINE void DeletedChain<Type>::
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<class Type>
INLINE bool DeletedChain<Type>::
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<class Type>
INLINE ReferenceCount *DeletedChain<Type>::
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<class Type>
INLINE ReferenceCount *DeletedChain<Type>::
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<class Type>
void DeletedChain<Type>::
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<class Type>
INLINE Type *StaticDeletedChain<Type>::
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<class Type>
INLINE void StaticDeletedChain<Type>::
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<class Type>
INLINE bool StaticDeletedChain<Type>::
validate(const Type *ptr) {

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -20,6 +20,22 @@
#include "mutexImpl.h"
#include <map>
#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);

View File

@ -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<class Type>
INLINE pallocator_single<Type>::
@ -25,7 +24,8 @@ allocate(TYPENAME pallocator_single<Type>::size_type n, TYPENAME allocator<void>
TAU_PROFILE("pallocator_single:allocate()", " ", TAU_USER);
// This doesn't support allocating arrays.
assert(n == 1);
return StaticDeletedChain<Type>::allocate(sizeof(Type), _type_handle);
return (Type *)ASSUME_ALIGNED(StaticDeletedChain<Type>::allocate(sizeof(Type), _type_handle),
MEMORY_HOOK_ALIGNMENT);
}
template<class Type>
@ -47,14 +47,13 @@ INLINE TYPENAME pallocator_array<Type>::pointer pallocator_array<Type>::
allocate(TYPENAME pallocator_array<Type>::size_type n, TYPENAME allocator<void>::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<Type>::pointer)PANDA_MALLOC_ARRAY(alloc_size);
*((size_t *)ptr) = alloc_size;
return (TYPENAME pallocator_array<Type>::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<Type>::pointer)ASSUME_ALIGNED(ptr, MEMORY_HOOK_ALIGNMENT);
#else
return (TYPENAME pallocator_array<Type>::pointer)PANDA_MALLOC_ARRAY(n * sizeof(Type));
#endif // DO_MEMORY_USAGE
@ -65,10 +64,10 @@ INLINE void pallocator_array<Type>::
deallocate(TYPENAME pallocator_array<Type>::pointer p, TYPENAME pallocator_array<Type>::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

View File

@ -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);
}
/**