--- old/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2011-12-09 10:54:40.445570695 -0800 +++ new/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2011-12-09 10:54:40.053089419 -0800 @@ -1842,7 +1842,9 @@ _full_collections_completed(0), _in_cset_fast_test(NULL), _in_cset_fast_test_base(NULL), - _dirty_cards_region_list(NULL) { + _dirty_cards_region_list(NULL), + _worker_cset_start_region(NULL), + _worker_cset_start_region_stamp(NULL) { _g1h = this; // To catch bugs. if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) { vm_exit_during_initialization("Failed necessary allocation."); @@ -1863,10 +1865,16 @@ } _rem_set_iterator = iter_arr; + _worker_cset_start_region = NEW_C_HEAP_ARRAY(HeapRegion*, n_queues); + _worker_cset_start_region_stamp = NEW_C_HEAP_ARRAY(unsigned int, n_queues); + for (int i = 0; i < n_queues; i++) { RefToScanQueue* q = new RefToScanQueue(); q->initialize(); _task_queues->register_queue(i, q); + + _worker_cset_start_region[i] = NULL; + _worker_cset_start_region_stamp[i] = 0; } guarantee(_task_queues != NULL, "task_queues allocation failure."); @@ -2684,16 +2692,37 @@ } #endif // ASSERT -// We want the parallel threads to start their collection -// set iteration at different collection set regions to -// avoid contention. -// If we have: -// n collection set regions -// p threads -// Then thread t will start at region t * floor (n/p) - +// Given the id of a worker, obtain or calculate a suitable +// starting region for iterating over the current collection set. HeapRegion* G1CollectedHeap::start_cset_region_for_worker(int worker_i) { - HeapRegion* result = g1_policy()->collection_set(); + assert(_worker_cset_start_region != NULL, "sanity"); + assert(_worker_cset_start_region_stamp != NULL, "sanity"); + assert(total_collections() > 0, "should have been updated by now"); + + HeapRegion* result = NULL; + + if (_worker_cset_start_region_stamp[worker_i] == total_collections()) { + // Cached starting region for current worker was set + // during the current pause - so it's valid. + // Note: the cached starting heap region may be NULL + // (when the collection set is empty). + result = _worker_cset_start_region[worker_i]; + assert(result == NULL || result->in_collection_set(), "sanity"); + return result; + } + + // The cached entry was not valid so let's calculate + // a suitable starting heap region for this worker. + + // We want the parallel threads to start their collection + // set iteration at different collection set regions to + // avoid contention. + // If we have: + // n collection set regions + // p threads + // Then thread t will start at region t * floor (n/p) + + result = g1_policy()->collection_set(); if (G1CollectedHeap::use_parallel_gc_threads()) { size_t cs_size = g1_policy()->cset_region_length(); int n_workers = workers()->total_workers(); @@ -2703,6 +2732,14 @@ result = result->next_in_collection_set(); } } + + // Note: the calculated starting heap region may be NULL + // (when the collection set is empty). + assert(result == NULL || result->in_collection_set(), "sanity"); + assert(_worker_cset_start_region_stamp[worker_i] != total_collections(), + "should be updated only once per pause"); + _worker_cset_start_region[worker_i] = result; + _worker_cset_start_region_stamp[worker_i] = total_collections(); return result; } @@ -3532,7 +3569,7 @@ // Please see comment in g1CollectedHeap.hpp and // G1CollectedHeap::ref_processing_init() to see how // reference processing currently works in G1. - + // Enable discovery in the STW reference processor ref_processor_stw()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); @@ -5249,7 +5286,7 @@ workers()->active_workers() : 1); assert(active_workers == workers()->active_workers(), - "Need to reset active_workers"); + "Need to reset active_workers"); set_par_threads(active_workers); G1ParPreserveCMReferentsTask keep_cm_referents(this, active_workers, _task_queues);