2 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * vim: set ts=8 sts=2 et sw=2 tw=80:
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 * GC-internal definition of GC cell kinds.
12 #ifndef gc_AllocKind_h
13 #define gc_AllocKind_h
15 #include "mozilla/EnumeratedArray.h"
16 #include "mozilla/EnumeratedRange.h"
21 #include "js/TraceKind.h"
23 class JSDependentString
;
24 class JSExternalString
;
25 class JSFatInlineString
;
28 class JSThinInlineString
;
36 class DictionaryPropMap
;
37 class DictionaryShape
;
44 // The GC allocation kinds.
46 // These are defined by macros which enumerate the different allocation kinds
47 // and supply the following information:
49 // - the corresponding AllocKind
50 // - their JS::TraceKind
51 // - their C++ base type
52 // - a C++ type of the correct size
53 // - whether they can be finalized on the background thread
54 // - whether they can be allocated in the nursery (this is true for foreground
55 // finalized objects but these will can only actually be allocated in the
56 // nursery if JSCLASS_SKIP_NURSERY_FINALIZE is set)
57 // - whether they can be compacted
60 #define FOR_EACH_OBJECT_ALLOCKIND(D) \
61 /* AllocKind TraceKind TypeName SizedType BGFinal Nursery Compact */ \
62 D(FUNCTION, Object, JSObject, JSObject_Slots4, true, true, true) \
63 D(FUNCTION_EXTENDED, Object, JSObject, JSObject_Slots6, true, true, true) \
64 D(OBJECT0, Object, JSObject, JSObject_Slots0, false, true, true) \
65 D(OBJECT0_BACKGROUND, Object, JSObject, JSObject_Slots0, true, true, true) \
66 D(OBJECT2, Object, JSObject, JSObject_Slots2, false, true, true) \
67 D(OBJECT2_BACKGROUND, Object, JSObject, JSObject_Slots2, true, true, true) \
68 D(ARRAYBUFFER4, Object, JSObject, JSObject_Slots4, true, true, true) \
69 D(OBJECT4, Object, JSObject, JSObject_Slots4, false, true, true) \
70 D(OBJECT4_BACKGROUND, Object, JSObject, JSObject_Slots4, true, true, true) \
71 D(ARRAYBUFFER8, Object, JSObject, JSObject_Slots8, true, true, true) \
72 D(OBJECT8, Object, JSObject, JSObject_Slots8, false, true, true) \
73 D(OBJECT8_BACKGROUND, Object, JSObject, JSObject_Slots8, true, true, true) \
74 D(ARRAYBUFFER12, Object, JSObject, JSObject_Slots12, true, true, true) \
75 D(OBJECT12, Object, JSObject, JSObject_Slots12, false, true, true) \
76 D(OBJECT12_BACKGROUND, Object, JSObject, JSObject_Slots12, true, true, true) \
77 D(ARRAYBUFFER16, Object, JSObject, JSObject_Slots16, true, true, true) \
78 D(OBJECT16, Object, JSObject, JSObject_Slots16, false, true, true) \
79 D(OBJECT16_BACKGROUND, Object, JSObject, JSObject_Slots16, true, true, true)
81 #define FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(D) \
82 /* AllocKind TraceKind TypeName SizedType BGFinal Nursery Compact */ \
83 D(SCRIPT, Script, js::BaseScript, js::BaseScript, false, false, true) \
84 D(SHAPE, Shape, js::Shape, js::SizedShape, true, false, true) \
85 D(BASE_SHAPE, BaseShape, js::BaseShape, js::BaseShape, true, false, true) \
86 D(GETTER_SETTER, GetterSetter, js::GetterSetter, js::GetterSetter, true, false, true) \
87 D(COMPACT_PROP_MAP, PropMap, js::CompactPropMap, js::CompactPropMap, true, false, true) \
88 D(NORMAL_PROP_MAP, PropMap, js::NormalPropMap, js::NormalPropMap, true, false, true) \
89 D(DICT_PROP_MAP, PropMap, js::DictionaryPropMap, js::DictionaryPropMap, true, false, true) \
90 D(EXTERNAL_STRING, String, JSExternalString, JSExternalString, true, false, true) \
91 D(FAT_INLINE_ATOM, String, js::FatInlineAtom, js::FatInlineAtom, true, false, false) \
92 D(ATOM, String, js::NormalAtom, js::NormalAtom, true, false, false) \
93 D(SYMBOL, Symbol, JS::Symbol, JS::Symbol, true, false, false) \
94 D(JITCODE, JitCode, js::jit::JitCode, js::jit::JitCode, false, false, false) \
95 D(SCOPE, Scope, js::Scope, js::Scope, true, false, true) \
96 D(REGEXP_SHARED, RegExpShared, js::RegExpShared, js::RegExpShared, true, false, true)
98 #define FOR_EACH_NONOBJECT_NURSERY_ALLOCKIND(D) \
99 /* AllocKind TraceKind TypeName SizedType BGFinal Nursery Compact */ \
100 D(BIGINT, BigInt, JS::BigInt, JS::BigInt, true, true, true)
102 #define FOR_EACH_NURSERY_STRING_ALLOCKIND(D) \
103 D(FAT_INLINE_STRING, String, JSFatInlineString, JSFatInlineString, true, true, true) \
104 D(STRING, String, JSString, JSString, true, true, true)
107 #define FOR_EACH_NONOBJECT_ALLOCKIND(D) \
108 FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(D) \
109 FOR_EACH_NONOBJECT_NURSERY_ALLOCKIND(D) \
110 FOR_EACH_NURSERY_STRING_ALLOCKIND(D)
112 #define FOR_EACH_ALLOCKIND(D) \
113 FOR_EACH_OBJECT_ALLOCKIND(D) \
114 FOR_EACH_NONOBJECT_ALLOCKIND(D)
116 #define DEFINE_ALLOC_KIND(allocKind, _1, _2, _3, _4, _5, _6) allocKind,
117 enum class AllocKind
: uint8_t {
119 FOR_EACH_OBJECT_ALLOCKIND(DEFINE_ALLOC_KIND
)
122 OBJECT_LAST
= OBJECT_LIMIT
- 1,
124 FOR_EACH_NONOBJECT_ALLOCKIND(DEFINE_ALLOC_KIND
)
130 OBJECT_FIRST
= FUNCTION
// Hardcoded to first object kind.
133 #undef DEFINE_ALLOC_KIND
135 static_assert(int(AllocKind::FIRST
) == 0,
136 "Various places depend on AllocKind starting at 0");
137 static_assert(int(AllocKind::OBJECT_FIRST
) == 0,
138 "OBJECT_FIRST must be defined as the first object kind");
140 constexpr size_t AllocKindCount
= size_t(AllocKind::LIMIT
);
143 * This flag allows an allocation site to request a specific heap based upon the
144 * estimated lifetime or lifetime requirements of objects allocated from that
147 enum InitialHeap
: uint8_t { DefaultHeap
, TenuredHeap
};
149 inline bool IsAllocKind(AllocKind kind
) {
150 return kind
>= AllocKind::FIRST
&& kind
<= AllocKind::LIMIT
;
153 inline bool IsValidAllocKind(AllocKind kind
) {
154 return kind
>= AllocKind::FIRST
&& kind
<= AllocKind::LAST
;
157 const char* AllocKindName(AllocKind kind
);
159 inline bool IsObjectAllocKind(AllocKind kind
) {
160 return kind
>= AllocKind::OBJECT_FIRST
&& kind
<= AllocKind::OBJECT_LAST
;
163 inline bool IsShapeAllocKind(AllocKind kind
) {
164 return kind
== AllocKind::SHAPE
;
167 // Returns a sequence for use in a range-based for loop,
168 // to iterate over all alloc kinds.
169 inline auto AllAllocKinds() {
170 return mozilla::MakeEnumeratedRange(AllocKind::FIRST
, AllocKind::LIMIT
);
173 // Returns a sequence for use in a range-based for loop,
174 // to iterate over all object alloc kinds.
175 inline auto ObjectAllocKinds() {
176 return mozilla::MakeEnumeratedRange(AllocKind::OBJECT_FIRST
,
177 AllocKind::OBJECT_LIMIT
);
180 // Returns a sequence for use in a range-based for loop,
181 // to iterate over alloc kinds from |first| to |limit|, exclusive.
182 inline auto SomeAllocKinds(AllocKind first
= AllocKind::FIRST
,
183 AllocKind limit
= AllocKind::LIMIT
) {
184 MOZ_ASSERT(IsAllocKind(first
), "|first| is not a valid AllocKind!");
185 MOZ_ASSERT(IsAllocKind(limit
), "|limit| is not a valid AllocKind!");
186 return mozilla::MakeEnumeratedRange(first
, limit
);
189 // AllAllocKindArray<ValueType> gives an enumerated array of ValueTypes,
190 // with each index corresponding to a particular alloc kind.
191 template <typename ValueType
>
192 using AllAllocKindArray
=
193 mozilla::EnumeratedArray
<AllocKind
, AllocKind::LIMIT
, ValueType
>;
195 // ObjectAllocKindArray<ValueType> gives an enumerated array of ValueTypes,
196 // with each index corresponding to a particular object alloc kind.
197 template <typename ValueType
>
198 using ObjectAllocKindArray
=
199 mozilla::EnumeratedArray
<AllocKind
, AllocKind::OBJECT_LIMIT
, ValueType
>;
202 * Map from C++ type to alloc kind for non-object types. JSObject does not have
203 * a 1:1 mapping, so must use Arena::thingSize.
205 * The AllocKind is available as MapTypeToAllocKind<SomeType>::kind.
207 * There are specializations for strings and shapes since more than one derived
208 * type shares the same alloc kind.
210 template <typename T
>
211 struct MapTypeToAllocKind
{};
212 #define EXPAND_MAPTYPETOALLOCKIND(allocKind, traceKind, type, sizedType, \
213 bgFinal, nursery, compact) \
215 struct MapTypeToAllocKind<type> { \
216 static const AllocKind kind = AllocKind::allocKind; \
218 FOR_EACH_NONOBJECT_ALLOCKIND(EXPAND_MAPTYPETOALLOCKIND
)
219 #undef EXPAND_MAPTYPETOALLOCKIND
222 struct MapTypeToAllocKind
<JSDependentString
> {
223 static const AllocKind kind
= AllocKind::STRING
;
226 struct MapTypeToAllocKind
<JSRope
> {
227 static const AllocKind kind
= AllocKind::STRING
;
230 struct MapTypeToAllocKind
<JSLinearString
> {
231 static const AllocKind kind
= AllocKind::STRING
;
234 struct MapTypeToAllocKind
<JSThinInlineString
> {
235 static const AllocKind kind
= AllocKind::STRING
;
239 struct MapTypeToAllocKind
<js::SharedShape
> {
240 static const AllocKind kind
= AllocKind::SHAPE
;
243 struct MapTypeToAllocKind
<js::DictionaryShape
> {
244 static const AllocKind kind
= AllocKind::SHAPE
;
247 struct MapTypeToAllocKind
<js::ProxyShape
> {
248 static const AllocKind kind
= AllocKind::SHAPE
;
251 struct MapTypeToAllocKind
<js::WasmGCShape
> {
252 static const AllocKind kind
= AllocKind::SHAPE
;
255 static inline JS::TraceKind
MapAllocToTraceKind(AllocKind kind
) {
256 static const JS::TraceKind map
[] = {
257 #define EXPAND_ELEMENT(allocKind, traceKind, type, sizedType, bgFinal, \
259 JS::TraceKind::traceKind,
260 FOR_EACH_ALLOCKIND(EXPAND_ELEMENT
)
261 #undef EXPAND_ELEMENT
264 static_assert(std::size(map
) == AllocKindCount
,
265 "AllocKind-to-TraceKind mapping must be in sync");
266 return map
[size_t(kind
)];
269 static inline bool IsNurseryAllocable(AllocKind kind
) {
270 MOZ_ASSERT(IsValidAllocKind(kind
));
272 static const bool map
[] = {
273 #define DEFINE_NURSERY_ALLOCABLE(_1, _2, _3, _4, _5, nursery, _6) nursery,
274 FOR_EACH_ALLOCKIND(DEFINE_NURSERY_ALLOCABLE
)
275 #undef DEFINE_NURSERY_ALLOCABLE
278 static_assert(std::size(map
) == AllocKindCount
,
279 "IsNurseryAllocable sanity check");
280 return map
[size_t(kind
)];
283 static inline bool IsBackgroundFinalized(AllocKind kind
) {
284 MOZ_ASSERT(IsValidAllocKind(kind
));
286 static const bool map
[] = {
287 #define DEFINE_BACKGROUND_FINALIZED(_1, _2, _3, _4, bgFinal, _5, _6) bgFinal,
288 FOR_EACH_ALLOCKIND(DEFINE_BACKGROUND_FINALIZED
)
289 #undef DEFINE_BACKGROUND_FINALIZED
292 static_assert(std::size(map
) == AllocKindCount
,
293 "IsBackgroundFinalized sanity check");
294 return map
[size_t(kind
)];
297 static inline bool IsForegroundFinalized(AllocKind kind
) {
298 return !IsBackgroundFinalized(kind
);
301 static inline bool IsCompactingKind(AllocKind kind
) {
302 MOZ_ASSERT(IsValidAllocKind(kind
));
304 static const bool map
[] = {
305 #define DEFINE_COMPACTING_KIND(_1, _2, _3, _4, _5, _6, compact) compact,
306 FOR_EACH_ALLOCKIND(DEFINE_COMPACTING_KIND
)
307 #undef DEFINE_COMPACTING_KIND
310 static_assert(std::size(map
) == AllocKindCount
,
311 "IsCompactingKind sanity check");
312 return map
[size_t(kind
)];
315 static inline bool IsMovableKind(AllocKind kind
) {
316 return IsNurseryAllocable(kind
) || IsCompactingKind(kind
);
322 #endif /* gc_AllocKind_h */