Implement __invoke dispatch and fix VM cleanup and allocator alignment

This commit is contained in:
2026-10-26 15:10:47 +01:00
parent 4fe0f4dcd9
commit 7ae2412a88
4 changed files with 75 additions and 48 deletions
+49 -26
View File
@@ -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;
}