1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=78:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is Mozilla Communicator client code, released
20 * The Initial Developer of the Original Code is
21 * Netscape Communications Corporation.
22 * Portions created by the Initial Developer are Copyright (C) 1998
23 * the Initial Developer. All Rights Reserved.
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
47 #include "jsutil.h" /* Added by JSIFY */
51 #include "jsversion.h"
65 #include "jsautooplen.h"
67 typedef struct JSTrap
{
72 JSTrapHandler handler
;
76 #define DBG_LOCK(rt) JS_ACQUIRE_LOCK((rt)->debuggerLock)
77 #define DBG_UNLOCK(rt) JS_RELEASE_LOCK((rt)->debuggerLock)
78 #define DBG_LOCK_EVAL(rt,expr) (DBG_LOCK(rt), (expr), DBG_UNLOCK(rt))
81 * NB: FindTrap must be called with rt->debuggerLock acquired.
84 FindTrap(JSRuntime
*rt
, JSScript
*script
, jsbytecode
*pc
)
88 for (trap
= (JSTrap
*)rt
->trapList
.next
;
89 &trap
->links
!= &rt
->trapList
;
90 trap
= (JSTrap
*)trap
->links
.next
) {
91 if (trap
->script
== script
&& trap
->pc
== pc
)
98 js_UntrapScriptCode(JSContext
*cx
, JSScript
*script
)
107 for (trap
= (JSTrap
*)rt
->trapList
.next
;
110 trap
= (JSTrap
*)trap
->links
.next
) {
111 if (trap
->script
== script
&&
112 (size_t)(trap
->pc
- script
->code
) < script
->length
) {
113 if (code
== script
->code
) {
114 jssrcnote
*sn
, *notes
;
117 nbytes
= script
->length
* sizeof(jsbytecode
);
118 notes
= SCRIPT_NOTES(script
);
119 for (sn
= notes
; !SN_IS_TERMINATOR(sn
); sn
= SN_NEXT(sn
))
121 nbytes
+= (sn
- notes
+ 1) * sizeof *sn
;
123 code
= (jsbytecode
*) JS_malloc(cx
, nbytes
);
126 memcpy(code
, script
->code
, nbytes
);
127 JS_CLEAR_GSN_CACHE(cx
);
129 code
[trap
->pc
- script
->code
] = trap
->op
;
136 JS_PUBLIC_API(JSBool
)
137 JS_SetTrap(JSContext
*cx
, JSScript
*script
, jsbytecode
*pc
,
138 JSTrapHandler handler
, void *closure
)
140 JSTrap
*junk
, *trap
, *twin
;
144 JS_ASSERT((JSOp
) *pc
!= JSOP_TRAP
);
148 trap
= FindTrap(rt
, script
, pc
);
150 JS_ASSERT(trap
->script
== script
&& trap
->pc
== pc
);
151 JS_ASSERT(*pc
== JSOP_TRAP
);
153 sample
= rt
->debuggerMutations
;
155 trap
= (JSTrap
*) JS_malloc(cx
, sizeof *trap
);
158 trap
->closure
= NULL
;
159 if(!js_AddRoot(cx
, &trap
->closure
, "trap->closure")) {
164 twin
= (rt
->debuggerMutations
!= sample
)
165 ? FindTrap(rt
, script
, pc
)
171 JS_APPEND_LINK(&trap
->links
, &rt
->trapList
);
172 ++rt
->debuggerMutations
;
173 trap
->script
= script
;
175 trap
->op
= (JSOp
)*pc
;
179 trap
->handler
= handler
;
180 trap
->closure
= closure
;
183 js_RemoveRoot(rt
, &junk
->closure
);
190 JS_GetTrapOpcode(JSContext
*cx
, JSScript
*script
, jsbytecode
*pc
)
198 trap
= FindTrap(rt
, script
, pc
);
199 op
= trap
? trap
->op
: (JSOp
) *pc
;
205 DestroyTrapAndUnlock(JSContext
*cx
, JSTrap
*trap
)
207 ++cx
->runtime
->debuggerMutations
;
208 JS_REMOVE_LINK(&trap
->links
);
209 *trap
->pc
= (jsbytecode
)trap
->op
;
210 DBG_UNLOCK(cx
->runtime
);
212 js_RemoveRoot(cx
->runtime
, &trap
->closure
);
217 JS_ClearTrap(JSContext
*cx
, JSScript
*script
, jsbytecode
*pc
,
218 JSTrapHandler
*handlerp
, void **closurep
)
222 DBG_LOCK(cx
->runtime
);
223 trap
= FindTrap(cx
->runtime
, script
, pc
);
225 *handlerp
= trap
? trap
->handler
: NULL
;
227 *closurep
= trap
? trap
->closure
: NULL
;
229 DestroyTrapAndUnlock(cx
, trap
);
231 DBG_UNLOCK(cx
->runtime
);
235 JS_ClearScriptTraps(JSContext
*cx
, JSScript
*script
)
243 for (trap
= (JSTrap
*)rt
->trapList
.next
;
244 &trap
->links
!= &rt
->trapList
;
246 next
= (JSTrap
*)trap
->links
.next
;
247 if (trap
->script
== script
) {
248 sample
= rt
->debuggerMutations
;
249 DestroyTrapAndUnlock(cx
, trap
);
251 if (rt
->debuggerMutations
!= sample
+ 1)
252 next
= (JSTrap
*)rt
->trapList
.next
;
259 JS_ClearAllTraps(JSContext
*cx
)
267 for (trap
= (JSTrap
*)rt
->trapList
.next
;
268 &trap
->links
!= &rt
->trapList
;
270 next
= (JSTrap
*)trap
->links
.next
;
271 sample
= rt
->debuggerMutations
;
272 DestroyTrapAndUnlock(cx
, trap
);
274 if (rt
->debuggerMutations
!= sample
+ 1)
275 next
= (JSTrap
*)rt
->trapList
.next
;
280 JS_PUBLIC_API(JSTrapStatus
)
281 JS_HandleTrap(JSContext
*cx
, JSScript
*script
, jsbytecode
*pc
, jsval
*rval
)
287 DBG_LOCK(cx
->runtime
);
288 trap
= FindTrap(cx
->runtime
, script
, pc
);
289 JS_ASSERT(!trap
|| trap
->handler
);
292 DBG_UNLOCK(cx
->runtime
);
294 /* Defend against "pc for wrong script" API usage error. */
295 JS_ASSERT(op
!= JSOP_TRAP
);
298 /* If the API was abused, we must fail for want of the real op. */
302 /* Assume a race with a debugger thread and try to carry on. */
303 *rval
= INT_TO_JSVAL(op
);
304 return JSTRAP_CONTINUE
;
306 /* Always fail if single-threaded (must be an API usage error). */
310 DBG_UNLOCK(cx
->runtime
);
313 * It's important that we not use 'trap->' after calling the callback --
314 * the callback might remove the trap!
316 op
= (jsint
)trap
->op
;
317 status
= trap
->handler(cx
, script
, pc
, rval
, trap
->closure
);
318 if (status
== JSTRAP_CONTINUE
) {
319 /* By convention, return the true op to the interpreter in rval. */
320 *rval
= INT_TO_JSVAL(op
);
325 JS_PUBLIC_API(JSBool
)
326 JS_SetInterrupt(JSRuntime
*rt
, JSTrapHandler handler
, void *closure
)
328 rt
->globalDebugHooks
.interruptHandler
= handler
;
329 rt
->globalDebugHooks
.interruptHandlerData
= closure
;
333 JS_PUBLIC_API(JSBool
)
334 JS_ClearInterrupt(JSRuntime
*rt
, JSTrapHandler
*handlerp
, void **closurep
)
337 *handlerp
= (JSTrapHandler
)rt
->globalDebugHooks
.interruptHandler
;
339 *closurep
= rt
->globalDebugHooks
.interruptHandlerData
;
340 rt
->globalDebugHooks
.interruptHandler
= 0;
341 rt
->globalDebugHooks
.interruptHandlerData
= 0;
345 /************************************************************************/
347 typedef struct JSWatchPoint
{
349 JSObject
*object
; /* weak link, see js_FinalizeObject */
350 JSScopeProperty
*sprop
;
352 JSWatchPointHandler handler
;
357 #define JSWP_LIVE 0x1 /* live because set and not cleared */
358 #define JSWP_HELD 0x2 /* held while running handler/setter */
361 * NB: DropWatchPointAndUnlock releases cx->runtime->debuggerLock in all cases.
364 DropWatchPointAndUnlock(JSContext
*cx
, JSWatchPoint
*wp
, uintN flag
)
367 JSScopeProperty
*sprop
;
373 if (wp
->flags
!= 0) {
374 DBG_UNLOCK(cx
->runtime
);
379 * Remove wp from the list, then if there are no other watchpoints for
380 * wp->sprop in any scope, restore wp->sprop->setter from wp.
382 ++cx
->runtime
->debuggerMutations
;
383 JS_REMOVE_LINK(&wp
->links
);
387 * Passing null for the scope parameter tells js_GetWatchedSetter to find
388 * any watch point for sprop, and not to lock or unlock rt->debuggerLock.
389 * If js_ChangeNativePropertyAttrs fails, propagate failure after removing
390 * wp->closure's root and freeing wp.
392 setter
= js_GetWatchedSetter(cx
->runtime
, NULL
, sprop
);
393 DBG_UNLOCK(cx
->runtime
);
395 JS_LOCK_OBJ(cx
, wp
->object
);
396 scope
= OBJ_SCOPE(wp
->object
);
397 found
= (scope
->object
== wp
->object
&&
398 SCOPE_GET_PROPERTY(scope
, sprop
->id
));
399 JS_UNLOCK_SCOPE(cx
, scope
);
402 * If the property wasn't found on wp->object or didn't exist, then
403 * someone else has dealt with this sprop, and we don't need to change
404 * the property attributes.
407 sprop
= js_ChangeScopePropertyAttrs(cx
, scope
, sprop
,
421 * NB: js_TraceWatchPoints does not acquire cx->runtime->debuggerLock, since
422 * the debugger should never be racing with the GC (i.e., the debugger must
423 * respect the request model).
426 js_TraceWatchPoints(JSTracer
*trc
, JSObject
*obj
)
431 rt
= trc
->context
->runtime
;
433 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
434 &wp
->links
!= &rt
->watchPointList
;
435 wp
= (JSWatchPoint
*)wp
->links
.next
) {
436 if (wp
->object
== obj
) {
437 TRACE_SCOPE_PROPERTY(trc
, wp
->sprop
);
438 if ((wp
->sprop
->attrs
& JSPROP_SETTER
) && wp
->setter
) {
439 JS_CALL_OBJECT_TRACER(trc
, (JSObject
*)wp
->setter
,
442 JS_SET_TRACING_NAME(trc
, "wp->closure");
443 js_CallValueTracerIfGCThing(trc
, (jsval
) wp
->closure
);
449 js_SweepWatchPoints(JSContext
*cx
)
452 JSWatchPoint
*wp
, *next
;
457 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
458 &wp
->links
!= &rt
->watchPointList
;
460 next
= (JSWatchPoint
*)wp
->links
.next
;
461 if (js_IsAboutToBeFinalized(cx
, wp
->object
)) {
462 sample
= rt
->debuggerMutations
;
464 /* Ignore failures. */
465 DropWatchPointAndUnlock(cx
, wp
, JSWP_LIVE
);
467 if (rt
->debuggerMutations
!= sample
+ 1)
468 next
= (JSWatchPoint
*)rt
->watchPointList
.next
;
477 * NB: FindWatchPoint must be called with rt->debuggerLock acquired.
479 static JSWatchPoint
*
480 FindWatchPoint(JSRuntime
*rt
, JSScope
*scope
, jsid id
)
484 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
485 &wp
->links
!= &rt
->watchPointList
;
486 wp
= (JSWatchPoint
*)wp
->links
.next
) {
487 if (wp
->object
== scope
->object
&& wp
->sprop
->id
== id
)
494 js_FindWatchPoint(JSRuntime
*rt
, JSScope
*scope
, jsid id
)
497 JSScopeProperty
*sprop
;
500 wp
= FindWatchPoint(rt
, scope
, id
);
501 sprop
= wp
? wp
->sprop
: NULL
;
507 * Secret handshake with DropWatchPointAndUnlock: if (!scope), we know our
508 * caller has acquired rt->debuggerLock, so we don't have to.
511 js_GetWatchedSetter(JSRuntime
*rt
, JSScope
*scope
,
512 const JSScopeProperty
*sprop
)
520 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
521 &wp
->links
!= &rt
->watchPointList
;
522 wp
= (JSWatchPoint
*)wp
->links
.next
) {
523 if ((!scope
|| wp
->object
== scope
->object
) && wp
->sprop
== sprop
) {
534 js_watch_set(JSContext
*cx
, JSObject
*obj
, jsval id
, jsval
*vp
)
538 JSScopeProperty
*sprop
;
539 jsval propid
, userid
;
545 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
546 &wp
->links
!= &rt
->watchPointList
;
547 wp
= (JSWatchPoint
*)wp
->links
.next
) {
549 if (wp
->object
== obj
&& SPROP_USERID(sprop
) == id
&&
550 !(wp
->flags
& JSWP_HELD
)) {
551 wp
->flags
|= JSWP_HELD
;
554 JS_LOCK_OBJ(cx
, obj
);
555 propid
= ID_TO_VALUE(sprop
->id
);
556 userid
= (sprop
->flags
& SPROP_HAS_SHORTID
)
557 ? INT_TO_JSVAL(sprop
->shortid
)
559 scope
= OBJ_SCOPE(obj
);
560 JS_UNLOCK_OBJ(cx
, obj
);
562 /* NB: wp is held, so we can safely dereference it still. */
563 ok
= wp
->handler(cx
, obj
, propid
,
564 SPROP_HAS_VALID_SLOT(sprop
, scope
)
565 ? OBJ_GET_SLOT(cx
, obj
, sprop
->slot
)
570 * Create a pseudo-frame for the setter invocation so that any
571 * stack-walking security code under the setter will correctly
572 * identify the guilty party. So that the watcher appears to
573 * be active to obj_eval and other such code, point frame.pc
574 * at the JSOP_STOP at the end of the script.
576 * The pseudo-frame is not created for fast natives as they
577 * are treated as interpreter frame extensions and always
591 closure
= (JSObject
*) wp
->closure
;
592 clasp
= OBJ_GET_CLASS(cx
, closure
);
593 if (clasp
== &js_FunctionClass
) {
594 fun
= GET_FUNCTION_PRIVATE(cx
, closure
);
595 script
= FUN_SCRIPT(fun
);
596 } else if (clasp
== &js_ScriptClass
) {
598 script
= (JSScript
*) JS_GetPrivate(cx
, closure
);
605 injectFrame
= JS_TRUE
;
607 nslots
+= FUN_MINARGS(fun
);
608 if (!FUN_INTERPRETED(fun
)) {
609 nslots
+= fun
->u
.n
.extra
;
610 injectFrame
= !(fun
->flags
& JSFUN_FAST_NATIVE
);
615 if (nslots
<= JS_ARRAY_LENGTH(smallv
)) {
618 argv
= (jsval
*) JS_malloc(cx
, nslots
* sizeof(jsval
));
621 DropWatchPointAndUnlock(cx
, wp
, JSWP_HELD
);
626 argv
[0] = OBJECT_TO_JSVAL(closure
);
627 argv
[1] = JSVAL_NULL
;
628 memset(argv
+ 2, 0, (nslots
- 2) * sizeof(jsval
));
630 memset(&frame
, 0, sizeof(frame
));
631 frame
.script
= script
;
634 JS_ASSERT(script
->length
>= JSOP_STOP_LENGTH
);
635 regs
.pc
= script
->code
+ script
->length
640 frame
.callee
= closure
;
642 frame
.argv
= argv
+ 2;
643 frame
.down
= js_GetTopStackFrame(cx
);
644 frame
.scopeChain
= OBJ_GET_PARENT(cx
, closure
);
650 argv
= NULL
; /* suppress bogus gcc warnings */
653 ((sprop
->attrs
& JSPROP_SETTER
)
654 ? js_InternalCall(cx
, obj
, OBJECT_TO_JSVAL(wp
->setter
),
656 : wp
->setter(cx
, OBJ_THIS_OBJECT(cx
, obj
), userid
, vp
));
658 /* Evil code can cause us to have an arguments object. */
660 ok
&= js_PutCallObject(cx
, &frame
);
662 ok
&= js_PutArgsObject(cx
, &frame
);
670 return DropWatchPointAndUnlock(cx
, wp
, JSWP_HELD
) && ok
;
678 js_watch_set_wrapper(JSContext
*cx
, JSObject
*obj
, uintN argc
, jsval
*argv
,
685 funobj
= JSVAL_TO_OBJECT(argv
[-2]);
686 JS_ASSERT(OBJ_GET_CLASS(cx
, funobj
) == &js_FunctionClass
);
687 wrapper
= GET_FUNCTION_PRIVATE(cx
, funobj
);
688 userid
= ATOM_KEY(wrapper
->atom
);
690 return js_watch_set(cx
, obj
, userid
, rval
);
694 js_WrapWatchedSetter(JSContext
*cx
, jsid id
, uintN attrs
, JSPropertyOp setter
)
699 if (!(attrs
& JSPROP_SETTER
))
700 return &js_watch_set
; /* & to silence schoolmarmish MSVC */
702 if (JSID_IS_ATOM(id
)) {
703 atom
= JSID_TO_ATOM(id
);
704 } else if (JSID_IS_INT(id
)) {
705 if (!js_ValueToStringId(cx
, INT_JSID_TO_JSVAL(id
), &id
))
707 atom
= JSID_TO_ATOM(id
);
711 wrapper
= js_NewFunction(cx
, NULL
, js_watch_set_wrapper
, 1, 0,
712 OBJ_GET_PARENT(cx
, (JSObject
*)setter
),
716 return (JSPropertyOp
) FUN_OBJECT(wrapper
);
719 JS_PUBLIC_API(JSBool
)
720 JS_SetWatchPoint(JSContext
*cx
, JSObject
*obj
, jsval idval
,
721 JSWatchPointHandler handler
, void *closure
)
726 JSScopeProperty
*sprop
;
730 JSPropertyOp watcher
;
732 if (!OBJ_IS_NATIVE(obj
)) {
733 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_WATCH
,
734 OBJ_GET_CLASS(cx
, obj
)->name
);
738 if (JSVAL_IS_INT(idval
))
739 propid
= INT_JSVAL_TO_JSID(idval
);
740 else if (!js_ValueToStringId(cx
, idval
, &propid
))
743 if (!js_LookupProperty(cx
, obj
, propid
, &pobj
, &prop
))
745 sprop
= (JSScopeProperty
*) prop
;
748 /* Check for a deleted symbol watchpoint, which holds its property. */
749 sprop
= js_FindWatchPoint(rt
, OBJ_SCOPE(obj
), propid
);
751 /* Make a new property in obj so we can watch for the first set. */
752 if (!js_DefineProperty(cx
, obj
, propid
, JSVAL_VOID
,
753 NULL
, NULL
, JSPROP_ENUMERATE
,
757 sprop
= (JSScopeProperty
*) prop
;
759 } else if (pobj
!= obj
) {
760 /* Clone the prototype property so we can watch the right object. */
762 JSPropertyOp getter
, setter
;
766 if (OBJ_IS_NATIVE(pobj
)) {
767 value
= SPROP_HAS_VALID_SLOT(sprop
, OBJ_SCOPE(pobj
))
768 ? LOCKED_OBJ_GET_SLOT(pobj
, sprop
->slot
)
770 getter
= sprop
->getter
;
771 setter
= sprop
->setter
;
772 attrs
= sprop
->attrs
;
773 flags
= sprop
->flags
;
774 shortid
= sprop
->shortid
;
776 if (!OBJ_GET_PROPERTY(cx
, pobj
, propid
, &value
) ||
777 !OBJ_GET_ATTRIBUTES(cx
, pobj
, propid
, prop
, &attrs
)) {
778 OBJ_DROP_PROPERTY(cx
, pobj
, prop
);
781 getter
= setter
= NULL
;
785 OBJ_DROP_PROPERTY(cx
, pobj
, prop
);
787 /* Recall that obj is native, whether or not pobj is native. */
788 if (!js_DefineNativeProperty(cx
, obj
, propid
, value
, getter
, setter
,
789 attrs
, flags
, shortid
, &prop
)) {
792 sprop
= (JSScopeProperty
*) prop
;
796 * At this point, prop/sprop exists in obj, obj is locked, and we must
797 * OBJ_DROP_PROPERTY(cx, obj, prop) before returning.
801 wp
= FindWatchPoint(rt
, OBJ_SCOPE(obj
), propid
);
804 watcher
= js_WrapWatchedSetter(cx
, propid
, sprop
->attrs
, sprop
->setter
);
810 wp
= (JSWatchPoint
*) JS_malloc(cx
, sizeof *wp
);
818 JS_ASSERT(sprop
->setter
!= js_watch_set
|| pobj
!= obj
);
819 wp
->setter
= sprop
->setter
;
820 wp
->flags
= JSWP_LIVE
;
822 /* XXXbe nest in obj lock here */
823 sprop
= js_ChangeNativePropertyAttrs(cx
, obj
, sprop
, 0, sprop
->attrs
,
824 sprop
->getter
, watcher
);
826 /* Self-link so DropWatchPointAndUnlock can JS_REMOVE_LINK it. */
827 JS_INIT_CLIST(&wp
->links
);
829 DropWatchPointAndUnlock(cx
, wp
, JSWP_LIVE
);
836 * Now that wp is fully initialized, append it to rt's wp list.
837 * Because obj is locked we know that no other thread could have added
838 * a watchpoint for (obj, propid).
841 JS_ASSERT(!FindWatchPoint(rt
, OBJ_SCOPE(obj
), propid
));
842 JS_APPEND_LINK(&wp
->links
, &rt
->watchPointList
);
843 ++rt
->debuggerMutations
;
845 wp
->handler
= handler
;
846 wp
->closure
= closure
;
850 OBJ_DROP_PROPERTY(cx
, obj
, prop
);
854 JS_PUBLIC_API(JSBool
)
855 JS_ClearWatchPoint(JSContext
*cx
, JSObject
*obj
, jsval id
,
856 JSWatchPointHandler
*handlerp
, void **closurep
)
863 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
864 &wp
->links
!= &rt
->watchPointList
;
865 wp
= (JSWatchPoint
*)wp
->links
.next
) {
866 if (wp
->object
== obj
&& SPROP_USERID(wp
->sprop
) == id
) {
868 *handlerp
= wp
->handler
;
870 *closurep
= wp
->closure
;
871 return DropWatchPointAndUnlock(cx
, wp
, JSWP_LIVE
);
882 JS_PUBLIC_API(JSBool
)
883 JS_ClearWatchPointsForObject(JSContext
*cx
, JSObject
*obj
)
886 JSWatchPoint
*wp
, *next
;
891 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
892 &wp
->links
!= &rt
->watchPointList
;
894 next
= (JSWatchPoint
*)wp
->links
.next
;
895 if (wp
->object
== obj
) {
896 sample
= rt
->debuggerMutations
;
897 if (!DropWatchPointAndUnlock(cx
, wp
, JSWP_LIVE
))
900 if (rt
->debuggerMutations
!= sample
+ 1)
901 next
= (JSWatchPoint
*)rt
->watchPointList
.next
;
908 JS_PUBLIC_API(JSBool
)
909 JS_ClearAllWatchPoints(JSContext
*cx
)
912 JSWatchPoint
*wp
, *next
;
917 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
918 &wp
->links
!= &rt
->watchPointList
;
920 next
= (JSWatchPoint
*)wp
->links
.next
;
921 sample
= rt
->debuggerMutations
;
922 if (!DropWatchPointAndUnlock(cx
, wp
, JSWP_LIVE
))
925 if (rt
->debuggerMutations
!= sample
+ 1)
926 next
= (JSWatchPoint
*)rt
->watchPointList
.next
;
932 /************************************************************************/
935 JS_PCToLineNumber(JSContext
*cx
, JSScript
*script
, jsbytecode
*pc
)
937 return js_PCToLineNumber(cx
, script
, pc
);
940 JS_PUBLIC_API(jsbytecode
*)
941 JS_LineNumberToPC(JSContext
*cx
, JSScript
*script
, uintN lineno
)
943 return js_LineNumberToPC(script
, lineno
);
946 JS_PUBLIC_API(JSScript
*)
947 JS_GetFunctionScript(JSContext
*cx
, JSFunction
*fun
)
949 return FUN_SCRIPT(fun
);
952 JS_PUBLIC_API(JSNative
)
953 JS_GetFunctionNative(JSContext
*cx
, JSFunction
*fun
)
955 return FUN_NATIVE(fun
);
958 JS_PUBLIC_API(JSFastNative
)
959 JS_GetFunctionFastNative(JSContext
*cx
, JSFunction
*fun
)
961 return FUN_FAST_NATIVE(fun
);
964 JS_PUBLIC_API(JSPrincipals
*)
965 JS_GetScriptPrincipals(JSContext
*cx
, JSScript
*script
)
967 return script
->principals
;
970 /************************************************************************/
973 * Stack Frame Iterator
975 JS_PUBLIC_API(JSStackFrame
*)
976 JS_FrameIterator(JSContext
*cx
, JSStackFrame
**iteratorp
)
978 *iteratorp
= (*iteratorp
== NULL
) ? js_GetTopStackFrame(cx
) : (*iteratorp
)->down
;
982 JS_PUBLIC_API(JSScript
*)
983 JS_GetFrameScript(JSContext
*cx
, JSStackFrame
*fp
)
988 JS_PUBLIC_API(jsbytecode
*)
989 JS_GetFramePC(JSContext
*cx
, JSStackFrame
*fp
)
991 return fp
->regs
? fp
->regs
->pc
: NULL
;
994 JS_PUBLIC_API(JSStackFrame
*)
995 JS_GetScriptedCaller(JSContext
*cx
, JSStackFrame
*fp
)
997 return js_GetScriptedCaller(cx
, fp
);
1000 JS_PUBLIC_API(JSPrincipals
*)
1001 JS_StackFramePrincipals(JSContext
*cx
, JSStackFrame
*fp
)
1003 JSSecurityCallbacks
*callbacks
;
1006 callbacks
= JS_GetSecurityCallbacks(cx
);
1007 if (callbacks
&& callbacks
->findObjectPrincipals
) {
1008 if (FUN_OBJECT(fp
->fun
) != fp
->callee
)
1009 return callbacks
->findObjectPrincipals(cx
, fp
->callee
);
1014 return fp
->script
->principals
;
1018 JS_PUBLIC_API(JSPrincipals
*)
1019 JS_EvalFramePrincipals(JSContext
*cx
, JSStackFrame
*fp
, JSStackFrame
*caller
)
1021 JSPrincipals
*principals
, *callerPrincipals
;
1022 JSSecurityCallbacks
*callbacks
;
1024 callbacks
= JS_GetSecurityCallbacks(cx
);
1025 if (callbacks
&& callbacks
->findObjectPrincipals
) {
1026 principals
= callbacks
->findObjectPrincipals(cx
, fp
->callee
);
1032 callerPrincipals
= JS_StackFramePrincipals(cx
, caller
);
1033 return (callerPrincipals
&& principals
&&
1034 callerPrincipals
->subsume(callerPrincipals
, principals
))
1039 JS_PUBLIC_API(void *)
1040 JS_GetFrameAnnotation(JSContext
*cx
, JSStackFrame
*fp
)
1042 if (fp
->annotation
&& fp
->script
) {
1043 JSPrincipals
*principals
= JS_StackFramePrincipals(cx
, fp
);
1045 if (principals
&& principals
->globalPrivilegesEnabled(cx
, principals
)) {
1047 * Give out an annotation only if privileges have not been revoked
1048 * or disabled globally.
1050 return fp
->annotation
;
1058 JS_SetFrameAnnotation(JSContext
*cx
, JSStackFrame
*fp
, void *annotation
)
1060 fp
->annotation
= annotation
;
1063 JS_PUBLIC_API(void *)
1064 JS_GetFramePrincipalArray(JSContext
*cx
, JSStackFrame
*fp
)
1066 JSPrincipals
*principals
;
1068 principals
= JS_StackFramePrincipals(cx
, fp
);
1071 return principals
->getPrincipalArray(cx
, principals
);
1074 JS_PUBLIC_API(JSBool
)
1075 JS_IsNativeFrame(JSContext
*cx
, JSStackFrame
*fp
)
1080 /* this is deprecated, use JS_GetFrameScopeChain instead */
1081 JS_PUBLIC_API(JSObject
*)
1082 JS_GetFrameObject(JSContext
*cx
, JSStackFrame
*fp
)
1084 return fp
->scopeChain
;
1087 JS_PUBLIC_API(JSObject
*)
1088 JS_GetFrameScopeChain(JSContext
*cx
, JSStackFrame
*fp
)
1090 /* Force creation of argument and call objects if not yet created */
1091 (void) JS_GetFrameCallObject(cx
, fp
);
1092 return js_GetScopeChain(cx
, fp
);
1095 JS_PUBLIC_API(JSObject
*)
1096 JS_GetFrameCallObject(JSContext
*cx
, JSStackFrame
*fp
)
1101 /* Force creation of argument object if not yet created */
1102 (void) js_GetArgsObject(cx
, fp
);
1105 * XXX ill-defined: null return here means error was reported, unlike a
1106 * null returned above or in the #else
1108 return js_GetCallObject(cx
, fp
, NULL
);
1111 JS_PUBLIC_API(JSObject
*)
1112 JS_GetFrameThis(JSContext
*cx
, JSStackFrame
*fp
)
1116 if (fp
->flags
& JSFRAME_COMPUTED_THIS
)
1119 /* js_ComputeThis gets confused if fp != cx->fp, so set it aside. */
1120 if (js_GetTopStackFrame(cx
) != fp
) {
1123 afp
->dormantNext
= cx
->dormantFrameChain
;
1124 cx
->dormantFrameChain
= afp
;
1131 if (!fp
->thisp
&& fp
->argv
)
1132 fp
->thisp
= js_ComputeThis(cx
, JS_TRUE
, fp
->argv
);
1136 cx
->dormantFrameChain
= afp
->dormantNext
;
1137 afp
->dormantNext
= NULL
;
1143 JS_PUBLIC_API(JSFunction
*)
1144 JS_GetFrameFunction(JSContext
*cx
, JSStackFrame
*fp
)
1149 JS_PUBLIC_API(JSObject
*)
1150 JS_GetFrameFunctionObject(JSContext
*cx
, JSStackFrame
*fp
)
1155 JS_ASSERT(OBJ_GET_CLASS(cx
, fp
->callee
) == &js_FunctionClass
);
1156 JS_ASSERT(OBJ_GET_PRIVATE(cx
, fp
->callee
) == fp
->fun
);
1160 JS_PUBLIC_API(JSBool
)
1161 JS_IsConstructorFrame(JSContext
*cx
, JSStackFrame
*fp
)
1163 return (fp
->flags
& JSFRAME_CONSTRUCTING
) != 0;
1166 JS_PUBLIC_API(JSObject
*)
1167 JS_GetFrameCalleeObject(JSContext
*cx
, JSStackFrame
*fp
)
1172 JS_PUBLIC_API(JSBool
)
1173 JS_IsDebuggerFrame(JSContext
*cx
, JSStackFrame
*fp
)
1175 return (fp
->flags
& JSFRAME_DEBUGGER
) != 0;
1178 JS_PUBLIC_API(jsval
)
1179 JS_GetFrameReturnValue(JSContext
*cx
, JSStackFrame
*fp
)
1185 JS_SetFrameReturnValue(JSContext
*cx
, JSStackFrame
*fp
, jsval rval
)
1190 /************************************************************************/
1192 JS_PUBLIC_API(const char *)
1193 JS_GetScriptFilename(JSContext
*cx
, JSScript
*script
)
1195 return script
->filename
;
1198 JS_PUBLIC_API(uintN
)
1199 JS_GetScriptBaseLineNumber(JSContext
*cx
, JSScript
*script
)
1201 return script
->lineno
;
1204 JS_PUBLIC_API(uintN
)
1205 JS_GetScriptLineExtent(JSContext
*cx
, JSScript
*script
)
1207 return js_GetScriptLineExtent(script
);
1210 JS_PUBLIC_API(JSVersion
)
1211 JS_GetScriptVersion(JSContext
*cx
, JSScript
*script
)
1213 return (JSVersion
) (script
->version
& JSVERSION_MASK
);
1216 /***************************************************************************/
1219 JS_SetNewScriptHook(JSRuntime
*rt
, JSNewScriptHook hook
, void *callerdata
)
1221 rt
->globalDebugHooks
.newScriptHook
= hook
;
1222 rt
->globalDebugHooks
.newScriptHookData
= callerdata
;
1226 JS_SetDestroyScriptHook(JSRuntime
*rt
, JSDestroyScriptHook hook
,
1229 rt
->globalDebugHooks
.destroyScriptHook
= hook
;
1230 rt
->globalDebugHooks
.destroyScriptHookData
= callerdata
;
1233 /***************************************************************************/
1235 JS_PUBLIC_API(JSBool
)
1236 JS_EvaluateUCInStackFrame(JSContext
*cx
, JSStackFrame
*fp
,
1237 const jschar
*chars
, uintN length
,
1238 const char *filename
, uintN lineno
,
1245 scobj
= JS_GetFrameScopeChain(cx
, fp
);
1249 script
= js_CompileScript(cx
, scobj
, fp
, JS_StackFramePrincipals(cx
, fp
),
1251 TCF_PUT_STATIC_DEPTH(fp
->script
->staticDepth
+ 1),
1252 chars
, length
, NULL
,
1257 ok
= js_Execute(cx
, scobj
, script
, fp
, JSFRAME_DEBUGGER
| JSFRAME_EVAL
,
1259 js_DestroyScript(cx
, script
);
1263 JS_PUBLIC_API(JSBool
)
1264 JS_EvaluateInStackFrame(JSContext
*cx
, JSStackFrame
*fp
,
1265 const char *bytes
, uintN length
,
1266 const char *filename
, uintN lineno
,
1271 size_t len
= length
;
1273 chars
= js_InflateString(cx
, bytes
, &len
);
1276 length
= (uintN
) len
;
1277 ok
= JS_EvaluateUCInStackFrame(cx
, fp
, chars
, length
, filename
, lineno
,
1284 /************************************************************************/
1286 /* XXXbe this all needs to be reworked to avoid requiring JSScope types. */
1288 JS_PUBLIC_API(JSScopeProperty
*)
1289 JS_PropertyIterator(JSObject
*obj
, JSScopeProperty
**iteratorp
)
1291 JSScopeProperty
*sprop
;
1295 scope
= OBJ_SCOPE(obj
);
1297 /* XXXbe minor(?) incompatibility: iterate in reverse definition order */
1299 sprop
= SCOPE_LAST_PROP(scope
);
1301 while ((sprop
= sprop
->parent
) != NULL
) {
1302 if (!SCOPE_HAD_MIDDLE_DELETE(scope
))
1304 if (SCOPE_HAS_PROPERTY(scope
, sprop
))
1312 JS_PUBLIC_API(JSBool
)
1313 JS_GetPropertyDesc(JSContext
*cx
, JSObject
*obj
, JSScopeProperty
*sprop
,
1317 JSScopeProperty
*aprop
;
1318 jsval lastException
;
1321 pd
->id
= ID_TO_VALUE(sprop
->id
);
1323 wasThrowing
= cx
->throwing
;
1325 lastException
= cx
->exception
;
1326 if (JSVAL_IS_GCTHING(lastException
) &&
1327 !js_AddRoot(cx
, &lastException
, "lastException")) {
1330 cx
->throwing
= JS_FALSE
;
1333 if (!js_GetProperty(cx
, obj
, sprop
->id
, &pd
->value
)) {
1334 if (!cx
->throwing
) {
1335 pd
->flags
= JSPD_ERROR
;
1336 pd
->value
= JSVAL_VOID
;
1338 pd
->flags
= JSPD_EXCEPTION
;
1339 pd
->value
= cx
->exception
;
1345 cx
->throwing
= wasThrowing
;
1347 cx
->exception
= lastException
;
1348 if (JSVAL_IS_GCTHING(lastException
))
1349 js_RemoveRoot(cx
->runtime
, &lastException
);
1352 pd
->flags
|= ((sprop
->attrs
& JSPROP_ENUMERATE
) ? JSPD_ENUMERATE
: 0)
1353 | ((sprop
->attrs
& JSPROP_READONLY
) ? JSPD_READONLY
: 0)
1354 | ((sprop
->attrs
& JSPROP_PERMANENT
) ? JSPD_PERMANENT
: 0);
1356 if (sprop
->getter
== js_GetCallArg
) {
1357 pd
->slot
= sprop
->shortid
;
1358 pd
->flags
|= JSPD_ARGUMENT
;
1359 } else if (sprop
->getter
== js_GetCallVar
) {
1360 pd
->slot
= sprop
->shortid
;
1361 pd
->flags
|= JSPD_VARIABLE
;
1365 pd
->alias
= JSVAL_VOID
;
1366 scope
= OBJ_SCOPE(obj
);
1367 if (SPROP_HAS_VALID_SLOT(sprop
, scope
)) {
1368 for (aprop
= SCOPE_LAST_PROP(scope
); aprop
; aprop
= aprop
->parent
) {
1369 if (aprop
!= sprop
&& aprop
->slot
== sprop
->slot
) {
1370 pd
->alias
= ID_TO_VALUE(aprop
->id
);
1378 JS_PUBLIC_API(JSBool
)
1379 JS_GetPropertyDescArray(JSContext
*cx
, JSObject
*obj
, JSPropertyDescArray
*pda
)
1385 JSScopeProperty
*sprop
;
1387 clasp
= OBJ_GET_CLASS(cx
, obj
);
1388 if (!OBJ_IS_NATIVE(obj
) || (clasp
->flags
& JSCLASS_NEW_ENUMERATE
)) {
1389 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
1390 JSMSG_CANT_DESCRIBE_PROPS
, clasp
->name
);
1393 if (!clasp
->enumerate(cx
, obj
))
1396 /* have no props, or object's scope has not mutated from that of proto */
1397 scope
= OBJ_SCOPE(obj
);
1398 if (scope
->object
!= obj
|| scope
->entryCount
== 0) {
1404 n
= STOBJ_NSLOTS(obj
);
1405 if (n
> scope
->entryCount
)
1406 n
= scope
->entryCount
;
1407 pd
= (JSPropertyDesc
*) JS_malloc(cx
, (size_t)n
* sizeof(JSPropertyDesc
));
1411 for (sprop
= SCOPE_LAST_PROP(scope
); sprop
; sprop
= sprop
->parent
) {
1412 if (SCOPE_HAD_MIDDLE_DELETE(scope
) && !SCOPE_HAS_PROPERTY(scope
, sprop
))
1414 if (!js_AddRoot(cx
, &pd
[i
].id
, NULL
))
1416 if (!js_AddRoot(cx
, &pd
[i
].value
, NULL
))
1418 if (!JS_GetPropertyDesc(cx
, obj
, sprop
, &pd
[i
]))
1420 if ((pd
[i
].flags
& JSPD_ALIAS
) && !js_AddRoot(cx
, &pd
[i
].alias
, NULL
))
1430 pda
->length
= i
+ 1;
1432 JS_PutPropertyDescArray(cx
, pda
);
1437 JS_PutPropertyDescArray(JSContext
*cx
, JSPropertyDescArray
*pda
)
1443 for (i
= 0; i
< pda
->length
; i
++) {
1444 js_RemoveRoot(cx
->runtime
, &pd
[i
].id
);
1445 js_RemoveRoot(cx
->runtime
, &pd
[i
].value
);
1446 if (pd
[i
].flags
& JSPD_ALIAS
)
1447 js_RemoveRoot(cx
->runtime
, &pd
[i
].alias
);
1452 /************************************************************************/
1454 JS_PUBLIC_API(JSBool
)
1455 JS_SetDebuggerHandler(JSRuntime
*rt
, JSTrapHandler handler
, void *closure
)
1457 rt
->globalDebugHooks
.debuggerHandler
= handler
;
1458 rt
->globalDebugHooks
.debuggerHandlerData
= closure
;
1462 JS_PUBLIC_API(JSBool
)
1463 JS_SetSourceHandler(JSRuntime
*rt
, JSSourceHandler handler
, void *closure
)
1465 rt
->globalDebugHooks
.sourceHandler
= handler
;
1466 rt
->globalDebugHooks
.sourceHandlerData
= closure
;
1470 JS_PUBLIC_API(JSBool
)
1471 JS_SetExecuteHook(JSRuntime
*rt
, JSInterpreterHook hook
, void *closure
)
1473 rt
->globalDebugHooks
.executeHook
= hook
;
1474 rt
->globalDebugHooks
.executeHookData
= closure
;
1478 JS_PUBLIC_API(JSBool
)
1479 JS_SetCallHook(JSRuntime
*rt
, JSInterpreterHook hook
, void *closure
)
1481 rt
->globalDebugHooks
.callHook
= hook
;
1482 rt
->globalDebugHooks
.callHookData
= closure
;
1486 JS_PUBLIC_API(JSBool
)
1487 JS_SetObjectHook(JSRuntime
*rt
, JSObjectHook hook
, void *closure
)
1489 rt
->globalDebugHooks
.objectHook
= hook
;
1490 rt
->globalDebugHooks
.objectHookData
= closure
;
1494 JS_PUBLIC_API(JSBool
)
1495 JS_SetThrowHook(JSRuntime
*rt
, JSTrapHandler hook
, void *closure
)
1497 rt
->globalDebugHooks
.throwHook
= hook
;
1498 rt
->globalDebugHooks
.throwHookData
= closure
;
1502 JS_PUBLIC_API(JSBool
)
1503 JS_SetDebugErrorHook(JSRuntime
*rt
, JSDebugErrorHook hook
, void *closure
)
1505 rt
->globalDebugHooks
.debugErrorHook
= hook
;
1506 rt
->globalDebugHooks
.debugErrorHookData
= closure
;
1510 /************************************************************************/
1512 JS_PUBLIC_API(size_t)
1513 JS_GetObjectTotalSize(JSContext
*cx
, JSObject
*obj
)
1518 nbytes
= sizeof *obj
;
1520 nbytes
+= ((uint32
)obj
->dslots
[-1] - JS_INITIAL_NSLOTS
+ 1)
1521 * sizeof obj
->dslots
[0];
1523 if (OBJ_IS_NATIVE(obj
)) {
1524 scope
= OBJ_SCOPE(obj
);
1525 if (scope
->object
== obj
) {
1526 nbytes
+= sizeof *scope
;
1527 nbytes
+= SCOPE_CAPACITY(scope
) * sizeof(JSScopeProperty
*);
1534 GetAtomTotalSize(JSContext
*cx
, JSAtom
*atom
)
1538 nbytes
= sizeof(JSAtom
*) + sizeof(JSDHashEntryStub
);
1539 if (ATOM_IS_STRING(atom
)) {
1540 nbytes
+= sizeof(JSString
);
1541 nbytes
+= (JSFLATSTR_LENGTH(ATOM_TO_STRING(atom
)) + 1) * sizeof(jschar
);
1542 } else if (ATOM_IS_DOUBLE(atom
)) {
1543 nbytes
+= sizeof(jsdouble
);
1548 JS_PUBLIC_API(size_t)
1549 JS_GetFunctionTotalSize(JSContext
*cx
, JSFunction
*fun
)
1553 nbytes
= sizeof *fun
;
1554 nbytes
+= JS_GetObjectTotalSize(cx
, FUN_OBJECT(fun
));
1555 if (FUN_INTERPRETED(fun
))
1556 nbytes
+= JS_GetScriptTotalSize(cx
, fun
->u
.i
.script
);
1558 nbytes
+= GetAtomTotalSize(cx
, fun
->atom
);
1564 JS_PUBLIC_API(size_t)
1565 JS_GetScriptTotalSize(JSContext
*cx
, JSScript
*script
)
1567 size_t nbytes
, pbytes
;
1569 jssrcnote
*sn
, *notes
;
1570 JSObjectArray
*objarray
;
1571 JSPrincipals
*principals
;
1573 nbytes
= sizeof *script
;
1574 if (script
->u
.object
)
1575 nbytes
+= JS_GetObjectTotalSize(cx
, script
->u
.object
);
1577 nbytes
+= script
->length
* sizeof script
->code
[0];
1578 nbytes
+= script
->atomMap
.length
* sizeof script
->atomMap
.vector
[0];
1579 for (i
= 0; i
< script
->atomMap
.length
; i
++)
1580 nbytes
+= GetAtomTotalSize(cx
, script
->atomMap
.vector
[i
]);
1582 if (script
->filename
)
1583 nbytes
+= strlen(script
->filename
) + 1;
1585 notes
= SCRIPT_NOTES(script
);
1586 for (sn
= notes
; !SN_IS_TERMINATOR(sn
); sn
= SN_NEXT(sn
))
1588 nbytes
+= (sn
- notes
+ 1) * sizeof *sn
;
1590 if (script
->objectsOffset
!= 0) {
1591 objarray
= JS_SCRIPT_OBJECTS(script
);
1592 i
= objarray
->length
;
1593 nbytes
+= sizeof *objarray
+ i
* sizeof objarray
->vector
[0];
1595 nbytes
+= JS_GetObjectTotalSize(cx
, objarray
->vector
[--i
]);
1599 if (script
->regexpsOffset
!= 0) {
1600 objarray
= JS_SCRIPT_REGEXPS(script
);
1601 i
= objarray
->length
;
1602 nbytes
+= sizeof *objarray
+ i
* sizeof objarray
->vector
[0];
1604 nbytes
+= JS_GetObjectTotalSize(cx
, objarray
->vector
[--i
]);
1608 if (script
->trynotesOffset
!= 0) {
1609 nbytes
+= sizeof(JSTryNoteArray
) +
1610 JS_SCRIPT_TRYNOTES(script
)->length
* sizeof(JSTryNote
);
1613 principals
= script
->principals
;
1615 JS_ASSERT(principals
->refcount
);
1616 pbytes
= sizeof *principals
;
1617 if (principals
->refcount
> 1)
1618 pbytes
= JS_HOWMANY(pbytes
, principals
->refcount
);
1625 JS_PUBLIC_API(uint32
)
1626 JS_GetTopScriptFilenameFlags(JSContext
*cx
, JSStackFrame
*fp
)
1629 fp
= js_GetTopStackFrame(cx
);
1632 return JS_GetScriptFilenameFlags(fp
->script
);
1638 JS_PUBLIC_API(uint32
)
1639 JS_GetScriptFilenameFlags(JSScript
*script
)
1642 if (!script
->filename
)
1643 return JSFILENAME_NULL
;
1644 return js_GetScriptFilenameFlags(script
->filename
);
1647 JS_PUBLIC_API(JSBool
)
1648 JS_FlagScriptFilenamePrefix(JSRuntime
*rt
, const char *prefix
, uint32 flags
)
1650 if (!js_SaveScriptFilenameRT(rt
, prefix
, flags
))
1655 JS_PUBLIC_API(JSBool
)
1656 JS_IsSystemObject(JSContext
*cx
, JSObject
*obj
)
1658 return STOBJ_IS_SYSTEM(obj
);
1661 JS_PUBLIC_API(JSObject
*)
1662 JS_NewSystemObject(JSContext
*cx
, JSClass
*clasp
, JSObject
*proto
,
1663 JSObject
*parent
, JSBool system
)
1667 obj
= js_NewObject(cx
, clasp
, proto
, parent
, 0);
1669 STOBJ_SET_SYSTEM(obj
);
1673 /************************************************************************/
1675 JS_PUBLIC_API(JSDebugHooks
*)
1676 JS_GetGlobalDebugHooks(JSRuntime
*rt
)
1678 return &rt
->globalDebugHooks
;
1681 JS_PUBLIC_API(JSDebugHooks
*)
1682 JS_SetContextDebugHooks(JSContext
*cx
, JSDebugHooks
*hooks
)
1687 old
= cx
->debugHooks
;
1688 cx
->debugHooks
= hooks
;
1694 #include <CHUD/CHUD.h>
1696 JS_PUBLIC_API(JSBool
)
1697 JS_StartChudRemote()
1699 if (chudIsRemoteAccessAcquired() &&
1700 (chudStartRemotePerfMonitor("Mozilla") == chudSuccess
)) {
1707 JS_PUBLIC_API(JSBool
)
1710 if (chudIsRemoteAccessAcquired() &&
1711 (chudStopRemotePerfMonitor() == chudSuccess
)) {
1718 JS_PUBLIC_API(JSBool
)
1721 if (!chudIsInitialized() && (chudInitialize() != chudSuccess
))
1724 if (chudAcquireRemoteAccess() != chudSuccess
)
1730 JS_PUBLIC_API(JSBool
)
1731 JS_DisconnectShark()
1733 if (chudIsRemoteAccessAcquired() && (chudReleaseRemoteAccess() != chudSuccess
))
1739 JS_FRIEND_API(JSBool
)
1740 js_StartShark(JSContext
*cx
, JSObject
*obj
,
1741 uintN argc
, jsval
*argv
, jsval
*rval
)
1743 if (!JS_StartChudRemote()) {
1744 JS_ReportError(cx
, "Error starting CHUD.");
1750 JS_FRIEND_API(JSBool
)
1751 js_StopShark(JSContext
*cx
, JSObject
*obj
,
1752 uintN argc
, jsval
*argv
, jsval
*rval
)
1754 if (!JS_StopChudRemote()) {
1755 JS_ReportError(cx
, "Error stopping CHUD.");
1761 JS_FRIEND_API(JSBool
)
1762 js_ConnectShark(JSContext
*cx
, JSObject
*obj
,
1763 uintN argc
, jsval
*argv
, jsval
*rval
)
1765 if (!JS_ConnectShark()) {
1766 JS_ReportError(cx
, "Error connecting to Shark.");
1772 JS_FRIEND_API(JSBool
)
1773 js_DisconnectShark(JSContext
*cx
, JSObject
*obj
,
1774 uintN argc
, jsval
*argv
, jsval
*rval
)
1776 if (!JS_DisconnectShark()) {
1777 JS_ReportError(cx
, "Error disconnecting from Shark.");
1783 #endif /* MOZ_SHARK */
1785 #ifdef MOZ_CALLGRIND
1787 #include <valgrind/callgrind.h>
1789 JS_FRIEND_API(JSBool
)
1790 js_StartCallgrind(JSContext
*cx
, JSObject
*obj
,
1791 uintN argc
, jsval
*argv
, jsval
*rval
)
1793 CALLGRIND_START_INSTRUMENTATION
;
1794 CALLGRIND_ZERO_STATS
;
1798 JS_FRIEND_API(JSBool
)
1799 js_StopCallgrind(JSContext
*cx
, JSObject
*obj
,
1800 uintN argc
, jsval
*argv
, jsval
*rval
)
1802 CALLGRIND_STOP_INSTRUMENTATION
;
1806 JS_FRIEND_API(JSBool
)
1807 js_DumpCallgrind(JSContext
*cx
, JSObject
*obj
,
1808 uintN argc
, jsval
*argv
, jsval
*rval
)
1813 if (argc
> 0 && JSVAL_IS_STRING(argv
[0])) {
1814 str
= JSVAL_TO_STRING(argv
[0]);
1815 cstr
= js_DeflateString(cx
, JSSTRING_CHARS(str
), JSSTRING_LENGTH(str
));
1817 CALLGRIND_DUMP_STATS_AT(cstr
);
1822 CALLGRIND_DUMP_STATS
;
1827 #endif /* MOZ_CALLGRIND */
1830 #include <VTuneApi.h>
1832 static const char *vtuneErrorMessages
[] = {
1833 "unknown, error #0",
1834 "invalid 'max samples' field",
1835 "invalid 'samples per buffer' field",
1836 "invalid 'sample interval' field",
1838 "sample file in use",
1839 "invalid 'number of events' field",
1840 "unknown, error #7",
1843 "VTStopSampling called without calling VTStartSampling",
1844 "no events selected for event-based sampling",
1845 "events selected cannot be run together",
1846 "no sampling parameters",
1847 "sample database already exists",
1848 "sampling already started",
1849 "time-based sampling not supported",
1850 "invalid 'sampling parameters size' field",
1851 "invalid 'event size' field",
1852 "sampling file already bound",
1853 "invalid event path",
1855 "invalid 'global options' field",
1859 JS_FRIEND_API(JSBool
)
1860 js_StartVtune(JSContext
*cx
, JSObject
*obj
,
1861 uintN argc
, jsval
*argv
, jsval
*rval
)
1863 VTUNE_EVENT events
[] = {
1864 { 1000000, 0, 0, 0, "CPU_CLK_UNHALTED.CORE" },
1865 { 1000000, 0, 0, 0, "INST_RETIRED.ANY" },
1868 U32 n_events
= sizeof(events
) / sizeof(VTUNE_EVENT
);
1869 char *default_filename
= "mozilla-vtune.tb5";
1873 VTUNE_SAMPLING_PARAMS params
= {
1874 sizeof(VTUNE_SAMPLING_PARAMS
),
1875 sizeof(VTUNE_EVENT
),
1876 0, 0, /* Reserved fields */
1877 1, /* Initialize in "paused" state */
1878 0, /* Max samples, or 0 for "continuous" */
1879 4096, /* Samples per buffer */
1880 0.1, /* Sampling interval in ms */
1881 1, /* 1 for event-based sampling, 0 for time-based */
1888 if (argc
> 0 && JSVAL_IS_STRING(argv
[0])) {
1889 str
= JSVAL_TO_STRING(argv
[0]);
1890 params
.tb5Filename
= js_DeflateString(cx
,
1891 JSSTRING_CHARS(str
),
1892 JSSTRING_LENGTH(str
));
1895 status
= VTStartSampling(¶ms
);
1897 if (params
.tb5Filename
!= default_filename
)
1898 JS_free(cx
, params
.tb5Filename
);
1901 if (status
== VTAPI_MULTIPLE_RUNS
)
1903 if (status
< sizeof(vtuneErrorMessages
))
1904 JS_ReportError(cx
, "Vtune setup error: %s",
1905 vtuneErrorMessages
[status
]);
1907 JS_ReportError(cx
, "Vtune setup error: %d",
1914 JS_FRIEND_API(JSBool
)
1915 js_StopVtune(JSContext
*cx
, JSObject
*obj
,
1916 uintN argc
, jsval
*argv
, jsval
*rval
)
1918 U32 status
= VTStopSampling(1);
1920 if (status
< sizeof(vtuneErrorMessages
))
1921 JS_ReportError(cx
, "Vtune shutdown error: %s",
1922 vtuneErrorMessages
[status
]);
1924 JS_ReportError(cx
, "Vtune shutdown error: %d",
1931 JS_FRIEND_API(JSBool
)
1932 js_PauseVtune(JSContext
*cx
, JSObject
*obj
,
1933 uintN argc
, jsval
*argv
, jsval
*rval
)
1939 JS_FRIEND_API(JSBool
)
1940 js_ResumeVtune(JSContext
*cx
, JSObject
*obj
,
1941 uintN argc
, jsval
*argv
, jsval
*rval
)
1947 #endif /* MOZ_VTUNE */