1/*
2 * Copyright (c) 1997, 2019, 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/oop.hpp"
30#include "utilities/debug.hpp"
31#include "utilities/globalDefinitions.hpp"
32#include "utilities/ostream.hpp"
33
34// A growable array.
35
36/*************************************************************************/
37/* */
38/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING */
39/* */
40/* Should you use GrowableArrays to contain handles you must be certain */
41/* the the GrowableArray does not outlive the HandleMark that contains */
42/* the handles. Since GrowableArrays are typically resource allocated */
43/* the following is an example of INCORRECT CODE, */
44/* */
45/* ResourceMark rm; */
46/* GrowableArray<Handle>* arr = new GrowableArray<Handle>(size); */
47/* if (blah) { */
48/* while (...) { */
49/* HandleMark hm; */
50/* ... */
51/* Handle h(THREAD, some_oop); */
52/* arr->append(h); */
53/* } */
54/* } */
55/* if (arr->length() != 0 ) { */
56/* oop bad_oop = arr->at(0)(); // Handle is BAD HERE. */
57/* ... */
58/* } */
59/* */
60/* If the GrowableArrays you are creating is C_Heap allocated then it */
61/* hould not old handles since the handles could trivially try and */
62/* outlive their HandleMark. In some situations you might need to do */
63/* this and it would be legal but be very careful and see if you can do */
64/* the code in some other manner. */
65/* */
66/*************************************************************************/
67
68// To call default constructor the placement operator new() is used.
69// It should be empty (it only returns the passed void* pointer).
70// The definition of placement operator new(size_t, void*) in the <new>.
71
72#include <new>
73
74// Need the correct linkage to call qsort without warnings
75extern "C" {
76 typedef int (*_sort_Fn)(const void *, const void *);
77}
78
79class GenericGrowableArray : public ResourceObj {
80 friend class VMStructs;
81
82 protected:
83 int _len; // current length
84 int _max; // maximum length
85 Arena* _arena; // Indicates where allocation occurs:
86 // 0 means default ResourceArea
87 // 1 means on C heap
88 // otherwise, allocate in _arena
89
90 MEMFLAGS _memflags; // memory type if allocation in C heap
91
92#ifdef ASSERT
93 int _nesting; // resource area nesting at creation
94 void set_nesting();
95 void check_nesting();
96#else
97#define set_nesting();
98#define check_nesting();
99#endif
100
101 // Where are we going to allocate memory?
102 bool on_C_heap() { return _arena == (Arena*)1; }
103 bool on_stack () { return _arena == NULL; }
104 bool on_arena () { return _arena > (Arena*)1; }
105
106 // This GA will use the resource stack for storage if c_heap==false,
107 // Else it will use the C heap. Use clear_and_deallocate to avoid leaks.
108 GenericGrowableArray(int initial_size, int initial_len, bool c_heap, MEMFLAGS flags = mtNone) {
109 _len = initial_len;
110 _max = initial_size;
111 _memflags = flags;
112
113 // memory type has to be specified for C heap allocation
114 assert(!(c_heap && flags == mtNone), "memory type not specified for C heap object");
115
116 assert(_len >= 0 && _len <= _max, "initial_len too big");
117 _arena = (c_heap ? (Arena*)1 : NULL);
118 set_nesting();
119 assert(!on_C_heap() || allocated_on_C_heap(), "growable array must be on C heap if elements are");
120 assert(!on_stack() ||
121 (allocated_on_res_area() || allocated_on_stack()),
122 "growable array must be on stack if elements are not on arena and not on C heap");
123 }
124
125 // This GA will use the given arena for storage.
126 // Consider using new(arena) GrowableArray<T> to allocate the header.
127 GenericGrowableArray(Arena* arena, int initial_size, int initial_len) {
128 _len = initial_len;
129 _max = initial_size;
130 assert(_len >= 0 && _len <= _max, "initial_len too big");
131 _arena = arena;
132 _memflags = mtNone;
133
134 assert(on_arena(), "arena has taken on reserved value 0 or 1");
135 // Relax next assert to allow object allocation on resource area,
136 // on stack or embedded into an other object.
137 assert(allocated_on_arena() || allocated_on_stack(),
138 "growable array must be on arena or on stack if elements are on arena");
139 }
140
141 void* raw_allocate(int elementSize);
142
143 // some uses pass the Thread explicitly for speed (4990299 tuning)
144 void* raw_allocate(Thread* thread, int elementSize) {
145 assert(on_stack(), "fast ResourceObj path only");
146 return (void*)resource_allocate_bytes(thread, elementSize * _max);
147 }
148
149 void free_C_heap(void* elements);
150};
151
152template<class E> class GrowableArrayIterator;
153template<class E, class UnaryPredicate> class GrowableArrayFilterIterator;
154
155template<class E>
156class CompareClosure : public Closure {
157public:
158 virtual int do_compare(const E&, const E&) = 0;
159};
160
161template<class E> class GrowableArray : public GenericGrowableArray {
162 friend class VMStructs;
163
164 private:
165 E* _data; // data array
166
167 void grow(int j);
168 void raw_at_put_grow(int i, const E& p, const E& fill);
169 void clear_and_deallocate();
170 public:
171 GrowableArray(Thread* thread, int initial_size) : GenericGrowableArray(initial_size, 0, false) {
172 _data = (E*)raw_allocate(thread, sizeof(E));
173 for (int i = 0; i < _max; i++) ::new ((void*)&_data[i]) E();
174 }
175
176 GrowableArray(int initial_size, bool C_heap = false, MEMFLAGS F = mtInternal)
177 : GenericGrowableArray(initial_size, 0, C_heap, F) {
178 _data = (E*)raw_allocate(sizeof(E));
179// Needed for Visual Studio 2012 and older
180#ifdef _MSC_VER
181#pragma warning(suppress: 4345)
182#endif
183 for (int i = 0; i < _max; i++) ::new ((void*)&_data[i]) E();
184 }
185
186 GrowableArray(int initial_size, int initial_len, const E& filler, bool C_heap = false, MEMFLAGS memflags = mtInternal)
187 : GenericGrowableArray(initial_size, initial_len, C_heap, memflags) {
188 _data = (E*)raw_allocate(sizeof(E));
189 int i = 0;
190 for (; i < _len; i++) ::new ((void*)&_data[i]) E(filler);
191 for (; i < _max; i++) ::new ((void*)&_data[i]) E();
192 }
193
194 GrowableArray(Arena* arena, int initial_size, int initial_len, const E& filler) : GenericGrowableArray(arena, initial_size, initial_len) {
195 _data = (E*)raw_allocate(sizeof(E));
196 int i = 0;
197 for (; i < _len; i++) ::new ((void*)&_data[i]) E(filler);
198 for (; i < _max; i++) ::new ((void*)&_data[i]) E();
199 }
200
201 GrowableArray() : GenericGrowableArray(2, 0, false) {
202 _data = (E*)raw_allocate(sizeof(E));
203 ::new ((void*)&_data[0]) E();
204 ::new ((void*)&_data[1]) E();
205 }
206
207 // Does nothing for resource and arena objects
208 ~GrowableArray() { if (on_C_heap()) clear_and_deallocate(); }
209
210 void clear() { _len = 0; }
211 int length() const { return _len; }
212 int max_length() const { return _max; }
213 void trunc_to(int l) { assert(l <= _len,"cannot increase length"); _len = l; }
214 bool is_empty() const { return _len == 0; }
215 bool is_nonempty() const { return _len != 0; }
216 bool is_full() const { return _len == _max; }
217 DEBUG_ONLY(E* data_addr() const { return _data; })
218
219 void print();
220
221 inline static bool safe_equals(oop obj1, oop obj2) {
222 return oopDesc::equals(obj1, obj2);
223 }
224
225 template <class X>
226 inline static bool safe_equals(X i1, X i2) {
227 return i1 == i2;
228 }
229
230 int append(const E& elem) {
231 check_nesting();
232 if (_len == _max) grow(_len);
233 int idx = _len++;
234 _data[idx] = elem;
235 return idx;
236 }
237
238 bool append_if_missing(const E& elem) {
239 // Returns TRUE if elem is added.
240 bool missed = !contains(elem);
241 if (missed) append(elem);
242 return missed;
243 }
244
245 E& at(int i) {
246 assert(0 <= i && i < _len, "illegal index");
247 return _data[i];
248 }
249
250 E const& at(int i) const {
251 assert(0 <= i && i < _len, "illegal index");
252 return _data[i];
253 }
254
255 E* adr_at(int i) const {
256 assert(0 <= i && i < _len, "illegal index");
257 return &_data[i];
258 }
259
260 E first() const {
261 assert(_len > 0, "empty list");
262 return _data[0];
263 }
264
265 E top() const {
266 assert(_len > 0, "empty list");
267 return _data[_len-1];
268 }
269
270 E last() const {
271 return top();
272 }
273
274 GrowableArrayIterator<E> begin() const {
275 return GrowableArrayIterator<E>(this, 0);
276 }
277
278 GrowableArrayIterator<E> end() const {
279 return GrowableArrayIterator<E>(this, length());
280 }
281
282 void push(const E& elem) { append(elem); }
283
284 E pop() {
285 assert(_len > 0, "empty list");
286 return _data[--_len];
287 }
288
289 void at_put(int i, const E& elem) {
290 assert(0 <= i && i < _len, "illegal index");
291 _data[i] = elem;
292 }
293
294 E at_grow(int i, const E& fill = E()) {
295 assert(0 <= i, "negative index");
296 check_nesting();
297 if (i >= _len) {
298 if (i >= _max) grow(i);
299 for (int j = _len; j <= i; j++)
300 _data[j] = fill;
301 _len = i+1;
302 }
303 return _data[i];
304 }
305
306 void at_put_grow(int i, const E& elem, const E& fill = E()) {
307 assert(0 <= i, "negative index");
308 check_nesting();
309 raw_at_put_grow(i, elem, fill);
310 }
311
312 bool contains(const E& elem) const {
313 for (int i = 0; i < _len; i++) {
314 if (safe_equals(_data[i], elem)) return true;
315 }
316 return false;
317 }
318
319 int find(const E& elem) const {
320 for (int i = 0; i < _len; i++) {
321 if (_data[i] == elem) return i;
322 }
323 return -1;
324 }
325
326 int find_from_end(const E& elem) const {
327 for (int i = _len-1; i >= 0; i--) {
328 if (_data[i] == elem) return i;
329 }
330 return -1;
331 }
332
333 int find(void* token, bool f(void*, E)) const {
334 for (int i = 0; i < _len; i++) {
335 if (f(token, _data[i])) return i;
336 }
337 return -1;
338 }
339
340 int find_from_end(void* token, bool f(void*, E)) const {
341 // start at the end of the array
342 for (int i = _len-1; i >= 0; i--) {
343 if (f(token, _data[i])) return i;
344 }
345 return -1;
346 }
347
348 void remove(const E& elem) {
349 for (int i = 0; i < _len; i++) {
350 if (_data[i] == elem) {
351 for (int j = i + 1; j < _len; j++) _data[j-1] = _data[j];
352 _len--;
353 return;
354 }
355 }
356 ShouldNotReachHere();
357 }
358
359 // The order is preserved.
360 void remove_at(int index) {
361 assert(0 <= index && index < _len, "illegal index");
362 for (int j = index + 1; j < _len; j++) _data[j-1] = _data[j];
363 _len--;
364 }
365
366 // The order is changed.
367 void delete_at(int index) {
368 assert(0 <= index && index < _len, "illegal index");
369 if (index < --_len) {
370 // Replace removed element with last one.
371 _data[index] = _data[_len];
372 }
373 }
374
375 // inserts the given element before the element at index i
376 void insert_before(const int idx, const E& elem) {
377 assert(0 <= idx && idx <= _len, "illegal index");
378 check_nesting();
379 if (_len == _max) grow(_len);
380 for (int j = _len - 1; j >= idx; j--) {
381 _data[j + 1] = _data[j];
382 }
383 _len++;
384 _data[idx] = elem;
385 }
386
387 void insert_before(const int idx, const GrowableArray<E>* array) {
388 assert(0 <= idx && idx <= _len, "illegal index");
389 check_nesting();
390 int array_len = array->length();
391 int new_len = _len + array_len;
392 if (new_len >= _max) grow(new_len);
393
394 for (int j = _len - 1; j >= idx; j--) {
395 _data[j + array_len] = _data[j];
396 }
397
398 for (int j = 0; j < array_len; j++) {
399 _data[idx + j] = array->_data[j];
400 }
401
402 _len += array_len;
403 }
404
405 void appendAll(const GrowableArray<E>* l) {
406 for (int i = 0; i < l->_len; i++) {
407 raw_at_put_grow(_len, l->_data[i], E());
408 }
409 }
410
411 void sort(int f(E*,E*)) {
412 qsort(_data, length(), sizeof(E), (_sort_Fn)f);
413 }
414 // sort by fixed-stride sub arrays:
415 void sort(int f(E*,E*), int stride) {
416 qsort(_data, length() / stride, sizeof(E) * stride, (_sort_Fn)f);
417 }
418
419 // Binary search and insertion utility. Search array for element
420 // matching key according to the static compare function. Insert
421 // that element is not already in the list. Assumes the list is
422 // already sorted according to compare function.
423 template <int compare(const E&, const E&)> E insert_sorted(const E& key) {
424 bool found;
425 int location = find_sorted<E, compare>(key, found);
426 if (!found) {
427 insert_before(location, key);
428 }
429 return at(location);
430 }
431
432 template <typename K, int compare(const K&, const E&)> int find_sorted(const K& key, bool& found) {
433 found = false;
434 int min = 0;
435 int max = length() - 1;
436
437 while (max >= min) {
438 int mid = (int)(((uint)max + min) / 2);
439 E value = at(mid);
440 int diff = compare(key, value);
441 if (diff > 0) {
442 min = mid + 1;
443 } else if (diff < 0) {
444 max = mid - 1;
445 } else {
446 found = true;
447 return mid;
448 }
449 }
450 return min;
451 }
452
453 E insert_sorted(CompareClosure<E>* cc, const E& key) {
454 bool found;
455 int location = find_sorted(cc, key, found);
456 if (!found) {
457 insert_before(location, key);
458 }
459 return at(location);
460 }
461
462 template<typename K>
463 int find_sorted(CompareClosure<E>* cc, const K& key, bool& found) {
464 found = false;
465 int min = 0;
466 int max = length() - 1;
467
468 while (max >= min) {
469 int mid = (int)(((uint)max + min) / 2);
470 E value = at(mid);
471 int diff = cc->do_compare(key, value);
472 if (diff > 0) {
473 min = mid + 1;
474 } else if (diff < 0) {
475 max = mid - 1;
476 } else {
477 found = true;
478 return mid;
479 }
480 }
481 return min;
482 }
483};
484
485// Global GrowableArray methods (one instance in the library per each 'E' type).
486
487template<class E> void GrowableArray<E>::grow(int j) {
488 // grow the array by doubling its size (amortized growth)
489 int old_max = _max;
490 if (_max == 0) _max = 1; // prevent endless loop
491 while (j >= _max) _max = _max*2;
492 // j < _max
493 E* newData = (E*)raw_allocate(sizeof(E));
494 int i = 0;
495 for ( ; i < _len; i++) ::new ((void*)&newData[i]) E(_data[i]);
496// Needed for Visual Studio 2012 and older
497#ifdef _MSC_VER
498#pragma warning(suppress: 4345)
499#endif
500 for ( ; i < _max; i++) ::new ((void*)&newData[i]) E();
501 for (i = 0; i < old_max; i++) _data[i].~E();
502 if (on_C_heap() && _data != NULL) {
503 free_C_heap(_data);
504 }
505 _data = newData;
506}
507
508template<class E> void GrowableArray<E>::raw_at_put_grow(int i, const E& p, const E& fill) {
509 if (i >= _len) {
510 if (i >= _max) grow(i);
511 for (int j = _len; j < i; j++)
512 _data[j] = fill;
513 _len = i+1;
514 }
515 _data[i] = p;
516}
517
518// This function clears and deallocate the data in the growable array that
519// has been allocated on the C heap. It's not public - called by the
520// destructor.
521template<class E> void GrowableArray<E>::clear_and_deallocate() {
522 assert(on_C_heap(),
523 "clear_and_deallocate should only be called when on C heap");
524 clear();
525 if (_data != NULL) {
526 for (int i = 0; i < _max; i++) _data[i].~E();
527 free_C_heap(_data);
528 _data = NULL;
529 }
530}
531
532template<class E> void GrowableArray<E>::print() {
533 tty->print("Growable Array " INTPTR_FORMAT, this);
534 tty->print(": length %ld (_max %ld) { ", _len, _max);
535 for (int i = 0; i < _len; i++) tty->print(INTPTR_FORMAT " ", *(intptr_t*)&(_data[i]));
536 tty->print("}\n");
537}
538
539// Custom STL-style iterator to iterate over GrowableArrays
540// It is constructed by invoking GrowableArray::begin() and GrowableArray::end()
541template<class E> class GrowableArrayIterator : public StackObj {
542 friend class GrowableArray<E>;
543 template<class F, class UnaryPredicate> friend class GrowableArrayFilterIterator;
544
545 private:
546 const GrowableArray<E>* _array; // GrowableArray we iterate over
547 int _position; // The current position in the GrowableArray
548
549 // Private constructor used in GrowableArray::begin() and GrowableArray::end()
550 GrowableArrayIterator(const GrowableArray<E>* array, int position) : _array(array), _position(position) {
551 assert(0 <= position && position <= _array->length(), "illegal position");
552 }
553
554 public:
555 GrowableArrayIterator() : _array(NULL), _position(0) { }
556 GrowableArrayIterator<E>& operator++() { ++_position; return *this; }
557 E operator*() { return _array->at(_position); }
558
559 bool operator==(const GrowableArrayIterator<E>& rhs) {
560 assert(_array == rhs._array, "iterator belongs to different array");
561 return _position == rhs._position;
562 }
563
564 bool operator!=(const GrowableArrayIterator<E>& rhs) {
565 assert(_array == rhs._array, "iterator belongs to different array");
566 return _position != rhs._position;
567 }
568};
569
570// Custom STL-style iterator to iterate over elements of a GrowableArray that satisfy a given predicate
571template<class E, class UnaryPredicate> class GrowableArrayFilterIterator : public StackObj {
572 friend class GrowableArray<E>;
573
574 private:
575 const GrowableArray<E>* _array; // GrowableArray we iterate over
576 int _position; // Current position in the GrowableArray
577 UnaryPredicate _predicate; // Unary predicate the elements of the GrowableArray should satisfy
578
579 public:
580 GrowableArrayFilterIterator(const GrowableArrayIterator<E>& begin, UnaryPredicate filter_predicate)
581 : _array(begin._array), _position(begin._position), _predicate(filter_predicate) {
582 // Advance to first element satisfying the predicate
583 while(_position != _array->length() && !_predicate(_array->at(_position))) {
584 ++_position;
585 }
586 }
587
588 GrowableArrayFilterIterator<E, UnaryPredicate>& operator++() {
589 do {
590 // Advance to next element satisfying the predicate
591 ++_position;
592 } while(_position != _array->length() && !_predicate(_array->at(_position)));
593 return *this;
594 }
595
596 E operator*() { return _array->at(_position); }
597
598 bool operator==(const GrowableArrayIterator<E>& rhs) {
599 assert(_array == rhs._array, "iterator belongs to different array");
600 return _position == rhs._position;
601 }
602
603 bool operator!=(const GrowableArrayIterator<E>& rhs) {
604 assert(_array == rhs._array, "iterator belongs to different array");
605 return _position != rhs._position;
606 }
607
608 bool operator==(const GrowableArrayFilterIterator<E, UnaryPredicate>& rhs) {
609 assert(_array == rhs._array, "iterator belongs to different array");
610 return _position == rhs._position;
611 }
612
613 bool operator!=(const GrowableArrayFilterIterator<E, UnaryPredicate>& rhs) {
614 assert(_array == rhs._array, "iterator belongs to different array");
615 return _position != rhs._position;
616 }
617};
618
619// Arrays for basic types
620typedef GrowableArray<int> intArray;
621typedef GrowableArray<int> intStack;
622typedef GrowableArray<bool> boolArray;
623
624#endif // SHARE_UTILITIES_GROWABLEARRAY_HPP
625