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