Keep source file descriptors stable for the lifetime of the VM and execute included fragments in the enclosing method and closure context
Build / AerScript (push) Successful in 40s

This commit is contained in:
2026-10-25 18:11:22 +01:00
parent c42b0ae010
commit 3e3b795626
5 changed files with 365 additions and 69 deletions
+189 -41
View File
@@ -302,7 +302,8 @@ PH7_PRIVATE sxi32 PH7_VmEmitInstr(
VmInstr sInstr;
sxi32 rc;
/* Extract the processed script */
SyString *pFile = (SyString *)SySetPeek(&pVm->aFiles);
SyString **ppFile = (SyString **)SySetPeek(&pVm->aFiles);
SyString *pFile = ppFile ? *ppFile : 0;
static const SyString sFileName = { "[MEMORY]", sizeof("[MEMORY]") - 1};
if(pFile == 0) {
pFile = (SyString *)&sFileName;
@@ -807,7 +808,11 @@ static sxi32 VmOverloadDominates(const sxi32 *aFirst, const sxi32 *aSecond, sxu3
return nFirstDefaults < nSecondDefaults;
}
/* Forward declaration */
static sxi32 VmExecIncludedFile(ph7_vm *pVm, SyString *pPath, int iFlags);
#define VM_EXEC_INCLUDE 2
#define VM_INCLUDE_RETURN 3
#define VM_INCLUDE_JUMP 4
#define VM_INCLUDE_EXCEPTION 5
static sxi32 VmExecIncludedFile(ph7_vm *pVm, SyString *pPath, int iFlags, ph7_value *pResult, ph7_include *pInclude);
static sxi32 VmLocalExec(ph7_vm *pVm, SySet *pByteCode, ph7_value *pResult);
static sxi32 VmClassMemberAccess(ph7_vm *pVm, ph7_class *pClass, sxi32 iProtection);
static ph7_class *VmMethodClass(ph7_vm *pVm);
@@ -1335,7 +1340,7 @@ PH7_PRIVATE ph7_value *VmReserveMemObj(ph7_vm *pVm, sxu32 *pIndex) {
return pObj;
}
/* Forward declaration */
static sxi32 VmEvalChunk(ph7_vm *pVm, ph7_context *pCtx, SyString *pChunk, int iFlags);
static sxi32 VmEvalChunk(ph7_vm *pVm, ph7_context *pCtx, SyString *pChunk, int iFlags, ph7_value *pResult, ph7_include *pInclude);
/*
* Built-in classes/interfaces and some functions that cannot be implemented
* directly as foreign functions.
@@ -1504,7 +1509,7 @@ PH7_PRIVATE sxi32 PH7_VmInit(
/* Configuration containers */
SySetInit(&pVm->aModules, &pVm->sAllocator, sizeof(VmModule));
SySetInit(&pVm->aModuleHandles, &pVm->sAllocator, sizeof(VmModule));
SySetInit(&pVm->aFiles, &pVm->sAllocator, sizeof(SyString));
SySetInit(&pVm->aFiles, &pVm->sAllocator, sizeof(SyString *));
SySetInit(&pVm->aPaths, &pVm->sAllocator, sizeof(SyString));
SySetInit(&pVm->aIncluded, &pVm->sAllocator, sizeof(SyString));
rc = SyHashInit(&pVm->hRequired, &pVm->sAllocator, SyStrHash, (int (*)(const void *, const void *, sxu32))SyMemcmp);
@@ -1558,7 +1563,7 @@ PH7_PRIVATE sxi32 PH7_VmInit(
pVm->nMagic = PH7_VM_INIT;
SyStringInitFromBuf(&sBuiltin, PH7_BUILTIN_LIB, sizeof(PH7_BUILTIN_LIB) - 1);
/* Precompile the built-in library */
VmEvalChunk(&(*pVm), 0, &sBuiltin, PH7_AERSCRIPT_CODE);
VmEvalChunk(&(*pVm), 0, &sBuiltin, PH7_AERSCRIPT_CODE, 0, 0);
if(bDebug) {
/* Enable debugging */
pVm->bDebug = TRUE;
@@ -2449,13 +2454,15 @@ static sxi32 VmByteCodeExec(
int nTos, /* Top entry in the operand stack (usually -1) */
ph7_value *pResult, /* Store program return value here. NULL otherwise */
sxu32 *pLastRef, /* Last referenced ph7_value index */
int is_callback /* TRUE if we are executing a callback */
int iExecFlags /* Callback (1) or included statements (VM_EXEC_INCLUDE) */
) {
VmInstr *pInstr;
ph7_value *pTos;
SySet aArg;
sxi32 pc;
sxi32 rc;
sxi32 bReturning = FALSE;
VmFrame *pEntryFrame = pVm->pFrame;
/* Argument container */
SySetInit(&aArg, &pVm->sAllocator, sizeof(ph7_value *));
if(nTos < 0) {
@@ -2465,6 +2472,7 @@ static sxi32 VmByteCodeExec(
}
pc = 0;
/* Execute as much as we can */
Resume:
for(;;) {
if(!pVm->bDebug) {
/* Reset instructions set container */
@@ -2491,6 +2499,11 @@ static sxi32 VmByteCodeExec(
* and return immediately.
*/
case PH7_OP_DONE:
bReturning = pInstr->p3 != 0;
if(bReturning && !pInstr->iP1 && (iExecFlags & VM_EXEC_INCLUDE) && pResult) {
PH7_MemObjRelease(pResult);
MemObjSetType(pResult, MEMOBJ_NULL);
}
if(pInstr->iP1) {
if(pTos < pStack) {
goto Abort;
@@ -2500,11 +2513,11 @@ static sxi32 VmByteCodeExec(
}
/* Unwind local loops, but let VmExecExceptionBlock() release
* the handler without freeing its borrowed owner frames. */
if(pInstr->p3) { /* Called from a return statement */
if(pInstr->p3 && (iExecFlags & VM_EXEC_INCLUDE) == 0) { /* Called from a return statement */
while(pVm->pFrame->pParent && (pVm->pFrame->iFlags & (VM_FRAME_ACTIVE | VM_FRAME_CATCH | VM_FRAME_FINALLY)) == 0) {
VmLeaveFrame(&(*pVm));
}
} else if(pVm->pFrame->iFlags & VM_FRAME_LOOP) {
} else if(!pInstr->p3 && (iExecFlags & VM_EXEC_INCLUDE) == 0 && (pVm->pFrame->iFlags & VM_FRAME_LOOP)) {
while(pVm->pFrame->pParent && (pVm->pFrame->iFlags & (VM_FRAME_ACTIVE | VM_FRAME_CATCH | VM_FRAME_FINALLY)) == 0) {
VmLeaveFrame(&(*pVm));
}
@@ -2512,8 +2525,14 @@ static sxi32 VmByteCodeExec(
if(pResult) {
/* Execution result */
PH7_MemObjStore(pTos, pResult);
if(!pInstr->iP2 && pVm->pFrame->iFlags & VM_FRAME_ACTIVE) {
ph7_vm_func *pFunc = (ph7_vm_func *)pVm->pFrame->pUserData;
VmFrame *pOwner = pVm->pFrame;
if(iExecFlags & VM_EXEC_INCLUDE) {
while(pOwner->pParent && (pOwner->iFlags & VM_FRAME_ACTIVE) == 0) {
pOwner = pOwner->pParent;
}
}
if(!pInstr->iP2 && (pOwner->iFlags & VM_FRAME_ACTIVE)) {
ph7_vm_func *pFunc = (ph7_vm_func *)pOwner->pUserData;
if(pFunc->nType) {
if((pFunc->nType & MEMOBJ_MIXED) == 0) {
if(pFunc->nType & MEMOBJ_VOID) {
@@ -2539,6 +2558,9 @@ static sxi32 VmByteCodeExec(
/* Nothing referenced */
*pLastRef = SXU32_HIGH;
}
if(bReturning && (iExecFlags & VM_EXEC_INCLUDE)) {
goto IncludeReturn;
}
goto Done;
/*
* HALT: P1 * *
@@ -2572,12 +2594,22 @@ static sxi32 VmByteCodeExec(
}
goto Abort;
/*
* JMP: * P2 *
* JMP: P1 P2 *
*
* Unconditional jump: The next instruction executed will be
* the one at index P2 from the beginning of the program.
* P1 marks an include-to-owner transfer rather than a local jump.
*/
case PH7_OP_JMP:
if(pInstr->iP1 && (iExecFlags & VM_EXEC_INCLUDE)) {
if(pResult) {
PH7_MemObjRelease(pResult);
pResult->x.iVal = pInstr->iP2;
MemObjSetType(pResult, MEMOBJ_INT);
}
SySetRelease(&aArg);
return VM_INCLUDE_JUMP;
}
pc = pInstr->iP2 - 1;
break;
/*
@@ -4434,6 +4466,9 @@ static sxi32 VmByteCodeExec(
pException->pFrame = 0;
/* Leave the exception frame */
VmLeaveFrame(&(*pVm));
if(bReturning) {
goto IncludeReturn;
}
break;
}
/*
@@ -4483,6 +4518,9 @@ static sxi32 VmByteCodeExec(
}
/* Pop the top entry */
VmPopOperand(&pTos, 1);
if(iExecFlags & VM_EXEC_INCLUDE) {
goto IncludeException;
}
/* Perform an unconditional jump */
pc = nJump - 1;
break;
@@ -4568,20 +4606,50 @@ static sxi32 VmByteCodeExec(
break;
}
/*
* OP_INCLUDE P1 * P3
* OP_INCLUDE P1 P2 P3
* Include another source file. If P1 is zero, 'include' statement was used, otherwise it was 'require'.
* P3 contains a path to the source file.
* P3 contains a path, or lexical include metadata when P2 is set.
*/
case PH7_OP_INCLUDE:
{
char *zFile = (char *) pInstr->p3;
ph7_include *pInclude = !pInstr->iP1 && pInstr->iP2 ? (ph7_include *)pInstr->p3 : 0;
char *zFile = pInclude ? pInclude->zPath : (char *)pInstr->p3;
ph7_value sIncludeResult;
int iFlags = pInstr->iP1 ? PH7_AERSCRIPT_CODE : PH7_AERSCRIPT_CHNK;
SyString sFile;
if(SyStrlen(zFile) < 1) {
break;
}
SyStringInitFromBuf(&sFile, zFile, SyStrlen(zFile));
rc = VmExecIncludedFile(&(*pVm), &sFile, iFlags | PH7_AERSCRIPT_FILE);
PH7_MemObjInit(pVm, &sIncludeResult);
rc = VmExecIncludedFile(&(*pVm), &sFile, iFlags | PH7_AERSCRIPT_FILE, &sIncludeResult, pInclude);
if(rc == VM_INCLUDE_JUMP) {
pc = (sxi32)sIncludeResult.x.iVal - 1;
PH7_MemObjRelease(&sIncludeResult);
break;
}
if(!pInstr->iP1 && rc == VM_INCLUDE_RETURN) {
if(pResult) {
PH7_MemObjStore(&sIncludeResult, pResult);
}
PH7_MemObjRelease(&sIncludeResult);
bReturning = TRUE;
goto IncludeReturn;
}
PH7_MemObjRelease(&sIncludeResult);
if(rc == VM_INCLUDE_EXCEPTION) {
goto IncludeException;
}
if(!pInstr->iP1 && rc == SXERR_NOTFOUND) {
PH7_VmThrowError(pVm, PH7_CTX_WARNING, "IO error while including file: '%z'", &sFile);
break;
}
if(!pInstr->iP1 && rc == PH7_ABORT) {
goto Abort;
}
if(!pInstr->iP1 && rc == PH7_EXCEPTION) {
goto Exception;
}
if(rc != SXRET_OK && rc != SXERR_EXISTS) {
PH7_VmThrowError(pVm, PH7_CTX_ERR, "IO error while including file: '%z'", &sFile);
}
@@ -5541,12 +5609,12 @@ static sxi32 VmByteCodeExec(
if(rc != PH7_ABORT && ((pFrame->iFlags & VM_FRAME_THROW) || rc == PH7_EXCEPTION)) {
/* An exception was throw in this frame */
pFrame = pFrame->pParent;
if(!is_callback && pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION) && pFrame->iExceptionJump > 0) {
if((iExecFlags & 1) == 0 && pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION) && pFrame->iExceptionJump > 0) {
/* Pop the result */
VmPopOperand(&pTos, 1);
/* Jump to this destination */
pc = pFrame->iExceptionJump - 1;
rc = PH7_OK;
rc = (iExecFlags & VM_EXEC_INCLUDE) ? VM_INCLUDE_EXCEPTION : PH7_OK;
} else {
if(pFrame->pParent) {
rc = PH7_EXCEPTION;
@@ -5560,6 +5628,9 @@ static sxi32 VmByteCodeExec(
SyMemBackendFree(&pVm->sAllocator, pFrameStack);
/* Leave the frame */
VmLeaveFrame(&(*pVm));
if(rc == VM_INCLUDE_EXCEPTION) {
goto IncludeException;
}
if(rc == PH7_ABORT) {
/* Abort processing immediately */
goto Abort;
@@ -5637,9 +5708,50 @@ static sxi32 VmByteCodeExec(
} /* Switch() */
pc++; /* Next instruction in the stream */
} /* For(;;) */
IncludeException:
/* The catch has already run. Transfer to its owning bytecode's epilogue,
* forwarding across included chunks without throwing/catching again. */
{
VmFrame *pFrame = pVm->pFrame;
while(pFrame->pParent) {
if((iExecFlags & VM_EXEC_INCLUDE) && pFrame == pEntryFrame) {
SySetRelease(&aArg);
while(pTos >= pStack) {
PH7_MemObjRelease(pTos);
pTos--;
}
return VM_INCLUDE_EXCEPTION;
}
if(pFrame->iFlags & VM_FRAME_EXCEPTION) {
while(pVm->pFrame != pFrame) {
VmLeaveFrame(pVm);
}
pc = pFrame->iExceptionJump;
goto Resume;
}
if(pFrame == pEntryFrame) {
/* A called method still has its own execution boundary. */
goto Exception;
}
pFrame = pFrame->pParent;
}
}
goto Exception;
IncludeReturn:
/* The include has no return boundary. Let the owner's existing exception
* epilogue run finally before completing the pending return. */
if((iExecFlags & VM_EXEC_INCLUDE) == 0 || pVm->pFrame != pEntryFrame) {
while(pVm->pFrame->pParent && pVm->pFrame != pEntryFrame && (pVm->pFrame->iFlags & (VM_FRAME_ACTIVE | VM_FRAME_CATCH | VM_FRAME_FINALLY | VM_FRAME_EXCEPTION)) == 0) {
VmLeaveFrame(pVm);
}
if(((iExecFlags & VM_EXEC_INCLUDE) == 0 || pVm->pFrame != pEntryFrame) && (pVm->pFrame->iFlags & VM_FRAME_EXCEPTION) && pVm->pFrame->iExceptionJump > 0) {
pc = pVm->pFrame->iExceptionJump;
goto Resume;
}
}
Done:
SySetRelease(&aArg);
return SXRET_OK;
return bReturning && (iExecFlags & VM_EXEC_INCLUDE) ? VM_INCLUDE_RETURN : SXRET_OK;
Abort:
SySetRelease(&aArg);
while(pTos >= pStack) {
@@ -8251,7 +8363,7 @@ static int vm_builtin_assert(ph7_context *pCtx, int nArg, ph7_value **apArg) {
SyString sChunk;
SyStringInitFromBuf(&sChunk, SyBlobData(&pAssert->sBlob), SyBlobLength(&pAssert->sBlob));
if(sChunk.nByte > 0) {
VmEvalChunk(pVm, pCtx, &sChunk, PH7_AERSCRIPT_CHNK | PH7_AERSCRIPT_EXPR);
VmEvalChunk(pVm, pCtx, &sChunk, PH7_AERSCRIPT_CHNK | PH7_AERSCRIPT_EXPR, 0, 0);
/* Extract evaluation result */
iResult = ph7_value_to_bool(pCtx->pRet);
} else {
@@ -8268,8 +8380,10 @@ static int vm_builtin_assert(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_value sFile, sLine;
ph7_value *apCbArg[3];
SyString *pFile;
SyString **ppFile;
/* Extract the processed script */
pFile = (SyString *)SySetPeek(&pVm->aFiles);
ppFile = (SyString **)SySetPeek(&pVm->aFiles);
pFile = ppFile ? *ppFile : 0;
if(pFile == 0) {
pFile = (SyString *)&sFileName;
}
@@ -9332,12 +9446,15 @@ static sxi32 VmEvalChunk(
ph7_vm *pVm, /* Underlying Virtual Machine */
ph7_context *pCtx, /* Call Context */
SyString *pChunk, /* PHP chunk to evaluate */
int iFlags /* Code evaluation flag */
int iFlags, /* Code evaluation flag */
ph7_value *pResult, /* Enclosing method/closure return value for include */
ph7_include *pInclude /* Lexical control-flow bridges */
) {
SySet *pByteCode, aByteCode;
sxi32 rc = SXRET_OK;
sxi32 bRequire = (iFlags & (PH7_AERSCRIPT_CODE | PH7_AERSCRIPT_FILE)) ==
(PH7_AERSCRIPT_CODE | PH7_AERSCRIPT_FILE);
sxi32 bInclude = (iFlags & PH7_AERSCRIPT_FILE) && !bRequire;
ProcConsumer xErr = 0;
void *pErrData = 0;
/* Initialize bytecode container */
@@ -9349,7 +9466,9 @@ static sxi32 VmEvalChunk(
/* Log compile-time errors */
xErr = pVm->pEngine->xConf.xErr;
pErrData = pVm->pEngine->xConf.pErrData;
PH7_ResetCodeGenerator(pVm, xErr, pErrData);
if(!bInclude) {
PH7_ResetCodeGenerator(pVm, xErr, pErrData);
}
/* Swap bytecode container */
pByteCode = pVm->pByteContainer;
pVm->pByteContainer = &aByteCode;
@@ -9358,8 +9477,16 @@ static sxi32 VmEvalChunk(
PH7_VmPushFilePath(pVm, "[MEMORY]", -1, TRUE, 0);
}
/* Compile the chunk */
rc = PH7_CompileAerScript(pVm, pChunk, iFlags);
if(rc != SXRET_OK && bRequire) {
if(bInclude) {
VmFrame *pOwner = pVm->pFrame;
while(pOwner->pParent && (pOwner->iFlags & VM_FRAME_ACTIVE) == 0) {
pOwner = pOwner->pParent;
}
rc = PH7_CompileIncludedChunk(pVm, pChunk, (ph7_vm_func *)pOwner->pUserData, pInclude);
} else {
rc = PH7_CompileAerScript(pVm, pChunk, iFlags);
}
if(rc != SXRET_OK && (bRequire || bInclude)) {
goto Cleanup;
}
ph7_value sResult; /* Return value */
@@ -9386,7 +9513,21 @@ static sxi32 VmEvalChunk(
/* Assume a boolean true return value */
PH7_MemObjInitFromBool(pVm, &sResult, 1);
/* Execute the compiled chunk */
rc = VmLocalExec(pVm, &aByteCode, &sResult);
if(bInclude) {
ph7_value *pStack = VmNewOperandStack(pVm, SySetUsed(&aByteCode));
if(pStack == 0) {
rc = SXERR_MEM;
} else {
rc = VmByteCodeExec(pVm, (VmInstr *)SySetBasePtr(&aByteCode), pStack, -1,
&sResult, 0, VM_EXEC_INCLUDE);
SyMemBackendFree(&pVm->sAllocator, pStack);
if((rc == VM_INCLUDE_RETURN || rc == VM_INCLUDE_JUMP) && pResult) {
PH7_MemObjStore(&sResult, pResult);
}
}
} else {
rc = VmLocalExec(pVm, &aByteCode, &sResult);
}
if(pCtx) {
/* Set the execution result */
ph7_result_value(pCtx, &sResult);
@@ -9396,7 +9537,7 @@ Cleanup:
/* Cleanup the mess left behind */
pVm->pByteContainer = pByteCode;
SySetRelease(&aByteCode);
return bRequire ? rc : SXRET_OK;
return bRequire || bInclude ? rc : SXRET_OK;
}
/*
* value eval(string $code)
@@ -9423,7 +9564,7 @@ static int vm_builtin_eval(ph7_context *pCtx, int nArg, ph7_value **apArg) {
return SXRET_OK;
}
/* Eval the chunk */
VmEvalChunk(pCtx->pVm, &(*pCtx), &sChunk, PH7_AERSCRIPT_CHNK);
VmEvalChunk(pCtx->pVm, &(*pCtx), &sChunk, PH7_AERSCRIPT_CHNK, 0, 0);
return SXRET_OK;
}
/*
@@ -9446,7 +9587,7 @@ static int VmIsIncludedFile(ph7_vm *pVm, SyString *pFile) {
* Push a file path in the appropriate VM container.
*/
PH7_PRIVATE sxi32 PH7_VmPushFilePath(ph7_vm *pVm, const char *zPath, int nLen, sxu8 bMain, sxi32 *pNew) {
SyString sPath;
SyString *pPath;
char *zDup;
#ifdef __WINNT__
char *zCur;
@@ -9455,11 +9596,16 @@ PH7_PRIVATE sxi32 PH7_VmPushFilePath(ph7_vm *pVm, const char *zPath, int nLen, s
if(nLen < 0) {
nLen = SyStrlen(zPath);
}
/* Duplicate the file path first */
zDup = SyMemBackendStrDup(&pVm->sAllocator, zPath, nLen);
if(zDup == 0) {
/* Instructions borrow the descriptor, not an element of the growable
* file list. Keep it and its bytes stable until the VM allocator releases
* them, including after nested include/require compilation. */
pPath = (SyString *)SyMemBackendAlloc(&pVm->sAllocator, sizeof(SyString) + nLen + 1);
if(pPath == 0) {
return SXERR_MEM;
}
zDup = (char *)(pPath + 1);
SyMemcpy(zPath, zDup, nLen);
zDup[nLen] = 0;
#ifdef __WINNT__
/* Normalize path on windows
* Example:
@@ -9479,27 +9625,27 @@ PH7_PRIVATE sxi32 PH7_VmPushFilePath(ph7_vm *pVm, const char *zPath, int nLen, s
}
#endif
/* Install the file path */
SyStringInitFromBuf(&sPath, zDup, nLen);
SyStringInitFromBuf(pPath, zDup, nLen);
if(!bMain) {
if(VmIsIncludedFile(&(*pVm), &sPath)) {
if(VmIsIncludedFile(&(*pVm), pPath)) {
/* Already included */
*pNew = 0;
} else {
/* Insert in the corresponding container */
rc = SySetPut(&pVm->aIncluded, (const void *)&sPath);
rc = SySetPut(&pVm->aIncluded, (const void *)pPath);
if(rc != SXRET_OK) {
SyMemBackendFree(&pVm->sAllocator, zDup);
SyMemBackendFree(&pVm->sAllocator, pPath);
return rc;
}
*pNew = 1;
}
}
rc = SySetPut(&pVm->aFiles, (const void *)&sPath);
rc = SySetPut(&pVm->aFiles, (const void *)&pPath);
if(rc != SXRET_OK) {
if(!bMain && *pNew) {
SySetPop(&pVm->aIncluded);
}
SyMemBackendFree(&pVm->sAllocator, zDup);
SyMemBackendFree(&pVm->sAllocator, pPath);
return rc;
}
return SXRET_OK;
@@ -9517,7 +9663,9 @@ PH7_PRIVATE sxi32 PH7_VmPushFilePath(ph7_vm *pVm, const char *zPath, int nLen, s
static sxi32 VmExecIncludedFile(
ph7_vm *pVm, /* Underlying Virtual Machine */
SyString *pPath, /* Script path or URL*/
int iFlags /* Code evaluation flag */
int iFlags, /* Code evaluation flag */
ph7_value *pResult, /* Enclosing method/closure return value */
ph7_include *pInclude /* Lexical control-flow bridges */
) {
sxi32 rc;
const ph7_io_stream *pStream;
@@ -9537,13 +9685,13 @@ static sxi32 VmExecIncludedFile(
*/
pHandle = PH7_StreamOpenHandle(pVm, pStream, pPath->zString, PH7_IO_OPEN_RDONLY, TRUE, 0, TRUE, &isNew);
if(pHandle == 0) {
return SXERR_IO;
return (iFlags & PH7_AERSCRIPT_CODE) ? SXERR_IO : SXERR_NOTFOUND;
}
rc = SXRET_OK; /* Stupid cc warning */
if(iFlags & PH7_AERSCRIPT_CODE) {
/* The loader owns these bytes until VM release. Do not use the spelling
* from the statement, or the independent include history, as the key. */
sRequired = *(SyString *)SySetPeek(&pVm->aFiles);
sRequired = **(SyString **)SySetPeek(&pVm->aFiles);
pRequired = SyHashGet(&pVm->hRequired, sRequired.zString, sRequired.nByte);
if(pRequired) {
PH7_VmThrowError(pVm, PH7_CTX_WARNING, pRequired->pUserData ?
@@ -9567,7 +9715,7 @@ static sxi32 VmExecIncludedFile(
/* Compile and execute the script */
SyStringInitFromBuf(&sScript, SyBlobData(&sContents), SyBlobLength(&sContents));
pVm->nMagic = PH7_VM_INCL;
rc = VmEvalChunk(pVm, 0, &sScript, iFlags);
rc = VmEvalChunk(pVm, 0, &sScript, iFlags, pResult, pInclude);
pVm->nMagic = (iFlags & PH7_AERSCRIPT_CODE) ? nMagic : PH7_VM_EXEC;
}
if(pRequired) {