summaryrefslogtreecommitdiffstats
path: root/js/src/gc/Marking-inl.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/gc/Marking-inl.h')
-rw-r--r--js/src/gc/Marking-inl.h53
1 files changed, 50 insertions, 3 deletions
diff --git a/js/src/gc/Marking-inl.h b/js/src/gc/Marking-inl.h
index 4afc9f7c8c..90f6337657 100644
--- a/js/src/gc/Marking-inl.h
+++ b/js/src/gc/Marking-inl.h
@@ -188,9 +188,40 @@ inline void PreWriteBarrierDuringFlattening(JSString* str) {
#ifdef JSGC_HASH_TABLE_CHECKS
+// Moving GC things whose pointers are used in hash table keys has the potential
+// to break hash tables in subtle and terrifying ways. For example, a key might
+// be reported as not present but iterating the table could still return it.
+//
+// Check that a table is correct following a moving GC, ensuring that nothing is
+// present in the table that points into the nursery or that has not been moved,
+// and that the hash table entries are discoverable.
+//
+// |checkEntryAndGetLookup| should check any GC thing pointers in the entry are
+// valid and return the lookup required to get this entry from the table.
+
+template <typename Table, typename Range, typename Lookup>
+void CheckTableEntryAfterMovingGC(const Table& table, const Range& r,
+ const Lookup& lookup) {
+ auto ptr = table.lookup(lookup);
+ MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front());
+}
+
+template <typename Table, typename F>
+void CheckTableAfterMovingGC(const Table& table, F&& checkEntryAndGetLookup) {
+ for (auto r = table.all(); !r.empty(); r.popFront()) {
+ auto lookup = checkEntryAndGetLookup(r.front());
+ CheckTableEntryAfterMovingGC(table, r, lookup);
+ }
+}
+
template <typename T>
inline bool IsGCThingValidAfterMovingGC(T* t) {
- return !IsInsideNursery(t) && !t->isForwarded();
+ if (!t->isTenured()) {
+ return false;
+ }
+
+ TenuredCell* cell = &t->asTenured();
+ return cell->arena()->allocated() && !cell->isForwarded();
}
template <typename T>
@@ -201,8 +232,24 @@ inline void CheckGCThingAfterMovingGC(T* t) {
}
template <typename T>
-inline void CheckGCThingAfterMovingGC(const WeakHeapPtr<T*>& t) {
- CheckGCThingAfterMovingGC(t.unbarrieredGet());
+inline void CheckGCThingAfterMovingGC(T* t, JS::Zone* expectedZone) {
+ if (t) {
+ MOZ_RELEASE_ASSERT(IsGCThingValidAfterMovingGC(t));
+ JS::Zone* zone = t->zoneFromAnyThread();
+ MOZ_RELEASE_ASSERT(zone == expectedZone || zone->isAtomsZone());
+ }
+}
+
+template <typename T>
+inline void CheckGCThingAfterMovingGC(const WeakHeapPtr<T*>& t,
+ JS::Zone* expectedZone) {
+ CheckGCThingAfterMovingGC(t.unbarrieredGet(), expectedZone);
+}
+
+inline void CheckProtoAfterMovingGC(const TaggedProto& proto, JS::Zone* zone) {
+ if (proto.isObject()) {
+ CheckGCThingAfterMovingGC(proto.toObject(), zone);
+ }
}
#endif // JSGC_HASH_TABLE_CHECKS