Bug 988486 - Re-organize Zone to save some space and increase readability; r=jonco
authorTerrence Cole <terrence@mozilla.com>
Fri, 16 May 2014 11:24:23 -0700
changeset 184771 eca41f62ac61c48060449c4e6621aacb6e220322
parent 184770 f50bbf4738d05a35c016abb116cfc0dd40a282fb
child 184772 67fe1ff27cadbf66000eb53514bdc6f5c62e0ed8
push id26836
push usercbook@mozilla.com
push dateMon, 26 May 2014 12:37:49 +0000
treeherdermozilla-central@5cd52de816f9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs988486
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 988486 - Re-organize Zone to save some space and increase readability; r=jonco
js/src/gc/Zone.cpp
js/src/gc/Zone.h
--- a/js/src/gc/Zone.cpp
+++ b/js/src/gc/Zone.cpp
@@ -19,36 +19,35 @@
 #include "jsgcinlines.h"
 
 using namespace js;
 using namespace js::gc;
 
 JS::Zone::Zone(JSRuntime *rt)
   : JS::shadow::Zone(rt, &rt->gc.marker),
     allocator(this),
-    ionUsingBarriers_(false),
-    active(false),
-    gcScheduled(false),
-    gcState(NoGC),
-    gcPreserveCode(false),
+    types(this),
+    compartments(),
+    gcGrayRoots(),
+    gcHeapGrowthFactor(3.0),
+    gcMallocBytes(0),
+    gcMallocGCTriggered(false),
     gcBytes(0),
     gcTriggerBytes(0),
-    gcHeapGrowthFactor(3.0),
+    data(nullptr),
     isSystem(false),
     usedByExclusiveThread(false),
     scheduledForDestruction(false),
     maybeAlive(true),
