PageRenderTime 50ms CodeModel.GetById 12ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/js/jsd/jsd_hook.c

http://github.com/zpao/v8monkey
C | 363 lines | 259 code | 55 blank | 49 comment | 28 complexity | 792b6045fa5d96ac3f002f839122e122 MD5 | raw file
  1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2/* ***** BEGIN LICENSE BLOCK *****
  3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4 *
  5 * The contents of this file are subject to the Mozilla Public License Version
  6 * 1.1 (the "License"); you may not use this file except in compliance with
  7 * the License. You may obtain a copy of the License at
  8 * http://www.mozilla.org/MPL/
  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 MPL, 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 MPL, the GPL or the LGPL.
 35 *
 36 * ***** END LICENSE BLOCK ***** */
 37
 38/*
 39 * JavaScript Debugging support - Hook support
 40 */
 41
 42#include "jsd.h"
 43
 44JSTrapStatus
 45jsd_InterruptHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
 46                     void *closure)
 47{
 48    JSDScript*      jsdscript;
 49    JSDContext*     jsdc = (JSDContext*) closure;
 50    JSD_ExecutionHookProc hook;
 51    void*                 hookData;
 52
 53    if( ! jsdc || ! jsdc->inited )
 54        return JSTRAP_CONTINUE;
 55
 56    if( JSD_IS_DANGEROUS_THREAD(jsdc) )
 57        return JSTRAP_CONTINUE;
 58
 59    /* local in case jsdc->interruptHook gets cleared on another thread */
 60    JSD_LOCK();
 61    hook     = jsdc->interruptHook;
 62    hookData = jsdc->interruptHookData;
 63    JSD_UNLOCK();
 64
 65    if (!hook)
 66        return JSTRAP_CONTINUE;
 67    
 68    JSD_LOCK_SCRIPTS(jsdc);
 69    jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
 70    JSD_UNLOCK_SCRIPTS(jsdc);
 71    if( ! jsdscript )
 72        return JSTRAP_CONTINUE;
 73
 74#ifdef LIVEWIRE
 75    if( ! jsdlw_UserCodeAtPC(jsdc, jsdscript, (uintptr_t)pc) )
 76        return JSTRAP_CONTINUE;
 77#endif
 78
 79    return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_INTERRUPTED,
 80                                 hook, hookData, rval);
 81}
 82
 83JSTrapStatus
 84jsd_DebuggerHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
 85                    jsval *rval, void *closure)
 86{
 87    JSDScript*      jsdscript;
 88    JSDContext*     jsdc = (JSDContext*) closure;
 89    JSD_ExecutionHookProc hook;
 90    void*                 hookData;
 91
 92    if( ! jsdc || ! jsdc->inited )
 93        return JSTRAP_CONTINUE;
 94
 95    if( JSD_IS_DANGEROUS_THREAD(jsdc) )
 96        return JSTRAP_CONTINUE;
 97
 98    /* local in case jsdc->debuggerHook gets cleared on another thread */
 99    JSD_LOCK();
100    hook     = jsdc->debuggerHook;
101    hookData = jsdc->debuggerHookData;
102    JSD_UNLOCK();
103    if(!hook)
104        return JSTRAP_CONTINUE;
105
106    JSD_LOCK_SCRIPTS(jsdc);
107    jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
108    JSD_UNLOCK_SCRIPTS(jsdc);
109    if( ! jsdscript )
110        return JSTRAP_CONTINUE;
111
112    return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_DEBUGGER_KEYWORD,
113                                 hook, hookData, rval);
114}
115
116
117JSTrapStatus
118jsd_ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
119                 jsval *rval, void *closure)
120{
121    JSDScript*      jsdscript;
122    JSDContext*     jsdc = (JSDContext*) closure;
123    JSD_ExecutionHookProc hook;
124    void*                 hookData;
125
126    if( ! jsdc || ! jsdc->inited )
127        return JSTRAP_CONTINUE;
128
129    if( JSD_IS_DANGEROUS_THREAD(jsdc) )
130        return JSTRAP_CONTINUE;
131
132    /* local in case jsdc->throwHook gets cleared on another thread */
133    JSD_LOCK();
134    hook     = jsdc->throwHook;
135    hookData = jsdc->throwHookData;
136    JSD_UNLOCK();
137    if (!hook)
138        return JSTRAP_CONTINUE;
139
140    JSD_LOCK_SCRIPTS(jsdc);
141    jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
142    JSD_UNLOCK_SCRIPTS(jsdc);
143    if( ! jsdscript )
144        return JSTRAP_CONTINUE;
145
146    JS_GetPendingException(cx, rval);
147
148    return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_THROW,
149                                 hook, hookData, rval);
150}
151
152JSTrapStatus
153jsd_CallExecutionHook(JSDContext* jsdc,
154                      JSContext *cx,
155                      uintN type,
156                      JSD_ExecutionHookProc hook,
157                      void* hookData,
158                      jsval* rval)
159{
160    uintN hookanswer = JSD_HOOK_THROW == type ? 
161                            JSD_HOOK_RETURN_CONTINUE_THROW :
162                            JSD_HOOK_RETURN_CONTINUE;
163    JSDThreadState* jsdthreadstate;
164
165    if(hook && NULL != (jsdthreadstate = jsd_NewThreadState(jsdc,cx)))
166    {
167        if ((type != JSD_HOOK_THROW && type != JSD_HOOK_INTERRUPTED) ||
168            jsdc->flags & JSD_MASK_TOP_FRAME_ONLY ||
169            !(jsdthreadstate->flags & TS_HAS_DISABLED_FRAME))
170        {
171            /*
172             * if it's not a throw and it's not an interrupt,
173             * or we're only masking the top frame,
174             * or there are no disabled frames in this stack,
175             * then call out.
176             */
177             hookanswer = hook(jsdc, jsdthreadstate, type, hookData, rval);
178             jsd_DestroyThreadState(jsdc, jsdthreadstate);
179        }
180    }
181
182    switch(hookanswer)
183    {
184        case JSD_HOOK_RETURN_ABORT:
185        case JSD_HOOK_RETURN_HOOK_ERROR:
186            return JSTRAP_ERROR;
187        case JSD_HOOK_RETURN_RET_WITH_VAL:
188            return JSTRAP_RETURN;
189        case JSD_HOOK_RETURN_THROW_WITH_VAL:
190            return JSTRAP_THROW;
191        case JSD_HOOK_RETURN_CONTINUE:
192            break;
193        case JSD_HOOK_RETURN_CONTINUE_THROW:
194            /* only makes sense for jsd_ThrowHandler (which init'd rval) */
195            JS_ASSERT(JSD_HOOK_THROW == type);
196            return JSTRAP_THROW;
197        default:
198            JS_ASSERT(0);
199            break;
200    }
201    return JSTRAP_CONTINUE;
202}
203
204JSBool
205jsd_CallCallHook (JSDContext* jsdc,
206                  JSContext *cx,
207                  uintN type,
208                  JSD_CallHookProc hook,
209                  void* hookData)
210{
211    JSBool hookanswer;
212    JSDThreadState*  jsdthreadstate;
213    
214    hookanswer = JS_FALSE;
215    if(hook && NULL != (jsdthreadstate = jsd_NewThreadState(jsdc, cx)))
216    {
217        hookanswer = hook(jsdc, jsdthreadstate, type, hookData);
218        jsd_DestroyThreadState(jsdc, jsdthreadstate);
219    }
220
221    return hookanswer;
222}
223
224JSBool
225jsd_SetInterruptHook(JSDContext*           jsdc,
226                     JSD_ExecutionHookProc hook,
227                     void*                 callerdata)
228{
229    JSD_LOCK();
230    jsdc->interruptHookData  = callerdata;
231    jsdc->interruptHook      = hook;
232    JS_SetInterrupt(jsdc->jsrt, jsd_InterruptHandler, (void*) jsdc);
233    JSD_UNLOCK();
234
235    return JS_TRUE;
236}
237
238JSBool
239jsd_ClearInterruptHook(JSDContext* jsdc)
240{
241    JSD_LOCK();
242    JS_ClearInterrupt(jsdc->jsrt, NULL, NULL );
243    jsdc->interruptHook      = NULL;
244    JSD_UNLOCK();
245
246    return JS_TRUE;
247}
248
249JSBool
250jsd_SetDebugBreakHook(JSDContext*           jsdc,
251                      JSD_ExecutionHookProc hook,
252                      void*                 callerdata)
253{
254    JSD_LOCK();
255    jsdc->debugBreakHookData  = callerdata;
256    jsdc->debugBreakHook      = hook;
257    JSD_UNLOCK();
258
259    return JS_TRUE;
260}
261
262JSBool
263jsd_ClearDebugBreakHook(JSDContext* jsdc)
264{
265    JSD_LOCK();
266    jsdc->debugBreakHook      = NULL;
267    JSD_UNLOCK();
268
269    return JS_TRUE;
270}
271
272JSBool
273jsd_SetDebuggerHook(JSDContext*           jsdc,
274                      JSD_ExecutionHookProc hook,
275                      void*                 callerdata)
276{
277    JSD_LOCK();
278    jsdc->debuggerHookData  = callerdata;
279    jsdc->debuggerHook      = hook;
280    JSD_UNLOCK();
281
282    return JS_TRUE;
283}
284
285JSBool
286jsd_ClearDebuggerHook(JSDContext* jsdc)
287{
288    JSD_LOCK();
289    jsdc->debuggerHook      = NULL;
290    JSD_UNLOCK();
291
292    return JS_TRUE;
293}
294
295JSBool
296jsd_SetThrowHook(JSDContext*           jsdc,
297                 JSD_ExecutionHookProc hook,
298                 void*                 callerdata)
299{
300    JSD_LOCK();
301    jsdc->throwHookData  = callerdata;
302    jsdc->throwHook      = hook;
303    JSD_UNLOCK();
304
305    return JS_TRUE;
306}
307
308JSBool
309jsd_ClearThrowHook(JSDContext* jsdc)
310{
311    JSD_LOCK();
312    jsdc->throwHook      = NULL;
313    JSD_UNLOCK();
314
315    return JS_TRUE;
316}
317
318JSBool
319jsd_SetFunctionHook(JSDContext*      jsdc,
320                    JSD_CallHookProc hook,
321                    void*            callerdata)
322{
323    JSD_LOCK();
324    jsdc->functionHookData  = callerdata;
325    jsdc->functionHook      = hook;
326    JSD_UNLOCK();
327
328    return JS_TRUE;
329}
330
331JSBool
332jsd_ClearFunctionHook(JSDContext* jsdc)
333{
334    JSD_LOCK();
335    jsdc->functionHook      = NULL;
336    JSD_UNLOCK();
337
338    return JS_TRUE;
339}
340
341JSBool
342jsd_SetTopLevelHook(JSDContext*      jsdc,
343                    JSD_CallHookProc hook,
344                    void*            callerdata)
345{
346    JSD_LOCK();
347    jsdc->toplevelHookData  = callerdata;
348    jsdc->toplevelHook      = hook;
349    JSD_UNLOCK();
350
351    return JS_TRUE;
352}
353
354JSBool
355jsd_ClearTopLevelHook(JSDContext* jsdc)
356{
357    JSD_LOCK();
358    jsdc->toplevelHook      = NULL;
359    JSD_UNLOCK();
360
361    return JS_TRUE;
362}
363