Thu, 20 Nov 2008 16:56:09 -0800
6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa
1 /*
2 * Copyright 2000-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
25 // correct linkage required to compile w/o warnings
26 // (must be on file level - cannot be local)
27 extern "C" { typedef int (*ftype)(const void*, const void*); }
30 class ResourceArray: public ResourceObj {
31 protected:
32 int _length; // the number of array elements
33 void* _data; // the array memory
34 #ifdef ASSERT
35 int _nesting; // the resource area nesting level
36 #endif
38 // creation
39 ResourceArray() {
40 _length = 0;
41 _data = NULL;
42 DEBUG_ONLY(init_nesting();)
43 // client may call initialize, at most once
44 }
47 ResourceArray(size_t esize, int length) {
48 DEBUG_ONLY(_data = NULL);
49 initialize(esize, length);
50 }
52 void initialize(size_t esize, int length) {
53 assert(length >= 0, "illegal length");
54 assert(_data == NULL, "must be new object");
55 _length = length;
56 _data = resource_allocate_bytes(esize * length);
57 DEBUG_ONLY(init_nesting();)
58 }
60 #ifdef ASSERT
61 void init_nesting();
62 #endif
64 // helper functions
65 void sort (size_t esize, ftype f); // sort the array
66 void expand (size_t esize, int i, int& size);// expand the array to include slot i
67 void remove_at(size_t esize, int i); // remove the element in slot i
69 public:
70 // standard operations
71 int length() const { return _length; }
72 bool is_empty() const { return length() == 0; }
73 };
76 class CHeapArray: public CHeapObj {
77 protected:
78 int _length; // the number of array elements
79 void* _data; // the array memory
81 // creation
82 CHeapArray() {
83 _length = 0;
84 _data = NULL;
85 }
88 CHeapArray(size_t esize, int length) {
89 assert(length >= 0, "illegal length");
90 _length = length;
91 _data = (void*) NEW_C_HEAP_ARRAY(char *, esize * length);
92 }
94 #ifdef ASSERT
95 void init_nesting();
96 #endif
98 // helper functions
99 void sort (size_t esize, ftype f); // sort the array
100 void expand (size_t esize, int i, int& size);// expand the array to include slot i
101 void remove_at(size_t esize, int i); // remove the element in slot i
103 public:
104 // standard operations
105 int length() const { return _length; }
106 bool is_empty() const { return length() == 0; }
107 };
109 #define define_generic_array(array_name,element_type, base_class) \
110 class array_name: public base_class { \
111 protected: \
112 typedef element_type etype; \
113 enum { esize = sizeof(etype) }; \
114 \
115 void base_remove_at(size_t size, int i) { base_class::remove_at(size, i); } \
116 \
117 public: \
118 /* creation */ \
119 array_name() : base_class() {} \
120 array_name(const int length) : base_class(esize, length) {} \
121 array_name(const int length, const etype fx) { initialize(length, fx); } \
122 void initialize(const int length) { base_class::initialize(esize, length); } \
123 void initialize(const int length, const etype fx) { \
124 initialize(length); \
125 for (int i = 0; i < length; i++) ((etype*)_data)[i] = fx; \
126 } \
127 \
128 /* standard operations */ \
129 etype& operator [] (const int i) const { \
130 assert(0 <= i && i < length(), "index out of bounds"); \
131 return ((etype*)_data)[i]; \
132 } \
133 \
134 int index_of(const etype x) const { \
135 int i = length(); \
136 while (i-- > 0 && ((etype*)_data)[i] != x) ; \
137 /* i < 0 || ((etype*)_data)_data[i] == x */ \
138 return i; \
139 } \
140 \
141 void sort(int f(etype*, etype*)) { base_class::sort(esize, (ftype)f); } \
142 bool contains(const etype x) const { return index_of(x) >= 0; } \
143 \
144 /* deprecated operations - for compatibility with GrowableArray only */ \
145 etype at(const int i) const { return (*this)[i]; } \
146 void at_put(const int i, const etype x) { (*this)[i] = x; } \
147 etype* adr_at(const int i) { return &(*this)[i]; } \
148 int find(const etype x) { return index_of(x); } \
149 }; \
152 #define define_array(array_name,element_type) \
153 define_generic_array(array_name, element_type, ResourceArray)
156 #define define_stack(stack_name,array_name) \
157 class stack_name: public array_name { \
158 protected: \
159 int _size; \
160 \
161 void grow(const int i, const etype fx) { \
162 assert(i >= length(), "index too small"); \
163 if (i >= size()) expand(esize, i, _size); \
164 for (int j = length(); j <= i; j++) ((etype*)_data)[j] = fx; \
165 _length = i+1; \
166 } \
167 \
168 public: \
169 /* creation */ \
170 stack_name() : array_name() { _size = 0; } \
171 stack_name(const int size) { initialize(size); } \
172 stack_name(const int size, const etype fx) { initialize(size, fx); } \
173 void initialize(const int size, const etype fx) { \
174 _size = size; \
175 array_name::initialize(size, fx); \
176 /* _length == size, allocation and size are the same */ \
177 } \
178 void initialize(const int size) { \
179 _size = size; \
180 array_name::initialize(size); \
181 _length = 0; /* reset length to zero; _size records the allocation */ \
182 } \
183 \
184 /* standard operations */ \
185 int size() const { return _size; } \
186 \
187 int push(const etype x) { \
188 int len = length(); \
189 if (len >= size()) expand(esize, len, _size); \
190 ((etype*)_data)[len] = x; \
191 _length = len+1; \
192 return len; \
193 } \
194 \
195 etype pop() { \
196 assert(!is_empty(), "stack is empty"); \
197 return ((etype*)_data)[--_length]; \
198 } \
199 \
200 etype top() const { \
201 assert(!is_empty(), "stack is empty"); \
202 return ((etype*)_data)[length() - 1]; \
203 } \
204 \
205 void push_all(const stack_name* stack) { \
206 const int l = stack->length(); \
207 for (int i = 0; i < l; i++) push(((etype*)(stack->_data))[i]); \
208 } \
209 \
210 etype at_grow(const int i, const etype fx) { \
211 if (i >= length()) grow(i, fx); \
212 return ((etype*)_data)[i]; \
213 } \
214 \
215 void at_put_grow(const int i, const etype x, const etype fx) { \
216 if (i >= length()) grow(i, fx); \
217 ((etype*)_data)[i] = x; \
218 } \
219 \
220 void truncate(const int length) { \
221 assert(0 <= length && length <= this->length(), "illegal length"); \
222 _length = length; \
223 } \
224 \
225 void remove_at(int i) { base_remove_at(esize, i); } \
226 void remove(etype x) { remove_at(index_of(x)); } \
227 \
228 /* inserts the given element before the element at index i */ \
229 void insert_before(const int i, const etype el) { \
230 int len = length(); \
231 int new_length = len + 1; \
232 if (new_length >= size()) expand(esize, new_length, _size); \
233 for (int j = len - 1; j >= i; j--) { \
234 ((etype*)_data)[j + 1] = ((etype*)_data)[j]; \
235 } \
236 _length = new_length; \
237 at_put(i, el); \
238 } \
239 \
240 /* inserts contents of the given stack before the element at index i */ \
241 void insert_before(const int i, const stack_name *st) { \
242 if (st->length() == 0) return; \
243 int len = length(); \
244 int st_len = st->length(); \
245 int new_length = len + st_len; \
246 if (new_length >= size()) expand(esize, new_length, _size); \
247 int j; \
248 for (j = len - 1; j >= i; j--) { \
249 ((etype*)_data)[j + st_len] = ((etype*)_data)[j]; \
250 } \
251 for (j = 0; j < st_len; j++) { \
252 ((etype*)_data)[i + j] = ((etype*)st->_data)[j]; \
253 } \
254 _length = new_length; \
255 } \
256 \
257 /* deprecated operations - for compatibility with GrowableArray only */ \
258 int capacity() const { return size(); } \
259 void clear() { truncate(0); } \
260 void trunc_to(const int length) { truncate(length); } \
261 int append(const etype x) { return push(x); } \
262 void appendAll(const stack_name* stack) { push_all(stack); } \
263 etype last() const { return top(); } \
264 }; \
267 #define define_resource_list(element_type) \
268 define_generic_array(element_type##Array, element_type, ResourceArray) \
269 define_stack(element_type##List, element_type##Array)
271 #define define_resource_pointer_list(element_type) \
272 define_generic_array(element_type##Array, element_type *, ResourceArray) \
273 define_stack(element_type##List, element_type##Array)
275 #define define_c_heap_list(element_type) \
276 define_generic_array(element_type##Array, element_type, CHeapArray) \
277 define_stack(element_type##List, element_type##Array)
279 #define define_c_heap_pointer_list(element_type) \
280 define_generic_array(element_type##Array, element_type *, CHeapArray) \
281 define_stack(element_type##List, element_type##Array)
284 // Arrays for basic types
286 define_array(boolArray, bool) define_stack(boolStack, boolArray)
287 define_array(intArray , int ) define_stack(intStack , intArray )