Files
GTASource/rage/scaleform/Src/GKernel/HeapMH/GHeapRootMH.h
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

259 lines
7.4 KiB
C++

/**********************************************************************
Filename : GHeapRootMH.h
Content : Heap root used for bootstrapping and bookkeeping.
:
Created : 2009
Authors : Maxim Shemanarev
Copyright : (c) 2008 Scaleform Corp. All Rights Reserved.
Licensees may use this file in accordance with the valid Scaleform
Commercial License Agreement provided with the software.
This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR ANY PURPOSE.
**********************************************************************/
#ifndef INC_GHeapRootMH_H
#define INC_GHeapRootMH_H
#include "GAtomic.h"
#include "GMemoryHeapMH.h"
#include "GSysAlloc.h"
#include "GRadixTree.h"
//------------------------------------------------------------------------
struct GHeapPageMH : public GListNode<GHeapPageMH>
{
enum
{
PageSize = 4096,
PageMask = PageSize-1,
UnitShift = 4,
UnitSize = 1 << UnitShift,
UnitMask = UnitSize - 1,
BitSetBytes = PageSize/UnitSize/4,
MaxBytes = 512
};
GMemoryHeapMH *pHeap; // Heap this page belongs to.
UByte* Start;
};
//------------------------------------------------------------------------
struct GPageTableMH
{
enum
{
Index1Shift = 7,
TableSize = 1 << Index1Shift,
Index0Mask = TableSize - 1
};
struct Level0Entry
{
GHeapPageMH* FirstPage;
UPInt SizeMask;
};
Level0Entry Entries[TableSize];
};
struct GHeapDebugDataMH;
//------------------------------------------------------------------------
struct GHeapMagicHeader
{
enum { MagicValue = 0x5FC0 }; // "SFCO" - Scaleform Corporation
UInt16 Magic; // Magic marker
UInt16 UseCount; // Existing allocation count
UInt32 Index; // 2-component index in page tables
GHeapDebugDataMH* DebugHeader;
#ifndef GFC_64BIT_POINTERS
UInt32 Filler;
#endif
UInt32 GetIndex0() const { return Index & GPageTableMH::Index0Mask; }
UInt32 GetIndex1() const { return Index >> GPageTableMH::Index1Shift; }
};
//------------------------------------------------------------------------
struct GHeapNodeMH
{
enum { Align4 = 0, Align8 = 1, Align16 = 2, MoreInfo = 3 };
GHeapNodeMH* Parent;
GHeapNodeMH* Child[2];
UPInt pHeap;
#ifdef GHEAP_DEBUG_INFO
GHeapDebugDataMH* DebugHeader;
#endif
//------------------ Optional data
UPInt Align;
static UPInt GetNodeSize(UPInt align)
{
UPInt size = 4*sizeof(void*);
#ifdef GHEAP_DEBUG_INFO
size += sizeof(void*);
#endif
return (align <= 16) ? size : size + sizeof(UPInt);
}
GMemoryHeapMH* GetHeap() const
{
return (GMemoryHeapMH*)(pHeap & ~UPInt(3));
}
UPInt GetAlign() const
{
return ((pHeap & 3) < 3) ? (UPInt(1) << ((pHeap & 3) + 2)) : Align;
}
void SetHeap(GMemoryHeapMH* heap, UPInt align)
{
switch(align)
{
case 1: case 2: case 4:
pHeap = UPInt(heap);
break;
case 8:
pHeap = UPInt(heap) | Align8;
break;
case 16:
pHeap = UPInt(heap) | Align16;
break;
default:
pHeap = UPInt(heap) | MoreInfo;
Align = align;
break;
}
}
};
//--------------------------------------------------------------------
struct GHeapTreeNodeAccessor
{
static UPInt GetKey (const GHeapNodeMH* n) { return UPInt(n); }
static GHeapNodeMH* GetChild ( GHeapNodeMH* n, UPInt i) { return n->Child[i]; }
static const GHeapNodeMH* GetChild (const GHeapNodeMH* n, UPInt i) { return n->Child[i]; }
static GHeapNodeMH** GetChildPtr( GHeapNodeMH* n, UPInt i) { return &n->Child[i]; }
static GHeapNodeMH* GetParent ( GHeapNodeMH* n) { return n->Parent; }
static const GHeapNodeMH* GetParent (const GHeapNodeMH* n) { return n->Parent; }
static void SetParent (GHeapNodeMH* n, GHeapNodeMH* p) { n->Parent = p; }
static void SetChild (GHeapNodeMH* n, UPInt i, GHeapNodeMH* c) { n->Child[i] = c; }
static void ClearLinks(GHeapNodeMH* n) { n->Parent = n->Child[0] = n->Child[1] = 0; }
};
//------------------------------------------------------------------------
struct GHeapMagicHeadersInfo
{
GHeapMagicHeader* Header1; // Header on the left ptr or 0
GHeapMagicHeader* Header2; // Header on the right ptr or 0
UInt32* BitSet; // Pointer to the bitset
UByte* AlignedStart; // Pointer to the beginning of the page, aligned
UByte* AlignedEnd; // Pointer to the end of the page, aligned
UByte* Bound; // The bound between physical pages
GHeapPageMH* Page; // Page, null after GetMagicHeaders()
};
//------------------------------------------------------------------------
struct GHeapPageInfoMH
{
#ifdef GHEAP_DEBUG_INFO
GHeapDebugDataMH** DebugHeaders[3];
#endif
GHeapPageMH* Page;
GHeapNodeMH* Node;
UPInt UsableSize;
};
//------------------------------------------------------------------------
void GHeapGetMagicHeaders(UPInt pageStart, GHeapMagicHeadersInfo* headers);
//------------------------------------------------------------------------
class GHeapRootMH
{
typedef GRadixTree<GHeapNodeMH, GHeapTreeNodeAccessor> HeapTreeType;
public:
GHeapRootMH(GSysAlloc* sysAlloc);
~GHeapRootMH();
void FreeTables();
GSysAlloc* GetSysAlloc() { return pSysAlloc; }
GMemoryHeapMH* CreateHeap(const char* name,
GMemoryHeapMH* parent,
const GMemoryHeap::HeapDesc& desc);
void DestroyHeap(GMemoryHeapMH* heap);
GLockSafe* GetLock() { return &RootLock; }
GHeapPageMH* AllocPage(GMemoryHeapMH* heap);
void FreePage(GHeapPageMH* page);
UInt32 GetPageIndex(const GHeapPageMH* page) const;
GHeapPageMH* ResolveAddress(UPInt addr) const;
GHeapNodeMH* AddToGlobalTree(UByte* ptr, UPInt size, UPInt align, GMemoryHeapMH* heap)
{
GHeapNodeMH* node = (GHeapNodeMH*)(ptr + size);
node->SetHeap(heap, align);
#ifdef GHEAP_DEBUG_INFO
node->DebugHeader = 0;
#endif
HeapTree.Insert(node);
return node;
}
GHeapNodeMH* FindNodeInGlobalTree(UByte* ptr)
{
return (GHeapNodeMH*)HeapTree.FindGrEq(UPInt(ptr));
}
void RemoveFromGlobalTree(GHeapNodeMH* node)
{
HeapTree.Remove(node);
}
#ifdef GHEAP_TRACE_ALL
void OnAlloc(const GMemoryHeapMH* heap, UPInt size, UPInt align, unsigned sid, const void* ptr);
void OnRealloc(const GMemoryHeapMH* heap, const void* oldPtr, UPInt newSize, const void* newPtr);
void OnFree(const GMemoryHeapMH* heap, const void* ptr);
static GMemoryHeap::HeapTracer* pTracer; // RAGE - moved into #ifdef region
#endif
private:
bool allocPagePool();
static void setMagic(UByte* pageStart, unsigned magicValue);
GSysAlloc* pSysAlloc;
mutable GLockSafe RootLock;
GList<GHeapPageMH> FreePages;
unsigned TableCount;
HeapTreeType HeapTree;
};
extern GHeapRootMH* GHeapGlobalRootMH;
extern GPageTableMH GHeapGlobalPageTableMH;
extern GHeapPageMH GHeapGlobalEmptyPage;
#endif