[SM91] Update to Spidermonkey 91.1.3 APIs
[0ad.git] / libraries / source / spidermonkey / include-win32-release / js / TracingAPI.h
blob339f1de60705c3a205781ce7d597dcf3f52bc56e
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 js_TracingAPI_h
8 #define js_TracingAPI_h
10 #include "js/GCTypeMacros.h"
11 #include "js/HeapAPI.h"
12 #include "js/TraceKind.h"
14 class JS_PUBLIC_API JSTracer;
16 namespace JS {
17 class JS_PUBLIC_API CallbackTracer;
18 template <typename T>
19 class Heap;
20 template <typename T>
21 class TenuredHeap;
23 /** Returns a static string equivalent of |kind|. */
24 JS_PUBLIC_API const char* GCTraceKindToAscii(JS::TraceKind kind);
26 /** Returns the base size in bytes of the GC thing of kind |kind|. */
27 JS_PUBLIC_API size_t GCTraceKindSize(JS::TraceKind kind);
29 // Kinds of JSTracer.
30 enum class TracerKind {
31 // Marking path: a tracer used only for marking liveness of cells, not
32 // for moving them.
33 Marking,
35 // Generic tracers: Internal tracers that have a different virtual method
36 // called for each edge kind.
38 // Order is important. All generic kinds must follow this one.
39 Generic,
41 // Specific kinds of generic tracer.
42 Tenuring,
43 Moving,
44 GrayBuffering,
45 ClearEdges,
46 Sweeping,
47 Barrier,
49 // Callback tracers: General-purpose tracers that have a single virtual
50 // method called on every edge.
52 // Order is important. All callback kinds must follow this one.
53 Callback,
55 // Specific kinds of callback tracer.
56 UnmarkGray,
57 VerifyTraceProtoAndIface,
60 enum class WeakMapTraceAction {
61 /**
62 * Do not trace into weak map keys or values during traversal. Users must
63 * handle weak maps manually.
65 Skip,
67 /**
68 * Do true ephemeron marking with a weak key lookup marking phase. This is
69 * the default for GCMarker.
71 Expand,
73 /**
74 * Trace through to all values, irrespective of whether the keys are live
75 * or not. Used for non-marking tracers.
77 TraceValues,
79 /**
80 * Trace through to all keys and values, irrespective of whether the keys
81 * are live or not. Used for non-marking tracers.
83 TraceKeysAndValues
86 // Whether a tracer should trace weak edges. GCMarker sets this to Skip.
87 enum class WeakEdgeTraceAction { Skip, Trace };
89 // Whether a tracer can skip tracing JS::Ids. This is needed by the cycle
90 // collector to skip some Ids for performance reasons. Not all Ids are skipped.
91 enum class IdTraceAction { CanSkip, Trace };
93 struct TraceOptions {
94 JS::WeakMapTraceAction weakMapAction = WeakMapTraceAction::TraceValues;
95 JS::WeakEdgeTraceAction weakEdgeAction = WeakEdgeTraceAction::Trace;
96 JS::IdTraceAction idAction = IdTraceAction::Trace;
98 TraceOptions() = default;
99 TraceOptions(JS::WeakMapTraceAction weakMapActionArg,
100 JS::WeakEdgeTraceAction weakEdgeActionArg,
101 JS::IdTraceAction idActionArg = IdTraceAction::Trace)
102 : weakMapAction(weakMapActionArg),
103 weakEdgeAction(weakEdgeActionArg),
104 idAction(idActionArg) {}
105 MOZ_IMPLICIT TraceOptions(JS::WeakMapTraceAction weakMapActionArg)
106 : weakMapAction(weakMapActionArg) {}
107 MOZ_IMPLICIT TraceOptions(JS::WeakEdgeTraceAction weakEdgeActionArg)
108 : weakEdgeAction(weakEdgeActionArg) {}
109 MOZ_IMPLICIT TraceOptions(JS::IdTraceAction idActionArg)
110 : idAction(idActionArg) {}
113 class AutoTracingName;
114 class AutoTracingIndex;
116 // Optional context information that can be used to construct human readable
117 // descriptions of what is being traced.
118 class TracingContext {
119 public:
120 // Access to the tracing context: When tracing with a JS::CallbackTracer, we
121 // invoke the callback with the edge location and the type of target. This is
122 // useful for operating on the edge in the abstract or on the target thing,
123 // satisfying most common use cases. However, some tracers need additional
124 // detail about the specific edge that is being traced in order to be
125 // useful. Unfortunately, the raw pointer to the edge that we provide is not
126 // enough information to infer much of anything useful about that edge.
128 // In order to better support use cases that care in particular about edges --
129 // as opposed to the target thing -- tracing implementations are responsible
130 // for providing extra context information about each edge they trace, as it
131 // is traced. This contains, at a minimum, an edge name and, when tracing an
132 // array, the index. Further specialization can be achieved (with some
133 // complexity), by associating a functor with the tracer so that, when
134 // requested, the user can generate totally custom edge descriptions.
136 // Returns the current edge's name. It is only valid to call this when
137 // inside the trace callback, however, the edge name will always be set.
138 const char* name() const {
139 MOZ_ASSERT(name_);
140 return name_;
143 // Returns the current edge's index, if marked as part of an array of edges.
144 // This must be called only inside the trace callback. When not tracing an
145 // array, the value will be InvalidIndex.
146 constexpr static size_t InvalidIndex = size_t(-1);
147 size_t index() const { return index_; }
149 // Build a description of this edge in the heap graph. This call may invoke
150 // the context functor, if set, which may inspect arbitrary areas of the
151 // heap. On the other hand, the description provided by this method may be
152 // substantially more accurate and useful than those provided by only the
153 // name and index.
154 void getEdgeName(char* buffer, size_t bufferSize);
156 // The trace implementation may associate a callback with one or more edges
157 // using AutoTracingDetails. This functor is called by getEdgeName and
158 // is responsible for providing a textual representation of the edge currently
159 // being traced. The callback has access to the full heap, including the
160 // currently set tracing context.
161 class Functor {
162 public:
163 virtual void operator()(TracingContext* tcx, char* buf, size_t bufsize) = 0;
166 private:
167 friend class AutoTracingName;
168 const char* name_ = nullptr;
170 friend class AutoTracingIndex;
171 size_t index_ = InvalidIndex;
173 friend class AutoTracingDetails;
174 Functor* functor_ = nullptr;
177 } // namespace JS
179 namespace js {
180 class GenericTracer;
181 } // namespace js
183 class JS_PUBLIC_API JSTracer {
184 public:
185 // Return the runtime set on the tracer.
186 JSRuntime* runtime() const { return runtime_; }
188 JS::TracerKind kind() const { return kind_; }
189 bool isMarkingTracer() const { return kind_ == JS::TracerKind::Marking; }
190 bool isTenuringTracer() const { return kind_ == JS::TracerKind::Tenuring; }
191 bool isGenericTracer() const { return kind_ >= JS::TracerKind::Generic; }
192 bool isCallbackTracer() const { return kind_ >= JS::TracerKind::Callback; }
194 inline js::GenericTracer* asGenericTracer();
195 inline JS::CallbackTracer* asCallbackTracer();
197 JS::WeakMapTraceAction weakMapAction() const {
198 return options_.weakMapAction;
200 bool traceWeakEdges() const {
201 return options_.weakEdgeAction == JS::WeakEdgeTraceAction::Trace;
203 bool canSkipJsids() const {
204 return options_.idAction == JS::IdTraceAction::CanSkip;
207 JS::TracingContext& context() { return context_; }
209 // Get the current GC number. Only call this method if |isMarkingTracer()|
210 // is true.
211 uint32_t gcNumberForMarking() const;
213 protected:
214 JSTracer(JSRuntime* rt, JS::TracerKind kind,
215 JS::TraceOptions options = JS::TraceOptions())
216 : runtime_(rt), kind_(kind), options_(options) {}
218 private:
219 JSRuntime* const runtime_;
220 const JS::TracerKind kind_;
221 const JS::TraceOptions options_;
222 JS::TracingContext context_;
225 namespace js {
227 class GenericTracer : public JSTracer {
228 public:
229 GenericTracer(JSRuntime* rt, JS::TracerKind kind = JS::TracerKind::Generic,
230 JS::TraceOptions options = JS::TraceOptions())
231 : JSTracer(rt, kind, options) {
232 MOZ_ASSERT(isGenericTracer());
235 // These methods are called when the tracer encounters an edge. Clients should
236 // override them to receive notifications when an edge of each type is
237 // visited.
239 // The caller updates the edge with the return value (if different).
241 // In C++, overriding a method hides all methods in the base class with that
242 // name, not just methods with that signature. Thus, the typed edge methods
243 // have to have distinct names to allow us to override them individually,
244 // which is freqently useful if, for example, we only want to process one type
245 // of edge.
246 virtual JSObject* onObjectEdge(JSObject* obj) = 0;
247 virtual JSString* onStringEdge(JSString* str) = 0;
248 virtual JS::Symbol* onSymbolEdge(JS::Symbol* sym) = 0;
249 virtual JS::BigInt* onBigIntEdge(JS::BigInt* bi) = 0;
250 virtual js::BaseScript* onScriptEdge(js::BaseScript* script) = 0;
251 virtual js::Shape* onShapeEdge(js::Shape* shape) = 0;
252 virtual js::RegExpShared* onRegExpSharedEdge(js::RegExpShared* shared) = 0;
253 virtual js::GetterSetter* onGetterSetterEdge(js::GetterSetter* gs) = 0;
254 virtual js::PropMap* onPropMapEdge(js::PropMap* map) = 0;
255 virtual js::BaseShape* onBaseShapeEdge(js::BaseShape* base) = 0;
256 virtual js::jit::JitCode* onJitCodeEdge(js::jit::JitCode* code) = 0;
257 virtual js::Scope* onScopeEdge(js::Scope* scope) = 0;
260 } // namespace js
262 namespace JS {
264 class JS_PUBLIC_API CallbackTracer : public js::GenericTracer {
265 public:
266 CallbackTracer(JSRuntime* rt, JS::TracerKind kind = JS::TracerKind::Callback,
267 JS::TraceOptions options = JS::TraceOptions())
268 : GenericTracer(rt, kind, options) {
269 MOZ_ASSERT(isCallbackTracer());
271 CallbackTracer(JSContext* cx, JS::TracerKind kind = JS::TracerKind::Callback,
272 JS::TraceOptions options = JS::TraceOptions());
274 // Override this method to receive notification when a node in the GC
275 // heap graph is visited.
276 virtual void onChild(const JS::GCCellPtr& thing) = 0;
278 private:
279 // This class implements the GenericTracer interface to dispatches to onChild.
280 virtual JSObject* onObjectEdge(JSObject* obj) {
281 onChild(JS::GCCellPtr(obj));
282 return obj;
284 virtual JSString* onStringEdge(JSString* str) {
285 onChild(JS::GCCellPtr(str));
286 return str;
288 virtual JS::Symbol* onSymbolEdge(JS::Symbol* sym) {
289 onChild(JS::GCCellPtr(sym));
290 return sym;
292 virtual JS::BigInt* onBigIntEdge(JS::BigInt* bi) {
293 onChild(JS::GCCellPtr(bi));
294 return bi;
296 virtual js::BaseScript* onScriptEdge(js::BaseScript* script) {
297 onChild(JS::GCCellPtr(script));
298 return script;
300 virtual js::Shape* onShapeEdge(js::Shape* shape) {
301 onChild(JS::GCCellPtr(shape, JS::TraceKind::Shape));
302 return shape;
304 virtual js::BaseShape* onBaseShapeEdge(js::BaseShape* base) {
305 onChild(JS::GCCellPtr(base, JS::TraceKind::BaseShape));
306 return base;
308 virtual js::GetterSetter* onGetterSetterEdge(js::GetterSetter* gs) {
309 onChild(JS::GCCellPtr(gs, JS::TraceKind::GetterSetter));
310 return gs;
312 virtual js::PropMap* onPropMapEdge(js::PropMap* map) {
313 onChild(JS::GCCellPtr(map, JS::TraceKind::PropMap));
314 return map;
316 virtual js::jit::JitCode* onJitCodeEdge(js::jit::JitCode* code) {
317 onChild(JS::GCCellPtr(code, JS::TraceKind::JitCode));
318 return code;
320 virtual js::Scope* onScopeEdge(js::Scope* scope) {
321 onChild(JS::GCCellPtr(scope, JS::TraceKind::Scope));
322 return scope;
324 virtual js::RegExpShared* onRegExpSharedEdge(js::RegExpShared* shared) {
325 onChild(JS::GCCellPtr(shared, JS::TraceKind::RegExpShared));
326 return shared;
330 // Set the name portion of the tracer's context for the current edge.
331 class MOZ_RAII AutoTracingName {
332 JSTracer* trc_;
334 public:
335 AutoTracingName(JSTracer* trc, const char* name) : trc_(trc) {
336 MOZ_ASSERT(name);
337 MOZ_ASSERT(!trc_->context().name_);
338 trc_->context().name_ = name;
340 ~AutoTracingName() {
341 MOZ_ASSERT(trc_->context().name_);
342 trc_->context().name_ = nullptr;
346 // Set the index portion of the tracer's context for the current range.
347 class MOZ_RAII AutoTracingIndex {
348 JSTracer* trc_;
350 public:
351 explicit AutoTracingIndex(JSTracer* trc, size_t initial = 0) : trc_(trc) {
352 MOZ_ASSERT(trc_->context().index_ == TracingContext::InvalidIndex);
353 trc_->context().index_ = initial;
355 ~AutoTracingIndex() {
356 MOZ_ASSERT(trc_->context().index_ != TracingContext::InvalidIndex);
357 trc_->context().index_ = TracingContext::InvalidIndex;
360 void operator++() {
361 MOZ_ASSERT(trc_->context().index_ != TracingContext::InvalidIndex);
362 ++trc_->context().index_;
366 // Set a context callback for the trace callback to use, if it needs a detailed
367 // edge description.
368 class MOZ_RAII AutoTracingDetails {
369 JSTracer* trc_;
371 public:
372 AutoTracingDetails(JSTracer* trc, TracingContext::Functor& func) : trc_(trc) {
373 MOZ_ASSERT(trc_->context().functor_ == nullptr);
374 trc_->context().functor_ = &func;
376 ~AutoTracingDetails() {
377 MOZ_ASSERT(trc_->context().functor_);
378 trc_->context().functor_ = nullptr;
382 // Save and clear tracing context when performing nested tracing.
383 class MOZ_RAII AutoClearTracingContext {
384 JSTracer* trc_;
385 TracingContext prev_;
387 public:
388 explicit AutoClearTracingContext(JSTracer* trc)
389 : trc_(trc), prev_(trc->context()) {
390 trc_->context() = TracingContext();
393 ~AutoClearTracingContext() { trc_->context() = prev_; }
396 } // namespace JS
398 js::GenericTracer* JSTracer::asGenericTracer() {
399 MOZ_ASSERT(isGenericTracer());
400 return static_cast<js::GenericTracer*>(this);
403 JS::CallbackTracer* JSTracer::asCallbackTracer() {
404 MOZ_ASSERT(isCallbackTracer());
405 return static_cast<JS::CallbackTracer*>(this);
408 namespace js {
410 class AbstractGeneratorObject;
411 class SavedFrame;
413 namespace gc {
415 #define JS_DECLARE_TRACE_EXTERNAL_EDGE(type) \
416 extern JS_PUBLIC_API void TraceExternalEdge(JSTracer* trc, type* thingp, \
417 const char* name);
419 // Declare edge-tracing function overloads for public GC pointer types.
420 JS_FOR_EACH_PUBLIC_GC_POINTER_TYPE(JS_DECLARE_TRACE_EXTERNAL_EDGE)
421 JS_FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(JS_DECLARE_TRACE_EXTERNAL_EDGE)
423 #undef JS_DECLARE_TRACE_EXTERNAL_EDGE
425 } // namespace gc
426 } // namespace js
428 namespace JS {
430 // The JS::TraceEdge family of functions traces the given GC thing reference.
431 // This performs the tracing action configured on the given JSTracer: typically
432 // calling the JSTracer::callback or marking the thing as live.
434 // The argument to JS::TraceEdge is an in-out param: when the function returns,
435 // the garbage collector might have moved the GC thing. In this case, the
436 // reference passed to JS::TraceEdge will be updated to the thing's new
437 // location. Callers of this method are responsible for updating any state that
438 // is dependent on the object's address. For example, if the object's address
439 // is used as a key in a hashtable, then the object must be removed and
440 // re-inserted with the correct hash.
442 // Note that while |edgep| must never be null, it is fine for |*edgep| to be
443 // nullptr.
445 template <typename T>
446 inline void TraceEdge(JSTracer* trc, JS::Heap<T>* thingp, const char* name) {
447 MOZ_ASSERT(thingp);
448 if (*thingp) {
449 js::gc::TraceExternalEdge(trc, thingp->unsafeGet(), name);
453 template <typename T>
454 inline void TraceEdge(JSTracer* trc, JS::TenuredHeap<T>* thingp,
455 const char* name) {
456 MOZ_ASSERT(thingp);
457 if (T ptr = thingp->unbarrieredGetPtr()) {
458 js::gc::TraceExternalEdge(trc, &ptr, name);
459 thingp->setPtr(ptr);
463 // Edges that are always traced as part of root marking do not require
464 // incremental barriers. |JS::UnsafeTraceRoot| overloads allow for marking
465 // non-barriered pointers but assert that this happens during root marking.
467 // Note that while |edgep| must never be null, it is fine for |*edgep| to be
468 // nullptr.
469 #define JS_DECLARE_UNSAFE_TRACE_ROOT(type) \
470 extern JS_PUBLIC_API void UnsafeTraceRoot(JSTracer* trc, type* edgep, \
471 const char* name);
473 // Declare edge-tracing function overloads for public GC pointer types.
474 JS_FOR_EACH_PUBLIC_GC_POINTER_TYPE(JS_DECLARE_UNSAFE_TRACE_ROOT)
475 JS_FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(JS_DECLARE_UNSAFE_TRACE_ROOT)
477 // We also require overloads for these purely-internal types. These overloads
478 // ought not be in public headers, and they should use a different name in order
479 // to not be *actual* overloads, but for the moment we still declare them here.
480 JS_DECLARE_UNSAFE_TRACE_ROOT(js::AbstractGeneratorObject*)
481 JS_DECLARE_UNSAFE_TRACE_ROOT(js::SavedFrame*)
483 #undef JS_DECLARE_UNSAFE_TRACE_ROOT
485 extern JS_PUBLIC_API void TraceChildren(JSTracer* trc, GCCellPtr thing);
487 } // namespace JS
489 namespace js {
491 inline bool IsTracerKind(JSTracer* trc, JS::TracerKind kind) {
492 return trc->kind() == kind;
495 // Trace an edge that is not a GC root and is not wrapped in a barriered
496 // wrapper for some reason.
498 // This method does not check if |*edgep| is non-null before tracing through
499 // it, so callers must check any nullable pointer before calling this method.
500 extern JS_PUBLIC_API void UnsafeTraceManuallyBarrieredEdge(JSTracer* trc,
501 JSObject** edgep,
502 const char* name);
504 // Not part of the public API, but declared here so we can use it in
505 // GCPolicyAPI.h
506 template <typename T>
507 inline bool TraceManuallyBarrieredWeakEdge(JSTracer* trc, T* thingp,
508 const char* name);
510 template <typename T>
511 class BarrieredBase;
513 template <typename T>
514 inline bool TraceWeakEdge(JSTracer* trc, BarrieredBase<T>* thingp,
515 const char* name);
517 namespace gc {
519 // Return true if the given edge is not live and is about to be swept.
520 template <typename T>
521 extern JS_PUBLIC_API bool EdgeNeedsSweep(JS::Heap<T>* edgep);
523 // Not part of the public API, but declared here so we can use it in GCPolicy
524 // which is.
525 template <typename T>
526 bool IsAboutToBeFinalizedUnbarriered(T* thingp);
528 } // namespace gc
530 #ifdef DEBUG
532 * Return whether the runtime is currently being destroyed, for use in
533 * assertions.
535 extern JS_PUBLIC_API bool RuntimeIsBeingDestroyed();
536 #endif
538 } // namespace js
540 #endif /* js_TracingAPI_h */