Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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 */
}                
Пример #6
0
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);
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
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

}