void *VDJITAllocator::Allocate(size_t len) { len = (len + 15) & ~(size_t)15; FreeChunks::iterator itMark(mNextChunk), itEnd(mFreeChunks.end()), it(itMark); if (it == itEnd) it = mFreeChunks.begin(); for(;;) { for(; it!=itEnd; ++it) { if (it->second >= len) { it->second -= len; void *p = (char *)it->first + it->second; if (!it->second) { if (mNextChunk == it) ++mNextChunk; mFreeChunks.erase(it); } return p; } } if (itEnd == itMark) break; it = mFreeChunks.begin(); itEnd = itMark; } size_t alloclen = (len + mAllocationGranularity - 1) & ~(mAllocationGranularity - 1); void *p = VirtualAlloc(NULL, alloclen, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (p) { try { Allocations::iterator itA(mAllocations.insert(Allocations::value_type(p, alloclen)).first); try { if (len < alloclen) mFreeChunks.insert(FreeChunks::value_type((char *)p + len, alloclen - len)); } catch(...) { mAllocations.erase(itA); throw; } } catch(...) { VirtualFree(p, 0, MEM_RELEASE); p = NULL; } } return p; }
void VDJITAllocator::Free(void *p, size_t len) { VDASSERT(p); VDASSERT(len < 0x10000); FreeChunks::iterator cur(mFreeChunks.lower_bound(p)); if (cur != mFreeChunks.end() && (char *)p + len == cur->first) { len += cur->second; if (mNextChunk == cur) ++mNextChunk; cur = mFreeChunks.erase(cur); } if (cur != mFreeChunks.begin()) { FreeChunks::iterator prev(cur); --prev; if ((char *)prev->first + prev->second == p) { p = prev->first; len += prev->second; if (mNextChunk == prev) ++mNextChunk; mFreeChunks.erase(prev); } } uintptr start = (size_t)p; uintptr end = start + len; if (!((start | end) & (mAllocationGranularity - 1))) { Allocations::iterator it(mAllocations.find(p)); if (it != mAllocations.end()) { VirtualFree((void *)start, 0, MEM_RELEASE); mAllocations.erase(it); return; } } mFreeChunks.insert(FreeChunks::value_type((void *)start, end-start)); }