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