LCOV - code coverage report
Current view: directory - js/src - jsfriendapi.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 348 180 51.7 %
Date: 2012-06-02 Functions: 82 51 62.2 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=4 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 SpiderMonkey code.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  *   Mozilla Foundation
      21                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "mozilla/GuardObjects.h"
      41                 : #include "mozilla/StandardInteger.h"
      42                 : 
      43                 : #include "jscntxt.h"
      44                 : #include "jscompartment.h"
      45                 : #include "jsfriendapi.h"
      46                 : #include "jswrapper.h"
      47                 : #include "jsweakmap.h"
      48                 : #include "jswatchpoint.h"
      49                 : 
      50                 : #include "builtin/TestingFunctions.h"
      51                 : 
      52                 : #include "jsobjinlines.h"
      53                 : 
      54                 : using namespace js;
      55                 : using namespace JS;
      56                 : 
      57                 : JS_FRIEND_API(void)
      58            1404 : JS_SetGrayGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
      59                 : {
      60            1404 :     rt->gcGrayRootsTraceOp = traceOp;
      61            1404 :     rt->gcGrayRootsData = data;
      62            1404 : }
      63                 : 
      64                 : JS_FRIEND_API(JSString *)
      65               2 : JS_GetAnonymousString(JSRuntime *rt)
      66                 : {
      67               2 :     JS_ASSERT(rt->hasContexts());
      68               2 :     return rt->atomState.anonymousAtom;
      69                 : }
      70                 : 
      71                 : JS_FRIEND_API(JSObject *)
      72             709 : JS_FindCompilationScope(JSContext *cx, JSObject *obj)
      73                 : {
      74                 :     /*
      75                 :      * We unwrap wrappers here. This is a little weird, but it's what's being
      76                 :      * asked of us.
      77                 :      */
      78             709 :     if (obj->isWrapper())
      79               0 :         obj = UnwrapObject(obj);
      80                 :     
      81                 :     /*
      82                 :      * Innerize the target_obj so that we compile in the correct (inner)
      83                 :      * scope.
      84                 :      */
      85             709 :     if (JSObjectOp op = obj->getClass()->ext.innerObject)
      86               0 :         obj = op(cx, obj);
      87             709 :     return obj;
      88                 : }
      89                 : 
      90                 : JS_FRIEND_API(JSFunction *)
      91         1867919 : JS_GetObjectFunction(JSObject *obj)
      92                 : {
      93         1867919 :     if (obj->isFunction())
      94         1867909 :         return obj->toFunction();
      95              10 :     return NULL;
      96                 : }
      97                 : 
      98                 : JS_FRIEND_API(JSObject *)
      99             445 : JS_GetGlobalForFrame(JSStackFrame *fp)
     100                 : {
     101             445 :     return &Valueify(fp)->scopeChain().global();
     102                 : }
     103                 : 
     104                 : JS_FRIEND_API(JSBool)
     105           13217 : JS_SplicePrototype(JSContext *cx, JSObject *obj, JSObject *proto)
     106                 : {
     107                 :     /*
     108                 :      * Change the prototype of an object which hasn't been used anywhere
     109                 :      * and does not share its type with another object. Unlike JS_SetPrototype,
     110                 :      * does not nuke type information for the object.
     111                 :      */
     112           26434 :     CHECK_REQUEST(cx);
     113                 : 
     114           13217 :     if (!obj->hasSingletonType()) {
     115                 :         /*
     116                 :          * We can see non-singleton objects when trying to splice prototypes
     117                 :          * due to mutable __proto__ (ugh).
     118                 :          */
     119           13217 :         return JS_SetPrototype(cx, obj, proto);
     120                 :     }
     121                 : 
     122               0 :     return obj->splicePrototype(cx, proto);
     123                 : }
     124                 : 
     125                 : JS_FRIEND_API(JSObject *)
     126          186922 : JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
     127                 : {
     128          186922 :     JSObject *obj = JS_NewObject(cx, clasp, proto, parent);
     129          186922 :     if (!obj || !obj->setSingletonType(cx))
     130               0 :         return NULL;
     131          186922 :     return obj;
     132                 : }
     133                 : 
     134                 : JS_FRIEND_API(void)
     135            1871 : js::GCForReason(JSContext *cx, gcreason::Reason reason)
     136                 : {
     137            1871 :     GC(cx, NULL, GC_NORMAL, reason);
     138            1871 : }
     139                 : 
     140                 : JS_FRIEND_API(void)
     141               0 : js::CompartmentGCForReason(JSContext *cx, JSCompartment *comp, gcreason::Reason reason)
     142                 : {
     143                 :     /* We cannot GC the atoms compartment alone; use a full GC instead. */
     144               0 :     JS_ASSERT(comp != cx->runtime->atomsCompartment);
     145                 : 
     146               0 :     GC(cx, comp, GC_NORMAL, reason);
     147               0 : }
     148                 : 
     149                 : JS_FRIEND_API(void)
     150               0 : js::ShrinkingGC(JSContext *cx, gcreason::Reason reason)
     151                 : {
     152               0 :     GC(cx, NULL, GC_SHRINK, reason);
     153               0 : }
     154                 : 
     155                 : JS_FRIEND_API(void)
     156               4 : js::IncrementalGC(JSContext *cx, gcreason::Reason reason)
     157                 : {
     158               4 :     GCSlice(cx, NULL, GC_NORMAL, reason);
     159               4 : }
     160                 : 
     161                 : JS_FRIEND_API(void)
     162               0 : JS_ShrinkGCBuffers(JSRuntime *rt)
     163                 : {
     164               0 :     ShrinkGCBuffers(rt);
     165               0 : }
     166                 : 
     167                 : JS_FRIEND_API(JSPrincipals *)
     168         1579994 : JS_GetCompartmentPrincipals(JSCompartment *compartment)
     169                 : {
     170         1579994 :     return compartment->principals;
     171                 : }
     172                 : 
     173                 : JS_FRIEND_API(JSBool)
     174               0 : JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc)
     175                 : {
     176               0 :     return cx->compartment->wrap(cx, desc);
     177                 : }
     178                 : 
     179                 : JS_FRIEND_API(void)
     180          375083 : JS_TraceShapeCycleCollectorChildren(JSTracer *trc, void *shape)
     181                 : {
     182          375083 :     MarkCycleCollectorChildren(trc, (Shape *)shape);
     183          375083 : }
     184                 : 
     185                 : static bool
     186         3514896 : DefineHelpProperty(JSContext *cx, JSObject *obj, const char *prop, const char *value)
     187                 : {
     188         3514896 :     JSAtom *atom = js_Atomize(cx, value, strlen(value));
     189         3514896 :     if (!atom)
     190               0 :         return false;
     191         3514896 :     jsval v = STRING_TO_JSVAL(atom);
     192                 :     return JS_DefineProperty(cx, obj, prop, v,
     193                 :                              JS_PropertyStub, JS_StrictPropertyStub,
     194         3514896 :                              JSPROP_READONLY | JSPROP_PERMANENT);
     195                 : }
     196                 : 
     197                 : JS_FRIEND_API(bool)
     198           45648 : JS_DefineFunctionsWithHelp(JSContext *cx, JSObject *obj, const JSFunctionSpecWithHelp *fs)
     199                 : {
     200           91296 :     RootObject objRoot(cx, &obj);
     201                 : 
     202           45648 :     JS_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     203                 : 
     204           91296 :     CHECK_REQUEST(cx);
     205           45648 :     assertSameCompartment(cx, obj);
     206         1803096 :     for (; fs->name; fs++) {
     207         1757448 :         JSAtom *atom = js_Atomize(cx, fs->name, strlen(fs->name));
     208         1757448 :         if (!atom)
     209               0 :             return false;
     210                 : 
     211                 :         JSFunction *fun = js_DefineFunction(cx, objRoot,
     212         1757448 :                                             ATOM_TO_JSID(atom), fs->call, fs->nargs, fs->flags);
     213         1757448 :         if (!fun)
     214               0 :             return false;
     215                 : 
     216         1757448 :         if (fs->usage) {
     217         1757448 :             if (!DefineHelpProperty(cx, fun, "usage", fs->usage))
     218               0 :                 return false;
     219                 :         }
     220                 : 
     221         1757448 :         if (fs->help) {
     222         1757448 :             if (!DefineHelpProperty(cx, fun, "help", fs->help))
     223               0 :                 return false;
     224                 :         }
     225                 :     }
     226                 : 
     227           45648 :     return true;
     228                 : }
     229                 : 
     230           11830 : AutoPreserveCompartment::AutoPreserveCompartment(JSContext *cx
     231                 :                                                  JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT)
     232           11830 :   : cx(cx), oldCompartment(cx->compartment)
     233                 : {
     234           11830 :     JS_GUARD_OBJECT_NOTIFIER_INIT;
     235           11830 : }
     236                 : 
     237           23660 : AutoPreserveCompartment::~AutoPreserveCompartment()
     238                 : {
     239                 :     /* The old compartment may have been destroyed, so we can't use cx->setCompartment. */
     240           11830 :     cx->compartment = oldCompartment;
     241           11830 : }
     242                 : 
     243           11826 : AutoSwitchCompartment::AutoSwitchCompartment(JSContext *cx, JSCompartment *newCompartment
     244                 :                                              JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT)
     245           11826 :   : cx(cx), oldCompartment(cx->compartment)
     246                 : {
     247           11826 :     JS_GUARD_OBJECT_NOTIFIER_INIT;
     248           11826 :     cx->setCompartment(newCompartment);
     249           11826 : }
     250                 : 
     251               0 : AutoSwitchCompartment::AutoSwitchCompartment(JSContext *cx, JSObject *target
     252                 :                                              JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT)
     253               0 :   : cx(cx), oldCompartment(cx->compartment)
     254                 : {
     255               0 :     JS_GUARD_OBJECT_NOTIFIER_INIT;
     256               0 :     cx->setCompartment(target->compartment());
     257               0 : }
     258                 : 
     259           23652 : AutoSwitchCompartment::~AutoSwitchCompartment()
     260                 : {
     261                 :     /* The old compartment may have been destroyed, so we can't use cx->setCompartment. */
     262           11826 :     cx->compartment = oldCompartment;
     263           11826 : }
     264                 : 
     265                 : JS_FRIEND_API(bool)
     266              21 : js::IsSystemCompartment(const JSCompartment *c)
     267                 : {
     268              21 :     return c->isSystemCompartment;
     269                 : }
     270                 : 
     271                 : JS_FRIEND_API(bool)
     272              18 : js::IsAtomsCompartment(const JSCompartment *c)
     273                 : {
     274              18 :     return c == c->rt->atomsCompartment;
     275                 : }
     276                 : 
     277                 : JS_FRIEND_API(bool)
     278        13043148 : js::IsScopeObject(JSObject *obj)
     279                 : {
     280        13043148 :     return obj->isScope();
     281                 : }
     282                 : 
     283                 : JS_FRIEND_API(JSObject *)
     284            5110 : js::GetObjectParentMaybeScope(JSObject *obj)
     285                 : {
     286            5110 :     return obj->enclosingScope();
     287                 : }
     288                 : 
     289                 : JS_FRIEND_API(JSObject *)
     290            4321 : js::GetGlobalForObjectCrossCompartment(JSObject *obj)
     291                 : {
     292            4321 :     return &obj->global();
     293                 : }
     294                 : 
     295                 : JS_FRIEND_API(uint32_t)
     296          782856 : js::GetObjectSlotSpan(JSObject *obj)
     297                 : {
     298          782856 :     return obj->slotSpan();
     299                 : }
     300                 : 
     301                 : JS_FRIEND_API(bool)
     302        11276148 : js::IsObjectInContextCompartment(const JSObject *obj, const JSContext *cx)
     303                 : {
     304        11276148 :     return obj->compartment() == cx->compartment;
     305                 : }
     306                 : 
     307                 : JS_FRIEND_API(bool)
     308         1867625 : js::IsOriginalScriptFunction(JSFunction *fun)
     309                 : {
     310         1867625 :     return fun->script()->function() == fun;
     311                 : }
     312                 : 
     313                 : JS_FRIEND_API(JSFunction *)
     314          138588 : js::DefineFunctionWithReserved(JSContext *cx, JSObject *obj, const char *name, JSNative call,
     315                 :                                unsigned nargs, unsigned attrs)
     316                 : {
     317          277176 :     RootObject objRoot(cx, &obj);
     318                 : 
     319          138588 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     320          277176 :     CHECK_REQUEST(cx);
     321          138588 :     assertSameCompartment(cx, obj);
     322          138588 :     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     323          138588 :     if (!atom)
     324               0 :         return NULL;
     325                 :     return js_DefineFunction(cx, objRoot, ATOM_TO_JSID(atom), call, nargs, attrs,
     326          138588 :                              JSFunction::ExtendedFinalizeKind);
     327                 : }
     328                 : 
     329                 : JS_FRIEND_API(JSFunction *)
     330               0 : js::NewFunctionWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
     331                 :                             JSObject *parent, const char *name)
     332                 : {
     333               0 :     RootObject parentRoot(cx, &parent);
     334                 : 
     335               0 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     336                 :     JSAtom *atom;
     337                 : 
     338               0 :     CHECK_REQUEST(cx);
     339               0 :     assertSameCompartment(cx, parent);
     340                 : 
     341               0 :     if (!name) {
     342               0 :         atom = NULL;
     343                 :     } else {
     344               0 :         atom = js_Atomize(cx, name, strlen(name));
     345               0 :         if (!atom)
     346               0 :             return NULL;
     347                 :     }
     348                 : 
     349                 :     return js_NewFunction(cx, NULL, native, nargs, flags, parentRoot, atom,
     350               0 :                           JSFunction::ExtendedFinalizeKind);
     351                 : }
     352                 : 
     353                 : JS_FRIEND_API(JSFunction *)
     354         1710919 : js::NewFunctionByIdWithReserved(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parent,
     355                 :                                 jsid id)
     356                 : {
     357         3421838 :     RootObject parentRoot(cx, &parent);
     358                 : 
     359         1710919 :     JS_ASSERT(JSID_IS_STRING(id));
     360         1710919 :     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     361         3421838 :     CHECK_REQUEST(cx);
     362         1710919 :     assertSameCompartment(cx, parent);
     363                 : 
     364                 :     return js_NewFunction(cx, NULL, native, nargs, flags, parentRoot, JSID_TO_ATOM(id),
     365         1710919 :                           JSFunction::ExtendedFinalizeKind);
     366                 : }
     367                 : 
     368                 : JS_FRIEND_API(JSObject *)
     369           18699 : js::InitClassWithReserved(JSContext *cx, JSObject *obj, JSObject *parent_proto,
     370                 :                           JSClass *clasp, JSNative constructor, unsigned nargs,
     371                 :                           JSPropertySpec *ps, JSFunctionSpec *fs,
     372                 :                           JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
     373                 : {
     374           37398 :     CHECK_REQUEST(cx);
     375           18699 :     assertSameCompartment(cx, obj, parent_proto);
     376           37398 :     RootObject objRoot(cx, &obj);
     377                 :     return js_InitClass(cx, objRoot, parent_proto, Valueify(clasp), constructor,
     378                 :                         nargs, ps, fs, static_ps, static_fs, NULL,
     379           18699 :                         JSFunction::ExtendedFinalizeKind);
     380                 : }
     381                 : 
     382                 : JS_FRIEND_API(const Value &)
     383        13443790 : js::GetFunctionNativeReserved(JSObject *fun, size_t which)
     384                 : {
     385        13443790 :     JS_ASSERT(fun->toFunction()->isNative());
     386        13443790 :     return fun->toFunction()->getExtendedSlot(which);
     387                 : }
     388                 : 
     389                 : JS_FRIEND_API(void)
     390         3578831 : js::SetFunctionNativeReserved(JSObject *fun, size_t which, const Value &val)
     391                 : {
     392         3578831 :     JS_ASSERT(fun->toFunction()->isNative());
     393         3578831 :     fun->toFunction()->setExtendedSlot(which, val);
     394         3578831 : }
     395                 : 
     396                 : JS_FRIEND_API(void)
     397               0 : js::SetReservedSlotWithBarrier(JSObject *obj, size_t slot, const js::Value &value)
     398                 : {
     399               0 :     obj->setSlot(slot, value);
     400               0 : }
     401                 : 
     402                 : void
     403            1404 : js::SetPreserveWrapperCallback(JSRuntime *rt, PreserveWrapperCallback callback)
     404                 : {
     405            1404 :     rt->preserveWrapperCallback = callback;
     406            1404 : }
     407                 : 
     408                 : /*
     409                 :  * The below code is for temporary telemetry use. It can be removed when
     410                 :  * sufficient data has been harvested.
     411                 :  */
     412                 : 
     413                 : extern size_t sE4XObjectsCreated;
     414                 : 
     415                 : JS_FRIEND_API(size_t)
     416               3 : JS_GetE4XObjectsCreated(JSContext *)
     417                 : {
     418               3 :     return sE4XObjectsCreated;
     419                 : }
     420                 : 
     421                 : extern size_t sSetProtoCalled;
     422                 : 
     423                 : JS_FRIEND_API(size_t)
     424               3 : JS_SetProtoCalled(JSContext *)
     425                 : {
     426               3 :     return sSetProtoCalled;
     427                 : }
     428                 : 
     429                 : extern size_t sCustomIteratorCount;
     430                 : 
     431                 : JS_FRIEND_API(size_t)
     432               3 : JS_GetCustomIteratorCount(JSContext *cx)
     433                 : {
     434               3 :     return sCustomIteratorCount;
     435                 : }
     436                 : 
     437                 : void
     438            1910 : js::TraceWeakMaps(WeakMapTracer *trc)
     439                 : {
     440            1910 :     WeakMapBase::traceAllMappings(trc);
     441            1910 :     WatchpointMap::traceAll(trc);
     442            1910 : }
     443                 : 
     444                 : JS_FRIEND_API(bool)
     445        26568033 : js::GCThingIsMarkedGray(void *thing)
     446                 : {
     447        26568033 :     JS_ASSERT(thing);
     448        26568033 :     return reinterpret_cast<gc::Cell *>(thing)->isMarked(gc::GRAY);
     449                 : }
     450                 : 
     451                 : JS_FRIEND_API(void)
     452            1404 : JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback)
     453                 : {
     454            1404 :     rt->telemetryCallback = callback;
     455            1404 : }
     456                 : 
     457                 : #ifdef DEBUG
     458                 : JS_FRIEND_API(void)
     459               0 : js_DumpString(JSString *str)
     460                 : {
     461               0 :     str->dump();
     462               0 : }
     463                 : 
     464                 : JS_FRIEND_API(void)
     465               0 : js_DumpAtom(JSAtom *atom)
     466                 : {
     467               0 :     atom->dump();
     468               0 : }
     469                 : 
     470                 : extern void
     471               0 : DumpChars(const jschar *s, size_t n)
     472                 : {
     473               0 :     if (n == SIZE_MAX) {
     474               0 :         n = 0;
     475               0 :         while (s[n])
     476               0 :             n++;
     477                 :     }
     478                 : 
     479               0 :     fputc('"', stderr);
     480               0 :     for (size_t i = 0; i < n; i++) {
     481               0 :         if (s[i] == '\n')
     482               0 :             fprintf(stderr, "\\n");
     483               0 :         else if (s[i] == '\t')
     484               0 :             fprintf(stderr, "\\t");
     485               0 :         else if (s[i] >= 32 && s[i] < 127)
     486               0 :             fputc(s[i], stderr);
     487               0 :         else if (s[i] <= 255)
     488               0 :             fprintf(stderr, "\\x%02x", (unsigned int) s[i]);
     489                 :         else
     490               0 :             fprintf(stderr, "\\u%04x", (unsigned int) s[i]);
     491                 :     }
     492               0 :     fputc('"', stderr);
     493               0 : }
     494                 : 
     495                 : JS_FRIEND_API(void)
     496               0 : js_DumpChars(const jschar *s, size_t n)
     497                 : {
     498               0 :     fprintf(stderr, "jschar * (%p) = ", (void *) s);
     499               0 :     DumpChars(s, n);
     500               0 :     fputc('\n', stderr);
     501               0 : }
     502                 : 
     503                 : JS_FRIEND_API(void)
     504               0 : js_DumpObject(JSObject *obj)
     505                 : {
     506               0 :     obj->dump();
     507               0 : }
     508                 : 
     509               0 : struct DumpingChildInfo {
     510                 :     void *node;
     511                 :     JSGCTraceKind kind;
     512                 : 
     513               0 :     DumpingChildInfo (void *n, JSGCTraceKind k)
     514               0 :         : node(n), kind(k)
     515               0 :     {}
     516                 : };
     517                 : 
     518                 : typedef HashSet<void *, DefaultHasher<void *>, SystemAllocPolicy> PtrSet;
     519                 : 
     520               0 : struct JSDumpHeapTracer : public JSTracer {
     521                 :     PtrSet visited;
     522                 :     FILE   *output;
     523                 :     Vector<DumpingChildInfo, 0, SystemAllocPolicy> nodes;
     524                 :     char   buffer[200];
     525                 :     bool   rootTracing;
     526                 : 
     527               0 :     JSDumpHeapTracer(FILE *fp)
     528               0 :       : output(fp)
     529               0 :     {}
     530                 : };
     531                 : 
     532                 : static void
     533                 : DumpHeapVisitChild(JSTracer *trc, void **thingp, JSGCTraceKind kind);
     534                 : 
     535                 : static char
     536               0 : MarkDescriptor(void *thing)
     537                 : {
     538               0 :     gc::Cell *cell = static_cast<gc::Cell*>(thing);
     539               0 :     if (cell->isMarked(gc::BLACK))
     540               0 :         return cell->isMarked(gc::GRAY) ? 'G' : 'B';
     541                 :     else
     542               0 :         return cell->isMarked(gc::GRAY) ? 'X' : 'W';
     543                 : }
     544                 : 
     545                 : static void
     546               0 : DumpHeapPushIfNew(JSTracer *trc, void **thingp, JSGCTraceKind kind)
     547                 : {
     548               0 :     JS_ASSERT(trc->callback == DumpHeapPushIfNew ||
     549               0 :               trc->callback == DumpHeapVisitChild);
     550               0 :     void *thing = *thingp;
     551               0 :     JSDumpHeapTracer *dtrc = static_cast<JSDumpHeapTracer *>(trc);
     552                 : 
     553                 :     /*
     554                 :      * If we're tracing roots, print root information.  Do this even if we've
     555                 :      * already seen thing, for complete root information.
     556                 :      */
     557               0 :     if (dtrc->rootTracing) {
     558               0 :         fprintf(dtrc->output, "%p %c %s\n", thing, MarkDescriptor(thing),
     559               0 :                 JS_GetTraceEdgeName(dtrc, dtrc->buffer, sizeof(dtrc->buffer)));
     560                 :     }
     561                 : 
     562               0 :     PtrSet::AddPtr ptrEntry = dtrc->visited.lookupForAdd(thing);
     563               0 :     if (ptrEntry || !dtrc->visited.add(ptrEntry, thing))
     564               0 :         return;
     565                 : 
     566               0 :     dtrc->nodes.append(DumpingChildInfo(thing, kind));
     567                 : }
     568                 : 
     569                 : static void
     570               0 : DumpHeapVisitChild(JSTracer *trc, void **thingp, JSGCTraceKind kind)
     571                 : {
     572               0 :     JS_ASSERT(trc->callback == DumpHeapVisitChild);
     573               0 :     JSDumpHeapTracer *dtrc = static_cast<JSDumpHeapTracer *>(trc);
     574               0 :     const char *edgeName = JS_GetTraceEdgeName(dtrc, dtrc->buffer, sizeof(dtrc->buffer));
     575               0 :     fprintf(dtrc->output, "> %p %c %s\n", *thingp, MarkDescriptor(*thingp), edgeName);
     576               0 :     DumpHeapPushIfNew(dtrc, thingp, kind);
     577               0 : }
     578                 : 
     579                 : void
     580               0 : js::DumpHeapComplete(JSRuntime *rt, FILE *fp)
     581                 : {
     582               0 :     JSDumpHeapTracer dtrc(fp);
     583               0 :     JS_TracerInit(&dtrc, rt, DumpHeapPushIfNew);
     584               0 :     if (!dtrc.visited.init(10000))
     585                 :         return;
     586                 : 
     587                 :     /* Store and log the root information. */
     588               0 :     dtrc.rootTracing = true;
     589               0 :     TraceRuntime(&dtrc);
     590               0 :     fprintf(dtrc.output, "==========\n");
     591                 : 
     592                 :     /* Log the graph. */
     593               0 :     dtrc.rootTracing = false;
     594               0 :     dtrc.callback = DumpHeapVisitChild;
     595                 : 
     596               0 :     while (!dtrc.nodes.empty()) {
     597               0 :         DumpingChildInfo dci = dtrc.nodes.popCopy();
     598                 :         JS_PrintTraceThingInfo(dtrc.buffer, sizeof(dtrc.buffer),
     599               0 :                                &dtrc, dci.node, dci.kind, JS_TRUE);
     600               0 :         fprintf(fp, "%p %c %s\n", dci.node, MarkDescriptor(dci.node), dtrc.buffer);
     601               0 :         JS_TraceChildren(&dtrc, dci.node, dci.kind);
     602                 :     }
     603                 : 
     604               0 :     dtrc.visited.finish();
     605               0 :     fflush(dtrc.output);
     606                 : }
     607                 : 
     608                 : #endif
     609                 : 
     610                 : namespace js {
     611                 : 
     612                 : JS_FRIEND_API(const JSStructuredCloneCallbacks *)
     613               0 : GetContextStructuredCloneCallbacks(JSContext *cx)
     614                 : {
     615               0 :     return cx->runtime->structuredCloneCallbacks;
     616                 : }
     617                 : 
     618                 : JS_FRIEND_API(JSVersion)
     619             968 : VersionSetXML(JSVersion version, bool enable)
     620                 : {
     621                 :     return enable ? JSVersion(uint32_t(version) | VersionFlags::HAS_XML)
     622             968 :                   : JSVersion(uint32_t(version) & ~VersionFlags::HAS_XML);
     623                 : }
     624                 : 
     625                 : JS_FRIEND_API(bool)
     626               0 : CanCallContextDebugHandler(JSContext *cx)
     627                 : {
     628               0 :     return !!cx->runtime->debugHooks.debuggerHandler;
     629                 : }
     630                 : 
     631                 : JS_FRIEND_API(JSTrapStatus)
     632               0 : CallContextDebugHandler(JSContext *cx, JSScript *script, jsbytecode *bc, Value *rval)
     633                 : {
     634               0 :     if (!cx->runtime->debugHooks.debuggerHandler)
     635               0 :         return JSTRAP_RETURN;
     636                 : 
     637                 :     return cx->runtime->debugHooks.debuggerHandler(cx, script, bc, rval,
     638               0 :                                                    cx->runtime->debugHooks.debuggerHandlerData);
     639                 : }
     640                 : 
     641                 : #ifdef JS_THREADSAFE
     642                 : void *
     643        27226744 : GetOwnerThread(const JSContext *cx)
     644                 : {
     645        27226744 :     return cx->runtime->ownerThread();
     646                 : }
     647                 : 
     648                 : JS_FRIEND_API(unsigned)
     649            5298 : GetContextOutstandingRequests(const JSContext *cx)
     650                 : {
     651            5298 :     return cx->outstandingRequests;
     652                 : }
     653                 : 
     654            1868 : AutoSkipConservativeScan::AutoSkipConservativeScan(JSContext *cx
     655                 :                                                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
     656            1868 :   : context(cx)
     657                 : {
     658            1868 :     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     659                 : 
     660            1868 :     JSRuntime *rt = context->runtime;
     661            1868 :     JS_ASSERT(rt->requestDepth >= 1);
     662            1868 :     JS_ASSERT(!rt->conservativeGC.requestThreshold);
     663            1868 :     if (rt->requestDepth == 1)
     664            1868 :         rt->conservativeGC.requestThreshold = 1;
     665            1868 : }
     666                 : 
     667            3736 : AutoSkipConservativeScan::~AutoSkipConservativeScan()
     668                 : {
     669            1868 :     JSRuntime *rt = context->runtime;
     670            1868 :     if (rt->requestDepth == 1)
     671            1868 :         rt->conservativeGC.requestThreshold = 0;
     672            1868 : }
     673                 : #endif
     674                 : 
     675                 : JS_FRIEND_API(JSCompartment *)
     676           10841 : GetContextCompartment(const JSContext *cx)
     677                 : {
     678           10841 :     return cx->compartment;
     679                 : }
     680                 : 
     681                 : JS_FRIEND_API(bool)
     682           66484 : HasUnrootedGlobal(const JSContext *cx)
     683                 : {
     684           66484 :     return cx->hasRunOption(JSOPTION_UNROOTED_GLOBAL);
     685                 : }
     686                 : 
     687                 : JS_FRIEND_API(void)
     688            1404 : SetActivityCallback(JSRuntime *rt, ActivityCallback cb, void *arg)
     689                 : {
     690            1404 :     rt->activityCallback = cb;
     691            1404 :     rt->activityCallbackArg = arg;
     692            1404 : }
     693                 : 
     694                 : JS_FRIEND_API(bool)
     695               0 : IsContextRunningJS(JSContext *cx)
     696                 : {
     697               0 :     return !cx->stack.empty();
     698                 : }
     699                 : 
     700                 : JS_FRIEND_API(const CompartmentVector&)
     701             280 : GetRuntimeCompartments(JSRuntime *rt)
     702                 : {
     703             280 :     return rt->compartments;
     704                 : }
     705                 : 
     706                 : JS_FRIEND_API(size_t)
     707            5298 : SizeOfJSContext()
     708                 : {
     709            5298 :     return sizeof(JSContext);
     710                 : }
     711                 : 
     712                 : JS_FRIEND_API(GCSliceCallback)
     713             330 : SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback)
     714                 : {
     715             330 :     GCSliceCallback old = rt->gcSliceCallback;
     716             330 :     rt->gcSliceCallback = callback;
     717             330 :     return old;
     718                 : }
     719                 : 
     720                 : JS_FRIEND_API(bool)
     721               0 : WantGCSlice(JSRuntime *rt)
     722                 : {
     723               0 :     if (rt->gcZeal() == gc::ZealFrameVerifierValue || rt->gcZeal() == gc::ZealFrameGCValue)
     724               0 :         return true;
     725                 : 
     726               0 :     if (rt->gcIncrementalState != gc::NO_INCREMENTAL)
     727               0 :         return true;
     728                 : 
     729               0 :     return false;
     730                 : }
     731                 : 
     732                 : JS_FRIEND_API(void)
     733               0 : NotifyDidPaint(JSContext *cx)
     734                 : {
     735               0 :     JSRuntime *rt = cx->runtime;
     736                 : 
     737               0 :     if (rt->gcZeal() == gc::ZealFrameVerifierValue) {
     738               0 :         gc::VerifyBarriers(cx);
     739               0 :         return;
     740                 :     }
     741                 : 
     742               0 :     if (rt->gcZeal() == gc::ZealFrameGCValue) {
     743               0 :         GCSlice(cx, NULL, GC_NORMAL, gcreason::REFRESH_FRAME);
     744               0 :         return;
     745                 :     }
     746                 : 
     747               0 :     if (rt->gcIncrementalState != gc::NO_INCREMENTAL && !rt->gcInterFrameGC)
     748               0 :         GCSlice(cx, rt->gcIncrementalCompartment, GC_NORMAL, gcreason::REFRESH_FRAME);
     749                 : 
     750               0 :     rt->gcInterFrameGC = false;
     751                 : }
     752                 : 
     753                 : extern JS_FRIEND_API(bool)
     754               0 : IsIncrementalGCEnabled(JSRuntime *rt)
     755                 : {
     756               0 :     return rt->gcIncrementalEnabled;
     757                 : }
     758                 : 
     759                 : extern JS_FRIEND_API(void)
     760               0 : DisableIncrementalGC(JSRuntime *rt)
     761                 : {
     762               0 :     rt->gcIncrementalEnabled = false;
     763               0 : }
     764                 : 
     765                 : JS_FRIEND_API(bool)
     766         1488662 : IsIncrementalBarrierNeeded(JSRuntime *rt)
     767                 : {
     768         1488662 :     return (rt->gcIncrementalState == gc::MARK && !rt->gcRunning);
     769                 : }
     770                 : 
     771                 : JS_FRIEND_API(bool)
     772               0 : IsIncrementalBarrierNeeded(JSContext *cx)
     773                 : {
     774               0 :     return IsIncrementalBarrierNeeded(cx->runtime);
     775                 : }
     776                 : 
     777                 : JS_FRIEND_API(bool)
     778        20314329 : IsIncrementalBarrierNeededOnObject(JSObject *obj)
     779                 : {
     780        20314329 :     return obj->compartment()->needsBarrier();
     781                 : }
     782                 : 
     783                 : extern JS_FRIEND_API(void)
     784          217998 : IncrementalReferenceBarrier(void *ptr)
     785                 : {
     786          217998 :     if (!ptr)
     787          217872 :         return;
     788             126 :     JS_ASSERT(!static_cast<gc::Cell *>(ptr)->compartment()->rt->gcRunning);
     789             126 :     uint32_t kind = gc::GetGCThingTraceKind(ptr);
     790             126 :     if (kind == JSTRACE_OBJECT)
     791             126 :         JSObject::writeBarrierPre((JSObject *) ptr);
     792               0 :     else if (kind == JSTRACE_STRING)
     793               0 :         JSString::writeBarrierPre((JSString *) ptr);
     794                 :     else
     795               0 :         JS_NOT_REACHED("invalid trace kind");
     796                 : }
     797                 : 
     798                 : extern JS_FRIEND_API(void)
     799               0 : IncrementalValueBarrier(const Value &v)
     800                 : {
     801               0 :     HeapValue::writeBarrierPre(v);
     802               0 : }
     803                 : 
     804                 : JS_FRIEND_API(JSObject *)
     805               0 : GetTestingFunctions(JSContext *cx)
     806                 : {
     807               0 :     JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
     808               0 :     if (!obj)
     809               0 :         return NULL;
     810                 : 
     811               0 :     if (!DefineTestingFunctions(cx, obj))
     812               0 :         return NULL;
     813                 : 
     814               0 :     return obj;
     815                 : }
     816                 : 
     817                 : } // namespace js

Generated by: LCOV version 1.7