1 /*
2 * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_UTILITIES_GROWABLEARRAY_HPP
26 #define SHARE_UTILITIES_GROWABLEARRAY_HPP
27
28 #include "memory/allocation.hpp"
29 #include "memory/iterator.hpp"
30 #include "oops/array.hpp"
31 #include "oops/oop.hpp"
32 #include "utilities/debug.hpp"
33 #include "utilities/globalDefinitions.hpp"
34 #include "utilities/ostream.hpp"
35 #include "utilities/powerOfTwo.hpp"
36
37 // A growable array.
38
39 /*************************************************************************/
40 /* */
41 /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */
42 /* */
43 /* Should you use GrowableArrays to contain handles you must be certain */
44 /* that the GrowableArray does not outlive the HandleMark that contains */
45 /* the handles. Since GrowableArrays are typically resource allocated */
46 /* the following is an example of INCORRECT CODE, */
47 /* */
48 /* ResourceMark rm; */
49 /* GrowableArray<Handle>* arr = new GrowableArray<Handle>(size); */
50 /* if (blah) { */
51 /* while (...) { */
52 /* HandleMark hm; */
53 /* ... */
54 /* Handle h(THREAD, some_oop); */
55 /* arr->append(h); */
56 /* } */
57 /* } */
58 /* if (arr->length() != 0 ) { */
59 /* oop bad_oop = arr->at(0)(); // Handle is BAD HERE. */
60 /* ... */
61 /* } */
62 /* */
63 /* If the GrowableArrays you are creating is C_Heap allocated then it */
64 /* should not hold handles since the handles could trivially try and */
65 /* outlive their HandleMark. In some situations you might need to do */
66 /* this and it would be legal but be very careful and see if you can do */
67 /* the code in some other manner. */
68 /* */
69 /*************************************************************************/
70
71 // Non-template base class responsible for handling the length and max.
72
73
74 class GrowableArrayBase : public AnyObj {
75 friend class VMStructs;
76
77 protected:
78 // Current number of accessible elements
79 int _len;
80 // Current number of allocated elements
81 int _capacity;
82
83 GrowableArrayBase(int capacity, int initial_len) :
84 _len(initial_len),
85 _capacity(capacity) {
86 assert(_len >= 0 && _len <= _capacity, "initial_len too big");
87 }
88
89 ~GrowableArrayBase() {}
90
91 public:
92 int length() const { return _len; }
93 int capacity() const { return _capacity; }
94
95 bool is_empty() const { return _len == 0; }
96 bool is_nonempty() const { return _len != 0; }
97 bool is_full() const { return _len == _capacity; }
98 };
99
100 template <typename E> class GrowableArrayIterator;
101 template <typename E, typename UnaryPredicate> class GrowableArrayFilterIterator;
102
103 // Extends GrowableArrayBase with a typed data array.
104 //
105 // E: Element type
106 //
107 // The "view" adds function that don't grow or deallocate
108 // the _data array, so there's no need for an allocator.
109 //
110 // The "view" can be used to type erase the allocator classes
111 // of GrowableArrayWithAllocator.
112 template <typename E>
113 class GrowableArrayView : public GrowableArrayBase {
114 protected:
115 E* _data; // data array
116
117 GrowableArrayView(E* data, int capacity, int initial_len) :
118 GrowableArrayBase(capacity, initial_len), _data(data) {}
119
120 ~GrowableArrayView() {}
121
122 public:
123 bool operator==(const GrowableArrayView& rhs) const {
124 if (_len != rhs._len)
125 return false;
126 for (int i = 0; i < _len; i++) {
127 if (at(i) != rhs.at(i)) {
128 return false;
129 }
130 }
131 return true;
132 }
133
134 bool operator!=(const GrowableArrayView& rhs) const {
135 return !(*this == rhs);
136 }
137
138 E& at(int i) {
139 assert(0 <= i && i < _len, "illegal index %d for length %d", i, _len);
140 return _data[i];
141 }
142
143 E const& at(int i) const {
144 assert(0 <= i && i < _len, "illegal index %d for length %d", i, _len);
145 return _data[i];
146 }
147
148 E* adr_at(int i) const {
149 assert(0 <= i && i < _len, "illegal index %d for length %d", i, _len);
150 return &_data[i];
151 }
152
153 E& first() {
154 assert(_len > 0, "empty");
155 return _data[0];
156 }
157
158 E const& first() const {
159 assert(_len > 0, "empty");
160 return _data[0];
161 }
162
163 E& top() {
164 assert(_len > 0, "empty");
165 return _data[_len - 1];
166 }
167
168 E const& top() const {
169 assert(_len > 0, "empty");
170 return _data[_len - 1];
171 }
172
173 E& last() {
174 return top();
175 }
176
177 E const& last() const {
178 return top();
179 }
180
181 GrowableArrayIterator<E> begin() const {
182 return GrowableArrayIterator<E>(this, 0);
183 }
184
185 GrowableArrayIterator<E> end() const {
186 return GrowableArrayIterator<E>(this, length());
187 }
188
189 void at_put(int i, const E& elem) {
190 assert(0 <= i && i < _len, "illegal index %d for length %d", i, _len);
191 _data[i] = elem;
192 }
193
194 bool contains(const E& elem) const {
195 for (int i = 0; i < _len; i++) {
196 if (_data[i] == elem) return true;
197 }
198 return false;
199 }
200
201 int find(const E& elem) const {
202 for (int i = 0; i < _len; i++) {
203 if (_data[i] == elem) return i;
204 }
205 return -1;
206 }
207
208 int find_from_end(const E& elem) const {
209 for (int i = _len-1; i >= 0; i--) {
210 if (_data[i] == elem) return i;
211 }
212 return -1;
213 }
214
215 // Find first element that matches the given predicate.
216 //
217 // Predicate: bool predicate(const E& elem)
218 //
219 // Returns the index of the element or -1 if no element matches the predicate
220 template<typename Predicate>
221 int find_if(Predicate predicate) const {
222 for (int i = 0; i < _len; i++) {
223 if (predicate(_data[i])) return i;
224 }
225 return -1;
226 }
227
228 // Find last element that matches the given predicate.
229 //
230 // Predicate: bool predicate(const E& elem)
231 //
232 // Returns the index of the element or -1 if no element matches the predicate
233 template<typename Predicate>
234 int find_from_end_if(Predicate predicate) const {
235 // start at the end of the array
236 for (int i = _len-1; i >= 0; i--) {
237 if (predicate(_data[i])) return i;
238 }
239 return -1;
240 }
241
242 void sort(int f(E*, E*)) {
243 if (_data == nullptr) return;
244 qsort(_data, length(), sizeof(E), (_sort_Fn)f);
245 }
246 // sort by fixed-stride sub arrays:
247 void sort(int f(E*, E*), int stride) {
248 if (_data == nullptr) return;
249 qsort(_data, length() / stride, sizeof(E) * stride, (_sort_Fn)f);
250 }
251
252 template <typename K, int compare(const K&, const E&)> int find_sorted(const K& key, bool& found) const {
253 found = false;
254 int min = 0;
255 int max = length() - 1;
256
257 while (max >= min) {
258 int mid = (int)(((uint)max + min) / 2);
259 E value = at(mid);
260 int diff = compare(key, value);
261 if (diff > 0) {
262 min = mid + 1;
263 } else if (diff < 0) {
264 max = mid - 1;
265 } else {
266 found = true;
267 return mid;
268 }
269 }
270 return min;
271 }
272
273 template <typename K>
274 int find_sorted(CompareClosure<E>* cc, const K& key, bool& found) {
275 found = false;
276 int min = 0;
277 int max = length() - 1;
278
279 while (max >= min) {
280 int mid = (int)(((uint)max + min) / 2);
281 E value = at(mid);
282 int diff = cc->do_compare(key, value);
283 if (diff > 0) {
284 min = mid + 1;
285 } else if (diff < 0) {
286 max = mid - 1;
287 } else {
288 found = true;
289 return mid;
290 }
291 }
292 return min;
293 }
294
295 void print() const {
296 tty->print("Growable Array " PTR_FORMAT, p2i(this));
297 tty->print(": length %d (capacity %d) { ", _len, _capacity);
298 for (int i = 0; i < _len; i++) {
299 tty->print(INTPTR_FORMAT " ", *(intptr_t*)&(_data[i]));
300 }
301 tty->print("}\n");
302 }
303
304 // MetaspaceClosure support
305 E** data_addr() {
306 return &_data;
307 }
308 };
309
310 template <typename E>
311 class GrowableArrayFromArray : public GrowableArrayView<E> {
312 public:
313
314 GrowableArrayFromArray(E* data, int len) :
315 GrowableArrayView<E>(data, len, len) {}
316 };
317
318 // GrowableArrayWithAllocator extends the "view" with
319 // the capability to grow and deallocate the data array.
320 //
321 // The allocator responsibility is delegated to the sub-class.
322 //
323 // Derived: The sub-class responsible for allocation / deallocation
324 // - E* Derived::allocate() - member function responsible for allocation
325 // - void Derived::deallocate(E*) - member function responsible for deallocation
326 template <typename E, typename Derived>
327 class GrowableArrayWithAllocator : public GrowableArrayView<E> {
328 void expand_to(int j);
329 void grow(int j);
330
331 protected:
332 GrowableArrayWithAllocator(E* data, int capacity) :
333 GrowableArrayView<E>(data, capacity, 0) {
334 for (int i = 0; i < capacity; i++) {
335 ::new ((void*)&data[i]) E();
336 }
337 }
338
339 GrowableArrayWithAllocator(E* data, int capacity, int initial_len, const E& filler) :
340 GrowableArrayView<E>(data, capacity, initial_len) {
341 int i = 0;
342 for (; i < initial_len; i++) {
343 ::new ((void*)&data[i]) E(filler);
344 }
345 for (; i < capacity; i++) {
346 ::new ((void*)&data[i]) E();
347 }
348 }
349
350 GrowableArrayWithAllocator(E* data, int capacity, int initial_len) :
351 GrowableArrayView<E>(data, capacity, initial_len) {}
352
353 ~GrowableArrayWithAllocator() {}
354
355 public:
356 int append(const E& elem) {
357 if (this->_len == this->_capacity) grow(this->_len);
358 int idx = this->_len++;
359 this->_data[idx] = elem;
360 return idx;
361 }
362
363 bool append_if_missing(const E& elem) {
364 // Returns TRUE if elem is added.
365 bool missed = !this->contains(elem);
366 if (missed) append(elem);
367 return missed;
368 }
369
370 void push(const E& elem) { append(elem); }
371
372 E pop() {
373 assert(this->_len > 0, "empty list");
374 return this->_data[--this->_len];
375 }
376
377 E& at_grow(int i, const E& fill = E()) {
378 assert(0 <= i, "negative index %d", i);
379 if (i >= this->_len) {
380 if (i >= this->_capacity) grow(i);
381 for (int j = this->_len; j <= i; j++)
382 this->_data[j] = fill;
383 this->_len = i+1;
384 }
385 return this->_data[i];
386 }
387
388 void at_put_grow(int i, const E& elem, const E& fill = E()) {
389 assert(0 <= i, "negative index %d", i);
390 if (i >= this->_len) {
391 if (i >= this->_capacity) grow(i);
392 for (int j = this->_len; j < i; j++)
393 this->_data[j] = fill;
394 this->_len = i+1;
395 }
396 this->_data[i] = elem;
397 }
398
399 // inserts the given element before the element at index i
400 void insert_before(const int idx, const E& elem) {
401 assert(0 <= idx && idx <= this->_len, "illegal index %d for length %d", idx, this->_len);
402 if (this->_len == this->_capacity) grow(this->_len);
403 for (int j = this->_len - 1; j >= idx; j--) {
404 this->_data[j + 1] = this->_data[j];
405 }
406 this->_len++;
407 this->_data[idx] = elem;
408 }
409
410 void insert_before(const int idx, const GrowableArrayView<E>* array) {
411 assert(0 <= idx && idx <= this->_len, "illegal index %d for length %d", idx, this->_len);
412 int array_len = array->length();
413 int new_len = this->_len + array_len;
414 if (new_len >= this->_capacity) grow(new_len);
415
416 for (int j = this->_len - 1; j >= idx; j--) {
417 this->_data[j + array_len] = this->_data[j];
418 }
419
420 for (int j = 0; j < array_len; j++) {
421 this->_data[idx + j] = array->at(j);
422 }
423
424 this->_len += array_len;
425 }
426
427 void appendAll(const GrowableArrayView<E>* l) {
428 for (int i = 0; i < l->length(); i++) {
429 this->at_put_grow(this->_len, l->at(i), E());
430 }
431 }
432
433 void appendAll(const Array<E>* l) {
434 for (int i = 0; i < l->length(); i++) {
435 this->at_put_grow(this->_len, l->at(i), E());
436 }
437 }
438
439 // Binary search and insertion utility. Search array for element
440 // matching key according to the static compare function. Insert
441 // that element if not already in the list. Assumes the list is
442 // already sorted according to compare function.
443 template <int compare(const E&, const E&)> E insert_sorted(const E& key) {
444 bool found;
445 int location = GrowableArrayView<E>::template find_sorted<E, compare>(key, found);
446 if (!found) {
447 insert_before(location, key);
448 }
449 return this->at(location);
450 }
451
452 E insert_sorted(CompareClosure<E>* cc, const E& key) {
453 bool found;
454 int location = find_sorted(cc, key, found);
455 if (!found) {
456 insert_before(location, key);
457 }
458 return this->at(location);
459 }
460
461 void swap(GrowableArrayWithAllocator* other) {
462 ::swap(this->_data, other->_data);
463 ::swap(this->_len, other->_len);
464 ::swap(this->_capacity, other->_capacity);
465 }
466
467 // Ensure capacity is at least new_capacity.
468 void reserve(int new_capacity);
469
470 void trunc_to(int length) {
471 assert(length <= this->_len,"cannot increase length");
472 this->_len = length;
473 }
474
475 // Order preserving remove operations.
476
477 void remove_at(int index) {
478 assert(0 <= index && index < this->_len,
479 "illegal index %d for length %d", index, this->_len);
480 for (int j = index + 1; j < this->_len; j++) {
481 this->_data[j-1] = this->_data[j];
482 }
483 this->_len--;
484 }
485
486 void remove(const E& elem) {
487 // Assuming that element does exist.
488 bool removed = this->remove_if_existing(elem);
489 if (removed) return;
490 ShouldNotReachHere();
491 }
492
493 bool remove_if_existing(const E& elem) {
494 // Returns TRUE if elem is removed.
495 for (int i = 0; i < this->_len; i++) {
496 if (this->_data[i] == elem) {
497 this->remove_at(i);
498 return true;
499 }
500 }
501 return false;
502 }
503
504 // Remove all elements in the range [0; end). The order is preserved.
505 void remove_till(int end) {
506 remove_range(0, end);
507 }
508
509 // Remove all elements in the range [start; end). The order is preserved.
510 void remove_range(int start, int end) {
511 assert(0 <= start, "illegal start index %d", start);
512 assert(start <= end && end <= this->_len,
513 "erase called with invalid range [%d, %d) for length %d",
514 start, end, this->_len);
515
516 for (int i = start, j = end; j < this->length(); i++, j++) {
517 this->at_put(i, this->at(j));
518 }
519 this->_len -= (end - start);
520 }
521
522 // Replaces the designated element with the last element and shrinks by 1.
523 void delete_at(int index) {
524 assert(0 <= index && index < this->_len, "illegal index %d for length %d", index, this->_len);
525 if (index < --this->_len) {
526 // Replace removed element with last one.
527 this->_data[index] = this->_data[this->_len];
528 }
529 }
530
531 // Reduce capacity to length.
532 void shrink_to_fit();
533
534 void clear() { this->_len = 0; }
535 void clear_and_deallocate();
536 };
537
538 template <typename E, typename Derived>
539 void GrowableArrayWithAllocator<E, Derived>::expand_to(int new_capacity) {
540 int old_capacity = this->_capacity;
541 assert(new_capacity > old_capacity,
542 "expected growth but %d <= %d", new_capacity, old_capacity);
543 this->_capacity = new_capacity;
544 E* newData = static_cast<Derived*>(this)->allocate();
545 int i = 0;
546 for ( ; i < this->_len; i++) ::new ((void*)&newData[i]) E(this->_data[i]);
547 for ( ; i < this->_capacity; i++) ::new ((void*)&newData[i]) E();
548 for (i = 0; i < old_capacity; i++) this->_data[i].~E();
549 if (this->_data != nullptr) {
550 static_cast<Derived*>(this)->deallocate(this->_data);
551 }
552 this->_data = newData;
553 }
554
555 template <typename E, typename Derived>
556 void GrowableArrayWithAllocator<E, Derived>::grow(int j) {
557 // grow the array by increasing _capacity to the first power of two larger than the size we need
558 expand_to(next_power_of_2(j));
559 }
560
561 template <typename E, typename Derived>
562 void GrowableArrayWithAllocator<E, Derived>::reserve(int new_capacity) {
563 if (new_capacity > this->_capacity) {
564 expand_to(new_capacity);
565 }
566 }
567
568 template <typename E, typename Derived>
569 void GrowableArrayWithAllocator<E, Derived>::shrink_to_fit() {
570 int old_capacity = this->_capacity;
571 int len = this->_len;
572 assert(len <= old_capacity, "invariant");
573
574 // If already at full capacity, nothing to do.
575 if (len == old_capacity) {
576 return;
577 }
578
579 // If not empty, allocate new, smaller, data, and copy old data to it.
580 E* old_data = this->_data;
581 E* new_data = nullptr;
582 this->_capacity = len; // Must preceed allocate().
583 if (len > 0) {
584 new_data = static_cast<Derived*>(this)->allocate();
585 for (int i = 0; i < len; ++i) ::new (&new_data[i]) E(old_data[i]);
586 }
587 // Destroy contents of old data, and deallocate it.
588 for (int i = 0; i < old_capacity; ++i) old_data[i].~E();
589 if (old_data != nullptr) {
590 static_cast<Derived*>(this)->deallocate(old_data);
591 }
592 // Install new data, which might be nullptr.
593 this->_data = new_data;
594 }
595
596 template <typename E, typename Derived>
597 void GrowableArrayWithAllocator<E, Derived>::clear_and_deallocate() {
598 this->clear();
599 this->shrink_to_fit();
600 }
601
602 class GrowableArrayResourceAllocator {
603 public:
604 static void* allocate(int max, int element_size);
605 };
606
607 // Arena allocator
608 class GrowableArrayArenaAllocator {
609 public:
610 static void* allocate(int max, int element_size, Arena* arena);
611 };
612
613 // CHeap allocator
614 class GrowableArrayCHeapAllocator {
615 public:
616 static void* allocate(int max, int element_size, MemTag mem_tag);
617 static void deallocate(void* mem);
618 };
619
620 #ifdef ASSERT
621
622 // Checks resource allocation nesting
623 class GrowableArrayNestingCheck {
624 // resource area nesting at creation
625 int _nesting;
626
627 public:
628 GrowableArrayNestingCheck(bool on_resource_area);
629 GrowableArrayNestingCheck(Arena* arena);
630
631 void on_resource_area_alloc() const;
632 void on_arena_alloc(Arena* arena) const;
633 };
634
635 #endif // ASSERT
636
637 // Encodes where the backing array is allocated
638 // and performs necessary checks.
639 class GrowableArrayMetadata {
640 uintptr_t _bits;
641
642 // resource area nesting at creation
643 DEBUG_ONLY(GrowableArrayNestingCheck _nesting_check;)
644
645 // Resource allocation
646 static uintptr_t bits() {
647 return 0;
648 }
649
650 // CHeap allocation
651 static uintptr_t bits(MemTag mem_tag) {
652 assert(mem_tag != mtNone, "Must provide a proper MemTag");
653 return (uintptr_t(mem_tag) << 1) | 1;
654 }
655
656 // Arena allocation
657 static uintptr_t bits(Arena* arena) {
658 assert((uintptr_t(arena) & 1) == 0, "Required for on_C_heap() to work");
659 return uintptr_t(arena);
660 }
661
662 public:
663 // Resource allocation
664 GrowableArrayMetadata() :
665 _bits(bits())
666 DEBUG_ONLY(COMMA _nesting_check(true)) {
667 }
668
669 // Arena allocation
670 GrowableArrayMetadata(Arena* arena) :
671 _bits(bits(arena))
672 DEBUG_ONLY(COMMA _nesting_check(arena)) {
673 }
674
675 // CHeap allocation
676 GrowableArrayMetadata(MemTag mem_tag) :
677 _bits(bits(mem_tag))
678 DEBUG_ONLY(COMMA _nesting_check(false)) {
679 }
680
681 #ifdef ASSERT
682 GrowableArrayMetadata(const GrowableArrayMetadata& other) :
683 _bits(other._bits),
684 _nesting_check(other._nesting_check) {
685 assert(!on_C_heap(), "Copying of CHeap arrays not supported");
686 assert(!other.on_C_heap(), "Copying of CHeap arrays not supported");
687 }
688
689 GrowableArrayMetadata& operator=(const GrowableArrayMetadata& other) {
690 _bits = other._bits;
691 _nesting_check = other._nesting_check;
692 assert(!on_C_heap(), "Assignment of CHeap arrays not supported");
693 assert(!other.on_C_heap(), "Assignment of CHeap arrays not supported");
694 return *this;
695 }
696
697 void init_checks(const GrowableArrayBase* array) const;
698 void on_resource_area_alloc_check() const;
699 void on_arena_alloc_check() const;
700 #endif // ASSERT
701
702 bool on_C_heap() const { return (_bits & 1) == 1; }
703 bool on_resource_area() const { return _bits == 0; }
704 bool on_arena() const { return (_bits & 1) == 0 && _bits != 0; }
705
706 Arena* arena() const { return (Arena*)_bits; }
707 MemTag mem_tag() const { return MemTag(_bits >> 1); }
708 };
709
710 // THE GrowableArray.
711 //
712 // Supports multiple allocation strategies:
713 // - Resource stack allocation: if no extra argument is provided
714 // - CHeap allocation: if mem_tag is provided
715 // - Arena allocation: if an arena is provided
716 //
717 // There are some drawbacks of using GrowableArray, that are removed in some
718 // of the other implementations of GrowableArrayWithAllocator sub-classes:
719 //
720 // Memory overhead: The multiple allocation strategies uses extra metadata
721 // embedded in the instance.
722 //
723 // Strict allocation locations: There are rules about where the GrowableArray
724 // instance is allocated, that depends on where the data array is allocated.
725 // See: init_checks.
726
727 template <typename E>
728 class GrowableArray : public GrowableArrayWithAllocator<E, GrowableArray<E>> {
729 friend class VMStructs;
730 friend class GrowableArrayWithAllocator<E, GrowableArray>;
731 friend class GrowableArrayTest;
732
733 static E* allocate(int max) {
734 return (E*)GrowableArrayResourceAllocator::allocate(max, sizeof(E));
735 }
736
737 static E* allocate(int max, MemTag mem_tag) {
738 return (E*)GrowableArrayCHeapAllocator::allocate(max, sizeof(E), mem_tag);
739 }
740
741 static E* allocate(int max, Arena* arena) {
742 return (E*)GrowableArrayArenaAllocator::allocate(max, sizeof(E), arena);
743 }
744
745 GrowableArrayMetadata _metadata;
746
747 void init_checks() const { DEBUG_ONLY(_metadata.init_checks(this);) }
748
749 // Where are we going to allocate memory?
750 bool on_C_heap() const { return _metadata.on_C_heap(); }
751 bool on_resource_area() const { return _metadata.on_resource_area(); }
752 bool on_arena() const { return _metadata.on_arena(); }
753
754 E* allocate() {
755 if (on_resource_area()) {
756 DEBUG_ONLY(_metadata.on_resource_area_alloc_check());
757 return allocate(this->_capacity);
758 }
759
760 if (on_C_heap()) {
761 return allocate(this->_capacity, _metadata.mem_tag());
762 }
763
764 assert(on_arena(), "Sanity");
765 DEBUG_ONLY(_metadata.on_arena_alloc_check());
766 return allocate(this->_capacity, _metadata.arena());
767 }
768
769 void deallocate(E* mem) {
770 if (on_C_heap()) {
771 GrowableArrayCHeapAllocator::deallocate(mem);
772 }
773 }
774
775 public:
776 GrowableArray() : GrowableArray(2 /* initial_capacity */) {}
777
778 explicit GrowableArray(int initial_capacity) :
779 GrowableArrayWithAllocator<E, GrowableArray>(
780 allocate(initial_capacity),
781 initial_capacity),
782 _metadata() {
783 init_checks();
784 }
785
786 GrowableArray(int initial_capacity, MemTag mem_tag) :
787 GrowableArrayWithAllocator<E, GrowableArray>(
788 allocate(initial_capacity, mem_tag),
789 initial_capacity),
790 _metadata(mem_tag) {
791 init_checks();
792 }
793
794 GrowableArray(int initial_capacity, int initial_len, const E& filler) :
795 GrowableArrayWithAllocator<E, GrowableArray>(
796 allocate(initial_capacity),
797 initial_capacity, initial_len, filler),
798 _metadata() {
799 init_checks();
800 }
801
802 // This constructor performs no default initialization, so be careful.
803 GrowableArray(int initial_capacity, int initial_len, MemTag mem_tag) :
804 GrowableArrayWithAllocator<E, GrowableArray>(
805 allocate(initial_capacity, mem_tag),
806 initial_capacity, initial_len),
807 _metadata(mem_tag) {
808 init_checks();
809 }
810
811 GrowableArray(int initial_capacity, int initial_len, const E& filler, MemTag mem_tag) :
812 GrowableArrayWithAllocator<E, GrowableArray>(
813 allocate(initial_capacity, mem_tag),
814 initial_capacity, initial_len, filler),
815 _metadata(mem_tag) {
816 init_checks();
817 }
818
819 GrowableArray(Arena* arena, int initial_capacity, int initial_len, const E& filler) :
820 GrowableArrayWithAllocator<E, GrowableArray>(
821 allocate(initial_capacity, arena),
822 initial_capacity, initial_len, filler),
823 _metadata(arena) {
824 init_checks();
825 }
826
827 ~GrowableArray() {
828 if (on_C_heap()) {
829 this->clear_and_deallocate();
830 }
831 }
832
833 void assert_on_C_heap() { assert(on_C_heap(), "must be on C heap"); }
834 };
835
836 // Leaner GrowableArray for CHeap backed data arrays, with compile-time decided MemTag.
837 template <typename E, MemTag MT>
838 class GrowableArrayCHeap : public GrowableArrayWithAllocator<E, GrowableArrayCHeap<E, MT> > {
839 friend class GrowableArrayWithAllocator<E, GrowableArrayCHeap<E, MT> >;
840
841 STATIC_ASSERT(MT != mtNone);
842
843 static E* allocate(int max, MemTag mem_tag) {
844 return (E*)GrowableArrayCHeapAllocator::allocate(max, sizeof(E), mem_tag);
845 }
846
847 NONCOPYABLE(GrowableArrayCHeap);
848
849 E* allocate() {
850 return allocate(this->_capacity, MT);
851 }
852
853 void deallocate(E* mem) {
854 GrowableArrayCHeapAllocator::deallocate(mem);
855 }
856
857 public:
858 GrowableArrayCHeap(int initial_capacity = 0) :
859 GrowableArrayWithAllocator<E, GrowableArrayCHeap<E, MT> >(
860 allocate(initial_capacity, MT),
861 initial_capacity) {}
862
863 GrowableArrayCHeap(int initial_capacity, int initial_len, const E& filler) :
864 GrowableArrayWithAllocator<E, GrowableArrayCHeap<E, MT> >(
865 allocate(initial_capacity, MT),
866 initial_capacity, initial_len, filler) {}
867
868 ~GrowableArrayCHeap() {
869 this->clear_and_deallocate();
870 }
871
872 void* operator new(size_t size) {
873 return AnyObj::operator new(size, MT);
874 }
875
876 void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() {
877 return AnyObj::operator new(size, nothrow_constant, MT);
878 }
879 void operator delete(void *p) {
880 AnyObj::operator delete(p);
881 }
882 };
883
884 // Custom STL-style iterator to iterate over GrowableArrays
885 // It is constructed by invoking GrowableArray::begin() and GrowableArray::end()
886 template <typename E>
887 class GrowableArrayIterator : public StackObj {
888 friend class GrowableArrayView<E>;
889 template <typename F, typename UnaryPredicate> friend class GrowableArrayFilterIterator;
890
891 private:
892 const GrowableArrayView<E>* _array; // GrowableArray we iterate over
893 int _position; // The current position in the GrowableArray
894
895 // Private constructor used in GrowableArray::begin() and GrowableArray::end()
896 GrowableArrayIterator(const GrowableArrayView<E>* array, int position) : _array(array), _position(position) {
897 assert(0 <= position && position <= _array->length(), "illegal position");
898 }
899
900 public:
901 GrowableArrayIterator() : _array(nullptr), _position(0) { }
902 GrowableArrayIterator& operator++() { ++_position; return *this; }
903 E operator*() { return _array->at(_position); }
904
905 bool operator==(const GrowableArrayIterator& rhs) {
906 assert(_array == rhs._array, "iterator belongs to different array");
907 return _position == rhs._position;
908 }
909
910 bool operator!=(const GrowableArrayIterator& rhs) {
911 assert(_array == rhs._array, "iterator belongs to different array");
912 return _position != rhs._position;
913 }
914 };
915
916 // Custom STL-style iterator to iterate over elements of a GrowableArray that satisfy a given predicate
917 template <typename E, class UnaryPredicate>
918 class GrowableArrayFilterIterator : public StackObj {
919 friend class GrowableArrayView<E>;
920
921 private:
922 const GrowableArrayView<E>* _array; // GrowableArray we iterate over
923 int _position; // Current position in the GrowableArray
924 UnaryPredicate _predicate; // Unary predicate the elements of the GrowableArray should satisfy
925
926 public:
927 GrowableArrayFilterIterator(const GrowableArray<E>* array, UnaryPredicate filter_predicate) :
928 _array(array), _position(0), _predicate(filter_predicate) {
929 // Advance to first element satisfying the predicate
930 while(!at_end() && !_predicate(_array->at(_position))) {
931 ++_position;
932 }
933 }
934
935 GrowableArrayFilterIterator<E, UnaryPredicate>& operator++() {
936 do {
937 // Advance to next element satisfying the predicate
938 ++_position;
939 } while(!at_end() && !_predicate(_array->at(_position)));
940 return *this;
941 }
942
943 E operator*() { return _array->at(_position); }
944
945 bool operator==(const GrowableArrayIterator<E>& rhs) {
946 assert(_array == rhs._array, "iterator belongs to different array");
947 return _position == rhs._position;
948 }
949
950 bool operator!=(const GrowableArrayIterator<E>& rhs) {
951 assert(_array == rhs._array, "iterator belongs to different array");
952 return _position != rhs._position;
953 }
954
955 bool operator==(const GrowableArrayFilterIterator<E, UnaryPredicate>& rhs) {
956 assert(_array == rhs._array, "iterator belongs to different array");
957 return _position == rhs._position;
958 }
959
960 bool operator!=(const GrowableArrayFilterIterator<E, UnaryPredicate>& rhs) {
961 assert(_array == rhs._array, "iterator belongs to different array");
962 return _position != rhs._position;
963 }
964
965 bool at_end() const {
966 return _array == nullptr || _position == _array->end()._position;
967 }
968 };
969
970 // Arrays for basic types
971 typedef GrowableArray<int> intArray;
972 typedef GrowableArray<int> intStack;
973 typedef GrowableArray<bool> boolArray;
974
975 #endif // SHARE_UTILITIES_GROWABLEARRAY_HPP