source: trunk/third/firefox/js/jsd/jsd_step.c @ 21695

Revision 21695, 7.7 KB checked in by rbasch, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21694, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Netscape Public License
6 * Version 1.1 (the "License"); you may not use this file except in
7 * compliance with the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/NPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the NPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the NPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38/*
39 * JavaScript Debugging support - Stepping support
40 */
41
42#include "jsd.h"
43
44/*
45* #define JSD_TRACE 1
46*/
47
48#ifdef JSD_TRACE
49
50static char*
51_indentSpaces(int i)
52{
53#define MAX_INDENT 63
54    static char* p = NULL;
55    if(!p)
56    {
57        p = calloc(1, MAX_INDENT+1);
58        if(!p) return "";
59        memset(p, ' ', MAX_INDENT);
60    }
61    if(i > MAX_INDENT) return p;
62    return p + MAX_INDENT-i;
63}
64
65static void
66_interpreterTrace(JSDContext* jsdc, JSContext *cx, JSStackFrame *fp,
67                  JSBool before)
68{
69    JSDScript* jsdscript = NULL;
70    JSScript * script;
71    static indent = 0;
72    char* buf;
73    const char* funName = NULL;
74
75    script = JS_GetFrameScript(cx, fp);
76    if(script)
77    {
78        JSD_LOCK_SCRIPTS(jsdc);
79        jsdscript = jsd_FindJSDScript(jsdc, script);
80        JSD_UNLOCK_SCRIPTS(jsdc);
81        if(jsdscript)
82            funName = JSD_GetScriptFunctionName(jsdc, jsdscript);
83    }
84    if(!funName)
85        funName = "TOP_LEVEL";
86
87    if(before)
88    {
89        buf = JS_smprintf("%sentering %s %s this: %0x\n",
90                _indentSpaces(indent++),
91                funName,
92                JS_IsConstructorFrame(cx, fp) ? "constructing":"",
93                (int)JS_GetFrameThis(cx, fp));
94    }
95    else
96    {
97        buf = JS_smprintf("%sleaving %s\n",
98                _indentSpaces(--indent),
99                funName);
100    }
101    JS_ASSERT(indent >= 0);
102
103    if(!buf)
104        return;
105
106    printf(buf);
107    free(buf);
108}
109#endif
110
111JSBool
112_callHook(JSDContext *jsdc, JSContext *cx, JSStackFrame *fp, JSBool before,
113          uintN type, JSD_CallHookProc hook, void *hookData)
114{
115    JSDScript*        jsdscript;
116    JSScript*         jsscript;
117    JSBool            hookresult = JS_TRUE;
118   
119    if (!jsdc || !jsdc->inited)
120        return JS_FALSE;
121
122    if (!hook && !(jsdc->flags & JSD_COLLECT_PROFILE_DATA) &&
123        jsdc->flags & JSD_DISABLE_OBJECT_TRACE)
124    {
125        /* no hook to call, no profile data needs to be collected, and
126         * the client has object tracing disabled, so there is nothing
127         * to do here.
128         */
129        return hookresult;
130    }
131   
132    if (before && JS_IsConstructorFrame(cx, fp))
133        jsd_Constructing(jsdc, cx, JS_GetFrameThis(cx, fp), fp);
134
135    jsscript = JS_GetFrameScript(cx, fp);
136    if (jsscript)
137    {
138        JSD_LOCK_SCRIPTS(jsdc);
139        jsdscript = jsd_FindJSDScript(jsdc, jsscript);
140        JSD_UNLOCK_SCRIPTS(jsdc);
141   
142        if (jsdscript)
143        {
144            if (JSD_IS_PROFILE_ENABLED(jsdc, jsdscript))
145            {
146                JSDProfileData *pdata;
147                pdata = jsd_GetScriptProfileData (jsdc, jsdscript);
148                if (pdata)
149                {
150                    if (before)
151                    {
152                        if (JSLL_IS_ZERO(pdata->lastCallStart))
153                        {
154                            pdata->lastCallStart = JS_Now();
155                        } else {
156                            if (++pdata->recurseDepth > pdata->maxRecurseDepth)
157                                pdata->maxRecurseDepth = pdata->recurseDepth;
158                        }   
159                        /* make sure we're called for the return too. */
160                        hookresult = JS_TRUE;
161                    } else if (!pdata->recurseDepth &&
162                               !JSLL_IS_ZERO(pdata->lastCallStart)) {
163                        int64 now, ll_delta;
164                        jsdouble delta;
165                        now = JS_Now();
166                        JSLL_SUB(ll_delta, now, pdata->lastCallStart);
167                        JSLL_L2D(delta, ll_delta);
168                        delta /= 1000.0;
169                        pdata->totalExecutionTime += delta;
170                        if (!pdata->minExecutionTime ||
171                            delta < pdata->minExecutionTime)
172                        {
173                            pdata->minExecutionTime = delta;
174                        }
175                        if (delta > pdata->maxExecutionTime)
176                            pdata->maxExecutionTime = delta;
177                        pdata->lastCallStart = JSLL_ZERO;
178                        ++pdata->callCount;
179                    } else if (pdata->recurseDepth) {
180                        --pdata->recurseDepth;
181                        ++pdata->callCount;
182                    }
183                }
184                if (hook)
185                    jsd_CallCallHook (jsdc, cx, type, hook, hookData);
186            } else {
187                if (hook)
188                    hookresult =
189                        jsd_CallCallHook (jsdc, cx, type, hook, hookData);
190                else
191                    hookresult = JS_TRUE;
192            }
193        }
194    }
195
196#ifdef JSD_TRACE
197    _interpreterTrace(jsdc, cx, fp, before);
198    return JS_TRUE;
199#else
200    return hookresult;
201#endif
202
203}
204
205void * JS_DLL_CALLBACK
206jsd_FunctionCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
207                     JSBool *ok, void *closure)
208{
209    JSDContext*       jsdc;
210    JSD_CallHookProc  hook;
211    void*             hookData;
212
213    jsdc = (JSDContext*) closure;
214   
215    /* local in case jsdc->functionHook gets cleared on another thread */
216    JSD_LOCK();
217    hook     = jsdc->functionHook;
218    hookData = jsdc->functionHookData;
219    JSD_UNLOCK();
220   
221    if (_callHook (jsdc, cx, fp, before,
222                   (before) ? JSD_HOOK_FUNCTION_CALL : JSD_HOOK_FUNCTION_RETURN,
223                   hook, hookData))
224    {
225        return closure;
226    }
227   
228    return NULL;
229}
230
231void * JS_DLL_CALLBACK
232jsd_TopLevelCallHook(JSContext *cx, JSStackFrame *fp, JSBool before,
233                     JSBool *ok, void *closure)
234{
235    JSDContext*       jsdc;
236    JSD_CallHookProc  hook;
237    void*             hookData;
238
239    jsdc = (JSDContext*) closure;
240
241    /* local in case jsdc->toplevelHook gets cleared on another thread */
242    JSD_LOCK();
243    hook     = jsdc->toplevelHook;
244    hookData = jsdc->toplevelHookData;
245    JSD_UNLOCK();
246   
247    if (_callHook (jsdc, cx, fp, before,
248                   (before) ? JSD_HOOK_TOPLEVEL_START : JSD_HOOK_TOPLEVEL_END,
249                   hook, hookData))
250    {
251        return closure;
252    }
253   
254    return NULL;
255   
256}
Note: See TracBrowser for help on using the repository browser.