[SM91] Update to Spidermonkey 91.1.3 APIs
[0ad.git] / libraries / source / spidermonkey / include-win32-release / js / TraceKind.h
blob81202a2c05369232990b4f9d870fede7d79757c3
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_TraceKind_h
8 #define js_TraceKind_h
10 #include "mozilla/UniquePtr.h"
12 #include "js/TypeDecls.h"
14 // Forward declarations of all the types a TraceKind can denote.
15 class JSLinearString;
17 namespace js {
18 class BaseScript;
19 class BaseShape;
20 class GetterSetter;
21 class PropMap;
22 class RegExpShared;
23 class Shape;
24 class Scope;
25 namespace jit {
26 class JitCode;
27 } // namespace jit
28 } // namespace js
30 namespace JS {
32 // When tracing a thing, the GC needs to know about the layout of the object it
33 // is looking at. There are a fixed number of different layouts that the GC
34 // knows about. The "trace kind" is a static map which tells which layout a GC
35 // thing has.
37 // Although this map is public, the details are completely hidden. Not all of
38 // the matching C++ types are exposed, and those that are, are opaque.
40 // See Value::gcKind() and JSTraceCallback in Tracer.h for more details.
41 enum class TraceKind {
42 // These trace kinds have a publicly exposed, although opaque, C++ type.
43 // Note: The order here is determined by our Value packing. Other users
44 // should sort alphabetically, for consistency.
45 Object = 0x00,
46 BigInt = 0x01,
47 String = 0x02,
48 Symbol = 0x03,
50 // Shape details are exposed through JS_TraceShapeCycleCollectorChildren.
51 Shape = 0x04,
53 BaseShape = 0x05,
55 // The kind associated with a nullptr.
56 Null = 0x06,
58 // The following kinds do not have an exposed C++ idiom.
59 JitCode,
60 Script,
61 Scope,
62 RegExpShared,
63 GetterSetter,
64 PropMap,
67 // GCCellPtr packs the trace kind into the low bits of the pointer for common
68 // kinds.
69 const static uintptr_t OutOfLineTraceKindMask = 0x07;
70 static_assert(uintptr_t(JS::TraceKind::Null) < OutOfLineTraceKindMask,
71 "GCCellPtr requires an inline representation for nullptr");
73 // When this header is imported inside SpiderMonkey, the class definitions are
74 // available and we can query those definitions to find the correct kind
75 // directly from the class hierarchy.
76 template <typename T>
77 struct MapTypeToTraceKind {
78 static const JS::TraceKind kind = T::TraceKind;
81 // When this header is used outside SpiderMonkey, the class definitions are not
82 // available, so the following table containing all public GC types is used.
84 // canBeGray: GC can mark things of this kind gray. The cycle collector
85 // traverses gray GC things when looking for cycles.
86 // inCCGraph: Things of this kind are represented as nodes in the CC graph. This
87 // also means they can be used as a keys in WeakMap.
89 // clang-format off
90 #define JS_FOR_EACH_TRACEKIND(D) \
91 /* name type canBeGray inCCGraph */ \
92 D(BaseShape, js::BaseShape, true, false) \
93 D(JitCode, js::jit::JitCode, true, false) \
94 D(Scope, js::Scope, true, true) \
95 D(Object, JSObject, true, true) \
96 D(Script, js::BaseScript, true, true) \
97 D(Shape, js::Shape, true, false) \
98 D(String, JSString, false, false) \
99 D(Symbol, JS::Symbol, false, false) \
100 D(BigInt, JS::BigInt, false, false) \
101 D(RegExpShared, js::RegExpShared, true, true) \
102 D(GetterSetter, js::GetterSetter, true, true) \
103 D(PropMap, js::PropMap, false, false)
104 // clang-format on
106 // Returns true if the JS::TraceKind is represented as a node in cycle collector
107 // graph.
108 inline constexpr bool IsCCTraceKind(JS::TraceKind aKind) {
109 switch (aKind) {
110 #define JS_EXPAND_DEF(name, _1, _2, inCCGraph) \
111 case JS::TraceKind::name: \
112 return inCCGraph;
113 JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
114 #undef JS_EXPAND_DEF
115 default:
116 return false;
120 // Helper for SFINAE to ensure certain methods are only used on appropriate base
121 // types. This avoids common footguns such as `Cell::is<JSFunction>()` which
122 // match any type of JSObject.
123 template <typename T>
124 struct IsBaseTraceType : std::false_type {};
126 #define JS_EXPAND_DEF(_, type, _1, _2) \
127 template <> \
128 struct IsBaseTraceType<type> : std::true_type {};
129 JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
130 #undef JS_EXPAND_DEF
132 template <typename T>
133 inline constexpr bool IsBaseTraceType_v = IsBaseTraceType<T>::value;
135 // Map from all public types to their trace kind.
136 #define JS_EXPAND_DEF(name, type, _, _1) \
137 template <> \
138 struct MapTypeToTraceKind<type> { \
139 static const JS::TraceKind kind = JS::TraceKind::name; \
141 JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
142 #undef JS_EXPAND_DEF
144 template <>
145 struct MapTypeToTraceKind<JSLinearString> {
146 static const JS::TraceKind kind = JS::TraceKind::String;
148 template <>
149 struct MapTypeToTraceKind<JSFunction> {
150 static const JS::TraceKind kind = JS::TraceKind::Object;
152 template <>
153 struct MapTypeToTraceKind<JSScript> {
154 static const JS::TraceKind kind = JS::TraceKind::Script;
157 // RootKind is closely related to TraceKind. Whereas TraceKind's indices are
158 // laid out for convenient embedding as a pointer tag, the indicies of RootKind
159 // are designed for use as array keys via EnumeratedArray.
160 enum class RootKind : int8_t {
161 // These map 1:1 with trace kinds.
162 #define EXPAND_ROOT_KIND(name, _0, _1, _2) name,
163 JS_FOR_EACH_TRACEKIND(EXPAND_ROOT_KIND)
164 #undef EXPAND_ROOT_KIND
166 // These tagged pointers are special-cased for performance.
168 Value,
170 // Everything else.
171 Traceable,
173 Limit
176 // Most RootKind correspond directly to a trace kind.
177 template <TraceKind traceKind>
178 struct MapTraceKindToRootKind {};
179 #define JS_EXPAND_DEF(name, _0, _1, _2) \
180 template <> \
181 struct MapTraceKindToRootKind<JS::TraceKind::name> { \
182 static const JS::RootKind kind = JS::RootKind::name; \
184 JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF)
185 #undef JS_EXPAND_DEF
187 // Specify the RootKind for all types. Value and jsid map to special cases;
188 // Cell pointer types we can derive directly from the TraceKind; everything else
189 // should go in the Traceable list and use GCPolicy<T>::trace for tracing.
190 template <typename T>
191 struct MapTypeToRootKind {
192 static const JS::RootKind kind = JS::RootKind::Traceable;
194 template <typename T>
195 struct MapTypeToRootKind<T*> {
196 static const JS::RootKind kind =
197 JS::MapTraceKindToRootKind<JS::MapTypeToTraceKind<T>::kind>::kind;
199 template <>
200 struct MapTypeToRootKind<JS::Realm*> {
201 // Not a pointer to a GC cell. Use GCPolicy.
202 static const JS::RootKind kind = JS::RootKind::Traceable;
204 template <typename T>
205 struct MapTypeToRootKind<mozilla::UniquePtr<T>> {
206 static const JS::RootKind kind = JS::MapTypeToRootKind<T>::kind;
208 template <>
209 struct MapTypeToRootKind<JS::Value> {
210 static const JS::RootKind kind = JS::RootKind::Value;
212 template <>
213 struct MapTypeToRootKind<jsid> {
214 static const JS::RootKind kind = JS::RootKind::Id;
217 // Fortunately, few places in the system need to deal with fully abstract
218 // cells. In those places that do, we generally want to move to a layout
219 // templated function as soon as possible. This template wraps the upcast
220 // for that dispatch.
222 // Given a call:
224 // DispatchTraceKindTyped(f, thing, traceKind, ... args)
226 // Downcast the |void *thing| to the specific type designated by |traceKind|,
227 // and pass it to the functor |f| along with |... args|, forwarded. Pass the
228 // type designated by |traceKind| as the functor's template argument. The
229 // |thing| parameter is optional; without it, we simply pass through |... args|.
230 template <typename F, typename... Args>
231 auto DispatchTraceKindTyped(F f, JS::TraceKind traceKind, Args&&... args) {
232 switch (traceKind) {
233 #define JS_EXPAND_DEF(name, type, _, _1) \
234 case JS::TraceKind::name: \
235 return f.template operator()<type>(std::forward<Args>(args)...);
236 JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
237 #undef JS_EXPAND_DEF
238 default:
239 MOZ_CRASH("Invalid trace kind in DispatchTraceKindTyped.");
243 // Given a GC thing specified by pointer and trace kind, calls the functor |f|
244 // with a template argument of the actual type of the pointer and returns the
245 // result.
246 template <typename F>
247 auto MapGCThingTyped(void* thing, JS::TraceKind traceKind, F&& f) {
248 switch (traceKind) {
249 #define JS_EXPAND_DEF(name, type, _, _1) \
250 case JS::TraceKind::name: \
251 return f(static_cast<type*>(thing));
252 JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
253 #undef JS_EXPAND_DEF
254 default:
255 MOZ_CRASH("Invalid trace kind in MapGCThingTyped.");
259 // Given a GC thing specified by pointer and trace kind, calls the functor |f|
260 // with a template argument of the actual type of the pointer and ignores the
261 // result.
262 template <typename F>
263 void ApplyGCThingTyped(void* thing, JS::TraceKind traceKind, F&& f) {
264 // This function doesn't do anything but is supplied for symmetry with other
265 // MapGCThingTyped/ApplyGCThingTyped implementations that have to wrap the
266 // functor to return a dummy value that is ignored.
267 MapGCThingTyped(thing, traceKind, std::move(f));
270 } // namespace JS
272 #endif // js_TraceKind_h