1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * vim: set ts=8 sts=4 et sw=4 tw=99: 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_TraceableFifo_h 8 #define js_TraceableFifo_h 9 10 #include "ds/Fifo.h" 11 #include "js/RootingAPI.h" 12 #include "js/TracingAPI.h" 13 14 namespace js { 15 16 // A TraceableFifo is a Fifo with an additional trace method that knows how to 17 // visit all of the items stored in the Fifo. For Fifos that contain GC things, 18 // this is usually more convenient than manually iterating and marking the 19 // contents. 20 // 21 // Most types of GC pointers as keys and values can be traced with no extra 22 // infrastructure. For structs and non-gc-pointer members, ensure that there is 23 // a specialization of GCPolicy<T> with an appropriate trace method available 24 // to handle the custom type. Generic helpers can be found in 25 // js/public/TracingAPI.h. Generic helpers can be found in 26 // js/public/TracingAPI.h. 27 // 28 // Note that although this Fifo's trace will deal correctly with moved items, it 29 // does not itself know when to barrier or trace items. To function properly it 30 // must either be used with Rooted, or barriered and traced manually. 31 template <typename T, 32 size_t MinInlineCapacity = 0, 33 typename AllocPolicy = TempAllocPolicy> 34 class TraceableFifo : public js::Fifo<T, MinInlineCapacity, AllocPolicy> 35 { 36 using Base = js::Fifo<T, MinInlineCapacity, AllocPolicy>; 37 38 public: Base(alloc)39 explicit TraceableFifo(AllocPolicy alloc = AllocPolicy()) : Base(alloc) {} 40 TraceableFifo(TraceableFifo && rhs)41 TraceableFifo(TraceableFifo&& rhs) : Base(mozilla::Move(rhs)) { } 42 TraceableFifo& operator=(TraceableFifo&& rhs) { return Base::operator=(mozilla::Move(rhs)); } 43 44 TraceableFifo(const TraceableFifo&) = delete; 45 TraceableFifo& operator=(const TraceableFifo&) = delete; 46 trace(JSTracer * trc)47 void trace(JSTracer* trc) { 48 for (size_t i = 0; i < this->front_.length(); ++i) 49 JS::GCPolicy<T>::trace(trc, &this->front_[i], "fifo element"); 50 for (size_t i = 0; i < this->rear_.length(); ++i) 51 JS::GCPolicy<T>::trace(trc, &this->rear_[i], "fifo element"); 52 } 53 }; 54 55 template <typename Outer, typename T, size_t Capacity, typename AllocPolicy> 56 class TraceableFifoOperations 57 { 58 using TF = TraceableFifo<T, Capacity, AllocPolicy>; fifo()59 const TF& fifo() const { return static_cast<const Outer*>(this)->extract(); } 60 61 public: length()62 size_t length() const { return fifo().length(); } empty()63 bool empty() const { return fifo().empty(); } front()64 const T& front() const { return fifo().front(); } 65 }; 66 67 template <typename Outer, typename T, size_t Capacity, typename AllocPolicy> 68 class MutableTraceableFifoOperations 69 : public TraceableFifoOperations<Outer, T, Capacity, AllocPolicy> 70 { 71 using TF = TraceableFifo<T, Capacity, AllocPolicy>; fifo()72 TF& fifo() { return static_cast<Outer*>(this)->extract(); } 73 74 public: front()75 T& front() { return fifo().front(); } 76 pushBack(U && u)77 template<typename U> bool pushBack(U&& u) { return fifo().pushBack(mozilla::Forward<U>(u)); } emplaceBack(Args &&...args)78 template<typename... Args> bool emplaceBack(Args&&... args) { 79 return fifo().emplaceBack(mozilla::Forward<Args...>(args...)); 80 } 81 popFront()82 bool popFront() { return fifo().popFront(); } clear()83 void clear() { fifo().clear(); } 84 }; 85 86 template <typename A, size_t B, typename C> 87 class RootedBase<TraceableFifo<A,B,C>> 88 : public MutableTraceableFifoOperations<JS::Rooted<TraceableFifo<A,B,C>>, A,B,C> 89 { 90 using TF = TraceableFifo<A,B,C>; 91 92 friend class TraceableFifoOperations<JS::Rooted<TF>, A,B,C>; extract()93 const TF& extract() const { return *static_cast<const JS::Rooted<TF>*>(this)->address(); } 94 95 friend class MutableTraceableFifoOperations<JS::Rooted<TF>, A,B,C>; extract()96 TF& extract() { return *static_cast<JS::Rooted<TF>*>(this)->address(); } 97 }; 98 99 template <typename A, size_t B, typename C> 100 class MutableHandleBase<TraceableFifo<A,B,C>> 101 : public MutableTraceableFifoOperations<JS::MutableHandle<TraceableFifo<A,B,C>>, A,B,C> 102 { 103 using TF = TraceableFifo<A,B,C>; 104 105 friend class TraceableFifoOperations<JS::MutableHandle<TF>, A,B,C>; extract()106 const TF& extract() const { 107 return *static_cast<const JS::MutableHandle<TF>*>(this)->address(); 108 } 109 110 friend class MutableTraceableFifoOperations<JS::MutableHandle<TF>, A,B,C>; extract()111 TF& extract() { return *static_cast<JS::MutableHandle<TF>*>(this)->address(); } 112 }; 113 114 template <typename A, size_t B, typename C> 115 class HandleBase<TraceableFifo<A,B,C>> 116 : public TraceableFifoOperations<JS::Handle<TraceableFifo<A,B,C>>, A,B,C> 117 { 118 using TF = TraceableFifo<A,B,C>; 119 120 friend class TraceableFifoOperations<JS::Handle<TF>, A,B,C>; extract()121 const TF& extract() const { 122 return *static_cast<const JS::Handle<TF>*>(this)->address(); 123 } 124 }; 125 126 } // namespace js 127 128 #endif // js_TraceableFifo_h 129