-    gcMallocBytes(0),
-    gcMallocGCTriggered(false),
-    gcGrayRoots(),
-    data(nullptr),
-    types(this)
-#ifdef JS_ION
-    , jitZone_(nullptr)
-#endif
+    active(false),
+    jitZone_(nullptr),
+    gcState_(NoGC),
+    gcScheduled_(false),
+    gcPreserveCode_(false),
+    ionUsingBarriers_(false)
 {
     /* Ensure that there are no vtables to mess us up here. */
     JS_ASSERT(reinterpret_cast<JS::shadow::Zone *>(this) ==
               static_cast<JS::shadow::Zone *>(this));
 
     setGCMaxMallocBytes(rt->gc.maxMallocBytes * 0.9);
 }
 
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -18,371 +18,296 @@
 #include "gc/FindSCCs.h"
 
 namespace js {
 
 namespace jit {
 class JitZone;
 }
 
-/*
- * Encapsulates the data needed to perform allocation.  Typically there is
- * precisely one of these per zone (|cx->zone().allocator|).  However, in
- * parallel execution mode, there will be one per worker thread.
- */
+// Encapsulates the data needed to perform allocation. Typically there is
+// precisely one of these per zone (|cx->zone().allocator|). However, in
+// parallel execution mode, there will be one per worker thread.
 class Allocator
 {
-    /*
-     * Since allocators can be accessed from worker threads, the parent zone_
-     * should not be accessed in general. ArenaLists is allowed to actually do
-     * the allocation, however.
-     */
-    friend class gc::ArenaLists;
-
-    JS::Zone *zone_;
-
   public:
     explicit Allocator(JS::Zone *zone);
 
     js::gc::ArenaLists arenas;
+
+  private:
+    // Since allocators can be accessed from worker threads, the parent zone_
+    // should not be accessed in general. ArenaLists is allowed to actually do
+    // the allocation, however.
+    friend class gc::ArenaLists;
+
+    JS::Zone *zone_;
 };
 
-typedef Vector<JSCompartment *, 1, SystemAllocPolicy> CompartmentVector;
-
-} /* namespace js */
+} // namespace js
 
 namespace JS {
 
-/*
- * A zone is a collection of compartments. Every compartment belongs to exactly
- * one zone. In Firefox, there is roughly one zone per tab along with a system
- * zone for everything else. Zones mainly serve as boundaries for garbage
- * collection. Unlike compartments, they have no special security properties.
- *
- * Every GC thing belongs to exactly one zone. GC things from the same zone but
- * different compartments can share an arena (4k page). GC things from different
- * zones cannot be stored in the same arena. The garbage collector is capable of
- * collecting one zone at a time; it cannot collect at the granularity of
- * compartments.
- *
- * GC things are tied to zones and compartments as follows:
- *
- * - JSObjects belong to a compartment and cannot be shared between
- *   compartments. If an object needs to point to a JSObject in a different
- *   compartment, regardless of zone, it must go through a cross-compartment
- *   wrapper. Each compartment keeps track of its outgoing wrappers in a table.
- *
- * - JSStrings do not belong to any particular compartment, but they do belong
- *   to a zone. Thus, two different compartments in the same zone can point to a
- *   JSString. When a string needs to be wrapped, we copy it if it's in a
- *   different zone and do nothing if it's in the same zone. Thus, transferring
- *   strings within a zone is very efficient.
- *
- * - Shapes and base shapes belong to a compartment and cannot be shared between
- *   compartments. A base shape holds a pointer to its compartment. Shapes find
- *   their compartment via their base shape. JSObjects find their compartment
- *   via their shape.
- *
- * - Scripts are also compartment-local and cannot be shared. A script points to
- *   its compartment.
- *
- * - Type objects and JitCode objects belong to a compartment and cannot be
- *   shared. However, there is no mechanism to obtain their compartments.
- *
- * A zone remains alive as long as any GC things in the zone are alive. A
- * compartment remains alive as long as any JSObjects, scripts, shapes, or base
- * shapes within it are alive.
- *
- * We always guarantee that a zone has at least one live compartment by refusing
- * to delete the last compartment in a live zone. (This could happen, for
- * example, if the conservative scanner marks a string in an otherwise dead
- * zone.)
- */
-
+// A zone is a collection of compartments. Every compartment belongs to exactly
+// one zone. In Firefox, there is roughly one zone per tab along with a system
+// zone for everything else. Zones mainly serve as boundaries for garbage
+// collection. Unlike compartments, they have no special security properties.
+//
+// Every GC thing belongs to exactly one zone. GC things from the same zone but
+// different compartments can share an arena (4k page). GC things from different
+// zones cannot be stored in the same arena. The garbage collector is capable of
+// collecting one zone at a time; it cannot collect at the granularity of
+// compartments.
+//
+// GC things are tied to zones and compartments as follows:
+//
+// - JSObjects belong to a compartment and cannot be shared between
+//   compartments. If an object needs to point to a JSObject in a different
+//   compartment, regardless of zone, it must go through a cross-compartment
+//   wrapper. Each compartment keeps track of its outgoing wrappers in a table.
+//
+// - JSStrings do not belong to any particular compartment, but they do belong
+//   to a zone. Thus, two different compartments in the same zone can point to a
+//   JSString. When a string needs to be wrapped, we copy it if it's in a
+//   different zone and do nothing if it's in the same zone. Thus, transferring
+//   strings within a zone is very efficient.
+//
+// - Shapes and base shapes belong to a compartment and cannot be shared between
+//   compartments. A base shape holds a pointer to its compartment. Shapes find
+//   their compartment via their base shape. JSObjects find their compartment
+//   via their shape.
+//
+// - Scripts are also compartment-local and cannot be shared. A script points to
+//   its compartment.
+//
+// - Type objects and JitCode objects belong to a compartment and cannot be
+//   shared. However, there is no mechanism to obtain their compartments.
+//
+// A zone remains alive as long as any GC things in the zone are alive. A
+// compartment remains alive as long as any JSObjects, scripts, shapes, or base
+// shapes within it are alive.
+//
+// We always guarantee that a zone has at least one live compartment by refusing
+// to delete the last compartment in a live zone. (This could happen, for
+// example, if the conservative scanner marks a string in an otherwise dead
+// zone.)
 struct Zone : public JS::shadow::Zone,
               public js::gc::GraphNodeBase<JS::Zone>,
               public js::MallocProvider<JS::Zone>
 {
-  private:
-    friend bool js::CurrentThreadCanAccessZone(Zone *zone);
-    friend class js::gc::GCRuntime;
-
-  public:
-    js::Allocator                allocator;
-
-    js::CompartmentVector        compartments;
-
-  private:
-    bool                         ionUsingBarriers_;
-
-  public:
-    bool                         active;  // GC flag, whether there are active frames
-
-    bool compileBarriers(bool needsBarrier) const {
-        return needsBarrier || runtimeFromMainThread()->gcZeal() == js::gc::ZealVerifierPreValue;
-    }
-
-    bool compileBarriers() const {
-        return compileBarriers(needsBarrier());
-    }
-
-    enum ShouldUpdateIon {
-        DontUpdateIon,
-        UpdateIon
-    };
-
-    void setNeedsBarrier(bool needs, ShouldUpdateIon updateIon);
-
-    const bool *addressOfNeedsBarrier() const {
-        return &needsBarrier_;
-    }
-
-  public:
-    enum GCState {
-        NoGC,
-        Mark,
-        MarkGray,
-        Sweep,
-        Finished
-    };
-
-  private:
-    bool                         gcScheduled;
-    GCState                      gcState;
-    bool                         gcPreserveCode;
-    mozilla::DebugOnly<unsigned> gcLastZoneGroupIndex;
-
-  public:
-    bool isCollecting() const {
-        if (runtimeFromMainThread()->isHeapCollecting())
-            return gcState != NoGC;
-        else
-            return needsBarrier();
-    }
-
-    bool isPreservingCode() const {
-        return gcPreserveCode;
-    }
-
-    /*
-     * If this returns true, all object tracing must be done with a GC marking
-     * tracer.
-     */
-    bool requireGCTracer() const {
-        return runtimeFromMainThread()->isHeapMajorCollecting() && gcState != NoGC;
-    }
-
-    void setGCState(GCState state) {
-        JS_ASSERT(runtimeFromMainThread()->isHeapBusy());
-        JS_ASSERT_IF(state != NoGC, canCollect());
-        gcState = state;
-    }
-
-    void scheduleGC() {
-        JS_ASSERT(!runtimeFromMainThread()->isHeapBusy());
-        gcScheduled = true;
-    }
-
-    void unscheduleGC() {
-        gcScheduled = false;
-    }
-
-    bool isGCScheduled() {
-        return gcScheduled && canCollect();
-    }
-
-    void setPreservingCode(bool preserving) {
-        gcPreserveCode = preserving;
-    }
-
-    bool canCollect() {
-        // Zones cannot be collected while in use by other threads.
-        if (usedByExclusiveThread)
-            return false;
-        JSRuntime *rt = runtimeFromAnyThread();
-        if (rt->isAtomsZone(this) && rt->exclusiveThreadsPresent())
-            return false;
-        return true;
-    }
-
-    bool wasGCStarted() const {
-        return gcState != NoGC;
-    }
-
-    bool isGCMarking() {
-        if (runtimeFromMainThread()->isHeapCollecting())
-            return gcState == Mark || gcState == MarkGray;
-        else
-            return needsBarrier();
-    }
-
-    bool isGCMarkingBlack() {
-        return gcState == Mark;
-    }
-
-    bool isGCMarkingGray() {
-        return gcState == MarkGray;
-    }
-
-    bool isGCSweeping() {
-        return gcState == Sweep;
-    }
-
-    bool isGCFinished() {
-        return gcState == Finished;
-    }
-
-#ifdef DEBUG
-    /*
-     * For testing purposes, return the index of the zone group which this zone
-     * was swept in in the last GC.
-     */
-    unsigned lastZoneGroupIndex() {
-        return gcLastZoneGroupIndex;
-    }
-#endif
-
-    /* This is updated by both the main and GC helper threads. */
-    mozilla::Atomic<size_t, mozilla::ReleaseAcquire> gcBytes;
-
-    size_t                       gcTriggerBytes;
-    size_t                       gcMaxMallocBytes;
-    double                       gcHeapGrowthFactor;
-
-    bool                         isSystem;
-
-    /* Whether this zone is being used by a thread with an ExclusiveContext. */
-    bool usedByExclusiveThread;
-
-    /*
-     * Get a number that is incremented whenever this zone is collected, and
-     * possibly at other times too.
-     */
-    uint64_t gcNumber();
-
-    /*
-     * These flags help us to discover if a compartment that shouldn't be alive
-     * manages to outlive a GC.
-     */
-    bool                         scheduledForDestruction;
-    bool                         maybeAlive;
-
-    /*
-     * Malloc counter to measure memory pressure for GC scheduling. It runs from
-     * gcMaxMallocBytes down to zero. This counter should be used only when it's
-     * not possible to know the size of a free.
-     */
-    mozilla::Atomic<ptrdiff_t, mozilla::ReleaseAcquire> gcMallocBytes;
-
-    /*
-     * Whether a GC has been triggered as a result of gcMallocBytes falling
-     * below zero.
-     *
-     * This should be a bool, but Atomic only supports 32-bit and pointer-sized
-     * types.
-     */
-    mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> gcMallocGCTriggered;
-
-    /* This compartment's gray roots. */
-    js::Vector<js::GrayRoot, 0, js::SystemAllocPolicy> gcGrayRoots;
-
-    /*
-     * A set of edges from this zone to other zones.
-     *
-     * This is used during GC while calculating zone groups to record edges that
-     * can't be determined by examining this zone by itself.
-     */
-    typedef js::HashSet<Zone *, js::DefaultHasher<Zone *>, js::SystemAllocPolicy> ZoneSet;
-    ZoneSet gcZoneGroupEdges;
-
-    /* Per-zone data for use by an embedder. */
-    void *data;
-
     Zone(JSRuntime *rt);
     ~Zone();
-
     bool init();
 
     void findOutgoingEdges(js::gc::ComponentFinder<JS::Zone> &finder);
 
     void discardJitCode(js::FreeOp *fop);
 
     void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
                                 size_t *typePool,
                                 size_t *baselineStubsOptimized);
 
     void setGCLastBytes(size_t lastBytes, js::JSGCInvocationKind gckind);
     void reduceGCTriggerBytes(size_t amount);
 
     void resetGCMallocBytes();
     void setGCMaxMallocBytes(size_t value);
     void updateMallocCounter(size_t nbytes) {
-        /*
-         * Note: this code may be run from worker threads.  We
-         * tolerate any thread races when updating gcMallocBytes.
-         */
+        // Note: this code may be run from worker threads. We tolerate any
+        // thread races when updating gcMallocBytes.
         gcMallocBytes -= ptrdiff_t(nbytes);
         if (MOZ_UNLIKELY(isTooMuchMalloc()))
             onTooMuchMalloc();
     }
 
-    bool isTooMuchMalloc() const {
-        return gcMallocBytes <= 0;
-     }
-
+    bool isTooMuchMalloc() const { return gcMallocBytes <= 0; }
     void onTooMuchMalloc();
 
     void *onOutOfMemory(void *p, size_t nbytes) {
         return runtimeFromMainThread()->onOutOfMemory(p, nbytes);
     }
-    void reportAllocationOverflow() {
-        js_ReportAllocationOverflow(nullptr);
-    }
-
-    js::types::TypeZone types;
+    void reportAllocationOverflow() { js_ReportAllocationOverflow(nullptr); }
 
     void sweep(js::FreeOp *fop, bool releaseTypes, bool *oom);
 
     bool hasMarkedCompartments();
 
+    void scheduleGC() { JS_ASSERT(!runtimeFromMainThread()->isHeapBusy()); gcScheduled_ = true; }
+    void unscheduleGC() { gcScheduled_ = false; }
+    bool isGCScheduled() { return gcScheduled_ && canCollect(); }
+
+    void setPreservingCode(bool preserving) { gcPreserveCode_ = preserving; }
+    bool isPreservingCode() const { return gcPreserveCode_; }
+
+    bool canCollect() {
+        // Zones cannot be collected while in use by other threads.
+        if (usedByExclusiveThread)
+            return false;
+        JSRuntime *rt = runtimeFromAnyThread();
+        if (rt->isAtomsZone(this) && rt->exclusiveThreadsPresent())
+            return false;
+        return true;
+    }
+
+    enum GCState {
+        NoGC,
+        Mark,
+        MarkGray,
+        Sweep,
+        Finished
+    };
+    void setGCState(GCState state) {
+        JS_ASSERT(runtimeFromMainThread()->isHeapBusy());
+        JS_ASSERT_IF(state != NoGC, canCollect());
+        gcState_ = state;
+    }
+
+    bool isCollecting() const {
+        if (runtimeFromMainThread()->isHeapCollecting())
+            return gcState_ != NoGC;
+        else
+            return needsBarrier();
+    }
+
+    // If this returns true, all object tracing must be done with a GC marking
+    // tracer.
+    bool requireGCTracer() const {
+        return runtimeFromMainThread()->isHeapMajorCollecting() && gcState_ != NoGC;
+    }
+
+    bool isGCMarking() {
+        if (runtimeFromMainThread()->isHeapCollecting())
+            return gcState_ == Mark || gcState_ == MarkGray;
+        else
+            return needsBarrier();
+    }
+
+    bool wasGCStarted() const { return gcState_ != NoGC; }
+    bool isGCMarkingBlack() { return gcState_ == Mark; }
+    bool isGCMarkingGray() { return gcState_ == MarkGray; }
+    bool isGCSweeping() { return gcState_ == Sweep; }
+    bool isGCFinished() { return gcState_ == Finished; }
+
+    // Get a number that is incremented whenever this zone is collected, and
+    // possibly at other times too.
+    uint64_t gcNumber();
+
+    bool compileBarriers() const { return compileBarriers(needsBarrier()); }
+    bool compileBarriers(bool needsBarrier) const {
+        return needsBarrier || runtimeFromMainThread()->gcZeal() == js::gc::ZealVerifierPreValue;
+    }
+
+    enum ShouldUpdateIon { DontUpdateIon, UpdateIon };
+    void setNeedsBarrier(bool needs, ShouldUpdateIon updateIon);
+    const bool *addressOfNeedsBarrier() const { return &needsBarrier_; }
+
+    js::jit::JitZone *getJitZone(JSContext *cx) { return jitZone_ ? jitZone_ : createJitZone(cx); }
+    js::jit::JitZone *jitZone() { return jitZone_; }
+
+#ifdef DEBUG
+    // For testing purposes, return the index of the zone group which this zone
+    // was swept in in the last GC.
+    unsigned lastZoneGroupIndex() { return gcLastZoneGroupIndex; }
+#endif
+
   private:
     void sweepBreakpoints(js::FreeOp *fop);
     void sweepCompartments(js::FreeOp *fop, bool keepAtleastOne, bool lastGC);
 
-#ifdef JS_ION
-    js::jit::JitZone *jitZone_;
     js::jit::JitZone *createJitZone(JSContext *cx);
 
   public:
-    js::jit::JitZone *getJitZone(JSContext *cx) {
-        return jitZone_ ? jitZone_ : createJitZone(cx);
-    }
-    js::jit::JitZone *jitZone() {
-        return jitZone_;
-    }
-#endif
+    js::Allocator allocator;
+
+    js::types::TypeZone types;
+
+    // The set of compartments in this zone.
+    typedef js::Vector<JSCompartment *, 1, js::SystemAllocPolicy> CompartmentVector;
+    CompartmentVector compartments;
+
+    // This compartment's gray roots.
+    typedef js::Vector<js::GrayRoot, 0, js::SystemAllocPolicy> GrayRootVector;
+    GrayRootVector gcGrayRoots;
+
+    // A set of edges from this zone to other zones.
+    //
+    // This is used during GC while calculating zone groups to record edges that
+    // can't be determined by examining this zone by itself.
+    typedef js::HashSet<Zone *, js::DefaultHasher<Zone *>, js::SystemAllocPolicy> ZoneSet;
+    ZoneSet gcZoneGroupEdges;
+
+    // The "growth factor" for computing our next thresholds after a GC.
+    double gcHeapGrowthFactor;
+
+    // Malloc counter to measure memory pressure for GC scheduling. It runs from
+    // gcMaxMallocBytes down to zero. This counter should be used only when it's
+    // not possible to know the size of a free.
+    mozilla::Atomic<ptrdiff_t, mozilla::ReleaseAcquire> gcMallocBytes;
+
+    // GC trigger threshold for allocations on the C heap.
+    size_t gcMaxMallocBytes;
+
+    // Whether a GC has been triggered as a result of gcMallocBytes falling
+    // below zero.
+    //
+    // This should be a bool, but Atomic only supports 32-bit and pointer-sized
+    // types.
+    mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> gcMallocGCTriggered;
+
+    // Counts the number of bytes allocated in the GC heap for this zone. It is
+    // updated by both the main and GC helper threads.
+    mozilla::Atomic<size_t, mozilla::ReleaseAcquire> gcBytes;
+
+    // GC trigger threshold for allocations on the GC heap.
+    size_t gcTriggerBytes;
+
+    // Per-zone data for use by an embedder.
+    void *data;
+
+    bool isSystem;
+
+    bool usedByExclusiveThread;
+
+    // These flags help us to discover if a compartment that shouldn't be alive
+    // manages to outlive a GC.
+    bool scheduledForDestruction;
+    bool maybeAlive;
+
+    // True when there are active frames.
+    bool active;
+
+    mozilla::DebugOnly<unsigned> gcLastZoneGroupIndex;
+
+  private:
+    js::jit::JitZone *jitZone_;
+
+    GCState gcState_;
+    bool gcScheduled_;
+    bool gcPreserveCode_;
+    bool ionUsingBarriers_;
+
+    friend bool js::CurrentThreadCanAccessZone(Zone *zone);
+    friend class js::gc::GCRuntime;
 };
 
