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