comparison src/share/vm/gc_implementation/g1/g1RemSet.cpp @ 10246:194f52aa2f23

7176479: G1: JVM crashes on T5-8 system with 1.5 TB heap Summary: Refactor G1's hot card cache and card counts table into their own files. Simplify the card counts table, including removing the encoding of the card index in each entry. The card counts table now has a 1:1 correspondence with the cards spanned by heap. Space for the card counts table is reserved from virtual memory (rather than C heap) during JVM startup and is committed/expanded when the heap is expanded. Changes were also reviewed-by Vitaly Davidovich. Reviewed-by: tschatzl, jmasa
author johnc
date Thu, 09 May 2013 11:16:39 -0700
parents 5c93c1f61226
children e72f7eecc96d
comparison
equal deleted inserted replaced
10245:923ac8d1df95 10246:194f52aa2f23
1 /* 1 /*
2 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
27 #include "gc_implementation/g1/concurrentG1Refine.hpp" 27 #include "gc_implementation/g1/concurrentG1Refine.hpp"
28 #include "gc_implementation/g1/concurrentG1RefineThread.hpp" 28 #include "gc_implementation/g1/concurrentG1RefineThread.hpp"
29 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp" 29 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
30 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" 30 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
31 #include "gc_implementation/g1/g1CollectorPolicy.hpp" 31 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
32 #include "gc_implementation/g1/g1HotCardCache.hpp"
32 #include "gc_implementation/g1/g1GCPhaseTimes.hpp" 33 #include "gc_implementation/g1/g1GCPhaseTimes.hpp"
33 #include "gc_implementation/g1/g1OopClosures.inline.hpp" 34 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
34 #include "gc_implementation/g1/g1RemSet.inline.hpp" 35 #include "gc_implementation/g1/g1RemSet.inline.hpp"
35 #include "gc_implementation/g1/heapRegionSeq.inline.hpp" 36 #include "gc_implementation/g1/heapRegionSeq.inline.hpp"
36 #include "memory/iterator.hpp" 37 #include "memory/iterator.hpp"
245 // is during RSet updating within an evacuation pause. 246 // is during RSet updating within an evacuation pause.
246 // In this case worker_i should be the id of a GC worker thread. 247 // In this case worker_i should be the id of a GC worker thread.
247 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); 248 assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause");
248 assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker"); 249 assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker");
249 250
250 if (_g1rs->concurrentRefineOneCard(card_ptr, worker_i, true)) { 251 if (_g1rs->refine_card(card_ptr, worker_i, true)) {
251 // 'card_ptr' contains references that point into the collection 252 // 'card_ptr' contains references that point into the collection
252 // set. We need to record the card in the DCQS 253 // set. We need to record the card in the DCQS
253 // (G1CollectedHeap::into_cset_dirty_card_queue_set()) 254 // (G1CollectedHeap::into_cset_dirty_card_queue_set())
254 // that's used for that purpose. 255 // that's used for that purpose.
255 // 256 //
286 void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc, 287 void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
287 int worker_i) { 288 int worker_i) {
288 #if CARD_REPEAT_HISTO 289 #if CARD_REPEAT_HISTO
289 ct_freq_update_histo_and_reset(); 290 ct_freq_update_histo_and_reset();
290 #endif 291 #endif
291 if (worker_i == 0) {
292 _cg1r->clear_and_record_card_counts();
293 }
294 292
295 // We cache the value of 'oc' closure into the appropriate slot in the 293 // We cache the value of 'oc' closure into the appropriate slot in the
296 // _cset_rs_update_cl for this worker 294 // _cset_rs_update_cl for this worker
297 assert(worker_i < (int)n_workers(), "sanity"); 295 assert(worker_i < (int)n_workers(), "sanity");
298 _cset_rs_update_cl[worker_i] = oc; 296 _cset_rs_update_cl[worker_i] = oc;
394 // * the DCQS to which this closure is applied is used to hold 392 // * the DCQS to which this closure is applied is used to hold
395 // references that point into the collection set from the prior 393 // references that point into the collection set from the prior
396 // RSet updating, 394 // RSet updating,
397 // * the post-write barrier shouldn't be logging updates to young 395 // * the post-write barrier shouldn't be logging updates to young
398 // regions (but there is a situation where this can happen - see 396 // regions (but there is a situation where this can happen - see
399 // the comment in G1RemSet::concurrentRefineOneCard below - 397 // the comment in G1RemSet::refine_card() below -
400 // that should not be applicable here), and 398 // that should not be applicable here), and
401 // * during actual RSet updating, the filtering of cards in young 399 // * during actual RSet updating, the filtering of cards in young
402 // regions in HeapRegion::oops_on_card_seq_iterate_careful is 400 // regions in HeapRegion::oops_on_card_seq_iterate_careful is
403 // employed. 401 // employed.
404 // As a result, when this closure is applied to "refs into cset" 402 // As a result, when this closure is applied to "refs into cset"
500 worker_num, 498 worker_num,
501 n_workers(), 499 n_workers(),
502 claim_val); 500 claim_val);
503 } 501 }
504 502
505
506
507 G1TriggerClosure::G1TriggerClosure() : 503 G1TriggerClosure::G1TriggerClosure() :
508 _triggered(false) { } 504 _triggered(false) { }
509 505
510 G1InvokeIfNotTriggeredClosure::G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t_cl, 506 G1InvokeIfNotTriggeredClosure::G1InvokeIfNotTriggeredClosure(G1TriggerClosure* t_cl,
511 OopClosure* oop_cl) : 507 OopClosure* oop_cl) :
522 int worker_i) : 518 int worker_i) :
523 _g1(g1h), _g1_rem_set(rs), _from(NULL), 519 _g1(g1h), _g1_rem_set(rs), _from(NULL),
524 _record_refs_into_cset(record_refs_into_cset), 520 _record_refs_into_cset(record_refs_into_cset),
525 _push_ref_cl(push_ref_cl), _worker_i(worker_i) { } 521 _push_ref_cl(push_ref_cl), _worker_i(worker_i) { }
526 522
527 bool G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i, 523 // Returns true if the given card contains references that point
528 bool check_for_refs_into_cset) { 524 // into the collection set, if we're checking for such references;
525 // false otherwise.
526
527 bool G1RemSet::refine_card(jbyte* card_ptr, int worker_i,
528 bool check_for_refs_into_cset) {
529
530 // If the card is no longer dirty, nothing to do.
531 if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
532 // No need to return that this card contains refs that point
533 // into the collection set.
534 return false;
535 }
536
529 // Construct the region representing the card. 537 // Construct the region representing the card.
530 HeapWord* start = _ct_bs->addr_for(card_ptr); 538 HeapWord* start = _ct_bs->addr_for(card_ptr);
531 // And find the region containing it. 539 // And find the region containing it.
532 HeapRegion* r = _g1->heap_region_containing(start); 540 HeapRegion* r = _g1->heap_region_containing(start);
533 assert(r != NULL, "unexpected null"); 541 if (r == NULL) {
542 // Again no need to return that this card contains refs that
543 // point into the collection set.
544 return false; // Not in the G1 heap (might be in perm, for example.)
545 }
546
547 // Why do we have to check here whether a card is on a young region,
548 // given that we dirty young regions and, as a result, the
549 // post-barrier is supposed to filter them out and never to enqueue
550 // them? When we allocate a new region as the "allocation region" we
551 // actually dirty its cards after we release the lock, since card
552 // dirtying while holding the lock was a performance bottleneck. So,
553 // as a result, it is possible for other threads to actually
554 // allocate objects in the region (after the acquire the lock)
555 // before all the cards on the region are dirtied. This is unlikely,
556 // and it doesn't happen often, but it can happen. So, the extra
557 // check below filters out those cards.
558 if (r->is_young()) {
559 return false;
560 }
561
562 // While we are processing RSet buffers during the collection, we
563 // actually don't want to scan any cards on the collection set,
564 // since we don't want to update remebered sets with entries that
565 // point into the collection set, given that live objects from the
566 // collection set are about to move and such entries will be stale
567 // very soon. This change also deals with a reliability issue which
568 // involves scanning a card in the collection set and coming across
569 // an array that was being chunked and looking malformed. Note,
570 // however, that if evacuation fails, we have to scan any objects
571 // that were not moved and create any missing entries.
572 if (r->in_collection_set()) {
573 return false;
574 }
575
576 // The result from the hot card cache insert call is either:
577 // * pointer to the current card
578 // (implying that the current card is not 'hot'),
579 // * null
580 // (meaning we had inserted the card ptr into the "hot" card cache,
581 // which had some headroom),
582 // * a pointer to a "hot" card that was evicted from the "hot" cache.
583 //
584
585 G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
586 if (hot_card_cache->use_cache()) {
587 assert(!check_for_refs_into_cset, "sanity");
588 assert(!SafepointSynchronize::is_at_safepoint(), "sanity");
589
590 card_ptr = hot_card_cache->insert(card_ptr);
591 if (card_ptr == NULL) {
592 // There was no eviction. Nothing to do.
593 return false;
594 }
595
596 start = _ct_bs->addr_for(card_ptr);
597 r = _g1->heap_region_containing(start);
598 if (r == NULL) {
599 // Not in the G1 heap
600 return false;
601 }
602
603 // Checking whether the region we got back from the cache
604 // is young here is inappropriate. The region could have been
605 // freed, reallocated and tagged as young while in the cache.
606 // Hence we could see its young type change at any time.
607 }
534 608
535 // Don't use addr_for(card_ptr + 1) which can ask for 609 // Don't use addr_for(card_ptr + 1) which can ask for
536 // a card beyond the heap. This is not safe without a perm 610 // a card beyond the heap. This is not safe without a perm
537 // gen at the upper end of the heap. 611 // gen at the upper end of the heap.
538 HeapWord* end = start + CardTableModRefBS::card_size_in_words; 612 HeapWord* end = start + CardTableModRefBS::card_size_in_words;
608 } 682 }
609 } else { 683 } else {
610 _conc_refine_cards++; 684 _conc_refine_cards++;
611 } 685 }
612 686
613 return trigger_cl.triggered(); 687 // This gets set to true if the card being refined has
614 } 688 // references that point into the collection set.
615 689 bool has_refs_into_cset = trigger_cl.triggered();
616 bool G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i, 690
617 bool check_for_refs_into_cset) { 691 // We should only be detecting that the card contains references
618 // If the card is no longer dirty, nothing to do. 692 // that point into the collection set if the current thread is
619 if (*card_ptr != CardTableModRefBS::dirty_card_val()) { 693 // a GC worker thread.
620 // No need to return that this card contains refs that point 694 assert(!has_refs_into_cset || SafepointSynchronize::is_at_safepoint(),
621 // into the collection set.
622 return false;
623 }
624
625 // Construct the region representing the card.
626 HeapWord* start = _ct_bs->addr_for(card_ptr);
627 // And find the region containing it.
628 HeapRegion* r = _g1->heap_region_containing(start);
629 if (r == NULL) {
630 // Again no need to return that this card contains refs that
631 // point into the collection set.
632 return false; // Not in the G1 heap (might be in perm, for example.)
633 }
634 // Why do we have to check here whether a card is on a young region,
635 // given that we dirty young regions and, as a result, the
636 // post-barrier is supposed to filter them out and never to enqueue
637 // them? When we allocate a new region as the "allocation region" we
638 // actually dirty its cards after we release the lock, since card
639 // dirtying while holding the lock was a performance bottleneck. So,
640 // as a result, it is possible for other threads to actually
641 // allocate objects in the region (after the acquire the lock)
642 // before all the cards on the region are dirtied. This is unlikely,
643 // and it doesn't happen often, but it can happen. So, the extra
644 // check below filters out those cards.
645 if (r->is_young()) {
646 return false;
647 }
648 // While we are processing RSet buffers during the collection, we
649 // actually don't want to scan any cards on the collection set,
650 // since we don't want to update remebered sets with entries that
651 // point into the collection set, given that live objects from the
652 // collection set are about to move and such entries will be stale
653 // very soon. This change also deals with a reliability issue which
654 // involves scanning a card in the collection set and coming across
655 // an array that was being chunked and looking malformed. Note,
656 // however, that if evacuation fails, we have to scan any objects
657 // that were not moved and create any missing entries.
658 if (r->in_collection_set()) {
659 return false;
660 }
661
662 // Should we defer processing the card?
663 //
664 // Previously the result from the insert_cache call would be
665 // either card_ptr (implying that card_ptr was currently "cold"),
666 // null (meaning we had inserted the card ptr into the "hot"
667 // cache, which had some headroom), or a "hot" card ptr
668 // extracted from the "hot" cache.
669 //
670 // Now that the _card_counts cache in the ConcurrentG1Refine
671 // instance is an evicting hash table, the result we get back
672 // could be from evicting the card ptr in an already occupied
673 // bucket (in which case we have replaced the card ptr in the
674 // bucket with card_ptr and "defer" is set to false). To avoid
675 // having a data structure (updates to which would need a lock)
676 // to hold these unprocessed dirty cards, we need to immediately
677 // process card_ptr. The actions needed to be taken on return
678 // from cache_insert are summarized in the following table:
679 //
680 // res defer action
681 // --------------------------------------------------------------
682 // null false card evicted from _card_counts & replaced with
683 // card_ptr; evicted ptr added to hot cache.
684 // No need to process res; immediately process card_ptr
685 //
686 // null true card not evicted from _card_counts; card_ptr added
687 // to hot cache.
688 // Nothing to do.
689 //
690 // non-null false card evicted from _card_counts & replaced with
691 // card_ptr; evicted ptr is currently "cold" or
692 // caused an eviction from the hot cache.
693 // Immediately process res; process card_ptr.
694 //
695 // non-null true card not evicted from _card_counts; card_ptr is
696 // currently cold, or caused an eviction from hot
697 // cache.
698 // Immediately process res; no need to process card_ptr.
699
700
701 jbyte* res = card_ptr;
702 bool defer = false;
703
704 // This gets set to true if the card being refined has references
705 // that point into the collection set.
706 bool oops_into_cset = false;
707
708 if (_cg1r->use_cache()) {
709 jbyte* res = _cg1r->cache_insert(card_ptr, &defer);
710 if (res != NULL && (res != card_ptr || defer)) {
711 start = _ct_bs->addr_for(res);
712 r = _g1->heap_region_containing(start);
713 if (r != NULL) {
714 // Checking whether the region we got back from the cache
715 // is young here is inappropriate. The region could have been
716 // freed, reallocated and tagged as young while in the cache.
717 // Hence we could see its young type change at any time.
718 //
719 // Process card pointer we get back from the hot card cache. This
720 // will check whether the region containing the card is young
721 // _after_ checking that the region has been allocated from.
722 oops_into_cset = concurrentRefineOneCard_impl(res, worker_i,
723 false /* check_for_refs_into_cset */);
724 // The above call to concurrentRefineOneCard_impl is only
725 // performed if the hot card cache is enabled. This cache is
726 // disabled during an evacuation pause - which is the only
727 // time when we need know if the card contains references
728 // that point into the collection set. Also when the hot card
729 // cache is enabled, this code is executed by the concurrent
730 // refine threads - rather than the GC worker threads - and
731 // concurrentRefineOneCard_impl will return false.
732 assert(!oops_into_cset, "should not see true here");
733 }
734 }
735 }
736
737 if (!defer) {
738 oops_into_cset =
739 concurrentRefineOneCard_impl(card_ptr, worker_i, check_for_refs_into_cset);
740 // We should only be detecting that the card contains references
741 // that point into the collection set if the current thread is
742 // a GC worker thread.
743 assert(!oops_into_cset || SafepointSynchronize::is_at_safepoint(),
744 "invalid result at non safepoint"); 695 "invalid result at non safepoint");
745 } 696
746 return oops_into_cset; 697 return has_refs_into_cset;
747 } 698 }
748 699
749 class HRRSStatsIter: public HeapRegionClosure { 700 class HRRSStatsIter: public HeapRegionClosure {
750 size_t _occupied; 701 size_t _occupied;
751 size_t _total_mem_sz; 702 size_t _total_mem_sz;
844 _g1->set_refine_cte_cl_concurrency(false); 795 _g1->set_refine_cte_cl_concurrency(false);
845 if (SafepointSynchronize::is_at_safepoint()) { 796 if (SafepointSynchronize::is_at_safepoint()) {
846 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); 797 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
847 dcqs.concatenate_logs(); 798 dcqs.concatenate_logs();
848 } 799 }
849 bool cg1r_use_cache = _cg1r->use_cache(); 800
850 _cg1r->set_use_cache(false); 801 G1HotCardCache* hot_card_cache = _cg1r->hot_card_cache();
802 bool use_hot_card_cache = hot_card_cache->use_cache();
803 hot_card_cache->set_use_cache(false);
804
851 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set()); 805 DirtyCardQueue into_cset_dcq(&_g1->into_cset_dirty_card_queue_set());
852 updateRS(&into_cset_dcq, 0); 806 updateRS(&into_cset_dcq, 0);
853 _g1->into_cset_dirty_card_queue_set().clear(); 807 _g1->into_cset_dirty_card_queue_set().clear();
854 _cg1r->set_use_cache(cg1r_use_cache); 808
855 809 hot_card_cache->set_use_cache(use_hot_card_cache);
856 assert(JavaThread::dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed"); 810 assert(JavaThread::dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");
857 } 811 }
858 } 812 }