sourcemod/knight/shared/KePageAllocator.cpp
David Anderson 7875fe1acd Landed sourcepawn-1.2. The big changes:
1) JIT compilation/optimization now occurs per-function, and only when functions are first used.  We're now officially a whole-method JIT rather than an AOT compiler (albiet, still a simple JIT).  This has two implications: Functions are now much better abstracted internally, and loading a plugin is now much less expensive.  If a function contains calls to other functions, THOSE functions are only compiled when they're invoked as well.

2) I've removed debug mode.  We always show full backtraces now, as there was a very cheap way to implement this which really cleaned up everything.  This is great for a number of reasons -- there's less code, the JIT is better designed, we don't need to relocate debug tables, and best of all we no longer have to tell users to enable debug mode at their own expense.

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%402459
2008-08-15 05:22:26 +00:00

149 lines
2.7 KiB
C++

#include "KePageAllocator.h"
using namespace Knight;
struct PageInfo
{
PageInfo *next;
void *base;
};
class Knight::KePageAllocator
{
public:
size_t page_size;
size_t page_granularity;
PageInfo *free_pages;
PageInfo *page_blocks;
};
static void *ke_LumpPageAlloc(KePageAllocator *alloc)
{
void *base;
char *page;
PageInfo *lump;
size_t pagesInBlock;
#if defined KE_PLATFORM_WINDOWS
base = VirtualAlloc(
NULL,
alloc->page_granularity,
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);
#elif defined KE_PLATFORM_POSIX
base = valloc(alloc->page_granularity);
#else
#error "Unsupported platform"
#endif
if (base == NULL)
{
return NULL;
}
lump = new PageInfo;
lump->base = base;
lump->next = alloc->page_blocks;
alloc->page_blocks = lump->next;
page = (char *)base + alloc->page_size;
pagesInBlock = alloc->page_granularity / alloc->page_size;
for (size_t i = 1; i < pagesInBlock; i++)
{
lump = new PageInfo;
lump->base = page;
lump->next = alloc->free_pages;
alloc->free_pages = lump;
page += alloc->page_size;
}
return base;
}
KePageAllocator *Knight::KE_CreatePageAllocator()
{
KePageAllocator *alloc;
alloc = new KePageAllocator;
#if defined KE_PLATFORM_WINDOWS
SYSTEM_INFO info;
GetSystemInfo(&info);
alloc->page_size = info.dwPageSize;
alloc->page_granularity = info.dwAllocationGranularity;
#elif defined KE_PLATFORM_POSIX
alloc->page_size = sysconf(_SC_PAGESIZE);
alloc->page_granularity = alloc->page_size * 16;
#else
#error "Unsupported platform"
#endif
alloc->free_pages = NULL;
alloc->page_blocks = NULL;
return alloc;
}
void Knight::KE_DestroyPageAllocator(KePageAllocator *alloc)
{
PageInfo *info, *next;
info = alloc->page_blocks;
while (info != NULL)
{
next = info->next;
#if defined KE_PLATFORM_WINDOWS
VirtualFree(info->base, 0, MEM_RELEASE);
#elif defined KE_PLATFORM_WINDOWS
free(info->base);
#else
#error "Unsupported platform"
#endif
delete info;
next = info;
}
info = alloc->free_pages;
while (info != NULL)
{
next = info->next;
delete info;
info = next;
}
}
void *Knight::KE_PageAlloc(KePageAllocator *alloc)
{
if (alloc->free_pages != NULL)
{
void *base;
PageInfo *info;
info = alloc->free_pages;
alloc->free_pages = info->next;
base = info->base;
delete info;
return base;
}
return ke_LumpPageAlloc(alloc);
}
void Knight::KE_PageFree(KePageAllocator *alloc, void *page)
{
PageInfo *info;
info = new PageInfo;
info->base = page;
info->next = alloc->free_pages;
alloc->free_pages = info->next;
}
size_t Knight::KE_PageSize(KePageAllocator *alloc)
{
return alloc->page_size;
}