js/src/gc/Nursery.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sw=4 et tw=78:
     3  *
     4  * This Source Code Form is subject to the terms of the Mozilla Public
     5  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     6  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     8 #ifndef gc_Nursery_h
     9 #define gc_Nursery_h
    11 #ifdef JSGC_GENERATIONAL
    13 #include "jsalloc.h"
    14 #include "jspubtd.h"
    16 #include "ds/BitArray.h"
    17 #include "gc/Heap.h"
    18 #include "gc/Memory.h"
    19 #include "js/GCAPI.h"
    20 #include "js/HashTable.h"
    21 #include "js/HeapAPI.h"
    22 #include "js/Value.h"
    23 #include "js/Vector.h"
    25 namespace JS {
    26 struct Zone;
    27 }
    29 namespace js {
    31 class ObjectElements;
    32 class HeapSlot;
    33 void SetGCZeal(JSRuntime *, uint8_t, uint32_t);
    35 namespace gc {
    36 class Cell;
    37 class MinorCollectionTracer;
    38 } /* namespace gc */
    40 namespace types {
    41 struct TypeObject;
    42 }
    44 namespace jit {
    45 class CodeGenerator;
    46 class MacroAssembler;
    47 class ICStubCompiler;
    48 class BaselineCompiler;
    49 }
    51 class Nursery
    52 {
    53   public:
    54     static const int NumNurseryChunks = 16;
    55     static const int LastNurseryChunk = NumNurseryChunks - 1;
    56     static const size_t Alignment = gc::ChunkSize;
    57     static const size_t ChunkShift = gc::ChunkShift;
    58     static const size_t NurserySize = gc::ChunkSize * NumNurseryChunks;
    60     explicit Nursery(JSRuntime *rt)
    61       : runtime_(rt),
    62         position_(0),
    63         currentStart_(0),
    64         currentEnd_(0),
    65         currentChunk_(0),
    66         numActiveChunks_(0)
    67     {}
    68     ~Nursery();
    70     bool init();
    72     void enable();
    73     void disable();
    74     bool isEnabled() const { return numActiveChunks_ != 0; }
    76     /* Return true if no allocations have been made since the last collection. */
    77     bool isEmpty() const;
    79     template <typename T>
    80     MOZ_ALWAYS_INLINE bool isInside(const T *p) const {
    81         return gc::IsInsideNursery((JS::shadow::Runtime *)runtime_, p);
    82     }
    84     /*
    85      * Allocate and return a pointer to a new GC object with its |slots|
    86      * pointer pre-filled. Returns nullptr if the Nursery is full.
    87      */
    88     JSObject *allocateObject(JSContext *cx, size_t size, size_t numDynamic);
    90     /* Allocate a slots array for the given object. */
    91     HeapSlot *allocateSlots(JSContext *cx, JSObject *obj, uint32_t nslots);
    93     /* Allocate an elements vector for the given object. */
    94     ObjectElements *allocateElements(JSContext *cx, JSObject *obj, uint32_t nelems);
    96     /* Resize an existing slots array. */
    97     HeapSlot *reallocateSlots(JSContext *cx, JSObject *obj, HeapSlot *oldSlots,
    98                               uint32_t oldCount, uint32_t newCount);
   100     /* Resize an existing elements vector. */
   101     ObjectElements *reallocateElements(JSContext *cx, JSObject *obj, ObjectElements *oldHeader,
   102                                        uint32_t oldCount, uint32_t newCount);
   104     /* Free a slots array. */
   105     void freeSlots(JSContext *cx, HeapSlot *slots);
   107     /* Add a slots to our tracking list if it is out-of-line. */
   108     void notifyInitialSlots(gc::Cell *cell, HeapSlot *slots);
   110     typedef Vector<types::TypeObject *, 0, SystemAllocPolicy> TypeObjectList;
   112     /*
   113      * Do a minor collection, optionally specifying a list to store types which
   114      * should be pretenured afterwards.
   115      */
   116     void collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList *pretenureTypes);
   118     /*
   119      * Check if the thing at |*ref| in the Nursery has been forwarded. If so,
   120      * sets |*ref| to the new location of the object and returns true. Otherwise
   121      * returns false and leaves |*ref| unset.
   122      */
   123     template <typename T>
   124     MOZ_ALWAYS_INLINE bool getForwardedPointer(T **ref);
   126     /* Forward a slots/elements pointer stored in an Ion frame. */
   127     void forwardBufferPointer(HeapSlot **pSlotsElems);
   129     size_t sizeOfHeapCommitted() const {
   130         return numActiveChunks_ * gc::ChunkSize;
   131     }
   132     size_t sizeOfHeapDecommitted() const {
   133         return (NumNurseryChunks - numActiveChunks_) * gc::ChunkSize;
   134     }
   135     size_t sizeOfHugeSlots(mozilla::MallocSizeOf mallocSizeOf) const {
   136         size_t total = 0;
   137         for (HugeSlotsSet::Range r = hugeSlots.all(); !r.empty(); r.popFront())
   138             total += mallocSizeOf(r.front());
   139         total += hugeSlots.sizeOfExcludingThis(mallocSizeOf);
   140         return total;
   141     }
   143     MOZ_ALWAYS_INLINE uintptr_t start() const {
   144         JS_ASSERT(runtime_);
   145         return ((JS::shadow::Runtime *)runtime_)->gcNurseryStart_;
   146     }
   148     MOZ_ALWAYS_INLINE uintptr_t heapEnd() const {
   149         JS_ASSERT(runtime_);
   150         return ((JS::shadow::Runtime *)runtime_)->gcNurseryEnd_;
   151     }
   153   private:
   154     /*
   155      * The start and end pointers are stored under the runtime so that we can
   156      * inline the isInsideNursery check into embedder code. Use the start()
   157      * and heapEnd() functions to access these values.
   158      */
   159     JSRuntime *runtime_;
   161     /* Pointer to the first unallocated byte in the nursery. */
   162     uintptr_t position_;
   164     /* Pointer to the logical start of the Nursery. */
   165     uintptr_t currentStart_;
   167     /* Pointer to the last byte of space in the current chunk. */
   168     uintptr_t currentEnd_;
   170     /* The index of the chunk that is currently being allocated from. */
   171     int currentChunk_;
   173     /* The index after the last chunk that we will allocate from. */
   174     int numActiveChunks_;
   176     /*
   177      * The set of externally malloced slots potentially kept live by objects
   178      * stored in the nursery. Any external slots that do not belong to a
   179      * tenured thing at the end of a minor GC must be freed.
   180      */
   181     typedef HashSet<HeapSlot *, PointerHasher<HeapSlot *, 3>, SystemAllocPolicy> HugeSlotsSet;
   182     HugeSlotsSet hugeSlots;
   184     /* The maximum number of slots allowed to reside inline in the nursery. */
   185     static const size_t MaxNurserySlots = 128;
   187     /* The amount of space in the mapped nursery available to allocations. */
   188     static const size_t NurseryChunkUsableSize = gc::ChunkSize - sizeof(gc::ChunkTrailer);
   190     struct NurseryChunkLayout {
   191         char data[NurseryChunkUsableSize];
   192         gc::ChunkTrailer trailer;
   193         uintptr_t start() { return uintptr_t(&data); }
   194         uintptr_t end() { return uintptr_t(&trailer); }
   195     };
   196     static_assert(sizeof(NurseryChunkLayout) == gc::ChunkSize,
   197                   "Nursery chunk size must match gc::Chunk size.");
   198     NurseryChunkLayout &chunk(int index) const {
   199         JS_ASSERT(index < NumNurseryChunks);
   200         JS_ASSERT(start());
   201         return reinterpret_cast<NurseryChunkLayout *>(start())[index];
   202     }
   204     MOZ_ALWAYS_INLINE void initChunk(int chunkno) {
   205         NurseryChunkLayout &c = chunk(chunkno);
   206         c.trailer.location = gc::ChunkLocationNursery;
   207         c.trailer.runtime = runtime();
   208     }
   210     MOZ_ALWAYS_INLINE void setCurrentChunk(int chunkno) {
   211         JS_ASSERT(chunkno < NumNurseryChunks);
   212         JS_ASSERT(chunkno < numActiveChunks_);
   213         currentChunk_ = chunkno;
   214         position_ = chunk(chunkno).start();
   215         currentEnd_ = chunk(chunkno).end();
   216         initChunk(chunkno);
   217     }
   219     void updateDecommittedRegion() {
   220 #ifndef JS_GC_ZEAL
   221         if (numActiveChunks_ < NumNurseryChunks) {
   222             // Bug 994054: madvise on MacOS is too slow to make this
   223             //             optimization worthwhile.
   224 # ifndef XP_MACOSX
   225             uintptr_t decommitStart = chunk(numActiveChunks_).start();
   226             JS_ASSERT(decommitStart == AlignBytes(decommitStart, 1 << 20));
   227             gc::MarkPagesUnused(runtime(), (void *)decommitStart, heapEnd() - decommitStart);
   228 # endif
   229         }
   230 #endif
   231     }
   233     MOZ_ALWAYS_INLINE uintptr_t allocationEnd() const {
   234         JS_ASSERT(numActiveChunks_ > 0);
   235         return chunk(numActiveChunks_ - 1).end();
   236     }
   238     MOZ_ALWAYS_INLINE bool isFullyGrown() const {
   239         return numActiveChunks_ == NumNurseryChunks;
   240     }
   242     MOZ_ALWAYS_INLINE uintptr_t currentEnd() const {
   243         JS_ASSERT(runtime_);
   244         JS_ASSERT(currentEnd_ == chunk(currentChunk_).end());
   245         return currentEnd_;
   246     }
   247     void *addressOfCurrentEnd() const {
   248         JS_ASSERT(runtime_);
   249         return (void *)&currentEnd_;
   250     }
   252     uintptr_t position() const { return position_; }
   253     void *addressOfPosition() const { return (void*)&position_; }
   255     JSRuntime *runtime() const { return runtime_; }
   257     /* Allocates and registers external slots with the nursery. */
   258     HeapSlot *allocateHugeSlots(JSContext *cx, size_t nslots);
   260     /* Allocates a new GC thing from the tenured generation during minor GC. */
   261     void *allocateFromTenured(JS::Zone *zone, gc::AllocKind thingKind);
   263     struct TenureCountCache;
   265     /* Common internal allocator function. */
   266     void *allocate(size_t size);
   268     /*
   269      * Move the object at |src| in the Nursery to an already-allocated cell
   270      * |dst| in Tenured.
   271      */
   272     void collectToFixedPoint(gc::MinorCollectionTracer *trc, TenureCountCache &tenureCounts);
   273     MOZ_ALWAYS_INLINE void traceObject(gc::MinorCollectionTracer *trc, JSObject *src);
   274     MOZ_ALWAYS_INLINE void markSlots(gc::MinorCollectionTracer *trc, HeapSlot *vp, uint32_t nslots);
   275     MOZ_ALWAYS_INLINE void markSlots(gc::MinorCollectionTracer *trc, HeapSlot *vp, HeapSlot *end);
   276     MOZ_ALWAYS_INLINE void markSlot(gc::MinorCollectionTracer *trc, HeapSlot *slotp);
   277     void *moveToTenured(gc::MinorCollectionTracer *trc, JSObject *src);
   278     size_t moveObjectToTenured(JSObject *dst, JSObject *src, gc::AllocKind dstKind);
   279     size_t moveElementsToTenured(JSObject *dst, JSObject *src, gc::AllocKind dstKind);
   280     size_t moveSlotsToTenured(JSObject *dst, JSObject *src, gc::AllocKind dstKind);
   281     void forwardTypedArrayPointers(JSObject *dst, JSObject *src);
   283     /* Handle relocation of slots/elements pointers stored in Ion frames. */
   284     void setSlotsForwardingPointer(HeapSlot *oldSlots, HeapSlot *newSlots, uint32_t nslots);
   285     void setElementsForwardingPointer(ObjectElements *oldHeader, ObjectElements *newHeader,
   286                                       uint32_t nelems);
   288     /* Free malloced pointers owned by freed things in the nursery. */
   289     void freeHugeSlots(JSRuntime *rt);
   291     /*
   292      * Frees all non-live nursery-allocated things at the end of a minor
   293      * collection.
   294      */
   295     void sweep(JSRuntime *rt);
   297     /* Change the allocable space provided by the nursery. */
   298     void growAllocableSpace();
   299     void shrinkAllocableSpace();
   301     static void MinorGCCallback(JSTracer *trc, void **thingp, JSGCTraceKind kind);
   303 #ifdef JS_GC_ZEAL
   304     /*
   305      * In debug and zeal builds, these bytes indicate the state of an unused
   306      * segment of nursery-allocated memory.
   307      */
   308     void enterZealMode() {
   309         if (isEnabled())
   310             numActiveChunks_ = NumNurseryChunks;
   311     }
   312     void leaveZealMode() {
   313         if (isEnabled()) {
   314             JS_ASSERT(isEmpty());
   315             setCurrentChunk(0);
   316             currentStart_ = start();
   317         }
   318     }
   319 #else
   320     void enterZealMode() {}
   321     void leaveZealMode() {}
   322 #endif
   324     friend class gc::MinorCollectionTracer;
   325     friend class jit::MacroAssembler;
   326     friend void SetGCZeal(JSRuntime *, uint8_t, uint32_t);
   327 };
   329 } /* namespace js */
   331 #endif /* JSGC_GENERATIONAL */
   332 #endif /* gc_Nursery_h */

mercurial