Merge

Tue, 16 Feb 2010 14:11:44 -0800

author
johnc
date
Tue, 16 Feb 2010 14:11:44 -0800
changeset 1697
58add740c4ee
parent 1692
7b4415a18c8a
parent 1696
0414c1049f15
child 1702
72f1840531a4
child 1717
b81f3572f355

Merge

src/share/vm/includeDB_core file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/classfile/loaderConstraints.cpp	Fri Feb 12 15:27:36 2010 -0800
     1.2 +++ b/src/share/vm/classfile/loaderConstraints.cpp	Tue Feb 16 14:11:44 2010 -0800
     1.3 @@ -457,7 +457,8 @@
     1.4  }
     1.5  
     1.6  
     1.7 -void LoaderConstraintTable::verify(Dictionary* dictionary) {
     1.8 +void LoaderConstraintTable::verify(Dictionary* dictionary,
     1.9 +                                   PlaceholderTable* placeholders) {
    1.10    Thread *thread = Thread::current();
    1.11    for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
    1.12      for (LoaderConstraintEntry* probe = bucket(cindex);
    1.13 @@ -472,7 +473,23 @@
    1.14          unsigned int d_hash = dictionary->compute_hash(name, loader);
    1.15          int d_index = dictionary->hash_to_index(d_hash);
    1.16          klassOop k = dictionary->find_class(d_index, d_hash, name, loader);
    1.17 -        guarantee(k == probe->klass(), "klass should be in dictionary");
    1.18 +        if (k != NULL) {
    1.19 +          // We found the class in the system dictionary, so we should
    1.20 +          // make sure that the klassOop matches what we already have.
    1.21 +          guarantee(k == probe->klass(), "klass should be in dictionary");
    1.22 +        } else {
    1.23 +          // If we don't find the class in the system dictionary, it
    1.24 +          // has to be in the placeholders table.
    1.25 +          unsigned int p_hash = placeholders->compute_hash(name, loader);
    1.26 +          int p_index = placeholders->hash_to_index(p_hash);
    1.27 +          PlaceholderEntry* entry = placeholders->get_entry(p_index, p_hash,
    1.28 +                                                            name, loader);
    1.29 +
    1.30 +          // The instanceKlass might not be on the entry, so the only
    1.31 +          // thing we can check here is whether we were successful in
    1.32 +          // finding the class in the placeholders table.
    1.33 +          guarantee(entry != NULL, "klass should be in the placeholders");
    1.34 +        }
    1.35        }
    1.36        for (int n = 0; n< probe->num_loaders(); n++) {
    1.37          guarantee(probe->loader(n)->is_oop_or_null(), "should be oop");
     2.1 --- a/src/share/vm/classfile/loaderConstraints.hpp	Fri Feb 12 15:27:36 2010 -0800
     2.2 +++ b/src/share/vm/classfile/loaderConstraints.hpp	Tue Feb 16 14:11:44 2010 -0800
     2.3 @@ -84,7 +84,7 @@
     2.4  
     2.5    void purge_loader_constraints(BoolObjectClosure* is_alive);
     2.6  
     2.7 -  void verify(Dictionary* dictionary);
     2.8 +  void verify(Dictionary* dictionary, PlaceholderTable* placeholders);
     2.9  #ifndef PRODUCT
    2.10    void print();
    2.11  #endif
     3.1 --- a/src/share/vm/classfile/systemDictionary.cpp	Fri Feb 12 15:27:36 2010 -0800
     3.2 +++ b/src/share/vm/classfile/systemDictionary.cpp	Tue Feb 16 14:11:44 2010 -0800
     3.3 @@ -2573,7 +2573,7 @@
     3.4  
     3.5    // Verify constraint table
     3.6    guarantee(constraints() != NULL, "Verify of loader constraints failed");
     3.7 -  constraints()->verify(dictionary());
     3.8 +  constraints()->verify(dictionary(), placeholders());
     3.9  }
    3.10  
    3.11  
     4.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Fri Feb 12 15:27:36 2010 -0800
     4.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Tue Feb 16 14:11:44 2010 -0800
     4.3 @@ -2646,6 +2646,13 @@
     4.4  
     4.5  // </NEW PREDICTION>
     4.6  
     4.7 +struct PrepareForRSScanningClosure : public HeapRegionClosure {
     4.8 +  bool doHeapRegion(HeapRegion *r) {
     4.9 +    r->rem_set()->set_iter_claimed(0);
    4.10 +    return false;
    4.11 +  }
    4.12 +};
    4.13 +
    4.14  void
    4.15  G1CollectedHeap::do_collection_pause_at_safepoint() {
    4.16    if (PrintHeapAtGC) {
    4.17 @@ -2784,6 +2791,8 @@
    4.18          gclog_or_tty->print_cr("\nAfter pause, heap:");
    4.19          print();
    4.20  #endif
    4.21 +        PrepareForRSScanningClosure prepare_for_rs_scan;
    4.22 +        collection_set_iterate(&prepare_for_rs_scan);
    4.23  
    4.24          setup_surviving_young_words();
    4.25  
    4.26 @@ -3781,22 +3790,16 @@
    4.27    return obj;
    4.28  }
    4.29  
    4.30 -template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee, bool skip_cset_test>
    4.31 +template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee>
    4.32  template <class T>
    4.33 -void G1ParCopyClosure <do_gen_barrier, barrier, do_mark_forwardee, skip_cset_test>
    4.34 +void G1ParCopyClosure <do_gen_barrier, barrier, do_mark_forwardee>
    4.35  ::do_oop_work(T* p) {
    4.36    oop obj = oopDesc::load_decode_heap_oop(p);
    4.37    assert(barrier != G1BarrierRS || obj != NULL,
    4.38           "Precondition: G1BarrierRS implies obj is nonNull");
    4.39  
    4.40 -  // The only time we skip the cset test is when we're scanning
    4.41 -  // references popped from the queue. And we only push on the queue
    4.42 -  // references that we know point into the cset, so no point in
    4.43 -  // checking again. But we'll leave an assert here for peace of mind.
    4.44 -  assert(!skip_cset_test || _g1->obj_in_cs(obj), "invariant");
    4.45 -
    4.46    // here the null check is implicit in the cset_fast_test() test
    4.47 -  if (skip_cset_test || _g1->in_cset_fast_test(obj)) {
    4.48 +  if (_g1->in_cset_fast_test(obj)) {
    4.49  #if G1_REM_SET_LOGGING
    4.50      gclog_or_tty->print_cr("Loc "PTR_FORMAT" contains pointer "PTR_FORMAT" "
    4.51                             "into CS.", p, (void*) obj);
    4.52 @@ -3813,7 +3816,6 @@
    4.53      }
    4.54    }
    4.55  
    4.56 -  // When scanning moved objs, must look at all oops.
    4.57    if (barrier == G1BarrierEvac && obj != NULL) {
    4.58      _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num());
    4.59    }
    4.60 @@ -3823,8 +3825,8 @@
    4.61    }
    4.62  }
    4.63  
    4.64 -template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(oop* p);
    4.65 -template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(narrowOop* p);
    4.66 +template void G1ParCopyClosure<false, G1BarrierEvac, false>::do_oop_work(oop* p);
    4.67 +template void G1ParCopyClosure<false, G1BarrierEvac, false>::do_oop_work(narrowOop* p);
    4.68  
    4.69  template <class T> void G1ParScanPartialArrayClosure::do_oop_nv(T* p) {
    4.70    assert(has_partial_array_mask(p), "invariant");
    4.71 @@ -3896,11 +3898,11 @@
    4.72            assert(UseCompressedOops, "Error");
    4.73            narrowOop* p = (narrowOop*) stolen_task;
    4.74            assert(has_partial_array_mask(p) ||
    4.75 -                 _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "Error");
    4.76 +                 _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "Error");
    4.77            pss->push_on_queue(p);
    4.78          } else {
    4.79            oop* p = (oop*) stolen_task;
    4.80 -          assert(has_partial_array_mask(p) || _g1h->obj_in_cs(*p), "Error");
    4.81 +          assert(has_partial_array_mask(p) || _g1h->is_in_g1_reserved(*p), "Error");
    4.82            pss->push_on_queue(p);
    4.83          }
    4.84          continue;
    4.85 @@ -3962,6 +3964,7 @@
    4.86      G1ParScanExtRootClosure         only_scan_root_cl(_g1h, &pss);
    4.87      G1ParScanPermClosure            only_scan_perm_cl(_g1h, &pss);
    4.88      G1ParScanHeapRSClosure          only_scan_heap_rs_cl(_g1h, &pss);
    4.89 +    G1ParPushHeapRSClosure          push_heap_rs_cl(_g1h, &pss);
    4.90  
    4.91      G1ParScanAndMarkExtRootClosure  scan_mark_root_cl(_g1h, &pss);
    4.92      G1ParScanAndMarkPermClosure     scan_mark_perm_cl(_g1h, &pss);
    4.93 @@ -3985,7 +3988,7 @@
    4.94      _g1h->g1_process_strong_roots(/* not collecting perm */ false,
    4.95                                    SharedHeap::SO_AllClasses,
    4.96                                    scan_root_cl,
    4.97 -                                  &only_scan_heap_rs_cl,
    4.98 +                                  &push_heap_rs_cl,
    4.99                                    scan_so_cl,
   4.100                                    scan_perm_cl,
   4.101                                    i);
     5.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Fri Feb 12 15:27:36 2010 -0800
     5.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Tue Feb 16 14:11:44 2010 -0800
     5.3 @@ -1623,7 +1623,7 @@
     5.4    template <class T> void push_on_queue(T* ref) {
     5.5      assert(ref != NULL, "invariant");
     5.6      assert(has_partial_array_mask(ref) ||
     5.7 -           _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(ref)), "invariant");
     5.8 +           _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(ref)), "invariant");
     5.9  #ifdef ASSERT
    5.10      if (has_partial_array_mask(ref)) {
    5.11        oop p = clear_partial_array_mask(ref);
    5.12 @@ -1644,9 +1644,9 @@
    5.13        assert((oop*)ref != NULL, "pop_local() returned true");
    5.14        assert(UseCompressedOops || !ref.is_narrow(), "Error");
    5.15        assert(has_partial_array_mask((oop*)ref) ||
    5.16 -             _g1h->obj_in_cs(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref)
    5.17 -                                             : oopDesc::load_decode_heap_oop((oop*)ref)),
    5.18 -             "invariant");
    5.19 +             _g1h->is_in_g1_reserved(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref)
    5.20 +                                                     : oopDesc::load_decode_heap_oop((oop*)ref)),
    5.21 +              "invariant");
    5.22        IF_G1_DETAILED_STATS(note_pop());
    5.23      } else {
    5.24        StarTask null_task;
    5.25 @@ -1659,9 +1659,9 @@
    5.26      assert((oop*)new_ref != NULL, "pop() from a local non-empty stack");
    5.27      assert(UseCompressedOops || !new_ref.is_narrow(), "Error");
    5.28      assert(has_partial_array_mask((oop*)new_ref) ||
    5.29 -           _g1h->obj_in_cs(new_ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)new_ref)
    5.30 -                                               : oopDesc::load_decode_heap_oop((oop*)new_ref)),
    5.31 -             "invariant");
    5.32 +           _g1h->is_in_g1_reserved(new_ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)new_ref)
    5.33 +                                                       : oopDesc::load_decode_heap_oop((oop*)new_ref)),
    5.34 +           "invariant");
    5.35      ref = new_ref;
    5.36    }
    5.37  
    5.38 @@ -1825,12 +1825,12 @@
    5.39            assert(UseCompressedOops, "Error");
    5.40            narrowOop* p = (narrowOop*)ref_to_scan;
    5.41            assert(!has_partial_array_mask(p) &&
    5.42 -                 _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity");
    5.43 +                 _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
    5.44            deal_with_reference(p);
    5.45          } else {
    5.46            oop* p = (oop*)ref_to_scan;
    5.47 -          assert((has_partial_array_mask(p) && _g1h->obj_in_cs(clear_partial_array_mask(p))) ||
    5.48 -                 _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity");
    5.49 +          assert((has_partial_array_mask(p) && _g1h->is_in_g1_reserved(clear_partial_array_mask(p))) ||
    5.50 +                 _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
    5.51            deal_with_reference(p);
    5.52          }
    5.53        }
    5.54 @@ -1844,12 +1844,12 @@
    5.55              assert(UseCompressedOops, "Error");
    5.56              narrowOop* p = (narrowOop*)ref_to_scan;
    5.57              assert(!has_partial_array_mask(p) &&
    5.58 -                   _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity");
    5.59 +                    _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
    5.60              deal_with_reference(p);
    5.61            } else {
    5.62              oop* p = (oop*)ref_to_scan;
    5.63              assert((has_partial_array_mask(p) && _g1h->obj_in_cs(clear_partial_array_mask(p))) ||
    5.64 -                  _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity");
    5.65 +                   _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
    5.66              deal_with_reference(p);
    5.67            }
    5.68          }
     6.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Fri Feb 12 15:27:36 2010 -0800
     6.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Tue Feb 16 14:11:44 2010 -0800
     6.3 @@ -205,6 +205,7 @@
     6.4    // policy is created before the heap, we have to set this up here,
     6.5    // so it's done as soon as possible.
     6.6    HeapRegion::setup_heap_region_size(Arguments::min_heap_size());
     6.7 +  HeapRegionRemSet::setup_remset_size();
     6.8  
     6.9    _recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime());
    6.10    _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0;
     7.1 --- a/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Fri Feb 12 15:27:36 2010 -0800
     7.2 +++ b/src/share/vm/gc_implementation/g1/g1OopClosures.hpp	Tue Feb 16 14:11:44 2010 -0800
     7.3 @@ -53,6 +53,15 @@
     7.4    bool apply_to_weak_ref_discovered_field() { return true; }
     7.5  };
     7.6  
     7.7 +class G1ParPushHeapRSClosure : public G1ParClosureSuper {
     7.8 +public:
     7.9 +  G1ParPushHeapRSClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
    7.10 +    G1ParClosureSuper(g1, par_scan_state) { }
    7.11 +  template <class T> void do_oop_nv(T* p);
    7.12 +  virtual void do_oop(oop* p)          { do_oop_nv(p); }
    7.13 +  virtual void do_oop(narrowOop* p)    { do_oop_nv(p); }
    7.14 +};
    7.15 +
    7.16  class G1ParScanClosure : public G1ParClosureSuper {
    7.17  public:
    7.18    G1ParScanClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
    7.19 @@ -100,7 +109,7 @@
    7.20  };
    7.21  
    7.22  template<bool do_gen_barrier, G1Barrier barrier,
    7.23 -         bool do_mark_forwardee, bool skip_cset_test>
    7.24 +         bool do_mark_forwardee>
    7.25  class G1ParCopyClosure : public G1ParCopyHelper {
    7.26    G1ParScanClosure _scanner;
    7.27    template <class T> void do_oop_work(T* p);
    7.28 @@ -116,12 +125,13 @@
    7.29    virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
    7.30  };
    7.31  
    7.32 -typedef G1ParCopyClosure<false, G1BarrierNone, false, false> G1ParScanExtRootClosure;
    7.33 -typedef G1ParCopyClosure<true,  G1BarrierNone, false, false> G1ParScanPermClosure;
    7.34 -typedef G1ParCopyClosure<false, G1BarrierRS,   false, false> G1ParScanHeapRSClosure;
    7.35 -typedef G1ParCopyClosure<false, G1BarrierNone, true,  false> G1ParScanAndMarkExtRootClosure;
    7.36 -typedef G1ParCopyClosure<true,  G1BarrierNone, true,  false> G1ParScanAndMarkPermClosure;
    7.37 -typedef G1ParCopyClosure<false, G1BarrierRS,   true,  false> G1ParScanAndMarkHeapRSClosure;
    7.38 +typedef G1ParCopyClosure<false, G1BarrierNone, false> G1ParScanExtRootClosure;
    7.39 +typedef G1ParCopyClosure<true,  G1BarrierNone, false> G1ParScanPermClosure;
    7.40 +typedef G1ParCopyClosure<false, G1BarrierRS,   false> G1ParScanHeapRSClosure;
    7.41 +typedef G1ParCopyClosure<false, G1BarrierNone, true> G1ParScanAndMarkExtRootClosure;
    7.42 +typedef G1ParCopyClosure<true,  G1BarrierNone, true> G1ParScanAndMarkPermClosure;
    7.43 +typedef G1ParCopyClosure<false, G1BarrierRS,   true> G1ParScanAndMarkHeapRSClosure;
    7.44 +
    7.45  // This is the only case when we set skip_cset_test. Basically, this
    7.46  // closure is (should?) only be called directly while we're draining
    7.47  // the overflow and task queues. In that case we know that the
    7.48 @@ -132,7 +142,7 @@
    7.49  // We need a separate closure to handle references during evacuation
    7.50  // failure processing, as we cannot asume that the reference already
    7.51  // points into the collection set (like G1ParScanHeapEvacClosure does).
    7.52 -typedef G1ParCopyClosure<false, G1BarrierEvac, false, false> G1ParScanHeapEvacFailureClosure;
    7.53 +typedef G1ParCopyClosure<false, G1BarrierEvac, false> G1ParScanHeapEvacFailureClosure;
    7.54  
    7.55  class FilterIntoCSClosure: public OopClosure {
    7.56    G1CollectedHeap* _g1;
     8.1 --- a/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp	Fri Feb 12 15:27:36 2010 -0800
     8.2 +++ b/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp	Tue Feb 16 14:11:44 2010 -0800
     8.3 @@ -104,3 +104,16 @@
     8.4      }
     8.5    }
     8.6  }
     8.7 +
     8.8 +template <class T> inline void G1ParPushHeapRSClosure::do_oop_nv(T* p) {
     8.9 +  T heap_oop = oopDesc::load_heap_oop(p);
    8.10 +
    8.11 +  if (!oopDesc::is_null(heap_oop)) {
    8.12 +    oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
    8.13 +    if (_g1->in_cset_fast_test(obj)) {
    8.14 +      Prefetch::write(obj->mark_addr(), 0);
    8.15 +      Prefetch::read(obj->mark_addr(), (HeapWordSize*2));
    8.16 +      _par_scan_state->push_on_queue(p);
    8.17 +    }
    8.18 +  }
    8.19 +}
     9.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Fri Feb 12 15:27:36 2010 -0800
     9.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp	Tue Feb 16 14:11:44 2010 -0800
     9.3 @@ -155,8 +155,8 @@
     9.4    G1BlockOffsetSharedArray* _bot_shared;
     9.5    CardTableModRefBS *_ct_bs;
     9.6    int _worker_i;
     9.7 +  int _block_size;
     9.8    bool _try_claimed;
     9.9 -  size_t _min_skip_distance, _max_skip_distance;
    9.10  public:
    9.11    ScanRSClosure(OopsInHeapRegionClosure* oc, int worker_i) :
    9.12      _oc(oc),
    9.13 @@ -168,8 +168,7 @@
    9.14      _g1h = G1CollectedHeap::heap();
    9.15      _bot_shared = _g1h->bot_shared();
    9.16      _ct_bs = (CardTableModRefBS*) (_g1h->barrier_set());
    9.17 -    _min_skip_distance = 16;
    9.18 -    _max_skip_distance = 2 * _g1h->n_par_threads() * _min_skip_distance;
    9.19 +    _block_size = MAX2<int>(G1RSetScanBlockSize, 1);
    9.20    }
    9.21  
    9.22    void set_try_claimed() { _try_claimed = true; }
    9.23 @@ -225,12 +224,15 @@
    9.24      HeapRegionRemSetIterator* iter = _g1h->rem_set_iterator(_worker_i);
    9.25      hrrs->init_iterator(iter);
    9.26      size_t card_index;
    9.27 -    size_t skip_distance = 0, current_card = 0, jump_to_card = 0;
    9.28 -    while (iter->has_next(card_index)) {
    9.29 -      if (current_card < jump_to_card) {
    9.30 -        ++current_card;
    9.31 -        continue;
    9.32 +
    9.33 +    // We claim cards in block so as to recude the contention. The block size is determined by
    9.34 +    // the G1RSetScanBlockSize parameter.
    9.35 +    size_t jump_to_card = hrrs->iter_claimed_next(_block_size);
    9.36 +    for (size_t current_card = 0; iter->has_next(card_index); current_card++) {
    9.37 +      if (current_card >= jump_to_card + _block_size) {
    9.38 +        jump_to_card = hrrs->iter_claimed_next(_block_size);
    9.39        }
    9.40 +      if (current_card < jump_to_card) continue;
    9.41        HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index);
    9.42  #if 0
    9.43        gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n",
    9.44 @@ -247,22 +249,14 @@
    9.45  
    9.46         // If the card is dirty, then we will scan it during updateRS.
    9.47        if (!card_region->in_collection_set() && !_ct_bs->is_card_dirty(card_index)) {
    9.48 -          if (!_ct_bs->is_card_claimed(card_index) && _ct_bs->claim_card(card_index)) {
    9.49 -            scanCard(card_index, card_region);
    9.50 -          } else if (_try_claimed) {
    9.51 -            if (jump_to_card == 0 || jump_to_card != current_card) {
    9.52 -              // We did some useful work in the previous iteration.
    9.53 -              // Decrease the distance.
    9.54 -              skip_distance = MAX2(skip_distance >> 1, _min_skip_distance);
    9.55 -            } else {
    9.56 -              // Previous iteration resulted in a claim failure.
    9.57 -              // Increase the distance.
    9.58 -              skip_distance = MIN2(skip_distance << 1, _max_skip_distance);
    9.59 -            }
    9.60 -            jump_to_card = current_card + skip_distance;
    9.61 -          }
    9.62 +        // We make the card as "claimed" lazily (so races are possible but they're benign),
    9.63 +        // which reduces the number of duplicate scans (the rsets of the regions in the cset
    9.64 +        // can intersect).
    9.65 +        if (!_ct_bs->is_card_claimed(card_index)) {
    9.66 +          _ct_bs->set_card_claimed(card_index);
    9.67 +          scanCard(card_index, card_region);
    9.68 +        }
    9.69        }
    9.70 -      ++current_card;
    9.71      }
    9.72      if (!_try_claimed) {
    9.73        hrrs->set_iter_complete();
    9.74 @@ -299,30 +293,18 @@
    9.75    double rs_time_start = os::elapsedTime();
    9.76    HeapRegion *startRegion = calculateStartRegion(worker_i);
    9.77  
    9.78 -  BufferingOopsInHeapRegionClosure boc(oc);
    9.79 -  ScanRSClosure scanRScl(&boc, worker_i);
    9.80 +  ScanRSClosure scanRScl(oc, worker_i);
    9.81    _g1->collection_set_iterate_from(startRegion, &scanRScl);
    9.82    scanRScl.set_try_claimed();
    9.83    _g1->collection_set_iterate_from(startRegion, &scanRScl);
    9.84  
    9.85 -  boc.done();
    9.86 -  double closure_app_time_sec = boc.closure_app_seconds();
    9.87 -  double scan_rs_time_sec = (os::elapsedTime() - rs_time_start) -
    9.88 -    closure_app_time_sec;
    9.89 -  double closure_app_time_ms = closure_app_time_sec * 1000.0;
    9.90 +  double scan_rs_time_sec = os::elapsedTime() - rs_time_start;
    9.91  
    9.92    assert( _cards_scanned != NULL, "invariant" );
    9.93    _cards_scanned[worker_i] = scanRScl.cards_done();
    9.94  
    9.95    _g1p->record_scan_rs_start_time(worker_i, rs_time_start * 1000.0);
    9.96    _g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
    9.97 -
    9.98 -  double scan_new_refs_time_ms = _g1p->get_scan_new_refs_time(worker_i);
    9.99 -  if (scan_new_refs_time_ms > 0.0) {
   9.100 -    closure_app_time_ms += scan_new_refs_time_ms;
   9.101 -  }
   9.102 -
   9.103 -  _g1p->record_obj_copy_time(worker_i, closure_app_time_ms);
   9.104  }
   9.105  
   9.106  void HRInto_G1RemSet::updateRS(int worker_i) {
   9.107 @@ -449,9 +431,8 @@
   9.108        oc->do_oop(p);
   9.109      }
   9.110    }
   9.111 -  _g1p->record_scan_new_refs_time(worker_i,
   9.112 -                                  (os::elapsedTime() - scan_new_refs_start_sec)
   9.113 -                                  * 1000.0);
   9.114 +  double scan_new_refs_time_ms = (os::elapsedTime() - scan_new_refs_start_sec) * 1000.0;
   9.115 +  _g1p->record_scan_new_refs_time(worker_i, scan_new_refs_time_ms);
   9.116  }
   9.117  
   9.118  void HRInto_G1RemSet::cleanupHRRS() {
    10.1 --- a/src/share/vm/gc_implementation/g1/g1_globals.hpp	Fri Feb 12 15:27:36 2010 -0800
    10.2 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp	Tue Feb 16 14:11:44 2010 -0800
    10.3 @@ -207,8 +207,20 @@
    10.4    develop(bool, G1PrintOopAppls, false,                                     \
    10.5            "When true, print applications of closures to external locs.")    \
    10.6                                                                              \
    10.7 -  develop(intx, G1LogRSRegionEntries, 7,                                    \
    10.8 -          "Log_2 of max number of regions for which we keep bitmaps.")      \
    10.9 +  develop(intx, G1RSetRegionEntriesBase, 256,                               \
   10.10 +          "Max number of regions in a fine-grain table per MB.")            \
   10.11 +                                                                            \
   10.12 +  product(intx, G1RSetRegionEntries, 0,                                     \
   10.13 +          "Max number of regions for which we keep bitmaps."                \
   10.14 +          "Will be set ergonomically by default")                           \
   10.15 +                                                                            \
   10.16 +  develop(intx, G1RSetSparseRegionEntriesBase, 4,                           \
   10.17 +          "Max number of entries per region in a sparse table "             \
   10.18 +          "per MB.")                                                        \
   10.19 +                                                                            \
   10.20 +  product(intx, G1RSetSparseRegionEntries, 0,                               \
   10.21 +          "Max number of entries per region in a sparse table."             \
   10.22 +          "Will be set ergonomically by default.")                          \
   10.23                                                                              \
   10.24    develop(bool, G1RecordHRRSOops, false,                                    \
   10.25            "When true, record recent calls to rem set operations.")          \
   10.26 @@ -293,6 +305,10 @@
   10.27    develop(bool, G1VerifyCTCleanup, false,                                   \
   10.28            "Verify card table cleanup.")                                     \
   10.29                                                                              \
   10.30 +  product(uintx, G1RSetScanBlockSize, 64,                                   \
   10.31 +          "Size of a work unit of cards claimed by a worker thread"         \
   10.32 +          "during RSet scanning.")                                          \
   10.33 +                                                                            \
   10.34    develop(bool, ReduceInitialCardMarksForG1, false,                         \
   10.35            "When ReduceInitialCardMarks is true, this flag setting "         \
   10.36            " controls whether G1 allows the RICM optimization")
    11.1 --- a/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp	Fri Feb 12 15:27:36 2010 -0800
    11.2 +++ b/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp	Tue Feb 16 14:11:44 2010 -0800
    11.3 @@ -33,11 +33,12 @@
    11.4  };
    11.5  
    11.6  template<bool do_gen_barrier, G1Barrier barrier,
    11.7 -         bool do_mark_forwardee, bool skip_cset_test>
    11.8 +         bool do_mark_forwardee>
    11.9  class G1ParCopyClosure;
   11.10  class G1ParScanClosure;
   11.11 +class G1ParPushHeapRSClosure;
   11.12  
   11.13 -typedef G1ParCopyClosure<false, G1BarrierEvac, false, true> G1ParScanHeapEvacClosure;
   11.14 +typedef G1ParCopyClosure<false, G1BarrierEvac, false> G1ParScanHeapEvacClosure;
   11.15  
   11.16  class FilterIntoCSClosure;
   11.17  class FilterOutOfRegionClosure;
   11.18 @@ -51,6 +52,7 @@
   11.19  #define FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES(f) \
   11.20        f(G1ParScanHeapEvacClosure,_nv)                   \
   11.21        f(G1ParScanClosure,_nv)                           \
   11.22 +      f(G1ParPushHeapRSClosure,_nv)                     \
   11.23        f(FilterIntoCSClosure,_nv)                        \
   11.24        f(FilterOutOfRegionClosure,_nv)                   \
   11.25        f(FilterInHeapRegionAndIntoCSClosure,_nv)         \
    12.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Fri Feb 12 15:27:36 2010 -0800
    12.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp	Tue Feb 16 14:11:44 2010 -0800
    12.3 @@ -258,42 +258,6 @@
    12.4      ReserveParTableExpansion = 1
    12.5    };
    12.6  
    12.7 -  void par_expand() {
    12.8 -    int n = HeapRegionRemSet::num_par_rem_sets()-1;
    12.9 -    if (n <= 0) return;
   12.10 -    if (_par_tables == NULL) {
   12.11 -      PerRegionTable* res =
   12.12 -        (PerRegionTable*)
   12.13 -        Atomic::cmpxchg_ptr((PerRegionTable*)ReserveParTableExpansion,
   12.14 -                            &_par_tables, NULL);
   12.15 -      if (res != NULL) return;
   12.16 -      // Otherwise, we reserved the right to do the expansion.
   12.17 -
   12.18 -      PerRegionTable** ptables = NEW_C_HEAP_ARRAY(PerRegionTable*, n);
   12.19 -      for (int i = 0; i < n; i++) {
   12.20 -        PerRegionTable* ptable = PerRegionTable::alloc(hr());
   12.21 -        ptables[i] = ptable;
   12.22 -      }
   12.23 -      // Here we do not need an atomic.
   12.24 -      _par_tables = ptables;
   12.25 -#if COUNT_PAR_EXPANDS
   12.26 -      print_par_expand();
   12.27 -#endif
   12.28 -      // We must put this table on the expanded list.
   12.29 -      PosParPRT* exp_head = _par_expanded_list;
   12.30 -      while (true) {
   12.31 -        set_next_par_expanded(exp_head);
   12.32 -        PosParPRT* res =
   12.33 -          (PosParPRT*)
   12.34 -          Atomic::cmpxchg_ptr(this, &_par_expanded_list, exp_head);
   12.35 -        if (res == exp_head) return;
   12.36 -        // Otherwise.
   12.37 -        exp_head = res;
   12.38 -      }
   12.39 -      ShouldNotReachHere();
   12.40 -    }
   12.41 -  }
   12.42 -
   12.43    void par_contract() {
   12.44      assert(_par_tables != NULL, "Precondition.");
   12.45      int n = HeapRegionRemSet::num_par_rem_sets()-1;
   12.46 @@ -391,13 +355,49 @@
   12.47    void set_next(PosParPRT* nxt) { _next = nxt; }
   12.48    PosParPRT** next_addr() { return &_next; }
   12.49  
   12.50 +  bool should_expand(int tid) {
   12.51 +    return par_tables() == NULL && tid > 0 && hr()->is_gc_alloc_region();
   12.52 +  }
   12.53 +
   12.54 +  void par_expand() {
   12.55 +    int n = HeapRegionRemSet::num_par_rem_sets()-1;
   12.56 +    if (n <= 0) return;
   12.57 +    if (_par_tables == NULL) {
   12.58 +      PerRegionTable* res =
   12.59 +        (PerRegionTable*)
   12.60 +        Atomic::cmpxchg_ptr((PerRegionTable*)ReserveParTableExpansion,
   12.61 +                            &_par_tables, NULL);
   12.62 +      if (res != NULL) return;
   12.63 +      // Otherwise, we reserved the right to do the expansion.
   12.64 +
   12.65 +      PerRegionTable** ptables = NEW_C_HEAP_ARRAY(PerRegionTable*, n);
   12.66 +      for (int i = 0; i < n; i++) {
   12.67 +        PerRegionTable* ptable = PerRegionTable::alloc(hr());
   12.68 +        ptables[i] = ptable;
   12.69 +      }
   12.70 +      // Here we do not need an atomic.
   12.71 +      _par_tables = ptables;
   12.72 +#if COUNT_PAR_EXPANDS
   12.73 +      print_par_expand();
   12.74 +#endif
   12.75 +      // We must put this table on the expanded list.
   12.76 +      PosParPRT* exp_head = _par_expanded_list;
   12.77 +      while (true) {
   12.78 +        set_next_par_expanded(exp_head);
   12.79 +        PosParPRT* res =
   12.80 +          (PosParPRT*)
   12.81 +          Atomic::cmpxchg_ptr(this, &_par_expanded_list, exp_head);
   12.82 +        if (res == exp_head) return;
   12.83 +        // Otherwise.
   12.84 +        exp_head = res;
   12.85 +      }
   12.86 +      ShouldNotReachHere();
   12.87 +    }
   12.88 +  }
   12.89 +
   12.90    void add_reference(OopOrNarrowOopStar from, int tid) {
   12.91      // Expand if necessary.
   12.92      PerRegionTable** pt = par_tables();
   12.93 -    if (par_tables() == NULL && tid > 0 && hr()->is_gc_alloc_region()) {
   12.94 -      par_expand();
   12.95 -      pt = par_tables();
   12.96 -    }
   12.97      if (pt != NULL) {
   12.98        // We always have to assume that mods to table 0 are in parallel,
   12.99        // because of the claiming scheme in parallel expansion.  A thread
  12.100 @@ -505,12 +505,13 @@
  12.101    typedef PosParPRT* PosParPRTPtr;
  12.102    if (_max_fine_entries == 0) {
  12.103      assert(_mod_max_fine_entries_mask == 0, "Both or none.");
  12.104 -    _max_fine_entries = (size_t)(1 << G1LogRSRegionEntries);
  12.105 +    size_t max_entries_log = (size_t)log2_long((jlong)G1RSetRegionEntries);
  12.106 +    _max_fine_entries = (size_t)(1 << max_entries_log);
  12.107      _mod_max_fine_entries_mask = _max_fine_entries - 1;
  12.108  #if SAMPLE_FOR_EVICTION
  12.109      assert(_fine_eviction_sample_size == 0
  12.110             && _fine_eviction_stride == 0, "All init at same time.");
  12.111 -    _fine_eviction_sample_size = MAX2((size_t)4, (size_t)G1LogRSRegionEntries);
  12.112 +    _fine_eviction_sample_size = MAX2((size_t)4, max_entries_log);
  12.113      _fine_eviction_stride = _max_fine_entries / _fine_eviction_sample_size;
  12.114  #endif
  12.115    }
  12.116 @@ -655,13 +656,6 @@
  12.117  #endif
  12.118        }
  12.119  
  12.120 -      // Otherwise, transfer from sparse to fine-grain.
  12.121 -      CardIdx_t cards[SparsePRTEntry::CardsPerEntry];
  12.122 -      if (G1HRRSUseSparseTable) {
  12.123 -        bool res = _sparse_table.get_cards(from_hrs_ind, &cards[0]);
  12.124 -        assert(res, "There should have been an entry");
  12.125 -      }
  12.126 -
  12.127        if (_n_fine_entries == _max_fine_entries) {
  12.128          prt = delete_region_table();
  12.129        } else {
  12.130 @@ -676,10 +670,12 @@
  12.131        _fine_grain_regions[ind] = prt;
  12.132        _n_fine_entries++;
  12.133  
  12.134 -      // Add in the cards from the sparse table.
  12.135        if (G1HRRSUseSparseTable) {
  12.136 -        for (int i = 0; i < SparsePRTEntry::CardsPerEntry; i++) {
  12.137 -          CardIdx_t c = cards[i];
  12.138 +        // Transfer from sparse to fine-grain.
  12.139 +        SparsePRTEntry *sprt_entry = _sparse_table.get_entry(from_hrs_ind);
  12.140 +        assert(sprt_entry != NULL, "There should have been an entry");
  12.141 +        for (int i = 0; i < SparsePRTEntry::cards_num(); i++) {
  12.142 +          CardIdx_t c = sprt_entry->card(i);
  12.143            if (c != SparsePRTEntry::NullEntry) {
  12.144              prt->add_card(c);
  12.145            }
  12.146 @@ -696,7 +692,21 @@
  12.147    // OtherRegionsTable for why this is OK.
  12.148    assert(prt != NULL, "Inv");
  12.149  
  12.150 -  prt->add_reference(from, tid);
  12.151 +  if (prt->should_expand(tid)) {
  12.152 +    MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
  12.153 +    HeapRegion* prt_hr = prt->hr();
  12.154 +    if (prt_hr == from_hr) {
  12.155 +      // Make sure the table still corresponds to the same region
  12.156 +      prt->par_expand();
  12.157 +      prt->add_reference(from, tid);
  12.158 +    }
  12.159 +    // else: The table has been concurrently coarsened, evicted, and
  12.160 +    // the table data structure re-used for another table. So, we
  12.161 +    // don't need to add the reference any more given that the table
  12.162 +    // has been coarsened and the whole region will be scanned anyway.
  12.163 +  } else {
  12.164 +    prt->add_reference(from, tid);
  12.165 +  }
  12.166    if (G1RecordHRRSOops) {
  12.167      HeapRegionRemSet::record(hr(), from);
  12.168  #if HRRS_VERBOSE
  12.169 @@ -1070,6 +1080,19 @@
  12.170  {}
  12.171  
  12.172  
  12.173 +void HeapRegionRemSet::setup_remset_size() {
  12.174 +  // Setup sparse and fine-grain tables sizes.
  12.175 +  // table_size = base * (log(region_size / 1M) + 1)
  12.176 +  int region_size_log_mb = MAX2((int)HeapRegion::LogOfHRGrainBytes - (int)LOG_M, 0);
  12.177 +  if (FLAG_IS_DEFAULT(G1RSetSparseRegionEntries)) {
  12.178 +    G1RSetSparseRegionEntries = G1RSetSparseRegionEntriesBase * (region_size_log_mb + 1);
  12.179 +  }
  12.180 +  if (FLAG_IS_DEFAULT(G1RSetRegionEntries)) {
  12.181 +    G1RSetRegionEntries = G1RSetRegionEntriesBase * (region_size_log_mb + 1);
  12.182 +  }
  12.183 +  guarantee(G1RSetSparseRegionEntries > 0 && G1RSetRegionEntries > 0 , "Sanity");
  12.184 +}
  12.185 +
  12.186  void HeapRegionRemSet::init_for_par_iteration() {
  12.187    _iter_state = Unclaimed;
  12.188  }
  12.189 @@ -1385,7 +1408,7 @@
  12.190    os::sleep(Thread::current(), (jlong)5000, false);
  12.191    G1CollectedHeap* g1h = G1CollectedHeap::heap();
  12.192  
  12.193 -  // Run with "-XX:G1LogRSRegionEntries=2", so that 1 and 5 end up in same
  12.194 +  // Run with "-XX:G1LogRSetRegionEntries=2", so that 1 and 5 end up in same
  12.195    // hash bucket.
  12.196    HeapRegion* hr0 = g1h->region_at(0);
  12.197    HeapRegion* hr1 = g1h->region_at(1);
    13.1 --- a/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Fri Feb 12 15:27:36 2010 -0800
    13.2 +++ b/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp	Tue Feb 16 14:11:44 2010 -0800
    13.3 @@ -187,7 +187,8 @@
    13.4    void clear_outgoing_entries();
    13.5  
    13.6    enum ParIterState { Unclaimed, Claimed, Complete };
    13.7 -  ParIterState _iter_state;
    13.8 +  volatile ParIterState _iter_state;
    13.9 +  volatile jlong _iter_claimed;
   13.10  
   13.11    // Unused unless G1RecordHRRSOops is true.
   13.12  
   13.13 @@ -209,6 +210,7 @@
   13.14                     HeapRegion* hr);
   13.15  
   13.16    static int num_par_rem_sets();
   13.17 +  static void setup_remset_size();
   13.18  
   13.19    HeapRegion* hr() const {
   13.20      return _other_regions.hr();
   13.21 @@ -272,6 +274,19 @@
   13.22    // Returns "true" iff the region's iteration is complete.
   13.23    bool iter_is_complete();
   13.24  
   13.25 +  // Support for claiming blocks of cards during iteration
   13.26 +  void set_iter_claimed(size_t x) { _iter_claimed = (jlong)x; }
   13.27 +  size_t iter_claimed() const { return (size_t)_iter_claimed; }
   13.28 +  // Claim the next block of cards
   13.29 +  size_t iter_claimed_next(size_t step) {
   13.30 +    size_t current, next;
   13.31 +    do {
   13.32 +      current = iter_claimed();
   13.33 +      next = current + step;
   13.34 +    } while (Atomic::cmpxchg((jlong)next, &_iter_claimed, (jlong)current) != (jlong)current);
   13.35 +    return current;
   13.36 +  }
   13.37 +
   13.38    // Initialize the given iterator to iterate over this rem set.
   13.39    void init_iterator(HeapRegionRemSetIterator* iter) const;
   13.40  
    14.1 --- a/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Fri Feb 12 15:27:36 2010 -0800
    14.2 +++ b/src/share/vm/gc_implementation/g1/sparsePRT.cpp	Tue Feb 16 14:11:44 2010 -0800
    14.3 @@ -27,7 +27,7 @@
    14.4  
    14.5  #define SPARSE_PRT_VERBOSE 0
    14.6  
    14.7 -#define UNROLL_CARD_LOOPS 1
    14.8 +#define UNROLL_CARD_LOOPS  1
    14.9  
   14.10  void SparsePRT::init_iterator(SparsePRTIter* sprt_iter) {
   14.11      sprt_iter->init(this);
   14.12 @@ -36,27 +36,32 @@
   14.13  void SparsePRTEntry::init(RegionIdx_t region_ind) {
   14.14    _region_ind = region_ind;
   14.15    _next_index = NullEntry;
   14.16 +
   14.17  #if UNROLL_CARD_LOOPS
   14.18 -  assert(CardsPerEntry == 4, "Assumption.  If changes, un-unroll.");
   14.19 -  _cards[0] = NullEntry;
   14.20 -  _cards[1] = NullEntry;
   14.21 -  _cards[2] = NullEntry;
   14.22 -  _cards[3] = NullEntry;
   14.23 +  assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry");
   14.24 +  for (int i = 0; i < cards_num(); i += UnrollFactor) {
   14.25 +    _cards[i] = NullEntry;
   14.26 +    _cards[i + 1] = NullEntry;
   14.27 +    _cards[i + 2] = NullEntry;
   14.28 +    _cards[i + 3] = NullEntry;
   14.29 +  }
   14.30  #else
   14.31 -  for (int i = 0; i < CardsPerEntry; i++)
   14.32 +  for (int i = 0; i < cards_num(); i++)
   14.33      _cards[i] = NullEntry;
   14.34  #endif
   14.35  }
   14.36  
   14.37  bool SparsePRTEntry::contains_card(CardIdx_t card_index) const {
   14.38  #if UNROLL_CARD_LOOPS
   14.39 -  assert(CardsPerEntry == 4, "Assumption.  If changes, un-unroll.");
   14.40 -  if (_cards[0] == card_index) return true;
   14.41 -  if (_cards[1] == card_index) return true;
   14.42 -  if (_cards[2] == card_index) return true;
   14.43 -  if (_cards[3] == card_index) return true;
   14.44 +  assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry");
   14.45 +  for (int i = 0; i < cards_num(); i += UnrollFactor) {
   14.46 +    if (_cards[i] == card_index ||
   14.47 +        _cards[i + 1] == card_index ||
   14.48 +        _cards[i + 2] == card_index ||
   14.49 +        _cards[i + 3] == card_index) return true;
   14.50 +  }
   14.51  #else
   14.52 -  for (int i = 0; i < CardsPerEntry; i++) {
   14.53 +  for (int i = 0; i < cards_num(); i++) {
   14.54      if (_cards[i] == card_index) return true;
   14.55    }
   14.56  #endif
   14.57 @@ -67,14 +72,16 @@
   14.58  int SparsePRTEntry::num_valid_cards() const {
   14.59    int sum = 0;
   14.60  #if UNROLL_CARD_LOOPS
   14.61 -  assert(CardsPerEntry == 4, "Assumption.  If changes, un-unroll.");
   14.62 -  if (_cards[0] != NullEntry) sum++;
   14.63 -  if (_cards[1] != NullEntry) sum++;
   14.64 -  if (_cards[2] != NullEntry) sum++;
   14.65 -  if (_cards[3] != NullEntry) sum++;
   14.66 +  assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry");
   14.67 +  for (int i = 0; i < cards_num(); i += UnrollFactor) {
   14.68 +    sum += (_cards[i] != NullEntry);
   14.69 +    sum += (_cards[i + 1] != NullEntry);
   14.70 +    sum += (_cards[i + 2] != NullEntry);
   14.71 +    sum += (_cards[i + 3] != NullEntry);
   14.72 +  }
   14.73  #else
   14.74 -  for (int i = 0; i < CardsPerEntry; i++) {
   14.75 -    if (_cards[i] != NulLEntry) sum++;
   14.76 +  for (int i = 0; i < cards_num(); i++) {
   14.77 +    sum += (_cards[i] != NullEntry);
   14.78    }
   14.79  #endif
   14.80    // Otherwise, we're full.
   14.81 @@ -83,27 +90,27 @@
   14.82  
   14.83  SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(CardIdx_t card_index) {
   14.84  #if UNROLL_CARD_LOOPS
   14.85 -  assert(CardsPerEntry == 4, "Assumption.  If changes, un-unroll.");
   14.86 -  CardIdx_t c = _cards[0];
   14.87 -  if (c == card_index) return found;
   14.88 -  if (c == NullEntry) { _cards[0] = card_index; return added; }
   14.89 -  c = _cards[1];
   14.90 -  if (c == card_index) return found;
   14.91 -  if (c == NullEntry) { _cards[1] = card_index; return added; }
   14.92 -  c = _cards[2];
   14.93 -  if (c == card_index) return found;
   14.94 -  if (c == NullEntry) { _cards[2] = card_index; return added; }
   14.95 -  c = _cards[3];
   14.96 -  if (c == card_index) return found;
   14.97 -  if (c == NullEntry) { _cards[3] = card_index; return added; }
   14.98 +  assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry");
   14.99 +  CardIdx_t c;
  14.100 +  for (int i = 0; i < cards_num(); i += UnrollFactor) {
  14.101 +    c = _cards[i];
  14.102 +    if (c == card_index) return found;
  14.103 +    if (c == NullEntry) { _cards[i] = card_index; return added; }
  14.104 +    c = _cards[i + 1];
  14.105 +    if (c == card_index) return found;
  14.106 +    if (c == NullEntry) { _cards[i + 1] = card_index; return added; }
  14.107 +    c = _cards[i + 2];
  14.108 +    if (c == card_index) return found;
  14.109 +    if (c == NullEntry) { _cards[i + 2] = card_index; return added; }
  14.110 +    c = _cards[i + 3];
  14.111 +    if (c == card_index) return found;
  14.112 +    if (c == NullEntry) { _cards[i + 3] = card_index; return added; }
  14.113 +  }
  14.114  #else
  14.115 -  for (int i = 0; i < CardsPerEntry; i++) {
  14.116 +  for (int i = 0; i < cards_num(); i++) {
  14.117      CardIdx_t c = _cards[i];
  14.118      if (c == card_index) return found;
  14.119 -    if (c == NullEntry) {
  14.120 -      _cards[i] = card_index;
  14.121 -      return added;
  14.122 -    }
  14.123 +    if (c == NullEntry) { _cards[i] = card_index; return added; }
  14.124    }
  14.125  #endif
  14.126    // Otherwise, we're full.
  14.127 @@ -112,13 +119,15 @@
  14.128  
  14.129  void SparsePRTEntry::copy_cards(CardIdx_t* cards) const {
  14.130  #if UNROLL_CARD_LOOPS
  14.131 -  assert(CardsPerEntry == 4, "Assumption.  If changes, un-unroll.");
  14.132 -  cards[0] = _cards[0];
  14.133 -  cards[1] = _cards[1];
  14.134 -  cards[2] = _cards[2];
  14.135 -  cards[3] = _cards[3];
  14.136 +  assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry");
  14.137 +  for (int i = 0; i < cards_num(); i += UnrollFactor) {
  14.138 +    cards[i] = _cards[i];
  14.139 +    cards[i + 1] = _cards[i + 1];
  14.140 +    cards[i + 2] = _cards[i + 2];
  14.141 +    cards[i + 3] = _cards[i + 3];
  14.142 +  }
  14.143  #else
  14.144 -  for (int i = 0; i < CardsPerEntry; i++) {
  14.145 +  for (int i = 0; i < cards_num(); i++) {
  14.146      cards[i] = _cards[i];
  14.147    }
  14.148  #endif
  14.149 @@ -133,7 +142,7 @@
  14.150  RSHashTable::RSHashTable(size_t capacity) :
  14.151    _capacity(capacity), _capacity_mask(capacity-1),
  14.152    _occupied_entries(0), _occupied_cards(0),
  14.153 -  _entries(NEW_C_HEAP_ARRAY(SparsePRTEntry, capacity)),
  14.154 +  _entries((SparsePRTEntry*)NEW_C_HEAP_ARRAY(char, SparsePRTEntry::size() * capacity)),
  14.155    _buckets(NEW_C_HEAP_ARRAY(int, capacity)),
  14.156    _free_list(NullEntry), _free_region(0)
  14.157  {
  14.158 @@ -161,8 +170,8 @@
  14.159                  "_capacity too large");
  14.160  
  14.161    // This will put -1 == NullEntry in the key field of all entries.
  14.162 -  memset(_entries, -1, _capacity * sizeof(SparsePRTEntry));
  14.163 -  memset(_buckets, -1, _capacity * sizeof(int));
  14.164 +  memset(_entries, NullEntry, _capacity * SparsePRTEntry::size());
  14.165 +  memset(_buckets, NullEntry, _capacity * sizeof(int));
  14.166    _free_list = NullEntry;
  14.167    _free_region = 0;
  14.168  }
  14.169 @@ -175,8 +184,8 @@
  14.170    if (res == SparsePRTEntry::added) _occupied_cards++;
  14.171  #if SPARSE_PRT_VERBOSE
  14.172    gclog_or_tty->print_cr("       after add_card[%d]: valid-cards = %d.",
  14.173 -                pointer_delta(e, _entries, sizeof(SparsePRTEntry)),
  14.174 -                e->num_valid_cards());
  14.175 +                         pointer_delta(e, _entries, SparsePRTEntry::size()),
  14.176 +                         e->num_valid_cards());
  14.177  #endif
  14.178    assert(e->num_valid_cards() > 0, "Postcondition");
  14.179    return res != SparsePRTEntry::overflow;
  14.180 @@ -199,6 +208,22 @@
  14.181    return true;
  14.182  }
  14.183  
  14.184 +SparsePRTEntry* RSHashTable::get_entry(RegionIdx_t region_ind) {
  14.185 +  int ind = (int) (region_ind & capacity_mask());
  14.186 +  int cur_ind = _buckets[ind];
  14.187 +  SparsePRTEntry* cur;
  14.188 +  while (cur_ind != NullEntry &&
  14.189 +         (cur = entry(cur_ind))->r_ind() != region_ind) {
  14.190 +    cur_ind = cur->next_index();
  14.191 +  }
  14.192 +
  14.193 +  if (cur_ind == NullEntry) return NULL;
  14.194 +  // Otherwise...
  14.195 +  assert(cur->r_ind() == region_ind, "Postcondition of loop + test above.");
  14.196 +  assert(cur->num_valid_cards() > 0, "Inv");
  14.197 +  return cur;
  14.198 +}
  14.199 +
  14.200  bool RSHashTable::delete_entry(RegionIdx_t region_ind) {
  14.201    int ind = (int) (region_ind & capacity_mask());
  14.202    int* prev_loc = &_buckets[ind];
  14.203 @@ -225,20 +250,8 @@
  14.204    int ind = (int) (region_ind & capacity_mask());
  14.205    int cur_ind = _buckets[ind];
  14.206    SparsePRTEntry* cur;
  14.207 -  // XXX
  14.208 -  // int k = 0;
  14.209    while (cur_ind != NullEntry &&
  14.210           (cur = entry(cur_ind))->r_ind() != region_ind) {
  14.211 -    /*
  14.212 -    k++;
  14.213 -    if (k > 10) {
  14.214 -      gclog_or_tty->print_cr("RSHashTable::entry_for_region_ind(%d): "
  14.215 -                    "k = %d, cur_ind = %d.", region_ind, k, cur_ind);
  14.216 -      if (k >= 1000) {
  14.217 -        while (1) ;
  14.218 -      }
  14.219 -    }
  14.220 -    */
  14.221      cur_ind = cur->next_index();
  14.222    }
  14.223  
  14.224 @@ -319,7 +332,7 @@
  14.225  bool /* RSHashTable:: */ RSHashTableIter::has_next(size_t& card_index) {
  14.226    _card_ind++;
  14.227    CardIdx_t ci;
  14.228 -  if (_card_ind < SparsePRTEntry::CardsPerEntry &&
  14.229 +  if (_card_ind < SparsePRTEntry::cards_num() &&
  14.230        ((ci = _rsht->entry(_bl_ind)->card(_card_ind)) !=
  14.231         SparsePRTEntry::NullEntry)) {
  14.232      card_index = compute_card_ind(ci);
  14.233 @@ -359,7 +372,7 @@
  14.234  
  14.235  size_t RSHashTable::mem_size() const {
  14.236    return sizeof(this) +
  14.237 -    capacity() * (sizeof(SparsePRTEntry) + sizeof(int));
  14.238 +    capacity() * (SparsePRTEntry::size() + sizeof(int));
  14.239  }
  14.240  
  14.241  // ----------------------------------------------------------------------
  14.242 @@ -446,6 +459,10 @@
  14.243    return _next->get_cards(region_id, cards);
  14.244  }
  14.245  
  14.246 +SparsePRTEntry* SparsePRT::get_entry(RegionIdx_t region_id) {
  14.247 +  return _next->get_entry(region_id);
  14.248 +}
  14.249 +
  14.250  bool SparsePRT::delete_entry(RegionIdx_t region_id) {
  14.251    return _next->delete_entry(region_id);
  14.252  }
    15.1 --- a/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Fri Feb 12 15:27:36 2010 -0800
    15.2 +++ b/src/share/vm/gc_implementation/g1/sparsePRT.hpp	Tue Feb 16 14:11:44 2010 -0800
    15.3 @@ -32,21 +32,28 @@
    15.4  // insertions only enqueue old versions for deletions, but do not delete
    15.5  // old versions synchronously.
    15.6  
    15.7 -
    15.8  class SparsePRTEntry: public CHeapObj {
    15.9  public:
   15.10 -
   15.11    enum SomePublicConstants {
   15.12 -    CardsPerEntry =  4,
   15.13 -    NullEntry     = -1
   15.14 +    NullEntry     = -1,
   15.15 +    UnrollFactor  =  4
   15.16    };
   15.17 -
   15.18  private:
   15.19    RegionIdx_t _region_ind;
   15.20    int         _next_index;
   15.21 -  CardIdx_t   _cards[CardsPerEntry];
   15.22 -
   15.23 +  CardIdx_t   _cards[1];
   15.24 +  // WARNING: Don't put any data members beyond this line. Card array has, in fact, variable length.
   15.25 +  // It should always be the last data member.
   15.26  public:
   15.27 +  // Returns the size of the entry, used for entry allocation.
   15.28 +  static size_t size() { return sizeof(SparsePRTEntry) + sizeof(CardIdx_t) * (cards_num() - 1); }
   15.29 +  // Returns the size of the card array.
   15.30 +  static int cards_num() {
   15.31 +    // The number of cards should be a multiple of 4, because that's our current
   15.32 +    // unrolling factor.
   15.33 +    static const int s = MAX2<int>(G1RSetSparseRegionEntries & ~(UnrollFactor - 1), UnrollFactor);
   15.34 +    return s;
   15.35 +  }
   15.36  
   15.37    // Set the region_ind to the given value, and delete all cards.
   15.38    inline void init(RegionIdx_t region_ind);
   15.39 @@ -134,12 +141,15 @@
   15.40    bool add_card(RegionIdx_t region_id, CardIdx_t card_index);
   15.41  
   15.42    bool get_cards(RegionIdx_t region_id, CardIdx_t* cards);
   15.43 +
   15.44    bool delete_entry(RegionIdx_t region_id);
   15.45  
   15.46    bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const;
   15.47  
   15.48    void add_entry(SparsePRTEntry* e);
   15.49  
   15.50 +  SparsePRTEntry* get_entry(RegionIdx_t region_id);
   15.51 +
   15.52    void clear();
   15.53  
   15.54    size_t capacity() const      { return _capacity;       }
   15.55 @@ -148,7 +158,7 @@
   15.56    size_t occupied_cards() const   { return _occupied_cards;   }
   15.57    size_t mem_size() const;
   15.58  
   15.59 -  SparsePRTEntry* entry(int i) const { return &_entries[i]; }
   15.60 +  SparsePRTEntry* entry(int i) const { return (SparsePRTEntry*)((char*)_entries + SparsePRTEntry::size() * i); }
   15.61  
   15.62    void print();
   15.63  };
   15.64 @@ -157,7 +167,7 @@
   15.65  class RSHashTableIter VALUE_OBJ_CLASS_SPEC {
   15.66    int _tbl_ind;         // [-1, 0.._rsht->_capacity)
   15.67    int _bl_ind;          // [-1, 0.._rsht->_capacity)
   15.68 -  short _card_ind;      // [0..CardsPerEntry)
   15.69 +  short _card_ind;      // [0..SparsePRTEntry::cards_num())
   15.70    RSHashTable* _rsht;
   15.71    size_t _heap_bot_card_ind;
   15.72  
   15.73 @@ -176,7 +186,7 @@
   15.74    RSHashTableIter(size_t heap_bot_card_ind) :
   15.75      _tbl_ind(RSHashTable::NullEntry),
   15.76      _bl_ind(RSHashTable::NullEntry),
   15.77 -    _card_ind((SparsePRTEntry::CardsPerEntry-1)),
   15.78 +    _card_ind((SparsePRTEntry::cards_num() - 1)),
   15.79      _rsht(NULL),
   15.80      _heap_bot_card_ind(heap_bot_card_ind)
   15.81    {}
   15.82 @@ -185,7 +195,7 @@
   15.83      _rsht = rsht;
   15.84      _tbl_ind = -1; // So that first increment gets to 0.
   15.85      _bl_ind = RSHashTable::NullEntry;
   15.86 -    _card_ind = (SparsePRTEntry::CardsPerEntry-1);
   15.87 +    _card_ind = (SparsePRTEntry::cards_num() - 1);
   15.88    }
   15.89  
   15.90    bool has_next(size_t& card_index);
   15.91 @@ -241,9 +251,13 @@
   15.92  
   15.93    // If the table hold an entry for "region_ind",  Copies its
   15.94    // cards into "cards", which must be an array of length at least
   15.95 -  // "CardsPerEntry", and returns "true"; otherwise, returns "false".
   15.96 +  // "SparePRTEntry::cards_num()", and returns "true"; otherwise,
   15.97 +  // returns "false".
   15.98    bool get_cards(RegionIdx_t region_ind, CardIdx_t* cards);
   15.99  
  15.100 +  // Return the pointer to the entry associated with the given region.
  15.101 +  SparsePRTEntry* get_entry(RegionIdx_t region_ind);
  15.102 +
  15.103    // If there is an entry for "region_ind", removes it and return "true";
  15.104    // otherwise returns "false."
  15.105    bool delete_entry(RegionIdx_t region_ind);
    16.1 --- a/src/share/vm/includeDB_core	Fri Feb 12 15:27:36 2010 -0800
    16.2 +++ b/src/share/vm/includeDB_core	Tue Feb 16 14:11:44 2010 -0800
    16.3 @@ -2655,6 +2655,7 @@
    16.4  loaderConstraints.cpp                   safepoint.hpp
    16.5  
    16.6  loaderConstraints.hpp                   dictionary.hpp
    16.7 +loaderConstraints.hpp                   placeholders.hpp
    16.8  loaderConstraints.hpp                   hashtable.hpp
    16.9  
   16.10  location.cpp                            debugInfo.hpp
    17.1 --- a/src/share/vm/memory/cardTableModRefBS.hpp	Fri Feb 12 15:27:36 2010 -0800
    17.2 +++ b/src/share/vm/memory/cardTableModRefBS.hpp	Tue Feb 16 14:11:44 2010 -0800
    17.3 @@ -339,6 +339,16 @@
    17.4      return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val();
    17.5    }
    17.6  
    17.7 +  void set_card_claimed(size_t card_index) {
    17.8 +      jbyte val = _byte_map[card_index];
    17.9 +      if (val == clean_card_val()) {
   17.10 +        val = (jbyte)claimed_card_val();
   17.11 +      } else {
   17.12 +        val |= (jbyte)claimed_card_val();
   17.13 +      }
   17.14 +      _byte_map[card_index] = val;
   17.15 +  }
   17.16 +
   17.17    bool claim_card(size_t card_index);
   17.18  
   17.19    bool is_card_clean(size_t card_index) {
    18.1 --- a/src/share/vm/runtime/vmThread.cpp	Fri Feb 12 15:27:36 2010 -0800
    18.2 +++ b/src/share/vm/runtime/vmThread.cpp	Tue Feb 16 14:11:44 2010 -0800
    18.3 @@ -1,5 +1,5 @@
    18.4  /*
    18.5 - * Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
    18.6 + * Copyright 1998-2010 Sun Microsystems, Inc.  All Rights Reserved.
    18.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    18.8   *
    18.9   * This code is free software; you can redistribute it and/or modify it
   18.10 @@ -426,11 +426,6 @@
   18.11        // follow that also require a safepoint
   18.12        if (_cur_vm_operation->evaluate_at_safepoint()) {
   18.13  
   18.14 -        if (PrintGCApplicationConcurrentTime) {
   18.15 -           gclog_or_tty->print_cr("Application time: %3.7f seconds",
   18.16 -                                  RuntimeService::last_application_time_sec());
   18.17 -        }
   18.18 -
   18.19          _vm_queue->set_drain_list(safepoint_ops); // ensure ops can be scanned
   18.20  
   18.21          SafepointSynchronize::begin();
   18.22 @@ -477,12 +472,6 @@
   18.23          // Complete safepoint synchronization
   18.24          SafepointSynchronize::end();
   18.25  
   18.26 -        if (PrintGCApplicationStoppedTime) {
   18.27 -          gclog_or_tty->print_cr("Total time for which application threads "
   18.28 -                                 "were stopped: %3.7f seconds",
   18.29 -                                 RuntimeService::last_safepoint_time_sec());
   18.30 -        }
   18.31 -
   18.32        } else {  // not a safepoint operation
   18.33          if (TraceLongCompiles) {
   18.34            elapsedTimer t;
    19.1 --- a/src/share/vm/services/runtimeService.cpp	Fri Feb 12 15:27:36 2010 -0800
    19.2 +++ b/src/share/vm/services/runtimeService.cpp	Tue Feb 16 14:11:44 2010 -0800
    19.3 @@ -1,5 +1,5 @@
    19.4  /*
    19.5 - * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
    19.6 + * Copyright 2003-2010 Sun Microsystems, Inc.  All Rights Reserved.
    19.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.8   *
    19.9   * This code is free software; you can redistribute it and/or modify it
   19.10 @@ -104,6 +104,13 @@
   19.11  
   19.12  void RuntimeService::record_safepoint_begin() {
   19.13    HS_DTRACE_PROBE(hs_private, safepoint__begin);
   19.14 +
   19.15 +  // Print the time interval in which the app was executing
   19.16 +  if (PrintGCApplicationConcurrentTime) {
   19.17 +    gclog_or_tty->print_cr("Application time: %3.7f seconds",
   19.18 +                                last_application_time_sec());
   19.19 +  }
   19.20 +
   19.21    // update the time stamp to begin recording safepoint time
   19.22    _safepoint_timer.update();
   19.23    if (UsePerfData) {
   19.24 @@ -122,6 +129,15 @@
   19.25  
   19.26  void RuntimeService::record_safepoint_end() {
   19.27    HS_DTRACE_PROBE(hs_private, safepoint__end);
   19.28 +
   19.29 +  // Print the time interval for which the app was stopped
   19.30 +  // during the current safepoint operation.
   19.31 +  if (PrintGCApplicationStoppedTime) {
   19.32 +    gclog_or_tty->print_cr("Total time for which application threads "
   19.33 +                           "were stopped: %3.7f seconds",
   19.34 +                           last_safepoint_time_sec());
   19.35 +  }
   19.36 +
   19.37    // update the time stamp to begin recording app time
   19.38    _app_timer.update();
   19.39    if (UsePerfData) {
    20.1 --- a/src/share/vm/utilities/globalDefinitions.hpp	Fri Feb 12 15:27:36 2010 -0800
    20.2 +++ b/src/share/vm/utilities/globalDefinitions.hpp	Tue Feb 16 14:11:44 2010 -0800
    20.3 @@ -139,6 +139,10 @@
    20.4  const size_t G                  = M*K;
    20.5  const size_t HWperKB            = K / sizeof(HeapWord);
    20.6  
    20.7 +const size_t LOG_K              = 10;
    20.8 +const size_t LOG_M              = 2 * LOG_K;
    20.9 +const size_t LOG_G              = 2 * LOG_M;
   20.10 +
   20.11  const jint min_jint = (jint)1 << (sizeof(jint)*BitsPerByte-1); // 0x80000000 == smallest jint
   20.12  const jint max_jint = (juint)min_jint - 1;                     // 0x7FFFFFFF == largest jint
   20.13  

mercurial