LCOV - code coverage report
Current view: top level - js/src/gc - GCInternals.h (source / functions) Hit Total Coverage
Test: output.info Lines: 22 32 68.8 %
Date: 2017-07-14 16:53:18 Functions: 5 10 50.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef gc_GCInternals_h
       8             : #define gc_GCInternals_h
       9             : 
      10             : #include "mozilla/ArrayUtils.h"
      11             : #include "mozilla/Maybe.h"
      12             : #include "mozilla/PodOperations.h"
      13             : 
      14             : #include "jscntxt.h"
      15             : 
      16             : #include "gc/Zone.h"
      17             : #include "vm/HelperThreads.h"
      18             : #include "vm/Runtime.h"
      19             : 
      20             : namespace js {
      21             : namespace gc {
      22             : 
      23             : void FinishGC(JSContext* cx);
      24             : 
      25             : /*
      26             :  * This class should be used by any code that needs to exclusive access to the
      27             :  * heap in order to trace through it...
      28             :  */
      29             : class MOZ_RAII AutoTraceSession
      30             : {
      31             :   public:
      32             :     explicit AutoTraceSession(JSRuntime* rt, JS::HeapState state = JS::HeapState::Tracing);
      33             :     ~AutoTraceSession();
      34             : 
      35             :     // Threads with an exclusive context can hit refillFreeList while holding
      36             :     // the exclusive access lock. To avoid deadlocking when we try to acquire
      37             :     // this lock during GC and the other thread is waiting, make sure we hold
      38             :     // the exclusive access lock during GC sessions.
      39             :     AutoLockForExclusiveAccess lock;
      40             : 
      41             :   protected:
      42             :     JSRuntime* runtime;
      43             : 
      44             :   private:
      45             :     AutoTraceSession(const AutoTraceSession&) = delete;
      46             :     void operator=(const AutoTraceSession&) = delete;
      47             : 
      48             :     JS::HeapState prevState;
      49             :     AutoGeckoProfilerEntry pseudoFrame;
      50             : };
      51             : 
      52           0 : class MOZ_RAII AutoPrepareForTracing
      53             : {
      54             :     mozilla::Maybe<AutoTraceSession> session_;
      55             : 
      56             :   public:
      57             :     AutoPrepareForTracing(JSContext* cx, ZoneSelector selector);
      58           0 :     AutoTraceSession& session() { return session_.ref(); }
      59             : };
      60             : 
      61             : AbortReason
      62             : IsIncrementalGCUnsafe(JSRuntime* rt);
      63             : 
      64             : #ifdef JS_GC_ZEAL
      65             : 
      66             : class MOZ_RAII AutoStopVerifyingBarriers
      67             : {
      68             :     GCRuntime* gc;
      69             :     bool restartPreVerifier;
      70             : 
      71             :   public:
      72          24 :     AutoStopVerifyingBarriers(JSRuntime* rt, bool isShutdown)
      73          24 :       : gc(&rt->gc)
      74             :     {
      75          24 :         if (gc->isVerifyPreBarriersEnabled()) {
      76           0 :             gc->endVerifyPreBarriers();
      77           0 :             restartPreVerifier = !isShutdown;
      78             :         } else {
      79          24 :             restartPreVerifier = false;
      80             :         }
      81          24 :     }
      82             : 
      83          48 :     ~AutoStopVerifyingBarriers() {
      84             :         // Nasty special case: verification runs a minor GC, which *may* nest
      85             :         // inside of an outer minor GC. This is not allowed by the
      86             :         // gc::Statistics phase tree. So we pause the "real" GC, if in fact one
      87             :         // is in progress.
      88          24 :         gcstats::PhaseKind outer = gc->stats().currentPhaseKind();
      89          24 :         if (outer != gcstats::PhaseKind::NONE)
      90          21 :             gc->stats().endPhase(outer);
      91          24 :         MOZ_ASSERT(gc->stats().currentPhaseKind() == gcstats::PhaseKind::NONE);
      92             : 
      93          24 :         if (restartPreVerifier)
      94           0 :             gc->startVerifyPreBarriers();
      95             : 
      96          24 :         if (outer != gcstats::PhaseKind::NONE)
      97          21 :             gc->stats().beginPhase(outer);
      98          24 :     }
      99             : };
     100             : #else
     101             : struct MOZ_RAII AutoStopVerifyingBarriers
     102             : {
     103             :     AutoStopVerifyingBarriers(JSRuntime*, bool) {}
     104             : };
     105             : #endif /* JS_GC_ZEAL */
     106             : 
     107             : #ifdef JSGC_HASH_TABLE_CHECKS
     108             : void CheckHashTablesAfterMovingGC(JSRuntime* rt);
     109             : void CheckHeapAfterGC(JSRuntime* rt);
     110             : #endif
     111             : 
     112             : struct MovingTracer : JS::CallbackTracer
     113             : {
     114           0 :     explicit MovingTracer(JSRuntime* rt) : CallbackTracer(rt, TraceWeakMapKeysValues) {}
     115             : 
     116             :     void onObjectEdge(JSObject** objp) override;
     117             :     void onShapeEdge(Shape** shapep) override;
     118             :     void onStringEdge(JSString** stringp) override;
     119             :     void onScriptEdge(JSScript** scriptp) override;
     120             :     void onLazyScriptEdge(LazyScript** lazyp) override;
     121             :     void onBaseShapeEdge(BaseShape** basep) override;
     122             :     void onScopeEdge(Scope** basep) override;
     123             :     void onRegExpSharedEdge(RegExpShared** sharedp) override;
     124           0 :     void onChild(const JS::GCCellPtr& thing) override {
     125           0 :         MOZ_ASSERT(!RelocationOverlay::isCellForwarded(thing.asCell()));
     126           0 :     }
     127             : 
     128             : #ifdef DEBUG
     129           0 :     TracerKind getTracerKind() const override { return TracerKind::Moving; }
     130             : #endif
     131             : 
     132             :   private:
     133             :     template <typename T>
     134             :     void updateEdge(T** thingp);
     135             : };
     136             : 
     137             : // Structure for counting how many times objects in a particular group have
     138             : // been tenured during a minor collection.
     139             : struct TenureCount
     140             : {
     141             :     ObjectGroup* group;
     142             :     int count;
     143             : };
     144             : 
     145             : // Keep rough track of how many times we tenure objects in particular groups
     146             : // during minor collections, using a fixed size hash for efficiency at the cost
     147             : // of potential collisions.
     148             : struct TenureCountCache
     149             : {
     150             :     static const size_t EntryShift = 4;
     151             :     static const size_t EntryCount = 1 << EntryShift;
     152             : 
     153             :     TenureCount entries[EntryCount];
     154             : 
     155          24 :     TenureCountCache() { mozilla::PodZero(this); }
     156             : 
     157       22681 :     HashNumber hash(ObjectGroup* group) {
     158             : #if JS_BITS_PER_WORD == 32
     159             :         static const size_t ZeroBits = 3;
     160             : #else
     161             :         static const size_t ZeroBits = 4;
     162             : #endif
     163             : 
     164       22681 :         uintptr_t word = uintptr_t(group);
     165       22681 :         MOZ_ASSERT((word & ((1 << ZeroBits) - 1)) == 0);
     166       22681 :         word >>= ZeroBits;
     167       22681 :         return HashNumber((word >> EntryShift) ^ word);
     168             :     }
     169             : 
     170       22681 :     TenureCount& findEntry(ObjectGroup* group) {
     171       22681 :         return entries[hash(group) % EntryCount];
     172             :     }
     173             : };
     174             : 
     175             : } /* namespace gc */
     176             : } /* namespace js */
     177             : 
     178             : #endif /* gc_GCInternals_h */

Generated by: LCOV version 1.13