28 #include "memory/allocation.hpp" |
28 #include "memory/allocation.hpp" |
29 #include "memory/allocation.inline.hpp" |
29 #include "memory/allocation.inline.hpp" |
30 #include "memory/metaspace.hpp" |
30 #include "memory/metaspace.hpp" |
31 #include "runtime/orderAccess.hpp" |
31 #include "runtime/orderAccess.hpp" |
32 |
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 |
33 // Arrays for basic types |
297 |
34 typedef GrowableArray<int> intArray; |
298 define_array(boolArray, bool) define_stack(boolStack, boolArray) |
35 typedef GrowableArray<int> intStack; |
299 define_array(intArray , int ) define_stack(intStack , intArray ) |
36 typedef GrowableArray<bool> boolArray; |
|
37 typedef GrowableArray<bool> boolStack; |
300 |
38 |
301 // Array for metadata allocation |
39 // Array for metadata allocation |
302 |
40 |
303 template <typename T> |
41 template <typename T> |
304 class Array: public MetaspaceObj { |
42 class Array: public MetaspaceObj { |