-} /* namespace JS */
+} // namespace JS
 
 namespace js {
 
-/*
- * Using the atoms zone without holding the exclusive access lock is dangerous
- * because worker threads may be using it simultaneously. Therefore, it's
- * better to skip the atoms zone when iterating over zones. If you need to
- * iterate over the atoms zone, consider taking the exclusive access lock first.
- */
+// Using the atoms zone without holding the exclusive access lock is dangerous
+// because worker threads may be using it simultaneously. Therefore, it's
+// better to skip the atoms zone when iterating over zones. If you need to
+// iterate over the atoms zone, consider taking the exclusive access lock first.
 enum ZoneSelector {
     WithAtoms,
     SkipAtoms
 };
 
-class ZonesIter {
-  private:
+class ZonesIter
+{
     JS::Zone **it, **end;
 
   public:
     ZonesIter(JSRuntime *rt, ZoneSelector selector) {
         it = rt->gc.zones.begin();
         end = rt->gc.zones.end();
 
         if (selector == SkipAtoms) {
@@ -406,26 +331,16 @@ class ZonesIter {
     }
 
     operator JS::Zone *() const { return get(); }
     JS::Zone *operator->() const { return get(); }
 };
 
 struct CompartmentsInZoneIter
 {
-    // This is for the benefit of CompartmentsIterT::comp.
-    friend class mozilla::Maybe<CompartmentsInZoneIter>;
-  private:
-    JSCompartment **it, **end;
-
-    CompartmentsInZoneIter()
-      : it(nullptr), end(nullptr)
-    {}
-
-  public:
     explicit CompartmentsInZoneIter(JS::Zone *zone) {
         it = zone->compartments.begin();
         end = zone->compartments.end();
     }
 
     bool done() const {
         JS_ASSERT(it);
         return it == end;
@@ -437,26 +352,33 @@ struct CompartmentsInZoneIter
 
     JSCompartment *get() const {
         JS_ASSERT(it);
         return *it;
     }
 
     operator JSCompartment *() const { return get(); }
     JSCompartment *operator->() const { return get(); }
+
+  private:
+    JSCompartment **it, **end;
+
+    CompartmentsInZoneIter()
+      : it(nullptr), end(nullptr)
+    {}
+
+    // This is for the benefit of CompartmentsIterT::comp.
+    friend class mozilla::Maybe<CompartmentsInZoneIter>;
 };
 
-/*
- * This iterator iterates over all the compartments in a given set of zones. The
- * set of zones is determined by iterating ZoneIterT.
- */
+// This iterator iterates over all the compartments in a given set of zones. The
+// set of zones is determined by iterating ZoneIterT.
 template<class ZonesIterT>
 class CompartmentsIterT
 {
-  private:
     ZonesIterT zone;
     mozilla::Maybe<CompartmentsInZoneIter> comp;
 
   public:
     explicit CompartmentsIterT(JSRuntime *rt)
       : zone(rt)
     {
         if (zone.done())
@@ -494,15 +416,15 @@ class CompartmentsIterT
     }
 
     operator JSCompartment *() const { return get(); }
     JSCompartment *operator->() const { return get(); }
 };
 
 typedef CompartmentsIterT<ZonesIter> CompartmentsIter;
 
-/* Return the Zone* of a Value. Asserts if the Value is not a GC thing. */
+// Return the Zone* of a Value. Asserts if the Value is not a GC thing.
 Zone *
 ZoneOfValue(const JS::Value &value);
 
-} /* namespace js */
+} // namespace js
 
-#endif /* gc_Zone_h */
+#endif // gc_Zone_h