JSDScript* jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval) { JSContext* cx = jsdc->dumbContext; jsval val = jsdval->val; JSFunction* fun; JSExceptionState* exceptionState; JSScript* script = NULL; JSDScript* jsdscript; if (!jsd_IsValueFunction(jsdc, jsdval)) return NULL; JS_BeginRequest(cx); exceptionState = JS_SaveExceptionState(cx); fun = JS_ValueToFunction(cx, val); JS_RestoreExceptionState(cx, exceptionState); if (fun) script = JS_GetFunctionScript(cx, fun); JS_EndRequest(cx); if (!script) return NULL; JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindJSDScript(jsdc, script); JSD_UNLOCK_SCRIPTS(jsdc); return jsdscript; }
JSDScript * jsd_FindOrCreateJSDScript(JSDContext *jsdc, JSContext *cx, JSScript *script_, JSAbstractFramePtr frame) { JS::RootedScript script(cx, script_); JSDScript *jsdscript; JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc)); jsdscript = jsd_FindJSDScript(jsdc, script); if (jsdscript) return jsdscript; /* Fallback for unknown scripts: create a new script. */ if (!frame) { JSBrokenFrameIterator iter(cx); if (!iter.done()) frame = iter.abstractFramePtr(); } if (frame) jsdscript = _newJSDScript(jsdc, cx, script); return jsdscript; }
static JSBool _isActiveHook(JSDContext* jsdc, JSScript *script, JSDExecHook* jsdhook) { JSDExecHook* current; JSCList* list; JSDScript* jsdscript; JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindJSDScript(jsdc, script); if( ! jsdscript) { JSD_UNLOCK_SCRIPTS(jsdc); return JS_FALSE; } list = &jsdscript->hooks; for( current = (JSDExecHook*)list->next; current != (JSDExecHook*)list; current = (JSDExecHook*)current->links.next ) { if(current == jsdhook) { JSD_UNLOCK_SCRIPTS(jsdc); return JS_TRUE; } } JSD_UNLOCK_SCRIPTS(jsdc); return JS_FALSE; }
JSDScript* jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval) { JSContext* cx = jsdc->dumbContext; JS::RootedValue val(cx, jsdval->val); JSFunction* fun = NULL; JSExceptionState* exceptionState; JS::RootedScript script(cx); JSDScript* jsdscript; JSCompartment* oldCompartment = NULL; if (!jsd_IsValueFunction(jsdc, jsdval)) return NULL; JS_BeginRequest(cx); oldCompartment = JS_EnterCompartment(cx, JSVAL_TO_OBJECT(val)); exceptionState = JS_SaveExceptionState(cx); fun = JSD_GetValueFunction(jsdc, jsdval); JS_RestoreExceptionState(cx, exceptionState); if (fun) script = JS_GetFunctionScript(cx, fun); JS_LeaveCompartment(cx, oldCompartment); JS_EndRequest(cx); if (!script) return NULL; JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindJSDScript(jsdc, script); JSD_UNLOCK_SCRIPTS(jsdc); return jsdscript; }
void jsd_DestroyScriptHookProc( JSFreeOp *fop, JSScript *script_, void* callerdata ) { JSDScript* jsdscript = NULL; JSDContext* jsdc = (JSDContext*) callerdata; JS::RootedScript script(jsdc->dumbContext, script_); JSD_ScriptHookProc hook; void* hookData; JSD_ASSERT_VALID_CONTEXT(jsdc); if( JSD_IS_DANGEROUS_THREAD(jsdc) ) return; JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindJSDScript(jsdc, script); JSD_UNLOCK_SCRIPTS(jsdc); if( ! jsdscript ) return; #ifdef JSD_DUMP JSD_LOCK_SCRIPTS(jsdc); _dumpJSDScript(jsdc, jsdscript, "***DESTROY Script: "); JSD_UNLOCK_SCRIPTS(jsdc); #endif /* JSD_DUMP */ /* local in case hook gets cleared on another thread */ JSD_LOCK(); hook = (jsdscript->flags & JSD_SCRIPT_CALL_DESTROY_HOOK_BIT) ? jsdc->scriptHook : NULL; hookData = jsdc->scriptHookData; JSD_UNLOCK(); if( hook ) hook(jsdc, jsdscript, JS_FALSE, hookData); JSD_LOCK_SCRIPTS(jsdc); JS_HashTableRemove(jsdc->scriptsTable, (void *)script); JSD_UNLOCK_SCRIPTS(jsdc); #ifdef JSD_DUMP JSD_LOCK_SCRIPTS(jsdc); _dumpJSDScriptList(jsdc); JSD_UNLOCK_SCRIPTS(jsdc); #endif /* JSD_DUMP */ }
static void _interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp, JSBool before) { JSDScript* jsdscript = NULL; JSScript * script; static indent = 0; char* buf; const char* funName = NULL; script = JS_GetFrameScript(cx, fp); if(script) { JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindJSDScript(jsdc, script); JSD_UNLOCK_SCRIPTS(jsdc); if(jsdscript) funName = JSD_GetScriptFunctionName(jsdc, jsdscript); } if(!funName) funName = "TOP_LEVEL"; if(before) { buf = JS_smprintf("%sentering %s %s this: %0x\n", _indentSpaces(indent++), funName, JS_IsConstructorFrame(cx, fp) ? "constructing":"", (int)JS_GetFrameThis(cx, fp)); } else { buf = JS_smprintf("%sleaving %s\n", _indentSpaces(--indent), funName); } JS_ASSERT(indent >= 0); if(!buf) return; printf(buf); free(buf); }
JSDScript * jsd_FindOrCreateJSDScript(JSDContext *jsdc, JSContext *cx, JSScript *script, JSStackFrame *fp) { JSDScript *jsdscript; JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc)); jsdscript = jsd_FindJSDScript(jsdc, script); if (jsdscript) return jsdscript; /* Fallback for unknown scripts: create a new script. */ if (!fp) JS_BrokenFrameIterator(cx, &fp); if (fp) jsdscript = _newJSDScript(jsdc, cx, script); return jsdscript; }
static JSDStackFrameInfo* _addNewFrame(JSDContext* jsdc, JSDThreadState* jsdthreadstate, JSScript* script, jsuword pc, JSStackFrame* fp) { JSDStackFrameInfo* jsdframe; JSDScript* jsdscript = NULL; if (!JS_IsNativeFrame(jsdthreadstate->context, fp)) { JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindJSDScript(jsdc, script); JSD_UNLOCK_SCRIPTS(jsdc); if (!jsdscript || (jsdc->flags & JSD_HIDE_DISABLED_FRAMES && !JSD_IS_DEBUG_ENABLED(jsdc, jsdscript))) { return NULL; } if (!JSD_IS_DEBUG_ENABLED(jsdc, jsdscript)) jsdthreadstate->flags |= TS_HAS_DISABLED_FRAME; } jsdframe = (JSDStackFrameInfo*) calloc(1, sizeof(JSDStackFrameInfo)); if( ! jsdframe ) return NULL; jsdframe->jsdthreadstate = jsdthreadstate; jsdframe->jsdscript = jsdscript; jsdframe->pc = pc; jsdframe->fp = fp; JS_APPEND_LINK(&jsdframe->links, &jsdthreadstate->stack); jsdthreadstate->stackDepth++; return jsdframe; }
JSDScript* jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval) { JSContext* cx = jsdc->dumbContext; jsval val = jsdval->val; JSFunction* fun = NULL; JSExceptionState* exceptionState; JSScript* script = NULL; JSDScript* jsdscript; JSCrossCompartmentCall *call = NULL; if (!jsd_IsValueFunction(jsdc, jsdval)) return NULL; JS_BeginRequest(cx); call = JS_EnterCrossCompartmentCall(cx, JSVAL_TO_OBJECT(val)); if (!call) { JS_EndRequest(cx); return NULL; } exceptionState = JS_SaveExceptionState(cx); fun = JSD_GetValueFunction(jsdc, jsdval); JS_RestoreExceptionState(cx, exceptionState); if (fun) script = JS_GetFunctionScript(cx, fun); JS_LeaveCrossCompartmentCall(call); JS_EndRequest(cx); if (!script) return NULL; JSD_LOCK_SCRIPTS(jsdc); jsdscript = jsd_FindJSDScript(jsdc, script); JSD_UNLOCK_SCRIPTS(jsdc); return jsdscript; }
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 }