tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

AllocKind.h (15337B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      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 /*
      8 * GC-internal definition of GC cell kinds.
      9 */
     10 
     11 #ifndef gc_AllocKind_h
     12 #define gc_AllocKind_h
     13 
     14 #include "mozilla/EnumeratedArray.h"
     15 #include "mozilla/EnumeratedRange.h"
     16 
     17 #include <stdint.h>
     18 
     19 #include "js/TraceKind.h"
     20 
     21 class JSDependentString;
     22 class JSExternalString;
     23 class JSFatInlineString;
     24 class JSLinearString;
     25 class JSRope;
     26 class JSThinInlineString;
     27 
     28 namespace js {
     29 
     30 class CompactPropMap;
     31 class FatInlineAtom;
     32 class ThinInlineAtom;
     33 class NormalAtom;
     34 class NormalPropMap;
     35 class DictionaryPropMap;
     36 class DictionaryShape;
     37 class SharedShape;
     38 class ProxyShape;
     39 class WasmGCShape;
     40 
     41 namespace gc {
     42 
     43 // The GC allocation kinds.
     44 //
     45 // These are defined by macros which enumerate the different allocation kinds
     46 // and supply the following information:
     47 //
     48 //  - the corresponding AllocKind
     49 //  - their JS::TraceKind
     50 //  - their C++ base type
     51 //  - a C++ type of the correct size
     52 //  - their FinalizeKind (see above)
     53 //  - whether they can be allocated in the nursery (this is true for foreground
     54 //    finalized objects but these will can only actually be allocated in the
     55 //    nursery if JSCLASS_SKIP_NURSERY_FINALIZE is set)
     56 //  - whether they can be compacted
     57 
     58 // clang-format off
     59 #define FOR_EACH_OBJECT_ALLOCKIND(D) \
     60 /* AllocKind              TraceKind     TypeName               SizedType              Finalize    Nursery Compact */ \
     61    D(FUNCTION,            Object,       JSObject,              JSObject_Slots4,       None,       true,   true) \
     62    D(FUNCTION_EXTENDED,   Object,       JSObject,              JSObject_Slots7,       None,       true,   true) \
     63    D(OBJECT0,             Object,       JSObject,              JSObject_Slots0,       None,       true,   true) \
     64    D(OBJECT0_FOREGROUND,  Object,       JSObject,              JSObject_Slots0,       Foreground, true,   true) \
     65    D(OBJECT0_BACKGROUND,  Object,       JSObject,              JSObject_Slots0,       Background, true,   true) \
     66    D(OBJECT2,             Object,       JSObject,              JSObject_Slots2,       None,       true,   true) \
     67    D(OBJECT2_FOREGROUND,  Object,       JSObject,              JSObject_Slots2,       Foreground, true,   true) \
     68    D(OBJECT2_BACKGROUND,  Object,       JSObject,              JSObject_Slots2,       Background, true,   true) \
     69    D(ARRAYBUFFER4,        Object,       JSObject,              JSObject_Slots4,       Background, true,   true) \
     70    D(OBJECT4,             Object,       JSObject,              JSObject_Slots4,       None,       true,   true) \
     71    D(OBJECT4_FOREGROUND,  Object,       JSObject,              JSObject_Slots4,       Foreground, true,   true) \
     72    D(OBJECT4_BACKGROUND,  Object,       JSObject,              JSObject_Slots4,       Background, true,   true) \
     73    D(ARRAYBUFFER6,        Object,       JSObject,              JSObject_Slots6,       Background, true,   true) \
     74    D(OBJECT6,             Object,       JSObject,              JSObject_Slots6,       None,       true,   true) \
     75    D(OBJECT6_FOREGROUND,  Object,       JSObject,              JSObject_Slots6,       Foreground, true,   true) \
     76    D(OBJECT6_BACKGROUND,  Object,       JSObject,              JSObject_Slots6,       Background, true,   true) \
     77    D(ARRAYBUFFER8,        Object,       JSObject,              JSObject_Slots8,       Background, true,   true) \
     78    D(OBJECT8,             Object,       JSObject,              JSObject_Slots8,       None,       true,   true) \
     79    D(OBJECT8_FOREGROUND,  Object,       JSObject,              JSObject_Slots8,       Foreground, true,   true) \
     80    D(OBJECT8_BACKGROUND,  Object,       JSObject,              JSObject_Slots8,       Background, true,   true) \
     81    D(ARRAYBUFFER12,       Object,       JSObject,              JSObject_Slots12,      Background, true,   true) \
     82    D(OBJECT12,            Object,       JSObject,              JSObject_Slots12,      None,       true,   true) \
     83    D(OBJECT12_FOREGROUND, Object,       JSObject,              JSObject_Slots12,      Foreground, true,   true) \
     84    D(OBJECT12_BACKGROUND, Object,       JSObject,              JSObject_Slots12,      Background, true,   true) \
     85    D(ARRAYBUFFER16,       Object,       JSObject,              JSObject_Slots16,      Background, true,   true) \
     86    D(OBJECT16,            Object,       JSObject,              JSObject_Slots16,      None,       true,   true) \
     87    D(OBJECT16_FOREGROUND, Object,       JSObject,              JSObject_Slots16,      Foreground, true,   true) \
     88    D(OBJECT16_BACKGROUND, Object,       JSObject,              JSObject_Slots16,      Background, true,   true)
     89 
     90 #define FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(D) \
     91 /* AllocKind              TraceKind     TypeName               SizedType              Finalize    Nursery Compact */ \
     92    D(SCRIPT,              Script,       js::BaseScript,        js::BaseScript,        Foreground, false,  true) \
     93    D(SHAPE,               Shape,        js::Shape,             js::SizedShape,        Background, false,  true) \
     94    D(BASE_SHAPE,          BaseShape,    js::BaseShape,         js::BaseShape,         None,       false,  true) \
     95    D(GETTER_SETTER,       GetterSetter, js::GetterSetter,      js::GetterSetter,      None,       true,   true) \
     96    D(COMPACT_PROP_MAP,    PropMap,      js::CompactPropMap,    js::CompactPropMap,    Background, false,  true) \
     97    D(NORMAL_PROP_MAP,     PropMap,      js::NormalPropMap,     js::NormalPropMap,     Background, false,  true) \
     98    D(DICT_PROP_MAP,       PropMap,      js::DictionaryPropMap, js::DictionaryPropMap, Background, false,  true) \
     99    D(EXTERNAL_STRING,     String,       JSExternalString,      JSExternalString,      Background, false,  true) \
    100    D(FAT_INLINE_ATOM,     String,       js::FatInlineAtom,     js::FatInlineAtom,     None,       false,  false) \
    101    D(ATOM,                String,       js::NormalAtom,        js::NormalAtom,        Background, false,  false) \
    102    D(SYMBOL,              Symbol,       JS::Symbol,            JS::Symbol,            None,       false,  false) \
    103    D(JITCODE,             JitCode,      js::jit::JitCode,      js::jit::JitCode,      Foreground, false,  false) \
    104    D(SCOPE,               Scope,        js::Scope,             js::Scope,             None,       false,  true) \
    105    D(REGEXP_SHARED,       RegExpShared, js::RegExpShared,      js::RegExpShared,      Background, false,  true)
    106 
    107 #define FOR_EACH_NONOBJECT_NURSERY_ALLOCKIND(D) \
    108 /* AllocKind              TraceKind     TypeName               SizedType              Finalize    Nursery Compact */ \
    109    D(BIGINT,              BigInt,       JS::BigInt,            JS::BigInt,            None,       true,   true)
    110 
    111 #define FOR_EACH_NURSERY_STRING_ALLOCKIND(D) \
    112 /* AllocKind              TraceKind     TypeName               SizedType              Finalize    Nursery Compact */ \
    113    D(FAT_INLINE_STRING,   String,       JSFatInlineString,     JSFatInlineString,     None,       true,   true) \
    114    D(STRING,              String,       JSString,              JSString,              Background, true,   true)
    115 
    116 #define FOR_EACH_NONOBJECT_NONBUFFER_ALLOCKIND(D) \
    117  FOR_EACH_NONOBJECT_NONNURSERY_ALLOCKIND(D)      \
    118  FOR_EACH_NONOBJECT_NURSERY_ALLOCKIND(D)         \
    119  FOR_EACH_NURSERY_STRING_ALLOCKIND(D)
    120 
    121 #define FOR_EACH_ALLOCKIND(D)  \
    122  FOR_EACH_OBJECT_ALLOCKIND(D) \
    123  FOR_EACH_NONOBJECT_NONBUFFER_ALLOCKIND(D)
    124 
    125 #define DEFINE_ALLOC_KIND(allocKind, _1, _2, _3, _4, _5, _6) allocKind,
    126 enum class AllocKind : uint8_t {
    127  // clang-format off
    128    FOR_EACH_OBJECT_ALLOCKIND(DEFINE_ALLOC_KIND)
    129 
    130    OBJECT_LIMIT,
    131    OBJECT_LAST = OBJECT_LIMIT - 1,
    132 
    133    FOR_EACH_NONOBJECT_NONBUFFER_ALLOCKIND(DEFINE_ALLOC_KIND)
    134 
    135    LIMIT,
    136    LAST = LIMIT - 1,
    137 
    138    INVALID = LIMIT,
    139 
    140    FIRST = 0,
    141    OBJECT_FIRST = FUNCTION, // Hardcoded to first object kind.
    142  // clang-format on
    143 };
    144 #undef DEFINE_ALLOC_KIND
    145 
    146 static_assert(int(AllocKind::FIRST) == 0,
    147              "Various places depend on AllocKind starting at 0");
    148 static_assert(int(AllocKind::OBJECT_FIRST) == 0,
    149              "OBJECT_FIRST must be defined as the first object kind");
    150 
    151 constexpr size_t AllocKindCount = size_t(AllocKind::LIMIT);
    152 
    153 /*
    154 * A flag specifying either the tenured heap or a default heap (which may be
    155 * either the nursery or the tenured heap).
    156 *
    157 * This allows an allocation site to request a heap based upon the estimated
    158 * lifetime or lifetime requirements of objects allocated from that site.
    159 *
    160 * Order is important as these are numerically compared.
    161 */
    162 enum class Heap : uint8_t { Default = 0, Tenured = 1 };
    163 
    164 enum class FinalizeKind {
    165  // Cells are not finalized. Arenas containing these cells are swept on a
    166  // background thread.
    167  None = 0,
    168 
    169  // Requires foreground finalization. May have client-supplied finalizer.
    170  Foreground,
    171 
    172  // Does not require foreground finalization but is non-trivial. May have
    173  // client-supplied finalizer. Finalized on a background thread.
    174  Background
    175 };
    176 
    177 constexpr bool IsAllocKind(AllocKind kind) {
    178  return kind >= AllocKind::FIRST && kind <= AllocKind::LIMIT;
    179 }
    180 
    181 constexpr bool IsValidAllocKind(AllocKind kind) {
    182  return kind >= AllocKind::FIRST && kind <= AllocKind::LAST;
    183 }
    184 
    185 const char* AllocKindName(AllocKind kind);
    186 
    187 constexpr bool IsObjectAllocKind(AllocKind kind) {
    188  return kind >= AllocKind::OBJECT_FIRST && kind <= AllocKind::OBJECT_LAST;
    189 }
    190 
    191 constexpr bool IsShapeAllocKind(AllocKind kind) {
    192  return kind == AllocKind::SHAPE;
    193 }
    194 
    195 // Returns a sequence for use in a range-based for loop,
    196 // to iterate over all alloc kinds.
    197 constexpr auto AllAllocKinds() {
    198  return mozilla::MakeEnumeratedRange(AllocKind::FIRST, AllocKind::LIMIT);
    199 }
    200 
    201 // Returns a sequence for use in a range-based for loop,
    202 // to iterate over all object alloc kinds.
    203 constexpr auto ObjectAllocKinds() {
    204  return mozilla::MakeEnumeratedRange(AllocKind::OBJECT_FIRST,
    205                                      AllocKind::OBJECT_LIMIT);
    206 }
    207 
    208 // Returns a sequence for use in a range-based for loop,
    209 // to iterate over alloc kinds from |first| to |limit|, exclusive.
    210 constexpr auto SomeAllocKinds(AllocKind first = AllocKind::FIRST,
    211                              AllocKind limit = AllocKind::LIMIT) {
    212  MOZ_ASSERT(IsAllocKind(first), "|first| is not a valid AllocKind!");
    213  MOZ_ASSERT(IsAllocKind(limit), "|limit| is not a valid AllocKind!");
    214  return mozilla::MakeEnumeratedRange(first, limit);
    215 }
    216 
    217 // AllAllocKindArray<ValueType> gives an enumerated array of ValueTypes,
    218 // with each index corresponding to a particular alloc kind.
    219 template <typename ValueType>
    220 using AllAllocKindArray =
    221    mozilla::EnumeratedArray<AllocKind, ValueType, size_t(AllocKind::LIMIT)>;
    222 
    223 // ObjectAllocKindArray<ValueType> gives an enumerated array of ValueTypes,
    224 // with each index corresponding to a particular object alloc kind.
    225 template <typename ValueType>
    226 using ObjectAllocKindArray =
    227    mozilla::EnumeratedArray<AllocKind, ValueType,
    228                             size_t(AllocKind::OBJECT_LIMIT)>;
    229 
    230 /*
    231 * Map from C++ type to alloc kind for non-object types. JSObject does not have
    232 * a 1:1 mapping, so must use Arena::thingSize.
    233 *
    234 * The AllocKind is available as MapTypeToAllocKind<SomeType>::kind.
    235 *
    236 * There are specializations for strings and shapes since more than one derived
    237 * type shares the same alloc kind.
    238 */
    239 template <typename T>
    240 struct MapTypeToAllocKind {};
    241 #define EXPAND_MAPTYPETOALLOCKIND(allocKind, _1, type, _2, _3, _4, _5) \
    242  template <>                                                          \
    243  struct MapTypeToAllocKind<type> {                                    \
    244    static const AllocKind kind = AllocKind::allocKind;                \
    245  };
    246 FOR_EACH_NONOBJECT_NONBUFFER_ALLOCKIND(EXPAND_MAPTYPETOALLOCKIND)
    247 #undef EXPAND_MAPTYPETOALLOCKIND
    248 
    249 template <>
    250 struct MapTypeToAllocKind<JSDependentString> {
    251  static const AllocKind kind = AllocKind::STRING;
    252 };
    253 template <>
    254 struct MapTypeToAllocKind<JSRope> {
    255  static const AllocKind kind = AllocKind::STRING;
    256 };
    257 template <>
    258 struct MapTypeToAllocKind<JSLinearString> {
    259  static const AllocKind kind = AllocKind::STRING;
    260 };
    261 template <>
    262 struct MapTypeToAllocKind<JSThinInlineString> {
    263  static const AllocKind kind = AllocKind::STRING;
    264 };
    265 template <>
    266 struct MapTypeToAllocKind<js::ThinInlineAtom> {
    267  static const AllocKind kind = AllocKind::ATOM;
    268 };
    269 
    270 template <>
    271 struct MapTypeToAllocKind<js::SharedShape> {
    272  static const AllocKind kind = AllocKind::SHAPE;
    273 };
    274 template <>
    275 struct MapTypeToAllocKind<js::DictionaryShape> {
    276  static const AllocKind kind = AllocKind::SHAPE;
    277 };
    278 template <>
    279 struct MapTypeToAllocKind<js::ProxyShape> {
    280  static const AllocKind kind = AllocKind::SHAPE;
    281 };
    282 template <>
    283 struct MapTypeToAllocKind<js::WasmGCShape> {
    284  static const AllocKind kind = AllocKind::SHAPE;
    285 };
    286 
    287 constexpr JS::TraceKind MapAllocToTraceKind(AllocKind kind) {
    288  constexpr JS::TraceKind map[] = {
    289 #define EXPAND_ELEMENT(_1, traceKind, _2, _3, _4, _5, _6) \
    290  JS::TraceKind::traceKind,
    291      FOR_EACH_ALLOCKIND(EXPAND_ELEMENT)
    292 #undef EXPAND_ELEMENT
    293  };
    294 
    295  static_assert(std::size(map) == AllocKindCount,
    296                "AllocKind-to-TraceKind mapping must be in sync");
    297  return map[size_t(kind)];
    298 }
    299 
    300 constexpr bool IsNurseryAllocable(AllocKind kind) {
    301  MOZ_ASSERT(IsValidAllocKind(kind));
    302 
    303  constexpr bool map[] = {
    304 #define DEFINE_NURSERY_ALLOCABLE(_1, _2, _3, _4, _5, nursery, _6) nursery,
    305      FOR_EACH_ALLOCKIND(DEFINE_NURSERY_ALLOCABLE)
    306 #undef DEFINE_NURSERY_ALLOCABLE
    307  };
    308 
    309  static_assert(std::size(map) == AllocKindCount,
    310                "IsNurseryAllocable sanity check");
    311  return map[size_t(kind)];
    312 }
    313 
    314 constexpr FinalizeKind GetFinalizeKind(AllocKind kind) {
    315  MOZ_ASSERT(IsValidAllocKind(kind));
    316 
    317  constexpr FinalizeKind map[] = {
    318 #define DEFINE_FINALIZE_KIND(_1, _2, _3, _4, finalizeKind, _5, _6) \
    319  FinalizeKind::finalizeKind,
    320      FOR_EACH_ALLOCKIND(DEFINE_FINALIZE_KIND)
    321 #undef DEFINE_FINALIZE_KIND
    322  };
    323 
    324  static_assert(std::size(map) == AllocKindCount);
    325  return map[size_t(kind)];
    326 }
    327 
    328 constexpr bool IsFinalizedKind(AllocKind kind) {
    329  return GetFinalizeKind(kind) != FinalizeKind::None;
    330 }
    331 
    332 constexpr bool IsForegroundFinalized(AllocKind kind) {
    333  return GetFinalizeKind(kind) == FinalizeKind::Foreground;
    334 }
    335 
    336 constexpr bool IsBackgroundFinalized(AllocKind kind) {
    337  return GetFinalizeKind(kind) == FinalizeKind::Background;
    338 }
    339 
    340 // Arenas containing cells of kind FinalizeKind::None and
    341 // FinalizeKind::Background are swept on a background thread.
    342 constexpr bool IsBackgroundSwept(AllocKind kind) {
    343  return !IsForegroundFinalized(kind);
    344 }
    345 
    346 constexpr bool IsCompactingKind(AllocKind kind) {
    347  MOZ_ASSERT(IsValidAllocKind(kind));
    348 
    349  constexpr bool map[] = {
    350 #define DEFINE_COMPACTING_KIND(_1, _2, _3, _4, _5, _6, compact) compact,
    351      FOR_EACH_ALLOCKIND(DEFINE_COMPACTING_KIND)
    352 #undef DEFINE_COMPACTING_KIND
    353  };
    354 
    355  static_assert(std::size(map) == AllocKindCount,
    356                "IsCompactingKind sanity check");
    357  return map[size_t(kind)];
    358 }
    359 
    360 constexpr bool IsMovableKind(AllocKind kind) {
    361  return IsNurseryAllocable(kind) || IsCompactingKind(kind);
    362 }
    363 
    364 } /* namespace gc */
    365 } /* namespace js */
    366 
    367 #endif /* gc_AllocKind_h */