/src/mozilla-central/js/src/gc/GC-inl.h
Line | Count | Source (jump to first uncovered line) |
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 | | #ifndef gc_GC_inl_h |
8 | | #define gc_GC_inl_h |
9 | | |
10 | | #include "gc/GC.h" |
11 | | |
12 | | #include "mozilla/DebugOnly.h" |
13 | | #include "mozilla/Maybe.h" |
14 | | |
15 | | #include "gc/Zone.h" |
16 | | |
17 | | #include "gc/ArenaList-inl.h" |
18 | | |
19 | | namespace js { |
20 | | namespace gc { |
21 | | |
22 | | class AutoAssertEmptyNursery; |
23 | | |
24 | | class ArenaIter |
25 | | { |
26 | | Arena* arena; |
27 | | Arena* unsweptArena; |
28 | | Arena* sweptArena; |
29 | | mozilla::DebugOnly<bool> initialized; |
30 | | |
31 | | public: |
32 | | ArenaIter() |
33 | 8 | : arena(nullptr), unsweptArena(nullptr), sweptArena(nullptr), initialized(false) {} |
34 | | |
35 | 0 | ArenaIter(JS::Zone* zone, AllocKind kind) : initialized(false) { init(zone, kind); } |
36 | | |
37 | 8 | void init(JS::Zone* zone, AllocKind kind) { |
38 | 8 | MOZ_ASSERT(!initialized); |
39 | 8 | MOZ_ASSERT(zone); |
40 | 8 | initialized = true; |
41 | 8 | arena = zone->arenas.getFirstArena(kind); |
42 | 8 | unsweptArena = zone->arenas.getFirstArenaToSweep(kind); |
43 | 8 | sweptArena = zone->arenas.getFirstSweptArena(kind); |
44 | 8 | if (!unsweptArena) { |
45 | 8 | unsweptArena = sweptArena; |
46 | 8 | sweptArena = nullptr; |
47 | 8 | } |
48 | 8 | if (!arena) { |
49 | 0 | arena = unsweptArena; |
50 | 0 | unsweptArena = sweptArena; |
51 | 0 | sweptArena = nullptr; |
52 | 0 | } |
53 | 8 | } |
54 | | |
55 | 696 | bool done() const { |
56 | 696 | MOZ_ASSERT(initialized); |
57 | 696 | return !arena; |
58 | 696 | } |
59 | | |
60 | 24 | Arena* get() const { |
61 | 24 | MOZ_ASSERT(!done()); |
62 | 24 | return arena; |
63 | 24 | } |
64 | | |
65 | 24 | void next() { |
66 | 24 | MOZ_ASSERT(!done()); |
67 | 24 | arena = arena->next; |
68 | 24 | if (!arena) { |
69 | 8 | arena = unsweptArena; |
70 | 8 | unsweptArena = sweptArena; |
71 | 8 | sweptArena = nullptr; |
72 | 8 | } |
73 | 24 | } |
74 | | }; |
75 | | |
76 | | enum CellIterNeedsBarrier : uint8_t |
77 | | { |
78 | | CellIterDoesntNeedBarrier = 0, |
79 | | CellIterMayNeedBarrier = 1 |
80 | | }; |
81 | | |
82 | | class ArenaCellIterImpl |
83 | | { |
84 | | size_t firstThingOffset; |
85 | | size_t thingSize; |
86 | | Arena* arenaAddr; |
87 | | FreeSpan span; |
88 | | uint_fast16_t thing; |
89 | | JS::TraceKind traceKind; |
90 | | bool needsBarrier; |
91 | | mozilla::DebugOnly<bool> initialized; |
92 | | |
93 | | // Upon entry, |thing| points to any thing (free or used) and finds the |
94 | | // first used thing, which may be |thing|. |
95 | 21.2M | void moveForwardIfFree() { |
96 | 21.2M | MOZ_ASSERT(!done()); |
97 | 21.2M | MOZ_ASSERT(thing); |
98 | 21.2M | // Note: if |span| is empty, this test will fail, which is what we want |
99 | 21.2M | // -- |span| being empty means that we're past the end of the last free |
100 | 21.2M | // thing, all the remaining things in the arena are used, and we'll |
101 | 21.2M | // never need to move forward. |
102 | 21.2M | if (thing == span.first) { |
103 | 1.23k | thing = span.last + thingSize; |
104 | 1.23k | span = *span.nextSpan(arenaAddr); |
105 | 1.23k | } |
106 | 21.2M | } |
107 | | |
108 | | public: |
109 | | ArenaCellIterImpl() |
110 | | : firstThingOffset(0), |
111 | | thingSize(0), |
112 | | arenaAddr(nullptr), |
113 | | thing(0), |
114 | | traceKind(JS::TraceKind::Null), |
115 | | needsBarrier(false), |
116 | | initialized(false) |
117 | 8 | {} |
118 | | |
119 | | explicit ArenaCellIterImpl(Arena* arena, CellIterNeedsBarrier mayNeedBarrier) |
120 | | : initialized(false) |
121 | 253k | { |
122 | 253k | init(arena, mayNeedBarrier); |
123 | 253k | } |
124 | | |
125 | 253k | void init(Arena* arena, CellIterNeedsBarrier mayNeedBarrier) { |
126 | 253k | MOZ_ASSERT(!initialized); |
127 | 253k | MOZ_ASSERT(arena); |
128 | 253k | initialized = true; |
129 | 253k | AllocKind kind = arena->getAllocKind(); |
130 | 253k | firstThingOffset = Arena::firstThingOffset(kind); |
131 | 253k | thingSize = Arena::thingSize(kind); |
132 | 253k | traceKind = MapAllocToTraceKind(kind); |
133 | 253k | needsBarrier = mayNeedBarrier && !JS::RuntimeHeapIsCollecting(); |
134 | 253k | reset(arena); |
135 | 253k | } |
136 | | |
137 | | // Use this to move from an Arena of a particular kind to another Arena of |
138 | | // the same kind. |
139 | 253k | void reset(Arena* arena) { |
140 | 253k | MOZ_ASSERT(initialized); |
141 | 253k | MOZ_ASSERT(arena); |
142 | 253k | arenaAddr = arena; |
143 | 253k | span = *arena->getFirstFreeSpan(); |
144 | 253k | thing = firstThingOffset; |
145 | 253k | moveForwardIfFree(); |
146 | 253k | } |
147 | | |
148 | 21.5M | bool done() const { |
149 | 21.5M | MOZ_ASSERT(initialized); |
150 | 21.5M | MOZ_ASSERT(thing <= ArenaSize); |
151 | 21.5M | return thing == ArenaSize; |
152 | 21.5M | } |
153 | | |
154 | 21.2M | TenuredCell* getCell() const { |
155 | 21.2M | MOZ_ASSERT(!done()); |
156 | 21.2M | TenuredCell* cell = reinterpret_cast<TenuredCell*>(uintptr_t(arenaAddr) + thing); |
157 | 21.2M | |
158 | 21.2M | // This can result in a a new reference being created to an object that |
159 | 21.2M | // an ongoing incremental GC may find to be unreachable, so we may need |
160 | 21.2M | // a barrier here. |
161 | 21.2M | if (needsBarrier) { |
162 | 0 | ExposeGCThingToActiveJS(JS::GCCellPtr(cell, traceKind)); |
163 | 0 | } |
164 | 21.2M | |
165 | 21.2M | return cell; |
166 | 21.2M | } |
167 | | |
168 | 13.0M | template<typename T> T* get() const { |
169 | 13.0M | MOZ_ASSERT(!done()); |
170 | 13.0M | MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind); |
171 | 13.0M | return reinterpret_cast<T*>(getCell()); |
172 | 13.0M | } JSScript* js::gc::ArenaCellIterImpl::get<JSScript>() const Line | Count | Source | 168 | 5.30k | template<typename T> T* get() const { | 169 | 5.30k | MOZ_ASSERT(!done()); | 170 | 5.30k | MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind); | 171 | 5.30k | return reinterpret_cast<T*>(getCell()); | 172 | 5.30k | } |
js::jit::JitCode* js::gc::ArenaCellIterImpl::get<js::jit::JitCode>() const Line | Count | Source | 168 | 405 | template<typename T> T* get() const { | 169 | 405 | MOZ_ASSERT(!done()); | 170 | 405 | MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind); | 171 | 405 | return reinterpret_cast<T*>(getCell()); | 172 | 405 | } |
js::ObjectGroup* js::gc::ArenaCellIterImpl::get<js::ObjectGroup>() const Line | Count | Source | 168 | 6.53M | template<typename T> T* get() const { | 169 | 6.53M | MOZ_ASSERT(!done()); | 170 | 6.53M | MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind); | 171 | 6.53M | return reinterpret_cast<T*>(getCell()); | 172 | 6.53M | } |
Unexecuted instantiation: js::LazyScript* js::gc::ArenaCellIterImpl::get<js::LazyScript>() const js::Shape* js::gc::ArenaCellIterImpl::get<js::Shape>() const Line | Count | Source | 168 | 3.28M | template<typename T> T* get() const { | 169 | 3.28M | MOZ_ASSERT(!done()); | 170 | 3.28M | MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind); | 171 | 3.28M | return reinterpret_cast<T*>(getCell()); | 172 | 3.28M | } |
js::AccessorShape* js::gc::ArenaCellIterImpl::get<js::AccessorShape>() const Line | Count | Source | 168 | 2.34k | template<typename T> T* get() const { | 169 | 2.34k | MOZ_ASSERT(!done()); | 170 | 2.34k | MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind); | 171 | 2.34k | return reinterpret_cast<T*>(getCell()); | 172 | 2.34k | } |
js::BaseShape* js::gc::ArenaCellIterImpl::get<js::BaseShape>() const Line | Count | Source | 168 | 878 | template<typename T> T* get() const { | 169 | 878 | MOZ_ASSERT(!done()); | 170 | 878 | MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind); | 171 | 878 | return reinterpret_cast<T*>(getCell()); | 172 | 878 | } |
JSExternalString* js::gc::ArenaCellIterImpl::get<JSExternalString>() const Line | Count | Source | 168 | 36 | template<typename T> T* get() const { | 169 | 36 | MOZ_ASSERT(!done()); | 170 | 36 | MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind); | 171 | 36 | return reinterpret_cast<T*>(getCell()); | 172 | 36 | } |
Unexecuted instantiation: js::FatInlineAtom* js::gc::ArenaCellIterImpl::get<js::FatInlineAtom>() const Unexecuted instantiation: js::NormalAtom* js::gc::ArenaCellIterImpl::get<js::NormalAtom>() const Unexecuted instantiation: JS::Symbol* js::gc::ArenaCellIterImpl::get<JS::Symbol>() const js::Scope* js::gc::ArenaCellIterImpl::get<js::Scope>() const Line | Count | Source | 168 | 2.61k | template<typename T> T* get() const { | 169 | 2.61k | MOZ_ASSERT(!done()); | 170 | 2.61k | MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind); | 171 | 2.61k | return reinterpret_cast<T*>(getCell()); | 172 | 2.61k | } |
Unexecuted instantiation: js::RegExpShared* js::gc::ArenaCellIterImpl::get<js::RegExpShared>() const JSFatInlineString* js::gc::ArenaCellIterImpl::get<JSFatInlineString>() const Line | Count | Source | 168 | 1.50k | template<typename T> T* get() const { | 169 | 1.50k | MOZ_ASSERT(!done()); | 170 | 1.50k | MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind); | 171 | 1.50k | return reinterpret_cast<T*>(getCell()); | 172 | 1.50k | } |
JSString* js::gc::ArenaCellIterImpl::get<JSString>() const Line | Count | Source | 168 | 3.26M | template<typename T> T* get() const { | 169 | 3.26M | MOZ_ASSERT(!done()); | 170 | 3.26M | MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind); | 171 | 3.26M | return reinterpret_cast<T*>(getCell()); | 172 | 3.26M | } |
|
173 | | |
174 | 21.2M | void next() { |
175 | 21.2M | MOZ_ASSERT(!done()); |
176 | 21.2M | thing += thingSize; |
177 | 21.2M | if (thing < ArenaSize) { |
178 | 21.0M | moveForwardIfFree(); |
179 | 21.0M | } |
180 | 21.2M | } |
181 | | }; |
182 | | |
183 | | template<> |
184 | | JSObject* |
185 | | ArenaCellIterImpl::get<JSObject>() const; |
186 | | |
187 | | class ArenaCellIter : public ArenaCellIterImpl |
188 | | { |
189 | | public: |
190 | | explicit ArenaCellIter(Arena* arena) |
191 | | : ArenaCellIterImpl(arena, CellIterMayNeedBarrier) |
192 | 0 | { |
193 | 0 | MOZ_ASSERT(JS::RuntimeHeapIsTracing()); |
194 | 0 | } |
195 | | }; |
196 | | |
197 | | template <typename T> |
198 | | class ZoneCellIter; |
199 | | |
200 | | template <> |
201 | | class ZoneCellIter<TenuredCell> { |
202 | | ArenaIter arenaIter; |
203 | | ArenaCellIterImpl cellIter; |
204 | | mozilla::Maybe<JS::AutoAssertNoGC> nogc; |
205 | | |
206 | | protected: |
207 | | // For use when a subclass wants to insert some setup before init(). |
208 | 8 | ZoneCellIter() {} |
209 | | |
210 | 8 | void init(JS::Zone* zone, AllocKind kind) { |
211 | 8 | MOZ_ASSERT_IF(IsNurseryAllocable(kind), |
212 | 8 | (zone->isAtomsZone() || |
213 | 8 | zone->runtimeFromMainThread()->gc.nursery().isEmpty())); |
214 | 8 | initForTenuredIteration(zone, kind); |
215 | 8 | } |
216 | | |
217 | 8 | void initForTenuredIteration(JS::Zone* zone, AllocKind kind) { |
218 | 8 | JSRuntime* rt = zone->runtimeFromAnyThread(); |
219 | 8 | |
220 | 8 | // If called from outside a GC, ensure that the heap is in a state |
221 | 8 | // that allows us to iterate. |
222 | 8 | if (!JS::RuntimeHeapIsBusy()) { |
223 | 0 | // Assert that no GCs can occur while a ZoneCellIter is live. |
224 | 0 | nogc.emplace(); |
225 | 0 | } |
226 | 8 | |
227 | 8 | // We have a single-threaded runtime, so there's no need to protect |
228 | 8 | // against other threads iterating or allocating. However, we do have |
229 | 8 | // background finalization; we may have to wait for this to finish if |
230 | 8 | // it's currently active. |
231 | 8 | if (IsBackgroundFinalized(kind) && zone->arenas.needBackgroundFinalizeWait(kind)) { |
232 | 0 | rt->gc.waitBackgroundSweepEnd(); |
233 | 0 | } |
234 | 8 | arenaIter.init(zone, kind); |
235 | 8 | if (!arenaIter.done()) { |
236 | 8 | cellIter.init(arenaIter.get(), CellIterMayNeedBarrier); |
237 | 8 | settle(); |
238 | 8 | } |
239 | 8 | } |
240 | | |
241 | | public: |
242 | 0 | ZoneCellIter(JS::Zone* zone, AllocKind kind) { |
243 | 0 | // If we are iterating a nursery-allocated kind then we need to |
244 | 0 | // evict first so that we can see all things. |
245 | 0 | if (IsNurseryAllocable(kind)) { |
246 | 0 | zone->runtimeFromMainThread()->gc.evictNursery(); |
247 | 0 | } |
248 | 0 |
|
249 | 0 | init(zone, kind); |
250 | 0 | } |
251 | | |
252 | 0 | ZoneCellIter(JS::Zone* zone, AllocKind kind, const js::gc::AutoAssertEmptyNursery&) { |
253 | 0 | // No need to evict the nursery. (This constructor is known statically |
254 | 0 | // to not GC.) |
255 | 0 | init(zone, kind); |
256 | 0 | } |
257 | | |
258 | 632 | bool done() const { |
259 | 632 | return arenaIter.done(); |
260 | 632 | } |
261 | | |
262 | | template<typename T> |
263 | 2.50k | T* get() const { |
264 | 2.50k | MOZ_ASSERT(!done()); |
265 | 2.50k | return cellIter.get<T>(); |
266 | 2.50k | } Unexecuted instantiation: JSObject* js::gc::ZoneCellIter<js::gc::TenuredCell>::get<JSObject>() const JSScript* js::gc::ZoneCellIter<js::gc::TenuredCell>::get<JSScript>() const Line | Count | Source | 263 | 2.50k | T* get() const { | 264 | 2.50k | MOZ_ASSERT(!done()); | 265 | 2.50k | return cellIter.get<T>(); | 266 | 2.50k | } |
Unexecuted instantiation: js::jit::JitCode* js::gc::ZoneCellIter<js::gc::TenuredCell>::get<js::jit::JitCode>() const Unexecuted instantiation: js::ObjectGroup* js::gc::ZoneCellIter<js::gc::TenuredCell>::get<js::ObjectGroup>() const Unexecuted instantiation: js::BaseShape* js::gc::ZoneCellIter<js::gc::TenuredCell>::get<js::BaseShape>() const Unexecuted instantiation: js::LazyScript* js::gc::ZoneCellIter<js::gc::TenuredCell>::get<js::LazyScript>() const |
267 | | |
268 | 0 | TenuredCell* getCell() const { |
269 | 0 | MOZ_ASSERT(!done()); |
270 | 0 | return cellIter.getCell(); |
271 | 0 | } |
272 | | |
273 | 632 | void settle() { |
274 | 656 | while (cellIter.done() && !arenaIter.done()) { |
275 | 24 | arenaIter.next(); |
276 | 24 | if (!arenaIter.done()) { |
277 | 16 | cellIter.reset(arenaIter.get()); |
278 | 16 | } |
279 | 24 | } |
280 | 632 | } |
281 | | |
282 | 624 | void next() { |
283 | 624 | MOZ_ASSERT(!done()); |
284 | 624 | cellIter.next(); |
285 | 624 | settle(); |
286 | 624 | } |
287 | | }; |
288 | | |
289 | | // Iterator over the cells in a Zone, where the GC type (JSString, JSObject) is |
290 | | // known, for a single AllocKind. Example usages: |
291 | | // |
292 | | // for (auto obj = zone->cellIter<JSObject>(AllocKind::OBJECT0); !obj.done(); obj.next()) |
293 | | // ... |
294 | | // |
295 | | // for (auto script = zone->cellIter<JSScript>(); !script.done(); script.next()) |
296 | | // f(script->code()); |
297 | | // |
298 | | // As this code demonstrates, you can use 'script' as if it were a JSScript*. |
299 | | // Its actual type is ZoneCellIter<JSScript>, but for most purposes it will |
300 | | // autoconvert to JSScript*. |
301 | | // |
302 | | // Note that in the JSScript case, ZoneCellIter is able to infer the AllocKind |
303 | | // from the type 'JSScript', whereas in the JSObject case, the kind must be |
304 | | // given (because there are multiple AllocKinds for objects). |
305 | | // |
306 | | // Also, the static rooting hazard analysis knows that the JSScript case will |
307 | | // not GC during construction. The JSObject case needs to GC, or more precisely |
308 | | // to empty the nursery and clear out the store buffer, so that it can see all |
309 | | // objects to iterate over (the nursery is not iterable) and remove the |
310 | | // possibility of having pointers from the store buffer to data hanging off |
311 | | // stuff we're iterating over that we are going to delete. (The latter should |
312 | | // not be a problem, since such instances should be using RelocatablePtr do |
313 | | // remove themselves from the store buffer on deletion, but currently for |
314 | | // subtle reasons that isn't good enough.) |
315 | | // |
316 | | // If the iterator is used within a GC, then there is no need to evict the |
317 | | // nursery (again). You may select a variant that will skip the eviction either |
318 | | // by specializing on a GCType that is never allocated in the nursery, or |
319 | | // explicitly by passing in a trailing AutoAssertEmptyNursery argument. |
320 | | // |
321 | | template <typename GCType> |
322 | | class ZoneCellIter : public ZoneCellIter<TenuredCell> { |
323 | | public: |
324 | | // Non-nursery allocated (equivalent to having an entry in |
325 | | // MapTypeToFinalizeKind). The template declaration here is to discard this |
326 | | // constructor overload if MapTypeToFinalizeKind<GCType>::kind does not |
327 | | // exist. Note that there will be no remaining overloads that will work, |
328 | | // which makes sense given that you haven't specified which of the |
329 | | // AllocKinds to use for GCType. |
330 | | // |
331 | | // If we later add a nursery allocable GCType with a single AllocKind, we |
332 | | // will want to add an overload of this constructor that does the right |
333 | | // thing (ie, it empties the nursery before iterating.) |
334 | 8 | explicit ZoneCellIter(JS::Zone* zone) : ZoneCellIter<TenuredCell>() { |
335 | 8 | init(zone, MapTypeToFinalizeKind<GCType>::kind); |
336 | 8 | } js::gc::ZoneCellIter<JSScript>::ZoneCellIter(JS::Zone*) Line | Count | Source | 334 | 8 | explicit ZoneCellIter(JS::Zone* zone) : ZoneCellIter<TenuredCell>() { | 335 | 8 | init(zone, MapTypeToFinalizeKind<GCType>::kind); | 336 | 8 | } |
Unexecuted instantiation: js::gc::ZoneCellIter<js::jit::JitCode>::ZoneCellIter(JS::Zone*) Unexecuted instantiation: js::gc::ZoneCellIter<js::ObjectGroup>::ZoneCellIter(JS::Zone*) Unexecuted instantiation: js::gc::ZoneCellIter<js::BaseShape>::ZoneCellIter(JS::Zone*) Unexecuted instantiation: js::gc::ZoneCellIter<js::LazyScript>::ZoneCellIter(JS::Zone*) |
337 | | |
338 | | // Non-nursery allocated, nursery is known to be empty: same behavior as above. |
339 | 0 | ZoneCellIter(JS::Zone* zone, const js::gc::AutoAssertEmptyNursery&) : ZoneCellIter(zone) { |
340 | 0 | } Unexecuted instantiation: js::gc::ZoneCellIter<JSScript>::ZoneCellIter(JS::Zone*, js::gc::AutoAssertEmptyNursery const&) Unexecuted instantiation: js::gc::ZoneCellIter<js::LazyScript>::ZoneCellIter(JS::Zone*, js::gc::AutoAssertEmptyNursery const&) |
341 | | |
342 | | // Arbitrary kind, which will be assumed to be nursery allocable (and |
343 | | // therefore the nursery will be emptied before iterating.) |
344 | 0 | ZoneCellIter(JS::Zone* zone, AllocKind kind) : ZoneCellIter<TenuredCell>(zone, kind) { |
345 | 0 | } |
346 | | |
347 | | // Arbitrary kind, which will be assumed to be nursery allocable, but the |
348 | | // nursery is known to be empty already: same behavior as non-nursery types. |
349 | | ZoneCellIter(JS::Zone* zone, AllocKind kind, const js::gc::AutoAssertEmptyNursery& empty) |
350 | | : ZoneCellIter<TenuredCell>(zone, kind, empty) |
351 | 0 | { |
352 | 0 | } |
353 | | |
354 | 2.50k | GCType* get() const { return ZoneCellIter<TenuredCell>::get<GCType>(); } js::gc::ZoneCellIter<JSScript>::get() const Line | Count | Source | 354 | 2.50k | GCType* get() const { return ZoneCellIter<TenuredCell>::get<GCType>(); } |
Unexecuted instantiation: js::gc::ZoneCellIter<js::jit::JitCode>::get() const Unexecuted instantiation: js::gc::ZoneCellIter<JSObject>::get() const Unexecuted instantiation: js::gc::ZoneCellIter<js::ObjectGroup>::get() const Unexecuted instantiation: js::gc::ZoneCellIter<js::BaseShape>::get() const Unexecuted instantiation: js::gc::ZoneCellIter<js::LazyScript>::get() const |
355 | 1.24k | operator GCType*() const { return get(); } js::gc::ZoneCellIter<JSScript>::operator JSScript*() const Line | Count | Source | 355 | 1.24k | operator GCType*() const { return get(); } |
Unexecuted instantiation: js::gc::ZoneCellIter<js::jit::JitCode>::operator js::jit::JitCode*() const Unexecuted instantiation: js::gc::ZoneCellIter<js::ObjectGroup>::operator js::ObjectGroup*() const Unexecuted instantiation: js::gc::ZoneCellIter<js::LazyScript>::operator js::LazyScript*() const |
356 | 1.25k | GCType* operator ->() const { return get(); } js::gc::ZoneCellIter<JSScript>::operator->() const Line | Count | Source | 356 | 1.25k | GCType* operator ->() const { return get(); } |
Unexecuted instantiation: js::gc::ZoneCellIter<JSObject>::operator->() const Unexecuted instantiation: js::gc::ZoneCellIter<js::BaseShape>::operator->() const Unexecuted instantiation: js::gc::ZoneCellIter<js::ObjectGroup>::operator->() const Unexecuted instantiation: js::gc::ZoneCellIter<js::LazyScript>::operator->() const |
357 | | }; |
358 | | |
359 | | } /* namespace gc */ |
360 | | } /* namespace js */ |
361 | | |
362 | | #endif /* gc_GC_inl_h */ |