Evaluate local constants once per declaration and invocation
Build / AerScript (push) Successful in 40s

This commit is contained in:
2026-10-25 19:57:49 +01:00
parent 8a2d7d8bd3
commit 85f59a2998
+42 -10
View File
@@ -492,6 +492,17 @@ static void VmScopeSync(ph7_vm *pVm, VmScopeInfo *pTarget, void *pExec) {
} }
VmScopeEnter(pVm, pTarget, pExec); VmScopeEnter(pVm, pTarget, pExec);
} }
/* Stable, invocation-owned storage: neither bytecode nor moving VM arrays own
* local constant values. Scope exit removes only their visible bindings. */
typedef struct VmLocalConstant VmLocalConstant;
struct VmLocalConstant {
ph7_constant_info *pDecl;
ph7_value sValue;
};
static void VmExpandLocalConstant(ph7_value *pVal, void *pUserData) {
VmLocalConstant *pConst = (VmLocalConstant *)pUserData;
PH7_MemObjLoad(&pConst->sValue, pVal);
}
/* /*
* Allocate a new virtual machine frame. * Allocate a new virtual machine frame.
*/ */
@@ -517,7 +528,7 @@ static VmFrame *VmNewFrame(
SySetInit(&pFrame->sArg, &pVm->sAllocator, sizeof(VmSlot)); SySetInit(&pFrame->sArg, &pVm->sAllocator, sizeof(VmSlot));
SySetInit(&pFrame->sLocal, &pVm->sAllocator, sizeof(VmSlot)); SySetInit(&pFrame->sLocal, &pVm->sAllocator, sizeof(VmSlot));
SySetInit(&pFrame->sRef, &pVm->sAllocator, sizeof(VmSlot)); SySetInit(&pFrame->sRef, &pVm->sAllocator, sizeof(VmSlot));
SySetInit(&pFrame->sConstDecl, &pVm->sAllocator, sizeof(void *)); SySetInit(&pFrame->sConstDecl, &pVm->sAllocator, sizeof(VmLocalConstant *));
return pFrame; return pFrame;
} }
/* /*
@@ -576,6 +587,14 @@ static void VmLeaveFrame(ph7_vm *pVm) {
SySetRelease(&pFrame->sArg); SySetRelease(&pFrame->sArg);
SySetRelease(&pFrame->sLocal); SySetRelease(&pFrame->sLocal);
SySetRelease(&pFrame->sRef); SySetRelease(&pFrame->sRef);
{
VmLocalConstant **apConst = (VmLocalConstant **)SySetBasePtr(&pFrame->sConstDecl);
sxu32 n;
for(n = 0; n < SySetUsed(&pFrame->sConstDecl); n++) {
PH7_MemObjRelease(&apConst[n]->sValue);
SyMemBackendPoolFree(&pVm->sAllocator, apConst[n]);
}
}
SySetRelease(&pFrame->sConstDecl); SySetRelease(&pFrame->sConstDecl);
/* Release the whole structure */ /* Release the whole structure */
SyMemBackendPoolFree(&pVm->sAllocator, pFrame); SyMemBackendPoolFree(&pVm->sAllocator, pFrame);
@@ -3071,25 +3090,39 @@ Resume:
/* Constant declaration */ /* Constant declaration */
ph7_constant_info *pConstInfo = (ph7_constant_info *) pInstr->p3; ph7_constant_info *pConstInfo = (ph7_constant_info *) pInstr->p3;
VmFrame *pOwner = pVm->pFrame; VmFrame *pOwner = pVm->pFrame;
void **apDecl; VmLocalConstant **apDecl, *pConst;
sxu32 n; sxu32 n;
while(pOwner->pParent && (pOwner->iFlags & VM_FRAME_ACTIVE) == 0) { while(pOwner->pParent && (pOwner->iFlags & VM_FRAME_ACTIVE) == 0) {
pOwner = pOwner->pParent; pOwner = pOwner->pParent;
} }
apDecl = (void **)SySetBasePtr(&pOwner->sConstDecl); apDecl = (VmLocalConstant **)SySetBasePtr(&pOwner->sConstDecl);
for(n = 0; n < SySetUsed(&pOwner->sConstDecl); n++) { for(n = 0; n < SySetUsed(&pOwner->sConstDecl); n++) {
if(apDecl[n] == pConstInfo) { if(apDecl[n]->pDecl == pConstInfo) {
PH7_VmThrowError(pVm, PH7_CTX_ERR, "Redeclaration of ‘%z’ constant", &pConstInfo->pName); PH7_VmThrowError(pVm, PH7_CTX_ERR, "Redeclaration of ‘%z’ constant", &pConstInfo->pName);
} }
} }
if(SySetPut(&pOwner->sConstDecl, &pConstInfo) != SXRET_OK) { pConst = (VmLocalConstant *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(VmLocalConstant));
if(pConst == 0) {
PH7_VmMemoryError(pVm); PH7_VmMemoryError(pVm);
} }
rc = PH7_VmRegisterConstant(&(*pVm), &pConstInfo->pName, PH7_VmExpandConstantValue, pConstInfo->pConsCode, FALSE); pConst->pDecl = pConstInfo;
PH7_MemObjInit(pVm, &pConst->sValue);
if(SySetPut(&pOwner->sConstDecl, &pConst) != SXRET_OK) {
PH7_VmMemoryError(pVm);
}
rc = PH7_VmRegisterConstant(&(*pVm), &pConstInfo->pName, VmExpandLocalConstant, pConst, FALSE);
if(rc == SXERR_EXISTS) { if(rc == SXERR_EXISTS) {
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, PH7_VmThrowError(&(*pVm), PH7_CTX_ERR,
"Redeclaration of ‘%z’ constant", &pConstInfo->pName); "Redeclaration of ‘%z’ constant", &pConstInfo->pName);
} }
rc = VmLocalExec(pVm, pConstInfo->pConsCode, &pConst->sValue);
if(rc == SXERR_MEM) {
PH7_VmMemoryError(pVm);
} else if(rc == PH7_ABORT) {
goto Abort;
} else if(rc == PH7_EXCEPTION) {
goto Exception;
}
} else { } else {
/* Variable declaration */ /* Variable declaration */
ph7_value *pObj; ph7_value *pObj;
@@ -6123,10 +6156,9 @@ PH7_PRIVATE sxi32 PH7_VmOutputConsumeAp(
return rc; return rc;
} }
/* /*
* Default constant expansion callback used by the 'const' statement if used * Constant expansion callback used by global constants declared with 'define'.
* outside a class body [i.e: global or function scope]. * Refer to the implementation of [PH7_CompileDefine()] defined
* Refer to the implementation of [PH7_CompileConstant()] defined * in 'compiler.c' for additional information.
* in 'compile.c' for additional information.
*/ */
PH7_PRIVATE void PH7_VmExpandConstantValue(ph7_value *pVal, void *pUserData) { PH7_PRIVATE void PH7_VmExpandConstantValue(ph7_value *pVal, void *pUserData) {
SySet *pByteCode = (SySet *)pUserData; SySet *pByteCode = (SySet *)pUserData;