/js/jsd/jsd_hook.c

http://github.com/zpao/v8monkey · C · 363 lines · 259 code · 55 blank · 49 comment · 29 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. * JavaScript Debugging support - Hook support
  39. */
  40. #include "jsd.h"
  41. JSTrapStatus
  42. jsd_InterruptHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
  43. void *closure)
  44. {
  45. JSDScript* jsdscript;
  46. JSDContext* jsdc = (JSDContext*) closure;
  47. JSD_ExecutionHookProc hook;
  48. void* hookData;
  49. if( ! jsdc || ! jsdc->inited )
  50. return JSTRAP_CONTINUE;
  51. if( JSD_IS_DANGEROUS_THREAD(jsdc) )
  52. return JSTRAP_CONTINUE;
  53. /* local in case jsdc->interruptHook gets cleared on another thread */
  54. JSD_LOCK();
  55. hook = jsdc->interruptHook;
  56. hookData = jsdc->interruptHookData;
  57. JSD_UNLOCK();
  58. if (!hook)
  59. return JSTRAP_CONTINUE;
  60. JSD_LOCK_SCRIPTS(jsdc);
  61. jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
  62. JSD_UNLOCK_SCRIPTS(jsdc);
  63. if( ! jsdscript )
  64. return JSTRAP_CONTINUE;
  65. #ifdef LIVEWIRE
  66. if( ! jsdlw_UserCodeAtPC(jsdc, jsdscript, (uintptr_t)pc) )
  67. return JSTRAP_CONTINUE;
  68. #endif
  69. return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_INTERRUPTED,
  70. hook, hookData, rval);
  71. }
  72. JSTrapStatus
  73. jsd_DebuggerHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
  74. jsval *rval, void *closure)
  75. {
  76. JSDScript* jsdscript;
  77. JSDContext* jsdc = (JSDContext*) closure;
  78. JSD_ExecutionHookProc hook;
  79. void* hookData;
  80. if( ! jsdc || ! jsdc->inited )
  81. return JSTRAP_CONTINUE;
  82. if( JSD_IS_DANGEROUS_THREAD(jsdc) )
  83. return JSTRAP_CONTINUE;
  84. /* local in case jsdc->debuggerHook gets cleared on another thread */
  85. JSD_LOCK();
  86. hook = jsdc->debuggerHook;
  87. hookData = jsdc->debuggerHookData;
  88. JSD_UNLOCK();
  89. if(!hook)
  90. return JSTRAP_CONTINUE;
  91. JSD_LOCK_SCRIPTS(jsdc);
  92. jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
  93. JSD_UNLOCK_SCRIPTS(jsdc);
  94. if( ! jsdscript )
  95. return JSTRAP_CONTINUE;
  96. return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_DEBUGGER_KEYWORD,
  97. hook, hookData, rval);
  98. }
  99. JSTrapStatus
  100. jsd_ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
  101. jsval *rval, void *closure)
  102. {
  103. JSDScript* jsdscript;
  104. JSDContext* jsdc = (JSDContext*) closure;
  105. JSD_ExecutionHookProc hook;
  106. void* hookData;
  107. if( ! jsdc || ! jsdc->inited )
  108. return JSTRAP_CONTINUE;
  109. if( JSD_IS_DANGEROUS_THREAD(jsdc) )
  110. return JSTRAP_CONTINUE;
  111. /* local in case jsdc->throwHook gets cleared on another thread */
  112. JSD_LOCK();
  113. hook = jsdc->throwHook;
  114. hookData = jsdc->throwHookData;
  115. JSD_UNLOCK();
  116. if (!hook)
  117. return JSTRAP_CONTINUE;
  118. JSD_LOCK_SCRIPTS(jsdc);
  119. jsdscript = jsd_FindOrCreateJSDScript(jsdc, cx, script, NULL);
  120. JSD_UNLOCK_SCRIPTS(jsdc);
  121. if( ! jsdscript )
  122. return JSTRAP_CONTINUE;
  123. JS_GetPendingException(cx, rval);
  124. return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_THROW,
  125. hook, hookData, rval);
  126. }
  127. JSTrapStatus
  128. jsd_CallExecutionHook(JSDContext* jsdc,
  129. JSContext *cx,
  130. uintN type,
  131. JSD_ExecutionHookProc hook,
  132. void* hookData,
  133. jsval* rval)
  134. {
  135. uintN hookanswer = JSD_HOOK_THROW == type ?
  136. JSD_HOOK_RETURN_CONTINUE_THROW :
  137. JSD_HOOK_RETURN_CONTINUE;
  138. JSDThreadState* jsdthreadstate;
  139. if(hook && NULL != (jsdthreadstate = jsd_NewThreadState(jsdc,cx)))
  140. {
  141. if ((type != JSD_HOOK_THROW && type != JSD_HOOK_INTERRUPTED) ||
  142. jsdc->flags & JSD_MASK_TOP_FRAME_ONLY ||
  143. !(jsdthreadstate->flags & TS_HAS_DISABLED_FRAME))
  144. {
  145. /*
  146. * if it's not a throw and it's not an interrupt,
  147. * or we're only masking the top frame,
  148. * or there are no disabled frames in this stack,
  149. * then call out.
  150. */
  151. hookanswer = hook(jsdc, jsdthreadstate, type, hookData, rval);
  152. jsd_DestroyThreadState(jsdc, jsdthreadstate);
  153. }
  154. }
  155. switch(hookanswer)
  156. {
  157. case JSD_HOOK_RETURN_ABORT:
  158. case JSD_HOOK_RETURN_HOOK_ERROR:
  159. return JSTRAP_ERROR;
  160. case JSD_HOOK_RETURN_RET_WITH_VAL:
  161. return JSTRAP_RETURN;
  162. case JSD_HOOK_RETURN_THROW_WITH_VAL:
  163. return JSTRAP_THROW;
  164. case JSD_HOOK_RETURN_CONTINUE:
  165. break;
  166. case JSD_HOOK_RETURN_CONTINUE_THROW:
  167. /* only makes sense for jsd_ThrowHandler (which init'd rval) */
  168. JS_ASSERT(JSD_HOOK_THROW == type);
  169. return JSTRAP_THROW;
  170. default:
  171. JS_ASSERT(0);
  172. break;
  173. }
  174. return JSTRAP_CONTINUE;
  175. }
  176. JSBool
  177. jsd_CallCallHook (JSDContext* jsdc,
  178. JSContext *cx,
  179. uintN type,
  180. JSD_CallHookProc hook,
  181. void* hookData)
  182. {
  183. JSBool hookanswer;
  184. JSDThreadState* jsdthreadstate;
  185. hookanswer = JS_FALSE;
  186. if(hook && NULL != (jsdthreadstate = jsd_NewThreadState(jsdc, cx)))
  187. {
  188. hookanswer = hook(jsdc, jsdthreadstate, type, hookData);
  189. jsd_DestroyThreadState(jsdc, jsdthreadstate);
  190. }
  191. return hookanswer;
  192. }
  193. JSBool
  194. jsd_SetInterruptHook(JSDContext* jsdc,
  195. JSD_ExecutionHookProc hook,
  196. void* callerdata)
  197. {
  198. JSD_LOCK();
  199. jsdc->interruptHookData = callerdata;
  200. jsdc->interruptHook = hook;
  201. JS_SetInterrupt(jsdc->jsrt, jsd_InterruptHandler, (void*) jsdc);
  202. JSD_UNLOCK();
  203. return JS_TRUE;
  204. }
  205. JSBool
  206. jsd_ClearInterruptHook(JSDContext* jsdc)
  207. {
  208. JSD_LOCK();
  209. JS_ClearInterrupt(jsdc->jsrt, NULL, NULL );
  210. jsdc->interruptHook = NULL;
  211. JSD_UNLOCK();
  212. return JS_TRUE;
  213. }
  214. JSBool
  215. jsd_SetDebugBreakHook(JSDContext* jsdc,
  216. JSD_ExecutionHookProc hook,
  217. void* callerdata)
  218. {
  219. JSD_LOCK();
  220. jsdc->debugBreakHookData = callerdata;
  221. jsdc->debugBreakHook = hook;
  222. JSD_UNLOCK();
  223. return JS_TRUE;
  224. }
  225. JSBool
  226. jsd_ClearDebugBreakHook(JSDContext* jsdc)
  227. {
  228. JSD_LOCK();
  229. jsdc->debugBreakHook = NULL;
  230. JSD_UNLOCK();
  231. return JS_TRUE;
  232. }
  233. JSBool
  234. jsd_SetDebuggerHook(JSDContext* jsdc,
  235. JSD_ExecutionHookProc hook,
  236. void* callerdata)
  237. {
  238. JSD_LOCK();
  239. jsdc->debuggerHookData = callerdata;
  240. jsdc->debuggerHook = hook;
  241. JSD_UNLOCK();
  242. return JS_TRUE;
  243. }
  244. JSBool
  245. jsd_ClearDebuggerHook(JSDContext* jsdc)
  246. {
  247. JSD_LOCK();
  248. jsdc->debuggerHook = NULL;
  249. JSD_UNLOCK();
  250. return JS_TRUE;
  251. }
  252. JSBool
  253. jsd_SetThrowHook(JSDContext* jsdc,
  254. JSD_ExecutionHookProc hook,
  255. void* callerdata)
  256. {
  257. JSD_LOCK();
  258. jsdc->throwHookData = callerdata;
  259. jsdc->throwHook = hook;
  260. JSD_UNLOCK();
  261. return JS_TRUE;
  262. }
  263. JSBool
  264. jsd_ClearThrowHook(JSDContext* jsdc)
  265. {
  266. JSD_LOCK();
  267. jsdc->throwHook = NULL;
  268. JSD_UNLOCK();
  269. return JS_TRUE;
  270. }
  271. JSBool
  272. jsd_SetFunctionHook(JSDContext* jsdc,
  273. JSD_CallHookProc hook,
  274. void* callerdata)
  275. {
  276. JSD_LOCK();
  277. jsdc->functionHookData = callerdata;
  278. jsdc->functionHook = hook;
  279. JSD_UNLOCK();
  280. return JS_TRUE;
  281. }
  282. JSBool
  283. jsd_ClearFunctionHook(JSDContext* jsdc)
  284. {
  285. JSD_LOCK();
  286. jsdc->functionHook = NULL;
  287. JSD_UNLOCK();
  288. return JS_TRUE;
  289. }
  290. JSBool
  291. jsd_SetTopLevelHook(JSDContext* jsdc,
  292. JSD_CallHookProc hook,
  293. void* callerdata)
  294. {
  295. JSD_LOCK();
  296. jsdc->toplevelHookData = callerdata;
  297. jsdc->toplevelHook = hook;
  298. JSD_UNLOCK();
  299. return JS_TRUE;
  300. }
  301. JSBool
  302. jsd_ClearTopLevelHook(JSDContext* jsdc)
  303. {
  304. JSD_LOCK();
  305. jsdc->toplevelHook = NULL;
  306. JSD_UNLOCK();
  307. return JS_TRUE;
  308. }