Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/utilities/growableArray.hpp
32285 views
1
/*
2
* Copyright (c) 1997, 2013, 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_VM_UTILITIES_GROWABLEARRAY_HPP
26
#define SHARE_VM_UTILITIES_GROWABLEARRAY_HPP
27
28
#include "memory/allocation.hpp"
29
#include "memory/allocation.inline.hpp"
30
#include "utilities/debug.hpp"
31
#include "utilities/globalDefinitions.hpp"
32
#include "utilities/top.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
75
extern "C" {
76
typedef int (*_sort_Fn)(const void *, const void *);
77
}
78
79
class 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
150
template<class E> class GrowableArrayIterator;
151
template<class E, class UnaryPredicate> class GrowableArrayFilterIterator;
152
153
template<class E> class GrowableArray : public GenericGrowableArray {
154
friend class VMStructs;
155
156
private:
157
E* _data; // data array
158
159
void grow(int j);
160
void raw_at_put_grow(int i, const E& p, const E& fill);
161
void clear_and_deallocate();
162
public:
163
GrowableArray(Thread* thread, int initial_size) : GenericGrowableArray(initial_size, 0, false) {
164
_data = (E*)raw_allocate(thread, sizeof(E));
165
for (int i = 0; i < _max; i++) ::new ((void*)&_data[i]) E();
166
}
167
168
GrowableArray(int initial_size, bool C_heap = false, MEMFLAGS F = mtInternal)
169
: GenericGrowableArray(initial_size, 0, C_heap, F) {
170
_data = (E*)raw_allocate(sizeof(E));
171
// Needed for Visual Studio 2012 and older
172
#ifdef _MSC_VER
173
#pragma warning(suppress: 4345)
174
#endif
175
for (int i = 0; i < _max; i++) ::new ((void*)&_data[i]) E();
176
}
177
178
GrowableArray(int initial_size, int initial_len, const E& filler, bool C_heap = false, MEMFLAGS memflags = mtInternal)
179
: GenericGrowableArray(initial_size, initial_len, C_heap, memflags) {
180
_data = (E*)raw_allocate(sizeof(E));
181
int i = 0;
182
for (; i < _len; i++) ::new ((void*)&_data[i]) E(filler);
183
for (; i < _max; i++) ::new ((void*)&_data[i]) E();
184
}
185
186
GrowableArray(Arena* arena, int initial_size, int initial_len, const E& filler) : GenericGrowableArray(arena, initial_size, initial_len) {
187
_data = (E*)raw_allocate(sizeof(E));
188
int i = 0;
189
for (; i < _len; i++) ::new ((void*)&_data[i]) E(filler);
190
for (; i < _max; i++) ::new ((void*)&_data[i]) E();
191
}
192
193
GrowableArray() : GenericGrowableArray(2, 0, false) {
194
_data = (E*)raw_allocate(sizeof(E));
195
::new ((void*)&_data[0]) E();
196
::new ((void*)&_data[1]) E();
197
}
198
199
// Does nothing for resource and arena objects
200
~GrowableArray() { if (on_C_heap()) clear_and_deallocate(); }
201
202
void clear() { _len = 0; }
203
int length() const { return _len; }
204
int max_length() const { return _max; }
205
void trunc_to(int l) { assert(l <= _len,"cannot increase length"); _len = l; }
206
bool is_empty() const { return _len == 0; }
207
bool is_nonempty() const { return _len != 0; }
208
bool is_full() const { return _len == _max; }
209
DEBUG_ONLY(E* data_addr() const { return _data; })
210
211
void print();
212
213
int append(const E& elem) {
214
check_nesting();
215
if (_len == _max) grow(_len);
216
int idx = _len++;
217
_data[idx] = elem;
218
return idx;
219
}
220
221
bool append_if_missing(const E& elem) {
222
// Returns TRUE if elem is added.
223
bool missed = !contains(elem);
224
if (missed) append(elem);
225
return missed;
226
}
227
228
E& at(int i) {
229
assert(0 <= i && i < _len, "illegal index");
230
return _data[i];
231
}
232
233
E const& at(int i) const {
234
assert(0 <= i && i < _len, "illegal index");
235
return _data[i];
236
}
237
238
E* adr_at(int i) const {
239
assert(0 <= i && i < _len, "illegal index");
240
return &_data[i];
241
}
242
243
E first() const {
244
assert(_len > 0, "empty list");
245
return _data[0];
246
}
247
248
E top() const {
249
assert(_len > 0, "empty list");
250
return _data[_len-1];
251
}
252
253
GrowableArrayIterator<E> begin() const {
254
return GrowableArrayIterator<E>(this, 0);
255
}
256
257
GrowableArrayIterator<E> end() const {
258
return GrowableArrayIterator<E>(this, length());
259
}
260
261
void push(const E& elem) { append(elem); }
262
263
E pop() {
264
assert(_len > 0, "empty list");
265
return _data[--_len];
266
}
267
268
void at_put(int i, const E& elem) {
269
assert(0 <= i && i < _len, "illegal index");
270
_data[i] = elem;
271
}
272
273
E at_grow(int i, const E& fill = E()) {
274
assert(0 <= i, "negative index");
275
check_nesting();
276
if (i >= _len) {
277
if (i >= _max) grow(i);
278
for (int j = _len; j <= i; j++)
279
_data[j] = fill;
280
_len = i+1;
281
}
282
return _data[i];
283
}
284
285
void at_put_grow(int i, const E& elem, const E& fill = E()) {
286
assert(0 <= i, "negative index");
287
check_nesting();
288
raw_at_put_grow(i, elem, fill);
289
}
290
291
bool contains(const E& elem) const {
292
for (int i = 0; i < _len; i++) {
293
if (_data[i] == elem) return true;
294
}
295
return false;
296
}
297
298
int find(const E& elem) const {
299
for (int i = 0; i < _len; i++) {
300
if (_data[i] == elem) return i;
301
}
302
return -1;
303
}
304
305
int find_from_end(const E& elem) const {
306
for (int i = _len-1; i >= 0; i--) {
307
if (_data[i] == elem) return i;
308
}
309
return -1;
310
}
311
312
int find(void* token, bool f(void*, E)) const {
313
for (int i = 0; i < _len; i++) {
314
if (f(token, _data[i])) return i;
315
}
316
return -1;
317
}
318
319
int find_from_end(void* token, bool f(void*, E)) const {
320
// start at the end of the array
321
for (int i = _len-1; i >= 0; i--) {
322
if (f(token, _data[i])) return i;
323
}
324
return -1;
325
}
326
327
void remove(const E& elem) {
328
for (int i = 0; i < _len; i++) {
329
if (_data[i] == elem) {
330
for (int j = i + 1; j < _len; j++) _data[j-1] = _data[j];
331
_len--;
332
return;
333
}
334
}
335
ShouldNotReachHere();
336
}
337
338
// The order is preserved.
339
void remove_at(int index) {
340
assert(0 <= index && index < _len, "illegal index");
341
for (int j = index + 1; j < _len; j++) _data[j-1] = _data[j];
342
_len--;
343
}
344
345
// The order is changed.
346
void delete_at(int index) {
347
assert(0 <= index && index < _len, "illegal index");
348
if (index < --_len) {
349
// Replace removed element with last one.
350
_data[index] = _data[_len];
351
}
352
}
353
354
// inserts the given element before the element at index i
355
void insert_before(const int idx, const E& elem) {
356
assert(0 <= idx && idx <= _len, "illegal index");
357
check_nesting();
358
if (_len == _max) grow(_len);
359
for (int j = _len - 1; j >= idx; j--) {
360
_data[j + 1] = _data[j];
361
}
362
_len++;
363
_data[idx] = elem;
364
}
365
366
void appendAll(const GrowableArray<E>* l) {
367
for (int i = 0; i < l->_len; i++) {
368
raw_at_put_grow(_len, l->_data[i], E());
369
}
370
}
371
372
void sort(int f(E*,E*)) {
373
qsort(_data, length(), sizeof(E), (_sort_Fn)f);
374
}
375
// sort by fixed-stride sub arrays:
376
void sort(int f(E*,E*), int stride) {
377
qsort(_data, length() / stride, sizeof(E) * stride, (_sort_Fn)f);
378
}
379
380
// Binary search and insertion utility. Search array for element
381
// matching key according to the static compare function. Insert
382
// that element is not already in the list. Assumes the list is
383
// already sorted according to compare function.
384
template <int compare(const E&, const E&)> E insert_sorted(const E& key) {
385
bool found;
386
int location = find_sorted<E, compare>(key, found);
387
if (!found) {
388
insert_before(location, key);
389
}
390
return at(location);
391
}
392
393
template <typename K, int compare(const K&, const E&)> int find_sorted(const K& key, bool& found) {
394
found = false;
395
int min = 0;
396
int max = length() - 1;
397
398
while (max >= min) {
399
int mid = (int)(((uint)max + min) / 2);
400
E value = at(mid);
401
int diff = compare(key, value);
402
if (diff > 0) {
403
min = mid + 1;
404
} else if (diff < 0) {
405
max = mid - 1;
406
} else {
407
found = true;
408
return mid;
409
}
410
}
411
return min;
412
}
413
};
414
415
// Global GrowableArray methods (one instance in the library per each 'E' type).
416
417
template<class E> void GrowableArray<E>::grow(int j) {
418
// grow the array by doubling its size (amortized growth)
419
int old_max = _max;
420
if (_max == 0) _max = 1; // prevent endless loop
421
while (j >= _max) _max = _max*2;
422
// j < _max
423
E* newData = (E*)raw_allocate(sizeof(E));
424
int i = 0;
425
for ( ; i < _len; i++) ::new ((void*)&newData[i]) E(_data[i]);
426
// Needed for Visual Studio 2012 and older
427
#ifdef _MSC_VER
428
#pragma warning(suppress: 4345)
429
#endif
430
for ( ; i < _max; i++) ::new ((void*)&newData[i]) E();
431
for (i = 0; i < old_max; i++) _data[i].~E();
432
if (on_C_heap() && _data != NULL) {
433
FreeHeap(_data);
434
}
435
_data = newData;
436
}
437
438
template<class E> void GrowableArray<E>::raw_at_put_grow(int i, const E& p, const E& fill) {
439
if (i >= _len) {
440
if (i >= _max) grow(i);
441
for (int j = _len; j < i; j++)
442
_data[j] = fill;
443
_len = i+1;
444
}
445
_data[i] = p;
446
}
447
448
// This function clears and deallocate the data in the growable array that
449
// has been allocated on the C heap. It's not public - called by the
450
// destructor.
451
template<class E> void GrowableArray<E>::clear_and_deallocate() {
452
assert(on_C_heap(),
453
"clear_and_deallocate should only be called when on C heap");
454
clear();
455
if (_data != NULL) {
456
for (int i = 0; i < _max; i++) _data[i].~E();
457
FreeHeap(_data);
458
_data = NULL;
459
}
460
}
461
462
template<class E> void GrowableArray<E>::print() {
463
tty->print("Growable Array " INTPTR_FORMAT, this);
464
tty->print(": length %ld (_max %ld) { ", _len, _max);
465
for (int i = 0; i < _len; i++) tty->print(INTPTR_FORMAT " ", *(intptr_t*)&(_data[i]));
466
tty->print("}\n");
467
}
468
469
// Custom STL-style iterator to iterate over GrowableArrays
470
// It is constructed by invoking GrowableArray::begin() and GrowableArray::end()
471
template<class E> class GrowableArrayIterator : public StackObj {
472
friend class GrowableArray<E>;
473
template<class F, class UnaryPredicate> friend class GrowableArrayFilterIterator;
474
475
private:
476
const GrowableArray<E>* _array; // GrowableArray we iterate over
477
int _position; // The current position in the GrowableArray
478
479
// Private constructor used in GrowableArray::begin() and GrowableArray::end()
480
GrowableArrayIterator(const GrowableArray<E>* array, int position) : _array(array), _position(position) {
481
assert(0 <= position && position <= _array->length(), "illegal position");
482
}
483
484
public:
485
GrowableArrayIterator<E>& operator++() { ++_position; return *this; }
486
E operator*() { return _array->at(_position); }
487
488
bool operator==(const GrowableArrayIterator<E>& rhs) {
489
assert(_array == rhs._array, "iterator belongs to different array");
490
return _position == rhs._position;
491
}
492
493
bool operator!=(const GrowableArrayIterator<E>& rhs) {
494
assert(_array == rhs._array, "iterator belongs to different array");
495
return _position != rhs._position;
496
}
497
};
498
499
// Custom STL-style iterator to iterate over elements of a GrowableArray that satisfy a given predicate
500
template<class E, class UnaryPredicate> class GrowableArrayFilterIterator : public StackObj {
501
friend class GrowableArray<E>;
502
503
private:
504
const GrowableArray<E>* _array; // GrowableArray we iterate over
505
int _position; // Current position in the GrowableArray
506
UnaryPredicate _predicate; // Unary predicate the elements of the GrowableArray should satisfy
507
508
public:
509
GrowableArrayFilterIterator(const GrowableArrayIterator<E>& begin, UnaryPredicate filter_predicate)
510
: _array(begin._array), _position(begin._position), _predicate(filter_predicate) {
511
// Advance to first element satisfying the predicate
512
while(_position != _array->length() && !_predicate(_array->at(_position))) {
513
++_position;
514
}
515
}
516
517
GrowableArrayFilterIterator<E, UnaryPredicate>& operator++() {
518
do {
519
// Advance to next element satisfying the predicate
520
++_position;
521
} while(_position != _array->length() && !_predicate(_array->at(_position)));
522
return *this;
523
}
524
525
E operator*() { return _array->at(_position); }
526
527
bool operator==(const GrowableArrayIterator<E>& rhs) {
528
assert(_array == rhs._array, "iterator belongs to different array");
529
return _position == rhs._position;
530
}
531
532
bool operator!=(const GrowableArrayIterator<E>& rhs) {
533
assert(_array == rhs._array, "iterator belongs to different array");
534
return _position != rhs._position;
535
}
536
537
bool operator==(const GrowableArrayFilterIterator<E, UnaryPredicate>& rhs) {
538
assert(_array == rhs._array, "iterator belongs to different array");
539
return _position == rhs._position;
540
}
541
542
bool operator!=(const GrowableArrayFilterIterator<E, UnaryPredicate>& rhs) {
543
assert(_array == rhs._array, "iterator belongs to different array");
544
return _position != rhs._position;
545
}
546
};
547
548
#endif // SHARE_VM_UTILITIES_GROWABLEARRAY_HPP
549
550