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 : #include "gc/Barrier.h"
8 :
9 : #include "jscompartment.h"
10 : #include "jsobj.h"
11 :
12 : #include "builtin/TypedObject.h"
13 : #include "gc/Policy.h"
14 : #include "gc/Zone.h"
15 : #include "js/HashTable.h"
16 : #include "js/Value.h"
17 : #include "vm/EnvironmentObject.h"
18 : #include "vm/SharedArrayObject.h"
19 : #include "vm/Symbol.h"
20 : #include "wasm/WasmJS.h"
21 :
22 : namespace js {
23 :
24 : bool
25 20712 : RuntimeFromActiveCooperatingThreadIsHeapMajorCollecting(JS::shadow::Zone* shadowZone)
26 : {
27 20712 : MOZ_ASSERT(CurrentThreadCanAccessRuntime(shadowZone->runtimeFromActiveCooperatingThread()));
28 20712 : return JS::CurrentThreadIsHeapMajorCollecting();
29 : }
30 :
31 : #ifdef DEBUG
32 :
33 : bool
34 562651 : IsMarkedBlack(JSObject* obj)
35 : {
36 : // Note: we assume conservatively that Nursery things will be live.
37 562651 : if (!obj->isTenured())
38 137449 : return true;
39 :
40 425207 : gc::TenuredCell& tenured = obj->asTenured();
41 425205 : if (tenured.isMarkedAny() || tenured.arena()->allocatedDuringIncremental)
42 5523 : return true;
43 :
44 419690 : return false;
45 : }
46 :
47 : bool
48 203866 : HeapSlot::preconditionForSet(NativeObject* owner, Kind kind, uint32_t slot) const
49 : {
50 203866 : if (kind == Slot)
51 194584 : return &owner->getSlotRef(slot) == this;
52 :
53 9282 : uint32_t numShifted = owner->getElementsHeader()->numShiftedElements();
54 9282 : MOZ_ASSERT(slot >= numShifted);
55 9282 : return &owner->getDenseElement(slot - numShifted) == (const Value*)this;
56 : }
57 :
58 : void
59 513810 : HeapSlot::assertPreconditionForWriteBarrierPost(NativeObject* obj, Kind kind, uint32_t slot,
60 : const Value& target) const
61 : {
62 513810 : if (kind == Slot) {
63 494522 : MOZ_ASSERT(obj->getSlotAddressUnchecked(slot)->get() == target);
64 : } else {
65 19288 : uint32_t numShifted = obj->getElementsHeader()->numShiftedElements();
66 19288 : MOZ_ASSERT(slot >= numShifted);
67 19288 : MOZ_ASSERT(static_cast<HeapSlot*>(obj->getDenseElements() + (slot - numShifted))->get() ==
68 : target);
69 : }
70 :
71 513809 : CheckEdgeIsNotBlackToGray(obj, target);
72 513818 : }
73 :
74 : bool
75 2708191 : CurrentThreadIsIonCompiling()
76 : {
77 2708191 : return TlsContext.get()->ionCompiling;
78 : }
79 :
80 : bool
81 0 : CurrentThreadIsIonCompilingSafeForMinorGC()
82 : {
83 0 : return TlsContext.get()->ionCompilingSafeForMinorGC;
84 : }
85 :
86 : bool
87 0 : CurrentThreadIsGCSweeping()
88 : {
89 0 : return TlsContext.get()->gcSweeping;
90 : }
91 :
92 : #endif // DEBUG
93 :
94 : template <typename S>
95 : template <typename T>
96 : void
97 20100 : ReadBarrierFunctor<S>::operator()(T* t)
98 : {
99 20100 : InternalBarrierMethods<T*>::readBarrier(t);
100 20100 : }
101 :
102 : // All GC things may be held in a Value, either publicly or as a private GC
103 : // thing.
104 : #define JS_EXPAND_DEF(name, type, _) \
105 : template void ReadBarrierFunctor<JS::Value>::operator()<type>(type*);
106 : JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
107 : #undef JS_EXPAND_DEF
108 :
109 : template <typename S>
110 : template <typename T>
111 : void
112 9153 : PreBarrierFunctor<S>::operator()(T* t)
113 : {
114 9153 : InternalBarrierMethods<T*>::preBarrier(t);
115 9153 : }
116 :
117 : // All GC things may be held in a Value, either publicly or as a private GC
118 : // thing.
119 : #define JS_EXPAND_DEF(name, type, _) \
120 : template void PreBarrierFunctor<JS::Value>::operator()<type>(type*);
121 : JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
122 : #undef JS_EXPAND_DEF
123 :
124 : template void PreBarrierFunctor<jsid>::operator()<JS::Symbol>(JS::Symbol*);
125 : template void PreBarrierFunctor<jsid>::operator()<JSString>(JSString*);
126 :
127 : template <typename T>
128 : /* static */ bool
129 6309 : MovableCellHasher<T>::hasHash(const Lookup& l)
130 : {
131 6309 : if (!l)
132 0 : return true;
133 :
134 6309 : return l->zoneFromAnyThread()->hasUniqueId(l);
135 : }
136 :
137 : template <typename T>
138 : /* static */ bool
139 231032 : MovableCellHasher<T>::ensureHash(const Lookup& l)
140 : {
141 231032 : if (!l)
142 116718 : return true;
143 :
144 : uint64_t unusedId;
145 114314 : return l->zoneFromAnyThread()->getOrCreateUniqueId(l, &unusedId);
146 : }
147 :
148 : template <typename T>
149 : /* static */ HashNumber
150 379884 : MovableCellHasher<T>::hash(const Lookup& l)
151 : {
152 379884 : if (!l)
153 116935 : return 0;
154 :
155 : // We have to access the zone from-any-thread here: a worker thread may be
156 : // cloning a self-hosted object from the main runtime's self- hosting zone
157 : // into another runtime. The zone's uid lock will protect against multiple
158 : // workers doing this simultaneously.
159 262949 : MOZ_ASSERT(CurrentThreadCanAccessZone(l->zoneFromAnyThread()) ||
160 : l->zoneFromAnyThread()->isSelfHostingZone() ||
161 : CurrentThreadIsPerformingGC());
162 :
163 262948 : return l->zoneFromAnyThread()->getHashCodeInfallible(l);
164 : }
165 :
166 : template <typename T>
167 : /* static */ bool
168 318567 : MovableCellHasher<T>::match(const Key& k, const Lookup& l)
169 : {
170 : // Return true if both are null or false if only one is null.
171 318567 : if (!k)
172 101568 : return !l;
173 216999 : if (!l)
174 0 : return false;
175 :
176 216999 : MOZ_ASSERT(k);
177 216999 : MOZ_ASSERT(l);
178 216999 : MOZ_ASSERT(CurrentThreadCanAccessZone(l->zoneFromAnyThread()) ||
179 : l->zoneFromAnyThread()->isSelfHostingZone());
180 :
181 216998 : Zone* zone = k->zoneFromAnyThread();
182 216998 : if (zone != l->zoneFromAnyThread())
183 0 : return false;
184 :
185 : #ifdef DEBUG
186 : // Incremental table sweeping means that existing table entries may no
187 : // longer have unique IDs. We fail the match in that case and the entry is
188 : // removed from the table later on.
189 216999 : if (!zone->hasUniqueId(k)) {
190 0 : Key key = k;
191 0 : MOZ_ASSERT(IsAboutToBeFinalizedUnbarriered(&key));
192 : }
193 216998 : MOZ_ASSERT(zone->hasUniqueId(l));
194 : #endif
195 :
196 : uint64_t keyId;
197 216997 : if (!zone->maybeGetUniqueId(k, &keyId)) {
198 : // Key is dead and cannot match lookup which must be live.
199 0 : return false;
200 : }
201 :
202 216998 : return keyId == zone->getUniqueIdInfallible(l);
203 : }
204 :
205 : #ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
206 : #pragma GCC diagnostic push
207 : #pragma GCC diagnostic ignored "-Wattributes"
208 : #endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
209 :
210 : template struct JS_PUBLIC_API(MovableCellHasher<JSObject*>);
211 : template struct JS_PUBLIC_API(MovableCellHasher<GlobalObject*>);
212 : template struct JS_PUBLIC_API(MovableCellHasher<SavedFrame*>);
213 : template struct JS_PUBLIC_API(MovableCellHasher<EnvironmentObject*>);
214 : template struct JS_PUBLIC_API(MovableCellHasher<WasmInstanceObject*>);
215 : template struct JS_PUBLIC_API(MovableCellHasher<JSScript*>);
216 :
217 : #ifdef JS_BROKEN_GCC_ATTRIBUTE_WARNING
218 : #pragma GCC diagnostic pop
219 : #endif // JS_BROKEN_GCC_ATTRIBUTE_WARNING
220 :
221 : } // namespace js
222 :
223 : JS_PUBLIC_API(void)
224 29715 : JS::HeapObjectPostBarrier(JSObject** objp, JSObject* prev, JSObject* next)
225 : {
226 29715 : MOZ_ASSERT(objp);
227 29715 : js::InternalBarrierMethods<JSObject*>::postBarrier(objp, prev, next);
228 29715 : }
229 :
230 : JS_PUBLIC_API(void)
231 2223 : JS::HeapValuePostBarrier(JS::Value* valuep, const Value& prev, const Value& next)
232 : {
233 2223 : MOZ_ASSERT(valuep);
234 2223 : js::InternalBarrierMethods<JS::Value>::postBarrier(valuep, prev, next);
235 2223 : }
|