LCOV - code coverage report
Current view: directory - js/src - jsfriendapi.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 358 52 14.5 %
Date: 2012-04-07 Functions: 85 10 11.8 %

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

Generated by: LCOV version 1.7