mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -04:00
New alignment code to hopefully fix the alignment issues
This commit is contained in:
parent
fdffcc280b
commit
2acde88695
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user