Coverage Report

Created: 2018-09-25 14:53

/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