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