Implement __invoke dispatch and fix VM cleanup and allocator alignment
This commit is contained in:
+49
-26
@@ -14,6 +14,13 @@
|
||||
|
||||
#include "ph7int.h"
|
||||
|
||||
/* Reserve a scalar-sized prefix for OS sizes and pool metadata. The engine's
|
||||
* heap scalars require at most this alignment on supported ABIs. Round the
|
||||
* tracking prefix too: SyMemBlock is only 12 bytes on AAPCS32.
|
||||
*/
|
||||
#define SXMEM_PREFIX_SIZE sizeof(sxu64)
|
||||
#define SXMEM_BLOCK_SIZE ((sizeof(SyMemBlock) + SXMEM_PREFIX_SIZE - 1) / SXMEM_PREFIX_SIZE * SXMEM_PREFIX_SIZE)
|
||||
|
||||
static void *SyOSHeapAlloc(sxu32 nBytes) {
|
||||
void *pNew;
|
||||
#if defined(__WINNT__)
|
||||
@@ -77,35 +84,41 @@ PH7_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen) {
|
||||
}
|
||||
static void *MemOSAlloc(sxu32 nBytes) {
|
||||
sxu32 *pChunk;
|
||||
pChunk = (sxu32 *)SyOSHeapAlloc(nBytes + sizeof(sxu32));
|
||||
if(nBytes > SXU32_HIGH - SXMEM_PREFIX_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
pChunk = (sxu32 *)SyOSHeapAlloc(nBytes + SXMEM_PREFIX_SIZE);
|
||||
if(pChunk == 0) {
|
||||
return 0;
|
||||
}
|
||||
pChunk[0] = nBytes;
|
||||
return (void *)&pChunk[1];
|
||||
return (void *)((char *)pChunk + SXMEM_PREFIX_SIZE);
|
||||
}
|
||||
static void *MemOSRealloc(void *pOld, sxu32 nBytes) {
|
||||
sxu32 *pOldChunk;
|
||||
sxu32 *pChunk;
|
||||
pOldChunk = (sxu32 *)(((char *)pOld) - sizeof(sxu32));
|
||||
pOldChunk = (sxu32 *)((char *)pOld - SXMEM_PREFIX_SIZE);
|
||||
if(pOldChunk[0] >= nBytes) {
|
||||
return pOld;
|
||||
}
|
||||
pChunk = (sxu32 *)SyOSHeapRealloc(pOldChunk, nBytes + sizeof(sxu32));
|
||||
if(nBytes > SXU32_HIGH - SXMEM_PREFIX_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
pChunk = (sxu32 *)SyOSHeapRealloc(pOldChunk, nBytes + SXMEM_PREFIX_SIZE);
|
||||
if(pChunk == 0) {
|
||||
return 0;
|
||||
}
|
||||
pChunk[0] = nBytes;
|
||||
return (void *)&pChunk[1];
|
||||
return (void *)((char *)pChunk + SXMEM_PREFIX_SIZE);
|
||||
}
|
||||
static void MemOSFree(void *pBlock) {
|
||||
void *pChunk;
|
||||
pChunk = (void *)(((char *)pBlock) - sizeof(sxu32));
|
||||
pChunk = (void *)((char *)pBlock - SXMEM_PREFIX_SIZE);
|
||||
SyOSHeapFree(pChunk);
|
||||
}
|
||||
static sxu32 MemOSChunkSize(void *pBlock) {
|
||||
sxu32 *pChunk;
|
||||
pChunk = (sxu32 *)(((char *)pBlock) - sizeof(sxu32));
|
||||
pChunk = (sxu32 *)((char *)pBlock - SXMEM_PREFIX_SIZE);
|
||||
return pChunk[0];
|
||||
}
|
||||
/* Export OS allocation methods */
|
||||
@@ -137,7 +150,10 @@ static void *MemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
||||
/* Append an extra block so we can tracks allocated chunks and avoid memory
|
||||
* leaks.
|
||||
*/
|
||||
nBytes += sizeof(SyMemBlock);
|
||||
if(nBytes > SXU32_HIGH - SXMEM_BLOCK_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
nBytes += SXMEM_BLOCK_SIZE;
|
||||
/* Calculate memory usage */
|
||||
if(MemBackendCalculate(pBackend, nBytes) != SXRET_OK) {
|
||||
return 0;
|
||||
@@ -158,7 +174,7 @@ static void *MemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
||||
MACRO_LD_PUSH(pBackend->pBlocks, pBlock);
|
||||
pBlock->nGuard = SXMEM_BACKEND_MAGIC;
|
||||
pBackend->nBlock++;
|
||||
return (void *)&pBlock[1];
|
||||
return (void *)((char *)pBlock + SXMEM_BLOCK_SIZE);
|
||||
}
|
||||
PH7_PRIVATE void *SyMemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
||||
void *pChunk;
|
||||
@@ -181,11 +197,14 @@ static void *MemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes)
|
||||
if(pOld == 0) {
|
||||
return MemBackendAlloc(&(*pBackend), nBytes);
|
||||
}
|
||||
pBlock = (SyMemBlock *)(((char *)pOld) - sizeof(SyMemBlock));
|
||||
pBlock = (SyMemBlock *)(((char *)pOld) - SXMEM_BLOCK_SIZE);
|
||||
if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) {
|
||||
return 0;
|
||||
}
|
||||
nBytes += sizeof(SyMemBlock);
|
||||
if(nBytes > SXU32_HIGH - SXMEM_BLOCK_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
nBytes += SXMEM_BLOCK_SIZE;
|
||||
pPrev = pBlock->pPrev;
|
||||
pNext = pBlock->pNext;
|
||||
nChunkSize = MemOSChunkSize(pBlock);
|
||||
@@ -219,7 +238,7 @@ static void *MemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes)
|
||||
} else {
|
||||
pNew = pBlock;
|
||||
}
|
||||
return (void *)&pNew[1];
|
||||
return (void *)((char *)pNew + SXMEM_BLOCK_SIZE);
|
||||
}
|
||||
PH7_PRIVATE void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes) {
|
||||
void *pChunk;
|
||||
@@ -237,8 +256,7 @@ PH7_PRIVATE void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32
|
||||
}
|
||||
static sxi32 MemBackendFree(SyMemBackend *pBackend, void *pChunk) {
|
||||
SyMemBlock *pBlock;
|
||||
sxu32 *pChunkSize;
|
||||
pBlock = (SyMemBlock *)(((char *)pChunk) - sizeof(SyMemBlock));
|
||||
pBlock = (SyMemBlock *)(((char *)pChunk) - SXMEM_BLOCK_SIZE);
|
||||
if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) {
|
||||
return SXERR_CORRUPT;
|
||||
}
|
||||
@@ -250,8 +268,7 @@ static sxi32 MemBackendFree(SyMemBackend *pBackend, void *pChunk) {
|
||||
MACRO_LD_REMOVE(pBackend->pBlocks, pBlock);
|
||||
pBackend->nBlock--;
|
||||
/* Release the heap */
|
||||
pChunkSize = (sxu32 *)(((char *)pBlock) - sizeof(sxu32));
|
||||
pBackend->pHeap->nSize -= pChunkSize[0];
|
||||
pBackend->pHeap->nSize -= MemOSChunkSize(pBlock);
|
||||
pBackend->pMethods->xFree(pBlock);
|
||||
}
|
||||
return SXRET_OK;
|
||||
@@ -308,20 +325,23 @@ static void *MemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
||||
SyMemHeader *pBucket, *pNext;
|
||||
sxu32 nBucketSize;
|
||||
sxu32 nBucket;
|
||||
if(nBytes + sizeof(SyMemHeader) >= SXMEM_POOL_MAXALLOC) {
|
||||
if(nBytes > SXU32_HIGH - SXMEM_PREFIX_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
if(nBytes + SXMEM_PREFIX_SIZE >= SXMEM_POOL_MAXALLOC) {
|
||||
/* Allocate a big chunk directly */
|
||||
pBucket = (SyMemHeader *)MemBackendAlloc(&(*pBackend), nBytes + sizeof(SyMemHeader));
|
||||
pBucket = (SyMemHeader *)MemBackendAlloc(&(*pBackend), nBytes + SXMEM_PREFIX_SIZE);
|
||||
if(pBucket == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Record as big block */
|
||||
pBucket->nBucket = (sxu32)(SXMEM_POOL_MAGIC << 16) | SXU16_HIGH;
|
||||
return (void *)(pBucket + 1);
|
||||
pBucket->nBucket = ((sxu32)SXMEM_POOL_MAGIC << 16) | SXU16_HIGH;
|
||||
return (void *)((char *)pBucket + SXMEM_PREFIX_SIZE);
|
||||
}
|
||||
/* Locate the appropriate bucket */
|
||||
nBucket = 0;
|
||||
nBucketSize = SXMEM_POOL_MINALLOC;
|
||||
while(nBytes + sizeof(SyMemHeader) > nBucketSize) {
|
||||
while(nBytes + SXMEM_PREFIX_SIZE > nBucketSize) {
|
||||
nBucketSize <<= 1;
|
||||
nBucket++;
|
||||
}
|
||||
@@ -338,8 +358,8 @@ static void *MemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
||||
pNext = pBucket->pNext;
|
||||
pBackend->apPool[nBucket] = pNext;
|
||||
/* Record bucket&magic number */
|
||||
pBucket->nBucket = (SXMEM_POOL_MAGIC << 16) | nBucket;
|
||||
return (void *)&pBucket[1];
|
||||
pBucket->nBucket = ((sxu32)SXMEM_POOL_MAGIC << 16) | nBucket;
|
||||
return (void *)((char *)pBucket + SXMEM_PREFIX_SIZE);
|
||||
}
|
||||
PH7_PRIVATE void *SyMemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
||||
void *pChunk;
|
||||
@@ -359,7 +379,7 @@ static sxi32 MemBackendPoolFree(SyMemBackend *pBackend, void *pChunk) {
|
||||
SyMemHeader *pHeader;
|
||||
sxu32 nBucket;
|
||||
/* Get the corresponding bucket */
|
||||
pHeader = (SyMemHeader *)(((char *)pChunk) - sizeof(SyMemHeader));
|
||||
pHeader = (SyMemHeader *)(((char *)pChunk) - SXMEM_PREFIX_SIZE);
|
||||
/* Sanity check to avoid misuse */
|
||||
if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) {
|
||||
return SXERR_CORRUPT;
|
||||
@@ -399,7 +419,7 @@ static void *MemBackendPoolRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBy
|
||||
return pNew;
|
||||
}
|
||||
/* Get the corresponding bucket */
|
||||
pHeader = (SyMemHeader *)(((char *)pOld) - sizeof(SyMemHeader));
|
||||
pHeader = (SyMemHeader *)(((char *)pOld) - SXMEM_PREFIX_SIZE);
|
||||
/* Sanity check to avoid misuse */
|
||||
if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) {
|
||||
return 0;
|
||||
@@ -410,7 +430,10 @@ static void *MemBackendPoolRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBy
|
||||
return MemBackendRealloc(&(*pBackend), pHeader, nByte);
|
||||
}
|
||||
nBucketSize = 1 << (nBucket + SXMEM_POOL_INCR);
|
||||
if(nBucketSize >= nByte + sizeof(SyMemHeader)) {
|
||||
if(nByte > SXU32_HIGH - SXMEM_PREFIX_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
if(nBucketSize >= nByte + SXMEM_PREFIX_SIZE) {
|
||||
/* The old bucket can honor the requested size */
|
||||
return pOld;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user