LCOV - code coverage report
Current view: directory - js/src - jsdbgapi.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 560 286 51.1 %
Date: 2012-06-02 Functions: 95 55 57.9 %

       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            1350 : JS_GetDebugMode(JSContext *cx)
      92                 : {
      93            1350 :     return cx->compartment->debugMode();
      94                 : }
      95                 : 
      96                 : JS_PUBLIC_API(JSBool)
      97            6852 : JS_SetDebugMode(JSContext *cx, JSBool debug)
      98                 : {
      99            6852 :     return JS_SetDebugModeForCompartment(cx, cx->compartment, debug);
     100                 : }
     101                 : 
     102                 : JS_PUBLIC_API(void)
     103            6847 : JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug)
     104                 : {
     105            6847 :     rt->debugMode = !!debug;
     106            6847 : }
     107                 : 
     108                 : namespace js {
     109                 : 
     110                 : JSTrapStatus
     111        15284752 : ScriptDebugPrologue(JSContext *cx, StackFrame *fp)
     112                 : {
     113        15284752 :     JS_ASSERT(fp == cx->fp());
     114                 : 
     115        15284752 :     if (fp->isFramePushedByExecute()) {
     116           63600 :         if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
     117            5101 :             fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->runtime->debugHooks.executeHookData));
     118                 :     } else {
     119        15221152 :         if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
     120         2895817 :             fp->setHookData(hook(cx, Jsvalify(fp), true, 0, cx->runtime->debugHooks.callHookData));
     121                 :     }
     122                 : 
     123                 :     Value rval;
     124        15284752 :     JSTrapStatus status = Debugger::onEnterFrame(cx, &rval);
     125        15284752 :     switch (status) {
     126                 :       case JSTRAP_CONTINUE:
     127        15282631 :         break;
     128                 :       case JSTRAP_THROW:
     129              27 :         cx->setPendingException(rval);
     130              27 :         break;
     131                 :       case JSTRAP_ERROR:
     132            2049 :         cx->clearPendingException();
     133            2049 :         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        15284752 :     return status;
     141                 : }
     142                 : 
     143                 : bool
     144        15285465 : ScriptDebugEpilogue(JSContext *cx, StackFrame *fp, bool okArg)
     145                 : {
     146        15285465 :     JS_ASSERT(fp == cx->fp());
     147        15285465 :     JSBool ok = okArg;
     148                 : 
     149        15285465 :     if (void *hookData = fp->maybeHookData()) {
     150         2900900 :         if (fp->isFramePushedByExecute()) {
     151            5101 :             if (JSInterpreterHook hook = cx->runtime->debugHooks.executeHook)
     152            5101 :                 hook(cx, Jsvalify(fp), false, &ok, hookData);
     153                 :         } else {
     154         2895799 :             if (JSInterpreterHook hook = cx->runtime->debugHooks.callHook)
     155         2895799 :                 hook(cx, Jsvalify(fp), false, &ok, hookData);
     156                 :         }
     157                 :     }
     158                 : 
     159        15285465 :     return Debugger::onLeaveFrame(cx, ok);
     160                 : }
     161                 : 
     162                 : } /* namespace js */
     163                 : 
     164                 : JS_FRIEND_API(JSBool)
     165            7413 : JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, JSBool debug)
     166                 : {
     167            7413 :     return comp->setDebugModeFromC(cx, !!debug);
     168                 : }
     169                 : 
     170                 : static JSBool
     171            1350 : CheckDebugMode(JSContext *cx)
     172                 : {
     173            1350 :     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            1350 :     if (!debugMode) {
     180                 :         JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
     181               0 :                                      NULL, JSMSG_NEED_DEBUG_MODE);
     182                 :     }
     183            1350 :     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             377 : JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc, JSTrapHandler handler, jsval closure)
     198                 : {
     199             377 :     assertSameCompartment(cx, script, closure);
     200                 : 
     201             377 :     if (!CheckDebugMode(cx))
     202               0 :         return false;
     203                 : 
     204             377 :     BreakpointSite *site = script->getOrCreateBreakpointSite(cx, pc, NULL);
     205             377 :     if (!site)
     206               0 :         return false;
     207             377 :     site->setTrap(cx, handler, closure);
     208             377 :     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, 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         1741059 : JS_ClearScriptTraps(JSContext *cx, JSScript *script)
     227                 : {
     228         1741059 :     script->clearTraps(cx);
     229         1741059 : }
     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             282 : JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *hoop, void **closurep)
     247                 : {
     248             282 :     if (hoop)
     249               0 :         *hoop = rt->debugHooks.interruptHook;
     250             282 :     if (closurep)
     251               0 :         *closurep = rt->debugHooks.interruptHookData;
     252             282 :     rt->debugHooks.interruptHook = 0;
     253             282 :     rt->debugHooks.interruptHookData = 0;
     254             282 :     return JS_TRUE;
     255                 : }
     256                 : 
     257                 : /************************************************************************/
     258                 : 
     259                 : JS_PUBLIC_API(JSBool)
     260            3630 : JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id,
     261                 :                  JSWatchPointHandler handler, JSObject *closure)
     262                 : {
     263            3630 :     assertSameCompartment(cx, obj);
     264            3630 :     id = js_CheckForStringIndex(id);
     265                 : 
     266                 :     JSObject *origobj;
     267                 :     Value v;
     268                 :     unsigned attrs;
     269                 :     jsid propid;
     270                 : 
     271            3630 :     origobj = obj;
     272            3630 :     OBJ_TO_INNER_OBJECT(cx, obj);
     273            3630 :     if (!obj)
     274               0 :         return false;
     275                 : 
     276            7260 :     AutoValueRooter idroot(cx);
     277            3630 :     if (JSID_IS_INT(id)) {
     278               0 :         propid = id;
     279            3630 :     } 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            3630 :         if (!js_ValueToStringId(cx, IdToValue(id), &propid))
     284               0 :             return false;
     285            3630 :         propid = js_CheckForStringIndex(propid);
     286            3630 :         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            3630 :     if (origobj != obj && !CheckAccess(cx, obj, propid, JSACC_WATCH, &v, &attrs))
     294               0 :         return false;
     295                 : 
     296            3630 :     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            3630 :     types::MarkTypePropertyConfigured(cx, obj, propid);
     303                 : 
     304            3630 :     WatchpointMap *wpmap = cx->compartment->watchpointMap;
     305            3630 :     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            3630 :     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           19908 : JS_ClearAllWatchPoints(JSContext *cx)
     340                 : {
     341           19908 :     if (JSCompartment *comp = cx->compartment) {
     342           18505 :         if (WatchpointMap *wpmap = comp->watchpointMap)
     343             216 :             wpmap->clear();
     344                 :     }
     345           19908 :     return true;
     346                 : }
     347                 : 
     348                 : /************************************************************************/
     349                 : 
     350                 : JS_PUBLIC_API(unsigned)
     351         1498606 : JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
     352                 : {
     353         1498606 :     return js::PCToLineNumber(script, pc);
     354                 : }
     355                 : 
     356                 : JS_PUBLIC_API(jsbytecode *)
     357              18 : JS_LineNumberToPC(JSContext *cx, JSScript *script, unsigned lineno)
     358                 : {
     359              18 :     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         1867666 : JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
     474                 : {
     475         1867666 :     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          230417 : JS_GetScriptPrincipals(JSContext *cx, JSScript *script)
     486                 : {
     487          230417 :     return script->principals;
     488                 : }
     489                 : 
     490                 : JS_PUBLIC_API(JSPrincipals *)
     491              40 : JS_GetScriptOriginPrincipals(JSContext *cx, JSScript *script)
     492                 : {
     493              40 :     return script->originPrincipals;
     494                 : }
     495                 : 
     496                 : /************************************************************************/
     497                 : 
     498                 : /*
     499                 :  *  Stack Frame Iterator
     500                 :  */
     501                 : JS_PUBLIC_API(JSStackFrame *)
     502         5042415 : JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp)
     503                 : {
     504         5042415 :     StackFrame *fp = Valueify(*iteratorp);
     505         5042415 :     *iteratorp = Jsvalify((fp == NULL) ? js_GetTopStackFrame(cx, FRAME_EXPAND_ALL) : fp->prev());
     506         5042415 :     return *iteratorp;
     507                 : }
     508                 : 
     509                 : JS_PUBLIC_API(JSScript *)
     510         3595737 : JS_GetFrameScript(JSContext *cx, JSStackFrame *fp)
     511                 : {
     512         3595737 :     return Valueify(fp)->maybeScript();
     513                 : }
     514                 : 
     515                 : JS_PUBLIC_API(jsbytecode *)
     516         1496576 : JS_GetFramePC(JSContext *cx, JSStackFrame *fp)
     517                 : {
     518         1496576 :     return Valueify(fp)->pcQuadratic(cx->stack);
     519                 : }
     520                 : 
     521                 : JS_PUBLIC_API(void *)
     522          410104 : JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fpArg)
     523                 : {
     524          410104 :     StackFrame *fp = Valueify(fpArg);
     525          410104 :     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          410104 :     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         1505742 : JS_IsScriptFrame(JSContext *cx, JSStackFrame *fp)
     548                 : {
     549         1505742 :     return !Valueify(fp)->isDummyFrame();
     550                 : }
     551                 : 
     552                 : JS_PUBLIC_API(JSObject *)
     553            2950 : JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fpArg)
     554                 : {
     555            2950 :     StackFrame *fp = Valueify(fpArg);
     556            2950 :     JS_ASSERT(cx->stack.containsSlow(fp));
     557                 : 
     558            5900 :     js::AutoCompartment ac(cx, &fp->scopeChain());
     559            2950 :     if (!ac.enter())
     560               0 :         return NULL;
     561                 : 
     562                 :     /* Force creation of argument and call objects if not yet created */
     563            2950 :     (void) JS_GetFrameCallObject(cx, Jsvalify(fp));
     564            2950 :     return GetScopeChain(cx, fp);
     565                 : }
     566                 : 
     567                 : JS_PUBLIC_API(JSObject *)
     568            3346 : JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fpArg)
     569                 : {
     570            3346 :     StackFrame *fp = Valueify(fpArg);
     571            3346 :     JS_ASSERT(cx->stack.containsSlow(fp));
     572                 : 
     573            3346 :     if (!fp->isFunctionFrame())
     574            1312 :         return NULL;
     575                 : 
     576            4068 :     js::AutoCompartment ac(cx, &fp->scopeChain());
     577            2034 :     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            2034 :     if (!fp->hasCallObj() && fp->isNonEvalFunctionFrame())
     585             865 :         return CallObject::createForFunction(cx, fp);
     586            1169 :     return &fp->callObj();
     587                 : }
     588                 : 
     589                 : JS_PUBLIC_API(JSBool)
     590             475 : JS_GetFrameThis(JSContext *cx, JSStackFrame *fpArg, jsval *thisv)
     591                 : {
     592             475 :     StackFrame *fp = Valueify(fpArg);
     593             475 :     if (fp->isDummyFrame())
     594               0 :         return false;
     595                 : 
     596             950 :     js::AutoCompartment ac(cx, &fp->scopeChain());
     597             475 :     if (!ac.enter())
     598               0 :         return false;
     599                 : 
     600             475 :     if (!ComputeThis(cx, fp))
     601               0 :         return false;
     602             475 :     *thisv = fp->thisValue();
     603             475 :     return true;
     604                 : }
     605                 : 
     606                 : JS_PUBLIC_API(JSFunction *)
     607         1496506 : JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp)
     608                 : {
     609         1496506 :     return Valueify(fp)->maybeScriptFunction();
     610                 : }
     611                 : 
     612                 : JS_PUBLIC_API(JSObject *)
     613         2098452 : JS_GetFrameFunctionObject(JSContext *cx, JSStackFrame *fpArg)
     614                 : {
     615         2098452 :     StackFrame *fp = Valueify(fpArg);
     616         2098452 :     if (!fp->isFunctionFrame())
     617          230824 :         return NULL;
     618                 : 
     619         1867628 :     JS_ASSERT(fp->callee().isFunction());
     620         1867628 :     return &fp->callee();
     621                 : }
     622                 : 
     623                 : JS_PUBLIC_API(JSFunction *)
     624               6 : JS_GetScriptFunction(JSContext *cx, JSScript *script)
     625                 : {
     626               6 :     return script->function();
     627                 : }
     628                 : 
     629                 : JS_PUBLIC_API(JSObject *)
     630               1 : JS_GetParentOrScopeChain(JSContext *cx, JSObject *obj)
     631                 : {
     632               1 :     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_GetValidFrameCalleeObject(JSContext *cx, JSStackFrame *fp, jsval *vp)
     649                 : {
     650                 :     Value v;
     651                 : 
     652               0 :     if (!Valueify(fp)->getValidCalleeObject(cx, &v))
     653               0 :         return false;
     654               0 :     *vp = v.isObject() ? v : JSVAL_VOID;
     655               0 :     return true;
     656                 : }
     657                 : 
     658                 : JS_PUBLIC_API(JSBool)
     659               0 : JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
     660                 : {
     661               0 :     return Valueify(fp)->isDebuggerFrame();
     662                 : }
     663                 : 
     664                 : JS_PUBLIC_API(JSBool)
     665               0 : JS_IsGlobalFrame(JSContext *cx, JSStackFrame *fp)
     666                 : {
     667               0 :     return Valueify(fp)->isGlobalFrame();
     668                 : }
     669                 : 
     670                 : JS_PUBLIC_API(jsval)
     671               0 : JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp)
     672                 : {
     673               0 :     return Valueify(fp)->returnValue();
     674                 : }
     675                 : 
     676                 : JS_PUBLIC_API(void)
     677               0 : JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fpArg, jsval rval)
     678                 : {
     679               0 :     StackFrame *fp = Valueify(fpArg);
     680                 : #ifdef JS_METHODJIT
     681               0 :     JS_ASSERT_IF(fp->isScriptFrame(), fp->script()->debugMode);
     682                 : #endif
     683               0 :     assertSameCompartment(cx, fp, rval);
     684               0 :     fp->setReturnValue(rval);
     685               0 : }
     686                 : 
     687                 : /************************************************************************/
     688                 : 
     689                 : JS_PUBLIC_API(const char *)
     690         1703587 : JS_GetScriptFilename(JSContext *cx, JSScript *script)
     691                 : {
     692         1703587 :     return script->filename;
     693                 : }
     694                 : 
     695                 : JS_PUBLIC_API(const jschar *)
     696               1 : JS_GetScriptSourceMap(JSContext *cx, JSScript *script)
     697                 : {
     698               1 :     return script->sourceMap;
     699                 : }
     700                 : 
     701                 : JS_PUBLIC_API(unsigned)
     702          210394 : JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script)
     703                 : {
     704          210394 :     return script->lineno;
     705                 : }
     706                 : 
     707                 : JS_PUBLIC_API(unsigned)
     708               7 : JS_GetScriptLineExtent(JSContext *cx, JSScript *script)
     709                 : {
     710               7 :     return js_GetScriptLineExtent(script);
     711                 : }
     712                 : 
     713                 : JS_PUBLIC_API(JSVersion)
     714               0 : JS_GetScriptVersion(JSContext *cx, JSScript *script)
     715                 : {
     716               0 :     return VersionNumber(script->getVersion());
     717                 : }
     718                 : 
     719                 : /***************************************************************************/
     720                 : 
     721                 : JS_PUBLIC_API(void)
     722             560 : JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata)
     723                 : {
     724             560 :     rt->debugHooks.newScriptHook = hook;
     725             560 :     rt->debugHooks.newScriptHookData = callerdata;
     726             560 : }
     727                 : 
     728                 : JS_PUBLIC_API(void)
     729             560 : JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
     730                 :                         void *callerdata)
     731                 : {
     732             560 :     rt->debugHooks.destroyScriptHook = hook;
     733             560 :     rt->debugHooks.destroyScriptHookData = callerdata;
     734             560 : }
     735                 : 
     736                 : /***************************************************************************/
     737                 : 
     738                 : JS_PUBLIC_API(JSBool)
     739             972 : JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fpArg,
     740                 :                           const jschar *chars, unsigned length,
     741                 :                           const char *filename, unsigned lineno,
     742                 :                           jsval *rval)
     743                 : {
     744             972 :     if (!CheckDebugMode(cx))
     745               0 :         return false;
     746                 : 
     747             972 :     Env *env = JS_GetFrameScopeChain(cx, fpArg);
     748             972 :     if (!env)
     749               0 :         return false;
     750                 : 
     751            1944 :     js::AutoCompartment ac(cx, env);
     752             972 :     if (!ac.enter())
     753               0 :         return false;
     754                 : 
     755             972 :     StackFrame *fp = Valueify(fpArg);
     756             972 :     return EvaluateInEnv(cx, env, fp, chars, length, filename, lineno, rval);
     757                 : }
     758                 : 
     759                 : JS_PUBLIC_API(JSBool)
     760               0 : JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
     761                 :                         const char *bytes, unsigned length,
     762                 :                         const char *filename, unsigned lineno,
     763                 :                         jsval *rval)
     764                 : {
     765                 :     jschar *chars;
     766                 :     JSBool ok;
     767               0 :     size_t len = length;
     768                 : 
     769               0 :     if (!CheckDebugMode(cx))
     770               0 :         return JS_FALSE;
     771                 : 
     772               0 :     chars = InflateString(cx, bytes, &len);
     773               0 :     if (!chars)
     774               0 :         return JS_FALSE;
     775               0 :     length = (unsigned) len;
     776                 :     ok = JS_EvaluateUCInStackFrame(cx, fp, chars, length, filename, lineno,
     777               0 :                                    rval);
     778               0 :     cx->free_(chars);
     779                 : 
     780               0 :     return ok;
     781                 : }
     782                 : 
     783                 : /************************************************************************/
     784                 : 
     785                 : /* This all should be reworked to avoid requiring JSScopeProperty types. */
     786                 : 
     787                 : JS_PUBLIC_API(JSScopeProperty *)
     788               3 : JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp)
     789                 : {
     790                 :     const Shape *shape;
     791                 : 
     792                 :     /* The caller passes null in *iteratorp to get things started. */
     793               3 :     shape = (Shape *) *iteratorp;
     794               3 :     if (!shape)
     795               2 :         shape = obj->lastProperty();
     796                 :     else
     797               1 :         shape = shape->previous();
     798                 : 
     799               3 :     if (!shape->previous()) {
     800               2 :         JS_ASSERT(shape->isEmptyShape());
     801               2 :         shape = NULL;
     802                 :     }
     803                 : 
     804               3 :     return *iteratorp = reinterpret_cast<JSScopeProperty *>(const_cast<Shape *>(shape));
     805                 : }
     806                 : 
     807                 : JS_PUBLIC_API(JSBool)
     808             532 : JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
     809                 :                    JSPropertyDesc *pd)
     810                 : {
     811             532 :     assertSameCompartment(cx, obj);
     812             532 :     Shape *shape = (Shape *) sprop;
     813             532 :     pd->id = IdToJsval(shape->propid());
     814                 : 
     815             532 :     JSBool wasThrowing = cx->isExceptionPending();
     816             532 :     Value lastException = UndefinedValue();
     817             532 :     if (wasThrowing)
     818               0 :         lastException = cx->getPendingException();
     819             532 :     cx->clearPendingException();
     820                 : 
     821             532 :     if (!js_GetProperty(cx, obj, shape->propid(), &pd->value)) {
     822               0 :         if (!cx->isExceptionPending()) {
     823               0 :             pd->flags = JSPD_ERROR;
     824               0 :             pd->value = JSVAL_VOID;
     825                 :         } else {
     826               0 :             pd->flags = JSPD_EXCEPTION;
     827               0 :             pd->value = cx->getPendingException();
     828                 :         }
     829                 :     } else {
     830             532 :         pd->flags = 0;
     831                 :     }
     832                 : 
     833             532 :     if (wasThrowing)
     834               0 :         cx->setPendingException(lastException);
     835                 : 
     836             532 :     pd->flags |= (shape->enumerable() ? JSPD_ENUMERATE : 0)
     837             532 :               |  (!shape->writable()  ? JSPD_READONLY  : 0)
     838            1596 :               |  (!shape->configurable() ? JSPD_PERMANENT : 0);
     839             532 :     pd->spare = 0;
     840             532 :     if (shape->getter() == CallObject::getArgOp) {
     841             253 :         pd->slot = shape->shortid();
     842             253 :         pd->flags |= JSPD_ARGUMENT;
     843             279 :     } else if (shape->getter() == CallObject::getVarOp) {
     844              55 :         pd->slot = shape->shortid();
     845              55 :         pd->flags |= JSPD_VARIABLE;
     846                 :     } else {
     847             224 :         pd->slot = 0;
     848                 :     }
     849             532 :     pd->alias = JSVAL_VOID;
     850                 : 
     851             532 :     return JS_TRUE;
     852                 : }
     853                 : 
     854                 : JS_PUBLIC_API(JSBool)
     855             344 : JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
     856                 : {
     857             344 :     assertSameCompartment(cx, obj);
     858             344 :     Class *clasp = obj->getClass();
     859             344 :     if (!obj->isNative() || (clasp->flags & JSCLASS_NEW_ENUMERATE)) {
     860                 :         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
     861               0 :                              JSMSG_CANT_DESCRIBE_PROPS, clasp->name);
     862               0 :         return JS_FALSE;
     863                 :     }
     864             344 :     if (!clasp->enumerate(cx, obj))
     865               0 :         return JS_FALSE;
     866                 : 
     867                 :     /* Return an empty pda early if obj has no own properties. */
     868             344 :     if (obj->nativeEmpty()) {
     869              55 :         pda->length = 0;
     870              55 :         pda->array = NULL;
     871              55 :         return JS_TRUE;
     872                 :     }
     873                 : 
     874             289 :     uint32_t n = obj->propertyCount();
     875             289 :     JSPropertyDesc *pd = (JSPropertyDesc *) cx->malloc_(size_t(n) * sizeof(JSPropertyDesc));
     876             289 :     if (!pd)
     877               0 :         return JS_FALSE;
     878             289 :     uint32_t i = 0;
     879             531 :     for (Shape::Range r = obj->lastProperty()->all(); !r.empty(); r.popFront()) {
     880             531 :         if (!js_AddRoot(cx, &pd[i].id, NULL))
     881               0 :             goto bad;
     882             531 :         if (!js_AddRoot(cx, &pd[i].value, NULL))
     883               0 :             goto bad;
     884             531 :         Shape *shape = const_cast<Shape *>(&r.front());
     885             531 :         if (!JS_GetPropertyDesc(cx, obj, reinterpret_cast<JSScopeProperty *>(shape), &pd[i]))
     886               0 :             goto bad;
     887             531 :         if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL))
     888               0 :             goto bad;
     889             531 :         if (++i == n)
     890             289 :             break;
     891                 :     }
     892             289 :     pda->length = i;
     893             289 :     pda->array = pd;
     894             289 :     return JS_TRUE;
     895                 : 
     896                 : bad:
     897               0 :     pda->length = i + 1;
     898               0 :     pda->array = pd;
     899               0 :     JS_PutPropertyDescArray(cx, pda);
     900               0 :     return JS_FALSE;
     901                 : }
     902                 : 
     903                 : JS_PUBLIC_API(void)
     904             289 : JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
     905                 : {
     906                 :     JSPropertyDesc *pd;
     907                 :     uint32_t i;
     908                 : 
     909             289 :     pd = pda->array;
     910             820 :     for (i = 0; i < pda->length; i++) {
     911             531 :         js_RemoveRoot(cx->runtime, &pd[i].id);
     912             531 :         js_RemoveRoot(cx->runtime, &pd[i].value);
     913             531 :         if (pd[i].flags & JSPD_ALIAS)
     914               0 :             js_RemoveRoot(cx->runtime, &pd[i].alias);
     915                 :     }
     916             289 :     cx->free_(pd);
     917             289 : }
     918                 : 
     919                 : /************************************************************************/
     920                 : 
     921                 : JS_PUBLIC_API(JSBool)
     922            1986 : JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler handler, void *closure)
     923                 : {
     924            1986 :     rt->debugHooks.debuggerHandler = handler;
     925            1986 :     rt->debugHooks.debuggerHandlerData = closure;
     926            1986 :     return JS_TRUE;
     927                 : }
     928                 : 
     929                 : JS_PUBLIC_API(JSBool)
     930               0 : JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure)
     931                 : {
     932               0 :     rt->debugHooks.sourceHandler = handler;
     933               0 :     rt->debugHooks.sourceHandlerData = closure;
     934               0 :     return JS_TRUE;
     935                 : }
     936                 : 
     937                 : JS_PUBLIC_API(JSBool)
     938             564 : JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
     939                 : {
     940             564 :     rt->debugHooks.executeHook = hook;
     941             564 :     rt->debugHooks.executeHookData = closure;
     942             564 :     return JS_TRUE;
     943                 : }
     944                 : 
     945                 : JS_PUBLIC_API(JSBool)
     946             567 : JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
     947                 : {
     948             567 :     rt->debugHooks.callHook = hook;
     949             567 :     rt->debugHooks.callHookData = closure;
     950             567 :     return JS_TRUE;
     951                 : }
     952                 : 
     953                 : JS_PUBLIC_API(JSBool)
     954             584 : JS_SetThrowHook(JSRuntime *rt, JSThrowHook hook, void *closure)
     955                 : {
     956             584 :     rt->debugHooks.throwHook = hook;
     957             584 :     rt->debugHooks.throwHookData = closure;
     958             584 :     return JS_TRUE;
     959                 : }
     960                 : 
     961                 : JS_PUBLIC_API(JSBool)
     962             564 : JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure)
     963                 : {
     964             564 :     rt->debugHooks.debugErrorHook = hook;
     965             564 :     rt->debugHooks.debugErrorHookData = closure;
     966             564 :     return JS_TRUE;
     967                 : }
     968                 : 
     969                 : /************************************************************************/
     970                 : 
     971                 : JS_PUBLIC_API(size_t)
     972               0 : JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
     973                 : {
     974               0 :     return obj->computedSizeOfThisSlotsElements();
     975                 : }
     976                 : 
     977                 : static size_t
     978               0 : GetAtomTotalSize(JSContext *cx, JSAtom *atom)
     979                 : {
     980                 :     size_t nbytes;
     981                 : 
     982               0 :     nbytes = sizeof(JSAtom *) + sizeof(JSDHashEntryStub);
     983               0 :     nbytes += sizeof(JSString);
     984               0 :     nbytes += (atom->length() + 1) * sizeof(jschar);
     985               0 :     return nbytes;
     986                 : }
     987                 : 
     988                 : JS_PUBLIC_API(size_t)
     989               0 : JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun)
     990                 : {
     991                 :     size_t nbytes;
     992                 : 
     993               0 :     nbytes = sizeof *fun;
     994               0 :     nbytes += JS_GetObjectTotalSize(cx, fun);
     995               0 :     if (fun->isInterpreted())
     996               0 :         nbytes += JS_GetScriptTotalSize(cx, fun->script());
     997               0 :     if (fun->atom)
     998               0 :         nbytes += GetAtomTotalSize(cx, fun->atom);
     999               0 :     return nbytes;
    1000                 : }
    1001                 : 
    1002                 : JS_PUBLIC_API(size_t)
    1003               0 : JS_GetScriptTotalSize(JSContext *cx, JSScript *script)
    1004                 : {
    1005                 :     size_t nbytes, pbytes;
    1006                 :     jssrcnote *sn, *notes;
    1007                 :     JSObjectArray *objarray;
    1008                 :     JSPrincipals *principals;
    1009                 : 
    1010               0 :     nbytes = sizeof *script;
    1011               0 :     nbytes += script->length * sizeof script->code[0];
    1012               0 :     nbytes += script->natoms * sizeof script->atoms[0];
    1013               0 :     for (size_t i = 0; i < script->natoms; i++)
    1014               0 :         nbytes += GetAtomTotalSize(cx, script->atoms[i]);
    1015                 : 
    1016               0 :     if (script->filename)
    1017               0 :         nbytes += strlen(script->filename) + 1;
    1018                 : 
    1019               0 :     notes = script->notes();
    1020               0 :     for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
    1021               0 :         continue;
    1022               0 :     nbytes += (sn - notes + 1) * sizeof *sn;
    1023                 : 
    1024               0 :     if (JSScript::isValidOffset(script->objectsOffset)) {
    1025               0 :         objarray = script->objects();
    1026               0 :         size_t i = objarray->length;
    1027               0 :         nbytes += sizeof *objarray + i * sizeof objarray->vector[0];
    1028               0 :         do {
    1029               0 :             nbytes += JS_GetObjectTotalSize(cx, objarray->vector[--i]);
    1030                 :         } while (i != 0);
    1031                 :     }
    1032                 : 
    1033               0 :     if (JSScript::isValidOffset(script->regexpsOffset)) {
    1034               0 :         objarray = script->regexps();
    1035               0 :         size_t i = objarray->length;
    1036               0 :         nbytes += sizeof *objarray + i * sizeof objarray->vector[0];
    1037               0 :         do {
    1038               0 :             nbytes += JS_GetObjectTotalSize(cx, objarray->vector[--i]);
    1039                 :         } while (i != 0);
    1040                 :     }
    1041                 : 
    1042               0 :     if (JSScript::isValidOffset(script->trynotesOffset)) {
    1043                 :         nbytes += sizeof(JSTryNoteArray) +
    1044               0 :             script->trynotes()->length * sizeof(JSTryNote);
    1045                 :     }
    1046                 : 
    1047               0 :     principals = script->principals;
    1048               0 :     if (principals) {
    1049               0 :         JS_ASSERT(principals->refcount);
    1050               0 :         pbytes = sizeof *principals;
    1051               0 :         if (principals->refcount > 1)
    1052               0 :             pbytes = JS_HOWMANY(pbytes, principals->refcount);
    1053               0 :         nbytes += pbytes;
    1054                 :     }
    1055                 : 
    1056               0 :     return nbytes;
    1057                 : }
    1058                 : 
    1059                 : JS_PUBLIC_API(JSBool)
    1060         1453003 : JS_IsSystemObject(JSContext *cx, JSObject *obj)
    1061                 : {
    1062         1453003 :     return obj->isSystem();
    1063                 : }
    1064                 : 
    1065                 : JS_PUBLIC_API(JSBool)
    1066         1445262 : JS_MakeSystemObject(JSContext *cx, JSObject *obj)
    1067                 : {
    1068         1445262 :     return obj->setSystem(cx);
    1069                 : }
    1070                 : 
    1071                 : /************************************************************************/
    1072                 : 
    1073                 : JS_FRIEND_API(void)
    1074              36 : js_RevertVersion(JSContext *cx)
    1075                 : {
    1076              36 :     cx->clearVersionOverride();
    1077              36 : }
    1078                 : 
    1079                 : JS_PUBLIC_API(const JSDebugHooks *)
    1080            1404 : JS_GetGlobalDebugHooks(JSRuntime *rt)
    1081                 : {
    1082            1404 :     return &rt->debugHooks;
    1083                 : }
    1084                 : 
    1085                 : /************************************************************************/
    1086                 : 
    1087                 : /* Profiling-related API */
    1088                 : 
    1089                 : /* Thread-unsafe error management */
    1090                 : 
    1091                 : static char gLastError[2000];
    1092                 : 
    1093                 : static void
    1094                 : #ifdef __GNUC__
    1095                 : __attribute__((unused,format(printf,1,2)))
    1096                 : #endif
    1097               0 : UnsafeError(const char *format, ...)
    1098                 : {
    1099                 :     va_list args;
    1100               0 :     va_start(args, format);
    1101               0 :     (void) vsnprintf(gLastError, sizeof(gLastError), format, args);
    1102               0 :     va_end(args);
    1103                 : 
    1104               0 :     gLastError[sizeof(gLastError) - 1] = '\0';
    1105               0 : }
    1106                 : 
    1107                 : JS_PUBLIC_API(const char *)
    1108               0 : JS_UnsafeGetLastProfilingError()
    1109                 : {
    1110               0 :     return gLastError;
    1111                 : }
    1112                 : 
    1113                 : JS_PUBLIC_API(JSBool)
    1114               0 : JS_StartProfiling(const char *profileName)
    1115                 : {
    1116               0 :     JSBool ok = JS_TRUE;
    1117                 : #if defined(MOZ_SHARK) && defined(__APPLE__)
    1118                 :     if (!Shark::Start()) {
    1119                 :         UnsafeError("Failed to start Shark for %s", profileName);
    1120                 :         ok = JS_FALSE;
    1121                 :     }
    1122                 : #endif
    1123                 : #ifdef MOZ_VTUNE
    1124                 :     if (!js_StartVtune(profileName))
    1125                 :         ok = JS_FALSE;
    1126                 : #endif
    1127               0 :     return ok;
    1128                 : }
    1129                 : 
    1130                 : JS_PUBLIC_API(JSBool)
    1131               0 : JS_StopProfiling(const char *profileName)
    1132                 : {
    1133               0 :     JSBool ok = JS_TRUE;
    1134                 : #if defined(MOZ_SHARK) && defined(__APPLE__)
    1135                 :     Shark::Stop();
    1136                 : #endif
    1137                 : #ifdef MOZ_VTUNE
    1138                 :     if (!js_StopVtune())
    1139                 :         ok = JS_FALSE;
    1140                 : #endif
    1141               0 :     return ok;
    1142                 : }
    1143                 : 
    1144                 : /*
    1145                 :  * Start or stop whatever platform- and configuration-specific profiling
    1146                 :  * backends are available.
    1147                 :  */
    1148                 : static JSBool
    1149               0 : ControlProfilers(bool toState)
    1150                 : {
    1151               0 :     JSBool ok = JS_TRUE;
    1152                 : 
    1153               0 :     if (! Probes::ProfilingActive && toState) {
    1154                 : #if defined(MOZ_SHARK) && defined(__APPLE__)
    1155                 :         if (!Shark::Start()) {
    1156                 :             UnsafeError("Failed to start Shark");
    1157                 :             ok = JS_FALSE;
    1158                 :         }
    1159                 : #endif
    1160                 : #ifdef MOZ_CALLGRIND
    1161                 :         if (! js_StartCallgrind()) {
    1162                 :             UnsafeError("Failed to start Callgrind");
    1163                 :             ok = JS_FALSE;
    1164                 :         }
    1165                 : #endif
    1166                 : #ifdef MOZ_VTUNE
    1167                 :         if (! js_ResumeVtune())
    1168                 :             ok = JS_FALSE;
    1169                 : #endif
    1170               0 :     } else if (Probes::ProfilingActive && ! toState) {
    1171                 : #if defined(MOZ_SHARK) && defined(__APPLE__)
    1172                 :         Shark::Stop();
    1173                 : #endif
    1174                 : #ifdef MOZ_CALLGRIND
    1175                 :         if (! js_StopCallgrind()) {
    1176                 :             UnsafeError("failed to stop Callgrind");
    1177                 :             ok = JS_FALSE;
    1178                 :         }
    1179                 : #endif
    1180                 : #ifdef MOZ_VTUNE
    1181                 :         if (! js_PauseVtune())
    1182                 :             ok = JS_FALSE;
    1183                 : #endif
    1184                 :     }
    1185                 : 
    1186               0 :     Probes::ProfilingActive = toState;
    1187                 : 
    1188               0 :     return ok;
    1189                 : }
    1190                 : 
    1191                 : /*
    1192                 :  * Pause/resume whatever profiling mechanism is currently compiled
    1193                 :  * in, if applicable. This will not affect things like dtrace.
    1194                 :  *
    1195                 :  * Do not mix calls to these APIs with calls to the individual
    1196                 :  * profilers' pause/resume functions, because only overall state is
    1197                 :  * tracked, not the state of each profiler.
    1198                 :  */
    1199                 : JS_PUBLIC_API(JSBool)
    1200               0 : JS_PauseProfilers(const char *profileName)
    1201                 : {
    1202               0 :     return ControlProfilers(false);
    1203                 : }
    1204                 : 
    1205                 : JS_PUBLIC_API(JSBool)
    1206               0 : JS_ResumeProfilers(const char *profileName)
    1207                 : {
    1208               0 :     return ControlProfilers(true);
    1209                 : }
    1210                 : 
    1211                 : JS_PUBLIC_API(JSBool)
    1212               0 : JS_DumpProfile(const char *outfile, const char *profileName)
    1213                 : {
    1214               0 :     JSBool ok = JS_TRUE;
    1215                 : #ifdef MOZ_CALLGRIND
    1216                 :     js_DumpCallgrind(outfile);
    1217                 : #endif
    1218               0 :     return ok;
    1219                 : }
    1220                 : 
    1221                 : #ifdef MOZ_PROFILING
    1222                 : 
    1223                 : struct RequiredStringArg {
    1224                 :     JSContext *mCx;
    1225                 :     char *mBytes;
    1226                 :     RequiredStringArg(JSContext *cx, unsigned argc, jsval *vp, size_t argi, const char *caller)
    1227                 :         : mCx(cx), mBytes(NULL)
    1228                 :     {
    1229                 :         if (argc <= argi) {
    1230                 :             JS_ReportError(cx, "%s: not enough arguments", caller);
    1231                 :         } else if (!JSVAL_IS_STRING(JS_ARGV(cx, vp)[argi])) {
    1232                 :             JS_ReportError(cx, "%s: invalid arguments (string expected)", caller);
    1233                 :         } else {
    1234                 :             mBytes = JS_EncodeString(cx, JSVAL_TO_STRING(JS_ARGV(cx, vp)[argi]));
    1235                 :         }
    1236                 :     }
    1237                 :     operator void*() {
    1238                 :         return (void*) mBytes;
    1239                 :     }
    1240                 :     ~RequiredStringArg() {
    1241                 :         if (mBytes)
    1242                 :             mCx->free_(mBytes);
    1243                 :     }
    1244                 : };
    1245                 : 
    1246                 : static JSBool
    1247                 : StartProfiling(JSContext *cx, unsigned argc, jsval *vp)
    1248                 : {
    1249                 :     if (argc == 0) {
    1250                 :         JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_StartProfiling(NULL)));
    1251                 :         return JS_TRUE;
    1252                 :     }
    1253                 : 
    1254                 :     RequiredStringArg profileName(cx, argc, vp, 0, "startProfiling");
    1255                 :     if (!profileName)
    1256                 :         return JS_FALSE;
    1257                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_StartProfiling(profileName.mBytes)));
    1258                 :     return JS_TRUE;
    1259                 : }
    1260                 : 
    1261                 : static JSBool
    1262                 : StopProfiling(JSContext *cx, unsigned argc, jsval *vp)
    1263                 : {
    1264                 :     if (argc == 0) {
    1265                 :         JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_StopProfiling(NULL)));
    1266                 :         return JS_TRUE;
    1267                 :     }
    1268                 : 
    1269                 :     RequiredStringArg profileName(cx, argc, vp, 0, "stopProfiling");
    1270                 :     if (!profileName)
    1271                 :         return JS_FALSE;
    1272                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_StopProfiling(profileName.mBytes)));
    1273                 :     return JS_TRUE;
    1274                 : }
    1275                 : 
    1276                 : static JSBool
    1277                 : PauseProfilers(JSContext *cx, unsigned argc, jsval *vp)
    1278                 : {
    1279                 :     if (argc == 0) {
    1280                 :         JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_PauseProfilers(NULL)));
    1281                 :         return JS_TRUE;
    1282                 :     }
    1283                 : 
    1284                 :     RequiredStringArg profileName(cx, argc, vp, 0, "pauseProfiling");
    1285                 :     if (!profileName)
    1286                 :         return JS_FALSE;
    1287                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_PauseProfilers(profileName.mBytes)));
    1288                 :     return JS_TRUE;
    1289                 : }
    1290                 : 
    1291                 : static JSBool
    1292                 : ResumeProfilers(JSContext *cx, unsigned argc, jsval *vp)
    1293                 : {
    1294                 :     if (argc == 0) {
    1295                 :         JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_ResumeProfilers(NULL)));
    1296                 :         return JS_TRUE;
    1297                 :     }
    1298                 : 
    1299                 :     RequiredStringArg profileName(cx, argc, vp, 0, "resumeProfiling");
    1300                 :     if (!profileName)
    1301                 :         return JS_FALSE;
    1302                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(JS_ResumeProfilers(profileName.mBytes)));
    1303                 :     return JS_TRUE;
    1304                 : }
    1305                 : 
    1306                 : /* Usage: DumpProfile([filename[, profileName]]) */
    1307                 : static JSBool
    1308                 : DumpProfile(JSContext *cx, unsigned argc, jsval *vp)
    1309                 : {
    1310                 :     bool ret;
    1311                 :     if (argc == 0) {
    1312                 :         ret = JS_DumpProfile(NULL, NULL);
    1313                 :     } else {
    1314                 :         RequiredStringArg filename(cx, argc, vp, 0, "dumpProfile");
    1315                 :         if (!filename)
    1316                 :             return JS_FALSE;
    1317                 : 
    1318                 :         if (argc == 1) {
    1319                 :             ret = JS_DumpProfile(filename.mBytes, NULL);
    1320                 :         } else {
    1321                 :             RequiredStringArg profileName(cx, argc, vp, 1, "dumpProfile");
    1322                 :             if (!profileName)
    1323                 :                 return JS_FALSE;
    1324                 : 
    1325                 :             ret = JS_DumpProfile(filename.mBytes, profileName.mBytes);
    1326                 :         }
    1327                 :     }
    1328                 : 
    1329                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(ret));
    1330                 :     return true;
    1331                 : }
    1332                 : 
    1333                 : #ifdef MOZ_SHARK
    1334                 : 
    1335                 : static JSBool
    1336                 : IgnoreAndReturnTrue(JSContext *cx, unsigned argc, jsval *vp)
    1337                 : {
    1338                 :     JS_SET_RVAL(cx, vp, JSVAL_TRUE);
    1339                 :     return true;
    1340                 : }
    1341                 : 
    1342                 : #endif
    1343                 : 
    1344                 : #ifdef MOZ_CALLGRIND
    1345                 : static JSBool
    1346                 : StartCallgrind(JSContext *cx, unsigned argc, jsval *vp)
    1347                 : {
    1348                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_StartCallgrind()));
    1349                 :     return JS_TRUE;
    1350                 : }
    1351                 : 
    1352                 : static JSBool
    1353                 : StopCallgrind(JSContext *cx, unsigned argc, jsval *vp)
    1354                 : {
    1355                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_StopCallgrind()));
    1356                 :     return JS_TRUE;
    1357                 : }
    1358                 : 
    1359                 : static JSBool
    1360                 : DumpCallgrind(JSContext *cx, unsigned argc, jsval *vp)
    1361                 : {
    1362                 :     if (argc == 0) {
    1363                 :         JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_DumpCallgrind(NULL)));
    1364                 :         return JS_TRUE;
    1365                 :     }
    1366                 : 
    1367                 :     RequiredStringArg outFile(cx, argc, vp, 0, "dumpCallgrind");
    1368                 :     if (!outFile)
    1369                 :         return JS_FALSE;
    1370                 : 
    1371                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_DumpCallgrind(outFile.mBytes)));
    1372                 :     return JS_TRUE;
    1373                 : }    
    1374                 : #endif
    1375                 : 
    1376                 : #ifdef MOZ_VTUNE
    1377                 : static JSBool
    1378                 : StartVtune(JSContext *cx, unsigned argc, jsval *vp)
    1379                 : {
    1380                 :     RequiredStringArg profileName(cx, argc, vp, 0, "startVtune");
    1381                 :     if (!profileName)
    1382                 :         return JS_FALSE;
    1383                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_StartVtune(profileName.mBytes)));
    1384                 :     return JS_TRUE;
    1385                 : }
    1386                 : 
    1387                 : static JSBool
    1388                 : StopVtune(JSContext *cx, unsigned argc, jsval *vp)
    1389                 : {
    1390                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_StopVtune()));
    1391                 :     return JS_TRUE;
    1392                 : }
    1393                 : 
    1394                 : static JSBool
    1395                 : PauseVtune(JSContext *cx, unsigned argc, jsval *vp)
    1396                 : {
    1397                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_PauseVtune()));
    1398                 :     return JS_TRUE;
    1399                 : }
    1400                 : 
    1401                 : static JSBool
    1402                 : ResumeVtune(JSContext *cx, unsigned argc, jsval *vp)
    1403                 : {
    1404                 :     JS_SET_RVAL(cx, vp, BOOLEAN_TO_JSVAL(js_ResumeVtune()));
    1405                 :     return JS_TRUE;
    1406                 : }
    1407                 : #endif
    1408                 : 
    1409                 : static JSFunctionSpec profiling_functions[] = {
    1410                 :     JS_FN("startProfiling",  StartProfiling,      1,0),
    1411                 :     JS_FN("stopProfiling",   StopProfiling,       1,0),
    1412                 :     JS_FN("pauseProfilers",  PauseProfilers,      1,0),
    1413                 :     JS_FN("resumeProfilers", ResumeProfilers,     1,0),
    1414                 :     JS_FN("dumpProfile",     DumpProfile,         2,0),
    1415                 : #ifdef MOZ_SHARK
    1416                 :     /* Keep users of the old shark API happy. */
    1417                 :     JS_FN("connectShark",    IgnoreAndReturnTrue, 0,0),
    1418                 :     JS_FN("disconnectShark", IgnoreAndReturnTrue, 0,0),
    1419                 :     JS_FN("startShark",      StartProfiling,      0,0),
    1420                 :     JS_FN("stopShark",       StopProfiling,       0,0),
    1421                 : #endif
    1422                 : #ifdef MOZ_CALLGRIND
    1423                 :     JS_FN("startCallgrind", StartCallgrind,       0,0),
    1424                 :     JS_FN("stopCallgrind",  StopCallgrind,        0,0),
    1425                 :     JS_FN("dumpCallgrind",  DumpCallgrind,        1,0),
    1426                 : #endif
    1427                 : #ifdef MOZ_VTUNE
    1428                 :     JS_FN("startVtune",     js_StartVtune,        1,0),
    1429                 :     JS_FN("stopVtune",      js_StopVtune,         0,0),
    1430                 :     JS_FN("pauseVtune",     js_PauseVtune,        0,0),
    1431                 :     JS_FN("resumeVtune",    js_ResumeVtune,       0,0),
    1432                 : #endif
    1433                 :     JS_FS_END
    1434                 : };
    1435                 : 
    1436                 : #endif
    1437                 : 
    1438                 : JS_PUBLIC_API(JSBool)
    1439           36041 : JS_DefineProfilingFunctions(JSContext *cx, JSObject *obj)
    1440                 : {
    1441           36041 :     assertSameCompartment(cx, obj);
    1442                 : #ifdef MOZ_PROFILING
    1443                 :     return JS_DefineFunctions(cx, obj, profiling_functions);
    1444                 : #else
    1445           36041 :     return true;
    1446                 : #endif
    1447                 : }
    1448                 : 
    1449                 : #ifdef MOZ_CALLGRIND
    1450                 : 
    1451                 : #include <valgrind/callgrind.h>
    1452                 : 
    1453                 : JS_FRIEND_API(JSBool)
    1454                 : js_StartCallgrind()
    1455                 : {
    1456                 :     JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_START_INSTRUMENTATION);
    1457                 :     JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_ZERO_STATS);
    1458                 :     return true;
    1459                 : }
    1460                 : 
    1461                 : JS_FRIEND_API(JSBool)
    1462                 : js_StopCallgrind()
    1463                 : {
    1464                 :     JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_STOP_INSTRUMENTATION);
    1465                 :     return true;
    1466                 : }
    1467                 : 
    1468                 : JS_FRIEND_API(JSBool)
    1469                 : js_DumpCallgrind(const char *outfile)
    1470                 : {
    1471                 :     if (outfile) {
    1472                 :         JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_DUMP_STATS_AT(outfile));
    1473                 :     } else {
    1474                 :         JS_SILENCE_UNUSED_VALUE_IN_EXPR(CALLGRIND_DUMP_STATS);
    1475                 :     }
    1476                 : 
    1477                 :     return true;
    1478                 : }
    1479                 : 
    1480                 : #endif /* MOZ_CALLGRIND */
    1481                 : 
    1482                 : #ifdef MOZ_VTUNE
    1483                 : #include <VTuneApi.h>
    1484                 : 
    1485                 : static const char *vtuneErrorMessages[] = {
    1486                 :   "unknown, error #0",
    1487                 :   "invalid 'max samples' field",
    1488                 :   "invalid 'samples per buffer' field",
    1489                 :   "invalid 'sample interval' field",
    1490                 :   "invalid path",
    1491                 :   "sample file in use",
    1492                 :   "invalid 'number of events' field",
    1493                 :   "unknown, error #7",
    1494                 :   "internal error",
    1495                 :   "bad event name",
    1496                 :   "VTStopSampling called without calling VTStartSampling",
    1497                 :   "no events selected for event-based sampling",
    1498                 :   "events selected cannot be run together",
    1499                 :   "no sampling parameters",
    1500                 :   "sample database already exists",
    1501                 :   "sampling already started",
    1502                 :   "time-based sampling not supported",
    1503                 :   "invalid 'sampling parameters size' field",
    1504                 :   "invalid 'event size' field",
    1505                 :   "sampling file already bound",
    1506                 :   "invalid event path",
    1507                 :   "invalid license",
    1508                 :   "invalid 'global options' field",
    1509                 : 
    1510                 : };
    1511                 : 
    1512                 : bool
    1513                 : js_StartVtune(const char *profileName)
    1514                 : {
    1515                 :     VTUNE_EVENT events[] = {
    1516                 :         { 1000000, 0, 0, 0, "CPU_CLK_UNHALTED.CORE" },
    1517                 :         { 1000000, 0, 0, 0, "INST_RETIRED.ANY" },
    1518                 :     };
    1519                 : 
    1520                 :     U32 n_events = sizeof(events) / sizeof(VTUNE_EVENT);
    1521                 :     char *default_filename = "mozilla-vtune.tb5";
    1522                 :     JSString *str;
    1523                 :     U32 status;
    1524                 : 
    1525                 :     VTUNE_SAMPLING_PARAMS params = {
    1526                 :         sizeof(VTUNE_SAMPLING_PARAMS),
    1527                 :         sizeof(VTUNE_EVENT),
    1528                 :         0, 0, /* Reserved fields */
    1529                 :         1,    /* Initialize in "paused" state */
    1530                 :         0,    /* Max samples, or 0 for "continuous" */
    1531                 :         4096, /* Samples per buffer */
    1532                 :         0.1,  /* Sampling interval in ms */
    1533                 :         1,    /* 1 for event-based sampling, 0 for time-based */
    1534                 : 
    1535                 :         n_events,
    1536                 :         events,
    1537                 :         default_filename,
    1538                 :     };
    1539                 : 
    1540                 :     if (profileName) {
    1541                 :         char filename[strlen(profileName) + strlen("-vtune.tb5") + 1];
    1542                 :         snprintf(filename, sizeof(filename), "%s-vtune.tb5", profileName);
    1543                 :         params.tb5Filename = filename;
    1544                 :     }
    1545                 : 
    1546                 :     status = VTStartSampling(&params);
    1547                 : 
    1548                 :     if (params.tb5Filename != default_filename)
    1549                 :         Foreground::free_(params.tb5Filename);
    1550                 : 
    1551                 :     if (status != 0) {
    1552                 :         if (status == VTAPI_MULTIPLE_RUNS)
    1553                 :             VTStopSampling(0);
    1554                 :         if (status < sizeof(vtuneErrorMessages))
    1555                 :             UnsafeError("Vtune setup error: %s", vtuneErrorMessages[status]);
    1556                 :         else
    1557                 :             UnsafeError("Vtune setup error: %d", status);
    1558                 :         return false;
    1559                 :     }
    1560                 :     return true;
    1561                 : }
    1562                 : 
    1563                 : bool
    1564                 : js_StopVtune()
    1565                 : {
    1566                 :     U32 status = VTStopSampling(1);
    1567                 :     if (status) {
    1568                 :         if (status < sizeof(vtuneErrorMessages))
    1569                 :             UnsafeError("Vtune shutdown error: %s", vtuneErrorMessages[status]);
    1570                 :         else
    1571                 :             UnsafeError("Vtune shutdown error: %d", status);
    1572                 :         return false;
    1573                 :     }
    1574                 :     return true;
    1575                 : }
    1576                 : 
    1577                 : bool
    1578                 : js_PauseVtune()
    1579                 : {
    1580                 :     VTPause();
    1581                 :     return true;
    1582                 : }
    1583                 : 
    1584                 : bool
    1585                 : js_ResumeVtune()
    1586                 : {
    1587                 :     VTResume();
    1588                 :     return true;
    1589                 : }
    1590                 : 
    1591                 : #endif /* MOZ_VTUNE */
    1592                 : 
    1593                 : JS_PUBLIC_API(void)
    1594               0 : JS_DumpBytecode(JSContext *cx, JSScript *script)
    1595                 : {
    1596                 : #if defined(DEBUG)
    1597               0 :     Sprinter sprinter(cx);
    1598               0 :     if (!sprinter.init())
    1599                 :         return;
    1600                 : 
    1601               0 :     fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename, script->lineno);
    1602               0 :     js_Disassemble(cx, script, true, &sprinter);
    1603               0 :     fputs(sprinter.string(), stdout);
    1604               0 :     fprintf(stdout, "--- END SCRIPT %s:%d ---\n", script->filename, script->lineno);
    1605                 : #endif
    1606                 : }
    1607                 : 
    1608                 : extern JS_PUBLIC_API(void)
    1609               0 : JS_DumpPCCounts(JSContext *cx, JSScript *script)
    1610                 : {
    1611                 : #if defined(DEBUG)
    1612               0 :     JS_ASSERT(script->pcCounters);
    1613                 : 
    1614               0 :     Sprinter sprinter(cx);
    1615               0 :     if (!sprinter.init())
    1616                 :         return;
    1617                 : 
    1618               0 :     fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename, script->lineno);
    1619               0 :     js_DumpPCCounts(cx, script, &sprinter);
    1620               0 :     fputs(sprinter.string(), stdout);
    1621               0 :     fprintf(stdout, "--- END SCRIPT %s:%d ---\n", script->filename, script->lineno);
    1622                 : #endif
    1623                 : }
    1624                 : 
    1625                 : namespace {
    1626                 : 
    1627                 : typedef Vector<JSScript *, 0, SystemAllocPolicy> ScriptsToDump;
    1628                 : 
    1629                 : static void
    1630               0 : DumpBytecodeScriptCallback(JSRuntime *rt, void *data, void *thing,
    1631                 :                            JSGCTraceKind traceKind, size_t thingSize)
    1632                 : {
    1633               0 :     JS_ASSERT(traceKind == JSTRACE_SCRIPT);
    1634               0 :     JSScript *script = static_cast<JSScript *>(thing);
    1635               0 :     static_cast<ScriptsToDump *>(data)->append(script);
    1636               0 : }
    1637                 : 
    1638                 : } /* anonymous namespace */
    1639                 : 
    1640                 : JS_PUBLIC_API(void)
    1641               0 : JS_DumpCompartmentBytecode(JSContext *cx)
    1642                 : {
    1643               0 :     ScriptsToDump scripts;
    1644               0 :     IterateCells(cx->runtime, cx->compartment, gc::FINALIZE_SCRIPT, &scripts, DumpBytecodeScriptCallback);
    1645                 : 
    1646               0 :     for (size_t i = 0; i < scripts.length(); i++)
    1647               0 :         JS_DumpBytecode(cx, scripts[i]);
    1648               0 : }
    1649                 : 
    1650                 : JS_PUBLIC_API(void)
    1651               0 : JS_DumpCompartmentPCCounts(JSContext *cx)
    1652                 : {
    1653               0 :     for (CellIter i(cx->compartment, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
    1654               0 :         JSScript *script = i.get<JSScript>();
    1655               0 :         if (script->pcCounters)
    1656               0 :             JS_DumpPCCounts(cx, script);
    1657                 :     }
    1658               0 : }
    1659                 : 
    1660                 : JS_PUBLIC_API(JSObject *)
    1661            1160 : JS_UnwrapObject(JSObject *obj)
    1662                 : {
    1663            1160 :     return UnwrapObject(obj);
    1664                 : }
    1665                 : 
    1666                 : JS_FRIEND_API(JSBool)
    1667               0 : js_CallContextDebugHandler(JSContext *cx)
    1668                 : {
    1669               0 :     FrameRegsIter iter(cx);
    1670               0 :     JS_ASSERT(!iter.done());
    1671                 : 
    1672                 :     jsval rval;
    1673               0 :     switch (js::CallContextDebugHandler(cx, iter.script(), iter.pc(), &rval)) {
    1674                 :       case JSTRAP_ERROR:
    1675               0 :         JS_ClearPendingException(cx);
    1676               0 :         return JS_FALSE;
    1677                 :       case JSTRAP_THROW:
    1678               0 :         JS_SetPendingException(cx, rval);
    1679               0 :         return JS_FALSE;
    1680                 :       case JSTRAP_RETURN:
    1681                 :       case JSTRAP_CONTINUE:
    1682                 :       default:
    1683               0 :         return JS_TRUE;
    1684                 :     }
    1685                 : }
    1686                 : 

Generated by: LCOV version 1.7