Preserve pending completions through finally and restore operand stack on unwind
Build / AerScript (push) Successful in 38s
Build / AerScript (push) Successful in 38s
This commit is contained in:
+39
-16
@@ -948,19 +948,29 @@ static ph7_class_instance *NewClassInstance(ph7_vm *pVm, ph7_class *pClass) {
|
||||
* See the block comment above for more information.
|
||||
*/
|
||||
PH7_PRIVATE ph7_class_instance *PH7_NewClassInstance(ph7_vm *pVm, ph7_class *pClass) {
|
||||
ph7_class_instance *pNew;
|
||||
PH7_NewClassInstanceWithResult(pVm, pClass, &pNew, 0);
|
||||
return pNew;
|
||||
}
|
||||
/* Source construction needs both the status and the initializer's exception,
|
||||
* while existing internal callers retain the pointer-returning interface. */
|
||||
PH7_PRIVATE sxi32 PH7_NewClassInstanceWithResult(ph7_vm *pVm, ph7_class *pClass,
|
||||
ph7_class_instance **ppNew, ph7_value *pResult) {
|
||||
ph7_class_instance *pNew;
|
||||
sxi32 rc;
|
||||
*ppNew = 0;
|
||||
pNew = NewClassInstance(&(*pVm), &(*pClass));
|
||||
if(pNew == 0) {
|
||||
return 0;
|
||||
return SXERR_MEM;
|
||||
}
|
||||
/* Associate a private VM frame with this class instance */
|
||||
rc = PH7_VmCreateClassInstanceFrame(&(*pVm), pNew);
|
||||
rc = PH7_VmCreateClassInstanceFrame(&(*pVm), pNew, pResult);
|
||||
if(rc != SXRET_OK) {
|
||||
SyMemBackendPoolFree(&pVm->sAllocator, pNew);
|
||||
return 0;
|
||||
PH7_ClassInstanceAbort(pNew);
|
||||
return rc;
|
||||
}
|
||||
return pNew;
|
||||
*ppNew = pNew;
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Extract the value of a class instance [i.e: Object in the PHP jargon] attribute.
|
||||
@@ -1057,23 +1067,25 @@ static ph7_value *ExtractClassAttrValue(ph7_vm *pVm, VmClassAttr *pAttr) {
|
||||
* )
|
||||
*/
|
||||
PH7_PRIVATE ph7_class_instance *PH7_CloneClassInstance(ph7_class_instance *pSrc) {
|
||||
ph7_class_instance *pClone;
|
||||
PH7_CloneClassInstanceWithResult(pSrc, &pClone, 0);
|
||||
return pClone;
|
||||
}
|
||||
/* Preserve the pointer interface while source clone can propagate completion. */
|
||||
PH7_PRIVATE sxi32 PH7_CloneClassInstanceWithResult(ph7_class_instance *pSrc,
|
||||
ph7_class_instance **ppClone, ph7_value *pResult) {
|
||||
ph7_class_instance *pClone;
|
||||
ph7_class_method *pMethod;
|
||||
SyHashEntry *pEntry2;
|
||||
SyHashEntry *pEntry;
|
||||
ph7_vm *pVm;
|
||||
sxi32 rc;
|
||||
/* Allocate a new instance */
|
||||
*ppClone = 0;
|
||||
/* Reuse construction's initializer completion and partial-instance cleanup. */
|
||||
pVm = pSrc->pVm;
|
||||
pClone = NewClassInstance(pVm, pSrc->pClass);
|
||||
if(pClone == 0) {
|
||||
return 0;
|
||||
}
|
||||
/* Associate a private VM frame with this class instance */
|
||||
rc = PH7_VmCreateClassInstanceFrame(pVm, pClone);
|
||||
rc = PH7_NewClassInstanceWithResult(pVm, pSrc->pClass, &pClone, pResult);
|
||||
if(rc != SXRET_OK) {
|
||||
SyMemBackendPoolFree(&pVm->sAllocator, pClone);
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
/* Duplicate object values */
|
||||
SyHashResetLoopCursor(&pSrc->hAttr);
|
||||
@@ -1096,19 +1108,30 @@ PH7_PRIVATE ph7_class_instance *PH7_CloneClassInstance(ph7_class_instance *pSrc)
|
||||
if(pMethod) {
|
||||
if(pMethod->iCloneDepth < 16) {
|
||||
pMethod->iCloneDepth++;
|
||||
PH7_VmCallClassMethod(pVm, pClone, pMethod, 0, 0, 0);
|
||||
rc = PH7_VmCallClassMethod(pVm, pClone, pMethod, pResult, 0, 0);
|
||||
} else {
|
||||
/* Nesting limit reached */
|
||||
PH7_VmThrowError(pVm, PH7_CTX_ERR, "Object clone limit reached");
|
||||
}
|
||||
/* Reset the cursor */
|
||||
pMethod->iCloneDepth = 0;
|
||||
if(rc != SXRET_OK) {
|
||||
PH7_ClassInstanceUnref(pClone);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
/* Return the cloned object */
|
||||
return pClone;
|
||||
*ppClone = pClone;
|
||||
return SXRET_OK;
|
||||
}
|
||||
#define CLASS_INSTANCE_DESTROYED 0x001 /* Instance is released */
|
||||
#define CLASS_INSTANCE_FINALIZED 0x002 /* Destructor has already been invoked */
|
||||
/* Failed construction releases installed fields, but must not invoke the
|
||||
* destructor on an instance whose initialization did not finish. */
|
||||
PH7_PRIVATE void PH7_ClassInstanceAbort(ph7_class_instance *pThis) {
|
||||
pThis->iFlags |= CLASS_INSTANCE_FINALIZED;
|
||||
PH7_ClassInstanceUnref(pThis);
|
||||
}
|
||||
/* Run user finalization separately from storage release so VM teardown can
|
||||
* keep every closure environment valid until destructors have finished. */
|
||||
PH7_PRIVATE sxi32 PH7_ClassInstanceFinalize(ph7_class_instance *pThis) {
|
||||
|
||||
Reference in New Issue
Block a user