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