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
+20 -9
View File
@@ -5563,7 +5563,24 @@ Resume:
SyString sName;
/* Extract function name */
/* 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");
} else if((pTos->nType & (MEMOBJ_CALL | MEMOBJ_STRING)) == 0) {
if(pTos->nType & MEMOBJ_HASHMAP) {
@@ -5585,14 +5602,8 @@ Resume:
PH7_MemObjStore(&sResult, pTos);
PH7_MemObjRelease(&sResult);
} else {
if(pTos->nType & MEMOBJ_OBJ) {
ph7_class_instance *pThis = (ph7_class_instance *)pTos->x.pOther;
/* 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");
}
/* Raise exception: Invalid function name */
PH7_VmThrowError(&(*pVm), PH7_CTX_WARNING, "Invalid function name");
/* Pop given arguments */
if(pInstr->iP1 > 0) {
VmPopOperand(&pTos, pInstr->iP1);