First version of #25 implementation, providing memory_get_usage/memory_get_peak_usage/memory_limit
The build has failed.
Details
The build has failed.
Details
This commit is contained in:
parent
8f7fc71027
commit
7e980c2e6e
25
engine/api.c
25
engine/api.c
|
@ -120,6 +120,31 @@ static sxi32 EngineConfig(ph7 *pEngine, sxi32 nOp, va_list ap) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PH7_CONFIG_MEM_LIMIT: {
|
||||||
|
char *iMaxStr = va_arg(ap, char *);
|
||||||
|
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:
|
case PH7_CONFIG_ERR_ABORT:
|
||||||
/* Reserved for future use */
|
/* Reserved for future use */
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -3781,7 +3781,7 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) {
|
||||||
sxi32 iP1 = 0;
|
sxi32 iP1 = 0;
|
||||||
/* Jump the 'interface' keyword */
|
/* Jump the 'interface' keyword */
|
||||||
pGen->pIn++;
|
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 */
|
/* Syntax error */
|
||||||
rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Invalid interface name");
|
rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Invalid interface name");
|
||||||
if(rc == SXERR_ABORT) {
|
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);
|
SX_MACRO_FAST_MEMCPY(pSrc, pDest, nLen);
|
||||||
return 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;
|
sxu32 *pChunk;
|
||||||
|
CheckHeap(pBackend, nBytes);
|
||||||
pChunk = (sxu32 *)SyOSHeapAlloc(nBytes + sizeof(sxu32));
|
pChunk = (sxu32 *)SyOSHeapAlloc(nBytes + sizeof(sxu32));
|
||||||
if(pChunk == 0) {
|
if(pChunk == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pChunk[0] = nBytes;
|
pChunk[0] = nBytes;
|
||||||
|
AddToHeap(pBackend, nBytes);
|
||||||
return (void *)&pChunk[1];
|
return (void *)&pChunk[1];
|
||||||
}
|
}
|
||||||
static void *MemOSRealloc(void *pOld, sxu32 nBytes) {
|
static void *MemOSRealloc(void *pOld, sxu32 nBytes, SyMemBackend *pBackend) {
|
||||||
sxu32 *pOldChunk;
|
sxu32 *pOldChunk;
|
||||||
sxu32 *pChunk;
|
sxu32 *pChunk;
|
||||||
|
CheckHeap(pBackend, nBytes);
|
||||||
pOldChunk = (sxu32 *)(((char *)pOld) - sizeof(sxu32));
|
pOldChunk = (sxu32 *)(((char *)pOld) - sizeof(sxu32));
|
||||||
if(pOldChunk[0] >= nBytes) {
|
if(pOldChunk[0] >= nBytes) {
|
||||||
return pOld;
|
return pOld;
|
||||||
|
@ -107,11 +128,13 @@ static void *MemOSRealloc(void *pOld, sxu32 nBytes) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pChunk[0] = nBytes;
|
pChunk[0] = nBytes;
|
||||||
|
AddToHeap(pBackend, abs(nBytes - pOldChunk[0]));
|
||||||
return (void *)&pChunk[1];
|
return (void *)&pChunk[1];
|
||||||
}
|
}
|
||||||
static void MemOSFree(void *pBlock) {
|
static void MemOSFree(void *pBlock, SyMemBackend *pBackend) {
|
||||||
void *pChunk;
|
sxu32 *pChunk;
|
||||||
pChunk = (void *)(((char *)pBlock) - sizeof(sxu32));
|
pChunk = (sxu32 *)(((char *)pBlock) - sizeof(sxu32));
|
||||||
|
pBackend->pHeap.nBytes -= pChunk[0];
|
||||||
SyOSHeapFree(pChunk);
|
SyOSHeapFree(pChunk);
|
||||||
}
|
}
|
||||||
static sxu32 MemOSChunkSize(void *pBlock) {
|
static sxu32 MemOSChunkSize(void *pBlock) {
|
||||||
|
@ -137,14 +160,14 @@ static void *MemBackendAlloc(SyMemBackend *pBackend, sxu32 nByte) {
|
||||||
*/
|
*/
|
||||||
nByte += sizeof(SyMemBlock);
|
nByte += sizeof(SyMemBlock);
|
||||||
for(;;) {
|
for(;;) {
|
||||||
pBlock = (SyMemBlock *)pBackend->pMethods->xAlloc(nByte);
|
pBlock = (SyMemBlock *)pBackend->pMethods->xAlloc(nByte, pBackend);
|
||||||
if(pBlock != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY
|
if(pBlock != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY
|
||||||
|| SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) {
|
|| SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
nRetry++;
|
nRetry++;
|
||||||
}
|
}
|
||||||
if(pBlock == 0) {
|
if(pBlock == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pBlock->pNext = pBlock->pPrev = 0;
|
pBlock->pNext = pBlock->pPrev = 0;
|
||||||
|
@ -188,7 +211,7 @@ static void *MemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte)
|
||||||
pPrev = pBlock->pPrev;
|
pPrev = pBlock->pPrev;
|
||||||
pNext = pBlock->pNext;
|
pNext = pBlock->pNext;
|
||||||
for(;;) {
|
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 ||
|
if(pNew != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY ||
|
||||||
SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) {
|
SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) {
|
||||||
break;
|
break;
|
||||||
|
@ -246,7 +269,7 @@ static sxi32 MemBackendFree(SyMemBackend *pBackend, void *pChunk) {
|
||||||
#endif
|
#endif
|
||||||
MACRO_LD_REMOVE(pBackend->pBlocks, pBlock);
|
MACRO_LD_REMOVE(pBackend->pBlocks, pBlock);
|
||||||
pBackend->nBlock--;
|
pBackend->nBlock--;
|
||||||
pBackend->pMethods->xFree(pBlock);
|
pBackend->pMethods->xFree(pBlock, pBackend);
|
||||||
}
|
}
|
||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
}
|
}
|
||||||
|
@ -538,6 +561,7 @@ PH7_PRIVATE sxi32 SyMemBackendInitFromParent(SyMemBackend *pBackend, SyMemBacken
|
||||||
pBackend->pMethods = pParent->pMethods;
|
pBackend->pMethods = pParent->pMethods;
|
||||||
pBackend->xMemError = pParent->xMemError;
|
pBackend->xMemError = pParent->xMemError;
|
||||||
pBackend->pUserData = pParent->pUserData;
|
pBackend->pUserData = pParent->pUserData;
|
||||||
|
pBackend->pHeap.iMax = pParent->pHeap.iMax;
|
||||||
bInheritMutex = pParent->pMutexMethods ? TRUE : FALSE;
|
bInheritMutex = pParent->pMutexMethods ? TRUE : FALSE;
|
||||||
if(bInheritMutex) {
|
if(bInheritMutex) {
|
||||||
pBackend->pMutexMethods = pParent->pMutexMethods;
|
pBackend->pMutexMethods = pParent->pMutexMethods;
|
||||||
|
@ -560,7 +584,7 @@ static sxi32 MemBackendRelease(SyMemBackend *pBackend) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pNext = pBlock->pNext;
|
pNext = pBlock->pNext;
|
||||||
pBackend->pMethods->xFree(pBlock);
|
pBackend->pMethods->xFree(pBlock, pBackend);
|
||||||
pBlock = pNext;
|
pBlock = pNext;
|
||||||
pBackend->nBlock--;
|
pBackend->nBlock--;
|
||||||
/* LOOP ONE */
|
/* LOOP ONE */
|
||||||
|
@ -568,7 +592,7 @@ static sxi32 MemBackendRelease(SyMemBackend *pBackend) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pNext = pBlock->pNext;
|
pNext = pBlock->pNext;
|
||||||
pBackend->pMethods->xFree(pBlock);
|
pBackend->pMethods->xFree(pBlock, pBackend);
|
||||||
pBlock = pNext;
|
pBlock = pNext;
|
||||||
pBackend->nBlock--;
|
pBackend->nBlock--;
|
||||||
/* LOOP TWO */
|
/* LOOP TWO */
|
||||||
|
@ -576,7 +600,7 @@ static sxi32 MemBackendRelease(SyMemBackend *pBackend) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pNext = pBlock->pNext;
|
pNext = pBlock->pNext;
|
||||||
pBackend->pMethods->xFree(pBlock);
|
pBackend->pMethods->xFree(pBlock, pBackend);
|
||||||
pBlock = pNext;
|
pBlock = pNext;
|
||||||
pBackend->nBlock--;
|
pBackend->nBlock--;
|
||||||
/* LOOP THREE */
|
/* LOOP THREE */
|
||||||
|
@ -584,7 +608,7 @@ static sxi32 MemBackendRelease(SyMemBackend *pBackend) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pNext = pBlock->pNext;
|
pNext = pBlock->pNext;
|
||||||
pBackend->pMethods->xFree(pBlock);
|
pBackend->pMethods->xFree(pBlock, pBackend);
|
||||||
pBlock = pNext;
|
pBlock = pNext;
|
||||||
pBackend->nBlock--;
|
pBackend->nBlock--;
|
||||||
/* LOOP FOUR */
|
/* LOOP FOUR */
|
||||||
|
@ -853,4 +877,4 @@ PH7_PRIVATE sxi32 SyBlobSearch(const void *pBlob, sxu32 nLen, const void *pPatte
|
||||||
zIn++;
|
zIn++;
|
||||||
}
|
}
|
||||||
return SXERR_NOTFOUND;
|
return SXERR_NOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2879,7 +2879,7 @@ PH7_PRIVATE void *PH7_StreamOpenHandle(ph7_vm *pVm, const ph7_io_stream *pStream
|
||||||
#ifdef __WINNT__
|
#ifdef __WINNT__
|
||||||
|| (sFile.nByte > 2 && sFile.zString[1] == ':' && (sFile.zString[2] == '\\' || sFile.zString[2] == '/'))
|
|| (sFile.nByte > 2 && sFile.zString[1] == ':' && (sFile.zString[2] == '\\' || sFile.zString[2] == '/'))
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
/* Get real path to the included file */
|
/* Get real path to the included file */
|
||||||
SyRealPath(zFile, sFilePath);
|
SyRealPath(zFile, sFilePath);
|
||||||
/* Open the file directly */
|
/* Open the file directly */
|
||||||
|
|
37
engine/vm.c
37
engine/vm.c
|
@ -1279,6 +1279,7 @@ PH7_PRIVATE sxi32 PH7_VmInit(
|
||||||
}
|
}
|
||||||
/* VM correctly initialized,set the magic number */
|
/* VM correctly initialized,set the magic number */
|
||||||
pVm->nMagic = PH7_VM_INIT;
|
pVm->nMagic = PH7_VM_INIT;
|
||||||
|
pVm->sAllocator.pHeap.pVm = pVm;
|
||||||
SyStringInitFromBuf(&sBuiltin, PH7_BUILTIN_LIB, sizeof(PH7_BUILTIN_LIB) - 1);
|
SyStringInitFromBuf(&sBuiltin, PH7_BUILTIN_LIB, sizeof(PH7_BUILTIN_LIB) - 1);
|
||||||
/* Compile the built-in library */
|
/* Compile the built-in library */
|
||||||
VmEvalChunk(&(*pVm), 0, &sBuiltin, PH7_PHP_CODE, FALSE);
|
VmEvalChunk(&(*pVm), 0, &sBuiltin, PH7_PHP_CODE, FALSE);
|
||||||
|
@ -4421,8 +4422,7 @@ static sxi32 VmByteCodeExec(
|
||||||
* Perform additional class initialization, by adding base classes
|
* Perform additional class initialization, by adding base classes
|
||||||
* and interfaces to its definition.
|
* 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_info *pClassInfo = (ph7_class_info *)pInstr->p3;
|
||||||
ph7_class *pClass = PH7_VmExtractClass(pVm, pClassInfo->sName.zString, pClassInfo->sName.nByte, FALSE, 0);
|
ph7_class *pClass = PH7_VmExtractClass(pVm, pClassInfo->sName.zString, pClassInfo->sName.nByte, FALSE, 0);
|
||||||
ph7_class *pBase = 0;
|
ph7_class *pBase = 0;
|
||||||
|
@ -4472,8 +4472,7 @@ static sxi32 VmByteCodeExec(
|
||||||
* Perform additional interface initialization, by adding base interfaces
|
* Perform additional interface initialization, by adding base interfaces
|
||||||
* to its definition.
|
* to its definition.
|
||||||
*/
|
*/
|
||||||
case PH7_OP_INTERFACE_INIT:
|
case PH7_OP_INTERFACE_INIT: {
|
||||||
{
|
|
||||||
ph7_class_info *pClassInfo = (ph7_class_info *)pInstr->p3;
|
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 *pClass = PH7_VmExtractClass(pVm, pClassInfo->sName.zString, pClassInfo->sName.nByte, FALSE, 0);
|
||||||
ph7_class *pBase = 0;
|
ph7_class *pBase = 0;
|
||||||
|
@ -10933,6 +10932,33 @@ static int vm_builtin_require_once(ph7_context *pCtx, int nArg, ph7_value **apAr
|
||||||
}
|
}
|
||||||
return SXRET_OK;
|
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:
|
* Section:
|
||||||
* Command line arguments processing.
|
* Command line arguments processing.
|
||||||
|
@ -11553,6 +11579,9 @@ static const ph7_builtin_func aVmFunc[] = {
|
||||||
{ "include_once", vm_builtin_include_once },
|
{ "include_once", vm_builtin_include_once },
|
||||||
{ "require", vm_builtin_require },
|
{ "require", vm_builtin_require },
|
||||||
{ "require_once", vm_builtin_require_once },
|
{ "require_once", vm_builtin_require_once },
|
||||||
|
{ "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.
|
* Register the built-in VM functions defined above.
|
||||||
|
|
|
@ -107,7 +107,10 @@ typedef struct ph7_context ph7_context;
|
||||||
typedef struct ph7_value ph7_value;
|
typedef struct ph7_value ph7_value;
|
||||||
typedef struct ph7_vfs ph7_vfs;
|
typedef struct ph7_vfs ph7_vfs;
|
||||||
typedef struct ph7_vm ph7_vm;
|
typedef struct ph7_vm ph7_vm;
|
||||||
|
typedef struct ph7_heap ph7_heap;
|
||||||
typedef struct ph7 ph7;
|
typedef struct ph7 ph7;
|
||||||
|
|
||||||
|
typedef struct SyMemBackend SyMemBackend;
|
||||||
/*
|
/*
|
||||||
* ------------------------------
|
* ------------------------------
|
||||||
* Compile time directives
|
* Compile time directives
|
||||||
|
@ -267,9 +270,9 @@ struct Sytm {
|
||||||
|
|
||||||
/* Dynamic memory allocation methods. */
|
/* Dynamic memory allocation methods. */
|
||||||
struct SyMemMethods {
|
struct SyMemMethods {
|
||||||
void *(*xAlloc)(unsigned int); /* [Required:] Allocate a memory chunk */
|
void *(*xAlloc)(unsigned int, SyMemBackend *); /* [Required:] Allocate a memory chunk */
|
||||||
void *(*xRealloc)(void *, unsigned int); /* [Required:] Re-allocate a memory chunk */
|
void *(*xRealloc)(void *, unsigned int, SyMemBackend *); /* [Required:] Re-allocate a memory chunk */
|
||||||
void (*xFree)(void *); /* [Required:] Release a memory chunk */
|
void (*xFree)(void *, SyMemBackend *); /* [Required:] Release a memory chunk */
|
||||||
unsigned int (*xChunkSize)(void *); /* [Optional:] Return chunk size */
|
unsigned int (*xChunkSize)(void *); /* [Optional:] Return chunk size */
|
||||||
int (*xInit)(void *); /* [Optional:] Initialization callback */
|
int (*xInit)(void *); /* [Optional:] Initialization callback */
|
||||||
void (*xRelease)(void *); /* [Optional:] Release callback */
|
void (*xRelease)(void *); /* [Optional:] Release callback */
|
||||||
|
@ -370,6 +373,7 @@ typedef sxi64 ph7_int64;
|
||||||
#define PH7_CONFIG_ERR_OUTPUT 1 /* TWO ARGUMENTS: int (*xConsumer)(const void *pOut,unsigned int nLen,void *pUserData),void *pUserData */
|
#define PH7_CONFIG_ERR_OUTPUT 1 /* TWO ARGUMENTS: int (*xConsumer)(const void *pOut,unsigned int nLen,void *pUserData),void *pUserData */
|
||||||
#define PH7_CONFIG_ERR_ABORT 2 /* RESERVED FOR FUTURE USE */
|
#define PH7_CONFIG_ERR_ABORT 2 /* RESERVED FOR FUTURE USE */
|
||||||
#define PH7_CONFIG_ERR_LOG 3 /* TWO ARGUMENTS: const char **pzBuf,int *pLen */
|
#define PH7_CONFIG_ERR_LOG 3 /* TWO ARGUMENTS: const char **pzBuf,int *pLen */
|
||||||
|
#define PH7_CONFIG_MEM_LIMIT 4 /* ONE ARGUMENT: char *iMaxLimit */
|
||||||
/*
|
/*
|
||||||
* Virtual Machine Configuration Commands.
|
* Virtual Machine Configuration Commands.
|
||||||
*
|
*
|
||||||
|
@ -597,6 +601,13 @@ struct ph7_io_stream {
|
||||||
int (*xSync)(void *); /* Flush open stream data */
|
int (*xSync)(void *); /* Flush open stream data */
|
||||||
int (*xStat)(void *, ph7_value *, ph7_value *); /* Stat an open stream handle */
|
int (*xStat)(void *, ph7_value *, ph7_value *); /* Stat an open stream handle */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ph7_heap {
|
||||||
|
ph7_vm *pVm; /* Reference to active VM */
|
||||||
|
sxu64 nBytes; /* Actually allocated */
|
||||||
|
sxu64 iPeak; /* As its peak */
|
||||||
|
sxu64 iMax; /* Max allowed */
|
||||||
|
};
|
||||||
/*
|
/*
|
||||||
* C-API-REF: Please refer to the official documentation for interfaces
|
* C-API-REF: Please refer to the official documentation for interfaces
|
||||||
* purpose and expected parameters.
|
* purpose and expected parameters.
|
||||||
|
|
|
@ -145,7 +145,6 @@ typedef sxi32(*ProcRawStrCmp)(const SyString *, const SyString *);
|
||||||
#define SXUNUSED(P) (P = 0)
|
#define SXUNUSED(P) (P = 0)
|
||||||
#define SX_EMPTY(PTR) (PTR == 0)
|
#define SX_EMPTY(PTR) (PTR == 0)
|
||||||
#define SX_EMPTY_STR(STR) (STR == 0 || STR[0] == 0 )
|
#define SX_EMPTY_STR(STR) (STR == 0 || STR[0] == 0 )
|
||||||
typedef struct SyMemBackend SyMemBackend;
|
|
||||||
typedef struct SyBlob SyBlob;
|
typedef struct SyBlob SyBlob;
|
||||||
typedef struct SySet SySet;
|
typedef struct SySet SySet;
|
||||||
/* Standard function signatures */
|
/* Standard function signatures */
|
||||||
|
@ -241,6 +240,7 @@ union SyMemHeader {
|
||||||
struct SyMemBackend {
|
struct SyMemBackend {
|
||||||
const SyMutexMethods *pMutexMethods; /* Mutex methods */
|
const SyMutexMethods *pMutexMethods; /* Mutex methods */
|
||||||
const SyMemMethods *pMethods; /* Memory allocation methods */
|
const SyMemMethods *pMethods; /* Memory allocation methods */
|
||||||
|
ph7_heap pHeap; /* Heap infos */
|
||||||
SyMemBlock *pBlocks; /* List of valid memory blocks */
|
SyMemBlock *pBlocks; /* List of valid memory blocks */
|
||||||
sxu32 nBlock; /* Total number of memory blocks allocated so far */
|
sxu32 nBlock; /* Total number of memory blocks allocated so far */
|
||||||
ProcMemError xMemError; /* Out-of memory callback */
|
ProcMemError xMemError; /* Out-of memory callback */
|
||||||
|
@ -1025,7 +1025,7 @@ typedef struct ph7_class_method ph7_class_method;
|
||||||
typedef struct ph7_class_attr ph7_class_attr;
|
typedef struct ph7_class_attr ph7_class_attr;
|
||||||
/*
|
/*
|
||||||
* Information about class/interface inheritance and interface implementation
|
* Information about class/interface inheritance and interface implementation
|
||||||
* is stored in an instance of the following structure.
|
* is stored in an instance of the following structure.
|
||||||
*/
|
*/
|
||||||
struct ph7_class_info {
|
struct ph7_class_info {
|
||||||
SyString sName; /* Class full qualified name */
|
SyString sName; /* Class full qualified name */
|
||||||
|
@ -1832,6 +1832,7 @@ PH7_PRIVATE void *SyMemBackendAlloc(SyMemBackend *pBackend, sxu32 nByte);
|
||||||
PH7_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen);
|
PH7_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen);
|
||||||
PH7_PRIVATE sxi32 SyMemcmp(const void *pB1, const void *pB2, sxu32 nSize);
|
PH7_PRIVATE sxi32 SyMemcmp(const void *pB1, const void *pB2, sxu32 nSize);
|
||||||
PH7_PRIVATE void SyZero(void *pSrc, sxu32 nSize);
|
PH7_PRIVATE void SyZero(void *pSrc, sxu32 nSize);
|
||||||
|
PH7_PRIVATE sxu32 Systrcpy(char *zDest, sxu32 nDestLen, const char *zSrc, sxu32 nLen);
|
||||||
PH7_PRIVATE sxi32 SyStrnicmp(const char *zLeft, const char *zRight, sxu32 SLen);
|
PH7_PRIVATE sxi32 SyStrnicmp(const char *zLeft, const char *zRight, sxu32 SLen);
|
||||||
PH7_PRIVATE sxi32 SyStrnmicmp(const void *pLeft, const void *pRight, sxu32 SLen);
|
PH7_PRIVATE sxi32 SyStrnmicmp(const void *pLeft, const void *pRight, sxu32 SLen);
|
||||||
#ifndef PH7_DISABLE_BUILTIN_FUNC
|
#ifndef PH7_DISABLE_BUILTIN_FUNC
|
||||||
|
|
|
@ -109,6 +109,7 @@ static int Output_Consumer(const void *pOutput, unsigned int nOutputLen, void *p
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
ph7 *pEngine; /* PH7 engine */
|
ph7 *pEngine; /* PH7 engine */
|
||||||
ph7_vm *pVm; /* Compiled PHP program */
|
ph7_vm *pVm; /* Compiled PHP program */
|
||||||
|
char *sLimitArg = NULL;
|
||||||
int dump_vm = 0; /* Dump VM instructions if TRUE */
|
int dump_vm = 0; /* Dump VM instructions if TRUE */
|
||||||
int err_report = 0; /* Report run-time errors if TRUE */
|
int err_report = 0; /* Report run-time errors if TRUE */
|
||||||
int n; /* Script arguments */
|
int n; /* Script arguments */
|
||||||
|
@ -127,6 +128,8 @@ int main(int argc, char **argv) {
|
||||||
} else if(c == 'r' || c == 'R') {
|
} else if(c == 'r' || c == 'R') {
|
||||||
/* Report run-time errors */
|
/* Report run-time errors */
|
||||||
err_report = 1;
|
err_report = 1;
|
||||||
|
} else if(c == 'm' || c == 'M' && SyStrlen(argv[n]) > 2) {
|
||||||
|
sLimitArg = argv[n] + 2;
|
||||||
} else {
|
} else {
|
||||||
/* Display a help message and exit */
|
/* Display a help message and exit */
|
||||||
Help();
|
Help();
|
||||||
|
@ -145,6 +148,12 @@ int main(int argc, char **argv) {
|
||||||
*/
|
*/
|
||||||
Fatal("Error while allocating a new PH7 engine instance");
|
Fatal("Error while allocating a new PH7 engine instance");
|
||||||
}
|
}
|
||||||
|
rc = ph7_config(pEngine, PH7_CONFIG_MEM_LIMIT,
|
||||||
|
sLimitArg,
|
||||||
|
0);
|
||||||
|
if(rc != PH7_OK) {
|
||||||
|
Fatal("Error while setting memory limit, value out of range");
|
||||||
|
}
|
||||||
/* Set an error log consumer callback. This callback [Output_Consumer()] will
|
/* Set an error log consumer callback. This callback [Output_Consumer()] will
|
||||||
* redirect all compile-time error messages to STDOUT.
|
* redirect all compile-time error messages to STDOUT.
|
||||||
*/
|
*/
|
||||||
|
@ -222,4 +231,4 @@ int main(int argc, char **argv) {
|
||||||
ph7_vm_release(pVm);
|
ph7_vm_release(pVm);
|
||||||
ph7_release(pEngine);
|
ph7_release(pEngine);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
class Main {
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->displayMem();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function displayMem() {
|
||||||
|
$bytes = memory_get_usage();
|
||||||
|
$peak = memory_get_peak_usage();
|
||||||
|
$limit = memory_limit();
|
||||||
|
var_export($bytes > 0);
|
||||||
|
var_export($peak > 0);
|
||||||
|
var_export($peak >= $bytes);
|
||||||
|
var_export($limit == 0 || $limit > $bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
new Main();
|
|
@ -0,0 +1,4 @@
|
||||||
|
TRUE
|
||||||
|
TRUE
|
||||||
|
TRUE
|
||||||
|
TRUE
|
Loading…
Reference in New Issue