tor-browser

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

ObjectKind-inl.h (6369B)


      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 helper functions for getting the AllocKind used to allocate a
      9 * JSObject and related information.
     10 */
     11 
     12 #ifndef gc_ObjectKind_inl_h
     13 #define gc_ObjectKind_inl_h
     14 
     15 #include "util/Memory.h"
     16 #include "vm/NativeObject.h"
     17 
     18 namespace js {
     19 namespace gc {
     20 
     21 inline constexpr AllocKind slotsToThingKind[] = {
     22    // clang-format off
     23    /*  0 */ AllocKind::OBJECT0,  AllocKind::OBJECT2,  AllocKind::OBJECT2,  AllocKind::OBJECT4,
     24    /*  4 */ AllocKind::OBJECT4,  AllocKind::OBJECT6,  AllocKind::OBJECT6,  AllocKind::OBJECT8,
     25    /*  8 */ AllocKind::OBJECT8,  AllocKind::OBJECT12, AllocKind::OBJECT12, AllocKind::OBJECT12,
     26    /* 12 */ AllocKind::OBJECT12, AllocKind::OBJECT16, AllocKind::OBJECT16, AllocKind::OBJECT16,
     27    /* 16 */ AllocKind::OBJECT16
     28    // clang-format on
     29 };
     30 
     31 extern const uint32_t slotsToAllocKindBytes[];
     32 
     33 static constexpr uint32_t MaxGCObjectFixedSlots = std::size(slotsToThingKind);
     34 
     35 /* Get the best kind to use when making an object with the given slot count. */
     36 static constexpr AllocKind GetGCObjectKind(size_t numSlots) {
     37  if (numSlots >= std::size(slotsToThingKind)) {
     38    return AllocKind::OBJECT16;
     39  }
     40  return slotsToThingKind[numSlots];
     41 }
     42 
     43 static inline AllocKind GetGCObjectKind(const JSClass* clasp) {
     44  MOZ_ASSERT(!clasp->isProxyObject(),
     45             "Proxies should use GetProxyGCObjectKind");
     46  MOZ_ASSERT(!clasp->isJSFunction());
     47 
     48  uint32_t nslots = JSCLASS_RESERVED_SLOTS(clasp);
     49  return GetGCObjectKind(nslots);
     50 }
     51 
     52 static constexpr bool CanUseFixedElementsForArray(size_t numElements) {
     53  if (numElements > NativeObject::MAX_DENSE_ELEMENTS_COUNT) {
     54    return false;
     55  }
     56  size_t numSlots = numElements + ObjectElements::VALUES_PER_HEADER;
     57  return numSlots < std::size(slotsToThingKind);
     58 }
     59 
     60 /* As for GetGCObjectKind, but for dense array allocation. */
     61 static constexpr AllocKind GetGCArrayKind(size_t numElements) {
     62  /*
     63   * Dense arrays can use their fixed slots to hold their elements array
     64   * (less two Values worth of ObjectElements header), but if more than the
     65   * maximum number of fixed slots is needed then the fixed slots will be
     66   * unused.
     67   */
     68  static_assert(ObjectElements::VALUES_PER_HEADER == 2);
     69  if (!CanUseFixedElementsForArray(numElements)) {
     70    return AllocKind::OBJECT2;
     71  }
     72  return slotsToThingKind[numElements + ObjectElements::VALUES_PER_HEADER];
     73 }
     74 
     75 static inline AllocKind GetGCObjectFixedSlotsKind(size_t numFixedSlots) {
     76  MOZ_ASSERT(numFixedSlots < std::size(slotsToThingKind));
     77  return slotsToThingKind[numFixedSlots];
     78 }
     79 
     80 // Get the best kind to use when allocating an object that needs a specific
     81 // number of bytes.
     82 static inline AllocKind GetGCObjectKindForBytes(size_t nbytes) {
     83  MOZ_ASSERT(nbytes <= JSObject::MAX_BYTE_SIZE);
     84 
     85  if (nbytes <= sizeof(NativeObject)) {
     86    return AllocKind::OBJECT0;
     87  }
     88  nbytes -= sizeof(NativeObject);
     89 
     90  size_t dataSlots = AlignBytes(nbytes, sizeof(Value)) / sizeof(Value);
     91  MOZ_ASSERT(nbytes <= dataSlots * sizeof(Value));
     92  return GetGCObjectKind(dataSlots);
     93 }
     94 
     95 /* Get the number of fixed slots and initial capacity associated with a kind. */
     96 static constexpr size_t GetGCKindSlots(AllocKind thingKind) {
     97  // Using a switch in hopes that thingKind will usually be a compile-time
     98  // constant.
     99  switch (thingKind) {
    100    case AllocKind::OBJECT0:
    101    case AllocKind::OBJECT0_FOREGROUND:
    102    case AllocKind::OBJECT0_BACKGROUND:
    103      return 0;
    104    case AllocKind::OBJECT2:
    105    case AllocKind::OBJECT2_FOREGROUND:
    106    case AllocKind::OBJECT2_BACKGROUND:
    107      return 2;
    108    case AllocKind::FUNCTION:
    109    case AllocKind::OBJECT4:
    110    case AllocKind::OBJECT4_FOREGROUND:
    111    case AllocKind::OBJECT4_BACKGROUND:
    112      return 4;
    113    case AllocKind::OBJECT6:
    114    case AllocKind::OBJECT6_FOREGROUND:
    115    case AllocKind::OBJECT6_BACKGROUND:
    116      return 6;
    117    case AllocKind::FUNCTION_EXTENDED:
    118      return 7;
    119    case AllocKind::OBJECT8:
    120    case AllocKind::OBJECT8_FOREGROUND:
    121    case AllocKind::OBJECT8_BACKGROUND:
    122      return 8;
    123    case AllocKind::OBJECT12:
    124    case AllocKind::OBJECT12_FOREGROUND:
    125    case AllocKind::OBJECT12_BACKGROUND:
    126      return 12;
    127    case AllocKind::OBJECT16:
    128    case AllocKind::OBJECT16_FOREGROUND:
    129    case AllocKind::OBJECT16_BACKGROUND:
    130      return 16;
    131    default:
    132      MOZ_CRASH("Bad object alloc kind");
    133  }
    134 }
    135 
    136 static inline size_t GetGCKindBytes(AllocKind thingKind) {
    137  return sizeof(JSObject_Slots0) + GetGCKindSlots(thingKind) * sizeof(Value);
    138 }
    139 
    140 static inline FinalizeKind GetObjectFinalizeKind(const JSClass* clasp) {
    141  if (!clasp->hasFinalize()) {
    142    MOZ_ASSERT((clasp->flags & JSCLASS_FOREGROUND_FINALIZE) == 0);
    143    MOZ_ASSERT((clasp->flags & JSCLASS_BACKGROUND_FINALIZE) == 0);
    144    return FinalizeKind::None;
    145  }
    146 
    147  if (clasp->flags & JSCLASS_BACKGROUND_FINALIZE) {
    148    MOZ_ASSERT((clasp->flags & JSCLASS_FOREGROUND_FINALIZE) == 0);
    149    return FinalizeKind::Background;
    150  }
    151 
    152  MOZ_ASSERT(clasp->flags & JSCLASS_FOREGROUND_FINALIZE);
    153  return FinalizeKind::Foreground;
    154 }
    155 
    156 static inline AllocKind GetFinalizedAllocKind(AllocKind kind,
    157                                              FinalizeKind finalizeKind) {
    158  MOZ_ASSERT(kind != AllocKind::FUNCTION &&
    159             kind != AllocKind::FUNCTION_EXTENDED);
    160  MOZ_ASSERT(IsObjectAllocKind(kind));
    161  MOZ_ASSERT(!IsFinalizedKind(kind));
    162 
    163  AllocKind newKind = AllocKind(size_t(kind) + size_t(finalizeKind));
    164  MOZ_ASSERT(IsObjectAllocKind(newKind));
    165  MOZ_ASSERT(GetGCKindSlots(newKind) == GetGCKindSlots(kind));
    166  MOZ_ASSERT_IF(finalizeKind == FinalizeKind::None, !IsFinalizedKind(newKind));
    167  MOZ_ASSERT_IF(finalizeKind == FinalizeKind::Foreground,
    168                IsForegroundFinalized(newKind));
    169  MOZ_ASSERT_IF(finalizeKind == FinalizeKind::Background,
    170                IsBackgroundFinalized(newKind));
    171 
    172  return newKind;
    173 }
    174 
    175 static inline AllocKind GetFinalizedAllocKindForClass(AllocKind kind,
    176                                                      const JSClass* clasp) {
    177  return GetFinalizedAllocKind(kind, GetObjectFinalizeKind(clasp));
    178 }
    179 
    180 }  // namespace gc
    181 }  // namespace js
    182 
    183 #endif  // gc_ObjectKind_inl_h