1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
#ifndef ALLOCATION_HEADER_H_
#define ALLOCATION_HEADER_H_
#if ENABLE_MEMORY_MANAGER
#include "Runtime/Profiler/MemoryProfiler.h"
#define USE_MEMORY_DEBUGGING (!UNITY_RELEASE && !(UNITY_LINUX && UNITY_64))
#if UNITY_LINUX
#pragma warning "FIXME LINUX: 64bit memory debugging"
#endif
/*
Allocation Header:
(12345hhhhhhhhmmmm____________) (1-n:paddingcount, h: header, m:memoryprofiler)
hasPadding: 1 bit
size: 31 bit
*********USE_MEMORY_DEBUGGING*********
allocator: 16 bit
magicValue: 12 bit
*********USE_MEMORY_DEBUGGING*********
---------------
Followed by x bytes requested by MemoryProfiler
----------------------------------------
Actual Allocated Data
----------------------------------------
*********USE_MEMORY_DEBUGGING*********
Followed by a footer if memory guarding is enabled
*********USE_MEMORY_DEBUGGING*********
*/
struct AllocationHeader
{
public:
static void Set(void* ptr, int id, int size, int padCount, int align);
static AllocationHeader* GetHeader(const void* ptr);
static ProfilerAllocationHeader* GetProfilerHeader(const void* ptr);
UInt32 GetPadding () const { return m_HasPadding ? *(((UInt32*)(this))-1) : 0; }
size_t GetRequestedSize () const { return m_AllocationSize; }
static size_t CalculateNeededAllocationSize( size_t size, int align );
static void ValidateIntegrity(void* ptr, int id, int align = -1);
static void* GetRealPointer( void* ptr );
static int GetRequiredPadding(void* realptr, int align);
static int GetHeaderSize();
static AllocationHeader* GetHeaderFromRealPointer( const void* realptr );
int GetOverheadSize();
private:
// prev byte is padding count, if there is padding
UInt32 m_HasPadding : 1;
UInt32 m_AllocationSize : 31;
#if USE_MEMORY_DEBUGGING
// DEBUG:
SInt16 m_AllocatorIdentifier;
UInt16 m_Magic : 12;
static const UInt32 kMagicValue = 0xDFA;
static const UInt32 kFooterSize = 4;
#else
static const UInt32 kFooterSize = 0;
#endif
// followed by x bytes used for memory profiling header (0 if no memory profiling)
};
inline void AllocationHeader::Set(void* ptr, int id, int size, int padCount, int align)
{
AllocationHeader* header = GetHeader(ptr);
header->m_AllocationSize = size;
header->m_HasPadding = padCount != 0;
if(header->m_HasPadding)
*(((UInt32*)(header))-1) = padCount;
#if USE_MEMORY_DEBUGGING
// set header
if(header->m_HasPadding) // set leading bytes
memset(((char*)header)-padCount,0xAA,padCount-4);
header->m_AllocatorIdentifier = id;
header->m_Magic = kMagicValue;
// set footer
memset(((char*)ptr)+size,0xFD,kFooterSize);
#endif
}
inline ProfilerAllocationHeader* AllocationHeader::GetProfilerHeader( const void* ptr )
{
return (ProfilerAllocationHeader*)( (const char*)ptr - MemoryProfiler::GetHeaderSize() );
}
inline AllocationHeader* AllocationHeader::GetHeader( const void* ptr )
{
return (AllocationHeader*)( (const char*)ptr - GetHeaderSize() );
}
inline int AllocationHeader::GetHeaderSize()
{
return sizeof(AllocationHeader) + MemoryProfiler::GetHeaderSize();
}
inline int AllocationHeader::GetRequiredPadding( void* realptr, int align )
{
return align - ((((int)realptr + GetHeaderSize() - 1)&(align - 1)) + 1);
}
inline size_t AllocationHeader::CalculateNeededAllocationSize( size_t size, int align )
{
int alignMask = align-1;
return size + GetHeaderSize() + kFooterSize + alignMask;
}
inline void* AllocationHeader::GetRealPointer( void* ptr )
{
AllocationHeader* header = GetHeader(ptr);
int padCount = header->GetPadding();
return ((char*)header) - padCount;
}
inline int AllocationHeader::GetOverheadSize()
{
int alignMask = kDefaultMemoryAlignment-1; // estimate
return GetHeaderSize() + kFooterSize + alignMask;
}
inline AllocationHeader* AllocationHeader::GetHeaderFromRealPointer( const void* realptr )
{
#if USE_MEMORY_DEBUGGING
unsigned char* ptr = (unsigned char*)realptr;
while(*ptr == 0xAA)
ptr++;
AllocationHeader* header = (AllocationHeader*)ptr;
if(header->m_Magic != kMagicValue)
header = (AllocationHeader*)(ptr+4);
return header;
#else
return NULL;
#endif
}
inline void AllocationHeader::ValidateIntegrity( void* ptr, int id, int /*align*/ )
{
#if USE_MEMORY_DEBUGGING
AllocationHeader* header = GetHeader(ptr);
Assert(header->m_Magic == AllocationHeader::kMagicValue);
Assert(id == -1 || id == header->m_AllocatorIdentifier);
int size = header->m_AllocationSize;
unsigned char* footer = ((unsigned char*)ptr)+size;
for(int i = 0; i < kFooterSize; i++, footer++)
Assert(*footer == 0xFD);
#endif
}
#endif
#endif
|