From cf5058f478f28baf0e05f416f4a4f586da1fcc7f Mon Sep 17 00:00:00 2001 From: Rafal Kupiec Date: Thu, 29 Oct 2026 17:42:38 +0100 Subject: [PATCH] Separate static and instance entry-point initialization --- engine/vm.c | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/engine/vm.c b/engine/vm.c index 82656a0..d1361f3 100644 --- a/engine/vm.c +++ b/engine/vm.c @@ -6496,11 +6496,12 @@ static ph7_class_method *VmEntryPoint(ph7_vm *pVm, ph7_class *pClass) { */ PH7_PRIVATE sxi32 PH7_VmByteCodeExec(ph7_vm *pVm) { ph7_class *pClass; - ph7_class_instance *pInstance; + ph7_class_instance *pInstance = 0; ph7_class_method *pMethod; ph7_class_method *pMain; ph7_value *pArgs, *sArgv; ph7_value pResult; + sxi32 rc; const char *zParam; sxu32 nByte, nOffset; /* Make sure we are ready to execute this program */ @@ -6511,25 +6512,42 @@ PH7_PRIVATE sxi32 PH7_VmByteCodeExec(ph7_vm *pVm) { pVm->nMagic = PH7_VM_EXEC; /* Execute the byte code */ VmByteCodeExec(&(*pVm), (VmInstr *)SySetBasePtr(pVm->pByteContainer), pVm->aOps, -1, 0, FALSE); - /* Extract and instantiate the entry point */ + /* Extract the entry class */ pClass = PH7_VmExtractClass(&(*pVm), "Program", 7, TRUE /* Only loadable class but not 'interface' or 'virtual' class*/); if(!pClass) { PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Cannot find an entry 'Program' class"); } /* Reject invalid entry points before running the Program constructor. */ pMain = VmEntryPoint(pVm, pClass); - pInstance = PH7_NewClassInstance(&(*pVm), pClass); - if(pInstance == 0) { - PH7_VmMemoryError(&(*pVm)); + if((pMain->iFlags & PH7_CLASS_ATTR_STATIC) == 0) { + PH7_MemObjInit(pVm, &pResult); + rc = PH7_NewClassInstanceWithResult(pVm, pClass, &pInstance, &pResult); + pMethod = PH7_ClassExtractMethod(pClass, "__construct", sizeof("__construct") - 1); + if(rc == SXRET_OK && pMethod) { + /* Use ordinary constructor access and overload selection, with no arguments. */ + rc = VmCallClassMethod(pVm, pInstance, pMethod, &pResult, 0, 0, FALSE); + if(pInstance->iRef < 1) { + pInstance->iRef = 1; + } + } + if(rc != SXRET_OK) { + if(pInstance) { + PH7_ClassInstanceAbort(pInstance); + } + if(rc == PH7_EXCEPTION) { + VmUncaughtException(pVm, (pResult.nType & MEMOBJ_OBJ) ? (ph7_class_instance *)pResult.x.pOther : 0); + } + PH7_MemObjRelease(&pResult); + if(rc == SXERR_MEM) { + PH7_VmMemoryError(pVm); + } + /* Construction may stop via exit(); skip main, not shutdown. */ + goto Shutdown; + } + PH7_MemObjRelease(&pResult); + /* Enable garbage collector */ + pInstance->iRef--; } - /* Check if a constructor is available */ - pMethod = PH7_ClassExtractMethod(pClass, "__construct", sizeof("__construct") - 1); - if(pMethod) { - /* Call the class constructor */ - VmCallClassMethod(pVm, pInstance, pMethod, 0, 0, 0, FALSE); - } - /* Enable garbage collector */ - pInstance->iRef--; pArgs = ph7_new_array(&(*pVm)); sArgv = ph7_new_scalar(&(*pVm)); if(!pArgs || !sArgv) { @@ -6561,6 +6579,8 @@ PH7_PRIVATE sxi32 PH7_VmByteCodeExec(ph7_vm *pVm) { pVm->iExitStatus = 0; } } + rc = SXRET_OK; +Shutdown: /* Preserve end-of-execution finalization before shutdown, but keep capture * environments and their indexed contents alive until VM release. */ VmFinalizeObjects(pVm); @@ -6571,7 +6591,7 @@ PH7_PRIVATE sxi32 PH7_VmByteCodeExec(ph7_vm *pVm) { * so that any following call to [ph7_vm_exec()] without calling * [ph7_vm_reset()] first would fail. */ - return SXRET_OK; + return rc; } /* * Invoke the installed VM output consumer callback to consume