no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / js / src / gc / AllocKind.h
blobcb3d063f89ce795a6b5aa63eba27f04c361830bc
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/. */
8 /*
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"
18 #include <iterator>
19 #include <stdint.h>
21 #include "js/TraceKind.h"
23 class JSDependentString;
24 class JSExternalString;
25 class JSFatInlineString;
26 class JSLinearString;
27 class JSRope;
28 class JSThinInlineString;
30 namespace js {
32 class CompactPropMap;
33 class FatInlineAtom;
34 class ThinInlineAtom;
35 class NormalAtom;
36 class NormalPropMap;
37 class DictionaryPropMap;
38 class DictionaryShape;
39 class SharedShape;
40 class ProxyShape;
41 class WasmGCShape;
43 namespace gc {
45 // The GC allocation kinds.
47 // These are defined by macros which enumerate the different allocation kinds
48 // and supply the following information:
50 // - the corresponding AllocKind
51 // - their JS::TraceKind
52 // - their C++ base type
53 // - a C++ type of the correct size
54 // - whether they can be finalized on the background thread
55 // - whether they can be allocated in the nursery (this is true for foreground
56 // finalized objects but these will can only actually be allocated in the
57 // nursery if JSCLASS_SKIP_NURSERY_FINALIZE is set)
58 // - whether they can be compacted
60 // clang-format off
61 #define FOR_EACH_OBJECT_ALLOCKIND(D) \
62 /* AllocKind TraceKind TypeName SizedType BGFinal Nursery Compact */ \
63 D(FUNCTION, Object, JSObject, JSObject_Slots4, true, true, true) \
64 D(FUNCTION_EXTENDED, Object, JSObject, JSObject_Slots7, true, true, true) \
65 D(OBJECT0, Object, JSObject, JSObject_Slots0, false, true, true) \
66 D(OBJECT0_BACKGROUND, Object, JSObject, JSObject_Slots0, true, true, true) \
67 D(OBJECT2, Object, JSObject, JSObject_Slots2, false, true, true) \
68 D(OBJECT2_BACKGROUND, Object, JSObject, JSObject_Slots2, true, true, true) \
69 D(ARRAYBUFFER4, Object, JSObject, JSObject_Slots4, true, true, true) \
70 D(OBJECT4, Object, JSObject, JSObject_Slots4, false, true, true) \
71 D(OBJECT4_BACKGROUND, Object, JSObject, JSObject_Slots4, true, true, true) \
72 D(ARRAYBUFFER8, Object, JSObject, JSObject_Slots8, true, true, true) \
73 D(OBJECT8, Object, JSObject, JSObject_Slots8, false, true, true) \
74 D(OBJECT8_BACKGROUND, Object, JSObject, JSObject_Slots8, true, true, true) \
75 D(ARRAYBUFFER12, Object, JSObject, JSObject_Slots12, true, true, true) \
76 D(OBJECT12, Object, JSObject, JSObject_Slots12, false, true, true) \
77 D(OBJECT12_BACKGROUND, Object, JSObject, JSObject_Slots12, true, true, true) \
78 D(ARRAYBUFFER16, Object, JSObject, JSObject_Slots16, true, true, true) \
79 D(OBJECT16, Object, JSObject, JSObject_Slots16, false, true, true) \
80 D(OBJECT16_BACKGROUND, Object, JSObject, JSObject_Slots16, true, true, true)
82 #define FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(D) \
83 /* AllocKind TraceKind TypeName SizedType BGFinal Nursery Compact */ \
84 D(SCRIPT, Script, js::BaseScript, js::BaseScript, false, false, true) \
85 D(SHAPE, Shape, js::Shape, js::SizedShape, true, false, true) \
86 D(BASE_SHAPE, BaseShape, js::BaseShape, js::BaseShape, true, false, true) \
87 D(GETTER_SETTER, GetterSetter, js::GetterSetter, js::GetterSetter, true, false, true) \
88 D(COMPACT_PROP_MAP, PropMap, js::CompactPropMap, js::CompactPropMap, true, false, true) \
89 D(NORMAL_PROP_MAP, PropMap, js::NormalPropMap, js::NormalPropMap, true, false, true) \
90 D(DICT_PROP_MAP, PropMap, js::DictionaryPropMap, js::DictionaryPropMap, true, false, true) \
91 D(EXTERNAL_STRING, String, JSExternalString, JSExternalString, true, false, true) \
92 D(FAT_INLINE_ATOM, String, js::FatInlineAtom, js::FatInlineAtom, true, false, false) \
93 D(ATOM, String, js::NormalAtom, js::NormalAtom, true, false, false) \
94 D(SYMBOL, Symbol, JS::Symbol, JS::Symbol, true, false, false) \
95 D(JITCODE, JitCode, js::jit::JitCode, js::jit::JitCode, false, false, false) \
96 D(SCOPE, Scope, js::Scope, js::Scope, true, false, true) \
97 D(REGEXP_SHARED, RegExpShared, js::RegExpShared, js::RegExpShared, true, false, true)
99 #define FOR_EACH_NONOBJECT_NURSERY_ALLOCKIND(D) \
100 /* AllocKind TraceKind TypeName SizedType BGFinal Nursery Compact */ \
101 D(BIGINT, BigInt, JS::BigInt, JS::BigInt, true, true, true)
103 #define FOR_EACH_NURSERY_STRING_ALLOCKIND(D) \
104 D(FAT_INLINE_STRING, String, JSFatInlineString, JSFatInlineString, true, true, true) \
105 D(STRING, String, JSString, JSString, true, true, true)
106 // clang-format on
108 #define FOR_EACH_NONOBJECT_ALLOCKIND(D) \
109 FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(D) \
110 FOR_EACH_NONOBJECT_NURSERY_ALLOCKIND(D) \
111 FOR_EACH_NURSERY_STRING_ALLOCKIND(D)
113 #define FOR_EACH_ALLOCKIND(D) \
114 FOR_EACH_OBJECT_ALLOCKIND(D) \
115 FOR_EACH_NONOBJECT_ALLOCKIND(D)
117 #define DEFINE_ALLOC_KIND(allocKind, _1, _2, _3, _4, _5, _6) allocKind,
118 enum class AllocKind : uint8_t {
119 // clang-format off
120 FOR_EACH_OBJECT_ALLOCKIND(DEFINE_ALLOC_KIND)
122 OBJECT_LIMIT,
123 OBJECT_LAST = OBJECT_LIMIT - 1,
125 FOR_EACH_NONOBJECT_ALLOCKIND(DEFINE_ALLOC_KIND)
127 LIMIT,
128 LAST = LIMIT - 1,
130 INVALID = LIMIT,
132 FIRST = 0,
133 OBJECT_FIRST = FUNCTION // Hardcoded to first object kind.
134 // clang-format on
136 #undef DEFINE_ALLOC_KIND
138 static_assert(int(AllocKind::FIRST) == 0,
139 "Various places depend on AllocKind starting at 0");
140 static_assert(int(AllocKind::OBJECT_FIRST) == 0,
141 "OBJECT_FIRST must be defined as the first object kind");
143 constexpr size_t AllocKindCount = size_t(AllocKind::LIMIT);
146 * A flag specifying either the tenured heap or a default heap (which may be
147 * either the nursery or the tenured heap).
149 * This allows an allocation site to request a heap based upon the estimated
150 * lifetime or lifetime requirements of objects allocated from that site.
152 * Order is important as these are numerically compared.
154 enum class Heap : uint8_t { Default = 0, Tenured = 1 };
156 constexpr bool IsAllocKind(AllocKind kind) {
157 return kind >= AllocKind::FIRST && kind <= AllocKind::LIMIT;
160 constexpr bool IsValidAllocKind(AllocKind kind) {
161 return kind >= AllocKind::FIRST && kind <= AllocKind::LAST;
164 const char* AllocKindName(AllocKind kind);
166 constexpr bool IsObjectAllocKind(AllocKind kind) {
167 return kind >= AllocKind::OBJECT_FIRST && kind <= AllocKind::OBJECT_LAST;
170 constexpr bool IsShapeAllocKind(AllocKind kind) {
171 return kind == AllocKind::SHAPE;
174 // Returns a sequence for use in a range-based for loop,
175 // to iterate over all alloc kinds.
176 constexpr auto AllAllocKinds() {
177 return mozilla::MakeEnumeratedRange(AllocKind::FIRST, AllocKind::LIMIT);
180 // Returns a sequence for use in a range-based for loop,
181 // to iterate over all object alloc kinds.
182 constexpr auto ObjectAllocKinds() {
183 return mozilla::MakeEnumeratedRange(AllocKind::OBJECT_FIRST,
184 AllocKind::OBJECT_LIMIT);
187 // Returns a sequence for use in a range-based for loop,
188 // to iterate over alloc kinds from |first| to |limit|, exclusive.
189 constexpr auto SomeAllocKinds(AllocKind first = AllocKind::FIRST,
190 AllocKind limit = AllocKind::LIMIT) {
191 MOZ_ASSERT(IsAllocKind(first), "|first| is not a valid AllocKind!");
192 MOZ_ASSERT(IsAllocKind(limit), "|limit| is not a valid AllocKind!");
193 return mozilla::MakeEnumeratedRange(first, limit);
196 // AllAllocKindArray<ValueType> gives an enumerated array of ValueTypes,
197 // with each index corresponding to a particular alloc kind.
198 template <typename ValueType>
199 using AllAllocKindArray =
200 mozilla::EnumeratedArray<AllocKind, AllocKind::LIMIT, ValueType>;
202 // ObjectAllocKindArray<ValueType> gives an enumerated array of ValueTypes,
203 // with each index corresponding to a particular object alloc kind.
204 template <typename ValueType>
205 using ObjectAllocKindArray =
206 mozilla::EnumeratedArray<AllocKind, AllocKind::OBJECT_LIMIT, ValueType>;
209 * Map from C++ type to alloc kind for non-object types. JSObject does not have
210 * a 1:1 mapping, so must use Arena::thingSize.
212 * The AllocKind is available as MapTypeToAllocKind<SomeType>::kind.
214 * There are specializations for strings and shapes since more than one derived
215 * type shares the same alloc kind.
217 template <typename T>
218 struct MapTypeToAllocKind {};
219 #define EXPAND_MAPTYPETOALLOCKIND(allocKind, traceKind, type, sizedType, \
220 bgFinal, nursery, compact) \
221 template <> \
222 struct MapTypeToAllocKind<type> { \
223 static const AllocKind kind = AllocKind::allocKind; \
225 FOR_EACH_NONOBJECT_ALLOCKIND(EXPAND_MAPTYPETOALLOCKIND)
226 #undef EXPAND_MAPTYPETOALLOCKIND
228 template <>
229 struct MapTypeToAllocKind<JSDependentString> {
230 static const AllocKind kind = AllocKind::STRING;
232 template <>
233 struct MapTypeToAllocKind<JSRope> {
234 static const AllocKind kind = AllocKind::STRING;
236 template <>
237 struct MapTypeToAllocKind<JSLinearString> {
238 static const AllocKind kind = AllocKind::STRING;
240 template <>
241 struct MapTypeToAllocKind<JSThinInlineString> {
242 static const AllocKind kind = AllocKind::STRING;
244 template <>
245 struct MapTypeToAllocKind<js::ThinInlineAtom> {
246 static const AllocKind kind = AllocKind::ATOM;
249 template <>
250 struct MapTypeToAllocKind<js::SharedShape> {
251 static const AllocKind kind = AllocKind::SHAPE;
253 template <>
254 struct MapTypeToAllocKind<js::DictionaryShape> {
255 static const AllocKind kind = AllocKind::SHAPE;
257 template <>
258 struct MapTypeToAllocKind<js::ProxyShape> {
259 static const AllocKind kind = AllocKind::SHAPE;
261 template <>
262 struct MapTypeToAllocKind<js::WasmGCShape> {
263 static const AllocKind kind = AllocKind::SHAPE;
266 constexpr JS::TraceKind MapAllocToTraceKind(AllocKind kind) {
267 constexpr JS::TraceKind map[] = {
268 #define EXPAND_ELEMENT(allocKind, traceKind, type, sizedType, bgFinal, \
269 nursery, compact) \
270 JS::TraceKind::traceKind,
271 FOR_EACH_ALLOCKIND(EXPAND_ELEMENT)
272 #undef EXPAND_ELEMENT
275 static_assert(std::size(map) == AllocKindCount,
276 "AllocKind-to-TraceKind mapping must be in sync");
277 return map[size_t(kind)];
280 constexpr bool IsNurseryAllocable(AllocKind kind) {
281 MOZ_ASSERT(IsValidAllocKind(kind));
283 constexpr bool map[] = {
284 #define DEFINE_NURSERY_ALLOCABLE(_1, _2, _3, _4, _5, nursery, _6) nursery,
285 FOR_EACH_ALLOCKIND(DEFINE_NURSERY_ALLOCABLE)
286 #undef DEFINE_NURSERY_ALLOCABLE
289 static_assert(std::size(map) == AllocKindCount,
290 "IsNurseryAllocable sanity check");
291 return map[size_t(kind)];
294 constexpr bool IsBackgroundFinalized(AllocKind kind) {
295 MOZ_ASSERT(IsValidAllocKind(kind));
297 constexpr bool map[] = {
298 #define DEFINE_BACKGROUND_FINALIZED(_1, _2, _3, _4, bgFinal, _5, _6) bgFinal,
299 FOR_EACH_ALLOCKIND(DEFINE_BACKGROUND_FINALIZED)
300 #undef DEFINE_BACKGROUND_FINALIZED
303 static_assert(std::size(map) == AllocKindCount,
304 "IsBackgroundFinalized sanity check");
305 return map[size_t(kind)];
308 constexpr bool IsForegroundFinalized(AllocKind kind) {
309 return !IsBackgroundFinalized(kind);
312 constexpr bool IsCompactingKind(AllocKind kind) {
313 MOZ_ASSERT(IsValidAllocKind(kind));
315 constexpr bool map[] = {
316 #define DEFINE_COMPACTING_KIND(_1, _2, _3, _4, _5, _6, compact) compact,
317 FOR_EACH_ALLOCKIND(DEFINE_COMPACTING_KIND)
318 #undef DEFINE_COMPACTING_KIND
321 static_assert(std::size(map) == AllocKindCount,
322 "IsCompactingKind sanity check");
323 return map[size_t(kind)];
326 constexpr bool IsMovableKind(AllocKind kind) {
327 return IsNurseryAllocable(kind) || IsCompactingKind(kind);
330 } /* namespace gc */
331 } /* namespace js */
333 #endif /* gc_AllocKind_h */