Mercurial > hg > truffle
annotate src/share/vm/utilities/taskqueue.hpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | 5f429ee79634 |
children | 8b10f48633dc |
rev | line source |
---|---|
0 | 1 /* |
1638 | 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1311
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1311
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1311
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1665 | 25 // Simple TaskQueue stats that are collected by default in debug builds. |
26 | |
27 #if !defined(TASKQUEUE_STATS) && defined(ASSERT) | |
28 #define TASKQUEUE_STATS 1 | |
29 #elif !defined(TASKQUEUE_STATS) | |
30 #define TASKQUEUE_STATS 0 | |
31 #endif | |
32 | |
33 #if TASKQUEUE_STATS | |
34 #define TASKQUEUE_STATS_ONLY(code) code | |
35 #else | |
36 #define TASKQUEUE_STATS_ONLY(code) | |
37 #endif // TASKQUEUE_STATS | |
38 | |
39 #if TASKQUEUE_STATS | |
40 class TaskQueueStats { | |
41 public: | |
42 enum StatId { | |
43 push, // number of taskqueue pushes | |
44 pop, // number of taskqueue pops | |
45 pop_slow, // subset of taskqueue pops that were done slow-path | |
46 steal_attempt, // number of taskqueue steal attempts | |
47 steal, // number of taskqueue steals | |
48 overflow, // number of overflow pushes | |
49 overflow_max_len, // max length of overflow stack | |
50 last_stat_id | |
51 }; | |
52 | |
53 public: | |
54 inline TaskQueueStats() { reset(); } | |
55 | |
56 inline void record_push() { ++_stats[push]; } | |
57 inline void record_pop() { ++_stats[pop]; } | |
58 inline void record_pop_slow() { record_pop(); ++_stats[pop_slow]; } | |
59 inline void record_steal(bool success); | |
60 inline void record_overflow(size_t new_length); | |
61 | |
1709 | 62 TaskQueueStats & operator +=(const TaskQueueStats & addend); |
63 | |
1665 | 64 inline size_t get(StatId id) const { return _stats[id]; } |
65 inline const size_t* get() const { return _stats; } | |
66 | |
67 inline void reset(); | |
68 | |
1709 | 69 // Print the specified line of the header (does not include a line separator). |
1665 | 70 static void print_header(unsigned int line, outputStream* const stream = tty, |
71 unsigned int width = 10); | |
1709 | 72 // Print the statistics (does not include a line separator). |
1665 | 73 void print(outputStream* const stream = tty, unsigned int width = 10) const; |
74 | |
1709 | 75 DEBUG_ONLY(void verify() const;) |
76 | |
1665 | 77 private: |
78 size_t _stats[last_stat_id]; | |
79 static const char * const _names[last_stat_id]; | |
80 }; | |
81 | |
82 void TaskQueueStats::record_steal(bool success) { | |
83 ++_stats[steal_attempt]; | |
84 if (success) ++_stats[steal]; | |
85 } | |
86 | |
87 void TaskQueueStats::record_overflow(size_t new_len) { | |
88 ++_stats[overflow]; | |
89 if (new_len > _stats[overflow_max_len]) _stats[overflow_max_len] = new_len; | |
90 } | |
91 | |
92 void TaskQueueStats::reset() { | |
93 memset(_stats, 0, sizeof(_stats)); | |
94 } | |
95 #endif // TASKQUEUE_STATS | |
96 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
97 template <unsigned int N> |
0 | 98 class TaskQueueSuper: public CHeapObj { |
99 protected: | |
907 | 100 // Internal type for indexing the queue; also used for the tag. |
101 typedef NOT_LP64(uint16_t) LP64_ONLY(uint32_t) idx_t; | |
102 | |
103 // The first free element after the last one pushed (mod N). | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
104 volatile uint _bottom; |
0 | 105 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
106 enum { MOD_N_MASK = N - 1 }; |
907 | 107 |
108 class Age { | |
109 public: | |
110 Age(size_t data = 0) { _data = data; } | |
111 Age(const Age& age) { _data = age._data; } | |
112 Age(idx_t top, idx_t tag) { _fields._top = top; _fields._tag = tag; } | |
0 | 113 |
907 | 114 Age get() const volatile { return _data; } |
115 void set(Age age) volatile { _data = age._data; } | |
116 | |
117 idx_t top() const volatile { return _fields._top; } | |
118 idx_t tag() const volatile { return _fields._tag; } | |
0 | 119 |
907 | 120 // Increment top; if it wraps, increment tag also. |
121 void increment() { | |
122 _fields._top = increment_index(_fields._top); | |
123 if (_fields._top == 0) ++_fields._tag; | |
124 } | |
0 | 125 |
907 | 126 Age cmpxchg(const Age new_age, const Age old_age) volatile { |
127 return (size_t) Atomic::cmpxchg_ptr((intptr_t)new_age._data, | |
128 (volatile intptr_t *)&_data, | |
129 (intptr_t)old_age._data); | |
130 } | |
131 | |
132 bool operator ==(const Age& other) const { return _data == other._data; } | |
0 | 133 |
907 | 134 private: |
135 struct fields { | |
136 idx_t _top; | |
137 idx_t _tag; | |
138 }; | |
139 union { | |
140 size_t _data; | |
141 fields _fields; | |
142 }; | |
0 | 143 }; |
907 | 144 |
145 volatile Age _age; | |
146 | |
147 // These both operate mod N. | |
148 static uint increment_index(uint ind) { | |
149 return (ind + 1) & MOD_N_MASK; | |
0 | 150 } |
907 | 151 static uint decrement_index(uint ind) { |
152 return (ind - 1) & MOD_N_MASK; | |
0 | 153 } |
154 | |
907 | 155 // Returns a number in the range [0..N). If the result is "N-1", it should be |
156 // interpreted as 0. | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
157 uint dirty_size(uint bot, uint top) const { |
907 | 158 return (bot - top) & MOD_N_MASK; |
0 | 159 } |
160 | |
161 // Returns the size corresponding to the given "bot" and "top". | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
162 uint size(uint bot, uint top) const { |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
163 uint sz = dirty_size(bot, top); |
907 | 164 // Has the queue "wrapped", so that bottom is less than top? There's a |
165 // complicated special case here. A pair of threads could perform pop_local | |
166 // and pop_global operations concurrently, starting from a state in which | |
167 // _bottom == _top+1. The pop_local could succeed in decrementing _bottom, | |
168 // and the pop_global in incrementing _top (in which case the pop_global | |
169 // will be awarded the contested queue element.) The resulting state must | |
170 // be interpreted as an empty queue. (We only need to worry about one such | |
171 // event: only the queue owner performs pop_local's, and several concurrent | |
172 // threads attempting to perform the pop_global will all perform the same | |
173 // CAS, and only one can succeed.) Any stealing thread that reads after | |
174 // either the increment or decrement will see an empty queue, and will not | |
175 // join the competitors. The "sz == -1 || sz == N-1" state will not be | |
176 // modified by concurrent queues, so the owner thread can reset the state to | |
177 // _bottom == top so subsequent pushes will be performed normally. | |
178 return (sz == N - 1) ? 0 : sz; | |
0 | 179 } |
180 | |
181 public: | |
182 TaskQueueSuper() : _bottom(0), _age() {} | |
183 | |
1638 | 184 // Return true if the TaskQueue contains/does not contain any tasks. |
185 bool peek() const { return _bottom != _age.top(); } | |
186 bool is_empty() const { return size() == 0; } | |
0 | 187 |
188 // Return an estimate of the number of elements in the queue. | |
189 // The "careful" version admits the possibility of pop_local/pop_global | |
190 // races. | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
191 uint size() const { |
907 | 192 return size(_bottom, _age.top()); |
0 | 193 } |
194 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
195 uint dirty_size() const { |
907 | 196 return dirty_size(_bottom, _age.top()); |
0 | 197 } |
198 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
199 void set_empty() { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
200 _bottom = 0; |
907 | 201 _age.set(0); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
202 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
203 |
0 | 204 // Maximum number of elements allowed in the queue. This is two less |
205 // than the actual queue size, for somewhat complicated reasons. | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
206 uint max_elems() const { return N - 2; } |
1284 | 207 |
208 // Total size of queue. | |
209 static const uint total_size() { return N; } | |
1665 | 210 |
211 TASKQUEUE_STATS_ONLY(TaskQueueStats stats;) | |
0 | 212 }; |
213 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
214 template<class E, unsigned int N = TASKQUEUE_SIZE> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
215 class GenericTaskQueue: public TaskQueueSuper<N> { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
216 protected: |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
217 typedef typename TaskQueueSuper<N>::Age Age; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
218 typedef typename TaskQueueSuper<N>::idx_t idx_t; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
219 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
220 using TaskQueueSuper<N>::_bottom; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
221 using TaskQueueSuper<N>::_age; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
222 using TaskQueueSuper<N>::increment_index; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
223 using TaskQueueSuper<N>::decrement_index; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
224 using TaskQueueSuper<N>::dirty_size; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
225 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
226 public: |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
227 using TaskQueueSuper<N>::max_elems; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
228 using TaskQueueSuper<N>::size; |
1665 | 229 TASKQUEUE_STATS_ONLY(using TaskQueueSuper<N>::stats;) |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
230 |
0 | 231 private: |
232 // Slow paths for push, pop_local. (pop_global has no fast path.) | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
233 bool push_slow(E t, uint dirty_n_elems); |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
234 bool pop_local_slow(uint localBot, Age oldAge); |
0 | 235 |
236 public: | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
237 typedef E element_type; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
238 |
0 | 239 // Initializes the queue to empty. |
240 GenericTaskQueue(); | |
241 | |
242 void initialize(); | |
243 | |
1638 | 244 // Push the task "t" on the queue. Returns "false" iff the queue is full. |
0 | 245 inline bool push(E t); |
246 | |
1638 | 247 // Attempts to claim a task from the "local" end of the queue (the most |
248 // recently pushed). If successful, returns true and sets t to the task; | |
249 // otherwise, returns false (the queue is empty). | |
0 | 250 inline bool pop_local(E& t); |
251 | |
1638 | 252 // Like pop_local(), but uses the "global" end of the queue (the least |
253 // recently pushed). | |
0 | 254 bool pop_global(E& t); |
255 | |
256 // Delete any resource associated with the queue. | |
257 ~GenericTaskQueue(); | |
258 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
259 // apply the closure to all elements in the task queue |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
260 void oops_do(OopClosure* f); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
261 |
0 | 262 private: |
263 // Element array. | |
264 volatile E* _elems; | |
265 }; | |
266 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
267 template<class E, unsigned int N> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
268 GenericTaskQueue<E, N>::GenericTaskQueue() { |
907 | 269 assert(sizeof(Age) == sizeof(size_t), "Depends on this."); |
0 | 270 } |
271 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
272 template<class E, unsigned int N> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
273 void GenericTaskQueue<E, N>::initialize() { |
907 | 274 _elems = NEW_C_HEAP_ARRAY(E, N); |
0 | 275 } |
276 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
277 template<class E, unsigned int N> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
278 void GenericTaskQueue<E, N>::oops_do(OopClosure* f) { |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
279 // tty->print_cr("START OopTaskQueue::oops_do"); |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
280 uint iters = size(); |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
281 uint index = _bottom; |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
282 for (uint i = 0; i < iters; ++i) { |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
283 index = decrement_index(index); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
284 // tty->print_cr(" doing entry %d," INTPTR_T " -> " INTPTR_T, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
285 // index, &_elems[index], _elems[index]); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
286 E* t = (E*)&_elems[index]; // cast away volatility |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
287 oop* p = (oop*)t; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
288 assert((*t)->is_oop_or_null(), "Not an oop or null"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
289 f->do_oop(p); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
290 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
291 // tty->print_cr("END OopTaskQueue::oops_do"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
292 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
293 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
294 template<class E, unsigned int N> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
295 bool GenericTaskQueue<E, N>::push_slow(E t, uint dirty_n_elems) { |
907 | 296 if (dirty_n_elems == N - 1) { |
0 | 297 // Actually means 0, so do the push. |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
298 uint localBot = _bottom; |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
299 // g++ complains if the volatile result of the assignment is unused. |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
300 const_cast<E&>(_elems[localBot] = t); |
1024
2c03ce058f55
6888847: TaskQueue needs release_store() for correctness on RMO machines
bobv
parents:
907
diff
changeset
|
301 OrderAccess::release_store(&_bottom, increment_index(localBot)); |
1665 | 302 TASKQUEUE_STATS_ONLY(stats.record_push()); |
0 | 303 return true; |
907 | 304 } |
305 return false; | |
0 | 306 } |
307 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
308 template<class E, unsigned int N> |
1665 | 309 bool GenericTaskQueue<E, N>::pop_local_slow(uint localBot, Age oldAge) { |
0 | 310 // This queue was observed to contain exactly one element; either this |
311 // thread will claim it, or a competing "pop_global". In either case, | |
312 // the queue will be logically empty afterwards. Create a new Age value | |
313 // that represents the empty queue for the given value of "_bottom". (We | |
314 // must also increment "tag" because of the case where "bottom == 1", | |
315 // "top == 0". A pop_global could read the queue element in that case, | |
316 // then have the owner thread do a pop followed by another push. Without | |
317 // the incrementing of "tag", the pop_global's CAS could succeed, | |
318 // allowing it to believe it has claimed the stale element.) | |
907 | 319 Age newAge((idx_t)localBot, oldAge.tag() + 1); |
0 | 320 // Perhaps a competing pop_global has already incremented "top", in which |
321 // case it wins the element. | |
322 if (localBot == oldAge.top()) { | |
323 // No competing pop_global has yet incremented "top"; we'll try to | |
324 // install new_age, thus claiming the element. | |
907 | 325 Age tempAge = _age.cmpxchg(newAge, oldAge); |
0 | 326 if (tempAge == oldAge) { |
327 // We win. | |
907 | 328 assert(dirty_size(localBot, _age.top()) != N - 1, "sanity"); |
1665 | 329 TASKQUEUE_STATS_ONLY(stats.record_pop_slow()); |
0 | 330 return true; |
331 } | |
332 } | |
907 | 333 // We lose; a completing pop_global gets the element. But the queue is empty |
334 // and top is greater than bottom. Fix this representation of the empty queue | |
335 // to become the canonical one. | |
336 _age.set(newAge); | |
337 assert(dirty_size(localBot, _age.top()) != N - 1, "sanity"); | |
0 | 338 return false; |
339 } | |
340 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
341 template<class E, unsigned int N> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
342 bool GenericTaskQueue<E, N>::pop_global(E& t) { |
907 | 343 Age oldAge = _age.get(); |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
344 uint localBot = _bottom; |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
345 uint n_elems = size(localBot, oldAge.top()); |
0 | 346 if (n_elems == 0) { |
347 return false; | |
348 } | |
907 | 349 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
350 const_cast<E&>(t = _elems[oldAge.top()]); |
907 | 351 Age newAge(oldAge); |
352 newAge.increment(); | |
353 Age resAge = _age.cmpxchg(newAge, oldAge); | |
354 | |
0 | 355 // Note that using "_bottom" here might fail, since a pop_local might |
356 // have decremented it. | |
907 | 357 assert(dirty_size(localBot, newAge.top()) != N - 1, "sanity"); |
358 return resAge == oldAge; | |
0 | 359 } |
360 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
361 template<class E, unsigned int N> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
362 GenericTaskQueue<E, N>::~GenericTaskQueue() { |
0 | 363 FREE_C_HEAP_ARRAY(E, _elems); |
364 } | |
365 | |
1638 | 366 // OverflowTaskQueue is a TaskQueue that also includes an overflow stack for |
367 // elements that do not fit in the TaskQueue. | |
368 // | |
369 // Three methods from super classes are overridden: | |
370 // | |
371 // initialize() - initialize the super classes and create the overflow stack | |
372 // push() - push onto the task queue or, if that fails, onto the overflow stack | |
373 // is_empty() - return true if both the TaskQueue and overflow stack are empty | |
374 // | |
375 // Note that size() is not overridden--it returns the number of elements in the | |
376 // TaskQueue, and does not include the size of the overflow stack. This | |
377 // simplifies replacement of GenericTaskQueues with OverflowTaskQueues. | |
378 template<class E, unsigned int N = TASKQUEUE_SIZE> | |
379 class OverflowTaskQueue: public GenericTaskQueue<E, N> | |
380 { | |
381 public: | |
382 typedef GrowableArray<E> overflow_t; | |
383 typedef GenericTaskQueue<E, N> taskqueue_t; | |
384 | |
1665 | 385 TASKQUEUE_STATS_ONLY(using taskqueue_t::stats;) |
386 | |
1638 | 387 OverflowTaskQueue(); |
388 ~OverflowTaskQueue(); | |
389 void initialize(); | |
390 | |
391 inline overflow_t* overflow_stack() const { return _overflow_stack; } | |
392 | |
393 // Push task t onto the queue or onto the overflow stack. Return true. | |
394 inline bool push(E t); | |
395 | |
396 // Attempt to pop from the overflow stack; return true if anything was popped. | |
397 inline bool pop_overflow(E& t); | |
398 | |
399 inline bool taskqueue_empty() const { return taskqueue_t::is_empty(); } | |
400 inline bool overflow_empty() const { return overflow_stack()->is_empty(); } | |
401 inline bool is_empty() const { | |
402 return taskqueue_empty() && overflow_empty(); | |
403 } | |
404 | |
405 private: | |
406 overflow_t* _overflow_stack; | |
407 }; | |
408 | |
409 template <class E, unsigned int N> | |
410 OverflowTaskQueue<E, N>::OverflowTaskQueue() | |
411 { | |
412 _overflow_stack = NULL; | |
413 } | |
414 | |
415 template <class E, unsigned int N> | |
416 OverflowTaskQueue<E, N>::~OverflowTaskQueue() | |
417 { | |
418 if (_overflow_stack != NULL) { | |
419 delete _overflow_stack; | |
420 _overflow_stack = NULL; | |
421 } | |
422 } | |
423 | |
424 template <class E, unsigned int N> | |
425 void OverflowTaskQueue<E, N>::initialize() | |
426 { | |
427 taskqueue_t::initialize(); | |
428 assert(_overflow_stack == NULL, "memory leak"); | |
429 _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<E>(10, true); | |
430 } | |
431 | |
432 template <class E, unsigned int N> | |
433 bool OverflowTaskQueue<E, N>::push(E t) | |
434 { | |
435 if (!taskqueue_t::push(t)) { | |
436 overflow_stack()->push(t); | |
1665 | 437 TASKQUEUE_STATS_ONLY(stats.record_overflow(overflow_stack()->length())); |
1638 | 438 } |
439 return true; | |
440 } | |
441 | |
442 template <class E, unsigned int N> | |
443 bool OverflowTaskQueue<E, N>::pop_overflow(E& t) | |
444 { | |
445 if (overflow_empty()) return false; | |
446 t = overflow_stack()->pop(); | |
447 return true; | |
448 } | |
449 | |
0 | 450 class TaskQueueSetSuper: public CHeapObj { |
451 protected: | |
452 static int randomParkAndMiller(int* seed0); | |
453 public: | |
454 // Returns "true" if some TaskQueue in the set contains a task. | |
455 virtual bool peek() = 0; | |
456 }; | |
457 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
458 template<class T> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
459 class GenericTaskQueueSet: public TaskQueueSetSuper { |
0 | 460 private: |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
461 uint _n; |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
462 T** _queues; |
0 | 463 |
464 public: | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
465 typedef typename T::element_type E; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
466 |
0 | 467 GenericTaskQueueSet(int n) : _n(n) { |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
468 typedef T* GenericTaskQueuePtr; |
0 | 469 _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n); |
470 for (int i = 0; i < n; i++) { | |
471 _queues[i] = NULL; | |
472 } | |
473 } | |
474 | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
475 bool steal_1_random(uint queue_num, int* seed, E& t); |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
476 bool steal_best_of_2(uint queue_num, int* seed, E& t); |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
477 bool steal_best_of_all(uint queue_num, int* seed, E& t); |
0 | 478 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
479 void register_queue(uint i, T* q); |
0 | 480 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
481 T* queue(uint n); |
0 | 482 |
1638 | 483 // The thread with queue number "queue_num" (and whose random number seed is |
484 // at "seed") is trying to steal a task from some other queue. (It may try | |
485 // several queues, according to some configuration parameter.) If some steal | |
486 // succeeds, returns "true" and sets "t" to the stolen task, otherwise returns | |
487 // false. | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
488 bool steal(uint queue_num, int* seed, E& t); |
0 | 489 |
490 bool peek(); | |
491 }; | |
492 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
493 template<class T> void |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
494 GenericTaskQueueSet<T>::register_queue(uint i, T* q) { |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
495 assert(i < _n, "index out of range."); |
0 | 496 _queues[i] = q; |
497 } | |
498 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
499 template<class T> T* |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
500 GenericTaskQueueSet<T>::queue(uint i) { |
0 | 501 return _queues[i]; |
502 } | |
503 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
504 template<class T> bool |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
505 GenericTaskQueueSet<T>::steal(uint queue_num, int* seed, E& t) { |
1665 | 506 for (uint i = 0; i < 2 * _n; i++) { |
507 if (steal_best_of_2(queue_num, seed, t)) { | |
508 TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true)); | |
0 | 509 return true; |
1665 | 510 } |
511 } | |
512 TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(false)); | |
0 | 513 return false; |
514 } | |
515 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
516 template<class T> bool |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
517 GenericTaskQueueSet<T>::steal_best_of_all(uint queue_num, int* seed, E& t) { |
0 | 518 if (_n > 2) { |
519 int best_k; | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
520 uint best_sz = 0; |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
521 for (uint k = 0; k < _n; k++) { |
0 | 522 if (k == queue_num) continue; |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
523 uint sz = _queues[k]->size(); |
0 | 524 if (sz > best_sz) { |
525 best_sz = sz; | |
526 best_k = k; | |
527 } | |
528 } | |
529 return best_sz > 0 && _queues[best_k]->pop_global(t); | |
530 } else if (_n == 2) { | |
531 // Just try the other one. | |
532 int k = (queue_num + 1) % 2; | |
533 return _queues[k]->pop_global(t); | |
534 } else { | |
535 assert(_n == 1, "can't be zero."); | |
536 return false; | |
537 } | |
538 } | |
539 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
540 template<class T> bool |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
541 GenericTaskQueueSet<T>::steal_1_random(uint queue_num, int* seed, E& t) { |
0 | 542 if (_n > 2) { |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
543 uint k = queue_num; |
0 | 544 while (k == queue_num) k = randomParkAndMiller(seed) % _n; |
545 return _queues[2]->pop_global(t); | |
546 } else if (_n == 2) { | |
547 // Just try the other one. | |
548 int k = (queue_num + 1) % 2; | |
549 return _queues[k]->pop_global(t); | |
550 } else { | |
551 assert(_n == 1, "can't be zero."); | |
552 return false; | |
553 } | |
554 } | |
555 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
556 template<class T> bool |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
557 GenericTaskQueueSet<T>::steal_best_of_2(uint queue_num, int* seed, E& t) { |
0 | 558 if (_n > 2) { |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
559 uint k1 = queue_num; |
0 | 560 while (k1 == queue_num) k1 = randomParkAndMiller(seed) % _n; |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
561 uint k2 = queue_num; |
0 | 562 while (k2 == queue_num || k2 == k1) k2 = randomParkAndMiller(seed) % _n; |
563 // Sample both and try the larger. | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
564 uint sz1 = _queues[k1]->size(); |
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
565 uint sz2 = _queues[k2]->size(); |
0 | 566 if (sz2 > sz1) return _queues[k2]->pop_global(t); |
567 else return _queues[k1]->pop_global(t); | |
568 } else if (_n == 2) { | |
569 // Just try the other one. | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
570 uint k = (queue_num + 1) % 2; |
0 | 571 return _queues[k]->pop_global(t); |
572 } else { | |
573 assert(_n == 1, "can't be zero."); | |
574 return false; | |
575 } | |
576 } | |
577 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
578 template<class T> |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
579 bool GenericTaskQueueSet<T>::peek() { |
0 | 580 // Try all the queues. |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
581 for (uint j = 0; j < _n; j++) { |
0 | 582 if (_queues[j]->peek()) |
583 return true; | |
584 } | |
585 return false; | |
586 } | |
587 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
588 // When to terminate from the termination protocol. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
589 class TerminatorTerminator: public CHeapObj { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
590 public: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
591 virtual bool should_exit_termination() = 0; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
592 }; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
593 |
0 | 594 // A class to aid in the termination of a set of parallel tasks using |
595 // TaskQueueSet's for work stealing. | |
596 | |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
597 #undef TRACESPINNING |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
598 |
0 | 599 class ParallelTaskTerminator: public StackObj { |
600 private: | |
601 int _n_threads; | |
602 TaskQueueSetSuper* _queue_set; | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
603 int _offered_termination; |
0 | 604 |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
605 #ifdef TRACESPINNING |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
606 static uint _total_yields; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
607 static uint _total_spins; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
608 static uint _total_peeks; |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
609 #endif |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
610 |
0 | 611 bool peek_in_queue_set(); |
612 protected: | |
613 virtual void yield(); | |
614 void sleep(uint millis); | |
615 | |
616 public: | |
617 | |
618 // "n_threads" is the number of threads to be terminated. "queue_set" is a | |
619 // queue sets of work queues of other threads. | |
620 ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set); | |
621 | |
622 // The current thread has no work, and is ready to terminate if everyone | |
623 // else is. If returns "true", all threads are terminated. If returns | |
624 // "false", available work has been observed in one of the task queues, | |
625 // so the global task is not complete. | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
626 bool offer_termination() { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
627 return offer_termination(NULL); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
628 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
629 |
907 | 630 // As above, but it also terminates if the should_exit_termination() |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
631 // method of the terminator parameter returns true. If terminator is |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
632 // NULL, then it is ignored. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
633 bool offer_termination(TerminatorTerminator* terminator); |
0 | 634 |
635 // Reset the terminator, so that it may be reused again. | |
636 // The caller is responsible for ensuring that this is done | |
637 // in an MT-safe manner, once the previous round of use of | |
638 // the terminator is finished. | |
639 void reset_for_reuse(); | |
640 | |
546
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
641 #ifdef TRACESPINNING |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
642 static uint total_yields() { return _total_yields; } |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
643 static uint total_spins() { return _total_spins; } |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
644 static uint total_peeks() { return _total_peeks; } |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
645 static void print_termination_counts(); |
05c6d52fa7a9
6690928: Use spinning in combination with yields for workstealing termination.
jmasa
parents:
541
diff
changeset
|
646 #endif |
0 | 647 }; |
648 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
649 template<class E, unsigned int N> inline bool |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
650 GenericTaskQueue<E, N>::push(E t) { |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
651 uint localBot = _bottom; |
907 | 652 assert((localBot >= 0) && (localBot < N), "_bottom out of range."); |
653 idx_t top = _age.top(); | |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
654 uint dirty_n_elems = dirty_size(localBot, top); |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
655 assert(dirty_n_elems < N, "n_elems out of range."); |
0 | 656 if (dirty_n_elems < max_elems()) { |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
657 // g++ complains if the volatile result of the assignment is unused. |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
658 const_cast<E&>(_elems[localBot] = t); |
1024
2c03ce058f55
6888847: TaskQueue needs release_store() for correctness on RMO machines
bobv
parents:
907
diff
changeset
|
659 OrderAccess::release_store(&_bottom, increment_index(localBot)); |
1665 | 660 TASKQUEUE_STATS_ONLY(stats.record_push()); |
0 | 661 return true; |
662 } else { | |
663 return push_slow(t, dirty_n_elems); | |
664 } | |
665 } | |
666 | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
667 template<class E, unsigned int N> inline bool |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
668 GenericTaskQueue<E, N>::pop_local(E& t) { |
541
23673011938d
6787254: Work queue capacity can be increased substantially on some platforms
ysr
parents:
375
diff
changeset
|
669 uint localBot = _bottom; |
907 | 670 // This value cannot be N-1. That can only occur as a result of |
0 | 671 // the assignment to bottom in this method. If it does, this method |
1638 | 672 // resets the size to 0 before the next call (which is sequential, |
0 | 673 // since this is pop_local.) |
907 | 674 uint dirty_n_elems = dirty_size(localBot, _age.top()); |
675 assert(dirty_n_elems != N - 1, "Shouldn't be possible..."); | |
0 | 676 if (dirty_n_elems == 0) return false; |
677 localBot = decrement_index(localBot); | |
678 _bottom = localBot; | |
679 // This is necessary to prevent any read below from being reordered | |
680 // before the store just above. | |
681 OrderAccess::fence(); | |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
682 const_cast<E&>(t = _elems[localBot]); |
0 | 683 // This is a second read of "age"; the "size()" above is the first. |
684 // If there's still at least one element in the queue, based on the | |
685 // "_bottom" and "age" we've read, then there can be no interference with | |
686 // a "pop_global" operation, and we're done. | |
907 | 687 idx_t tp = _age.top(); // XXX |
0 | 688 if (size(localBot, tp) > 0) { |
907 | 689 assert(dirty_size(localBot, tp) != N - 1, "sanity"); |
1665 | 690 TASKQUEUE_STATS_ONLY(stats.record_pop()); |
0 | 691 return true; |
692 } else { | |
693 // Otherwise, the queue contained exactly one element; we take the slow | |
694 // path. | |
907 | 695 return pop_local_slow(localBot, _age.get()); |
0 | 696 } |
697 } | |
698 | |
1638 | 699 typedef GenericTaskQueue<oop> OopTaskQueue; |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
700 typedef GenericTaskQueueSet<OopTaskQueue> OopTaskQueueSet; |
0 | 701 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
702 #ifdef _MSC_VER |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
703 #pragma warning(push) |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
704 // warning C4522: multiple assignment operators specified |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
705 #pragma warning(disable:4522) |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
706 #endif |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
707 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
708 // This is a container class for either an oop* or a narrowOop*. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
709 // Both are pushed onto a task queue and the consumer will test is_narrow() |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
710 // to determine which should be processed. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
711 class StarTask { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
712 void* _holder; // either union oop* or narrowOop* |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
713 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
714 enum { COMPRESSED_OOP_MASK = 1 }; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
715 |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
716 public: |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
717 StarTask(narrowOop* p) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
718 assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
719 _holder = (void *)((uintptr_t)p | COMPRESSED_OOP_MASK); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
720 } |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
721 StarTask(oop* p) { |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
722 assert(((uintptr_t)p & COMPRESSED_OOP_MASK) == 0, "Information loss!"); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
723 _holder = (void*)p; |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
579
diff
changeset
|
724 } |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
725 StarTask() { _holder = NULL; } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
726 operator oop*() { return (oop*)_holder; } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
727 operator narrowOop*() { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
728 return (narrowOop*)((uintptr_t)_holder & ~COMPRESSED_OOP_MASK); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
729 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
730 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
731 StarTask& operator=(const StarTask& t) { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
732 _holder = t._holder; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
733 return *this; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
734 } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
735 volatile StarTask& operator=(const volatile StarTask& t) volatile { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
736 _holder = t._holder; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
737 return *this; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
738 } |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
739 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
740 bool is_narrow() const { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
741 return (((uintptr_t)_holder & COMPRESSED_OOP_MASK) != 0); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
742 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
743 }; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
744 |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
745 class ObjArrayTask |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
746 { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
747 public: |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
748 ObjArrayTask(oop o = NULL, int idx = 0): _obj(o), _index(idx) { } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
749 ObjArrayTask(oop o, size_t idx): _obj(o), _index(int(idx)) { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
750 assert(idx <= size_t(max_jint), "too big"); |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
751 } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
752 ObjArrayTask(const ObjArrayTask& t): _obj(t._obj), _index(t._index) { } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
753 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
754 ObjArrayTask& operator =(const ObjArrayTask& t) { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
755 _obj = t._obj; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
756 _index = t._index; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
757 return *this; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
758 } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
759 volatile ObjArrayTask& |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
760 operator =(const volatile ObjArrayTask& t) volatile { |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
761 _obj = t._obj; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
762 _index = t._index; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
763 return *this; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
764 } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
765 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
766 inline oop obj() const { return _obj; } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
767 inline int index() const { return _index; } |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
768 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
769 DEBUG_ONLY(bool is_valid() const); // Tasks to be pushed/popped must be valid. |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
770 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
771 private: |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
772 oop _obj; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
773 int _index; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
774 }; |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
775 |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
776 #ifdef _MSC_VER |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
777 #pragma warning(pop) |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
778 #endif |
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
779 |
1638 | 780 typedef OverflowTaskQueue<StarTask> OopStarTaskQueue; |
1311
2a1472c30599
4396719: Mark Sweep stack overflow on deeply nested Object arrays
jcoomes
parents:
1284
diff
changeset
|
781 typedef GenericTaskQueueSet<OopStarTaskQueue> OopStarTaskQueueSet; |
0 | 782 |
1638 | 783 typedef OverflowTaskQueue<size_t> RegionTaskQueue; |
784 typedef GenericTaskQueueSet<RegionTaskQueue> RegionTaskQueueSet; |