LCOV - app.info - js/src/jsdbgapi.cpp

LCOV - code coverage report
| Current view: | directory - js/src - jsdbgapi.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 552 | 190 | 34.4 %
| Date: | 2012-04-07 | Functions: | 94 | 35 | 37.2 %

           1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  * vim: set ts=8 sw=4 et tw=99:
           3                 :  *
           4                 :  * ***** BEGIN LICENSE BLOCK *****
           5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           6                 :  *
           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/
          11                 :  *
          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
          15                 :  * License.
          16                 :  *
          17                 :  * The Original Code is Mozilla Communicator client code, released
          18                 :  * March 31, 1998.
          19                 :  *
          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.
          24                 :  *
          25                 :  * Contributor(s):
          26                 :  *   Nick Fitzgerald <nfitzgerald@mozilla.com>
          27                 :  *
          28                 :  * Alternatively, the contents of this file may be used under the terms of
          29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          32                 :  * of those above. If you wish to allow use of your version of this file only
          33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          34                 :  * use your version of this file under the terms of the MPL, indicate your
          35                 :  * decision by deleting the provisions above and replace them with the notice
          36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          37                 :  * the provisions above, a recipient may use your version of this file under
          38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          39                 :  *
          40                 :  * ***** END LICENSE BLOCK ***** */
          41                 :
          42                 : /*
          43                 :  * JS debugging API.
          44                 :  */
          45                 : #include <string.h>
          46                 : #include <stdarg.h>
          47                 : #include "jsprvtd.h"
          48                 : #include "jstypes.h"
          49                 : #include "jsutil.h"
          50                 : #include "jsclist.h"
          51                 : #include "jsapi.h"
          52                 : #include "jscntxt.h"
          53                 : #include "jsversion.h"
          54                 : #include "jsdbgapi.h"
          55                 : #include "jsfun.h"
          56                 : #include "jsgc.h"
          57                 : #include "jsgcmark.h"
          58                 : #include "jsinterp.h"
          59                 : #include "jslock.h"
          60                 : #include "jsobj.h"
          61                 : #include "jsopcode.h"
          62                 : #include "jsscope.h"
          63                 : #include "jsscript.h"
          64                 : #include "jsstr.h"
          65                 : #include "jswatchpoint.h"
          66                 : #include "jswrapper.h"
          67                 :
          68                 : #include "frontend/BytecodeEmitter.h"
          69                 : #include "frontend/Parser.h"
          70                 : #include "vm/Debugger.h"
          71                 :
          72                 : #include "jsatominlines.h"
          73                 : #include "jsinferinlines.h"
          74                 : #include "jsobjinlines.h"
          75                 : #include "jsinterpinlines.h"
          76                 : #include "jsscopeinlines.h"
          77                 : #include "jsscriptinlines.h"
          78                 :
          79                 : #include "vm/Stack-inl.h"
          80                 :
          81                 : #include "jsautooplen.h"
          82                 :
          83                 : #ifdef __APPLE__
          84                 : #include "sharkctl.h"
          85                 : #endif
          86                 :
          87                 : using namespace js;
          88                 : using namespace js::gc;
          89                 :
          90                 : JS_PUBLIC_API(JSBool)
          91            1344 : JS_GetDebugMode(JSContext *cx)
          92                 : {
          93            1344 :     return cx->compartment->debugMode();
          94                 : }
          95                 :
          96                 : JS_PUBLIC_API(JSBool)
          97            6939 : JS_SetDebugMode(JSContext *cx, JSBool debug)
          98                 : {
          99            6939 :     return JS_SetDebugModeForCompartment(cx, cx->compartment, debug);
         100                 : }
         101                 :
         102                 : JS_PUBLIC_API(void)
         103            6654 : JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug)
         104                 : {
         105            6654 :     rt->debugMode = !!debug;
         106            6654 : }
         107                 :
         108                 : namespace js {
         109                 :
         110                 : JSTrapStatus
         111        12393915 : ScriptDebugPrologue(JSContext *cx, StackFrame *fp)
         112                 : {
         113        12393915 :     JS_ASSERT(fp == cx->fp());
         114                 :
         115        12393915 :     if (fp->isFramePushedByExecute()) {
         116           58886 :         if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
         117               0 :             fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->runtime->debugHooks.executeHookData));
         118                 :     } else {
         119        12335029 :         if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
         120              38 :             fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->runtime->debugHooks.callHookData));
         121                 :     }
         122                 :
         123                 :     Value rval;
         124        12393915 :     JSTrapStatus status = Debugger::onEnterFrame(cx, &rval);
         125        12393915 :     switch (status) {
         126                 :       case JSTRAP_CONTINUE:
         127        12391802 :         break;
         128                 :       case JSTRAP_THROW:
         129              27 :         cx->setPendingException(rval);
         130              27 :         break;
         131                 :       case JSTRAP_ERROR:
         132            2041 :         cx->clearPendingException();
         133            2041 :         break;
         134                 :       case JSTRAP_RETURN:
         135              45 :         fp->setReturnValue(rval);
         136              45 :         break;
         137                 :       default:
         138               0 :         JS_NOT_REACHED("bad Debugger::onEnterFrame JSTrapStatus value");
         139                 :     }
         140        12393915 :     return status;
         141                 : }
         142                 :
         143                 : bool
         144        12394644 : ScriptDebugEpilogue(JSContext *cx, StackFrame *fp, bool okArg)
         145                 : {
         146        12394644 :     JS_ASSERT(fp == cx->fp());
         147        12394644 :     JSBool ok = okArg;
         148                 :
         149        12394644 :     if (void *hookData = fp->maybeHookData()) {
         150              20 :         if (fp->isFramePushedByExecute()) {
         151               0 :             if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
         152               0 :                 hook(cx, Jsvalify(fp), false, &ok, hookData);
         153                 :         } else {
         154              20 :             if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
         155              20 :                 hook(cx, Jsvalify(fp), false, &ok, hookData);
         156                 :         }
         157                 :     }
         158                 :
         159        12394644 :     return Debugger::onLeaveFrame(cx, ok);
         160                 : }
         161                 :
         162                 : } /* namespace js */
         163                 :
         164                 : JS_FRIEND_API(JSBool)
         165            6940 : JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, JSBool debug)
         166                 : {
         167            6940 :     return comp->setDebugModeFromC(cx, !!debug);
         168                 : }
         169                 :
         170                 : static JSBool
         171            1344 : CheckDebugMode(JSContext *cx)
         172                 : {
         173            1344 :     JSBool debugMode = JS_GetDebugMode(cx);
         174                 :     /*
         175                 :      * :TODO:
         176                 :      * This probably should be an assertion, since it's indicative of a severe
         177                 :      * API misuse.
         178                 :      */
         179            1344 :     if (!debugMode) {
         180                 :         JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
         181               0 :                                      NULL, JSMSG_NEED_DEBUG_MODE);
         182                 :     }
         183            1344 :     return debugMode;
         184                 : }
         185                 :
         186                 : JS_PUBLIC_API(JSBool)
         187               1 : JS_SetSingleStepMode(JSContext *cx, JSScript *script, JSBool singleStep)
         188                 : {
         189               1 :     assertSameCompartment(cx, script);
         190               1 :     if (!CheckDebugMode(cx))
         191               0 :         return JS_FALSE;
         192                 :
         193               1 :     return script->setStepModeFlag(cx, singleStep);
         194                 : }
         195                 :
         196                 : JS_PUBLIC_API(JSBool)
         197             371 : JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, JSTrapHandler handler, jsval closure)
         198                 : {
         199             371 :     assertSameCompartment(cx, script, closure);
         200                 :
         201             371 :     if (!CheckDebugMode(cx))
         202               0 :         return false;
         203                 :
         204             371 :     BreakpointSite *site = script->getOrCreateBreakpointSite(cx, pc, NULL);
         205             371 :     if (!site)
         206               0 :         return false;
         207             371 :     site->setTrap(cx->runtime->defaultFreeOp(), handler, closure);
         208             371 :     return true;
         209                 : }
         210                 :
         211                 : JS_PUBLIC_API(void)
         212              36 : JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
         213                 :              JSTrapHandler *handlerp, jsval *closurep)
         214                 : {
         215              36 :     if (BreakpointSite *site = script->getBreakpointSite(pc)) {
         216              27 :         site->clearTrap(cx->runtime->defaultFreeOp(), handlerp, closurep);
         217                 :     } else {
         218               9 :         if (handlerp)
         219               0 :             *handlerp = NULL;
         220               9 :         if (closurep)
         221               0 :             *closurep = JSVAL_VOID;
         222                 :     }
         223              36 : }
         224                 :
         225                 : JS_PUBLIC_API(void)
         226               0 : JS_ClearScriptTraps(JSContext *cx, JSScript *script)
         227                 : {
         228               0 :     script->clearTraps(cx->runtime->defaultFreeOp());
         229               0 : }
         230                 :
         231                 : JS_PUBLIC_API(void)
         232               0 : JS_ClearAllTrapsForCompartment(JSContext *cx)
         233                 : {
         234               0 :     cx->compartment->clearTraps(cx);
         235               0 : }
         236                 :
         237                 : JS_PUBLIC_API(JSBool)
         238               1 : JS_SetInterrupt(JSRuntime *rt, JSInterruptHook hook, void *closure)
         239                 : {
         240               1 :     rt->debugHooks.interruptHook = hook;
         241               1 :     rt->debugHooks.interruptHookData = closure;
         242               1 :     return JS_TRUE;
         243                 : }
         244                 :
         245                 : JS_PUBLIC_API(JSBool)
         246               0 : JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *hoop, void **closurep)
         247                 : {
         248               0 :     if (hoop)
         249               0 :         *hoop = rt->debugHooks.interruptHook;
         250               0 :     if (closurep)
         251               0 :         *closurep = rt->debugHooks.interruptHookData;
         252               0 :     rt->debugHooks.interruptHook = 0;
         253               0 :     rt->debugHooks.interruptHookData = 0;
         254               0 :     return JS_TRUE;
         255                 : }
         256                 :
         257                 : /************************************************************************/
         258                 :
         259                 : JS_PUBLIC_API(JSBool)
         260            3672 : JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id,
         261                 :                  JSWatchPointHandler handler, JSObject *closure)
         262                 : {
         263            3672 :     assertSameCompartment(cx, obj);
         264            3672 :     id = js_CheckForStringIndex(id);
         265                 :
         266                 :     JSObject *origobj;
         267                 :     Value v;
         268                 :     unsigned attrs;
         269                 :     jsid propid;
         270                 :
         271            3672 :     origobj = obj;
         272            3672 :     OBJ_TO_INNER_OBJECT(cx, obj);
         273            3672 :     if (!obj)
         274               0 :         return false;
         275                 :
         276            7344 :     AutoValueRooter idroot(cx);
         277            3672 :     if (JSID_IS_INT(id)) {
         278               0 :         propid = id;
         279            3672 :     } else if (JSID_IS_OBJECT(id)) {
         280               0 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH_PROP);
         281               0 :         return false;
         282                 :     } else {
         283            3672 :         if (!js_ValueToStringId(cx, IdToValue(id), &propid))
         284               0 :             return false;
         285            3672 :         propid = js_CheckForStringIndex(propid);
         286            3672 :         idroot.set(IdToValue(propid));
         287                 :     }
         288                 :
         289                 :     /*
         290                 :      * If, by unwrapping and innerizing, we changed the object, check
         291                 :      * again to make sure that we're allowed to set a watch point.
         292                 :      */
         293            3672 :     if (origobj != obj && !CheckAccess(cx, obj, propid, JSACC_WATCH, &v, &attrs))
         294               0 :         return false;
         295                 :
         296            3672 :     if (!obj->isNative()) {
         297                 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH,
         298               0 :                              obj->getClass()->name);
         299               0 :         return false;
         300                 :     }
         301                 :
         302            3672 :     types::MarkTypePropertyConfigured(cx, obj, propid);
         303                 :
         304            3672 :     WatchpointMap *wpmap = cx->compartment->watchpointMap;
         305            3672 :     if (!wpmap) {
         306             225 :         wpmap = cx->runtime->new_<WatchpointMap>();
         307             225 :         if (!wpmap || !wpmap->init()) {
         308               0 :             js_ReportOutOfMemory(cx);
         309               0 :             return false;
         310                 :         }
         311             225 :         cx->compartment->watchpointMap = wpmap;
         312                 :     }
         313            3672 :     return wpmap->watch(cx, obj, propid, handler, closure);
         314                 : }
         315                 :
         316                 : JS_PUBLIC_API(JSBool)
         317             945 : JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsid id,
         318                 :                    JSWatchPointHandler *handlerp, JSObject **closurep)
         319                 : {
         320             945 :     assertSameCompartment(cx, obj, id);
         321                 :
         322             945 :     id = js_CheckForStringIndex(id);
         323             945 :     if (WatchpointMap *wpmap = cx->compartment->watchpointMap)
         324               9 :         wpmap->unwatch(obj, id, handlerp, closurep);
         325             945 :     return true;
         326                 : }
         327                 :
         328                 : JS_PUBLIC_API(JSBool)
         329               0 : JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj)
         330                 : {
         331               0 :     assertSameCompartment(cx, obj);
         332                 :
         333               0 :     if (WatchpointMap *wpmap = cx->compartment->watchpointMap)
         334               0 :         wpmap->unwatchObject(obj);
         335               0 :     return true;
         336                 : }
         337                 :
         338                 : JS_PUBLIC_API(JSBool)
         339           18761 : JS_ClearAllWatchPoints(JSContext *cx)
         340                 : {
         341           18761 :     if (JSCompartment *comp = cx->compartment) {
         342           18761 :         if (WatchpointMap *wpmap = comp->watchpointMap)
         343             216 :             wpmap->clear();
         344                 :     }
         345           18761 :     return true;
         346                 : }
         347                 :
         348                 : /************************************************************************/
         349                 :
         350                 : JS_PUBLIC_API(unsigned)
         351            2008 : JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
         352                 : {
         353            2008 :     return js::PCToLineNumber(script, pc);
         354                 : }
         355                 :
         356                 : JS_PUBLIC_API(jsbytecode *)
         357              12 : JS_LineNumberToPC(JSContext *cx, JSScript *script, unsigned lineno)
         358                 : {
         359              12 :     return js_LineNumberToPC(script, lineno);
         360                 : }
         361                 :
         362                 : JS_PUBLIC_API(jsbytecode *)
         363               0 : JS_EndPC(JSContext *cx, JSScript *script)
         364                 : {
         365               0 :     return script->code + script->length;
         366                 : }
         367                 :
         368                 : JS_PUBLIC_API(JSBool)
         369               0 : JS_GetLinePCs(JSContext *cx, JSScript *script,
         370                 :               unsigned startLine, unsigned maxLines,
         371                 :               unsigned* count, unsigned** retLines, jsbytecode*** retPCs)
         372                 : {
         373                 :     unsigned* lines;
         374                 :     jsbytecode** pcs;
         375               0 :     size_t len = (script->length > maxLines ? maxLines : script->length);
         376               0 :     lines = (unsigned*) cx->malloc_(len * sizeof(unsigned));
         377               0 :     if (!lines)
         378               0 :         return JS_FALSE;
         379                 :
         380               0 :     pcs = (jsbytecode**) cx->malloc_(len * sizeof(jsbytecode*));
         381               0 :     if (!pcs) {
         382               0 :         cx->free_(lines);
         383               0 :         return JS_FALSE;
         384                 :     }
         385                 :
         386               0 :     unsigned lineno = script->lineno;
         387               0 :     unsigned offset = 0;
         388               0 :     unsigned i = 0;
         389               0 :     for (jssrcnote *sn = script->notes(); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
         390               0 :         offset += SN_DELTA(sn);
         391               0 :         SrcNoteType type = (SrcNoteType) SN_TYPE(sn);
         392               0 :         if (type == SRC_SETLINE || type == SRC_NEWLINE) {
         393               0 :             if (type == SRC_SETLINE)
         394               0 :                 lineno = (unsigned) js_GetSrcNoteOffset(sn, 0);
         395                 :             else
         396               0 :                 lineno++;
         397                 :
         398               0 :             if (lineno >= startLine) {
         399               0 :                 lines[i] = lineno;
         400               0 :                 pcs[i] = script->code + offset;
         401               0 :                 if (++i >= maxLines)
         402               0 :                     break;
         403                 :             }
         404                 :         }
         405                 :     }
         406                 :
         407               0 :     *count = i;
         408               0 :     if (retLines)
         409               0 :         *retLines = lines;
         410                 :     else
         411               0 :         cx->free_(lines);
         412                 :
         413               0 :     if (retPCs)
         414               0 :         *retPCs = pcs;
         415                 :     else
         416               0 :         cx->free_(pcs);
         417                 :
         418               0 :     return JS_TRUE;
         419                 : }
         420                 :
         421                 : JS_PUBLIC_API(unsigned)
         422               0 : JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun)
         423                 : {
         424               0 :     return fun->nargs;
         425                 : }
         426                 :
         427                 : JS_PUBLIC_API(JSBool)
         428               0 : JS_FunctionHasLocalNames(JSContext *cx, JSFunction *fun)
         429                 : {
         430               0 :     return fun->script()->bindings.hasLocalNames();
         431                 : }
         432                 :
         433                 : extern JS_PUBLIC_API(uintptr_t *)
         434               0 : JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **markp)
         435                 : {
         436               0 :     Vector<JSAtom *> localNames(cx);
         437               0 :     if (!fun->script()->bindings.getLocalNameArray(cx, &localNames))
         438               0 :         return NULL;
         439                 :
         440                 :     /* Munge data into the API this method implements.  Avert your eyes! */
         441               0 :     *markp = cx->tempLifoAlloc().mark();
         442                 :
         443               0 :     uintptr_t *names = cx->tempLifoAlloc().newArray<uintptr_t>(localNames.length());
         444               0 :     if (!names) {
         445               0 :         js_ReportOutOfMemory(cx);
         446               0 :         return NULL;
         447                 :     }
         448                 :
         449                 :     JS_ASSERT(sizeof(*names) == sizeof(*localNames.begin()));
         450               0 :     js_memcpy(names, localNames.begin(), localNames.length() * sizeof(*names));
         451               0 :     return names;
         452                 : }
         453                 :
         454                 : extern JS_PUBLIC_API(JSAtom *)
         455               0 : JS_LocalNameToAtom(uintptr_t w)
         456                 : {
         457               0 :     return JS_LOCAL_NAME_TO_ATOM(w);
         458                 : }
         459                 :
         460                 : extern JS_PUBLIC_API(JSString *)
         461               0 : JS_AtomKey(JSAtom *atom)
         462                 : {
         463               0 :     return atom;
         464                 : }
         465                 :
         466                 : extern JS_PUBLIC_API(void)
         467               0 : JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mark)
         468                 : {
         469               0 :     cx->tempLifoAlloc().release(mark);
         470               0 : }
         471                 :
         472                 : JS_PUBLIC_API(JSScript *)
         473              44 : JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
         474                 : {
         475              44 :     return fun->maybeScript();
         476                 : }
         477                 :
         478                 : JS_PUBLIC_API(JSNative)
         479               0 : JS_GetFunctionNative(JSContext *cx, JSFunction *fun)
         480                 : {
         481               0 :     return fun->maybeNative();
         482                 : }
         483                 :
         484                 : JS_PUBLIC_API(JSPrincipals *)
         485              43 : JS_GetScriptPrincipals(JSScript *script)
         486                 : {
         487              43 :     return script->principals;
         488                 : }
         489                 :
         490                 : JS_PUBLIC_API(JSPrincipals *)
         491              40 : JS_GetScriptOriginPrincipals(JSScript *script)
         492                 : {
         493              40 :     return script->originPrincipals;
         494                 : }
         495                 :
         496                 : /************************************************************************/
         497                 :
         498                 : /*
         499                 :  *  Stack Frame Iterator
         500                 :  */
         501                 : JS_PUBLIC_API(JSStackFrame *)
         502               0 : JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp)
         503                 : {
         504               0 :     StackFrame *fp = Valueify(*iteratorp);
         505               0 :     *iteratorp = Jsvalify((fp == NULL) ? js_GetTopStackFrame(cx, FRAME_EXPAND_ALL) : fp->prev());
         506               0 :     return *iteratorp;
         507                 : }
         508                 :
         509                 : JS_PUBLIC_API(JSScript *)
         510               0 : JS_GetFrameScript(JSContext *cx, JSStackFrame *fp)
         511                 : {
         512               0 :     return Valueify(fp)->maybeScript();
         513                 : }
         514                 :
         515                 : JS_PUBLIC_API(jsbytecode *)
         516               0 : JS_GetFramePC(JSContext *cx, JSStackFrame *fp)
         517                 : {
         518               0 :     return Valueify(fp)->pcQuadratic(cx->stack);
         519                 : }
         520                 :
         521                 : JS_PUBLIC_API(void *)
         522               0 : JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fpArg)
         523                 : {
         524               0 :     StackFrame *fp = Valueify(fpArg);
         525               0 :     if (fp->annotation() && fp->isScriptFrame()) {
         526               0 :         JSPrincipals *principals = fp->scopeChain().principals(cx);
         527                 :
         528               0 :         if (principals) {
         529                 :             /*
         530                 :              * Give out an annotation only if privileges have not been revoked
         531                 :              * or disabled globally.
         532                 :              */
         533               0 :             return fp->annotation();
         534                 :         }
         535                 :     }
         536                 :
         537               0 :     return NULL;
         538                 : }
         539                 :
         540                 : JS_PUBLIC_API(void)
         541               0 : JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation)
         542                 : {
         543               0 :     Valueify(fp)->setAnnotation(annotation);
         544               0 : }
         545                 :
         546                 : JS_PUBLIC_API(JSBool)
         547               0 : JS_IsScriptFrame(JSContext *cx, JSStackFrame *fp)
         548                 : {
         549               0 :     return !Valueify(fp)->isDummyFrame();
         550                 : }
         551                 :
         552                 : JS_PUBLIC_API(JSObject *)
         553            2952 : JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fpArg)
         554                 : {
         555            2952 :     StackFrame *fp = Valueify(fpArg);
         556            2952 :     JS_ASSERT(cx->stack.containsSlow(fp));
         557                 :
         558            5904 :     js::AutoCompartment ac(cx, &fp->scopeChain());
         559            2952 :     if (!ac.enter())
         560               0 :         return NULL;
         561                 :
         562                 :     /* Force creation of argument and call objects if not yet created */
         563            2952 :     (void) JS_GetFrameCallObject(cx, Jsvalify(fp));
         564            2952 :     return GetScopeChain(cx, fp);
         565                 : }
         566                 :
         567                 : JS_PUBLIC_API(JSObject *)
         568            2952 : JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fpArg)
         569                 : {
         570            2952 :     StackFrame *fp = Valueify(fpArg);
         571            2952 :     JS_ASSERT(cx->stack.containsSlow(fp));
         572                 :
         573            2952 :     if (!fp->isFunctionFrame())
         574            1269 :         return NULL;
         575                 :
         576            3366 :     js::AutoCompartment ac(cx, &fp->scopeChain());
         577            1683 :     if (!ac.enter())
         578               0 :         return NULL;
         579                 :
         580                 :     /*
         581                 :      * XXX ill-defined: null return here means error was reported, unlike a
         582                 :      *     null returned above or in the #else
         583                 :      */
         584            1683 :     if (!fp->hasCallObj() && fp->isNonEvalFunctionFrame())
         585             639 :         return CallObject::createForFunction(cx, fp);
         586            1044 :     return &fp->callObj();
         587                 : }
         588                 :
         589                 : JS_PUBLIC_API(JSBool)
         590              58 : JS_GetFrameThis(JSContext *cx, JSStackFrame *fpArg, jsval *thisv)
         591                 : {
         592              58 :     StackFrame *fp = Valueify(fpArg);
         593              58 :     if (fp->isDummyFrame())
         594               0 :         return false;
         595                 :
         596             116 :     js::AutoCompartment ac(cx, &fp->scopeChain());
         597              58 :     if (!ac.enter())
         598               0 :         return false;
         599                 :
         600              58 :     if (!ComputeThis(cx, fp))
         601               0 :         return false;
         602              58 :     *thisv = fp->thisValue();
         603              58 :     return true;
         604                 : }
         605                 :
         606                 : JS_PUBLIC_API(JSFunction *)
         607               0 : JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp)
         608                 : {
         609               0 :     return Valueify(fp)->maybeScriptFunction();
         610                 : }
         611                 :
         612                 : JS_PUBLIC_API(JSObject *)
         613               0 : JS_GetFrameFunctionObject(JSContext *cx, JSStackFrame *fpArg)
         614                 : {
         615               0 :     StackFrame *fp = Valueify(fpArg);
         616               0 :     if (!fp->isFunctionFrame())
         617               0 :         return NULL;
         618                 :
         619               0 :     JS_ASSERT(fp->callee().isFunction());
         620               0 :     return &fp->callee();
         621                 : }
         622                 :
         623                 : JS_PUBLIC_API(JSFunction *)
         624               0 : JS_GetScriptFunction(JSContext *cx, JSScript *script)
         625                 : {
         626               0 :     return script->function();
         627                 : }
         628                 :
         629                 : JS_PUBLIC_API(JSObject *)
         630               0 : JS_GetParentOrScopeChain(JSContext *cx, JSObject *obj)
         631                 : {
         632               0 :     return obj->enclosingScope();
         633                 : }
         634                 :
         635                 : JS_PUBLIC_API(JSBool)
         636               0 : JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp)
         637                 : {
         638               0 :     return Valueify(fp)->isConstructing();
         639                 : }
         640                 :
         641                 : JS_PUBLIC_API(JSObject *)
         642               0 : JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp)
         643                 : {
         644               0 :     return Valueify(fp)->maybeCalleev().toObjectOrNull();
         645                 : }
         646                 :
         647                 : JS_PUBLIC_API(JSBool)
         648               0 : JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
         649                 : {
         650               0 :     return Valueify(fp)->isDebuggerFrame();
         651                 : }
         652                 :
         653                 : JS_PUBLIC_API(JSBool)
         654               0 : JS_IsGlobalFrame(JSContext *cx, JSStackFrame *fp)
         655                 : {
         656               0 :     return Valueify(fp)->isGlobalFrame();
         657                 : }
         658                 :
         659                 : JS_PUBLIC_API(jsval)
         660               0 : JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp)
         661                 : {
         662               0 :     return Valueify(fp)->returnValue();
         663                 : }
         664                 :
         665                 : JS_PUBLIC_API(void)
         666               0 : JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fpArg, jsval rval)
         667                 : {
         668               0 :     StackFrame *fp = Valueify(fpArg);
         669                 : #ifdef JS_METHODJIT
         670               0 :     JS_ASSERT_IF(fp->isScriptFrame(), fp->script()->debugMode);
         671                 : #endif
         672               0 :     assertSameCompartment(cx, fp, rval);
         673               0 :     fp->setReturnValue(rval);
         674               0 : }
         675                 :
         676                 : /************************************************************************/
         677                 :
         678                 : JS_PUBLIC_API(const char *)
         679               3 : JS_GetScriptFilename(JSContext *cx, JSScript *script)
         680                 : {
         681               3 :     return script->filename;
         682                 : }
         683                 :
         684                 : JS_PUBLIC_API(const jschar *)
         685               1 : JS_GetScriptSourceMap(JSContext *cx, JSScript *script)
         686                 : {
         687               1 :     return script->sourceMap;
         688                 : }
         689                 :
         690                 : JS_PUBLIC_API(unsigned)
         691               1 : JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script)
         692                 : {
         693               1 :     return script->lineno;
         694                 : }
         695                 :
         696                 : JS_PUBLIC_API(unsigned)
         697               1 : JS_GetScriptLineExtent(JSContext *cx, JSScript *script)
         698                 : {
         699               1 :     return js_GetScriptLineExtent(script);
         700                 : }
         701                 :
         702                 : JS_PUBLIC_API(JSVersion)
         703               0 : JS_GetScriptVersion(JSContext *cx, JSScript *script)
         704                 : {
         705               0 :     return VersionNumber(script->getVersion());
         706                 : }
         707                 :
         708                 : /***************************************************************************/
         709                 :
         710                 : JS_PUBLIC_API(void)
         711               0 : JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata)
         712                 : {
         713               0 :     rt->debugHooks.newScriptHook = hook;
         714               0 :     rt->debugHooks.newScriptHookData = callerdata;
         715               0 : }
         716                 :
         717                 : JS_PUBLIC_API(void)
         718               0 : JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
         719                 :                         void *callerdata)
         720                 : {
         721               0 :     rt->debugHooks.destroyScriptHook = hook;
         722               0 :     rt->debugHooks.destroyScriptHookData = callerdata;
         723               0 : }
         724                 :
         725                 : /***************************************************************************/
         726                 :
         727                 : JS_PUBLIC_API(JSBool)
         728             972 : JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fpArg,
         729                 :                           const jschar *chars, unsigned length,
         730                 :                           const char *filename, unsigned lineno,
         731                 :                           jsval *rval)
         732                 : {
         733             972 :     if (!CheckDebugMode(cx))
         734               0 :         return false;
         735                 :
         736             972 :     Env *env = JS_GetFrameScopeChain(cx, fpArg);
         737             972 :     if (!env)
         738               0 :         return false;
         739                 :
         740            1944 :     js::AutoCompartment ac(cx, env);
         741             972 :     if (!ac.enter())
         742               0 :         return false;
         743                 :
         744             972 :     StackFrame *fp = Valueify(fpArg);
         745             972 :     return EvaluateInEnv(cx, env, fp, chars, length, filename, lineno, rval);
         746                 : }
         747                 :
         748                 : JS_PUBLIC_API(JSBool)
         749               0 : JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
         750                 :                         const char *bytes, unsigned length,
         751                 :                         const char *filename, unsigned lineno,
         752                 :                         jsval *rval)
         753                 : {
         754                 :     jschar *chars;
         755                 :     JSBool ok;
         756               0 :     size_t len = length;
         757                 :
         758               0 :     if (!CheckDebugMode(cx))
         759               0 :         return JS_FALSE;
         760                 :
         761               0 :     chars = InflateString(cx, bytes, &len);
         762               0 :     if (!chars)
         763               0 :         return JS_FALSE;
         764               0 :     length = (unsigned) len;
         765                 :     ok = JS_EvaluateUCInStackFrame(cx, fp, chars, length, filename, lineno,
         766               0 :                                    rval);
         767               0 :     cx->free_(chars);
         768                 :
         769               0 :     return ok;
         770                 : }
         771                 :
         772                 : /************************************************************************/
         773                 :
         774                 : /* This all should be reworked to avoid requiring JSScopeProperty types. */
         775                 :
         776                 : JS_PUBLIC_API(JSScopeProperty *)
         777               3 : JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp)
         778                 : {
         779                 :     const Shape *shape;
         780                 :
         781                 :     /* The caller passes null in *iteratorp to get things started. */
         782               3 :     shape = (Shape *) *iteratorp;
         783               3 :     if (!shape)
         784               2 :         shape = obj->lastProperty();
         785                 :     else
         786               1 :         shape = shape->previous();
         787                 :
         788               3 :     if (!shape->previous()) {
         789               2 :         JS_ASSERT(shape->isEmptyShape());
         790               2 :         shape = NULL;
         791                 :     }
         792                 :
         793               3 :     return *iteratorp = reinterpret_cast<JSScopeProperty *>(const_cast<Shape *>(shape));
         794                 : }
         795                 :
         796                 : JS_PUBLIC_API(JSBool)
         797               1 : JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
         798                 :                    JSPropertyDesc *pd)
         799                 : {
         800               1 :     assertSameCompartment(cx, obj);
         801               1 :     Shape *shape = (Shape *) sprop;
         802               1 :     pd->id = IdToJsval(shape->propid());
         803                 :
         804               1 :     JSBool wasThrowing = cx->isExceptionPending();
         805               1 :     Value lastException = UndefinedValue();
         806               1 :     if (wasThrowing)
         807               0 :         lastException = cx->getPendingException();
         808               1 :     cx->clearPendingException();
         809                 :
         810               1 :     if (!js_GetProperty(cx, obj, shape->propid(), &pd->value)) {
         811               0 :         if (!cx->isExceptionPending()) {
         812               0 :             pd->flags = JSPD_ERROR;
         813               0 :             pd->value = JSVAL_VOID;
         814                 :         } else {
         815               0 :             pd->flags = JSPD_EXCEPTION;
         816               0 :             pd->value = cx->getPendingException();
         817                 :         }
         818                 :     } else {
         819               1 :         pd->flags = 0;
         820                 :     }
         821                 :
         822               1 :     if (wasThrowing)
         823               0 :         cx->setPendingException(lastException);
         824                 :
         825               1 :     pd->flags |= (shape->enumerable() ? JSPD_ENUMERATE : 0)
         826               1 :               |  (!shape->writable()  ? JSPD_READONLY  : 0)
         827               3 :               |  (!shape->configurable() ? JSPD_PERMANENT : 0);
         828               1 :     pd->spare = 0;
         829               1 :     if (shape->getter() == CallObject::getArgOp) {
         830               0 :         pd->slot = shape->shortid();
         831               0 :         pd->flags |= JSPD_ARGUMENT;
         832               1 :     } else if (shape->getter() == CallObject::getVarOp) {
         833               0 :         pd->slot = shape->shortid();
         834               0 :         pd->flags |= JSPD_VARIABLE;
         835                 :     } else {
         836               1 :         pd->slot = 0;
         837                 :     }
         838               1 :     pd->alias = JSVAL_VOID;
         839                 :
         840               1 :     return JS_TRUE;
         841                 : }
         842                 :
         843                 : JS_PUBLIC_API(JSBool)
         844               0 : JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
         845                 : {
         846               0 :     assertSameCompartment(cx, obj);
         847               0 :     Class *clasp = obj->getClass();
         848               0 :     if (!obj->isNative() || (clasp->flags & JSCLASS_NEW_ENUMERATE)) {
         849                 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
         850               0 :                              JSMSG_CANT_DESCRIBE_PROPS, clasp->name);
         851               0 :         return JS_FALSE;
         852                 :     }
         853               0 :     if (!clasp->enumerate(cx, obj))
         854               0 :         return JS_FALSE;
         855                 :
         856                 :     /* Return an empty pda early if obj has no own properties. */
         857               0 :     if (obj->nativeEmpty()) {
         858               0 :         pda->length = 0;
         859               0 :         pda->array = NULL;
         860               0 :         return JS_TRUE;
         861                 :     }
         862                 :
         863               0 :     uint32_t n = obj->propertyCount();
         864               0 :     JSPropertyDesc *pd = (JSPropertyDesc *) cx->malloc_(size_t(n) * sizeof(JSPropertyDesc));
         865               0 :     if (!pd)
         866               0 :         return JS_FALSE;
         867               0 :     uint32_t i = 0;
         868               0 :     for (Shape::Range r = obj->lastProperty()->all(); !r.empty(); r.popFront()) {
         869               0 :         if (!js_AddRoot(cx, &pd[i].id, NULL))
         870               0 :             goto bad;
         871               0 :         if (!js_AddRoot(cx, &pd[i].value, NULL))
         872               0 :             goto bad;
         873               0 :         Shape *shape = const_cast<Shape *>(&r.front());
         874               0 :         if (!JS_GetPropertyDesc(cx, obj, reinterpret_cast<JSScopeProperty *>(shape), &pd[i]))
         875               0 :             goto bad;
         876               0 :         if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL))
         877               0 :             goto bad;
         878               0 :         if (++i == n)
         879               0 :             break;
         880                 :     }
         881               0 :     pda->length = i;
         882               0 :     pda->array = pd;
         883               0 :     return JS_TRUE;
         884                 :
         885                 : bad:
         886               0 :     pda->length = i + 1;
         887               0 :     pda->array = pd;
         888               0 :     JS_PutPropertyDescArray(cx, pda);
         889               0 :     return JS_FALSE;
         890                 : }
         891                 :
         892                 : JS_PUBLIC_API(void)
         893               0 : JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
         894                 : {
         895                 :     JSPropertyDesc *pd;
         896                 :     uint32_t i;
         897                 :
         898               0 :     pd = pda->array;
         899               0 :     for (i = 0; i < pda->length; i++) {
         900               0 :         js_RemoveRoot(cx->runtime, &pd[i].id);
         901               0 :         js_RemoveRoot(cx->runtime, &pd[i].value);
         902               0 :         if (pd[i].flags & JSPD_ALIAS)
         903               0 :             js_RemoveRoot(cx->runtime, &pd[i].alias);
         904                 :     }
         905               0 :     cx->free_(pd);
         906               0 : }
         907                 :
         908                 : /************************************************************************/
         909                 :
         910                 : JS_PUBLIC_API(JSBool)
         911              18 : JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler handler, void *closure)
         912                 : {
         913              18 :     rt->debugHooks.debuggerHandler = handler;
         914              18 :     rt->debugHooks.debuggerHandlerData = closure;
         915              18 :     return JS_TRUE;
         916                 : }
         917                 :
         918                 : JS_PUBLIC_API(JSBool)
         919               0 : JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure)
         920                 : {
         921               0 :     rt->debugHooks.sourceHandler = handler;
         922               0 :     rt->debugHooks.sourceHandlerData = closure;
         923               0 :     return JS_TRUE;
         924                 : }
         925                 :
         926                 : JS_PUBLIC_API(JSBool)
         927               0 : JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
         928                 : {
         929               0 :     rt->debugHooks.executeHook = hook;
         930               0 :     rt->debugHooks.executeHookData = closure;
         931               0 :     return JS_TRUE;
         932                 : }
         933                 :
         934                 : JS_PUBLIC_API(JSBool)
         935               3 : JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
         936                 : {
         937               3 :     rt->debugHooks.callHook = hook;
         938               3 :     rt->debugHooks.callHookData = closure;
         939               3 :     return JS_TRUE;
         940                 : }
         941                 :
         942                 : JS_PUBLIC_API(JSBool)
         943              20 : JS_SetThrowHook(JSRuntime *rt, JSThrowHook hook, void *closure)
         944                 : {
         945              20 :     rt->debugHooks.throwHook = hook;
         946              20 :     rt->debugHooks.throwHookData = closure;
         947              20 :     return JS_TRUE;
         948                 : }
         949                 :
         950                 : JS_PUBLIC_API(JSBool)
         951               0 : JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure)
         952                 : {
         953               0 :     rt->debugHooks.debugErrorHook = hook;
         954               0 :     rt->debugHooks.debugErrorHookData = closure;
         955               0 :     return JS_TRUE;
         956                 : }
         957                 :
         958                 : /************************************************************************/
         959                 :
         960                 : JS_PUBLIC_API(size_t)
         961               0 : JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
         962                 : {
         963               0 :     return obj->computedSizeOfThisSlotsElements();
         964                 : }
         965                 :
         966                 : static size_t
         967               0 : GetAtomTotalSize(JSContext *cx, JSAtom *atom)
         968                 : {
         969                 :     return sizeof(AtomStateEntry) + sizeof(HashNumber) +
         970                 :            sizeof(JSString) +
         971               0 :            (atom->length() + 1) * sizeof(jschar);
         972                 : }
         973                 :
         974                 : JS_PUBLIC_API(size_t)
         975               0 : JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun)
         976                 : {
         977                 :     size_t nbytes;
         978                 :
         979               0 :     nbytes = sizeof *fun;
         980               0 :     nbytes += JS_GetObjectTotalSize(cx, fun);
         981               0 :     if (fun->isInterpreted())
         982               0 :         nbytes += JS_GetScriptTotalSize(cx, fun->script());
         983               0 :     if (fun->atom)
         984               0 :         nbytes += GetAtomTotalSize(cx, fun->atom);
         985               0 :     return nbytes;
         986                 : }
         987                 :
         988                 : JS_PUBLIC_API(size_t)
         989               0 : JS_GetScriptTotalSize(JSContext *cx, JSScript *script)
         990                 : {
         991                 :     size_t nbytes, pbytes;
         992                 :     jssrcnote *sn, *notes;
         993                 :     JSObjectArray *objarray;
         994                 :     JSPrincipals *principals;
         995                 :
         996               0 :     nbytes = sizeof *script;
         997               0 :     nbytes += script->length * sizeof script->code[0];
         998               0 :     nbytes += script->natoms * sizeof script->atoms[0];
         999               0 :     for (size_t i = 0; i < script->natoms; i++)
        1000               0 :         nbytes += GetAtomTotalSize(cx, script->atoms[i]);
        1001                 :
        1002               0 :     if (script->filename)
        1003               0 :         nbytes += strlen(script->filename) + 1;
        1004                 :
        1005               0 :     notes = script->notes();
        1006               0 :     for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
        1007               0 :         continue;
        1008               0 :     nbytes += (sn - notes + 1) * sizeof *sn;
        1009                 :
        1010               0 :     if (JSScript::isValidOffset(script->objectsOffset)) {
        1011               0 :         objarray = script->objects();
        1012               0 :         size_t i = objarray->length;
        1013               0 :         nbytes += sizeof *objarray + i * sizeof objarray->vector[0];
        1014               0 :         do {
        1015               0 :             nbytes += JS_GetObjectTotalSize(cx, objarray->vector[--i]);
        1016                 :         } while (i != 0);
        1017                 :     }
        1018                 :
        1019               0 :     if (JSScript::isValidOffset(script->regexpsOffset)) {
        1020               0 :         objarray = script->regexps();
        1021               0 :         size_t i = objarray->length;
        1022               0 :         nbytes += sizeof *objarray + i * sizeof objarray->vector[0];
        1023               0 :         do {
        1024               0 :             nbytes += JS_GetObjectTotalSize(cx, objarray->vector[--i]);
        1025                 :         } while (i != 0);
        1026                 :     }
        1027                 :
        1028               0 :     if (JSScript::isValidOffset(script->trynotesOffset)) {
        1029                 :         nbytes += sizeof(JSTryNoteArray) +
        1030               0 :             script->trynotes()->length * sizeof(JSTryNote);
        1031                 :     }
        1032                 :
        1033               0 :     principals = script->principals;
        1034               0 :     if (principals) {
        1035               0 :         JS_ASSERT(principals->refcount);
        1036               0 :         pbytes = sizeof *principals;
        1037               0 :         if (principals->refcount > 1)
        1038               0 :             pbytes = JS_HOWMANY(pbytes, principals->refcount);
        1039               0 :         nbytes += pbytes;
        1040                 :     }
        1041                 :
        1042               0 :     return nbytes;
        1043                 : }
        1044                 :
        1045                 : JS_PUBLIC_API(JSBool)
        1046               0 : JS_IsSystemObject(JSContext *cx, JSObject *obj)
        1047                 : {
        1048               0 :     return obj->isSystem();
        1049                 : }
        1050                 :
        1051                 : JS_PUBLIC_API(JSBool)
        1052               0 : JS_MakeSystemObject(JSContext *cx, JSObject *obj)
        1053                 : {
        1054               0 :     return obj->setSystem(cx);
        1055                 : }
        1056                 :
        1057                 : /************************************************************************/
        1058                 :
        1059                 : JS_FRIEND_API(void)
        1060              36 : js_RevertVersion(JSContext *cx)
        1061                 : {
        1062              36 :     cx->clearVersionOverride();
        1063              36 : }
        1064                 :
        1065                 : JS_PUBLIC_API(const JSDebugHooks *)
        1066               0 : JS_GetGlobalDebugHooks(JSRuntime *rt)
        1067                 : {
        1068               0 :     return &rt->debugHooks;
        1069                 : }
        1070                 :
        1071                 : /************************************************************************/
        1072                 :
        1073                 : /* Profiling-related API */
        1074                 :
        1075                 : /* Thread-unsafe error management */
        1076                 :
        1077                 : static char gLastError[2000];
        1078                 :
        1079                 : static void
        1080                 : #ifdef __GNUC__
        1081                 : __attribute__((unused,format(printf,1,2)))
        1082                 : #endif
        1083               0 : UnsafeError(const char *format, ...)
        1084                 : {
        1085                 :     va_list args;
        1086               0 :     va_start(args, format);
        1087               0 :     (void) vsnprintf(gLastError, sizeof(gLastError), format, args);
        1088               0 :     va_end(args);
        1089                 :
        1090               0 :     gLastError[sizeof(gLastError) - 1] = '\0';
        1091               0 : }
        1092                 :
        1093                 : JS_PUBLIC_API(const char *)
        1094               0 : JS_UnsafeGetLastProfilingError()
        1095                 : {
        1096               0 :     return gLastError;
        1097                 : }
        1098                 :
        1099                 : JS_PUBLIC_API(JSBool)
        1100               0 : JS_StartProfiling(const char *profileName)
        1101                 : {
        1102               0 :     JSBool ok = JS_TRUE;
        1103                 : #if defined(MOZ_SHARK) && defined(__APPLE__)
        1104                 :     if (!Shark::Start()) {
        1105                 :         UnsafeError("Failed to start Shark for %s", profileName);
        1106                 :         ok = JS_FALSE;
        1107                 :     }
        1108                 : #endif
        1109                 : #ifdef MOZ_VTUNE
        1110                 :     if (!js_StartVtune(profileName))
        1111                 :         ok = JS_FALSE;
        1112                 : #endif
        1113               0 :     return ok;
        1114                 : }
        1115                 :
        1116                 : JS_PUBLIC_API(JSBool)
        1117               0 : JS_StopProfiling(const char *profileName)
        1118                 : {
        1119               0 :     JSBool ok = JS_TRUE;
        1120                 : #if defined(MOZ_SHARK) && defined(__APPLE__)
        1121                 :     Shark::Stop();
        1122                 : #endif
        1123                 : #ifdef MOZ_VTUNE
        1124                 :     if (!js_StopVtune())
        1125                 :         ok = JS_FALSE;
        1126                 : #endif
        1127               0 :     return ok;
        1128                 : }
        1129                 :
        1130                 : /*
        1131                 :  * Start or stop whatever platform- and configuration-specific profiling
        1132                 :  * backends are available.
        1133                 :  */
        1134                 : static JSBool
        1135               0 : ControlProfilers(bool toState)
        1136                 : {
        1137               0 :     JSBool ok = JS_TRUE;
        1138                 :
        1139               0 :     if (! Probes::ProfilingActive && toState) {
        1140                 : #if defined(MOZ_SHARK) && defined(__APPLE__)
        1141                 :         if (!Shark::Start()) {
        1142                 :             UnsafeError("Failed to start Shark");
        1143                 :             ok = JS_FALSE;
        1144                 :         }
        1145                 : #endif
        1146                 : #ifdef MOZ_CALLGRIND
        1147                 :         if (! js_StartCallgrind()) {
        1148                 :             UnsafeError("Failed to start Callgrind");
        1149                 :             ok = JS_FALSE;
        1150                 :         }
        1151                 : #endif
        1152                 : #ifdef MOZ_VTUNE
        1153                 :         if (! js_ResumeVtune())
        1154                 :             ok = JS_FALSE;
        1155                 : #endif
        1156               0 :     } else if (Probes::ProfilingActive && ! toState) {
        1157                 : #if defined(MOZ_SHARK) && defined(__APPLE__)
        1158                 :         Shark::Stop();
        1159                 : #endif
        1160                 : #ifdef MOZ_CALLGRIND
        1161                 :         if (! js_StopCallgrind()) {
        1162                 :             UnsafeError("failed to stop Callgrind");
        1163                 :             ok = JS_FALSE;
        1164                 :         }
        1165                 : #endif
        1166                 : #ifdef MOZ_VTUNE
        1167                 :         if (! js_PauseVtune())
        1168                 :             ok = JS_FALSE;
        1169                 : #endif
        1170                 :     }
        1171                 :
        1172               0 :     Probes::ProfilingActive = toState;
        1173                 :
        1174               0 :     return ok;
        1175                 : }
        1176                 :
        1177                 : /*
        1178                 :  * Pause/resume whatever profiling mechanism is currently compiled
        1179                 :  * in, if applicable. This will not affect things like dtrace.
        1180                 :  *
        1181                 :  * Do not mix calls to these APIs with calls to the individual
        1182                 :  * profilers' pause/resume functions, because only overall state is
        1183                 :  * tracked, not the state of each profiler.
        1184                 :  */
        1185                 : JS_PUBLIC_API(JSBool)
        1186               0 : JS_PauseProfilers(const char *profileName)
        1187                 : {
        1188               0 :     return ControlProfilers(false);
        1189                 : }
        1190                 :
        1191                 : JS_PUBLIC_API(JSBool)
        1192               0 : JS_ResumeProfilers(const char *profileName)
        1193                 : {
        1194               0 :     return ControlProfilers(true);
        1195                 : }
        1196                 :
        1197                 : JS_PUBLIC_API(JSBool)
        1198               0 : JS_DumpProfile(const char *outfile, const char *profileName)
        1199                 : {
        1200               0 :     JSBool ok = JS_TRUE;
        1201                 : #ifdef MOZ_CALLGRIND
        1202                 :     js_DumpCallgrind(outfile);
        1203                 : #endif
        1204               0 :     return ok;
        1205                 : }
        1206                 :
        1207                 : #ifdef MOZ_PROFILING
        1208                 :
        1209                 : struct RequiredStringArg {
        1210                 :     JSContext *mCx;
        1211                 :     char *mBytes;
        1212                 :     RequiredStringArg(JSContext *cx, unsigned argc, jsval *vp, size_t argi, const char *caller)
        1213                 :         : mCx(cx), mBytes(NULL)
        1214                 :     {
        1215                 :         if (argc <= argi) {
        1216                 :             JS_ReportError(cx, "%s: not enough arguments", caller);
        1217                 :         } else if (!JSVAL_IS_STRING(JS_ARGV(cx, vp)[argi])) {
        1218                 :             JS_ReportError(cx, "%s: invalid arguments (string expected)", caller);
        1219                 :         } else {
        1220                 :             mBytes = JS_EncodeString(cx, JSVAL_TO_STRING(JS_ARGV(cx, vp)[argi]));
        1221                 :         }
        1222                 :     }
        1223                 :     operator void*() {
        1224                 :         return (void*) mBytes;
        1225                 :     }
        1226                 :     ~RequiredStringArg() {
        1227                 :         if (mBytes)
        1228                 :             mCx->free_(mBytes);
        1229                 :     }
        1230                 : };
        1231                 :
        1232                 : static JSBool
        1233                 : StartProfiling(JSContext *cx, unsigned argc, jsval *vp)
        1234                 : {
        1235                 :     if (argc == 0) {
        1236                 :         JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_StartProfiling(NULL)));
        1237                 :         return JS_TRUE;
        1238                 :     }
        1239                 :
        1240                 :     RequiredStringArg profileName(cx, argc, vp, 0, "startProfiling");
        1241                 :     if (!profileName)
        1242                 :         return JS_FALSE;
        1243                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_StartProfiling(profileName.mBytes)));
        1244                 :     return JS_TRUE;
        1245                 : }
        1246                 :
        1247                 : static JSBool
        1248                 : StopProfiling(JSContext *cx, unsigned argc, jsval *vp)
        1249                 : {
        1250                 :     if (argc == 0) {
        1251                 :         JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_StopProfiling(NULL)));
        1252                 :         return JS_TRUE;
        1253                 :     }
        1254                 :
        1255                 :     RequiredStringArg profileName(cx, argc, vp, 0, "stopProfiling");
        1256                 :     if (!profileName)
        1257                 :         return JS_FALSE;
        1258                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_StopProfiling(profileName.mBytes)));
        1259                 :     return JS_TRUE;
        1260                 : }
        1261                 :
        1262                 : static JSBool
        1263                 : PauseProfilers(JSContext *cx, unsigned argc, jsval *vp)
        1264                 : {
        1265                 :     if (argc == 0) {
        1266                 :         JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_PauseProfilers(NULL)));
        1267                 :         return JS_TRUE;
        1268                 :     }
        1269                 :
        1270                 :     RequiredStringArg profileName(cx, argc, vp, 0, "pauseProfiling");
        1271                 :     if (!profileName)
        1272                 :         return JS_FALSE;
        1273                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_PauseProfilers(profileName.mBytes)));
        1274                 :     return JS_TRUE;
        1275                 : }
        1276                 :
        1277                 : static JSBool
        1278                 : ResumeProfilers(JSContext *cx, unsigned argc, jsval *vp)
        1279                 : {
        1280                 :     if (argc == 0) {
        1281                 :         JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_ResumeProfilers(NULL)));
        1282                 :         return JS_TRUE;
        1283                 :     }
        1284                 :
        1285                 :     RequiredStringArg profileName(cx, argc, vp, 0, "resumeProfiling");
        1286                 :     if (!profileName)
        1287                 :         return JS_FALSE;
        1288                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_ResumeProfilers(profileName.mBytes)));
        1289                 :     return JS_TRUE;
        1290                 : }
        1291                 :
        1292                 : /* Usage: DumpProfile([filename[, profileName]]) */
        1293                 : static JSBool
        1294                 : DumpProfile(JSContext *cx, unsigned argc, jsval *vp)
        1295                 : {
        1296                 :     bool ret;
        1297                 :     if (argc == 0) {
        1298                 :         ret = JS_DumpProfile(NULL, NULL);
        1299                 :     } else {
        1300                 :         RequiredStringArg filename(cx, argc, vp, 0, "dumpProfile");
        1301                 :         if (!filename)
        1302                 :             return JS_FALSE;
        1303                 :
        1304                 :         if (argc == 1) {
        1305                 :             ret = JS_DumpProfile(filename.mBytes, NULL);
        1306                 :         } else {
        1307                 :             RequiredStringArg profileName(cx, argc, vp, 1, "dumpProfile");
        1308                 :             if (!profileName)
        1309                 :                 return JS_FALSE;
        1310                 :
        1311                 :             ret = JS_DumpProfile(filename.mBytes, profileName.mBytes);
        1312                 :         }
        1313                 :     }
        1314                 :
        1315                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(ret));
        1316                 :     return true;
        1317                 : }
        1318                 :
        1319                 : #ifdef MOZ_SHARK
        1320                 :
        1321                 : static JSBool
        1322                 : IgnoreAndReturnTrue(JSContext *cx, unsigned argc, jsval *vp)
        1323                 : {
        1324                 :     JS_SET_RVAL(cx, vp, JSVAL_TRUE);
        1325                 :     return true;
        1326                 : }
        1327                 :
        1328                 : #endif
        1329                 :
        1330                 : #ifdef MOZ_CALLGRIND
        1331                 : static JSBool
        1332                 : StartCallgrind(JSContext *cx, unsigned argc, jsval *vp)
        1333                 : {
        1334                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_StartCallgrind()));
        1335                 :     return JS_TRUE;
        1336                 : }
        1337                 :
        1338                 : static JSBool
        1339                 : StopCallgrind(JSContext *cx, unsigned argc, jsval *vp)
        1340                 : {
        1341                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_StopCallgrind()));
        1342                 :     return JS_TRUE;
        1343                 : }
        1344                 :
        1345                 : static JSBool
        1346                 : DumpCallgrind(JSContext *cx, unsigned argc, jsval *vp)
        1347                 : {
        1348                 :     if (argc == 0) {
        1349                 :         JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_DumpCallgrind(NULL)));
        1350                 :         return JS_TRUE;
        1351                 :     }
        1352                 :
        1353                 :     RequiredStringArg outFile(cx, argc, vp, 0, "dumpCallgrind");
        1354                 :     if (!outFile)
        1355                 :         return JS_FALSE;
        1356                 :
        1357                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_DumpCallgrind(outFile.mBytes)));
        1358                 :     return JS_TRUE;
        1359                 : }
        1360                 : #endif
        1361                 :
        1362                 : #ifdef MOZ_VTUNE
        1363                 : static JSBool
        1364                 : StartVtune(JSContext *cx, unsigned argc, jsval *vp)
        1365                 : {
        1366                 :     RequiredStringArg profileName(cx, argc, vp, 0, "startVtune");
        1367                 :     if (!profileName)
        1368                 :         return JS_FALSE;
        1369                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_StartVtune(profileName.mBytes)));
        1370                 :     return JS_TRUE;
        1371                 : }
        1372                 :
        1373                 : static JSBool
        1374                 : StopVtune(JSContext *cx, unsigned argc, jsval *vp)
        1375                 : {
        1376                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_StopVtune()));
        1377                 :     return JS_TRUE;
        1378                 : }
        1379                 :
        1380                 : static JSBool
        1381                 : PauseVtune(JSContext *cx, unsigned argc, jsval *vp)
        1382                 : {
        1383                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_PauseVtune()));
        1384                 :     return JS_TRUE;
        1385                 : }
        1386                 :
        1387                 : static JSBool
        1388                 : ResumeVtune(JSContext *cx, unsigned argc, jsval *vp)
        1389                 : {
        1390                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_ResumeVtune()));
        1391                 :     return JS_TRUE;
        1392                 : }
        1393                 : #endif
        1394                 :
        1395                 : static JSFunctionSpec profiling_functions[] = {
        1396                 :     JS_FN("startProfiling",  StartProfiling,      1,0),
        1397                 :     JS_FN("stopProfiling",   StopProfiling,       1,0),
        1398                 :     JS_FN("pauseProfilers",  PauseProfilers,      1,0),
        1399                 :     JS_FN("resumeProfilers", ResumeProfilers,     1,0),
        1400                 :     JS_FN("dumpProfile",     DumpProfile,         2,0),
        1401                 : #ifdef MOZ_SHARK
        1402                 :     /* Keep users of the old shark API happy. */
        1403                 :     JS_FN("connectShark",    IgnoreAndReturnTrue, 0,0),
        1404                 :     JS_FN("disconnectShark", IgnoreAndReturnTrue, 0,0),
        1405                 :     JS_FN("startShark",      StartProfiling,      0,0),
        1406                 :     JS_FN("stopShark",       StopProfiling,       0,0),
        1407                 : #endif
        1408                 : #ifdef MOZ_CALLGRIND
        1409                 :     JS_FN("startCallgrind", StartCallgrind,       0,0),
        1410                 :     JS_FN("stopCallgrind",  StopCallgrind,        0,0),
        1411                 :     JS_FN("dumpCallgrind",  DumpCallgrind,        1,0),
        1412                 : #endif
        1413                 : #ifdef MOZ_VTUNE
        1414                 :     JS_FN("startVtune",     js_StartVtune,        1,0),
        1415                 :     JS_FN("stopVtune",      js_StopVtune,         0,0),
        1416                 :     JS_FN("pauseVtune",     js_PauseVtune,        0,0),
        1417                 :     JS_FN("resumeVtune",    js_ResumeVtune,       0,0),
        1418                 : #endif
        1419                 :     JS_FS_END
        1420                 : };
        1421                 :
        1422                 : #endif
        1423                 :
        1424                 : JS_PUBLIC_API(JSBool)
        1425           23328 : JS_DefineProfilingFunctions(JSContext *cx, JSObject *obj)
        1426                 : {
        1427           23328 :     assertSameCompartment(cx, obj);
        1428                 : #ifdef MOZ_PROFILING
        1429                 :     return JS_DefineFunctions(cx, obj, profiling_functions);
        1430                 : #else
        1431           23328 :     return true;
        1432                 : #endif
        1433                 : }
        1434                 :
        1435                 : #ifdef MOZ_CALLGRIND
        1436                 :
        1437                 : #include <valgrind/callgrind.h>
        1438                 :
        1439                 : JS_FRIEND_API(JSBool)
        1440                 : js_StartCallgrind()
        1441                 : {
        1442                 :     JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_START_INSTRUMENTATION);
        1443                 :     JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_ZERO_STATS);
        1444                 :     return true;
        1445                 : }
        1446                 :
        1447                 : JS_FRIEND_API(JSBool)
        1448                 : js_StopCallgrind()
        1449                 : {
        1450                 :     JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_STOP_INSTRUMENTATION);
        1451                 :     return true;
        1452                 : }
        1453                 :
        1454                 : JS_FRIEND_API(JSBool)
        1455                 : js_DumpCallgrind(const char *outfile)
        1456                 : {
        1457                 :     if (outfile) {
        1458                 :         JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_DUMP_STATS_AT(outfile));
        1459                 :     } else {
        1460                 :         JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_DUMP_STATS);
        1461                 :     }
        1462                 :
        1463                 :     return true;
        1464                 : }
        1465                 :
        1466                 : #endif /* MOZ_CALLGRIND */
        1467                 :
        1468                 : #ifdef MOZ_VTUNE
        1469                 : #include <VTuneApi.h>
        1470                 :
        1471                 : static const char *vtuneErrorMessages[] = {
        1472                 :   "unknown, error #0",
        1473                 :   "invalid 'max samples' field",
        1474                 :   "invalid 'samples per buffer' field",
        1475                 :   "invalid 'sample interval' field",
        1476                 :   "invalid path",
        1477                 :   "sample file in use",
        1478                 :   "invalid 'number of events' field",
        1479                 :   "unknown, error #7",
        1480                 :   "internal error",
        1481                 :   "bad event name",
        1482                 :   "VTStopSampling called without calling VTStartSampling",
        1483                 :   "no events selected for event-based sampling",
        1484                 :   "events selected cannot be run together",
        1485                 :   "no sampling parameters",
        1486                 :   "sample database already exists",
        1487                 :   "sampling already started",
        1488                 :   "time-based sampling not supported",
        1489                 :   "invalid 'sampling parameters size' field",
        1490                 :   "invalid 'event size' field",
        1491                 :   "sampling file already bound",
        1492                 :   "invalid event path",
        1493                 :   "invalid license",
        1494                 :   "invalid 'global options' field",
        1495                 :
        1496                 : };
        1497                 :
        1498                 : bool
        1499                 : js_StartVtune(const char *profileName)
        1500                 : {
        1501                 :     VTUNE_EVENT events[] = {
        1502                 :         { 1000000, 0, 0, 0, "CPU_CLK_UNHALTED.CORE" },
        1503                 :         { 1000000, 0, 0, 0, "INST_RETIRED.ANY" },
        1504                 :     };
        1505                 :
        1506                 :     U32 n_events = sizeof(events) / sizeof(VTUNE_EVENT);
        1507                 :     char *default_filename = "mozilla-vtune.tb5";
        1508                 :     JSString *str;
        1509                 :     U32 status;
        1510                 :
        1511                 :     VTUNE_SAMPLING_PARAMS params = {
        1512                 :         sizeof(VTUNE_SAMPLING_PARAMS),
        1513                 :         sizeof(VTUNE_EVENT),
        1514                 :         0, 0, /* Reserved fields */
        1515                 :         1,    /* Initialize in "paused" state */
        1516                 :         0,    /* Max samples, or 0 for "continuous" */
        1517                 :         4096, /* Samples per buffer */
        1518                 :         0.1,  /* Sampling interval in ms */
        1519                 :         1,    /* 1 for event-based sampling, 0 for time-based */
        1520                 :
        1521                 :         n_events,
        1522                 :         events,
        1523                 :         default_filename,
        1524                 :     };
        1525                 :
        1526                 :     if (profileName) {
        1527                 :         char filename[strlen(profileName) + strlen("-vtune.tb5") + 1];
        1528                 :         snprintf(filename, sizeof(filename), "%s-vtune.tb5", profileName);
        1529                 :         params.tb5Filename = filename;
        1530                 :     }
        1531                 :
        1532                 :     status = VTStartSampling(&params);
        1533                 :
        1534                 :     if (params.tb5Filename != default_filename)
        1535                 :         Foreground::free_(params.tb5Filename);
        1536                 :
        1537                 :     if (status != 0) {
        1538                 :         if (status == VTAPI_MULTIPLE_RUNS)
        1539                 :             VTStopSampling(0);
        1540                 :         if (status < sizeof(vtuneErrorMessages))
        1541                 :             UnsafeError("Vtune setup error: %s", vtuneErrorMessages[status]);
        1542                 :         else
        1543                 :             UnsafeError("Vtune setup error: %d", status);
        1544                 :         return false;
        1545                 :     }
        1546                 :     return true;
        1547                 : }
        1548                 :
        1549                 : bool
        1550                 : js_StopVtune()
        1551                 : {
        1552                 :     U32 status = VTStopSampling(1);
        1553                 :     if (status) {
        1554                 :         if (status < sizeof(vtuneErrorMessages))
        1555                 :             UnsafeError("Vtune shutdown error: %s", vtuneErrorMessages[status]);
        1556                 :         else
        1557                 :             UnsafeError("Vtune shutdown error: %d", status);
        1558                 :         return false;
        1559                 :     }
        1560                 :     return true;
        1561                 : }
        1562                 :
        1563                 : bool
        1564                 : js_PauseVtune()
        1565                 : {
        1566                 :     VTPause();
        1567                 :     return true;
        1568                 : }
        1569                 :
        1570                 : bool
        1571                 : js_ResumeVtune()
        1572                 : {
        1573                 :     VTResume();
        1574                 :     return true;
        1575                 : }
        1576                 :
        1577                 : #endif /* MOZ_VTUNE */
        1578                 :
        1579                 : JS_PUBLIC_API(void)
        1580               0 : JS_DumpBytecode(JSContext *cx, JSScript *script)
        1581                 : {
        1582                 : #if defined(DEBUG)
        1583               0 :     Sprinter sprinter(cx);
        1584               0 :     if (!sprinter.init())
        1585                 :         return;
        1586                 :
        1587               0 :     fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename, script->lineno);
        1588               0 :     js_Disassemble(cx, script, true, &sprinter);
        1589               0 :     fputs(sprinter.string(), stdout);
        1590               0 :     fprintf(stdout, "--- END SCRIPT %s:%d ---\n", script->filename, script->lineno);
        1591                 : #endif
        1592                 : }
        1593                 :
        1594                 : extern JS_PUBLIC_API(void)
        1595               0 : JS_DumpPCCounts(JSContext *cx, JSScript *script)
        1596                 : {
        1597                 : #if defined(DEBUG)
        1598               0 :     JS_ASSERT(script->scriptCounts);
        1599                 :
        1600               0 :     Sprinter sprinter(cx);
        1601               0 :     if (!sprinter.init())
        1602                 :         return;
        1603                 :
        1604               0 :     fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename, script->lineno);
        1605               0 :     js_DumpPCCounts(cx, script, &sprinter);
        1606               0 :     fputs(sprinter.string(), stdout);
        1607               0 :     fprintf(stdout, "--- END SCRIPT %s:%d ---\n", script->filename, script->lineno);
        1608                 : #endif
        1609                 : }
        1610                 :
        1611                 : namespace {
        1612                 :
        1613                 : typedef Vector<JSScript *, 0, SystemAllocPolicy> ScriptsToDump;
        1614                 :
        1615                 : static void
        1616               0 : DumpBytecodeScriptCallback(JSRuntime *rt, void *data, void *thing,
        1617                 :                            JSGCTraceKind traceKind, size_t thingSize)
        1618                 : {
        1619               0 :     JS_ASSERT(traceKind == JSTRACE_SCRIPT);
        1620               0 :     JSScript *script = static_cast<JSScript *>(thing);
        1621               0 :     static_cast<ScriptsToDump *>(data)->append(script);
        1622               0 : }
        1623                 :
        1624                 : } /* anonymous namespace */
        1625                 :
        1626                 : JS_PUBLIC_API(void)
        1627               0 : JS_DumpCompartmentBytecode(JSContext *cx)
        1628                 : {
        1629               0 :     ScriptsToDump scripts;
        1630               0 :     IterateCells(cx->runtime, cx->compartment, gc::FINALIZE_SCRIPT, &scripts, DumpBytecodeScriptCallback);
        1631                 :
        1632               0 :     for (size_t i = 0; i < scripts.length(); i++)
        1633               0 :         JS_DumpBytecode(cx, scripts[i]);
        1634               0 : }
        1635                 :
        1636                 : JS_PUBLIC_API(void)
        1637               0 : JS_DumpCompartmentPCCounts(JSContext *cx)
        1638                 : {
        1639               0 :     for (CellIter i(cx->compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
        1640               0 :         JSScript *script = i.get<JSScript>();
        1641               0 :         if (script->scriptCounts)
        1642               0 :             JS_DumpPCCounts(cx, script);
        1643                 :     }
        1644               0 : }
        1645                 :
        1646                 : JS_PUBLIC_API(JSObject *)
        1647             666 : JS_UnwrapObject(JSObject *obj)
        1648                 : {
        1649             666 :     return UnwrapObject(obj);
        1650                 : }
        1651                 :
        1652                 : JS_FRIEND_API(JSBool)
        1653               0 : js_CallContextDebugHandler(JSContext *cx)
        1654                 : {
        1655               0 :     FrameRegsIter iter(cx);
        1656               0 :     JS_ASSERT(!iter.done());
        1657                 :
        1658                 :     jsval rval;
        1659               0 :     switch (js::CallContextDebugHandler(cx, iter.script(), iter.pc(), &rval)) {
        1660                 :       case JSTRAP_ERROR:
        1661               0 :         JS_ClearPendingException(cx);
        1662               0 :         return JS_FALSE;
        1663                 :       case JSTRAP_THROW:
        1664               0 :         JS_SetPendingException(cx, rval);
        1665               0 :         return JS_FALSE;
        1666                 :       case JSTRAP_RETURN:
        1667                 :       case JSTRAP_CONTINUE:
        1668                 :       default:
        1669               0 :         return JS_TRUE;
        1670                 :     }
        1671                 : }
        1672                 :

Generated by: LCOV version 1.7