Backed out changeset 4191b252db9b (bug 1886734) for causing build bustages @netwerk...
[gecko.git] / js / src / gc / Marking-inl.h
blob4afc9f7c8c58c048b9e08a2cb824b829e0344b37
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/. */
7 #ifndef gc_Marking_inl_h
8 #define gc_Marking_inl_h
10 #include "gc/Marking.h"
12 #include <type_traits>
14 #include "gc/RelocationOverlay.h"
15 #include "js/Id.h"
16 #include "js/Value.h"
17 #include "vm/StringType.h"
18 #include "vm/TaggedProto.h"
19 #include "wasm/WasmAnyRef.h"
21 #include "gc/Nursery-inl.h"
23 namespace js {
24 namespace gc {
26 // An abstraction to re-wrap any kind of typed pointer back to the tagged
27 // pointer it came from with |TaggedPtr<TargetType>::wrap(sourcePtr)|.
28 template <typename T>
29 struct TaggedPtr {};
31 template <>
32 struct TaggedPtr<JS::Value> {
33 static JS::Value wrap(JSObject* obj) {
34 if (!obj) {
35 return JS::NullValue();
37 #ifdef ENABLE_RECORD_TUPLE
38 if (MaybeForwardedIsExtendedPrimitive(*obj)) {
39 return JS::ExtendedPrimitiveValue(*obj);
41 #endif
42 return JS::ObjectValue(*obj);
44 static JS::Value wrap(JSString* str) { return JS::StringValue(str); }
45 static JS::Value wrap(JS::Symbol* sym) { return JS::SymbolValue(sym); }
46 static JS::Value wrap(JS::BigInt* bi) { return JS::BigIntValue(bi); }
47 template <typename T>
48 static JS::Value wrap(T* priv) {
49 static_assert(std::is_base_of_v<Cell, T>,
50 "Type must be a GC thing derived from js::gc::Cell");
51 return JS::PrivateGCThingValue(priv);
53 static JS::Value empty() { return JS::UndefinedValue(); }
56 template <>
57 struct TaggedPtr<jsid> {
58 static jsid wrap(JSString* str) { return JS::PropertyKey::NonIntAtom(str); }
59 static jsid wrap(JS::Symbol* sym) { return PropertyKey::Symbol(sym); }
60 static jsid empty() { return JS::PropertyKey::Void(); }
63 template <>
64 struct TaggedPtr<TaggedProto> {
65 static TaggedProto wrap(JSObject* obj) { return TaggedProto(obj); }
66 static TaggedProto empty() { return TaggedProto(); }
69 template <>
70 struct TaggedPtr<wasm::AnyRef> {
71 static wasm::AnyRef wrap(JSObject* obj) {
72 return wasm::AnyRef::fromJSObjectOrNull(obj);
74 static wasm::AnyRef wrap(JSString* str) {
75 return wasm::AnyRef::fromJSString(str);
77 static wasm::AnyRef empty() { return wasm::AnyRef(); }
80 template <typename T>
81 struct MightBeForwarded {
82 static_assert(std::is_base_of_v<Cell, T>);
83 static_assert(!std::is_same_v<Cell, T> && !std::is_same_v<TenuredCell, T>);
85 #define CAN_FORWARD_KIND_OR(_1, _2, Type, _3, _4, _5, canCompact) \
86 std::is_base_of_v<Type, T> ? canCompact:
88 // FOR_EACH_ALLOCKIND doesn't cover every possible type: make sure
89 // to default to `true` for unknown types.
90 static constexpr bool value = FOR_EACH_ALLOCKIND(CAN_FORWARD_KIND_OR) true;
91 #undef CAN_FORWARD_KIND_OR
94 template <typename T>
95 inline bool IsForwarded(const T* t) {
96 if constexpr (!MightBeForwarded<T>::value) {
97 MOZ_ASSERT(!t->isForwarded());
98 return false;
101 return t->isForwarded();
104 template <>
105 inline bool IsForwarded<Cell>(const Cell* t) {
106 return t->isForwarded();
109 template <typename T>
110 inline T* Forwarded(const T* t) {
111 const RelocationOverlay* overlay = RelocationOverlay::fromCell(t);
112 MOZ_ASSERT(overlay->isForwarded());
113 return reinterpret_cast<T*>(overlay->forwardingAddress());
116 template <typename T>
117 inline T MaybeForwarded(T t) {
118 if (IsForwarded(t)) {
119 t = Forwarded(t);
121 MOZ_ASSERT(!IsForwarded(t));
122 return t;
125 inline const JSClass* MaybeForwardedObjectClass(const JSObject* obj) {
126 Shape* shape = MaybeForwarded(obj->shapeMaybeForwarded());
127 BaseShape* baseShape = MaybeForwarded(shape->base());
128 return baseShape->clasp();
131 template <typename T>
132 inline bool MaybeForwardedObjectIs(const JSObject* obj) {
133 MOZ_ASSERT(!obj->isForwarded());
134 return MaybeForwardedObjectClass(obj) == &T::class_;
137 template <typename T>
138 inline T& MaybeForwardedObjectAs(JSObject* obj) {
139 MOZ_ASSERT(MaybeForwardedObjectIs<T>(obj));
140 return *static_cast<T*>(obj);
143 inline RelocationOverlay::RelocationOverlay(Cell* dst) {
144 MOZ_ASSERT(dst->flags() == 0);
145 uintptr_t ptr = uintptr_t(dst);
146 header_.setForwardingAddress(ptr);
149 /* static */
150 inline RelocationOverlay* RelocationOverlay::forwardCell(Cell* src, Cell* dst) {
151 MOZ_ASSERT(!src->isForwarded());
152 MOZ_ASSERT(!dst->isForwarded());
153 return new (src) RelocationOverlay(dst);
156 inline bool IsAboutToBeFinalizedDuringMinorSweep(Cell** cellp) {
157 MOZ_ASSERT(JS::RuntimeHeapIsMinorCollecting());
159 if ((*cellp)->isTenured()) {
160 return false;
163 return !Nursery::getForwardedPointer(cellp);
166 // Special case pre-write barrier for strings used during rope flattening. This
167 // avoids eager marking of ropes which does not immediately mark the cells if we
168 // hit OOM. This does not traverse ropes and is instead called on every node in
169 // a rope during flattening.
170 inline void PreWriteBarrierDuringFlattening(JSString* str) {
171 MOZ_ASSERT(str);
172 MOZ_ASSERT(!JS::RuntimeHeapIsMajorCollecting());
174 if (IsInsideNursery(str)) {
175 return;
178 auto* cell = reinterpret_cast<TenuredCell*>(str);
179 JS::shadow::Zone* zone = cell->shadowZoneFromAnyThread();
180 if (!zone->needsIncrementalBarrier()) {
181 return;
184 MOZ_ASSERT(!str->isPermanentAndMayBeShared());
185 MOZ_ASSERT(CurrentThreadCanAccessRuntime(zone->runtimeFromAnyThread()));
186 PerformIncrementalBarrierDuringFlattening(str);
189 #ifdef JSGC_HASH_TABLE_CHECKS
191 template <typename T>
192 inline bool IsGCThingValidAfterMovingGC(T* t) {
193 return !IsInsideNursery(t) && !t->isForwarded();
196 template <typename T>
197 inline void CheckGCThingAfterMovingGC(T* t) {
198 if (t) {
199 MOZ_RELEASE_ASSERT(IsGCThingValidAfterMovingGC(t));
203 template <typename T>
204 inline void CheckGCThingAfterMovingGC(const WeakHeapPtr<T*>& t) {
205 CheckGCThingAfterMovingGC(t.unbarrieredGet());
208 #endif // JSGC_HASH_TABLE_CHECKS
210 } /* namespace gc */
211 } /* namespace js */
213 #endif // gc_Marking_inl_h