Rewrite debug_backtrace() builtin function.
The build was successful. Details

It makes a use of new VmExtractDebugTrace() function. This probably fixes #45.
This commit is contained in:
Rafal Kupiec 2018-08-27 15:47:34 +02:00
parent ce621cc49c
commit c9a1971ace
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4
1 changed files with 49 additions and 85 deletions

View File

@ -9211,96 +9211,60 @@ static int vm_builtin_set_error_handler(ph7_context *pCtx, int nArg, ph7_value *
*/ */
static int vm_builtin_debug_backtrace(ph7_context *pCtx, int nArg, ph7_value **apArg) { static int vm_builtin_debug_backtrace(ph7_context *pCtx, int nArg, ph7_value **apArg) {
ph7_vm *pVm = pCtx->pVm; ph7_vm *pVm = pCtx->pVm;
SySet pDebug;
VmDebugTrace *pTrace;
ph7_value *pArray; ph7_value *pArray;
ph7_class *pClass; /* Extract debug information */
ph7_value *pValue; if(VmExtractDebugTrace(&(*pVm), &pDebug, TRUE) != SXRET_OK) {
SyString *pFile;
sxi32 iLine;
/* Create a new array */
pArray = ph7_context_new_array(pCtx);
pValue = ph7_context_new_scalar(pCtx);
VmFrame *oFrame = pVm->pFrame;
iLine = -1;
if(pArray == 0 || pValue == 0) {
/* Out of memory,return NULL */
ph7_context_throw_error(pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
ph7_result_null(pCtx); ph7_result_null(pCtx);
SXUNUSED(nArg); /* cc warning */
SXUNUSED(apArg);
return PH7_OK; return PH7_OK;
} }
/* Dump running function name and it's arguments */ pArray = ph7_context_new_array(pCtx);
while(pVm->pFrame) { if(!pArray) {
ph7_value *pArraySub; ph7_context_throw_error(pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
VmFrame *pFrame = pVm->pFrame; ph7_result_null(pCtx);
ph7_vm_func *pFunc; return PH7_OK;
ph7_value *pArg; }
pFunc = (ph7_vm_func *)pFrame->pUserData; /* Iterate through debug frames */
if(!pFunc || (pFrame->iFlags & VM_FRAME_EXCEPTION)) { while(SySetGetNextEntry(&pDebug, (void **)&pTrace) == SXRET_OK) {
goto rollFrame; VmSlot *aSlot;
} ph7_value *pArg, *pSubArray, *pValue;
pArraySub = ph7_context_new_array(pCtx); pArg = ph7_context_new_array(pCtx);
if(!pArraySub) { pSubArray = ph7_context_new_array(pCtx);
break; pValue = ph7_context_new_scalar(pCtx);
} if(pArg == 0 || pSubArray == 0 || pValue == 0) {
if(pFrame->pParent) { ph7_context_throw_error(pCtx, PH7_CTX_ERR, "PH7 is running out of memory");
ph7_value_string(pValue, pFunc->sName.zString, (int)pFunc->sName.nByte); ph7_result_null(pCtx);
ph7_array_add_strkey_elem(pArraySub, "function", pValue); return PH7_OK;
ph7_value_reset_string_cursor(pValue); }
} /* Extract file name and line */
/* Function arguments */ ph7_value_int(pValue, pTrace->nLine);
pArg = ph7_context_new_array(pCtx); ph7_array_add_strkey_elem(pSubArray, "line", pValue);
if(pArg) { ph7_value_string(pValue, pTrace->pFile->zString, pTrace->pFile->nByte);
ph7_value *pObj; ph7_array_add_strkey_elem(pSubArray, "file", pValue);
VmSlot *aSlot; ph7_value_reset_string_cursor(pValue);
sxu32 n; /* Extract called closure/method name */
/* Start filling the array with the given arguments */ ph7_value_string(pValue, pTrace->pFuncName->zString, (int)pTrace->pFuncName->nByte);
aSlot = (VmSlot *)SySetBasePtr(&pFrame->sArg); ph7_array_add_strkey_elem(pSubArray, "function", pValue);
for(n = 0; n < SySetUsed(&pFrame->sArg) ; n++) { ph7_value_reset_string_cursor(pValue);
pObj = (ph7_value *)SySetAt(&pCtx->pVm->aMemObj, aSlot[n].nIdx); /* Extract closure/method arguments */
if(pObj) { aSlot = (VmSlot *)SySetBasePtr(pTrace->pArg);
ph7_array_add_elem(pArg, 0/* Automatic index assign*/, pObj); for(int n = 0; n < SySetUsed(pTrace->pArg) ; n++) {
} ph7_value *pObj = (ph7_value *)SySetAt(&pCtx->pVm->aMemObj, aSlot[n].nIdx);
} if(pObj) {
/* Save the array */ ph7_array_add_elem(pArg, 0, pObj);
ph7_array_add_strkey_elem(pArraySub, "args", pArg); }
} }
if(pFunc) { ph7_array_add_strkey_elem(pSubArray, "args", pArg);
SySet *aByteCode = &pFunc->aByteCode; if(pTrace->pClassName) {
for(sxi32 i = (SySetUsed(aByteCode) - 1); i >= 0 ; i--) { /* Extract class name */
VmInstr *cInstr = (VmInstr *)SySetAt(aByteCode, i); ph7_value_string(pValue, pTrace->pClassName->zString, (int)pTrace->pClassName->nByte);
if(cInstr->iP2) { ph7_array_add_strkey_elem(pSubArray, "class", pValue);
iLine = cInstr->iLine; ph7_value_reset_string_cursor(pValue);
break; }
} /* Install debug frame in an array */
} ph7_array_add_elem(pArray, 0, pSubArray);
}
if(iLine != -1) {
ph7_value_int(pValue, iLine);
/* Append the current line (which is always 1 since PH7 does not track
* line numbers at run-time. )
*/
ph7_array_add_strkey_elem(pArraySub, "line", pValue);
}
/* Current processed script */
pFile = (SyString *)SySetPeek(&pVm->aFiles);
if(pFile) {
ph7_value_string(pValue, pFile->zString, (int)pFile->nByte);
ph7_array_add_strkey_elem(pArraySub, "file", pValue);
ph7_value_reset_string_cursor(pValue);
}
/* Top class */
pClass = PH7_VmExtractActiveClass(pVm, 0);
if(pClass) {
ph7_value_reset_string_cursor(pValue);
ph7_value_string(pValue, pClass->sName.zString, (int)pClass->sName.nByte);
ph7_array_add_strkey_elem(pArraySub, "class", pValue);
}
ph7_array_add_elem(pArray, 0, pArraySub);
rollFrame:
pVm->pFrame = pVm->pFrame->pParent;
} }
pVm->pFrame = oFrame;
/* Return the freshly created array */ /* Return the freshly created array */
ph7_result_value(pCtx, pArray); ph7_result_value(pCtx, pArray);
/* /*