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