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