--- old/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2011-10-03 15:48:25.353517785 -0700 +++ new/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2011-10-03 15:48:25.142070296 -0700 @@ -3883,7 +3883,7 @@ assert(_cm->isPrevMarked(obj), "Should be marked!"); _prev_marked_bytes += (obj_size * HeapWordSize); if (_g1->mark_in_progress() && !_g1->is_obj_ill(obj)) { - _cm->markAndGrayObjectIfNecessary(obj); + _cm->markAndGrayObjectIfNecessary(obj, 0 /* worker_i */); } obj->set_mark(markOopDesc::prototype()); // While we were processing RSet buffers during the @@ -4005,7 +4005,8 @@ oop G1CollectedHeap::handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop old, - bool should_mark_root) { + bool should_mark_root, + int worker_i) { assert(obj_in_cs(old), err_msg("obj: "PTR_FORMAT" should still be in the CSet", (HeapWord*) old)); @@ -4020,7 +4021,7 @@ // object is also responsible for marking the object. if (should_mark_root) { assert(!oopDesc::is_null(old), "shouldn't be"); - _cm->grayRoot(old); + _cm->grayRoot(old, worker_i); } if (_evac_failure_closure != cl) { @@ -4126,10 +4127,11 @@ } #endif // PRODUCT -G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) : +G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size, int worker_i) : ParGCAllocBuffer(gclab_word_size), _should_mark_objects(false), _bitmap(G1CollectedHeap::heap()->reserved_region().start(), gclab_word_size), + _worker_i(worker_i), _retired(false) { //_should_mark_objects is set to true when G1ParCopyHelper needs to @@ -4151,8 +4153,8 @@ _g1_rem(g1h->g1_rem_set()), _hash_seed(17), _queue_num(queue_num), _term_attempts(0), - _surviving_alloc_buffer(g1h->desired_plab_sz(GCAllocForSurvived)), - _tenured_alloc_buffer(g1h->desired_plab_sz(GCAllocForTenured)), + _surviving_alloc_buffer(g1h->desired_plab_sz(GCAllocForSurvived), queue_num), + _tenured_alloc_buffer(g1h->desired_plab_sz(GCAllocForTenured), queue_num), _age_table(false), _strong_roots_time(0), _term_time(0), _alloc_buffer_waste(0), _undo_waste(0) @@ -4264,6 +4266,7 @@ G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : _g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()), _par_scan_state(par_scan_state), + _worker_i(par_scan_state->queue_num()), _during_initial_mark(_g1->g1_policy()->during_initial_mark_pause()), _mark_in_progress(_g1->mark_in_progress()) { } @@ -4277,7 +4280,7 @@ oop obj = oopDesc::decode_heap_oop(heap_oop); HeapWord* addr = (HeapWord*)obj; if (_g1->is_in_g1_reserved(addr)) { - _cm->grayRoot(oop(addr)); + _cm->grayRoot(oop(addr), _worker_i); } } } @@ -4303,7 +4306,7 @@ // This will either forward-to-self, or detect that someone else has // installed a forwarding pointer. OopsInHeapRegionClosure* cl = _par_scan_state->evac_failure_closure(); - return _g1->handle_evacuation_failure_par(cl, old, should_mark_root); + return _g1->handle_evacuation_failure_par(cl, old, should_mark_root, _worker_i); } // We're going to allocate linearly, so might as well prefetch ahead. @@ -4342,17 +4345,33 @@ // Mark the evacuated object or propagate "next" mark bit if (should_mark_copy) { if (!use_local_bitmaps || - !_par_scan_state->alloc_buffer(alloc_purpose)->mark(obj_ptr)) { + !_par_scan_state->alloc_buffer(alloc_purpose)->mark(obj_ptr, word_sz)) { // if we couldn't mark it on the local bitmap (this happens when // the object was not allocated in the GCLab), we have to bite // the bullet and do the standard parallel mark - _cm->markAndGrayObjectIfNecessary(obj); + _cm->markAndGrayObjectIfNecessary(obj, _worker_i); } if (_g1->isMarkedNext(old)) { // Unmark the object's old location so that marking // doesn't think the old object is alive. _cm->nextMarkBitMap()->parClear((HeapWord*)old); + + // We could clear the count data for the old object here but + // currently we do not. Why don't we do this? The thread/task + // that marks a newly copied object is likely _not_ the thread/task + // that originally marked the old object. So, to clear the count + // data for the old object, we would have to scan the count + // data for all of the tasks (and clear the data for the old object + // in parallel with other threads adding to the count data). Even + // then we could clear a bit incorrectly (e.g. if the old object + // does not start or end on a card boundary). It's more important + // that we don't have missed bits that should've been set than + // having extra bits set. + // + // As a result the accumulated count data could be a superset + // of the data that is/would have been calculated by walking + // the marking bitmap. } } @@ -4439,7 +4458,8 @@ } // When scanning the RS, we only care about objs in CS. if (barrier == G1BarrierRS) { - _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); + assert(_worker_i == _par_scan_state->queue_num(), "sanity"); + _par_scan_state->update_rs(_from, p, _worker_i); } } else { // The object is not in collection set. If we're a root scanning @@ -4451,7 +4471,8 @@ } if (barrier == G1BarrierEvac && obj != NULL) { - _par_scan_state->update_rs(_from, p, _par_scan_state->queue_num()); + assert(_worker_i == _par_scan_state->queue_num(), "sanity"); + _par_scan_state->update_rs(_from, p, _worker_i); } if (do_gen_barrier && obj != NULL) {