Bug 1877642 - Disable browser_fullscreen-tab-close-race.js on apple_silicon !debug...
[gecko.git] / js / src / gc / PublicIterators.cpp
blob582a21ddf39d0ba916ca334833697d15dc098340
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 #include "gc/GCInternals.h"
8 #include "gc/GCLock.h"
9 #include "vm/Realm.h"
10 #include "vm/Runtime.h"
12 #include "gc/PrivateIterators-inl.h"
14 using namespace js;
15 using namespace js::gc;
17 static void IterateRealmsArenasCellsUnbarriered(
18 JSContext* cx, Zone* zone, void* data,
19 JS::IterateRealmCallback realmCallback, IterateArenaCallback arenaCallback,
20 IterateCellCallback cellCallback, const JS::AutoRequireNoGC& nogc) {
22 Rooted<Realm*> realm(cx);
23 for (RealmsInZoneIter r(zone); !r.done(); r.next()) {
24 realm = r;
25 (*realmCallback)(cx, data, realm, nogc);
29 for (auto thingKind : AllAllocKinds()) {
30 JS::TraceKind traceKind = MapAllocToTraceKind(thingKind);
31 size_t thingSize = Arena::thingSize(thingKind);
33 for (ArenaIter aiter(zone, thingKind); !aiter.done(); aiter.next()) {
34 Arena* arena = aiter.get();
35 (*arenaCallback)(cx->runtime(), data, arena, traceKind, thingSize, nogc);
36 for (ArenaCellIter cell(arena); !cell.done(); cell.next()) {
37 (*cellCallback)(cx->runtime(), data, JS::GCCellPtr(cell, traceKind),
38 thingSize, nogc);
44 void js::IterateHeapUnbarriered(JSContext* cx, void* data,
45 IterateZoneCallback zoneCallback,
46 JS::IterateRealmCallback realmCallback,
47 IterateArenaCallback arenaCallback,
48 IterateCellCallback cellCallback) {
49 AutoPrepareForTracing prep(cx);
50 JS::AutoSuppressGCAnalysis nogc(cx);
52 auto iterateZone = [&](Zone* zone) -> void {
53 (*zoneCallback)(cx->runtime(), data, zone, nogc);
54 IterateRealmsArenasCellsUnbarriered(cx, zone, data, realmCallback,
55 arenaCallback, cellCallback, nogc);
58 // Include the shared atoms zone if present.
59 if (Zone* zone = cx->runtime()->gc.maybeSharedAtomsZone()) {
60 iterateZone(zone);
63 for (ZonesIter zone(cx->runtime(), WithAtoms); !zone.done(); zone.next()) {
64 iterateZone(zone);
68 void js::IterateHeapUnbarrieredForZone(JSContext* cx, Zone* zone, void* data,
69 IterateZoneCallback zoneCallback,
70 JS::IterateRealmCallback realmCallback,
71 IterateArenaCallback arenaCallback,
72 IterateCellCallback cellCallback) {
73 AutoPrepareForTracing prep(cx);
74 JS::AutoSuppressGCAnalysis nogc(cx);
76 (*zoneCallback)(cx->runtime(), data, zone, nogc);
77 IterateRealmsArenasCellsUnbarriered(cx, zone, data, realmCallback,
78 arenaCallback, cellCallback, nogc);
81 void js::IterateChunks(JSContext* cx, void* data,
82 IterateChunkCallback chunkCallback) {
83 AutoPrepareForTracing prep(cx);
84 AutoLockGC lock(cx->runtime());
85 JS::AutoSuppressGCAnalysis nogc(cx);
87 for (auto chunk = cx->runtime()->gc.allNonEmptyChunks(lock); !chunk.done();
88 chunk.next()) {
89 chunkCallback(cx->runtime(), data, chunk, nogc);
93 static void TraverseInnerLazyScriptsForLazyScript(
94 JSContext* cx, void* data, BaseScript* enclosingScript,
95 IterateScriptCallback lazyScriptCallback, const JS::AutoRequireNoGC& nogc) {
96 for (JS::GCCellPtr gcThing : enclosingScript->gcthings()) {
97 if (!gcThing.is<JSObject>()) {
98 continue;
100 JSObject* obj = &gcThing.as<JSObject>();
102 MOZ_ASSERT(obj->is<JSFunction>(),
103 "All objects in lazy scripts should be functions");
104 JSFunction* fun = &obj->as<JSFunction>();
106 if (!fun->hasBaseScript()) {
107 // Ignore asm.js.
108 continue;
110 MOZ_ASSERT(fun->baseScript());
111 if (!fun->baseScript()) {
112 // If the function doesn't have script, ignore it.
113 continue;
116 if (fun->hasBytecode()) {
117 // Ignore non lazy function.
118 continue;
121 // If the function is "ghost", we shouldn't expose it to the debugger.
123 // See GHOST_FUNCTION in FunctionFlags.h for more details.
124 if (fun->isGhost()) {
125 continue;
128 BaseScript* script = fun->baseScript();
129 MOZ_ASSERT_IF(script->hasEnclosingScript(),
130 script->enclosingScript() == enclosingScript);
132 lazyScriptCallback(cx->runtime(), data, script, nogc);
134 TraverseInnerLazyScriptsForLazyScript(cx, data, script, lazyScriptCallback,
135 nogc);
139 static inline void DoScriptCallback(JSContext* cx, void* data,
140 BaseScript* script,
141 IterateScriptCallback callback,
142 const JS::AutoRequireNoGC& nogc) {
143 // Exclude any scripts that may be the result of a failed compile. Check that
144 // script either has bytecode or is ready to delazify.
146 // This excludes lazy scripts that do not have an enclosing scope because we
147 // cannot distinguish a failed compile fragment from a lazy script with a lazy
148 // parent.
149 if (!script->hasBytecode() && !script->isReadyForDelazification()) {
150 return;
153 // Invoke callback.
154 callback(cx->runtime(), data, script, nogc);
156 // The check above excluded lazy scripts with lazy parents, so explicitly
157 // visit inner scripts now if we are lazy with a successfully compiled parent.
158 if (!script->hasBytecode()) {
159 TraverseInnerLazyScriptsForLazyScript(cx, data, script, callback, nogc);
163 void js::IterateScripts(JSContext* cx, Realm* realm, void* data,
164 IterateScriptCallback scriptCallback) {
165 MOZ_ASSERT(!cx->suppressGC);
166 AutoEmptyNurseryAndPrepareForTracing prep(cx);
167 JS::AutoSuppressGCAnalysis nogc;
169 if (realm) {
170 Zone* zone = realm->zone();
171 for (auto iter = zone->cellIter<BaseScript>(prep); !iter.done();
172 iter.next()) {
173 if (iter->realm() != realm) {
174 continue;
176 DoScriptCallback(cx, data, iter.get(), scriptCallback, nogc);
178 } else {
179 for (ZonesIter zone(cx->runtime(), SkipAtoms); !zone.done(); zone.next()) {
180 for (auto iter = zone->cellIter<BaseScript>(prep); !iter.done();
181 iter.next()) {
182 DoScriptCallback(cx, data, iter.get(), scriptCallback, nogc);
188 void js::IterateGrayObjects(Zone* zone, IterateGCThingCallback cellCallback,
189 void* data) {
190 MOZ_ASSERT(!JS::RuntimeHeapIsBusy());
192 JSContext* cx = TlsContext.get();
193 AutoPrepareForTracing prep(cx);
194 JS::AutoSuppressGCAnalysis nogc(cx);
196 for (auto kind : ObjectAllocKinds()) {
197 for (GrayObjectIter obj(zone, kind); !obj.done(); obj.next()) {
198 if (obj->asTenured().isMarkedGray()) {
199 cellCallback(data, JS::GCCellPtr(obj.get()), nogc);
205 JS_PUBLIC_API void JS_IterateCompartments(
206 JSContext* cx, void* data,
207 JSIterateCompartmentCallback compartmentCallback) {
208 AutoTraceSession session(cx->runtime());
210 for (CompartmentsIter c(cx->runtime()); !c.done(); c.next()) {
211 if ((*compartmentCallback)(cx, data, c) ==
212 JS::CompartmentIterResult::Stop) {
213 break;
218 JS_PUBLIC_API void JS_IterateCompartmentsInZone(
219 JSContext* cx, JS::Zone* zone, void* data,
220 JSIterateCompartmentCallback compartmentCallback) {
221 AutoTraceSession session(cx->runtime());
223 for (CompartmentsInZoneIter c(zone); !c.done(); c.next()) {
224 if ((*compartmentCallback)(cx, data, c) ==
225 JS::CompartmentIterResult::Stop) {
226 break;
231 JS_PUBLIC_API void JS::IterateRealms(JSContext* cx, void* data,
232 JS::IterateRealmCallback realmCallback) {
233 AutoTraceSession session(cx->runtime());
234 JS::AutoSuppressGCAnalysis nogc(cx);
236 Rooted<Realm*> realm(cx);
237 for (RealmsIter r(cx->runtime()); !r.done(); r.next()) {
238 realm = r;
239 (*realmCallback)(cx, data, realm, nogc);
243 JS_PUBLIC_API void JS::IterateRealmsWithPrincipals(
244 JSContext* cx, JSPrincipals* principals, void* data,
245 JS::IterateRealmCallback realmCallback) {
246 MOZ_ASSERT(principals);
248 AutoTraceSession session(cx->runtime());
249 JS::AutoSuppressGCAnalysis nogc(cx);
251 Rooted<Realm*> realm(cx);
252 for (RealmsIter r(cx->runtime()); !r.done(); r.next()) {
253 if (r->principals() != principals) {
254 continue;
256 realm = r;
257 (*realmCallback)(cx, data, realm, nogc);
261 JS_PUBLIC_API void JS::IterateRealmsInCompartment(
262 JSContext* cx, JS::Compartment* compartment, void* data,
263 JS::IterateRealmCallback realmCallback) {
264 AutoTraceSession session(cx->runtime());
265 JS::AutoSuppressGCAnalysis nogc(cx);
267 Rooted<Realm*> realm(cx);
268 for (RealmsInCompartmentIter r(compartment); !r.done(); r.next()) {
269 realm = r;
270 (*realmCallback)(cx, data, realm, nogc);