First version of #25 implementation, providing memory_get_usage/memory_get_peak_usage/memory_limit
This commit is contained in:
28
engine/api.c
28
engine/api.c
@@ -120,6 +120,34 @@ static sxi32 EngineConfig(ph7 *pEngine, sxi32 nOp, va_list ap) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PH7_CONFIG_MEM_LIMIT: {
|
||||
char *iMaxStr = va_arg(ap, char *);
|
||||
if(!iMaxStr) {
|
||||
break;
|
||||
}
|
||||
char *iMaxRem;
|
||||
sxu64 iMax;
|
||||
SyStrToInt64(iMaxStr, strlen(iMaxStr), (void *)&iMax, &iMaxRem);
|
||||
if(iMaxRem) {
|
||||
switch(*iMaxRem) {
|
||||
case 'G':
|
||||
case 'g':
|
||||
iMax *= 1024;
|
||||
case 'M':
|
||||
case 'm':
|
||||
iMax *= 1024;
|
||||
case 'K':
|
||||
case 'k':
|
||||
iMax *= 1024;
|
||||
}
|
||||
}
|
||||
if(iMax >= 1024 * 100 && iMax <= LONG_MAX) {
|
||||
pEngine->sAllocator.pHeap.iMax = iMax;
|
||||
} else {
|
||||
rc = PH7_CORRUPT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PH7_CONFIG_ERR_ABORT:
|
||||
/* Reserved for future use */
|
||||
break;
|
||||
|
@@ -3637,7 +3637,7 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) {
|
||||
sxi32 iP1 = 0;
|
||||
/* Jump the 'interface' keyword */
|
||||
pGen->pIn++;
|
||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_ID) == 0) {
|
||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_ID) == 0) {
|
||||
/* Syntax error */
|
||||
rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Invalid interface name");
|
||||
if(rc == SXERR_ABORT) {
|
||||
|
@@ -86,18 +86,39 @@ PH7_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen) {
|
||||
SX_MACRO_FAST_MEMCPY(pSrc, pDest, nLen);
|
||||
return nLen;
|
||||
}
|
||||
static void *MemOSAlloc(sxu32 nBytes) {
|
||||
|
||||
#define CheckHeap(BACKEND, BYTES)\
|
||||
if(BACKEND->pHeap.iMax && BACKEND->pHeap.nBytes + BYTES > BACKEND->pHeap.iMax) {\
|
||||
if(BACKEND->xMemError) {\
|
||||
char buf[256] = {0};\
|
||||
snprintf(buf, sizeof(buf) - 1, "Out of memory, max allowed %llu bytes, allocated %llu bytes\n", BACKEND->pHeap.iMax, BACKEND->pHeap.nBytes);\
|
||||
BACKEND->xMemError(buf);\
|
||||
}\
|
||||
PH7_VmRelease(BACKEND->pHeap.pVm);\
|
||||
exit(255);\
|
||||
}\
|
||||
(void)BYTES
|
||||
#define AddToHeap(BACKEND, BYTES)\
|
||||
BACKEND->pHeap.nBytes += BYTES;\
|
||||
if(BACKEND->pHeap.nBytes > BACKEND->pHeap.iPeak) {\
|
||||
BACKEND->pHeap.iPeak = BACKEND->pHeap.nBytes;\
|
||||
}\
|
||||
(void)BYTES
|
||||
static void *MemOSAlloc(sxu32 nBytes, SyMemBackend *pBackend) {
|
||||
sxu32 *pChunk;
|
||||
CheckHeap(pBackend, nBytes);
|
||||
pChunk = (sxu32 *)SyOSHeapAlloc(nBytes + sizeof(sxu32));
|
||||
if(pChunk == 0) {
|
||||
return 0;
|
||||
}
|
||||
pChunk[0] = nBytes;
|
||||
AddToHeap(pBackend, nBytes);
|
||||
return (void *)&pChunk[1];
|
||||
}
|
||||
static void *MemOSRealloc(void *pOld, sxu32 nBytes) {
|
||||
static void *MemOSRealloc(void *pOld, sxu32 nBytes, SyMemBackend *pBackend) {
|
||||
sxu32 *pOldChunk;
|
||||
sxu32 *pChunk;
|
||||
CheckHeap(pBackend, nBytes);
|
||||
pOldChunk = (sxu32 *)(((char *)pOld) - sizeof(sxu32));
|
||||
if(pOldChunk[0] >= nBytes) {
|
||||
return pOld;
|
||||
@@ -107,11 +128,13 @@ static void *MemOSRealloc(void *pOld, sxu32 nBytes) {
|
||||
return 0;
|
||||
}
|
||||
pChunk[0] = nBytes;
|
||||
AddToHeap(pBackend, abs(nBytes - pOldChunk[0]));
|
||||
return (void *)&pChunk[1];
|
||||
}
|
||||
static void MemOSFree(void *pBlock) {
|
||||
void *pChunk;
|
||||
pChunk = (void *)(((char *)pBlock) - sizeof(sxu32));
|
||||
static void MemOSFree(void *pBlock, SyMemBackend *pBackend) {
|
||||
sxu32 *pChunk;
|
||||
pChunk = (sxu32 *)(((char *)pBlock) - sizeof(sxu32));
|
||||
pBackend->pHeap.nBytes -= pChunk[0];
|
||||
SyOSHeapFree(pChunk);
|
||||
}
|
||||
static sxu32 MemOSChunkSize(void *pBlock) {
|
||||
@@ -137,14 +160,14 @@ static void *MemBackendAlloc(SyMemBackend *pBackend, sxu32 nByte) {
|
||||
*/
|
||||
nByte += sizeof(SyMemBlock);
|
||||
for(;;) {
|
||||
pBlock = (SyMemBlock *)pBackend->pMethods->xAlloc(nByte);
|
||||
pBlock = (SyMemBlock *)pBackend->pMethods->xAlloc(nByte, pBackend);
|
||||
if(pBlock != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY
|
||||
|| SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) {
|
||||
break;
|
||||
}
|
||||
nRetry++;
|
||||
}
|
||||
if(pBlock == 0) {
|
||||
if(pBlock == 0) {
|
||||
return 0;
|
||||
}
|
||||
pBlock->pNext = pBlock->pPrev = 0;
|
||||
@@ -188,7 +211,7 @@ static void *MemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte)
|
||||
pPrev = pBlock->pPrev;
|
||||
pNext = pBlock->pNext;
|
||||
for(;;) {
|
||||
pNew = (SyMemBlock *)pBackend->pMethods->xRealloc(pBlock, nByte);
|
||||
pNew = (SyMemBlock *)pBackend->pMethods->xRealloc(pBlock, nByte, pBackend);
|
||||
if(pNew != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY ||
|
||||
SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) {
|
||||
break;
|
||||
@@ -246,7 +269,7 @@ static sxi32 MemBackendFree(SyMemBackend *pBackend, void *pChunk) {
|
||||
#endif
|
||||
MACRO_LD_REMOVE(pBackend->pBlocks, pBlock);
|
||||
pBackend->nBlock--;
|
||||
pBackend->pMethods->xFree(pBlock);
|
||||
pBackend->pMethods->xFree(pBlock, pBackend);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
@@ -538,6 +561,7 @@ PH7_PRIVATE sxi32 SyMemBackendInitFromParent(SyMemBackend *pBackend, SyMemBacken
|
||||
pBackend->pMethods = pParent->pMethods;
|
||||
pBackend->xMemError = pParent->xMemError;
|
||||
pBackend->pUserData = pParent->pUserData;
|
||||
pBackend->pHeap.iMax = pParent->pHeap.iMax;
|
||||
bInheritMutex = pParent->pMutexMethods ? TRUE : FALSE;
|
||||
if(bInheritMutex) {
|
||||
pBackend->pMutexMethods = pParent->pMutexMethods;
|
||||
@@ -560,7 +584,7 @@ static sxi32 MemBackendRelease(SyMemBackend *pBackend) {
|
||||
break;
|
||||
}
|
||||
pNext = pBlock->pNext;
|
||||
pBackend->pMethods->xFree(pBlock);
|
||||
pBackend->pMethods->xFree(pBlock, pBackend);
|
||||
pBlock = pNext;
|
||||
pBackend->nBlock--;
|
||||
/* LOOP ONE */
|
||||
@@ -568,7 +592,7 @@ static sxi32 MemBackendRelease(SyMemBackend *pBackend) {
|
||||
break;
|
||||
}
|
||||
pNext = pBlock->pNext;
|
||||
pBackend->pMethods->xFree(pBlock);
|
||||
pBackend->pMethods->xFree(pBlock, pBackend);
|
||||
pBlock = pNext;
|
||||
pBackend->nBlock--;
|
||||
/* LOOP TWO */
|
||||
@@ -576,7 +600,7 @@ static sxi32 MemBackendRelease(SyMemBackend *pBackend) {
|
||||
break;
|
||||
}
|
||||
pNext = pBlock->pNext;
|
||||
pBackend->pMethods->xFree(pBlock);
|
||||
pBackend->pMethods->xFree(pBlock, pBackend);
|
||||
pBlock = pNext;
|
||||
pBackend->nBlock--;
|
||||
/* LOOP THREE */
|
||||
@@ -584,7 +608,7 @@ static sxi32 MemBackendRelease(SyMemBackend *pBackend) {
|
||||
break;
|
||||
}
|
||||
pNext = pBlock->pNext;
|
||||
pBackend->pMethods->xFree(pBlock);
|
||||
pBackend->pMethods->xFree(pBlock, pBackend);
|
||||
pBlock = pNext;
|
||||
pBackend->nBlock--;
|
||||
/* LOOP FOUR */
|
||||
@@ -853,4 +877,4 @@ PH7_PRIVATE sxi32 SyBlobSearch(const void *pBlob, sxu32 nLen, const void *pPatte
|
||||
zIn++;
|
||||
}
|
||||
return SXERR_NOTFOUND;
|
||||
}
|
||||
}
|
||||
|
@@ -2998,7 +2998,7 @@ PH7_PRIVATE void *PH7_StreamOpenHandle(ph7_vm *pVm, const ph7_io_stream *pStream
|
||||
#ifdef __WINNT__
|
||||
|| (sFile.nByte > 2 && sFile.zString[1] == ':' && (sFile.zString[2] == '\\' || sFile.zString[2] == '/'))
|
||||
#endif
|
||||
) {
|
||||
) {
|
||||
/* Get real path to the included file */
|
||||
SyRealPath(zFile, sFilePath);
|
||||
/* Open the file directly */
|
||||
|
38
engine/vm.c
38
engine/vm.c
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
/* $SymiscID: vm.c v1.4 FreeBSD 2012-09-10 00:06 stable <chm@symisc.net> $ */
|
||||
#include "ph7int.h"
|
||||
#include <stdlib.h>
|
||||
/*
|
||||
* The code in this file implements execution method of the PH7 Virtual Machine.
|
||||
* The PH7 compiler (implemented in 'compiler.c' and 'parse.c') generates a bytecode program
|
||||
@@ -1075,6 +1076,7 @@ PH7_PRIVATE sxi32 PH7_VmInit(
|
||||
}
|
||||
/* VM correctly initialized,set the magic number */
|
||||
pVm->nMagic = PH7_VM_INIT;
|
||||
pVm->sAllocator.pHeap.pVm = pVm;
|
||||
SyStringInitFromBuf(&sBuiltin, PH7_BUILTIN_LIB, sizeof(PH7_BUILTIN_LIB) - 1);
|
||||
/* Precompile the built-in library */
|
||||
VmEvalChunk(&(*pVm), 0, &sBuiltin, PH7_AERSCRIPT_CODE);
|
||||
@@ -4217,8 +4219,7 @@ static sxi32 VmByteCodeExec(
|
||||
* Perform additional class initialization, by adding base classes
|
||||
* and interfaces to its definition.
|
||||
*/
|
||||
case PH7_OP_CLASS_INIT:
|
||||
{
|
||||
case PH7_OP_CLASS_INIT: {
|
||||
ph7_class_info *pClassInfo = (ph7_class_info *)pInstr->p3;
|
||||
ph7_class *pClass = PH7_VmExtractClass(pVm, pClassInfo->sName.zString, pClassInfo->sName.nByte, FALSE, 0);
|
||||
ph7_class *pBase = 0;
|
||||
@@ -4268,8 +4269,7 @@ static sxi32 VmByteCodeExec(
|
||||
* Perform additional interface initialization, by adding base interfaces
|
||||
* to its definition.
|
||||
*/
|
||||
case PH7_OP_INTERFACE_INIT:
|
||||
{
|
||||
case PH7_OP_INTERFACE_INIT: {
|
||||
ph7_class_info *pClassInfo = (ph7_class_info *)pInstr->p3;
|
||||
ph7_class *pClass = PH7_VmExtractClass(pVm, pClassInfo->sName.zString, pClassInfo->sName.nByte, FALSE, 0);
|
||||
ph7_class *pBase = 0;
|
||||
@@ -10677,6 +10677,33 @@ static int vm_builtin_require(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
|
||||
static int vm_builtin_memory_get_usage(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
if(nArg != 0) {
|
||||
ph7_result_bool(pCtx, 0);
|
||||
} else {
|
||||
ph7_result_int64(pCtx, pCtx->pVm->sAllocator.pHeap.nBytes);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
|
||||
static int vm_builtin_memory_get_peak_usage(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
if(nArg != 0) {
|
||||
ph7_result_bool(pCtx, 0);
|
||||
} else {
|
||||
ph7_result_int64(pCtx, pCtx->pVm->sAllocator.pHeap.iPeak);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
|
||||
static int vm_builtin_memory_limit(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
if(nArg != 0) {
|
||||
ph7_result_bool(pCtx, 0);
|
||||
} else {
|
||||
ph7_result_int64(pCtx, pCtx->pVm->sAllocator.pHeap.iMax);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Section:
|
||||
* Command line arguments processing.
|
||||
@@ -11285,6 +11312,9 @@ static const ph7_builtin_func aVmFunc[] = {
|
||||
{ "get_included_files", vm_builtin_get_included_files},
|
||||
{ "include", vm_builtin_include },
|
||||
{ "require", vm_builtin_require },
|
||||
{ "memory_get_usage", vm_builtin_memory_get_usage },
|
||||
{ "memory_get_peak_usage", vm_builtin_memory_get_peak_usage },
|
||||
{ "memory_limit", vm_builtin_memory_limit },
|
||||
};
|
||||
/*
|
||||
* Register the built-in VM functions defined above.
|
||||
|
Reference in New Issue
Block a user