Line data Source code
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_GCVector_h
8 : #define js_GCVector_h
9 :
10 : #include "mozilla/Vector.h"
11 :
12 : #include "js/GCPolicyAPI.h"
13 : #include "js/RootingAPI.h"
14 : #include "js/TracingAPI.h"
15 : #include "js/Vector.h"
16 :
17 : namespace JS {
18 :
19 : // A GCVector is a Vector with an additional trace method that knows how
20 : // to visit all of the items stored in the Vector. For vectors that contain GC
21 : // things, this is usually more convenient than manually iterating and marking
22 : // the contents.
23 : //
24 : // Most types of GC pointers as keys and values can be traced with no extra
25 : // infrastructure. For structs and non-gc-pointer members, ensure that there is
26 : // a specialization of GCPolicy<T> with an appropriate trace method available
27 : // to handle the custom type. Generic helpers can be found in
28 : // js/public/TracingAPI.h.
29 : //
30 : // Note that although this Vector's trace will deal correctly with moved items,
31 : // it does not itself know when to barrier or trace items. To function properly
32 : // it must either be used with Rooted, or barriered and traced manually.
33 : template <typename T,
34 : size_t MinInlineCapacity = 0,
35 : typename AllocPolicy = js::TempAllocPolicy>
36 133906 : class GCVector
37 : {
38 : mozilla::Vector<T, MinInlineCapacity, AllocPolicy> vector;
39 :
40 : public:
41 67015 : explicit GCVector(AllocPolicy alloc = AllocPolicy())
42 67015 : : vector(alloc)
43 67015 : {}
44 :
45 66943 : GCVector(GCVector&& vec)
46 66943 : : vector(mozilla::Move(vec.vector))
47 66943 : {}
48 :
49 8 : GCVector& operator=(GCVector&& vec) {
50 8 : vector = mozilla::Move(vec.vector);
51 8 : return *this;
52 : }
53 :
54 124492 : size_t length() const { return vector.length(); }
55 1346 : bool empty() const { return vector.empty(); }
56 32 : size_t capacity() const { return vector.capacity(); }
57 :
58 29958 : T* begin() { return vector.begin(); }
59 704 : const T* begin() const { return vector.begin(); }
60 :
61 10784 : T* end() { return vector.end(); }
62 19 : const T* end() const { return vector.end(); }
63 :
64 146377 : T& operator[](size_t i) { return vector[i]; }
65 37163 : const T& operator[](size_t i) const { return vector[i]; }
66 :
67 4263 : T& back() { return vector.back(); }
68 : const T& back() const { return vector.back(); }
69 :
70 : bool initCapacity(size_t cap) { return vector.initCapacity(cap); }
71 1823 : MOZ_MUST_USE bool reserve(size_t req) { return vector.reserve(req); }
72 : void shrinkBy(size_t amount) { return vector.shrinkBy(amount); }
73 0 : MOZ_MUST_USE bool growBy(size_t amount) { return vector.growBy(amount); }
74 8608 : MOZ_MUST_USE bool resize(size_t newLen) { return vector.resize(newLen); }
75 :
76 72 : void clear() { return vector.clear(); }
77 2404 : void clearAndFree() { return vector.clearAndFree(); }
78 :
79 61493 : template<typename U> bool append(U&& item) { return vector.append(mozilla::Forward<U>(item)); }
80 :
81 : template<typename... Args>
82 : MOZ_MUST_USE bool
83 0 : emplaceBack(Args&&... args) {
84 0 : return vector.emplaceBack(mozilla::Forward<Args>(args)...);
85 : }
86 :
87 : template<typename U>
88 10140 : void infallibleAppend(U&& aU) {
89 10140 : return vector.infallibleAppend(mozilla::Forward<U>(aU));
90 : }
91 : void infallibleAppendN(const T& aT, size_t aN) {
92 : return vector.infallibleAppendN(aT, aN);
93 : }
94 : template<typename U> void
95 : infallibleAppend(const U* aBegin, const U* aEnd) {
96 : return vector.infallibleAppend(aBegin, aEnd);
97 : }
98 : template<typename U> void infallibleAppend(const U* aBegin, size_t aLength) {
99 : return vector.infallibleAppend(aBegin, aLength);
100 : }
101 :
102 : template<typename U, size_t O, class BP>
103 : MOZ_MUST_USE bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vector.appendAll(aU); }
104 : template<typename U, size_t O, class BP>
105 0 : MOZ_MUST_USE bool appendAll(const GCVector<U, O, BP>& aU) {
106 0 : return vector.append(aU.begin(), aU.length());
107 : }
108 :
109 7942 : MOZ_MUST_USE bool appendN(const T& val, size_t count) { return vector.appendN(val, count); }
110 :
111 : template<typename U>
112 19 : MOZ_MUST_USE bool append(const U* aBegin, const U* aEnd) {
113 19 : return vector.append(aBegin, aEnd);
114 : }
115 : template<typename U>
116 0 : MOZ_MUST_USE bool append(const U* aBegin, size_t aLength) {
117 0 : return vector.append(aBegin, aLength);
118 : }
119 :
120 860 : void popBack() { return vector.popBack(); }
121 0 : T popCopy() { return vector.popCopy(); }
122 :
123 0 : size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
124 0 : return vector.sizeOfExcludingThis(mallocSizeOf);
125 : }
126 :
127 : size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
128 : return vector.sizeOfIncludingThis(mallocSizeOf);
129 : }
130 :
131 : static void trace(GCVector* vec, JSTracer* trc) { vec->trace(trc); }
132 :
133 182 : void trace(JSTracer* trc) {
134 503 : for (auto& elem : vector)
135 321 : GCPolicy<T>::trace(trc, &elem, "vector element");
136 182 : }
137 :
138 : bool needsSweep() const {
139 : return !this->empty();
140 : }
141 :
142 : void sweep() {
143 : uint32_t src, dst = 0;
144 : for (src = 0; src < length(); src++) {
145 : if (!GCPolicy<T>::needsSweep(&vector[src])) {
146 : if (dst != src)
147 : vector[dst] = vector[src].unbarrieredGet();
148 : dst++;
149 : }
150 : }
151 :
152 : if (dst != length())
153 : vector.shrinkTo(dst);
154 : }
155 : };
156 :
157 : } // namespace JS
158 :
159 : namespace js {
160 :
161 : template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
162 91203 : class WrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper>
163 : {
164 : using Vec = JS::GCVector<T, Capacity, AllocPolicy>;
165 124770 : const Vec& vec() const { return static_cast<const Wrapper*>(this)->get(); }
166 :
167 : public:
168 : const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
169 122032 : size_t length() const { return vec().length(); }
170 1346 : bool empty() const { return vec().empty(); }
171 : size_t capacity() const { return vec().capacity(); }
172 0 : const T* begin() const { return vec().begin(); }
173 0 : const T* end() const { return vec().end(); }
174 : const T& back() const { return vec().back(); }
175 :
176 1392 : JS::Handle<T> operator[](size_t aIndex) const {
177 1392 : return JS::Handle<T>::fromMarkedLocation(&vec().operator[](aIndex));
178 : }
179 : };
180 :
181 : template <typename Wrapper, typename T, size_t Capacity, typename AllocPolicy>
182 88800 : class MutableWrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper>
183 : : public WrappedPtrOperations<JS::GCVector<T, Capacity, AllocPolicy>, Wrapper>
184 : {
185 : using Vec = JS::GCVector<T, Capacity, AllocPolicy>;
186 36456 : const Vec& vec() const { return static_cast<const Wrapper*>(this)->get(); }
187 272228 : Vec& vec() { return static_cast<Wrapper*>(this)->get(); }
188 :
189 : public:
190 : const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
191 : AllocPolicy& allocPolicy() { return vec().allocPolicy(); }
192 685 : const T* begin() const { return vec().begin(); }
193 27506 : T* begin() { return vec().begin(); }
194 0 : const T* end() const { return vec().end(); }
195 8332 : T* end() { return vec().end(); }
196 : const T& back() const { return vec().back(); }
197 1856 : T& back() { return vec().back(); }
198 :
199 35771 : JS::Handle<T> operator[](size_t aIndex) const {
200 35771 : return JS::Handle<T>::fromMarkedLocation(&vec().operator[](aIndex));
201 : }
202 146377 : JS::MutableHandle<T> operator[](size_t aIndex) {
203 146377 : return JS::MutableHandle<T>::fromMarkedLocation(&vec().operator[](aIndex));
204 : }
205 :
206 : MOZ_MUST_USE bool initCapacity(size_t aRequest) { return vec().initCapacity(aRequest); }
207 1759 : MOZ_MUST_USE bool reserve(size_t aRequest) { return vec().reserve(aRequest); }
208 : void shrinkBy(size_t aIncr) { vec().shrinkBy(aIncr); }
209 0 : MOZ_MUST_USE bool growBy(size_t aIncr) { return vec().growBy(aIncr); }
210 8608 : MOZ_MUST_USE bool resize(size_t aNewLength) { return vec().resize(aNewLength); }
211 : MOZ_MUST_USE bool growByUninitialized(size_t aIncr) { return vec().growByUninitialized(aIncr); }
212 : void infallibleGrowByUninitialized(size_t aIncr) { vec().infallibleGrowByUninitialized(aIncr); }
213 : MOZ_MUST_USE bool resizeUninitialized(size_t aNewLength) { return vec().resizeUninitialized(aNewLength); }
214 72 : void clear() { vec().clear(); }
215 : void clearAndFree() { vec().clearAndFree(); }
216 : template<typename U>
217 59082 : MOZ_MUST_USE bool append(U&& aU) { return vec().append(mozilla::Forward<U>(aU)); }
218 : template<typename... Args>
219 : MOZ_MUST_USE bool emplaceBack(Args&&... aArgs) {
220 : return vec().emplaceBack(mozilla::Forward<Args...>(aArgs...));
221 : }
222 : template<typename U, size_t O, class BP>
223 : MOZ_MUST_USE bool appendAll(const mozilla::Vector<U, O, BP>& aU) { return vec().appendAll(aU); }
224 : template<typename U, size_t O, class BP>
225 0 : MOZ_MUST_USE bool appendAll(const JS::GCVector<U, O, BP>& aU) { return vec().appendAll(aU); }
226 7943 : MOZ_MUST_USE bool appendN(const T& aT, size_t aN) { return vec().appendN(aT, aN); }
227 : template<typename U>
228 19 : MOZ_MUST_USE bool append(const U* aBegin, const U* aEnd) {
229 19 : return vec().append(aBegin, aEnd);
230 : }
231 : template<typename U>
232 0 : MOZ_MUST_USE bool append(const U* aBegin, size_t aLength) {
233 0 : return vec().append(aBegin, aLength);
234 : }
235 9786 : template<typename U> void infallibleAppend(U&& aU) {
236 9786 : vec().infallibleAppend(mozilla::Forward<U>(aU));
237 9786 : }
238 : void infallibleAppendN(const T& aT, size_t aN) { vec().infallibleAppendN(aT, aN); }
239 : template<typename U> void infallibleAppend(const U* aBegin, const U* aEnd) {
240 : vec().infallibleAppend(aBegin, aEnd);
241 : }
242 : template<typename U> void infallibleAppend(const U* aBegin, size_t aLength) {
243 : vec().infallibleAppend(aBegin, aLength);
244 : }
245 857 : void popBack() { vec().popBack(); }
246 0 : T popCopy() { return vec().popCopy(); }
247 : template<typename U> T* insert(T* aP, U&& aVal) {
248 : return vec().insert(aP, mozilla::Forward<U>(aVal));
249 : }
250 : void erase(T* aT) { vec().erase(aT); }
251 : void erase(T* aBegin, T* aEnd) { vec().erase(aBegin, aEnd); }
252 : };
253 :
254 : } // namespace js
255 :
256 : #endif // js_GCVector_h
|