JSBool _callHook(JSDContext *jsdc, JSContext *cx, JSAbstractFramePtr frame, bool isConstructing, JSBool before, unsigned type, JSD_CallHookProc hook, void *hookData) { JSDScript* jsdscript; JSScript* jsscript; JSBool hookresult = JS_TRUE; if (!jsdc || !jsdc->inited) return JS_FALSE; if (!hook && !(jsdc->flags & JSD_COLLECT_PROFILE_DATA)) { /* no hook to call, no profile data needs to be collected, * so there is nothing to do here. */ return hookresult; } if (before && isConstructing) { js::RootedValue newObj(cx); if (!frame.getThisValue(cx, &newObj)) return JS_FALSE; jsd_Constructing(jsdc, cx, JSVAL_TO_OBJECT(newObj), frame); } jsscript = frame.script(); if (jsscript) { JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, jsscript, frame); JSD_UNLOCK_SCRIPTS(jsdc); if (jsdscript) { if (JSD_IS_PROFILE_ENABLED(jsdc, jsdscript)) { JSDProfileData *pdata; pdata = jsd_GetScriptProfileData (jsdc, jsdscript); if (pdata) { if (before) { if (!pdata->lastCallStart) { int64_t now; JSDProfileData *callerpdata; /* Get the time just the once, for consistency. */ now = JS_Now(); /* This contains a pointer to the profile data for * the caller of this function. */ callerpdata = jsdc->callingFunctionPData; if (callerpdata) { int64_t ll_delta; pdata->caller = callerpdata; /* We need to 'stop' the timer for the caller. * Use time since last return if appropriate. */ ll_delta = jsdc->lastReturnTime ? now - jsdc->lastReturnTime : now - callerpdata->lastCallStart; callerpdata->runningTime += ll_delta; } /* We're the new current function, and no return * has happened yet. */ jsdc->callingFunctionPData = pdata; jsdc->lastReturnTime = 0; /* This function has no running time (just been * called!), and we'll need the call start time. */ pdata->runningTime = 0; pdata->lastCallStart = now; } else { if (++pdata->recurseDepth > pdata->maxRecurseDepth) pdata->maxRecurseDepth = pdata->recurseDepth; } /* make sure we're called for the return too. */ hookresult = JS_TRUE; } else if (!pdata->recurseDepth && pdata->lastCallStart) { int64_t now, ll_delta; double delta; now = JS_Now(); ll_delta = now - pdata->lastCallStart; delta = ll_delta; delta /= 1000.0; pdata->totalExecutionTime += delta; /* minExecutionTime starts as 0, so we need to overwrite * it on the first call always. */ if ((0 == pdata->callCount) || delta < pdata->minExecutionTime) { pdata->minExecutionTime = delta; } if (delta > pdata->maxExecutionTime) pdata->maxExecutionTime = delta; /* If we last returned from a function (as opposed to * having last entered this function), we need to inc. * the running total by the time delta since the last * return, and use the running total instead of the * delta calculated above. */ if (jsdc->lastReturnTime) { /* Add last chunk to running time, and use total * running time as 'delta'. */ ll_delta = now - jsdc->lastReturnTime; pdata->runningTime += ll_delta; delta = pdata->runningTime; delta /= 1000.0; } pdata->totalOwnExecutionTime += delta; /* See minExecutionTime comment above. */ if ((0 == pdata->callCount) || delta < pdata->minOwnExecutionTime) { pdata->minOwnExecutionTime = delta; } if (delta > pdata->maxOwnExecutionTime) pdata->maxOwnExecutionTime = delta; /* Current function is now our caller. */ jsdc->callingFunctionPData = pdata->caller; /* No hanging pointers, please. */ pdata->caller = NULL; /* Mark the time we returned, and indicate this * function is no longer running. */ jsdc->lastReturnTime = now; pdata->lastCallStart = 0; ++pdata->callCount; } else if (pdata->recurseDepth) { --pdata->recurseDepth; ++pdata->callCount; } } if (hook) jsd_CallCallHook (jsdc, cx, type, hook, hookData); } else { if (hook) hookresult = jsd_CallCallHook (jsdc, cx, type, hook, hookData); else hookresult = JS_TRUE; } } } #ifdef JSD_TRACE _interpreterTrace(jsdc, cx, frame, isConstructing, before); return JS_TRUE; #else return hookresult; #endif }
JSBool _callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before, uintN type, JSD_CallHookProc hook, void *hookData) { JSDScript* jsdscript; JSScript* jsscript; JSBool hookresult = JS_TRUE; if (!jsdc || !jsdc->inited) return JS_FALSE; if (!hook && !(jsdc->flags & JSD_COLLECT_PROFILE_DATA) && jsdc->flags & JSD_DISABLE_OBJECT_TRACE) { /* no hook to call, no profile data needs to be collected, and * the client has object tracing disabled, so there is nothing * to do here. */ return hookresult; } if (before && JS_IsConstructorFrame(cx, fp)) jsd_Constructing(jsdc, cx, JS_GetFrameThis(cx, fp), fp); jsscript = JS_GetFrameScript(cx, fp); if (jsscript) { JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindJSDScript(jsdc, jsscript); JSD_UNLOCK_SCRIPTS(jsdc); if (jsdscript) { if (JSD_IS_PROFILE_ENABLED(jsdc, jsdscript)) { JSDProfileData *pdata; pdata = jsd_GetScriptProfileData (jsdc, jsdscript); if (pdata) { if (before) { if (JSLL_IS_ZERO(pdata->lastCallStart)) { int64 now; JSDProfileData *callerpdata; /* Get the time just the once, for consistency. */ now = JS_Now(); /* This contains a pointer to the profile data for * the caller of this function. */ callerpdata = jsdc->callingFunctionPData; if (callerpdata) { int64 ll_delta; pdata->caller = callerpdata; /* We need to 'stop' the timer for the caller. * Use time since last return if appropriate. */ if (JSLL_IS_ZERO(jsdc->lastReturnTime)) { JSLL_SUB(ll_delta, now, callerpdata->lastCallStart); } else { JSLL_SUB(ll_delta, now, jsdc->lastReturnTime); } JSLL_ADD(callerpdata->runningTime, callerpdata->runningTime, ll_delta); } /* We're the new current function, and no return * has happened yet. */ jsdc->callingFunctionPData = pdata; jsdc->lastReturnTime = JSLL_ZERO; /* This function has no running time (just been * called!), and we'll need the call start time. */ pdata->runningTime = JSLL_ZERO; pdata->lastCallStart = now; } else { if (++pdata->recurseDepth > pdata->maxRecurseDepth) pdata->maxRecurseDepth = pdata->recurseDepth; } /* make sure we're called for the return too. */ hookresult = JS_TRUE; } else if (!pdata->recurseDepth && !JSLL_IS_ZERO(pdata->lastCallStart)) { int64 now, ll_delta; jsdouble delta; now = JS_Now(); JSLL_SUB(ll_delta, now, pdata->lastCallStart); JSLL_L2D(delta, ll_delta); delta /= 1000.0; pdata->totalExecutionTime += delta; /* minExecutionTime starts as 0, so we need to overwrite * it on the first call always. */ if ((0 == pdata->callCount) || delta < pdata->minExecutionTime) { pdata->minExecutionTime = delta; } if (delta > pdata->maxExecutionTime) pdata->maxExecutionTime = delta; /* If we last returned from a function (as opposed to * having last entered this function), we need to inc. * the running total by the time delta since the last * return, and use the running total instead of the * delta calculated above. */ if (!JSLL_IS_ZERO(jsdc->lastReturnTime)) { /* Add last chunk to running time, and use total * running time as 'delta'. */ JSLL_SUB(ll_delta, now, jsdc->lastReturnTime); JSLL_ADD(pdata->runningTime, pdata->runningTime, ll_delta); JSLL_L2D(delta, pdata->runningTime); delta /= 1000.0; } pdata->totalOwnExecutionTime += delta; /* See minExecutionTime comment above. */ if ((0 == pdata->callCount) || delta < pdata->minOwnExecutionTime) { pdata->minOwnExecutionTime = delta; } if (delta > pdata->maxOwnExecutionTime) pdata->maxOwnExecutionTime = delta; /* Current function is now our caller. */ jsdc->callingFunctionPData = pdata->caller; /* No hanging pointers, please. */ pdata->caller = NULL; /* Mark the time we returned, and indicate this * function is no longer running. */ jsdc->lastReturnTime = now; pdata->lastCallStart = JSLL_ZERO; ++pdata->callCount; } else if (pdata->recurseDepth) { --pdata->recurseDepth; ++pdata->callCount; } } if (hook) jsd_CallCallHook (jsdc, cx, type, hook, hookData); } else { if (hook) hookresult = jsd_CallCallHook (jsdc, cx, type, hook, hookData); else hookresult = JS_TRUE; } } } #ifdef JSD_TRACE _interpreterTrace(jsdc, cx, fp, before); return JS_TRUE; #else return hookresult; #endif }