Tenuring.h (5565B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 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_Tenuring_h 8 #define gc_Tenuring_h 9 10 #include "mozilla/HashTable.h" 11 #include "mozilla/Maybe.h" 12 13 #include "gc/AllocKind.h" 14 #include "js/GCAPI.h" 15 #include "js/TracingAPI.h" 16 #include "js/UniquePtr.h" 17 #include "util/Text.h" 18 19 namespace js { 20 21 class NativeObject; 22 class Nursery; 23 class PlainObject; 24 25 namespace wasm { 26 class AnyRef; 27 } // namespace wasm 28 29 namespace gc { 30 31 class AllocSite; 32 class ArenaCellSet; 33 class RelocationOverlay; 34 class StringRelocationOverlay; 35 #ifdef JS_GC_ZEAL 36 class PromotionStats; 37 #endif 38 39 template <typename Key> 40 struct DeduplicationStringHasher { 41 using Lookup = Key; 42 static inline HashNumber hash(const Lookup& lookup); 43 static MOZ_ALWAYS_INLINE bool match(const Key& key, const Lookup& lookup); 44 }; 45 46 class TenuringTracer final : public JSTracer { 47 Nursery& nursery_; 48 49 // Size of data promoted during collection. 50 size_t promotedSize = 0; 51 // Number of cells promoted during collection. 52 size_t promotedCells = 0; 53 54 // These lists are threaded through the Nursery using the space from 55 // already moved things. The lists are used to fix up the moved things and 56 // to find things held live by intra-Nursery pointers. 57 gc::RelocationOverlay* objHead = nullptr; 58 gc::StringRelocationOverlay* stringHead = nullptr; 59 60 using StringDeDupSet = 61 HashSet<JSString*, DeduplicationStringHasher<JSString*>, 62 SystemAllocPolicy>; 63 64 // deDupSet is emplaced at the beginning of the nursery collection and reset 65 // at the end of the nursery collection. It can also be reset during nursery 66 // collection when out of memory to insert new entries. 67 mozilla::Maybe<StringDeDupSet> stringDeDupSet; 68 69 bool tenureEverything; 70 71 // A flag set when a GC thing is promoted to the next nursery generation (as 72 // opposed to the tenured heap). This is used to check when we need to add an 73 // edge to the remembered set during nursery collection. 74 bool promotedToNursery = false; 75 76 #ifdef JS_GC_ZEAL 77 UniquePtr<PromotionStats> promotionStats; 78 #endif 79 80 public: 81 TenuringTracer(JSRuntime* rt, Nursery* nursery, bool tenureEverything); 82 ~TenuringTracer(); 83 84 Nursery& nursery() { return nursery_; } 85 86 #ifdef JS_GC_ZEAL 87 void initPromotionReport(); 88 void printPromotionReport(JSContext* cx, JS::GCReason reason, 89 const JS::AutoRequireNoGC& nogc) const; 90 #endif 91 92 // Promote all live objects and everything they can reach. Called after all 93 // roots have been traced. 94 void collectToObjectFixedPoint(); 95 96 // Promote all live strings and all strings they can reach, and additionally 97 // do any fixups for when strings are pointing into memory that was 98 // deduplicated. Called after collectToObjectFixedPoint(). 99 void collectToStringFixedPoint(); 100 101 size_t getPromotedSize() const; 102 size_t getPromotedCells() const; 103 104 void traverse(JS::Value* thingp); 105 void traverse(wasm::AnyRef* thingp); 106 107 // The store buffers need to be able to call these directly. 108 void traceObject(JSObject* obj); 109 void traceObjectSlots(NativeObject* nobj, uint32_t start, uint32_t end); 110 void traceObjectElements(JS::Value* vp, uint32_t count); 111 void traceString(JSString* str); 112 113 // Methods to promote a live cell or get the pointer to its new location if 114 // that has already happened. The store buffers call these. 115 JSObject* promoteOrForward(JSObject* obj); 116 JSString* promoteOrForward(JSString* str); 117 JS::BigInt* promoteOrForward(JS::BigInt* bip); 118 GetterSetter* promoteOrForward(GetterSetter* gs); 119 120 // Returns whether any cells in the arena require sweeping. 121 template <typename T> 122 bool traceBufferedCells(Arena* arena, ArenaCellSet* cells); 123 124 class AutoPromotedAnyToNursery; 125 126 private: 127 #define DEFINE_ON_EDGE_METHOD(name, type, _1, _2) \ 128 void on##name##Edge(type** thingp, const char* name) override; 129 JS_FOR_EACH_TRACEKIND(DEFINE_ON_EDGE_METHOD) 130 #undef DEFINE_ON_EDGE_METHOD 131 132 inline void insertIntoObjectFixupList(gc::RelocationOverlay* entry); 133 inline void insertIntoStringFixupList(gc::StringRelocationOverlay* entry); 134 135 template <typename T> 136 T* alloc(JS::Zone* zone, gc::AllocKind kind, gc::Cell* src); 137 template <JS::TraceKind traceKind> 138 void* allocCell(JS::Zone* zone, gc::AllocKind allocKind, gc::AllocSite* site, 139 gc::Cell* src); 140 JSString* allocString(JSString* src, JS::Zone* zone, gc::AllocKind dstKind); 141 142 bool shouldTenure(Zone* zone, JS::TraceKind traceKind, Cell* cell); 143 144 MOZ_ALWAYS_INLINE JSObject* promoteObject(JSObject* obj); 145 inline JSObject* promotePlainObject(PlainObject* src); 146 JSObject* promoteObjectSlow(JSObject* src); 147 JSString* promoteString(JSString* src); 148 JS::BigInt* promoteBigInt(JS::BigInt* src); 149 GetterSetter* promoteGetterSetter(GetterSetter* src); 150 151 size_t moveElements(NativeObject* dst, NativeObject* src, 152 gc::AllocKind dstKind); 153 size_t moveSlots(NativeObject* dst, NativeObject* src); 154 size_t moveString(JSString* dst, JSString* src, gc::AllocKind dstKind); 155 size_t moveBigInt(JS::BigInt* dst, JS::BigInt* src, gc::AllocKind dstKind); 156 size_t moveGetterSetter(GetterSetter* dst, GetterSetter* src, 157 gc::AllocKind dstKind); 158 159 void traceSlots(JS::Value* vp, JS::Value* end); 160 }; 161 162 } // namespace gc 163 } // namespace js 164 165 #endif // gc_Tenuring_h