Implement __invoke dispatch and fix VM cleanup and allocator alignment
This commit is contained in:
+5
-12
@@ -463,6 +463,9 @@ static sxi32 ProcessSourceFile(
|
|||||||
int iFileDir, rc;
|
int iFileDir, rc;
|
||||||
char *pFileDir, fFilePath[PATH_MAX + 1];
|
char *pFileDir, fFilePath[PATH_MAX + 1];
|
||||||
char pFilePath[PATH_MAX + 1];
|
char pFilePath[PATH_MAX + 1];
|
||||||
|
/* Track the initialized VM before compilation can trigger library shutdown. */
|
||||||
|
MACRO_LD_PUSH(pEngine->pVms, pVm);
|
||||||
|
pEngine->iVm++;
|
||||||
/* Install local import path which is the current directory */
|
/* Install local import path which is the current directory */
|
||||||
rc = ph7_vm_config(pVm, PH7_VM_CONFIG_IMPORT_PATH, "./");
|
rc = ph7_vm_config(pVm, PH7_VM_CONFIG_IMPORT_PATH, "./");
|
||||||
if(rc != PH7_OK) {
|
if(rc != PH7_OK) {
|
||||||
@@ -488,26 +491,16 @@ static sxi32 ProcessSourceFile(
|
|||||||
}
|
}
|
||||||
/* Compile the script */
|
/* Compile the script */
|
||||||
PH7_CompileAerScript(pVm, &(*pScript), PH7_AERSCRIPT_CODE);
|
PH7_CompileAerScript(pVm, &(*pScript), PH7_AERSCRIPT_CODE);
|
||||||
if(pVm == 0) {
|
|
||||||
/* Null ppVm pointer,release this VM */
|
|
||||||
SyMemBackendRelease(&pVm->sAllocator);
|
|
||||||
SyMemBackendPoolFree(&pEngine->sAllocator, pVm);
|
|
||||||
if(ppVm) {
|
|
||||||
*ppVm = 0;
|
|
||||||
}
|
|
||||||
return PH7_OK;
|
|
||||||
}
|
|
||||||
/* Prepare the virtual machine for bytecode execution */
|
/* Prepare the virtual machine for bytecode execution */
|
||||||
rc = PH7_VmMakeReady(pVm);
|
rc = PH7_VmMakeReady(pVm);
|
||||||
if(rc != PH7_OK) {
|
if(rc != PH7_OK) {
|
||||||
goto Release;
|
goto Release;
|
||||||
}
|
}
|
||||||
/* Script successfully compiled,link to the list of active virtual machines */
|
|
||||||
MACRO_LD_PUSH(pEngine->pVms, pVm);
|
|
||||||
pEngine->iVm++;
|
|
||||||
/* Ready to execute PH7 bytecode */
|
/* Ready to execute PH7 bytecode */
|
||||||
return PH7_OK;
|
return PH7_OK;
|
||||||
Release:
|
Release:
|
||||||
|
MACRO_LD_REMOVE(pEngine->pVms, pVm);
|
||||||
|
pEngine->iVm--;
|
||||||
SyMemBackendRelease(&pVm->sAllocator);
|
SyMemBackendRelease(&pVm->sAllocator);
|
||||||
SyMemBackendPoolFree(&pEngine->sAllocator, pVm);
|
SyMemBackendPoolFree(&pEngine->sAllocator, pVm);
|
||||||
*ppVm = 0;
|
*ppVm = 0;
|
||||||
|
|||||||
+49
-26
@@ -14,6 +14,13 @@
|
|||||||
|
|
||||||
#include "ph7int.h"
|
#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) {
|
static void *SyOSHeapAlloc(sxu32 nBytes) {
|
||||||
void *pNew;
|
void *pNew;
|
||||||
#if defined(__WINNT__)
|
#if defined(__WINNT__)
|
||||||
@@ -77,35 +84,41 @@ PH7_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen) {
|
|||||||
}
|
}
|
||||||
static void *MemOSAlloc(sxu32 nBytes) {
|
static void *MemOSAlloc(sxu32 nBytes) {
|
||||||
sxu32 *pChunk;
|
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) {
|
if(pChunk == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pChunk[0] = nBytes;
|
pChunk[0] = nBytes;
|
||||||
return (void *)&pChunk[1];
|
return (void *)((char *)pChunk + SXMEM_PREFIX_SIZE);
|
||||||
}
|
}
|
||||||
static void *MemOSRealloc(void *pOld, sxu32 nBytes) {
|
static void *MemOSRealloc(void *pOld, sxu32 nBytes) {
|
||||||
sxu32 *pOldChunk;
|
sxu32 *pOldChunk;
|
||||||
sxu32 *pChunk;
|
sxu32 *pChunk;
|
||||||
pOldChunk = (sxu32 *)(((char *)pOld) - sizeof(sxu32));
|
pOldChunk = (sxu32 *)((char *)pOld - SXMEM_PREFIX_SIZE);
|
||||||
if(pOldChunk[0] >= nBytes) {
|
if(pOldChunk[0] >= nBytes) {
|
||||||
return pOld;
|
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) {
|
if(pChunk == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pChunk[0] = nBytes;
|
pChunk[0] = nBytes;
|
||||||
return (void *)&pChunk[1];
|
return (void *)((char *)pChunk + SXMEM_PREFIX_SIZE);
|
||||||
}
|
}
|
||||||
static void MemOSFree(void *pBlock) {
|
static void MemOSFree(void *pBlock) {
|
||||||
void *pChunk;
|
void *pChunk;
|
||||||
pChunk = (void *)(((char *)pBlock) - sizeof(sxu32));
|
pChunk = (void *)((char *)pBlock - SXMEM_PREFIX_SIZE);
|
||||||
SyOSHeapFree(pChunk);
|
SyOSHeapFree(pChunk);
|
||||||
}
|
}
|
||||||
static sxu32 MemOSChunkSize(void *pBlock) {
|
static sxu32 MemOSChunkSize(void *pBlock) {
|
||||||
sxu32 *pChunk;
|
sxu32 *pChunk;
|
||||||
pChunk = (sxu32 *)(((char *)pBlock) - sizeof(sxu32));
|
pChunk = (sxu32 *)((char *)pBlock - SXMEM_PREFIX_SIZE);
|
||||||
return pChunk[0];
|
return pChunk[0];
|
||||||
}
|
}
|
||||||
/* Export OS allocation methods */
|
/* 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
|
/* Append an extra block so we can tracks allocated chunks and avoid memory
|
||||||
* leaks.
|
* leaks.
|
||||||
*/
|
*/
|
||||||
nBytes += sizeof(SyMemBlock);
|
if(nBytes > SXU32_HIGH - SXMEM_BLOCK_SIZE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
nBytes += SXMEM_BLOCK_SIZE;
|
||||||
/* Calculate memory usage */
|
/* Calculate memory usage */
|
||||||
if(MemBackendCalculate(pBackend, nBytes) != SXRET_OK) {
|
if(MemBackendCalculate(pBackend, nBytes) != SXRET_OK) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -158,7 +174,7 @@ static void *MemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
|||||||
MACRO_LD_PUSH(pBackend->pBlocks, pBlock);
|
MACRO_LD_PUSH(pBackend->pBlocks, pBlock);
|
||||||
pBlock->nGuard = SXMEM_BACKEND_MAGIC;
|
pBlock->nGuard = SXMEM_BACKEND_MAGIC;
|
||||||
pBackend->nBlock++;
|
pBackend->nBlock++;
|
||||||
return (void *)&pBlock[1];
|
return (void *)((char *)pBlock + SXMEM_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
PH7_PRIVATE void *SyMemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
PH7_PRIVATE void *SyMemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
||||||
void *pChunk;
|
void *pChunk;
|
||||||
@@ -181,11 +197,14 @@ static void *MemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes)
|
|||||||
if(pOld == 0) {
|
if(pOld == 0) {
|
||||||
return MemBackendAlloc(&(*pBackend), nBytes);
|
return MemBackendAlloc(&(*pBackend), nBytes);
|
||||||
}
|
}
|
||||||
pBlock = (SyMemBlock *)(((char *)pOld) - sizeof(SyMemBlock));
|
pBlock = (SyMemBlock *)(((char *)pOld) - SXMEM_BLOCK_SIZE);
|
||||||
if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) {
|
if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
nBytes += sizeof(SyMemBlock);
|
if(nBytes > SXU32_HIGH - SXMEM_BLOCK_SIZE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
nBytes += SXMEM_BLOCK_SIZE;
|
||||||
pPrev = pBlock->pPrev;
|
pPrev = pBlock->pPrev;
|
||||||
pNext = pBlock->pNext;
|
pNext = pBlock->pNext;
|
||||||
nChunkSize = MemOSChunkSize(pBlock);
|
nChunkSize = MemOSChunkSize(pBlock);
|
||||||
@@ -219,7 +238,7 @@ static void *MemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes)
|
|||||||
} else {
|
} else {
|
||||||
pNew = pBlock;
|
pNew = pBlock;
|
||||||
}
|
}
|
||||||
return (void *)&pNew[1];
|
return (void *)((char *)pNew + SXMEM_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
PH7_PRIVATE void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes) {
|
PH7_PRIVATE void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes) {
|
||||||
void *pChunk;
|
void *pChunk;
|
||||||
@@ -237,8 +256,7 @@ PH7_PRIVATE void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32
|
|||||||
}
|
}
|
||||||
static sxi32 MemBackendFree(SyMemBackend *pBackend, void *pChunk) {
|
static sxi32 MemBackendFree(SyMemBackend *pBackend, void *pChunk) {
|
||||||
SyMemBlock *pBlock;
|
SyMemBlock *pBlock;
|
||||||
sxu32 *pChunkSize;
|
pBlock = (SyMemBlock *)(((char *)pChunk) - SXMEM_BLOCK_SIZE);
|
||||||
pBlock = (SyMemBlock *)(((char *)pChunk) - sizeof(SyMemBlock));
|
|
||||||
if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) {
|
if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) {
|
||||||
return SXERR_CORRUPT;
|
return SXERR_CORRUPT;
|
||||||
}
|
}
|
||||||
@@ -250,8 +268,7 @@ static sxi32 MemBackendFree(SyMemBackend *pBackend, void *pChunk) {
|
|||||||
MACRO_LD_REMOVE(pBackend->pBlocks, pBlock);
|
MACRO_LD_REMOVE(pBackend->pBlocks, pBlock);
|
||||||
pBackend->nBlock--;
|
pBackend->nBlock--;
|
||||||
/* Release the heap */
|
/* Release the heap */
|
||||||
pChunkSize = (sxu32 *)(((char *)pBlock) - sizeof(sxu32));
|
pBackend->pHeap->nSize -= MemOSChunkSize(pBlock);
|
||||||
pBackend->pHeap->nSize -= pChunkSize[0];
|
|
||||||
pBackend->pMethods->xFree(pBlock);
|
pBackend->pMethods->xFree(pBlock);
|
||||||
}
|
}
|
||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
@@ -308,20 +325,23 @@ static void *MemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
|||||||
SyMemHeader *pBucket, *pNext;
|
SyMemHeader *pBucket, *pNext;
|
||||||
sxu32 nBucketSize;
|
sxu32 nBucketSize;
|
||||||
sxu32 nBucket;
|
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 */
|
/* Allocate a big chunk directly */
|
||||||
pBucket = (SyMemHeader *)MemBackendAlloc(&(*pBackend), nBytes + sizeof(SyMemHeader));
|
pBucket = (SyMemHeader *)MemBackendAlloc(&(*pBackend), nBytes + SXMEM_PREFIX_SIZE);
|
||||||
if(pBucket == 0) {
|
if(pBucket == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Record as big block */
|
/* Record as big block */
|
||||||
pBucket->nBucket = (sxu32)(SXMEM_POOL_MAGIC << 16) | SXU16_HIGH;
|
pBucket->nBucket = ((sxu32)SXMEM_POOL_MAGIC << 16) | SXU16_HIGH;
|
||||||
return (void *)(pBucket + 1);
|
return (void *)((char *)pBucket + SXMEM_PREFIX_SIZE);
|
||||||
}
|
}
|
||||||
/* Locate the appropriate bucket */
|
/* Locate the appropriate bucket */
|
||||||
nBucket = 0;
|
nBucket = 0;
|
||||||
nBucketSize = SXMEM_POOL_MINALLOC;
|
nBucketSize = SXMEM_POOL_MINALLOC;
|
||||||
while(nBytes + sizeof(SyMemHeader) > nBucketSize) {
|
while(nBytes + SXMEM_PREFIX_SIZE > nBucketSize) {
|
||||||
nBucketSize <<= 1;
|
nBucketSize <<= 1;
|
||||||
nBucket++;
|
nBucket++;
|
||||||
}
|
}
|
||||||
@@ -338,8 +358,8 @@ static void *MemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
|||||||
pNext = pBucket->pNext;
|
pNext = pBucket->pNext;
|
||||||
pBackend->apPool[nBucket] = pNext;
|
pBackend->apPool[nBucket] = pNext;
|
||||||
/* Record bucket&magic number */
|
/* Record bucket&magic number */
|
||||||
pBucket->nBucket = (SXMEM_POOL_MAGIC << 16) | nBucket;
|
pBucket->nBucket = ((sxu32)SXMEM_POOL_MAGIC << 16) | nBucket;
|
||||||
return (void *)&pBucket[1];
|
return (void *)((char *)pBucket + SXMEM_PREFIX_SIZE);
|
||||||
}
|
}
|
||||||
PH7_PRIVATE void *SyMemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
PH7_PRIVATE void *SyMemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes) {
|
||||||
void *pChunk;
|
void *pChunk;
|
||||||
@@ -359,7 +379,7 @@ static sxi32 MemBackendPoolFree(SyMemBackend *pBackend, void *pChunk) {
|
|||||||
SyMemHeader *pHeader;
|
SyMemHeader *pHeader;
|
||||||
sxu32 nBucket;
|
sxu32 nBucket;
|
||||||
/* Get the corresponding bucket */
|
/* Get the corresponding bucket */
|
||||||
pHeader = (SyMemHeader *)(((char *)pChunk) - sizeof(SyMemHeader));
|
pHeader = (SyMemHeader *)(((char *)pChunk) - SXMEM_PREFIX_SIZE);
|
||||||
/* Sanity check to avoid misuse */
|
/* Sanity check to avoid misuse */
|
||||||
if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) {
|
if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) {
|
||||||
return SXERR_CORRUPT;
|
return SXERR_CORRUPT;
|
||||||
@@ -399,7 +419,7 @@ static void *MemBackendPoolRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBy
|
|||||||
return pNew;
|
return pNew;
|
||||||
}
|
}
|
||||||
/* Get the corresponding bucket */
|
/* Get the corresponding bucket */
|
||||||
pHeader = (SyMemHeader *)(((char *)pOld) - sizeof(SyMemHeader));
|
pHeader = (SyMemHeader *)(((char *)pOld) - SXMEM_PREFIX_SIZE);
|
||||||
/* Sanity check to avoid misuse */
|
/* Sanity check to avoid misuse */
|
||||||
if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) {
|
if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -410,7 +430,10 @@ static void *MemBackendPoolRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBy
|
|||||||
return MemBackendRealloc(&(*pBackend), pHeader, nByte);
|
return MemBackendRealloc(&(*pBackend), pHeader, nByte);
|
||||||
}
|
}
|
||||||
nBucketSize = 1 << (nBucket + SXMEM_POOL_INCR);
|
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 */
|
/* The old bucket can honor the requested size */
|
||||||
return pOld;
|
return pOld;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -942,7 +942,7 @@ PH7_PRIVATE sxi32 PH7_MemObjStore(ph7_value *pSrc, ph7_value *pDest) {
|
|||||||
((ph7_class_instance *)pSrc->x.pOther)->iRef++;
|
((ph7_class_instance *)pSrc->x.pOther)->iRef++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(pDest->nType & MEMOBJ_OBJ) {
|
if((pDest->nType & (MEMOBJ_OBJ | MEMOBJ_HASHMAP)) == MEMOBJ_OBJ) {
|
||||||
pObj = (ph7_class_instance *)pDest->x.pOther;
|
pObj = (ph7_class_instance *)pDest->x.pOther;
|
||||||
}
|
}
|
||||||
SyMemcpy((const void *) & (*pSrc), &(*pDest), sizeof(ph7_value) - (sizeof(ph7_vm *) + sizeof(SyBlob) + sizeof(sxu32)));
|
SyMemcpy((const void *) & (*pSrc), &(*pDest), sizeof(ph7_value) - (sizeof(ph7_vm *) + sizeof(SyBlob) + sizeof(sxu32)));
|
||||||
|
|||||||
+20
-9
@@ -5563,7 +5563,24 @@ Resume:
|
|||||||
SyString sName;
|
SyString sName;
|
||||||
/* Extract function name */
|
/* Extract function name */
|
||||||
/* Synthetic calls have no preceding instruction at pc == 0. */
|
/* Synthetic calls have no preceding instruction at pc == 0. */
|
||||||
if(pTos->nType & MEMOBJ_STRING && pc > 0 && aInstr[pc - 1].iOp == PH7_OP_LOADV) {
|
if((pTos->nType & (MEMOBJ_OBJ | MEMOBJ_HASHMAP)) == MEMOBJ_OBJ) {
|
||||||
|
ph7_class_instance *pThis = (ph7_class_instance *)pTos->x.pOther;
|
||||||
|
ph7_class_method *pMeth;
|
||||||
|
if(pThis == 0) {
|
||||||
|
PH7_VmThrowError(pVm, PH7_CTX_ERR, "Call to non-instantiated object");
|
||||||
|
}
|
||||||
|
SyStringInitFromBuf(&sName, "__invoke", sizeof("__invoke") - 1);
|
||||||
|
pMeth = VmMethodSeed(pVm, pThis->pClass, &sName, 0, FALSE);
|
||||||
|
if(pMeth == 0) {
|
||||||
|
PH7_VmThrowError(pVm, PH7_CTX_ERR, "Call to undefined method '%z->%z()'",
|
||||||
|
&pThis->pClass->sName, &sName);
|
||||||
|
}
|
||||||
|
/* Keep arguments and receiver intact for ordinary method dispatch. */
|
||||||
|
pTos++;
|
||||||
|
SyBlobAppend(&pTos->sBlob, SyStringData(&pMeth->sVmName), SyStringLength(&pMeth->sVmName));
|
||||||
|
MemObjSetType(pTos, MEMOBJ_STRING);
|
||||||
|
pTos->nIdx = SXU32_HIGH;
|
||||||
|
} else if(pTos->nType & MEMOBJ_STRING && pc > 0 && aInstr[pc - 1].iOp == PH7_OP_LOADV) {
|
||||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Calling a non-callable object");
|
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Calling a non-callable object");
|
||||||
} else if((pTos->nType & (MEMOBJ_CALL | MEMOBJ_STRING)) == 0) {
|
} else if((pTos->nType & (MEMOBJ_CALL | MEMOBJ_STRING)) == 0) {
|
||||||
if(pTos->nType & MEMOBJ_HASHMAP) {
|
if(pTos->nType & MEMOBJ_HASHMAP) {
|
||||||
@@ -5585,14 +5602,8 @@ Resume:
|
|||||||
PH7_MemObjStore(&sResult, pTos);
|
PH7_MemObjStore(&sResult, pTos);
|
||||||
PH7_MemObjRelease(&sResult);
|
PH7_MemObjRelease(&sResult);
|
||||||
} else {
|
} else {
|
||||||
if(pTos->nType & MEMOBJ_OBJ) {
|
/* Raise exception: Invalid function name */
|
||||||
ph7_class_instance *pThis = (ph7_class_instance *)pTos->x.pOther;
|
PH7_VmThrowError(&(*pVm), PH7_CTX_WARNING, "Invalid function name");
|
||||||
/* Call the magic method '__invoke' if available */
|
|
||||||
PH7_ClassInstanceCallMagicMethod(&(*pVm), pThis->pClass, pThis, "__invoke", sizeof("__invoke") - 1, 0);
|
|
||||||
} else {
|
|
||||||
/* Raise exception: Invalid function name */
|
|
||||||
PH7_VmThrowError(&(*pVm), PH7_CTX_WARNING, "Invalid function name");
|
|
||||||
}
|
|
||||||
/* Pop given arguments */
|
/* Pop given arguments */
|
||||||
if(pInstr->iP1 > 0) {
|
if(pInstr->iP1 > 0) {
|
||||||
VmPopOperand(&pTos, pInstr->iP1);
|
VmPopOperand(&pTos, pInstr->iP1);
|
||||||
|
|||||||
Reference in New Issue
Block a user