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