Tue, 16 Feb 2010 14:11:44 -0800
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