src/share/vm/utilities/taskqueue.hpp

changeset 9138
b56ab8e56604
parent 8860
43b19021a5a9
child 9756
2be326848943
equal deleted inserted replaced
9137:dc1769738300 9138:b56ab8e56604
109 class TaskQueueSuper: public CHeapObj<F> { 109 class TaskQueueSuper: public CHeapObj<F> {
110 protected: 110 protected:
111 // Internal type for indexing the queue; also used for the tag. 111 // Internal type for indexing the queue; also used for the tag.
112 typedef NOT_LP64(uint16_t) LP64_ONLY(uint32_t) idx_t; 112 typedef NOT_LP64(uint16_t) LP64_ONLY(uint32_t) idx_t;
113 113
114 #ifdef MIPS64 114 #ifdef MIPS
115 private: 115 private:
116 #endif 116 #endif
117 // The first free element after the last one pushed (mod N). 117 // The first free element after the last one pushed (mod N).
118 volatile uint _bottom; 118 volatile uint _bottom;
119 119
120 #ifdef MIPS64 120 #ifdef MIPS
121 protected: 121 protected:
122 inline uint get_bottom() const { 122 inline uint get_bottom() const {
123 return OrderAccess::load_acquire((volatile juint*)&_bottom); 123 return OrderAccess::load_acquire((volatile juint*)&_bottom);
124 } 124 }
125 125
134 public: 134 public:
135 Age(size_t data = 0) { _data = data; } 135 Age(size_t data = 0) { _data = data; }
136 Age(const Age& age) { _data = age._data; } 136 Age(const Age& age) { _data = age._data; }
137 Age(idx_t top, idx_t tag) { _fields._top = top; _fields._tag = tag; } 137 Age(idx_t top, idx_t tag) { _fields._top = top; _fields._tag = tag; }
138 138
139 #ifndef MIPS64 139 #ifndef MIPS
140 Age get() const volatile { return _data; } 140 Age get() const volatile { return _data; }
141 void set(Age age) volatile { _data = age._data; } 141 void set(Age age) volatile { _data = age._data; }
142 142
143 idx_t top() const volatile { return _fields._top; } 143 idx_t top() const volatile { return _fields._top; }
144 idx_t tag() const volatile { return _fields._tag; } 144 idx_t tag() const volatile { return _fields._tag; }
217 public: 217 public:
218 TaskQueueSuper() : _bottom(0), _age() {} 218 TaskQueueSuper() : _bottom(0), _age() {}
219 219
220 // Return true if the TaskQueue contains/does not contain any tasks. 220 // Return true if the TaskQueue contains/does not contain any tasks.
221 bool peek() const { 221 bool peek() const {
222 #ifdef MIPS64 222 #ifdef MIPS
223 return get_bottom() != _age.top(); 223 return get_bottom() != _age.top();
224 #else 224 #else
225 return _bottom != _age.top(); 225 return _bottom != _age.top();
226 #endif 226 #endif
227 } 227 }
229 229
230 // Return an estimate of the number of elements in the queue. 230 // Return an estimate of the number of elements in the queue.
231 // The "careful" version admits the possibility of pop_local/pop_global 231 // The "careful" version admits the possibility of pop_local/pop_global
232 // races. 232 // races.
233 uint size() const { 233 uint size() const {
234 #ifdef MIPS64 234 #ifdef MIPS
235 return size(get_bottom(), _age.top()); 235 return size(get_bottom(), _age.top());
236 #else 236 #else
237 return size(_bottom, _age.top()); 237 return size(_bottom, _age.top());
238 #endif 238 #endif
239 } 239 }
240 240
241 uint dirty_size() const { 241 uint dirty_size() const {
242 #ifdef MIPS64 242 #ifdef MIPS
243 return dirty_size(get_bottom(), _age.top()); 243 return dirty_size(get_bottom(), _age.top());
244 #else 244 #else
245 return dirty_size(_bottom, _age.top()); 245 return dirty_size(_bottom, _age.top());
246 #endif 246 #endif
247 } 247 }
248 248
249 void set_empty() { 249 void set_empty() {
250 #ifdef MIPS64 250 #ifdef MIPS
251 set_bottom(0); 251 set_bottom(0);
252 #else 252 #else
253 _bottom = 0; 253 _bottom = 0;
254 #endif 254 #endif
255 _age.set(0); 255 _age.set(0);
301 ArrayAllocator<E, F> _array_allocator; 301 ArrayAllocator<E, F> _array_allocator;
302 protected: 302 protected:
303 typedef typename TaskQueueSuper<N, F>::Age Age; 303 typedef typename TaskQueueSuper<N, F>::Age Age;
304 typedef typename TaskQueueSuper<N, F>::idx_t idx_t; 304 typedef typename TaskQueueSuper<N, F>::idx_t idx_t;
305 305
306 #ifndef MIPS64 306 #ifndef MIPS
307 using TaskQueueSuper<N, F>::_bottom; 307 using TaskQueueSuper<N, F>::_bottom;
308 #endif 308 #endif
309 using TaskQueueSuper<N, F>::_age; 309 using TaskQueueSuper<N, F>::_age;
310 using TaskQueueSuper<N, F>::increment_index; 310 using TaskQueueSuper<N, F>::increment_index;
311 using TaskQueueSuper<N, F>::decrement_index; 311 using TaskQueueSuper<N, F>::decrement_index;
367 367
368 template<class E, MEMFLAGS F, unsigned int N> 368 template<class E, MEMFLAGS F, unsigned int N>
369 void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) { 369 void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) {
370 // tty->print_cr("START OopTaskQueue::oops_do"); 370 // tty->print_cr("START OopTaskQueue::oops_do");
371 uint iters = size(); 371 uint iters = size();
372 #ifdef MIPS64 372 #ifdef MIPS
373 uint index = this->get_bottom(); 373 uint index = this->get_bottom();
374 #else 374 #else
375 uint index = _bottom; 375 uint index = _bottom;
376 #endif 376 #endif
377 for (uint i = 0; i < iters; ++i) { 377 for (uint i = 0; i < iters; ++i) {
388 388
389 template<class E, MEMFLAGS F, unsigned int N> 389 template<class E, MEMFLAGS F, unsigned int N>
390 bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) { 390 bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) {
391 if (dirty_n_elems == N - 1) { 391 if (dirty_n_elems == N - 1) {
392 // Actually means 0, so do the push. 392 // Actually means 0, so do the push.
393 #ifdef MIPS64 393 #ifdef MIPS
394 uint localBot = this->get_bottom(); 394 uint localBot = this->get_bottom();
395 #else 395 #else
396 uint localBot = _bottom; 396 uint localBot = _bottom;
397 #endif 397 #endif
398 // g++ complains if the volatile result of the assignment is 398 // g++ complains if the volatile result of the assignment is
399 // unused, so we cast the volatile away. We cannot cast directly 399 // unused, so we cast the volatile away. We cannot cast directly
400 // to void, because gcc treats that as not using the result of the 400 // to void, because gcc treats that as not using the result of the
401 // assignment. However, casting to E& means that we trigger an 401 // assignment. However, casting to E& means that we trigger an
402 // unused-value warning. So, we cast the E& to void. 402 // unused-value warning. So, we cast the E& to void.
403 (void)const_cast<E&>(_elems[localBot] = t); 403 (void)const_cast<E&>(_elems[localBot] = t);
404 #ifdef MIPS64 404 #ifdef MIPS
405 this->set_bottom(increment_index(localBot)); 405 this->set_bottom(increment_index(localBot));
406 #else 406 #else
407 OrderAccess::release_store(&_bottom, increment_index(localBot)); 407 OrderAccess::release_store(&_bottom, increment_index(localBot));
408 #endif 408 #endif
409 TASKQUEUE_STATS_ONLY(stats.record_push()); 409 TASKQUEUE_STATS_ONLY(stats.record_push());
458 // to guarantee that bottom is not older than age, 458 // to guarantee that bottom is not older than age,
459 // which is crucial for the correctness of the algorithm. 459 // which is crucial for the correctness of the algorithm.
460 #if !(defined SPARC || defined IA32 || defined AMD64) 460 #if !(defined SPARC || defined IA32 || defined AMD64)
461 OrderAccess::fence(); 461 OrderAccess::fence();
462 #endif 462 #endif
463 #ifdef MIPS64 463 #ifdef MIPS
464 uint localBot = this->get_bottom(); 464 uint localBot = this->get_bottom();
465 #else 465 #else
466 uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom); 466 uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom);
467 #endif 467 #endif
468 uint n_elems = size(localBot, oldAge.top()); 468 uint n_elems = size(localBot, oldAge.top());
717 #endif 717 #endif
718 }; 718 };
719 719
720 template<class E, MEMFLAGS F, unsigned int N> inline bool 720 template<class E, MEMFLAGS F, unsigned int N> inline bool
721 GenericTaskQueue<E, F, N>::push(E t) { 721 GenericTaskQueue<E, F, N>::push(E t) {
722 #ifdef MIPS64 722 #ifdef MIPS
723 uint localBot = this->get_bottom(); 723 uint localBot = this->get_bottom();
724 #else 724 #else
725 uint localBot = _bottom; 725 uint localBot = _bottom;
726 #endif 726 #endif
727 assert(localBot < N, "_bottom out of range."); 727 assert(localBot < N, "_bottom out of range.");
733 // unused, so we cast the volatile away. We cannot cast directly 733 // unused, so we cast the volatile away. We cannot cast directly
734 // to void, because gcc treats that as not using the result of the 734 // to void, because gcc treats that as not using the result of the
735 // assignment. However, casting to E& means that we trigger an 735 // assignment. However, casting to E& means that we trigger an
736 // unused-value warning. So, we cast the E& to void. 736 // unused-value warning. So, we cast the E& to void.
737 (void) const_cast<E&>(_elems[localBot] = t); 737 (void) const_cast<E&>(_elems[localBot] = t);
738 #ifdef MIPS64 738 #ifdef MIPS
739 this->set_bottom(increment_index(localBot)); 739 this->set_bottom(increment_index(localBot));
740 #else 740 #else
741 OrderAccess::release_store(&_bottom, increment_index(localBot)); 741 OrderAccess::release_store(&_bottom, increment_index(localBot));
742 #endif 742 #endif
743 TASKQUEUE_STATS_ONLY(stats.record_push()); 743 TASKQUEUE_STATS_ONLY(stats.record_push());
747 } 747 }
748 } 748 }
749 749
750 template<class E, MEMFLAGS F, unsigned int N> inline bool 750 template<class E, MEMFLAGS F, unsigned int N> inline bool
751 GenericTaskQueue<E, F, N>::pop_local(volatile E& t) { 751 GenericTaskQueue<E, F, N>::pop_local(volatile E& t) {
752 #ifdef MIPS64 752 #ifdef MIPS
753 uint localBot = this->get_bottom(); 753 uint localBot = this->get_bottom();
754 #else 754 #else
755 uint localBot = _bottom; 755 uint localBot = _bottom;
756 #endif 756 #endif
757 // This value cannot be N-1. That can only occur as a result of 757 // This value cannot be N-1. That can only occur as a result of
760 // since this is pop_local.) 760 // since this is pop_local.)
761 uint dirty_n_elems = dirty_size(localBot, _age.top()); 761 uint dirty_n_elems = dirty_size(localBot, _age.top());
762 assert(dirty_n_elems != N - 1, "Shouldn't be possible..."); 762 assert(dirty_n_elems != N - 1, "Shouldn't be possible...");
763 if (dirty_n_elems == 0) return false; 763 if (dirty_n_elems == 0) return false;
764 localBot = decrement_index(localBot); 764 localBot = decrement_index(localBot);
765 #ifdef MIPS64 765 #ifdef MIPS
766 this->set_bottom(localBot); 766 this->set_bottom(localBot);
767 #else 767 #else
768 _bottom = localBot; 768 _bottom = localBot;
769 #endif 769 #endif
770 // This is necessary to prevent any read below from being reordered 770 // This is necessary to prevent any read below from being reordered

mercurial