LCOV - app.info - js/src/jscompartment.h

LCOV - code coverage report
| Current view: | directory - js/src - jscompartment.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 125 | 118 | 94.4 %
| Date: | 2012-04-07 | Functions: | 44 | 42 | 95.5 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  *
           3                 :  * ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is SpiderMonkey code.
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is
          19                 :  * Mozilla Corporation.
          20                 :  * Portions created by the Initial Developer are Copyright (C) 2010
          21                 :  * the Initial Developer. All Rights Reserved.
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *
          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                 : #ifndef jscompartment_h___
          41                 : #define jscompartment_h___
          42                 :
          43                 : #include "mozilla/Attributes.h"
          44                 :
          45                 : #include "jsclist.h"
          46                 : #include "jscntxt.h"
          47                 : #include "jsfun.h"
          48                 : #include "jsgc.h"
          49                 : #include "jsobj.h"
          50                 : #include "jsscope.h"
          51                 : #include "vm/GlobalObject.h"
          52                 : #include "vm/RegExpObject.h"
          53                 :
          54                 : #ifdef _MSC_VER
          55                 : #pragma warning(push)
          56                 : #pragma warning(disable:4251) /* Silence warning about JS_FRIEND_API and data members. */
          57                 : #endif
          58                 :
          59                 : namespace js {
          60                 :
          61                 : typedef HashMap<JSFunction *,
          62                 :                 JSString *,
          63                 :                 DefaultHasher<JSFunction *>,
          64                 :                 SystemAllocPolicy> ToSourceCache;
          65                 :
          66                 : namespace mjit {
          67                 : class JaegerCompartment;
          68                 : }
          69                 :
          70                 : /* Defined in jsapi.cpp */
          71                 : extern Class dummy_class;
          72                 :
          73                 : } /* namespace js */
          74                 :
          75                 : #ifndef JS_EVAL_CACHE_SHIFT
          76                 : # define JS_EVAL_CACHE_SHIFT        6
          77                 : #endif
          78                 :
          79                 : /* Number of buckets in the hash of eval scripts. */
          80                 : #define JS_EVAL_CACHE_SIZE          JS_BIT(JS_EVAL_CACHE_SHIFT)
          81                 :
          82                 : namespace js {
          83                 :
          84                 : class NativeIterCache {
          85                 :     static const size_t SIZE = size_t(1) << 8;
          86                 :
          87                 :     /* Cached native iterators. */
          88                 :     JSObject            *data[SIZE];
          89                 :
          90           10405 :     static size_t getIndex(uint32_t key) {
          91           10405 :         return size_t(key) % SIZE;
          92                 :     }
          93                 :
          94                 :   public:
          95                 :     /* Native iterator most recently started. */
          96                 :     JSObject            *last;
          97                 :
          98           41285 :     NativeIterCache()
          99           41285 :       : last(NULL) {
         100           41285 :         PodArrayZero(data);
         101           41285 :     }
         102                 :
         103           89042 :     void purge() {
         104           89042 :         PodArrayZero(data);
         105           89042 :         last = NULL;
         106           89042 :     }
         107                 :
         108            8720 :     JSObject *get(uint32_t key) const {
         109            8720 :         return data[getIndex(key)];
         110                 :     }
         111                 :
         112            1685 :     void set(uint32_t key, JSObject *iterobj) {
         113            1685 :         data[getIndex(key)] = iterobj;
         114            1685 :     }
         115                 : };
         116                 :
         117                 : class MathCache;
         118                 :
         119                 : /*
         120                 :  * A single-entry cache for some base-10 double-to-string conversions. This
         121                 :  * helps date-format-xparb.js.  It also avoids skewing the results for
         122                 :  * v8-splay.js when measured by the SunSpider harness, where the splay tree
         123                 :  * initialization (which includes many repeated double-to-string conversions)
         124                 :  * is erroneously included in the measurement; see bug 562553.
         125                 :  */
         126                 : class DtoaCache {
         127                 :     double        d;
         128                 :     int         base;
         129                 :     JSFixedString *s;      // if s==NULL, d and base are not valid
         130                 :   public:
         131           41285 :     DtoaCache() : s(NULL) {}
         132           89042 :     void purge() { s = NULL; }
         133                 :
         134        41750151 :     JSFixedString *lookup(int base, double d) {
         135        41750151 :         return this->s && base == this->base && d == this->d ? this->s : NULL;
         136                 :     }
         137                 :
         138        39027547 :     void cache(int base, double d, JSFixedString *s) {
         139        39027547 :         this->base = base;
         140        39027547 :         this->d = d;
         141        39027547 :         this->s = s;
         142        39027547 :     }
         143                 :
         144                 : };
         145                 :
         146                 : struct ScriptFilenameEntry
         147                 : {
         148                 :     bool marked;
         149                 :     char filename[1];
         150                 : };
         151                 :
         152                 : struct ScriptFilenameHasher
         153                 : {
         154                 :     typedef const char *Lookup;
         155         6038588 :     static HashNumber hash(const char *l) { return JS_HashString(l); }
         156         5977420 :     static bool match(const ScriptFilenameEntry *e, const char *l) {
         157         5977420 :         return strcmp(e->filename, l) == 0;
         158                 :     }
         159                 : };
         160                 :
         161                 : typedef HashSet<ScriptFilenameEntry *,
         162                 :                 ScriptFilenameHasher,
         163                 :                 SystemAllocPolicy> ScriptFilenameTable;
         164                 :
         165                 : /* If HashNumber grows, need to change WrapperHasher. */
         166                 : JS_STATIC_ASSERT(sizeof(HashNumber) == 4);
         167                 :
         168                 : struct WrapperHasher
         169                 : {
         170                 :     typedef Value Lookup;
         171                 :
         172          156380 :     static HashNumber hash(Value key) {
         173          156380 :         uint64_t bits = JSVAL_TO_IMPL(key).asBits;
         174          156380 :         return uint32_t(bits) ^ uint32_t(bits >> 32);
         175                 :     }
         176                 :
         177           66073 :     static bool match(const Value &l, const Value &k) { return l == k; }
         178                 : };
         179                 :
         180                 : typedef HashMap<Value, ReadBarrieredValue, WrapperHasher, SystemAllocPolicy> WrapperMap;
         181                 :
         182                 : } /* namespace js */
         183                 :
         184                 : namespace JS {
         185                 : struct TypeInferenceSizes;
         186                 : }
         187                 :
         188                 : struct JSCompartment
         189                 : {
         190                 :     JSRuntime                    *rt;
         191                 :     JSPrincipals                 *principals;
         192                 :
         193                 :     js::gc::ArenaLists           arenas;
         194                 :
         195                 :     bool                         needsBarrier_;
         196                 :
         197       539854494 :     bool needsBarrier() const {
         198       539854494 :         return needsBarrier_;
         199                 :     }
         200                 :
         201          152440 :     js::GCMarker *barrierTracer() {
         202          152440 :         JS_ASSERT(needsBarrier_);
         203          152440 :         return &rt->gcMarker;
         204                 :     }
         205                 :
         206                 :   private:
         207                 :     enum CompartmentGCState {
         208                 :         NoGCScheduled,
         209                 :         GCScheduled,
         210                 :         GCRunning
         211                 :     };
         212                 :
         213                 :     CompartmentGCState           gcState;
         214                 :
         215                 :   public:
         216       860227806 :     bool isCollecting() const {
         217                 :         /* Allow this if we're in the middle of an incremental GC. */
         218       860227806 :         if (rt->gcRunning) {
         219       859839113 :             return gcState == GCRunning;
         220                 :         } else {
         221          388693 :             JS_ASSERT(gcState != GCRunning);
         222          388693 :             return needsBarrier();
         223                 :         }
         224                 :     }
         225                 :
         226                 :     /*
         227                 :      * If this returns true, all object tracing must be done with a GC marking
         228                 :      * tracer.
         229                 :      */
         230       263204738 :     bool requireGCTracer() const {
         231       263204738 :         return gcState == GCRunning;
         232                 :     }
         233                 :
         234          145068 :     void setCollecting(bool collecting) {
         235          145068 :         JS_ASSERT(rt->gcRunning);
         236          145068 :         if (collecting)
         237           83796 :             gcState = GCRunning;
         238                 :         else
         239           61272 :             gcState = NoGCScheduled;
         240          145068 :     }
         241                 :
         242          181865 :     void scheduleGC() {
         243          181865 :         JS_ASSERT(!rt->gcRunning);
         244          181865 :         JS_ASSERT(gcState != GCRunning);
         245          181865 :         gcState = GCScheduled;
         246          181865 :     }
         247                 :
         248          192109 :     bool isGCScheduled() const {
         249          192109 :         return gcState == GCScheduled;
         250                 :     }
         251                 :
         252                 :     size_t                       gcBytes;
         253                 :     size_t                       gcTriggerBytes;
         254                 :     size_t                       gcMaxMallocBytes;
         255                 :
         256                 :     bool                         hold;
         257                 :     bool                         isSystemCompartment;
         258                 :
         259                 :     /*
         260                 :      * Pool for analysis and intermediate type information in this compartment.
         261                 :      * Cleared on every GC, unless the GC happens during analysis (indicated
         262                 :      * by activeAnalysis, which is implied by activeInference).
         263                 :      */
         264                 :     static const size_t TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 128 * 1024;
         265                 :     js::LifoAlloc                typeLifoAlloc;
         266                 :     bool                         activeAnalysis;
         267                 :     bool                         activeInference;
         268                 :
         269                 :     /* Type information about the scripts and objects in this compartment. */
         270                 :     js::types::TypeCompartment   types;
         271                 :
         272                 :   public:
         273                 :     /* Hashed lists of scripts created by eval to garbage-collect. */
         274                 :     JSScript                     *evalCache[JS_EVAL_CACHE_SIZE];
         275                 :
         276                 :     void                         *data;
         277                 :     bool                         active;  // GC flag, whether there are active frames
         278                 :     js::WrapperMap               crossCompartmentWrappers;
         279                 :
         280                 : #ifdef JS_METHODJIT
         281                 :   private:
         282                 :     /* This is created lazily because many compartments don't need it. */
         283                 :     js::mjit::JaegerCompartment  *jaegerCompartment_;
         284                 :     /*
         285                 :      * This function is here so that xpconnect/src/xpcjsruntime.cpp doesn't
         286                 :      * need to see the declaration of JaegerCompartment, which would require
         287                 :      * #including MethodJIT.h into xpconnect/src/xpcjsruntime.cpp, which is
         288                 :      * difficult due to reasons explained in bug 483677.
         289                 :      */
         290                 :   public:
         291         1208590 :     bool hasJaegerCompartment() {
         292         1208590 :         return !!jaegerCompartment_;
         293                 :     }
         294                 :
         295         4549189 :     js::mjit::JaegerCompartment *jaegerCompartment() const {
         296         4549189 :         JS_ASSERT(jaegerCompartment_);
         297         4549189 :         return jaegerCompartment_;
         298                 :     }
         299                 :
         300                 :     bool ensureJaegerCompartmentExists(JSContext *cx);
         301                 :
         302                 :     size_t sizeOfMjitCode() const;
         303                 : #endif
         304                 :
         305                 :     js::RegExpCompartment        regExps;
         306                 :
         307                 :     size_t sizeOfShapeTable(JSMallocSizeOfFun mallocSizeOf);
         308                 :     void sizeOfTypeInferenceData(JS::TypeInferenceSizes *stats, JSMallocSizeOfFun mallocSizeOf);
         309                 :
         310                 :     /*
         311                 :      * Shared scope property tree, and arena-pool for allocating its nodes.
         312                 :      */
         313                 :     js::PropertyTree             propertyTree;
         314                 :
         315                 :     /* Set of all unowned base shapes in the compartment. */
         316                 :     js::BaseShapeSet             baseShapes;
         317                 :     void sweepBaseShapeTable();
         318                 :
         319                 :     /* Set of initial shapes in the compartment. */
         320                 :     js::InitialShapeSet          initialShapes;
         321                 :     void sweepInitialShapeTable();
         322                 :
         323                 :     /* Set of default 'new' or lazy types in the compartment. */
         324                 :     js::types::TypeObjectSet     newTypeObjects;
         325                 :     js::types::TypeObjectSet     lazyTypeObjects;
         326                 :     void sweepNewTypeObjectTable(js::types::TypeObjectSet &table);
         327                 :
         328                 :     js::types::TypeObject        *emptyTypeObject;
         329                 :
         330                 :     /* Get the default 'new' type for objects with a NULL prototype. */
         331                 :     inline js::types::TypeObject *getEmptyType(JSContext *cx);
         332                 :
         333                 :     js::types::TypeObject *getLazyType(JSContext *cx, JSObject *proto);
         334                 :
         335                 :     /* Cache to speed up object creation. */
         336                 :     js::NewObjectCache           newObjectCache;
         337                 :
         338                 :     /*
         339                 :      * Keeps track of the total number of malloc bytes connected to a
         340                 :      * compartment's GC things. This counter should be used in preference to
         341                 :      * gcMallocBytes. These counters affect collection in the same way as
         342                 :      * gcBytes and gcTriggerBytes.
         343                 :      */
         344                 :     size_t                       gcMallocAndFreeBytes;
         345                 :     size_t                       gcTriggerMallocAndFreeBytes;
         346                 :
         347                 :   private:
         348                 :     /*
         349                 :      * Malloc counter to measure memory pressure for GC scheduling. It runs from
         350                 :      * gcMaxMallocBytes down to zero. This counter should be used only when it's
         351                 :      * not possible to know the size of a free.
         352                 :      */
         353                 :     ptrdiff_t                    gcMallocBytes;
         354                 :
         355                 :     enum { DebugFromC = 1, DebugFromJS = 2 };
         356                 :
         357                 :     unsigned                     debugModeBits;  // see debugMode() below
         358                 :
         359                 :   public:
         360                 :     js::NativeIterCache          nativeIterCache;
         361                 :
         362                 :     typedef js::Maybe<js::ToSourceCache> LazyToSourceCache;
         363                 :     LazyToSourceCache            toSourceCache;
         364                 :
         365                 :     js::ScriptFilenameTable      scriptFilenameTable;
         366                 :
         367                 :     JSCompartment(JSRuntime *rt);
         368                 :     ~JSCompartment();
         369                 :
         370                 :     bool init(JSContext *cx);
         371                 :
         372                 :     /* Mark cross-compartment wrappers. */
         373                 :     void markCrossCompartmentWrappers(JSTracer *trc);
         374                 :
         375                 :     bool wrap(JSContext *cx, js::Value *vp);
         376                 :     bool wrap(JSContext *cx, JSString **strp);
         377                 :     bool wrap(JSContext *cx, js::HeapPtrString *strp);
         378                 :     bool wrap(JSContext *cx, JSObject **objp);
         379                 :     bool wrapId(JSContext *cx, jsid *idp);
         380                 :     bool wrap(JSContext *cx, js::PropertyOp *op);
         381                 :     bool wrap(JSContext *cx, js::StrictPropertyOp *op);
         382                 :     bool wrap(JSContext *cx, js::PropertyDescriptor *desc);
         383                 :     bool wrap(JSContext *cx, js::AutoIdVector &props);
         384                 :
         385                 :     void markTypes(JSTracer *trc);
         386                 :     void discardJitCode(js::FreeOp *fop);
         387                 :     void sweep(js::FreeOp *fop, bool releaseTypes);
         388                 :     void purge();
         389                 :
         390                 :     void setGCLastBytes(size_t lastBytes, size_t lastMallocBytes, js::JSGCInvocationKind gckind);
         391                 :     void reduceGCTriggerBytes(size_t amount);
         392                 :
         393                 :     void resetGCMallocBytes();
         394                 :     void setGCMaxMallocBytes(size_t value);
         395        16143748 :     void updateMallocCounter(size_t nbytes) {
         396        16143748 :         ptrdiff_t oldCount = gcMallocBytes;
         397        16143748 :         ptrdiff_t newCount = oldCount - ptrdiff_t(nbytes);
         398        16143748 :         gcMallocBytes = newCount;
         399        16143748 :         if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
         400             108 :             onTooMuchMalloc();
         401        16143748 :     }
         402                 :
         403                 :     void onTooMuchMalloc();
         404                 :
         405               0 :     void mallocInCompartment(size_t nbytes) {
         406               0 :         gcMallocAndFreeBytes += nbytes;
         407               0 :     }
         408                 :
         409               0 :     void freeInCompartment(size_t nbytes) {
         410               0 :         JS_ASSERT(gcMallocAndFreeBytes >= nbytes);
         411               0 :         gcMallocAndFreeBytes -= nbytes;
         412               0 :     }
         413                 :
         414                 :     js::DtoaCache dtoaCache;
         415                 :
         416                 :   private:
         417                 :     js::MathCache                *mathCache;
         418                 :
         419                 :     js::MathCache *allocMathCache(JSContext *cx);
         420                 :
         421                 :     /*
         422                 :      * Weak reference to each global in this compartment that is a debuggee.
         423                 :      * Each global has its own list of debuggers.
         424                 :      */
         425                 :     js::GlobalObjectSet              debuggees;
         426                 :
         427                 :   private:
         428           41285 :     JSCompartment *thisForCtor() { return this; }
         429                 :
         430                 :   public:
         431         2850876 :     js::MathCache *getMathCache(JSContext *cx) {
         432         2850876 :         return mathCache ? mathCache : allocMathCache(cx);
         433                 :     }
         434                 :
         435                 :     /*
         436                 :      * There are dueling APIs for debug mode. It can be enabled or disabled via
         437                 :      * JS_SetDebugModeForCompartment. It is automatically enabled and disabled
         438                 :      * by Debugger objects. Therefore debugModeBits has the DebugFromC bit set
         439                 :      * if the C API wants debug mode and the DebugFromJS bit set if debuggees
         440                 :      * is non-empty.
         441                 :      */
         442        22530077 :     bool debugMode() const { return !!debugModeBits; }
         443                 :
         444                 :     /* True if any scripts from this compartment are on the JS stack. */
         445                 :     bool hasScriptsOnStack();
         446                 :
         447                 :   private:
         448                 :     /* This is called only when debugMode() has just toggled. */
         449                 :     void updateForDebugMode(js::FreeOp *fop);
         450                 :
         451                 :   public:
         452        28456831 :     js::GlobalObjectSet &getDebuggees() { return debuggees; }
         453                 :     bool addDebuggee(JSContext *cx, js::GlobalObject *global);
         454                 :     void removeDebuggee(js::FreeOp *fop, js::GlobalObject *global,
         455                 :                         js::GlobalObjectSet::Enum *debuggeesEnum = NULL);
         456                 :     bool setDebugModeFromC(JSContext *cx, bool b);
         457                 :
         458                 :     void clearBreakpointsIn(JSContext *cx, js::Debugger *dbg, JSObject *handler);
         459                 :     void clearTraps(JSContext *cx);
         460                 :
         461                 :   private:
         462                 :     void sweepBreakpoints(js::FreeOp *fop);
         463                 :
         464                 :   public:
         465                 :     js::WatchpointMap *watchpointMap;
         466                 : };
         467                 :
         468                 : #define JS_PROPERTY_TREE(cx)    ((cx)->compartment->propertyTree)
         469                 :
         470                 : namespace js {
         471                 : static inline MathCache *
         472         2850876 : GetMathCache(JSContext *cx)
         473                 : {
         474         2850876 :     return cx->compartment->getMathCache(cx);
         475                 : }
         476                 : }
         477                 :
         478                 : inline void
         479        12139038 : JSContext::setCompartment(JSCompartment *compartment)
         480                 : {
         481        12139038 :     this->compartment = compartment;
         482        12139038 :     this->inferenceEnabled = compartment ? compartment->types.inferenceEnabled : false;
         483        12139038 : }
         484                 :
         485                 : #ifdef _MSC_VER
         486                 : #pragma warning(pop)
         487                 : #endif
         488                 :
         489                 : namespace js {
         490                 :
         491                 : class PreserveCompartment {
         492                 :   protected:
         493                 :     JSContext *cx;
         494                 :   private:
         495                 :     JSCompartment *oldCompartment;
         496                 :     bool oldInferenceEnabled;
         497                 :     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
         498                 :   public:
         499        11883986 :      PreserveCompartment(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM) : cx(cx) {
         500        11883986 :         JS_GUARD_OBJECT_NOTIFIER_INIT;
         501        11883986 :         oldCompartment = cx->compartment;
         502        11883986 :         oldInferenceEnabled = cx->inferenceEnabled;
         503        11883986 :     }
         504                 :
         505        23767972 :     ~PreserveCompartment() {
         506                 :         /* The old compartment may have been destroyed, so we can't use cx->setCompartment. */
         507        11883986 :         cx->compartment = oldCompartment;
         508        11883986 :         cx->inferenceEnabled = oldInferenceEnabled;
         509        11883986 :     }
         510                 : };
         511                 :
         512        11883986 : class SwitchToCompartment : public PreserveCompartment {
         513                 :   public:
         514        11883986 :     SwitchToCompartment(JSContext *cx, JSCompartment *newCompartment
         515                 :                         JS_GUARD_OBJECT_NOTIFIER_PARAM)
         516        11883986 :         : PreserveCompartment(cx)
         517                 :     {
         518        11883986 :         JS_GUARD_OBJECT_NOTIFIER_INIT;
         519        11883986 :         cx->setCompartment(newCompartment);
         520        11883986 :     }
         521                 :
         522                 :     SwitchToCompartment(JSContext *cx, JSObject *target JS_GUARD_OBJECT_NOTIFIER_PARAM)
         523                 :         : PreserveCompartment(cx)
         524                 :     {
         525                 :         JS_GUARD_OBJECT_NOTIFIER_INIT;
         526                 :         cx->setCompartment(target->compartment());
         527                 :     }
         528                 :
         529                 :     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
         530                 : };
         531                 :
         532                 : class AssertCompartmentUnchanged {
         533                 :   protected:
         534                 :     JSContext * const cx;
         535                 :     JSCompartment * const oldCompartment;
         536                 :     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
         537                 :   public:
         538         1189174 :      AssertCompartmentUnchanged(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM)
         539         1189174 :      : cx(cx), oldCompartment(cx->compartment) {
         540         1189174 :         JS_GUARD_OBJECT_NOTIFIER_INIT;
         541         1189174 :     }
         542                 :
         543         2378348 :     ~AssertCompartmentUnchanged() {
         544         1189174 :         JS_ASSERT(cx->compartment == oldCompartment);
         545         1189174 :     }
         546                 : };
         547                 :
         548                 : class AutoCompartment
         549                 : {
         550                 :   public:
         551                 :     JSContext * const context;
         552                 :     JSCompartment * const origin;
         553                 :     JSObject * const target;
         554                 :     JSCompartment * const destination;
         555                 :   private:
         556                 :     Maybe<DummyFrameGuard> frame;
         557                 :     bool entered;
         558                 :
         559                 :   public:
         560                 :     AutoCompartment(JSContext *cx, JSObject *target);
         561                 :     ~AutoCompartment();
         562                 :
         563                 :     bool enter();
         564                 :     void leave();
         565                 :
         566                 :   private:
         567                 :     AutoCompartment(const AutoCompartment &) MOZ_DELETE;
         568                 :     AutoCompartment & operator=(const AutoCompartment &) MOZ_DELETE;
         569                 : };
         570                 :
         571                 : /*
         572                 :  * Use this to change the behavior of an AutoCompartment slightly on error. If
         573                 :  * the exception happens to be an Error object, copy it to the origin compartment
         574                 :  * instead of wrapping it.
         575                 :  */
         576                 : class ErrorCopier
         577                 : {
         578                 :     AutoCompartment &ac;
         579                 :     JSObject *scope;
         580                 :
         581                 :   public:
         582            9981 :     ErrorCopier(AutoCompartment &ac, JSObject *scope) : ac(ac), scope(scope) {
         583            9981 :         JS_ASSERT(scope->compartment() == ac.origin);
         584            9981 :     }
         585                 :     ~ErrorCopier();
         586                 : };
         587                 :
         588                 : class CompartmentsIter {
         589                 :   private:
         590                 :     JSCompartment **it, **end;
         591                 :
         592                 :   public:
         593          745252 :     CompartmentsIter(JSRuntime *rt) {
         594          745252 :         it = rt->compartments.begin();
         595          745252 :         end = rt->compartments.end();
         596          745252 :     }
         597                 :
         598         5772921 :     bool done() const { return it == end; }
         599                 :
         600         1569153 :     void next() {
         601         1569153 :         JS_ASSERT(!done());
         602         1569153 :         it++;
         603         1569153 :     }
         604                 :
         605         1889363 :     JSCompartment *get() const {
         606         1889363 :         JS_ASSERT(!done());
         607         1889363 :         return *it;
         608                 :     }
         609                 :
         610           95544 :     operator JSCompartment *() const { return get(); }
         611         1775058 :     JSCompartment *operator->() const { return get(); }
         612                 : };
         613                 :
         614                 : } /* namespace js */
         615                 :
         616                 : #endif /* jscompartment_h___ */

Generated by: LCOV version 1.7