/work/obj-fuzz/dist/include/js/TraceKind.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 js_TraceKind_h |
8 | | #define js_TraceKind_h |
9 | | |
10 | | #include "mozilla/UniquePtr.h" |
11 | | |
12 | | #include "js/TypeDecls.h" |
13 | | |
14 | | // Forward declarations of all the types a TraceKind can denote. |
15 | | namespace js { |
16 | | class BaseShape; |
17 | | class LazyScript; |
18 | | class ObjectGroup; |
19 | | class RegExpShared; |
20 | | class Shape; |
21 | | class Scope; |
22 | | namespace jit { |
23 | | class JitCode; |
24 | | } // namespace jit |
25 | | } // namespace js |
26 | | |
27 | | namespace JS { |
28 | | |
29 | | // When tracing a thing, the GC needs to know about the layout of the object it |
30 | | // is looking at. There are a fixed number of different layouts that the GC |
31 | | // knows about. The "trace kind" is a static map which tells which layout a GC |
32 | | // thing has. |
33 | | // |
34 | | // Although this map is public, the details are completely hidden. Not all of |
35 | | // the matching C++ types are exposed, and those that are, are opaque. |
36 | | // |
37 | | // See Value::gcKind() and JSTraceCallback in Tracer.h for more details. |
38 | | enum class TraceKind |
39 | | { |
40 | | // These trace kinds have a publicly exposed, although opaque, C++ type. |
41 | | // Note: The order here is determined by our Value packing. Other users |
42 | | // should sort alphabetically, for consistency. |
43 | | Object = 0x00, |
44 | | String = 0x02, |
45 | | Symbol = 0x03, |
46 | | |
47 | | // 0x1 is not used for any GCThing Value tag, so we use it for Script. |
48 | | Script = 0x01, |
49 | | |
50 | | // Shape details are exposed through JS_TraceShapeCycleCollectorChildren. |
51 | | Shape = 0x04, |
52 | | |
53 | | // ObjectGroup details are exposed through JS_TraceObjectGroupCycleCollectorChildren. |
54 | | ObjectGroup = 0x05, |
55 | | |
56 | | // The kind associated with a nullptr. |
57 | | Null = 0x06, |
58 | | |
59 | | // The following kinds do not have an exposed C++ idiom. |
60 | | BaseShape = 0x0F, |
61 | | JitCode = 0x1F, |
62 | | LazyScript = 0x2F, |
63 | | Scope = 0x3F, |
64 | | RegExpShared = 0x4F, |
65 | | #ifdef ENABLE_BIGINT |
66 | | BigInt = 0x5F |
67 | | #endif |
68 | | }; |
69 | | const static uintptr_t OutOfLineTraceKindMask = 0x07; |
70 | | |
71 | | #define ASSERT_TRACE_KIND(tk) \ |
72 | | static_assert((uintptr_t(tk) & OutOfLineTraceKindMask) == OutOfLineTraceKindMask, \ |
73 | | "mask bits are set") |
74 | | ASSERT_TRACE_KIND(JS::TraceKind::BaseShape); |
75 | | ASSERT_TRACE_KIND(JS::TraceKind::JitCode); |
76 | | ASSERT_TRACE_KIND(JS::TraceKind::LazyScript); |
77 | | ASSERT_TRACE_KIND(JS::TraceKind::Scope); |
78 | | ASSERT_TRACE_KIND(JS::TraceKind::RegExpShared); |
79 | | #undef ASSERT_TRACE_KIND |
80 | | |
81 | | // When this header is imported inside SpiderMonkey, the class definitions are |
82 | | // available and we can query those definitions to find the correct kind |
83 | | // directly from the class hierarchy. |
84 | | template <typename T> |
85 | | struct MapTypeToTraceKind { |
86 | | static const JS::TraceKind kind = T::TraceKind; |
87 | | }; |
88 | | |
89 | | // When this header is used outside SpiderMonkey, the class definitions are not |
90 | | // available, so the following table containing all public GC types is used. |
91 | | #define JS_FOR_EACH_TRACEKIND(D) \ |
92 | | /* PrettyName TypeName AddToCCKind */ \ |
93 | 75.5k | D(BaseShape, js::BaseShape, true) \ |
94 | 75.5k | D(JitCode, js::jit::JitCode, true) \ |
95 | 267 | D(LazyScript, js::LazyScript, true) \ |
96 | 1.03k | D(Scope, js::Scope, true) \ |
97 | 5.55M | D(Object, JSObject, true) \ |
98 | 5.55M | D(ObjectGroup, js::ObjectGroup, true) \ |
99 | 681k | D(Script, JSScript, true) \ |
100 | 530k | D(Shape, js::Shape, true) \ |
101 | 530k | D(String, JSString, false) \ |
102 | 52 | D(Symbol, JS::Symbol, false) \ |
103 | 0 | IF_BIGINT(D(BigInt, JS::BigInt, false),) \ |
104 | 52 | D(RegExpShared, js::RegExpShared, true) |
105 | | |
106 | | // Map from all public types to their trace kind. |
107 | | #define JS_EXPAND_DEF(name, type, _) \ |
108 | | template <> struct MapTypeToTraceKind<type> { \ |
109 | | static const JS::TraceKind kind = JS::TraceKind::name; \ |
110 | | }; |
111 | | JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF); |
112 | | #undef JS_EXPAND_DEF |
113 | | |
114 | | // RootKind is closely related to TraceKind. Whereas TraceKind's indices are |
115 | | // laid out for convenient embedding as a pointer tag, the indicies of RootKind |
116 | | // are designed for use as array keys via EnumeratedArray. |
117 | | enum class RootKind : int8_t |
118 | | { |
119 | | // These map 1:1 with trace kinds. |
120 | | #define EXPAND_ROOT_KIND(name, _0, _1) \ |
121 | | name, |
122 | | JS_FOR_EACH_TRACEKIND(EXPAND_ROOT_KIND) |
123 | | #undef EXPAND_ROOT_KIND |
124 | | |
125 | | // These tagged pointers are special-cased for performance. |
126 | | Id, |
127 | | Value, |
128 | | |
129 | | // Everything else. |
130 | | Traceable, |
131 | | |
132 | | Limit |
133 | | }; |
134 | | |
135 | | // Most RootKind correspond directly to a trace kind. |
136 | | template <TraceKind traceKind> struct MapTraceKindToRootKind {}; |
137 | | #define JS_EXPAND_DEF(name, _0, _1) \ |
138 | | template <> struct MapTraceKindToRootKind<JS::TraceKind::name> { \ |
139 | | static const JS::RootKind kind = JS::RootKind::name; \ |
140 | | }; |
141 | | JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF) |
142 | | #undef JS_EXPAND_DEF |
143 | | |
144 | | // Specify the RootKind for all types. Value and jsid map to special cases; |
145 | | // Cell pointer types we can derive directly from the TraceKind; everything else |
146 | | // should go in the Traceable list and use GCPolicy<T>::trace for tracing. |
147 | | template <typename T> |
148 | | struct MapTypeToRootKind { |
149 | | static const JS::RootKind kind = JS::RootKind::Traceable; |
150 | | }; |
151 | | template <typename T> |
152 | | struct MapTypeToRootKind<T*> { |
153 | | static const JS::RootKind kind = |
154 | | JS::MapTraceKindToRootKind<JS::MapTypeToTraceKind<T>::kind>::kind; |
155 | | }; |
156 | | template <> struct MapTypeToRootKind<JS::Realm*> { |
157 | | // Not a pointer to a GC cell. Use GCPolicy. |
158 | | static const JS::RootKind kind = JS::RootKind::Traceable; |
159 | | }; |
160 | | template <typename T> |
161 | | struct MapTypeToRootKind<mozilla::UniquePtr<T>> { |
162 | | static const JS::RootKind kind = JS::MapTypeToRootKind<T>::kind; |
163 | | }; |
164 | | template <> struct MapTypeToRootKind<JS::Value> { |
165 | | static const JS::RootKind kind = JS::RootKind::Value; |
166 | | }; |
167 | | template <> struct MapTypeToRootKind<jsid> { |
168 | | static const JS::RootKind kind = JS::RootKind::Id; |
169 | | }; |
170 | | template <> struct MapTypeToRootKind<JSFunction*> : public MapTypeToRootKind<JSObject*> {}; |
171 | | |
172 | | // Fortunately, few places in the system need to deal with fully abstract |
173 | | // cells. In those places that do, we generally want to move to a layout |
174 | | // templated function as soon as possible. This template wraps the upcast |
175 | | // for that dispatch. |
176 | | // |
177 | | // Given a call: |
178 | | // |
179 | | // DispatchTraceKindTyped(f, thing, traceKind, ... args) |
180 | | // |
181 | | // Downcast the |void *thing| to the specific type designated by |traceKind|, |
182 | | // and pass it to the functor |f| along with |... args|, forwarded. Pass the |
183 | | // type designated by |traceKind| as the functor's template argument. The |
184 | | // |thing| parameter is optional; without it, we simply pass through |... args|. |
185 | | |
186 | | // VS2017+, GCC and Clang require an explicit template declaration in front of |
187 | | // the specialization of operator() because it is a dependent template. VS2015, |
188 | | // on the other hand, gets very confused if we have a |template| token there. |
189 | | // The clang-cl front end defines _MSC_VER, but still requires the explicit |
190 | | // template declaration, so we must test for __clang__ here as well. |
191 | | #if (defined(_MSC_VER) && _MSC_VER < 1910) && !defined(__clang__) |
192 | | # define JS_DEPENDENT_TEMPLATE_HINT |
193 | | #else |
194 | | # define JS_DEPENDENT_TEMPLATE_HINT template |
195 | | #endif |
196 | | template <typename F, typename... Args> |
197 | | auto |
198 | | DispatchTraceKindTyped(F f, JS::TraceKind traceKind, Args&&... args) |
199 | | -> decltype(f. JS_DEPENDENT_TEMPLATE_HINT operator()<JSObject>(std::forward<Args>(args)...)) |
200 | 4.88M | { |
201 | 4.88M | switch (traceKind) { |
202 | 4.88M | #define JS_EXPAND_DEF(name, type, _) \ |
203 | 4.88M | case JS::TraceKind::name: \ |
204 | 4.88M | return f. JS_DEPENDENT_TEMPLATE_HINT operator()<type>(std::forward<Args>(args)...); |
205 | 4.88M | JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF); |
206 | 0 | #undef JS_EXPAND_DEF |
207 | 0 | default: |
208 | 0 | MOZ_CRASH("Invalid trace kind in DispatchTraceKindTyped."); |
209 | 4.88M | } |
210 | 4.88M | } Unexecuted instantiation: _ZN2JS22DispatchTraceKindTypedI20TraceChildrenFunctorJRP8JSTracerRPvEEEDTcldtfp_onclI8JSObjectEspclsr3stdE7forwardIT0_Efp1_EEET_NS_9TraceKindEDpOS8_ Unexecuted instantiation: Unified_cpp_js_src9.cpp:_ZN2JS22DispatchTraceKindTypedIN12_GLOBAL__N_123ParticipatesInCCFunctorEJEEEDTcldtfp_onclI8JSObjectEspclsr3stdE7forwardIT0_Efp1_EEET_NS_9TraceKindEDpOS4_ _ZN2JS22DispatchTraceKindTypedI27IsAboutToBeFinalizedFunctorJRPPN2js2gc4CellEEEEDTcldtfp_onclI8JSObjectEspclsr3stdE7forwardIT0_Efp1_EEET_NS_9TraceKindEDpOS9_ Line | Count | Source | 200 | 1.63M | { | 201 | 1.63M | switch (traceKind) { | 202 | 1.63M | #define JS_EXPAND_DEF(name, type, _) \ | 203 | 1.63M | case JS::TraceKind::name: \ | 204 | 1.63M | return f. JS_DEPENDENT_TEMPLATE_HINT operator()<type>(std::forward<Args>(args)...); | 205 | 1.63M | JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF); | 206 | 0 | #undef JS_EXPAND_DEF | 207 | 0 | default: | 208 | 0 | MOZ_CRASH("Invalid trace kind in DispatchTraceKindTyped."); | 209 | 1.63M | } | 210 | 1.63M | } |
_ZN2JS22DispatchTraceKindTypedI16TraceRootFunctorJRP8JSTracerRPPN2js2gc4CellERPKcEEEDTcldtfp_onclI8JSObjectEspclsr3stdE7forwardIT0_Efp1_EEET_NS_9TraceKindEDpOSF_ Line | Count | Source | 200 | 97 | { | 201 | 97 | switch (traceKind) { | 202 | 97 | #define JS_EXPAND_DEF(name, type, _) \ | 203 | 97 | case JS::TraceKind::name: \ | 204 | 97 | return f. JS_DEPENDENT_TEMPLATE_HINT operator()<type>(std::forward<Args>(args)...); | 205 | 97 | JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF); | 206 | 0 | #undef JS_EXPAND_DEF | 207 | 0 | default: | 208 | 0 | MOZ_CRASH("Invalid trace kind in DispatchTraceKindTyped."); | 209 | 97 | } | 210 | 97 | } |
_ZN2JS22DispatchTraceKindTypedI33TraceManuallyBarrieredEdgeFunctorJRP8JSTracerRPPN2js2gc4CellERPKcEEEDTcldtfp_onclI8JSObjectEspclsr3stdE7forwardIT0_Efp1_EEET_NS_9TraceKindEDpOSF_ Line | Count | Source | 200 | 3.25M | { | 201 | 3.25M | switch (traceKind) { | 202 | 3.25M | #define JS_EXPAND_DEF(name, type, _) \ | 203 | 3.25M | case JS::TraceKind::name: \ | 204 | 3.25M | return f. JS_DEPENDENT_TEMPLATE_HINT operator()<type>(std::forward<Args>(args)...); | 205 | 3.25M | JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF); | 206 | 0 | #undef JS_EXPAND_DEF | 207 | 0 | default: | 208 | 0 | MOZ_CRASH("Invalid trace kind in DispatchTraceKindTyped."); | 209 | 3.25M | } | 210 | 3.25M | } |
Unexecuted instantiation: _ZN2JS22DispatchTraceKindTypedI16PushArenaFunctorJRPN2js8GCMarkerERPNS2_2gc5ArenaEEEEDTcldtfp_onclI8JSObjectEspclsr3stdE7forwardIT0_Efp1_EEET_NS_9TraceKindEDpOSB_ |
211 | | #undef JS_DEPENDENT_TEMPLATE_HINT |
212 | | |
213 | | template <typename F, typename... Args> |
214 | | auto |
215 | | DispatchTraceKindTyped(F f, void* thing, JS::TraceKind traceKind, Args&&... args) |
216 | | -> decltype(f(static_cast<JSObject*>(nullptr), std::forward<Args>(args)...)) |
217 | | { |
218 | | switch (traceKind) { |
219 | | #define JS_EXPAND_DEF(name, type, _) \ |
220 | | case JS::TraceKind::name: \ |
221 | | return f(static_cast<type*>(thing), std::forward<Args>(args)...); |
222 | | JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF); |
223 | | #undef JS_EXPAND_DEF |
224 | | default: |
225 | | MOZ_CRASH("Invalid trace kind in DispatchTraceKindTyped."); |
226 | | } |
227 | | } |
228 | | |
229 | | } // namespace JS |
230 | | |
231 | | #endif // js_TraceKind_h |