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