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/array.hpp
32285 views
1
/*
2
* Copyright (c) 2000, 2018, 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_ARRAY_HPP
26
#define SHARE_VM_UTILITIES_ARRAY_HPP
27
28
#include "memory/allocation.hpp"
29
#include "memory/allocation.inline.hpp"
30
#include "memory/metaspace.hpp"
31
#include "runtime/orderAccess.hpp"
32
33
// correct linkage required to compile w/o warnings
34
// (must be on file level - cannot be local)
35
extern "C" { typedef int (*ftype)(const void*, const void*); }
36
37
38
class ResourceArray: public ResourceObj {
39
protected:
40
int _length; // the number of array elements
41
void* _data; // the array memory
42
#ifdef ASSERT
43
int _nesting; // the resource area nesting level
44
#endif
45
46
// creation
47
ResourceArray() {
48
_length = 0;
49
_data = NULL;
50
DEBUG_ONLY(init_nesting();)
51
// client may call initialize, at most once
52
}
53
54
55
ResourceArray(size_t esize, int length) {
56
DEBUG_ONLY(_data = NULL);
57
initialize(esize, length);
58
}
59
60
void initialize(size_t esize, int length) {
61
assert(length >= 0, "illegal length");
62
assert(StressRewriter || _data == NULL, "must be new object");
63
_length = length;
64
_data = resource_allocate_bytes(esize * length);
65
DEBUG_ONLY(init_nesting();)
66
}
67
68
#ifdef ASSERT
69
void init_nesting();
70
#endif
71
72
// helper functions
73
void sort (size_t esize, ftype f); // sort the array
74
void expand (size_t esize, int i, int& size);// expand the array to include slot i
75
void remove_at(size_t esize, int i); // remove the element in slot i
76
77
public:
78
// standard operations
79
int length() const { return _length; }
80
bool is_empty() const { return length() == 0; }
81
};
82
83
84
template <MEMFLAGS F>class CHeapArray: public CHeapObj<F> {
85
protected:
86
int _length; // the number of array elements
87
void* _data; // the array memory
88
89
// creation
90
CHeapArray() {
91
_length = 0;
92
_data = NULL;
93
}
94
95
96
CHeapArray(size_t esize, int length) {
97
assert(length >= 0, "illegal length");
98
_length = length;
99
_data = (void*) NEW_C_HEAP_ARRAY(char *, esize * length, F);
100
}
101
102
void initialize(size_t esize, int length) {
103
// In debug set array to 0?
104
}
105
106
#ifdef ASSERT
107
void init_nesting();
108
#endif
109
110
// helper functions
111
void sort (size_t esize, ftype f); // sort the array
112
void expand (size_t esize, int i, int& size);// expand the array to include slot i
113
void remove_at(size_t esize, int i); // remove the element in slot i
114
115
public:
116
// standard operations
117
int length() const { return _length; }
118
bool is_empty() const { return length() == 0; }
119
};
120
121
#define define_generic_array(array_name,element_type, base_class) \
122
class array_name: public base_class { \
123
protected: \
124
typedef element_type etype; \
125
enum { esize = sizeof(etype) }; \
126
\
127
void base_remove_at(size_t size, int i) { base_class::remove_at(size, i); } \
128
\
129
public: \
130
/* creation */ \
131
array_name() : base_class() {} \
132
explicit array_name(const int length) : base_class(esize, length) {} \
133
array_name(const int length, const etype fx) { initialize(length, fx); } \
134
void initialize(const int length) { base_class::initialize(esize, length); } \
135
void initialize(const int length, const etype fx) { \
136
initialize(length); \
137
for (int i = 0; i < length; i++) ((etype*)_data)[i] = fx; \
138
} \
139
\
140
/* standard operations */ \
141
etype& operator [] (const int i) const { \
142
assert(0 <= i && i < length(), "index out of bounds"); \
143
return ((etype*)_data)[i]; \
144
} \
145
\
146
int index_of(const etype x) const { \
147
int i = length(); \
148
while (i-- > 0 && ((etype*)_data)[i] != x) ; \
149
/* i < 0 || ((etype*)_data)_data[i] == x */ \
150
return i; \
151
} \
152
\
153
void sort(int f(etype*, etype*)) { base_class::sort(esize, (ftype)f); } \
154
bool contains(const etype x) const { return index_of(x) >= 0; } \
155
\
156
/* deprecated operations - for compatibility with GrowableArray only */ \
157
etype at(const int i) const { return (*this)[i]; } \
158
void at_put(const int i, const etype x) { (*this)[i] = x; } \
159
etype* adr_at(const int i) { return &(*this)[i]; } \
160
int find(const etype x) { return index_of(x); } \
161
}; \
162
163
164
#define define_array(array_name,element_type) \
165
define_generic_array(array_name, element_type, ResourceArray)
166
167
168
#define define_stack(stack_name,array_name) \
169
class stack_name: public array_name { \
170
protected: \
171
int _size; \
172
\
173
void grow(const int i, const etype fx) { \
174
assert(i >= length(), "index too small"); \
175
if (i >= size()) expand(esize, i, _size); \
176
for (int j = length(); j <= i; j++) ((etype*)_data)[j] = fx; \
177
_length = i+1; \
178
} \
179
\
180
public: \
181
/* creation */ \
182
stack_name() : array_name() { _size = 0; } \
183
stack_name(const int size) { initialize(size); } \
184
stack_name(const int size, const etype fx) { initialize(size, fx); } \
185
void initialize(const int size, const etype fx) { \
186
_size = size; \
187
array_name::initialize(size, fx); \
188
/* _length == size, allocation and size are the same */ \
189
} \
190
void initialize(const int size) { \
191
_size = size; \
192
array_name::initialize(size); \
193
_length = 0; /* reset length to zero; _size records the allocation */ \
194
} \
195
\
196
/* standard operations */ \
197
int size() const { return _size; } \
198
\
199
int push(const etype x) { \
200
int len = length(); \
201
if (len >= size()) expand(esize, len, _size); \
202
((etype*)_data)[len] = x; \
203
_length = len+1; \
204
return len; \
205
} \
206
\
207
etype pop() { \
208
assert(!is_empty(), "stack is empty"); \
209
return ((etype*)_data)[--_length]; \
210
} \
211
\
212
etype top() const { \
213
assert(!is_empty(), "stack is empty"); \
214
return ((etype*)_data)[length() - 1]; \
215
} \
216
\
217
void push_all(const stack_name* stack) { \
218
const int l = stack->length(); \
219
for (int i = 0; i < l; i++) push(((etype*)(stack->_data))[i]); \
220
} \
221
\
222
etype at_grow(const int i, const etype fx) { \
223
if (i >= length()) grow(i, fx); \
224
return ((etype*)_data)[i]; \
225
} \
226
\
227
void at_put_grow(const int i, const etype x, const etype fx) { \
228
if (i >= length()) grow(i, fx); \
229
((etype*)_data)[i] = x; \
230
} \
231
\
232
void truncate(const int length) { \
233
assert(0 <= length && length <= this->length(), "illegal length"); \
234
_length = length; \
235
} \
236
\
237
void remove_at(int i) { base_remove_at(esize, i); } \
238
void remove(etype x) { remove_at(index_of(x)); } \
239
\
240
/* inserts the given element before the element at index i */ \
241
void insert_before(const int i, const etype el) { \
242
int len = length(); \
243
int new_length = len + 1; \
244
if (new_length >= size()) expand(esize, new_length, _size); \
245
for (int j = len - 1; j >= i; j--) { \
246
((etype*)_data)[j + 1] = ((etype*)_data)[j]; \
247
} \
248
_length = new_length; \
249
at_put(i, el); \
250
} \
251
\
252
/* inserts contents of the given stack before the element at index i */ \
253
void insert_before(const int i, const stack_name *st) { \
254
if (st->length() == 0) return; \
255
int len = length(); \
256
int st_len = st->length(); \
257
int new_length = len + st_len; \
258
if (new_length >= size()) expand(esize, new_length, _size); \
259
int j; \
260
for (j = len - 1; j >= i; j--) { \
261
((etype*)_data)[j + st_len] = ((etype*)_data)[j]; \
262
} \
263
for (j = 0; j < st_len; j++) { \
264
((etype*)_data)[i + j] = ((etype*)st->_data)[j]; \
265
} \
266
_length = new_length; \
267
} \
268
\
269
/* deprecated operations - for compatibility with GrowableArray only */ \
270
int capacity() const { return size(); } \
271
void clear() { truncate(0); } \
272
void trunc_to(const int length) { truncate(length); } \
273
int append(const etype x) { return push(x); } \
274
void appendAll(const stack_name* stack) { push_all(stack); } \
275
etype last() const { return top(); } \
276
}; \
277
278
279
#define define_resource_list(element_type) \
280
define_generic_array(element_type##Array, element_type, ResourceArray) \
281
define_stack(element_type##List, element_type##Array)
282
283
#define define_resource_pointer_list(element_type) \
284
define_generic_array(element_type##Array, element_type *, ResourceArray) \
285
define_stack(element_type##List, element_type##Array)
286
287
#define define_c_heap_list(element_type) \
288
define_generic_array(element_type##Array, element_type, CHeapArray) \
289
define_stack(element_type##List, element_type##Array)
290
291
#define define_c_heap_pointer_list(element_type) \
292
define_generic_array(element_type##Array, element_type *, CHeapArray) \
293
define_stack(element_type##List, element_type##Array)
294
295
296
// Arrays for basic types
297
298
define_array(boolArray, bool) define_stack(boolStack, boolArray)
299
define_array(intArray , int ) define_stack(intStack , intArray )
300
301
// Array for metadata allocation
302
303
template <typename T>
304
class Array: public MetaspaceObj {
305
friend class MetadataFactory;
306
friend class VMStructs;
307
friend class MethodHandleCompiler; // special case
308
friend class WhiteBox;
309
protected:
310
int _length; // the number of array elements
311
T _data[1]; // the array memory
312
313
void initialize(int length) {
314
_length = length;
315
}
316
317
private:
318
// Turn off copy constructor and assignment operator.
319
Array(const Array<T>&);
320
void operator=(const Array<T>&);
321
322
void* operator new(size_t size, ClassLoaderData* loader_data, int length, bool read_only, TRAPS) throw() {
323
size_t word_size = Array::size(length);
324
return (void*) Metaspace::allocate(loader_data, word_size, read_only,
325
MetaspaceObj::array_type(sizeof(T)), THREAD);
326
}
327
328
static size_t byte_sizeof(int length) { return sizeof(Array<T>) + MAX2(length - 1, 0) * sizeof(T); }
329
330
// WhiteBox API helper.
331
// Can't distinguish between array of length 0 and length 1,
332
// will always return 0 in those cases.
333
static int bytes_to_length(size_t bytes) {
334
assert(is_size_aligned(bytes, BytesPerWord), "Must be, for now");
335
336
if (sizeof(Array<T>) >= bytes) {
337
return 0;
338
}
339
340
size_t left = bytes - sizeof(Array<T>);
341
assert(is_size_aligned(left, sizeof(T)), "Must be");
342
343
size_t elements = left / sizeof(T);
344
assert(elements <= (size_t)INT_MAX, err_msg("number of elements " SIZE_FORMAT "doesn't fit into an int.", elements));
345
346
int length = (int)elements;
347
348
assert((size_t)size(length) * BytesPerWord == bytes,
349
err_msg("Expected: " SIZE_FORMAT " got: " SIZE_FORMAT,
350
bytes, (size_t)size(length) * BytesPerWord));
351
352
return length;
353
}
354
355
explicit Array(int length) : _length(length) {
356
assert(length >= 0, "illegal length");
357
}
358
359
Array(int length, T init) : _length(length) {
360
assert(length >= 0, "illegal length");
361
for (int i = 0; i < length; i++) {
362
_data[i] = init;
363
}
364
}
365
366
public:
367
368
// standard operations
369
int length() const { return _length; }
370
T* data() { return _data; }
371
bool is_empty() const { return length() == 0; }
372
373
int index_of(const T& x) const {
374
int i = length();
375
while (i-- > 0 && _data[i] != x) ;
376
377
return i;
378
}
379
380
// sort the array.
381
bool contains(const T& x) const { return index_of(x) >= 0; }
382
383
T at(int i) const { assert(i >= 0 && i< _length, err_msg("oob: 0 <= %d < %d", i, _length)); return _data[i]; }
384
void at_put(const int i, const T& x) { assert(i >= 0 && i< _length, err_msg("oob: 0 <= %d < %d", i, _length)); _data[i] = x; }
385
T* adr_at(const int i) { assert(i >= 0 && i< _length, err_msg("oob: 0 <= %d < %d", i, _length)); return &_data[i]; }
386
int find(const T& x) { return index_of(x); }
387
388
T at_acquire(const int which) { return OrderAccess::load_acquire(adr_at(which)); }
389
void release_at_put(int which, T contents) { OrderAccess::release_store(adr_at(which), contents); }
390
391
static int size(int length) {
392
return align_size_up(byte_sizeof(length), BytesPerWord) / BytesPerWord;
393
}
394
395
int size() {
396
return size(_length);
397
}
398
399
static int length_offset_in_bytes() { return (int) (offset_of(Array<T>, _length)); }
400
// Note, this offset don't have to be wordSize aligned.
401
static int base_offset_in_bytes() { return (int) (offset_of(Array<T>, _data)); };
402
403
// FIXME: How to handle this?
404
void print_value_on(outputStream* st) const {
405
st->print("Array<T>(" INTPTR_FORMAT ")", p2i(this));
406
}
407
408
#ifndef PRODUCT
409
void print(outputStream* st) {
410
for (int i = 0; i< _length; i++) {
411
st->print_cr("%d: " INTPTR_FORMAT, i, (intptr_t)at(i));
412
}
413
}
414
void print() { print(tty); }
415
#endif // PRODUCT
416
};
417
418
419
#endif // SHARE_VM_UTILITIES_ARRAY_HPP
420
421