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