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

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