From 101453950eeefebbbdf1ae028c29de57461e7ce0 Mon Sep 17 00:00:00 2001 From: belliash Date: Tue, 4 Jun 2019 19:42:48 +0200 Subject: [PATCH] Execute the compiled 'finally' block. --- engine/vm.c | 46 +++++++++++++++++++++---------------- tests/exception_handler.exp | 1 + 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/engine/vm.c b/engine/vm.c index acfedae..fcbe212 100644 --- a/engine/vm.c +++ b/engine/vm.c @@ -6178,7 +6178,7 @@ static int VmClassMemberAccess( if(iProtection != PH7_CLASS_PROT_PUBLIC) { VmFrame *pFrame = pVm->pFrame; ph7_vm_func *pVmFunc; - while(pFrame->pParent && (pFrame->iFlags & (VM_FRAME_EXCEPTION | VM_FRAME_CATCH))) { + while(pFrame->pParent && (pFrame->iFlags & (VM_FRAME_EXCEPTION | VM_FRAME_CATCH | VM_FRAME_FINALLY))) { /* Safely ignore the exception frame */ pFrame = pFrame->pParent; } @@ -8149,6 +8149,8 @@ static sxi32 VmUncaughtException( if(pFrame->pParent) { if(pFrame->iFlags & VM_FRAME_CATCH) { SyStringInitFromBuf(&sFuncName, "Catch_block", sizeof("Catch_block") - 1); + } else if(pFrame->iFlags & VM_FRAME_FINALLY) { + SyStringInitFromBuf(&sFuncName, "Finally_block", sizeof("Finally_block") - 1); } else { ph7_vm_func *pFunc = (ph7_vm_func *)pFrame->pUserData; if(pFunc) { @@ -8174,6 +8176,7 @@ static sxi32 VmThrowException( ph7_exception_block *pCatch; /* Catch block to execute */ ph7_exception **apException; ph7_exception *pException; + sxi32 rc; /* Point to the stack of loaded exceptions */ apException = (ph7_exception **)SySetBasePtr(&pVm->aException); pException = 0; @@ -8201,25 +8204,9 @@ static sxi32 VmThrowException( } } } - /* Execute the cached block if available */ - if(pCatch == 0) { - sxi32 rc; - rc = VmUncaughtException(&(*pVm), pThis); - if(rc == SXRET_OK && pException) { - VmFrame *pFrame = pVm->pFrame; - while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) { - /* Safely ignore the exception frame */ - pFrame = pFrame->pParent; - } - if(pException->pFrame == pFrame) { - /* Tell the upper layer that the exception was caught */ - pFrame->iFlags &= ~VM_FRAME_THROW; - } - } - return rc; - } else { + /* Execute the 'catch' block if available */ + if(pCatch) { VmFrame *pFrame = pVm->pFrame; - sxi32 rc; while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) { /* Safely ignore the exception frame */ pFrame = pFrame->pParent; @@ -8246,10 +8233,29 @@ static sxi32 VmThrowException( VmLeaveFrame(&(*pVm)); } } + /* Execute the 'finally' block if available */ + if(pException && SySetUsed(&pException->sFinally)) { + rc = VmExecFinallyBlock(&(*pVm), pException); + } + /* No matching 'catch' block found */ + if(pCatch == 0) { + rc = VmUncaughtException(&(*pVm), pThis); + if(rc == SXRET_OK && pException) { + VmFrame *pFrame = pVm->pFrame; + while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) { + /* Safely ignore the exception frame */ + pFrame = pFrame->pParent; + } + if(pException->pFrame == pFrame) { + /* Tell the upper layer that the exception was caught */ + pFrame->iFlags &= ~VM_FRAME_THROW; + } + } + } /* TICKET 1433-60: Do not release the 'pException' pointer since it may * be used again if a 'goto' statement is executed. */ - return SXRET_OK; + return rc; } /* * Section: diff --git a/tests/exception_handler.exp b/tests/exception_handler.exp index 8310cc2..7a9deae 100644 --- a/tests/exception_handler.exp +++ b/tests/exception_handler.exp @@ -1,4 +1,5 @@ Uncaught NewException, code: 1 Message: Catch me once +Called finally block 1 Uncaught Exception, code: 2 Message: Catch me twice