#ifndef gc_AllocKind_h
#define gc_AllocKind_h
#include "mozilla/ArrayUtils.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/EnumeratedRange.h"
#include <stdint.h>
#include "js/TraceKind.h"
#include "js/Utility.h"
namespace js {
namespace gc {
#define FOR_EACH_OBJECT_ALLOCKIND(D) \
\
D(FUNCTION, Object, JSObject, JSFunction, true, true, true) \
D(FUNCTION_EXTENDED, Object, JSObject, FunctionExtended, true, true, true) \
D(OBJECT0, Object, JSObject, JSObject_Slots0, false, false, true) \
D(OBJECT0_BACKGROUND, Object, JSObject, JSObject_Slots0, true, true, true) \
D(OBJECT2, Object, JSObject, JSObject_Slots2, false, false, true) \
D(OBJECT2_BACKGROUND, Object, JSObject, JSObject_Slots2, true, true, true) \
D(OBJECT4, Object, JSObject, JSObject_Slots4, false, false, true) \
D(OBJECT4_BACKGROUND, Object, JSObject, JSObject_Slots4, true, true, true) \
D(OBJECT8, Object, JSObject, JSObject_Slots8, false, false, true) \
D(OBJECT8_BACKGROUND, Object, JSObject, JSObject_Slots8, true, true, true) \
D(OBJECT12, Object, JSObject, JSObject_Slots12, false, false, true) \
D(OBJECT12_BACKGROUND, Object, JSObject, JSObject_Slots12, true, true, true) \
D(OBJECT16, Object, JSObject, JSObject_Slots16, false, false, true) \
D(OBJECT16_BACKGROUND, Object, JSObject, JSObject_Slots16, true, true, true)
#define FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(D) \
\
D(SCRIPT, Script, JSScript, JSScript, false, false, true) \
D(LAZY_SCRIPT, LazyScript, js::LazyScript, js::LazyScript, true, false, true) \
D(SHAPE, Shape, js::Shape, js::Shape, true, false, true) \
D(ACCESSOR_SHAPE, Shape, js::AccessorShape, js::AccessorShape, true, false, true) \
D(BASE_SHAPE, BaseShape, js::BaseShape, js::BaseShape, true, false, true) \
D(OBJECT_GROUP, ObjectGroup, js::ObjectGroup, js::ObjectGroup, true, false, false) \
D(EXTERNAL_STRING, String, JSExternalString, JSExternalString, true, false, true) \
D(FAT_INLINE_ATOM, String, js::FatInlineAtom, js::FatInlineAtom, true, false, true) \
D(ATOM, String, js::NormalAtom, js::NormalAtom, true, false, true) \
D(SYMBOL, Symbol, JS::Symbol, JS::Symbol, true, false, false) \
D(BIGINT, BigInt, JS::BigInt, JS::BigInt, true, false, true) \
D(JITCODE, JitCode, js::jit::JitCode, js::jit::JitCode, false, false, false) \
D(SCOPE, Scope, js::Scope, js::Scope, true, false, true) \
D(REGEXP_SHARED, RegExpShared, js::RegExpShared, js::RegExpShared, true, false, true)
#define FOR_EACH_NURSERY_STRING_ALLOCKIND(D) \
D(FAT_INLINE_STRING, String, JSFatInlineString, JSFatInlineString, true, true, true) \
D(STRING, String, JSString, JSString, true, true, true)
#define FOR_EACH_NONOBJECT_ALLOCKIND(D) \
FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(D) \
FOR_EACH_NURSERY_STRING_ALLOCKIND(D)
#define FOR_EACH_ALLOCKIND(D) \
FOR_EACH_OBJECT_ALLOCKIND(D) \
FOR_EACH_NONOBJECT_ALLOCKIND(D)
#define DEFINE_ALLOC_KIND(allocKind, _1, _2, _3, _4, _5, _6) allocKind,
enum class AllocKind : uint8_t {
FOR_EACH_OBJECT_ALLOCKIND(DEFINE_ALLOC_KIND)
OBJECT_LIMIT,
OBJECT_LAST = OBJECT_LIMIT - 1,
FOR_EACH_NONOBJECT_ALLOCKIND(DEFINE_ALLOC_KIND)
LIMIT,
LAST = LIMIT - 1,
FIRST = 0,
OBJECT_FIRST = FUNCTION };
#undef DEFINE_ALLOC_KIND
static_assert(int(AllocKind::FIRST) == 0,
"Various places depend on AllocKind starting at 0");
static_assert(int(AllocKind::OBJECT_FIRST) == 0,
"OBJECT_FIRST must be defined as the first object kind");
inline bool IsAllocKind(AllocKind kind) {
return kind >= AllocKind::FIRST && kind <= AllocKind::LIMIT;
}
inline bool IsValidAllocKind(AllocKind kind) {
return kind >= AllocKind::FIRST && kind <= AllocKind::LAST;
}
const char* AllocKindName(AllocKind kind);
inline bool IsObjectAllocKind(AllocKind kind) {
return kind >= AllocKind::OBJECT_FIRST && kind <= AllocKind::OBJECT_LAST;
}
inline bool IsShapeAllocKind(AllocKind kind) {
return kind == AllocKind::SHAPE || kind == AllocKind::ACCESSOR_SHAPE;
}
inline auto AllAllocKinds() {
return mozilla::MakeEnumeratedRange(AllocKind::FIRST, AllocKind::LIMIT);
}
inline auto ObjectAllocKinds() {
return mozilla::MakeEnumeratedRange(AllocKind::OBJECT_FIRST,
AllocKind::OBJECT_LIMIT);
}
inline auto SomeAllocKinds(AllocKind first = AllocKind::FIRST,
AllocKind limit = AllocKind::LIMIT) {
MOZ_ASSERT(IsAllocKind(first), "|first| is not a valid AllocKind!");
MOZ_ASSERT(IsAllocKind(limit), "|limit| is not a valid AllocKind!");
return mozilla::MakeEnumeratedRange(first, limit);
}
template <typename ValueType>
using AllAllocKindArray =
mozilla::EnumeratedArray<AllocKind, AllocKind::LIMIT, ValueType>;
template <typename ValueType>
using ObjectAllocKindArray =
mozilla::EnumeratedArray<AllocKind, AllocKind::OBJECT_LIMIT, ValueType>;
static inline JS::TraceKind MapAllocToTraceKind(AllocKind kind) {
static const JS::TraceKind map[] = {
#define EXPAND_ELEMENT(allocKind, traceKind, type, sizedType, bgFinal, \
nursery, compact) \
JS::TraceKind::traceKind,
FOR_EACH_ALLOCKIND(EXPAND_ELEMENT)
#undef EXPAND_ELEMENT
};
static_assert(mozilla::ArrayLength(map) == size_t(AllocKind::LIMIT),
"AllocKind-to-TraceKind mapping must be in sync");
return map[size_t(kind)];
}
static const size_t MAX_BACKGROUND_FINALIZE_KINDS =
size_t(AllocKind::LIMIT) - size_t(AllocKind::OBJECT_LIMIT) / 2;
static inline bool IsNurseryAllocable(AllocKind kind) {
MOZ_ASSERT(IsValidAllocKind(kind));
static const bool map[] = {
#define DEFINE_NURSERY_ALLOCABLE(_1, _2, _3, _4, _5, nursery, _6) nursery,
FOR_EACH_ALLOCKIND(DEFINE_NURSERY_ALLOCABLE)
#undef DEFINE_NURSERY_ALLOCABLE
};
static_assert(mozilla::ArrayLength(map) == size_t(AllocKind::LIMIT),
"IsNurseryAllocable sanity check");
return map[size_t(kind)];
}
static inline bool IsBackgroundFinalized(AllocKind kind) {
MOZ_ASSERT(IsValidAllocKind(kind));
static const bool map[] = {
#define DEFINE_BACKGROUND_FINALIZED(_1, _2, _3, _4, bgFinal, _5, _6) bgFinal,
FOR_EACH_ALLOCKIND(DEFINE_BACKGROUND_FINALIZED)
#undef DEFINE_BG_FINALIZE
};
static_assert(mozilla::ArrayLength(map) == size_t(AllocKind::LIMIT),
"IsBackgroundFinalized sanity check");
return map[size_t(kind)];
}
static inline bool IsCompactingKind(AllocKind kind) {
MOZ_ASSERT(IsValidAllocKind(kind));
static const bool map[] = {
#define DEFINE_COMPACTING_KIND(_1, _2, _3, _4, _5, _6, compact) compact,
FOR_EACH_ALLOCKIND(DEFINE_COMPACTING_KIND)
#undef DEFINE_COMPACTING_KIND
};
static_assert(mozilla::ArrayLength(map) == size_t(AllocKind::LIMIT),
"IsCompactingKind sanity check");
return map[size_t(kind)];
}
static inline bool IsMovableKind(AllocKind kind) {
return IsNurseryAllocable(kind) || IsCompactingKind(kind);
}
}
}
#endif