GCArray.h (3284B)
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 #ifndef js_GCArray_h 8 #define js_GCArray_h 9 10 #include "mozilla/Assertions.h" 11 12 #include "gc/Barrier.h" 13 #include "gc/Tracer.h" 14 #include "js/Value.h" 15 16 namespace js { 17 18 /* 19 * A fixed size array of |T| for use with GC things. 20 * 21 * Must be allocated manually to allow space for the trailing elements 22 * data. Call bytesRequired to get the required allocation size. 23 * 24 * Does not provide any barriers by default. 25 */ 26 template <typename T> 27 class GCArray { 28 const uint32_t size_; 29 T elements_[1]; 30 31 public: 32 explicit GCArray(uint32_t size) : size_(size) { 33 // The array contents following the first element are not initialized. 34 } 35 36 uint32_t size() const { return size_; } 37 38 const T& operator[](uint32_t i) const { 39 MOZ_ASSERT(i < size_); 40 return elements_[i]; 41 } 42 T& operator[](uint32_t i) { 43 MOZ_ASSERT(i < size_); 44 return elements_[i]; 45 } 46 47 const T* begin() const { return elements_; } 48 T* begin() { return elements_; } 49 const T* end() const { return elements_ + size_; } 50 T* end() { return elements_ + size_; } 51 52 void trace(JSTracer* trc) { 53 TraceRange(trc, size(), begin(), "array element"); 54 } 55 56 static constexpr ptrdiff_t offsetOfElements() { 57 return offsetof(GCArray, elements_); 58 } 59 60 static size_t bytesRequired(size_t size) { 61 return offsetOfElements() + std::max(size, size_t(1)) * sizeof(T); 62 } 63 }; 64 65 /* 66 * A fixed size array of GC things owned by a GC thing. 67 * 68 * Uses the appropriate barriers depending on whether the owner is in the 69 * nursery or the tenured heap. If the owner cannot be allocated in the nursery 70 * then this class is not required. 71 */ 72 template <typename T> 73 class GCOwnedArray { 74 using StorageType = GCArray<PreAndPostBarrierWrapper<T>>; 75 using TenuredInterface = StorageType; 76 using NurseryInterface = GCArray<PreBarrierWrapper<T>>; 77 78 StorageType array; 79 80 public: 81 explicit GCOwnedArray(uint32_t size) : array(size) {} 82 83 uint32_t size() const { return array.size(); } 84 const T& operator[](uint32_t i) const { return array[i].get(); } 85 86 // Apply |f| to a view of the data with appropriate barriers given |owner|. 87 template <typename F> 88 void withOwner(gc::Cell* owner, F&& f) { 89 if (gc::IsInsideNursery(owner)) { 90 f(nurseryOwned()); 91 } else { 92 f(tenuredOwned()); 93 } 94 } 95 96 // For convenience, special case setElement. 97 void setElement(gc::Cell* owner, uint32_t i, const T& newValue) { 98 withOwner(owner, [&](auto& self) { self[i] = newValue; }); 99 } 100 101 void trace(JSTracer* trc) { array.trace(trc); } 102 103 static constexpr ptrdiff_t offsetOfElements() { 104 return offsetof(GCOwnedArray, array) + StorageType::offsetOfElements(); 105 } 106 107 static size_t bytesRequired(size_t size) { 108 return offsetof(GCOwnedArray, array) + StorageType::bytesRequired(size); 109 } 110 111 private: 112 TenuredInterface& tenuredOwned() { return array; } 113 NurseryInterface& nurseryOwned() { 114 return reinterpret_cast<NurseryInterface&>(array); 115 } 116 }; 117 118 } // namespace js 119 120 #endif // js_GCArray_h