knight/shared/KePageAllocator.cpp
author David Anderson <dvander@alliedmods.net>
Fri Aug 15 05:22:26 2008 +0000 (2008-08-15)
changeset 2226 d10b38524be3
permissions -rw-r--r--
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.
dvander@2226
     1
#include "KePageAllocator.h"
dvander@2226
     2
dvander@2226
     3
using namespace Knight;
dvander@2226
     4
dvander@2226
     5
struct PageInfo
dvander@2226
     6
{
dvander@2226
     7
	PageInfo *next;
dvander@2226
     8
	void *base;
dvander@2226
     9
};
dvander@2226
    10
dvander@2226
    11
class Knight::KePageAllocator
dvander@2226
    12
{
dvander@2226
    13
public:
dvander@2226
    14
	size_t page_size;
dvander@2226
    15
	size_t page_granularity;
dvander@2226
    16
	PageInfo *free_pages;
dvander@2226
    17
	PageInfo *page_blocks;
dvander@2226
    18
};
dvander@2226
    19
dvander@2226
    20
static void *ke_LumpPageAlloc(KePageAllocator *alloc)
dvander@2226
    21
{
dvander@2226
    22
	void *base;
dvander@2226
    23
	char *page;
dvander@2226
    24
	PageInfo *lump;
dvander@2226
    25
	size_t pagesInBlock;
dvander@2226
    26
dvander@2226
    27
#if defined KE_PLATFORM_WINDOWS
dvander@2226
    28
	base = VirtualAlloc(
dvander@2226
    29
		NULL,
dvander@2226
    30
		alloc->page_granularity,
dvander@2226
    31
		MEM_COMMIT|MEM_RESERVE,
dvander@2226
    32
		PAGE_READWRITE);
dvander@2226
    33
#elif defined KE_PLATFORM_POSIX
dvander@2226
    34
	base = valloc(alloc->page_granularity);
dvander@2226
    35
#else 
dvander@2226
    36
#error "Unsupported platform"
dvander@2226
    37
#endif
dvander@2226
    38
dvander@2226
    39
	if (base == NULL)
dvander@2226
    40
	{
dvander@2226
    41
		return NULL;
dvander@2226
    42
	}
dvander@2226
    43
dvander@2226
    44
	lump = new PageInfo;
dvander@2226
    45
	lump->base = base;
dvander@2226
    46
	lump->next = alloc->page_blocks;
dvander@2226
    47
	alloc->page_blocks = lump->next;
dvander@2226
    48
dvander@2226
    49
	page = (char *)base + alloc->page_size;
dvander@2226
    50
	pagesInBlock = alloc->page_granularity / alloc->page_size;
dvander@2226
    51
dvander@2226
    52
	for (size_t i = 1; i < pagesInBlock; i++)
dvander@2226
    53
	{
dvander@2226
    54
		lump = new PageInfo;
dvander@2226
    55
		lump->base = page;
dvander@2226
    56
		lump->next = alloc->free_pages;
dvander@2226
    57
		alloc->free_pages = lump;
dvander@2226
    58
		page += alloc->page_size;
dvander@2226
    59
	}
dvander@2226
    60
dvander@2226
    61
	return base;
dvander@2226
    62
}
dvander@2226
    63
dvander@2226
    64
KePageAllocator *Knight::KE_CreatePageAllocator()
dvander@2226
    65
{
dvander@2226
    66
	KePageAllocator *alloc;
dvander@2226
    67
dvander@2226
    68
	alloc = new KePageAllocator;
dvander@2226
    69
	
dvander@2226
    70
#if defined KE_PLATFORM_WINDOWS
dvander@2226
    71
	SYSTEM_INFO info;
dvander@2226
    72
	
dvander@2226
    73
	GetSystemInfo(&info);
dvander@2226
    74
	alloc->page_size = info.dwPageSize;
dvander@2226
    75
	alloc->page_granularity = info.dwAllocationGranularity;
dvander@2226
    76
#elif defined KE_PLATFORM_POSIX
dvander@2226
    77
	alloc->page_size = sysconf(_SC_PAGESIZE);
dvander@2226
    78
	alloc->page_granularity = alloc->page_size * 16;
dvander@2226
    79
#else 
dvander@2226
    80
#error "Unsupported platform"
dvander@2226
    81
#endif
dvander@2226
    82
dvander@2226
    83
	alloc->free_pages = NULL;
dvander@2226
    84
	alloc->page_blocks = NULL;
dvander@2226
    85
dvander@2226
    86
	return alloc;
dvander@2226
    87
}
dvander@2226
    88
dvander@2226
    89
void Knight::KE_DestroyPageAllocator(KePageAllocator *alloc)
dvander@2226
    90
{
dvander@2226
    91
	PageInfo *info, *next;
dvander@2226
    92
dvander@2226
    93
	info = alloc->page_blocks;
dvander@2226
    94
	while (info != NULL)
dvander@2226
    95
	{
dvander@2226
    96
		next = info->next;
dvander@2226
    97
#if defined KE_PLATFORM_WINDOWS
dvander@2226
    98
		VirtualFree(info->base, 0, MEM_RELEASE);
dvander@2226
    99
#elif defined KE_PLATFORM_WINDOWS
dvander@2226
   100
		free(info->base);
dvander@2226
   101
#else 
dvander@2226
   102
#error "Unsupported platform"
dvander@2226
   103
#endif
dvander@2226
   104
		delete info;
dvander@2226
   105
		next = info;
dvander@2226
   106
	}
dvander@2226
   107
dvander@2226
   108
	info = alloc->free_pages;
dvander@2226
   109
	while (info != NULL)
dvander@2226
   110
	{
dvander@2226
   111
		next = info->next;
dvander@2226
   112
		delete info;
dvander@2226
   113
		info = next;
dvander@2226
   114
	}
dvander@2226
   115
}
dvander@2226
   116
dvander@2226
   117
void *Knight::KE_PageAlloc(KePageAllocator *alloc)
dvander@2226
   118
{
dvander@2226
   119
	if (alloc->free_pages != NULL)
dvander@2226
   120
	{
dvander@2226
   121
		void *base;
dvander@2226
   122
		PageInfo *info;
dvander@2226
   123
dvander@2226
   124
		info = alloc->free_pages;
dvander@2226
   125
		alloc->free_pages = info->next;
dvander@2226
   126
		base = info->base;
dvander@2226
   127
		delete info;
dvander@2226
   128
dvander@2226
   129
		return base;
dvander@2226
   130
	}
dvander@2226
   131
dvander@2226
   132
	return ke_LumpPageAlloc(alloc);
dvander@2226
   133
}
dvander@2226
   134
dvander@2226
   135
void Knight::KE_PageFree(KePageAllocator *alloc, void *page)
dvander@2226
   136
{
dvander@2226
   137
	PageInfo *info;
dvander@2226
   138
dvander@2226
   139
	info = new PageInfo;
dvander@2226
   140
	info->base = page;
dvander@2226
   141
	info->next = alloc->free_pages;
dvander@2226
   142
	alloc->free_pages = info->next;
dvander@2226
   143
}
dvander@2226
   144
dvander@2226
   145
size_t Knight::KE_PageSize(KePageAllocator *alloc)
dvander@2226
   146
{
dvander@2226
   147
	return alloc->page_size;
dvander@2226
   148
}