597 }
598
599 void ZMark::work(uint64_t timeout_in_millis) {
600 ZMarkCache cache(_stripes.nstripes());
601 ZMarkStripe* const stripe = _stripes.stripe_for_worker(_nworkers, ZThread::worker_id());
602 ZMarkThreadLocalStacks* const stacks = ZThreadLocalData::stacks(Thread::current());
603
604 if (timeout_in_millis == 0) {
605 work_without_timeout(&cache, stripe, stacks);
606 } else {
607 work_with_timeout(&cache, stripe, stacks, timeout_in_millis);
608 }
609
610 // Make sure stacks have been flushed
611 assert(stacks->is_empty(&_stripes), "Should be empty");
612
613 // Free remaining stacks
614 stacks->free(&_allocator);
615 }
616
617 class ZMarkTask : public ZTask {
618 private:
619 ZMark* const _mark;
620 const uint64_t _timeout_in_millis;
621
622 public:
623 ZMarkTask(ZMark* mark, uint64_t timeout_in_millis = 0) :
624 ZTask("ZMarkTask"),
625 _mark(mark),
626 _timeout_in_millis(timeout_in_millis) {
627 _mark->prepare_work();
628 }
629
630 ~ZMarkTask() {
631 _mark->finish_work();
632 }
633
634 virtual void work() {
635 _mark->work(_timeout_in_millis);
636 }
637 };
638
639 void ZMark::mark() {
640 ZMarkTask task(this);
641 _workers->run_concurrent(&task);
642 }
643
644 bool ZMark::try_complete() {
645 _ntrycomplete++;
646
647 // Use nconcurrent number of worker threads to maintain the
648 // worker/stripe distribution used during concurrent mark.
649 ZMarkTask task(this, ZMarkCompleteTimeout);
650 _workers->run_concurrent(&task);
651
652 // Successful if all stripes are empty
653 return _stripes.is_empty();
654 }
655
656 bool ZMark::try_end() {
657 // Flush all mark stacks
658 if (!flush(true /* at_safepoint */)) {
|
597 }
598
599 void ZMark::work(uint64_t timeout_in_millis) {
600 ZMarkCache cache(_stripes.nstripes());
601 ZMarkStripe* const stripe = _stripes.stripe_for_worker(_nworkers, ZThread::worker_id());
602 ZMarkThreadLocalStacks* const stacks = ZThreadLocalData::stacks(Thread::current());
603
604 if (timeout_in_millis == 0) {
605 work_without_timeout(&cache, stripe, stacks);
606 } else {
607 work_with_timeout(&cache, stripe, stacks, timeout_in_millis);
608 }
609
610 // Make sure stacks have been flushed
611 assert(stacks->is_empty(&_stripes), "Should be empty");
612
613 // Free remaining stacks
614 stacks->free(&_allocator);
615 }
616
617 class ZMarkConcurrentRootsIteratorClosure : public ZRootsIteratorClosure {
618 public:
619 virtual void do_oop(oop* p) {
620 ZBarrier::mark_barrier_on_oop_field(p, false /* finalizable */);
621 }
622
623 virtual void do_oop(narrowOop* p) {
624 ShouldNotReachHere();
625 }
626 };
627
628
629 class ZMarkConcurrentRootsTask : public ZTask {
630 private:
631 ZConcurrentRootsIterator _roots;
632 ZMarkConcurrentRootsIteratorClosure _cl;
633
634 public:
635 ZMarkConcurrentRootsTask(ZMark* mark) :
636 ZTask("ZMarkConcurrentRootsTask"),
637 _roots(true /* claim_clds */),
638 _cl() {}
639
640 virtual void work() {
641 _roots.oops_do(&_cl);
642 }
643 };
644
645 class ZMarkTask : public ZTask {
646 private:
647 ZMark* const _mark;
648 const uint64_t _timeout_in_millis;
649
650 public:
651 ZMarkTask(ZMark* mark, uint64_t timeout_in_millis = 0) :
652 ZTask("ZMarkTask"),
653 _mark(mark),
654 _timeout_in_millis(timeout_in_millis) {
655 _mark->prepare_work();
656 }
657
658 ~ZMarkTask() {
659 _mark->finish_work();
660 }
661
662 virtual void work() {
663 _mark->work(_timeout_in_millis);
664 }
665 };
666
667 void ZMark::mark(bool initial) {
668 if (initial) {
669 ZMarkConcurrentRootsTask task(this);
670 _workers->run_concurrent(&task);
671 }
672
673 ZMarkTask task(this);
674 _workers->run_concurrent(&task);
675 }
676
677 bool ZMark::try_complete() {
678 _ntrycomplete++;
679
680 // Use nconcurrent number of worker threads to maintain the
681 // worker/stripe distribution used during concurrent mark.
682 ZMarkTask task(this, ZMarkCompleteTimeout);
683 _workers->run_concurrent(&task);
684
685 // Successful if all stripes are empty
686 return _stripes.is_empty();
687 }
688
689 bool ZMark::try_end() {
690 // Flush all mark stacks
691 if (!flush(true /* at_safepoint */)) {
|