Wed, 01 Oct 2008 15:05:06 -0400
Merge
src/share/vm/runtime/globals.hpp | file | annotate | diff | comparison | revisions |
1.1 --- a/src/share/vm/code/nmethod.cpp Tue Sep 30 15:53:55 2008 -0700 1.2 +++ b/src/share/vm/code/nmethod.cpp Wed Oct 01 15:05:06 2008 -0400 1.3 @@ -1350,11 +1350,7 @@ 1.4 return false; 1.5 } 1.6 } 1.7 - if (!UseParallelOldGC || !VerifyParallelOldWithMarkSweep) { 1.8 - // Cannot do this test if verification of the UseParallelOldGC 1.9 - // code using the PSMarkSweep code is being done. 1.10 - assert(unloading_occurred, "Inconsistency in unloading"); 1.11 - } 1.12 + assert(unloading_occurred, "Inconsistency in unloading"); 1.13 make_unloaded(is_alive, obj); 1.14 return true; 1.15 }
2.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Tue Sep 30 15:53:55 2008 -0700 2.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Wed Oct 01 15:05:06 2008 -0400 2.3 @@ -210,10 +210,6 @@ 2.4 PSScavenge::initialize(); 2.5 if (UseParallelOldGC) { 2.6 PSParallelCompact::post_initialize(); 2.7 - if (VerifyParallelOldWithMarkSweep) { 2.8 - // Will be used for verification of par old. 2.9 - PSMarkSweep::initialize(); 2.10 - } 2.11 } else { 2.12 PSMarkSweep::initialize(); 2.13 } 2.14 @@ -402,7 +398,7 @@ 2.15 return result; 2.16 } 2.17 if (!is_tlab && 2.18 - size >= (young_gen()->eden_space()->capacity_in_words() / 2)) { 2.19 + size >= (young_gen()->eden_space()->capacity_in_words(Thread::current()) / 2)) { 2.20 result = old_gen()->allocate(size, is_tlab); 2.21 if (result != NULL) { 2.22 return result;
3.1 --- a/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Tue Sep 30 15:53:55 2008 -0700 3.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Wed Oct 01 15:05:06 2008 -0400 3.3 @@ -146,7 +146,7 @@ 3.4 { 3.5 ParallelScavengeHeap* heap = PSParallelCompact::gc_heap(); 3.6 uint parallel_gc_threads = heap->gc_task_manager()->workers(); 3.7 - ChunkTaskQueueSet* qset = ParCompactionManager::chunk_array(); 3.8 + RegionTaskQueueSet* qset = ParCompactionManager::region_array(); 3.9 ParallelTaskTerminator terminator(parallel_gc_threads, qset); 3.10 GCTaskQueue* q = GCTaskQueue::create(); 3.11 for(uint i=0; i<parallel_gc_threads; i++) { 3.12 @@ -205,38 +205,38 @@ 3.13 } 3.14 3.15 // 3.16 -// StealChunkCompactionTask 3.17 +// StealRegionCompactionTask 3.18 // 3.19 3.20 3.21 -StealChunkCompactionTask::StealChunkCompactionTask(ParallelTaskTerminator* t) : 3.22 - _terminator(t) {}; 3.23 +StealRegionCompactionTask::StealRegionCompactionTask(ParallelTaskTerminator* t): 3.24 + _terminator(t) {} 3.25 3.26 -void StealChunkCompactionTask::do_it(GCTaskManager* manager, uint which) { 3.27 +void StealRegionCompactionTask::do_it(GCTaskManager* manager, uint which) { 3.28 assert(Universe::heap()->is_gc_active(), "called outside gc"); 3.29 3.30 - NOT_PRODUCT(TraceTime tm("StealChunkCompactionTask", 3.31 + NOT_PRODUCT(TraceTime tm("StealRegionCompactionTask", 3.32 PrintGCDetails && TraceParallelOldGCTasks, true, gclog_or_tty)); 3.33 3.34 ParCompactionManager* cm = 3.35 ParCompactionManager::gc_thread_compaction_manager(which); 3.36 3.37 - // Has to drain stacks first because there may be chunks on 3.38 + // Has to drain stacks first because there may be regions on 3.39 // preloaded onto the stack and this thread may never have 3.40 // done a draining task. Are the draining tasks needed? 3.41 3.42 - cm->drain_chunk_stacks(); 3.43 + cm->drain_region_stacks(); 3.44 3.45 - size_t chunk_index = 0; 3.46 + size_t region_index = 0; 3.47 int random_seed = 17; 3.48 3.49 // If we're the termination task, try 10 rounds of stealing before 3.50 // setting the termination flag 3.51 3.52 while(true) { 3.53 - if (ParCompactionManager::steal(which, &random_seed, chunk_index)) { 3.54 - PSParallelCompact::fill_and_update_chunk(cm, chunk_index); 3.55 - cm->drain_chunk_stacks(); 3.56 + if (ParCompactionManager::steal(which, &random_seed, region_index)) { 3.57 + PSParallelCompact::fill_and_update_region(cm, region_index); 3.58 + cm->drain_region_stacks(); 3.59 } else { 3.60 if (terminator()->offer_termination()) { 3.61 break; 3.62 @@ -249,11 +249,10 @@ 3.63 3.64 UpdateDensePrefixTask::UpdateDensePrefixTask( 3.65 PSParallelCompact::SpaceId space_id, 3.66 - size_t chunk_index_start, 3.67 - size_t chunk_index_end) : 3.68 - _space_id(space_id), _chunk_index_start(chunk_index_start), 3.69 - _chunk_index_end(chunk_index_end) 3.70 -{} 3.71 + size_t region_index_start, 3.72 + size_t region_index_end) : 3.73 + _space_id(space_id), _region_index_start(region_index_start), 3.74 + _region_index_end(region_index_end) {} 3.75 3.76 void UpdateDensePrefixTask::do_it(GCTaskManager* manager, uint which) { 3.77 3.78 @@ -265,8 +264,8 @@ 3.79 3.80 PSParallelCompact::update_and_deadwood_in_dense_prefix(cm, 3.81 _space_id, 3.82 - _chunk_index_start, 3.83 - _chunk_index_end); 3.84 + _region_index_start, 3.85 + _region_index_end); 3.86 } 3.87 3.88 void DrainStacksCompactionTask::do_it(GCTaskManager* manager, uint which) { 3.89 @@ -278,6 +277,6 @@ 3.90 ParCompactionManager* cm = 3.91 ParCompactionManager::gc_thread_compaction_manager(which); 3.92 3.93 - // Process any chunks already in the compaction managers stacks. 3.94 - cm->drain_chunk_stacks(); 3.95 + // Process any regions already in the compaction managers stacks. 3.96 + cm->drain_region_stacks(); 3.97 }
4.1 --- a/src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp Tue Sep 30 15:53:55 2008 -0700 4.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/pcTasks.hpp Wed Oct 01 15:05:06 2008 -0400 4.3 @@ -188,18 +188,18 @@ 4.4 }; 4.5 4.6 // 4.7 -// StealChunkCompactionTask 4.8 +// StealRegionCompactionTask 4.9 // 4.10 // This task is used to distribute work to idle threads. 4.11 // 4.12 4.13 -class StealChunkCompactionTask : public GCTask { 4.14 +class StealRegionCompactionTask : public GCTask { 4.15 private: 4.16 ParallelTaskTerminator* const _terminator; 4.17 public: 4.18 - StealChunkCompactionTask(ParallelTaskTerminator* t); 4.19 + StealRegionCompactionTask(ParallelTaskTerminator* t); 4.20 4.21 - char* name() { return (char *)"steal-chunk-task"; } 4.22 + char* name() { return (char *)"steal-region-task"; } 4.23 ParallelTaskTerminator* terminator() { return _terminator; } 4.24 4.25 virtual void do_it(GCTaskManager* manager, uint which); 4.26 @@ -215,15 +215,15 @@ 4.27 class UpdateDensePrefixTask : public GCTask { 4.28 private: 4.29 PSParallelCompact::SpaceId _space_id; 4.30 - size_t _chunk_index_start; 4.31 - size_t _chunk_index_end; 4.32 + size_t _region_index_start; 4.33 + size_t _region_index_end; 4.34 4.35 public: 4.36 char* name() { return (char *)"update-dense_prefix-task"; } 4.37 4.38 UpdateDensePrefixTask(PSParallelCompact::SpaceId space_id, 4.39 - size_t chunk_index_start, 4.40 - size_t chunk_index_end); 4.41 + size_t region_index_start, 4.42 + size_t region_index_end); 4.43 4.44 virtual void do_it(GCTaskManager* manager, uint which); 4.45 }; 4.46 @@ -231,17 +231,17 @@ 4.47 // 4.48 // DrainStacksCompactionTask 4.49 // 4.50 -// This task processes chunks that have been added to the stacks of each 4.51 +// This task processes regions that have been added to the stacks of each 4.52 // compaction manager. 4.53 // 4.54 // Trying to use one draining thread does not work because there are no 4.55 // guarantees about which task will be picked up by which thread. For example, 4.56 -// if thread A gets all the preloaded chunks, thread A may not get a draining 4.57 +// if thread A gets all the preloaded regions, thread A may not get a draining 4.58 // task (they may all be done by other threads). 4.59 // 4.60 4.61 class DrainStacksCompactionTask : public GCTask { 4.62 public: 4.63 - char* name() { return (char *)"drain-chunk-task"; } 4.64 + char* name() { return (char *)"drain-region-task"; } 4.65 virtual void do_it(GCTaskManager* manager, uint which); 4.66 };
5.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Tue Sep 30 15:53:55 2008 -0700 5.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Wed Oct 01 15:05:06 2008 -0400 5.3 @@ -30,7 +30,7 @@ 5.4 OopTaskQueueSet* ParCompactionManager::_stack_array = NULL; 5.5 ObjectStartArray* ParCompactionManager::_start_array = NULL; 5.6 ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL; 5.7 -ChunkTaskQueueSet* ParCompactionManager::_chunk_array = NULL; 5.8 +RegionTaskQueueSet* ParCompactionManager::_region_array = NULL; 5.9 5.10 ParCompactionManager::ParCompactionManager() : 5.11 _action(CopyAndUpdate) { 5.12 @@ -46,13 +46,13 @@ 5.13 5.14 // We want the overflow stack to be permanent 5.15 _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(10, true); 5.16 -#ifdef USE_ChunkTaskQueueWithOverflow 5.17 - chunk_stack()->initialize(); 5.18 +#ifdef USE_RegionTaskQueueWithOverflow 5.19 + region_stack()->initialize(); 5.20 #else 5.21 - chunk_stack()->initialize(); 5.22 + region_stack()->initialize(); 5.23 5.24 // We want the overflow stack to be permanent 5.25 - _chunk_overflow_stack = 5.26 + _region_overflow_stack = 5.27 new (ResourceObj::C_HEAP) GrowableArray<size_t>(10, true); 5.28 #endif 5.29 5.30 @@ -86,18 +86,18 @@ 5.31 5.32 _stack_array = new OopTaskQueueSet(parallel_gc_threads); 5.33 guarantee(_stack_array != NULL, "Count not initialize promotion manager"); 5.34 - _chunk_array = new ChunkTaskQueueSet(parallel_gc_threads); 5.35 - guarantee(_chunk_array != NULL, "Count not initialize promotion manager"); 5.36 + _region_array = new RegionTaskQueueSet(parallel_gc_threads); 5.37 + guarantee(_region_array != NULL, "Count not initialize promotion manager"); 5.38 5.39 // Create and register the ParCompactionManager(s) for the worker threads. 5.40 for(uint i=0; i<parallel_gc_threads; i++) { 5.41 _manager_array[i] = new ParCompactionManager(); 5.42 guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager"); 5.43 stack_array()->register_queue(i, _manager_array[i]->marking_stack()); 5.44 -#ifdef USE_ChunkTaskQueueWithOverflow 5.45 - chunk_array()->register_queue(i, _manager_array[i]->chunk_stack()->task_queue()); 5.46 +#ifdef USE_RegionTaskQueueWithOverflow 5.47 + region_array()->register_queue(i, _manager_array[i]->region_stack()->task_queue()); 5.48 #else 5.49 - chunk_array()->register_queue(i, _manager_array[i]->chunk_stack()); 5.50 + region_array()->register_queue(i, _manager_array[i]->region_stack()); 5.51 #endif 5.52 } 5.53 5.54 @@ -153,31 +153,31 @@ 5.55 return NULL; 5.56 } 5.57 5.58 -// Save chunk on a stack 5.59 -void ParCompactionManager::save_for_processing(size_t chunk_index) { 5.60 +// Save region on a stack 5.61 +void ParCompactionManager::save_for_processing(size_t region_index) { 5.62 #ifdef ASSERT 5.63 const ParallelCompactData& sd = PSParallelCompact::summary_data(); 5.64 - ParallelCompactData::ChunkData* const chunk_ptr = sd.chunk(chunk_index); 5.65 - assert(chunk_ptr->claimed(), "must be claimed"); 5.66 - assert(chunk_ptr->_pushed++ == 0, "should only be pushed once"); 5.67 + ParallelCompactData::RegionData* const region_ptr = sd.region(region_index); 5.68 + assert(region_ptr->claimed(), "must be claimed"); 5.69 + assert(region_ptr->_pushed++ == 0, "should only be pushed once"); 5.70 #endif 5.71 - chunk_stack_push(chunk_index); 5.72 + region_stack_push(region_index); 5.73 } 5.74 5.75 -void ParCompactionManager::chunk_stack_push(size_t chunk_index) { 5.76 +void ParCompactionManager::region_stack_push(size_t region_index) { 5.77 5.78 -#ifdef USE_ChunkTaskQueueWithOverflow 5.79 - chunk_stack()->save(chunk_index); 5.80 +#ifdef USE_RegionTaskQueueWithOverflow 5.81 + region_stack()->save(region_index); 5.82 #else 5.83 - if(!chunk_stack()->push(chunk_index)) { 5.84 - chunk_overflow_stack()->push(chunk_index); 5.85 + if(!region_stack()->push(region_index)) { 5.86 + region_overflow_stack()->push(region_index); 5.87 } 5.88 #endif 5.89 } 5.90 5.91 -bool ParCompactionManager::retrieve_for_processing(size_t& chunk_index) { 5.92 -#ifdef USE_ChunkTaskQueueWithOverflow 5.93 - return chunk_stack()->retrieve(chunk_index); 5.94 +bool ParCompactionManager::retrieve_for_processing(size_t& region_index) { 5.95 +#ifdef USE_RegionTaskQueueWithOverflow 5.96 + return region_stack()->retrieve(region_index); 5.97 #else 5.98 // Should not be used in the parallel case 5.99 ShouldNotReachHere(); 5.100 @@ -230,14 +230,14 @@ 5.101 assert(overflow_stack()->length() == 0, "Sanity"); 5.102 } 5.103 5.104 -void ParCompactionManager::drain_chunk_overflow_stack() { 5.105 - size_t chunk_index = (size_t) -1; 5.106 - while(chunk_stack()->retrieve_from_overflow(chunk_index)) { 5.107 - PSParallelCompact::fill_and_update_chunk(this, chunk_index); 5.108 +void ParCompactionManager::drain_region_overflow_stack() { 5.109 + size_t region_index = (size_t) -1; 5.110 + while(region_stack()->retrieve_from_overflow(region_index)) { 5.111 + PSParallelCompact::fill_and_update_region(this, region_index); 5.112 } 5.113 } 5.114 5.115 -void ParCompactionManager::drain_chunk_stacks() { 5.116 +void ParCompactionManager::drain_region_stacks() { 5.117 #ifdef ASSERT 5.118 ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); 5.119 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); 5.120 @@ -249,42 +249,42 @@ 5.121 #if 1 // def DO_PARALLEL - the serial code hasn't been updated 5.122 do { 5.123 5.124 -#ifdef USE_ChunkTaskQueueWithOverflow 5.125 +#ifdef USE_RegionTaskQueueWithOverflow 5.126 // Drain overflow stack first, so other threads can steal from 5.127 // claimed stack while we work. 5.128 - size_t chunk_index = (size_t) -1; 5.129 - while(chunk_stack()->retrieve_from_overflow(chunk_index)) { 5.130 - PSParallelCompact::fill_and_update_chunk(this, chunk_index); 5.131 + size_t region_index = (size_t) -1; 5.132 + while(region_stack()->retrieve_from_overflow(region_index)) { 5.133 + PSParallelCompact::fill_and_update_region(this, region_index); 5.134 } 5.135 5.136 - while (chunk_stack()->retrieve_from_stealable_queue(chunk_index)) { 5.137 - PSParallelCompact::fill_and_update_chunk(this, chunk_index); 5.138 + while (region_stack()->retrieve_from_stealable_queue(region_index)) { 5.139 + PSParallelCompact::fill_and_update_region(this, region_index); 5.140 } 5.141 - } while (!chunk_stack()->is_empty()); 5.142 + } while (!region_stack()->is_empty()); 5.143 #else 5.144 // Drain overflow stack first, so other threads can steal from 5.145 // claimed stack while we work. 5.146 - while(!chunk_overflow_stack()->is_empty()) { 5.147 - size_t chunk_index = chunk_overflow_stack()->pop(); 5.148 - PSParallelCompact::fill_and_update_chunk(this, chunk_index); 5.149 + while(!region_overflow_stack()->is_empty()) { 5.150 + size_t region_index = region_overflow_stack()->pop(); 5.151 + PSParallelCompact::fill_and_update_region(this, region_index); 5.152 } 5.153 5.154 - size_t chunk_index = -1; 5.155 + size_t region_index = -1; 5.156 // obj is a reference!!! 5.157 - while (chunk_stack()->pop_local(chunk_index)) { 5.158 + while (region_stack()->pop_local(region_index)) { 5.159 // It would be nice to assert about the type of objects we might 5.160 // pop, but they can come from anywhere, unfortunately. 5.161 - PSParallelCompact::fill_and_update_chunk(this, chunk_index); 5.162 + PSParallelCompact::fill_and_update_region(this, region_index); 5.163 } 5.164 - } while((chunk_stack()->size() != 0) || 5.165 - (chunk_overflow_stack()->length() != 0)); 5.166 + } while((region_stack()->size() != 0) || 5.167 + (region_overflow_stack()->length() != 0)); 5.168 #endif 5.169 5.170 -#ifdef USE_ChunkTaskQueueWithOverflow 5.171 - assert(chunk_stack()->is_empty(), "Sanity"); 5.172 +#ifdef USE_RegionTaskQueueWithOverflow 5.173 + assert(region_stack()->is_empty(), "Sanity"); 5.174 #else 5.175 - assert(chunk_stack()->size() == 0, "Sanity"); 5.176 - assert(chunk_overflow_stack()->length() == 0, "Sanity"); 5.177 + assert(region_stack()->size() == 0, "Sanity"); 5.178 + assert(region_overflow_stack()->length() == 0, "Sanity"); 5.179 #endif 5.180 #else 5.181 oop obj;
6.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp Tue Sep 30 15:53:55 2008 -0700 6.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp Wed Oct 01 15:05:06 2008 -0400 6.3 @@ -52,7 +52,7 @@ 6.4 friend class ParallelTaskTerminator; 6.5 friend class ParMarkBitMap; 6.6 friend class PSParallelCompact; 6.7 - friend class StealChunkCompactionTask; 6.8 + friend class StealRegionCompactionTask; 6.9 friend class UpdateAndFillClosure; 6.10 friend class RefProcTaskExecutor; 6.11 6.12 @@ -72,27 +72,27 @@ 6.13 // ------------------------ End don't putback if not needed 6.14 6.15 private: 6.16 - static ParCompactionManager** _manager_array; 6.17 - static OopTaskQueueSet* _stack_array; 6.18 - static ObjectStartArray* _start_array; 6.19 - static ChunkTaskQueueSet* _chunk_array; 6.20 - static PSOldGen* _old_gen; 6.21 + static ParCompactionManager** _manager_array; 6.22 + static OopTaskQueueSet* _stack_array; 6.23 + static ObjectStartArray* _start_array; 6.24 + static RegionTaskQueueSet* _region_array; 6.25 + static PSOldGen* _old_gen; 6.26 6.27 - OopTaskQueue _marking_stack; 6.28 - GrowableArray<oop>* _overflow_stack; 6.29 + OopTaskQueue _marking_stack; 6.30 + GrowableArray<oop>* _overflow_stack; 6.31 // Is there a way to reuse the _marking_stack for the 6.32 - // saving empty chunks? For now just create a different 6.33 + // saving empty regions? For now just create a different 6.34 // type of TaskQueue. 6.35 6.36 -#ifdef USE_ChunkTaskQueueWithOverflow 6.37 - ChunkTaskQueueWithOverflow _chunk_stack; 6.38 +#ifdef USE_RegionTaskQueueWithOverflow 6.39 + RegionTaskQueueWithOverflow _region_stack; 6.40 #else 6.41 - ChunkTaskQueue _chunk_stack; 6.42 - GrowableArray<size_t>* _chunk_overflow_stack; 6.43 + RegionTaskQueue _region_stack; 6.44 + GrowableArray<size_t>* _region_overflow_stack; 6.45 #endif 6.46 6.47 #if 1 // does this happen enough to need a per thread stack? 6.48 - GrowableArray<Klass*>* _revisit_klass_stack; 6.49 + GrowableArray<Klass*>* _revisit_klass_stack; 6.50 #endif 6.51 static ParMarkBitMap* _mark_bitmap; 6.52 6.53 @@ -100,21 +100,22 @@ 6.54 6.55 static PSOldGen* old_gen() { return _old_gen; } 6.56 static ObjectStartArray* start_array() { return _start_array; } 6.57 - static OopTaskQueueSet* stack_array() { return _stack_array; } 6.58 + static OopTaskQueueSet* stack_array() { return _stack_array; } 6.59 6.60 static void initialize(ParMarkBitMap* mbm); 6.61 6.62 protected: 6.63 // Array of tasks. Needed by the ParallelTaskTerminator. 6.64 - static ChunkTaskQueueSet* chunk_array() { return _chunk_array; } 6.65 - 6.66 - OopTaskQueue* marking_stack() { return &_marking_stack; } 6.67 - GrowableArray<oop>* overflow_stack() { return _overflow_stack; } 6.68 -#ifdef USE_ChunkTaskQueueWithOverflow 6.69 - ChunkTaskQueueWithOverflow* chunk_stack() { return &_chunk_stack; } 6.70 + static RegionTaskQueueSet* region_array() { return _region_array; } 6.71 + OopTaskQueue* marking_stack() { return &_marking_stack; } 6.72 + GrowableArray<oop>* overflow_stack() { return _overflow_stack; } 6.73 +#ifdef USE_RegionTaskQueueWithOverflow 6.74 + RegionTaskQueueWithOverflow* region_stack() { return &_region_stack; } 6.75 #else 6.76 - ChunkTaskQueue* chunk_stack() { return &_chunk_stack; } 6.77 - GrowableArray<size_t>* chunk_overflow_stack() { return _chunk_overflow_stack; } 6.78 + RegionTaskQueue* region_stack() { return &_region_stack; } 6.79 + GrowableArray<size_t>* region_overflow_stack() { 6.80 + return _region_overflow_stack; 6.81 + } 6.82 #endif 6.83 6.84 // Pushes onto the marking stack. If the marking stack is full, 6.85 @@ -123,9 +124,9 @@ 6.86 // Do not implement an equivalent stack_pop. Deal with the 6.87 // marking stack and overflow stack directly. 6.88 6.89 - // Pushes onto the chunk stack. If the chunk stack is full, 6.90 - // pushes onto the chunk overflow stack. 6.91 - void chunk_stack_push(size_t chunk_index); 6.92 + // Pushes onto the region stack. If the region stack is full, 6.93 + // pushes onto the region overflow stack. 6.94 + void region_stack_push(size_t region_index); 6.95 public: 6.96 6.97 Action action() { return _action; } 6.98 @@ -160,10 +161,10 @@ 6.99 // Get a oop for scanning. If returns null, no oop were found. 6.100 oop retrieve_for_scanning(); 6.101 6.102 - // Save chunk for later processing. Must not fail. 6.103 - void save_for_processing(size_t chunk_index); 6.104 - // Get a chunk for processing. If returns null, no chunk were found. 6.105 - bool retrieve_for_processing(size_t& chunk_index); 6.106 + // Save region for later processing. Must not fail. 6.107 + void save_for_processing(size_t region_index); 6.108 + // Get a region for processing. If returns null, no region were found. 6.109 + bool retrieve_for_processing(size_t& region_index); 6.110 6.111 // Access function for compaction managers 6.112 static ParCompactionManager* gc_thread_compaction_manager(int index); 6.113 @@ -172,18 +173,18 @@ 6.114 return stack_array()->steal(queue_num, seed, t); 6.115 } 6.116 6.117 - static bool steal(int queue_num, int* seed, ChunkTask& t) { 6.118 - return chunk_array()->steal(queue_num, seed, t); 6.119 + static bool steal(int queue_num, int* seed, RegionTask& t) { 6.120 + return region_array()->steal(queue_num, seed, t); 6.121 } 6.122 6.123 // Process tasks remaining on any stack 6.124 void drain_marking_stacks(OopClosure *blk); 6.125 6.126 // Process tasks remaining on any stack 6.127 - void drain_chunk_stacks(); 6.128 + void drain_region_stacks(); 6.129 6.130 // Process tasks remaining on any stack 6.131 - void drain_chunk_overflow_stack(); 6.132 + void drain_region_overflow_stack(); 6.133 6.134 // Debugging support 6.135 #ifdef ASSERT
7.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Tue Sep 30 15:53:55 2008 -0700 7.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Wed Oct 01 15:05:06 2008 -0400 7.3 @@ -35,9 +35,7 @@ 7.4 _ref_processor = new ReferenceProcessor(mr, 7.5 true, // atomic_discovery 7.6 false); // mt_discovery 7.7 - if (!UseParallelOldGC || !VerifyParallelOldWithMarkSweep) { 7.8 - _counters = new CollectorCounters("PSMarkSweep", 1); 7.9 - } 7.10 + _counters = new CollectorCounters("PSMarkSweep", 1); 7.11 } 7.12 7.13 // This method contains all heap specific policy for invoking mark sweep. 7.14 @@ -518,9 +516,6 @@ 7.15 follow_stack(); 7.16 7.17 // Process reference objects found during marking 7.18 - 7.19 - // Skipping the reference processing for VerifyParallelOldWithMarkSweep 7.20 - // affects the marking (makes it different). 7.21 { 7.22 ReferencePolicy *soft_ref_policy; 7.23 if (clear_all_softrefs) {
8.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp Tue Sep 30 15:53:55 2008 -0700 8.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp Wed Oct 01 15:05:06 2008 -0400 8.3 @@ -152,20 +152,15 @@ 8.4 oop(q)->forward_to(oop(compact_top)); 8.5 assert(oop(q)->is_gc_marked(), "encoding the pointer should preserve the mark"); 8.6 } else { 8.7 - // Don't clear the mark since it's confuses parallel old 8.8 - // verification. 8.9 - if (!UseParallelOldGC || !VerifyParallelOldWithMarkSweep) { 8.10 - // if the object isn't moving we can just set the mark to the default 8.11 - // mark and handle it specially later on. 8.12 - oop(q)->init_mark(); 8.13 - } 8.14 + // if the object isn't moving we can just set the mark to the default 8.15 + // mark and handle it specially later on. 8.16 + oop(q)->init_mark(); 8.17 assert(oop(q)->forwardee() == NULL, "should be forwarded to NULL"); 8.18 } 8.19 8.20 // Update object start array 8.21 - if (!UseParallelOldGC || !VerifyParallelOldWithMarkSweep) { 8.22 - if (start_array) 8.23 - start_array->allocate_block(compact_top); 8.24 + if (start_array) { 8.25 + start_array->allocate_block(compact_top); 8.26 } 8.27 8.28 VALIDATE_MARK_SWEEP_ONLY(MarkSweep::register_live_oop(oop(q), size)); 8.29 @@ -219,19 +214,14 @@ 8.30 assert(oop(q)->is_gc_marked(), "encoding the pointer should preserve the mark"); 8.31 } else { 8.32 // if the object isn't moving we can just set the mark to the default 8.33 - // Don't clear the mark since it's confuses parallel old 8.34 - // verification. 8.35 - if (!UseParallelOldGC || !VerifyParallelOldWithMarkSweep) { 8.36 - // mark and handle it specially later on. 8.37 - oop(q)->init_mark(); 8.38 - } 8.39 + // mark and handle it specially later on. 8.40 + oop(q)->init_mark(); 8.41 assert(oop(q)->forwardee() == NULL, "should be forwarded to NULL"); 8.42 } 8.43 8.44 - if (!UseParallelOldGC || !VerifyParallelOldWithMarkSweep) { 8.45 - // Update object start array 8.46 - if (start_array) 8.47 - start_array->allocate_block(compact_top); 8.48 + // Update object start array 8.49 + if (start_array) { 8.50 + start_array->allocate_block(compact_top); 8.51 } 8.52 8.53 VALIDATE_MARK_SWEEP_ONLY(MarkSweep::register_live_oop(oop(q), sz));
9.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp Tue Sep 30 15:53:55 2008 -0700 9.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp Wed Oct 01 15:05:06 2008 -0400 9.3 @@ -152,9 +152,7 @@ 9.4 assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); 9.5 9.6 // Reset start array first. 9.7 - debug_only(if (!UseParallelOldGC || !VerifyParallelOldWithMarkSweep) {) 9.8 start_array()->reset(); 9.9 - debug_only(}) 9.10 9.11 object_mark_sweep()->precompact(); 9.12
10.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Tue Sep 30 15:53:55 2008 -0700 10.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Oct 01 15:05:06 2008 -0400 10.3 @@ -28,43 +28,31 @@ 10.4 #include <math.h> 10.5 10.6 // All sizes are in HeapWords. 10.7 -const size_t ParallelCompactData::Log2ChunkSize = 9; // 512 words 10.8 -const size_t ParallelCompactData::ChunkSize = (size_t)1 << Log2ChunkSize; 10.9 -const size_t ParallelCompactData::ChunkSizeBytes = ChunkSize << LogHeapWordSize; 10.10 -const size_t ParallelCompactData::ChunkSizeOffsetMask = ChunkSize - 1; 10.11 -const size_t ParallelCompactData::ChunkAddrOffsetMask = ChunkSizeBytes - 1; 10.12 -const size_t ParallelCompactData::ChunkAddrMask = ~ChunkAddrOffsetMask; 10.13 - 10.14 -// 32-bit: 128 words covers 4 bitmap words 10.15 -// 64-bit: 128 words covers 2 bitmap words 10.16 -const size_t ParallelCompactData::Log2BlockSize = 7; // 128 words 10.17 -const size_t ParallelCompactData::BlockSize = (size_t)1 << Log2BlockSize; 10.18 -const size_t ParallelCompactData::BlockOffsetMask = BlockSize - 1; 10.19 -const size_t ParallelCompactData::BlockMask = ~BlockOffsetMask; 10.20 - 10.21 -const size_t ParallelCompactData::BlocksPerChunk = ChunkSize / BlockSize; 10.22 - 10.23 -const ParallelCompactData::ChunkData::chunk_sz_t 10.24 -ParallelCompactData::ChunkData::dc_shift = 27; 10.25 - 10.26 -const ParallelCompactData::ChunkData::chunk_sz_t 10.27 -ParallelCompactData::ChunkData::dc_mask = ~0U << dc_shift; 10.28 - 10.29 -const ParallelCompactData::ChunkData::chunk_sz_t 10.30 -ParallelCompactData::ChunkData::dc_one = 0x1U << dc_shift; 10.31 - 10.32 -const ParallelCompactData::ChunkData::chunk_sz_t 10.33 -ParallelCompactData::ChunkData::los_mask = ~dc_mask; 10.34 - 10.35 -const ParallelCompactData::ChunkData::chunk_sz_t 10.36 -ParallelCompactData::ChunkData::dc_claimed = 0x8U << dc_shift; 10.37 - 10.38 -const ParallelCompactData::ChunkData::chunk_sz_t 10.39 -ParallelCompactData::ChunkData::dc_completed = 0xcU << dc_shift; 10.40 - 10.41 -#ifdef ASSERT 10.42 -short ParallelCompactData::BlockData::_cur_phase = 0; 10.43 -#endif 10.44 +const size_t ParallelCompactData::Log2RegionSize = 9; // 512 words 10.45 +const size_t ParallelCompactData::RegionSize = (size_t)1 << Log2RegionSize; 10.46 +const size_t ParallelCompactData::RegionSizeBytes = 10.47 + RegionSize << LogHeapWordSize; 10.48 +const size_t ParallelCompactData::RegionSizeOffsetMask = RegionSize - 1; 10.49 +const size_t ParallelCompactData::RegionAddrOffsetMask = RegionSizeBytes - 1; 10.50 +const size_t ParallelCompactData::RegionAddrMask = ~RegionAddrOffsetMask; 10.51 + 10.52 +const ParallelCompactData::RegionData::region_sz_t 10.53 +ParallelCompactData::RegionData::dc_shift = 27; 10.54 + 10.55 +const ParallelCompactData::RegionData::region_sz_t 10.56 +ParallelCompactData::RegionData::dc_mask = ~0U << dc_shift; 10.57 + 10.58 +const ParallelCompactData::RegionData::region_sz_t 10.59 +ParallelCompactData::RegionData::dc_one = 0x1U << dc_shift; 10.60 + 10.61 +const ParallelCompactData::RegionData::region_sz_t 10.62 +ParallelCompactData::RegionData::los_mask = ~dc_mask; 10.63 + 10.64 +const ParallelCompactData::RegionData::region_sz_t 10.65 +ParallelCompactData::RegionData::dc_claimed = 0x8U << dc_shift; 10.66 + 10.67 +const ParallelCompactData::RegionData::region_sz_t 10.68 +ParallelCompactData::RegionData::dc_completed = 0xcU << dc_shift; 10.69 10.70 SpaceInfo PSParallelCompact::_space_info[PSParallelCompact::last_space_id]; 10.71 bool PSParallelCompact::_print_phases = false; 10.72 @@ -100,99 +88,12 @@ 10.73 GrowableArray<size_t> * PSParallelCompact::_last_gc_live_oops_size = NULL; 10.74 #endif 10.75 10.76 -// XXX beg - verification code; only works while we also mark in object headers 10.77 -static void 10.78 -verify_mark_bitmap(ParMarkBitMap& _mark_bitmap) 10.79 -{ 10.80 - ParallelScavengeHeap* heap = PSParallelCompact::gc_heap(); 10.81 - 10.82 - PSPermGen* perm_gen = heap->perm_gen(); 10.83 - PSOldGen* old_gen = heap->old_gen(); 10.84 - PSYoungGen* young_gen = heap->young_gen(); 10.85 - 10.86 - MutableSpace* perm_space = perm_gen->object_space(); 10.87 - MutableSpace* old_space = old_gen->object_space(); 10.88 - MutableSpace* eden_space = young_gen->eden_space(); 10.89 - MutableSpace* from_space = young_gen->from_space(); 10.90 - MutableSpace* to_space = young_gen->to_space(); 10.91 - 10.92 - // 'from_space' here is the survivor space at the lower address. 10.93 - if (to_space->bottom() < from_space->bottom()) { 10.94 - from_space = to_space; 10.95 - to_space = young_gen->from_space(); 10.96 - } 10.97 - 10.98 - HeapWord* boundaries[12]; 10.99 - unsigned int bidx = 0; 10.100 - const unsigned int bidx_max = sizeof(boundaries) / sizeof(boundaries[0]); 10.101 - 10.102 - boundaries[0] = perm_space->bottom(); 10.103 - boundaries[1] = perm_space->top(); 10.104 - boundaries[2] = old_space->bottom(); 10.105 - boundaries[3] = old_space->top(); 10.106 - boundaries[4] = eden_space->bottom(); 10.107 - boundaries[5] = eden_space->top(); 10.108 - boundaries[6] = from_space->bottom(); 10.109 - boundaries[7] = from_space->top(); 10.110 - boundaries[8] = to_space->bottom(); 10.111 - boundaries[9] = to_space->top(); 10.112 - boundaries[10] = to_space->end(); 10.113 - boundaries[11] = to_space->end(); 10.114 - 10.115 - BitMap::idx_t beg_bit = 0; 10.116 - BitMap::idx_t end_bit; 10.117 - BitMap::idx_t tmp_bit; 10.118 - const BitMap::idx_t last_bit = _mark_bitmap.size(); 10.119 - do { 10.120 - HeapWord* addr = _mark_bitmap.bit_to_addr(beg_bit); 10.121 - if (_mark_bitmap.is_marked(beg_bit)) { 10.122 - oop obj = (oop)addr; 10.123 - assert(obj->is_gc_marked(), "obj header is not marked"); 10.124 - end_bit = _mark_bitmap.find_obj_end(beg_bit, last_bit); 10.125 - const size_t size = _mark_bitmap.obj_size(beg_bit, end_bit); 10.126 - assert(size == (size_t)obj->size(), "end bit wrong?"); 10.127 - beg_bit = _mark_bitmap.find_obj_beg(beg_bit + 1, last_bit); 10.128 - assert(beg_bit > end_bit, "bit set in middle of an obj"); 10.129 - } else { 10.130 - if (addr >= boundaries[bidx] && addr < boundaries[bidx + 1]) { 10.131 - // a dead object in the current space. 10.132 - oop obj = (oop)addr; 10.133 - end_bit = _mark_bitmap.addr_to_bit(addr + obj->size()); 10.134 - assert(!obj->is_gc_marked(), "obj marked in header, not in bitmap"); 10.135 - tmp_bit = beg_bit + 1; 10.136 - beg_bit = _mark_bitmap.find_obj_beg(tmp_bit, end_bit); 10.137 - assert(beg_bit == end_bit, "beg bit set in unmarked obj"); 10.138 - beg_bit = _mark_bitmap.find_obj_end(tmp_bit, end_bit); 10.139 - assert(beg_bit == end_bit, "end bit set in unmarked obj"); 10.140 - } else if (addr < boundaries[bidx + 2]) { 10.141 - // addr is between top in the current space and bottom in the next. 10.142 - end_bit = beg_bit + pointer_delta(boundaries[bidx + 2], addr); 10.143 - tmp_bit = beg_bit; 10.144 - beg_bit = _mark_bitmap.find_obj_beg(tmp_bit, end_bit); 10.145 - assert(beg_bit == end_bit, "beg bit set above top"); 10.146 - beg_bit = _mark_bitmap.find_obj_end(tmp_bit, end_bit); 10.147 - assert(beg_bit == end_bit, "end bit set above top"); 10.148 - bidx += 2; 10.149 - } else if (bidx < bidx_max - 2) { 10.150 - bidx += 2; // ??? 10.151 - } else { 10.152 - tmp_bit = beg_bit; 10.153 - beg_bit = _mark_bitmap.find_obj_beg(tmp_bit, last_bit); 10.154 - assert(beg_bit == last_bit, "beg bit set outside heap"); 10.155 - beg_bit = _mark_bitmap.find_obj_end(tmp_bit, last_bit); 10.156 - assert(beg_bit == last_bit, "end bit set outside heap"); 10.157 - } 10.158 - } 10.159 - } while (beg_bit < last_bit); 10.160 -} 10.161 -// XXX end - verification code; only works while we also mark in object headers 10.162 - 10.163 #ifndef PRODUCT 10.164 const char* PSParallelCompact::space_names[] = { 10.165 "perm", "old ", "eden", "from", "to " 10.166 }; 10.167 10.168 -void PSParallelCompact::print_chunk_ranges() 10.169 +void PSParallelCompact::print_region_ranges() 10.170 { 10.171 tty->print_cr("space bottom top end new_top"); 10.172 tty->print_cr("------ ---------- ---------- ---------- ----------"); 10.173 @@ -203,31 +104,31 @@ 10.174 SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) " " 10.175 SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10) " ", 10.176 id, space_names[id], 10.177 - summary_data().addr_to_chunk_idx(space->bottom()), 10.178 - summary_data().addr_to_chunk_idx(space->top()), 10.179 - summary_data().addr_to_chunk_idx(space->end()), 10.180 - summary_data().addr_to_chunk_idx(_space_info[id].new_top())); 10.181 + summary_data().addr_to_region_idx(space->bottom()), 10.182 + summary_data().addr_to_region_idx(space->top()), 10.183 + summary_data().addr_to_region_idx(space->end()), 10.184 + summary_data().addr_to_region_idx(_space_info[id].new_top())); 10.185 } 10.186 } 10.187 10.188 void 10.189 -print_generic_summary_chunk(size_t i, const ParallelCompactData::ChunkData* c) 10.190 +print_generic_summary_region(size_t i, const ParallelCompactData::RegionData* c) 10.191 { 10.192 -#define CHUNK_IDX_FORMAT SIZE_FORMAT_W(7) 10.193 -#define CHUNK_DATA_FORMAT SIZE_FORMAT_W(5) 10.194 +#define REGION_IDX_FORMAT SIZE_FORMAT_W(7) 10.195 +#define REGION_DATA_FORMAT SIZE_FORMAT_W(5) 10.196 10.197 ParallelCompactData& sd = PSParallelCompact::summary_data(); 10.198 - size_t dci = c->destination() ? sd.addr_to_chunk_idx(c->destination()) : 0; 10.199 - tty->print_cr(CHUNK_IDX_FORMAT " " PTR_FORMAT " " 10.200 - CHUNK_IDX_FORMAT " " PTR_FORMAT " " 10.201 - CHUNK_DATA_FORMAT " " CHUNK_DATA_FORMAT " " 10.202 - CHUNK_DATA_FORMAT " " CHUNK_IDX_FORMAT " %d", 10.203 + size_t dci = c->destination() ? sd.addr_to_region_idx(c->destination()) : 0; 10.204 + tty->print_cr(REGION_IDX_FORMAT " " PTR_FORMAT " " 10.205 + REGION_IDX_FORMAT " " PTR_FORMAT " " 10.206 + REGION_DATA_FORMAT " " REGION_DATA_FORMAT " " 10.207 + REGION_DATA_FORMAT " " REGION_IDX_FORMAT " %d", 10.208 i, c->data_location(), dci, c->destination(), 10.209 c->partial_obj_size(), c->live_obj_size(), 10.210 - c->data_size(), c->source_chunk(), c->destination_count()); 10.211 - 10.212 -#undef CHUNK_IDX_FORMAT 10.213 -#undef CHUNK_DATA_FORMAT 10.214 + c->data_size(), c->source_region(), c->destination_count()); 10.215 + 10.216 +#undef REGION_IDX_FORMAT 10.217 +#undef REGION_DATA_FORMAT 10.218 } 10.219 10.220 void 10.221 @@ -236,14 +137,14 @@ 10.222 HeapWord* const end_addr) 10.223 { 10.224 size_t total_words = 0; 10.225 - size_t i = summary_data.addr_to_chunk_idx(beg_addr); 10.226 - const size_t last = summary_data.addr_to_chunk_idx(end_addr); 10.227 + size_t i = summary_data.addr_to_region_idx(beg_addr); 10.228 + const size_t last = summary_data.addr_to_region_idx(end_addr); 10.229 HeapWord* pdest = 0; 10.230 10.231 while (i <= last) { 10.232 - ParallelCompactData::ChunkData* c = summary_data.chunk(i); 10.233 + ParallelCompactData::RegionData* c = summary_data.region(i); 10.234 if (c->data_size() != 0 || c->destination() != pdest) { 10.235 - print_generic_summary_chunk(i, c); 10.236 + print_generic_summary_region(i, c); 10.237 total_words += c->data_size(); 10.238 pdest = c->destination(); 10.239 } 10.240 @@ -265,16 +166,16 @@ 10.241 } 10.242 10.243 void 10.244 -print_initial_summary_chunk(size_t i, 10.245 - const ParallelCompactData::ChunkData* c, 10.246 - bool newline = true) 10.247 +print_initial_summary_region(size_t i, 10.248 + const ParallelCompactData::RegionData* c, 10.249 + bool newline = true) 10.250 { 10.251 tty->print(SIZE_FORMAT_W(5) " " PTR_FORMAT " " 10.252 SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " " 10.253 SIZE_FORMAT_W(5) " " SIZE_FORMAT_W(5) " %d", 10.254 i, c->destination(), 10.255 c->partial_obj_size(), c->live_obj_size(), 10.256 - c->data_size(), c->source_chunk(), c->destination_count()); 10.257 + c->data_size(), c->source_region(), c->destination_count()); 10.258 if (newline) tty->cr(); 10.259 } 10.260 10.261 @@ -285,47 +186,48 @@ 10.262 return; 10.263 } 10.264 10.265 - const size_t chunk_size = ParallelCompactData::ChunkSize; 10.266 - HeapWord* const top_aligned_up = summary_data.chunk_align_up(space->top()); 10.267 - const size_t end_chunk = summary_data.addr_to_chunk_idx(top_aligned_up); 10.268 - const ParallelCompactData::ChunkData* c = summary_data.chunk(end_chunk - 1); 10.269 + const size_t region_size = ParallelCompactData::RegionSize; 10.270 + typedef ParallelCompactData::RegionData RegionData; 10.271 + HeapWord* const top_aligned_up = summary_data.region_align_up(space->top()); 10.272 + const size_t end_region = summary_data.addr_to_region_idx(top_aligned_up); 10.273 + const RegionData* c = summary_data.region(end_region - 1); 10.274 HeapWord* end_addr = c->destination() + c->data_size(); 10.275 const size_t live_in_space = pointer_delta(end_addr, space->bottom()); 10.276 10.277 - // Print (and count) the full chunks at the beginning of the space. 10.278 - size_t full_chunk_count = 0; 10.279 - size_t i = summary_data.addr_to_chunk_idx(space->bottom()); 10.280 - while (i < end_chunk && summary_data.chunk(i)->data_size() == chunk_size) { 10.281 - print_initial_summary_chunk(i, summary_data.chunk(i)); 10.282 - ++full_chunk_count; 10.283 + // Print (and count) the full regions at the beginning of the space. 10.284 + size_t full_region_count = 0; 10.285 + size_t i = summary_data.addr_to_region_idx(space->bottom()); 10.286 + while (i < end_region && summary_data.region(i)->data_size() == region_size) { 10.287 + print_initial_summary_region(i, summary_data.region(i)); 10.288 + ++full_region_count; 10.289 ++i; 10.290 } 10.291 10.292 - size_t live_to_right = live_in_space - full_chunk_count * chunk_size; 10.293 + size_t live_to_right = live_in_space - full_region_count * region_size; 10.294 10.295 double max_reclaimed_ratio = 0.0; 10.296 - size_t max_reclaimed_ratio_chunk = 0; 10.297 + size_t max_reclaimed_ratio_region = 0; 10.298 size_t max_dead_to_right = 0; 10.299 size_t max_live_to_right = 0; 10.300 10.301 - // Print the 'reclaimed ratio' for chunks while there is something live in the 10.302 - // chunk or to the right of it. The remaining chunks are empty (and 10.303 + // Print the 'reclaimed ratio' for regions while there is something live in 10.304 + // the region or to the right of it. The remaining regions are empty (and 10.305 // uninteresting), and computing the ratio will result in division by 0. 10.306 - while (i < end_chunk && live_to_right > 0) { 10.307 - c = summary_data.chunk(i); 10.308 - HeapWord* const chunk_addr = summary_data.chunk_to_addr(i); 10.309 - const size_t used_to_right = pointer_delta(space->top(), chunk_addr); 10.310 + while (i < end_region && live_to_right > 0) { 10.311 + c = summary_data.region(i); 10.312 + HeapWord* const region_addr = summary_data.region_to_addr(i); 10.313 + const size_t used_to_right = pointer_delta(space->top(), region_addr); 10.314 const size_t dead_to_right = used_to_right - live_to_right; 10.315 const double reclaimed_ratio = double(dead_to_right) / live_to_right; 10.316 10.317 if (reclaimed_ratio > max_reclaimed_ratio) { 10.318 max_reclaimed_ratio = reclaimed_ratio; 10.319 - max_reclaimed_ratio_chunk = i; 10.320 + max_reclaimed_ratio_region = i; 10.321 max_dead_to_right = dead_to_right; 10.322 max_live_to_right = live_to_right; 10.323 } 10.324 10.325 - print_initial_summary_chunk(i, c, false); 10.326 + print_initial_summary_region(i, c, false); 10.327 tty->print_cr(" %12.10f " SIZE_FORMAT_W(10) " " SIZE_FORMAT_W(10), 10.328 reclaimed_ratio, dead_to_right, live_to_right); 10.329 10.330 @@ -333,14 +235,14 @@ 10.331 ++i; 10.332 } 10.333 10.334 - // Any remaining chunks are empty. Print one more if there is one. 10.335 - if (i < end_chunk) { 10.336 - print_initial_summary_chunk(i, summary_data.chunk(i)); 10.337 + // Any remaining regions are empty. Print one more if there is one. 10.338 + if (i < end_region) { 10.339 + print_initial_summary_region(i, summary_data.region(i)); 10.340 } 10.341 10.342 tty->print_cr("max: " SIZE_FORMAT_W(4) " d2r=" SIZE_FORMAT_W(10) " " 10.343 "l2r=" SIZE_FORMAT_W(10) " max_ratio=%14.12f", 10.344 - max_reclaimed_ratio_chunk, max_dead_to_right, 10.345 + max_reclaimed_ratio_region, max_dead_to_right, 10.346 max_live_to_right, max_reclaimed_ratio); 10.347 } 10.348 10.349 @@ -372,13 +274,9 @@ 10.350 { 10.351 _region_start = 0; 10.352 10.353 - _chunk_vspace = 0; 10.354 - _chunk_data = 0; 10.355 - _chunk_count = 0; 10.356 - 10.357 - _block_vspace = 0; 10.358 - _block_data = 0; 10.359 - _block_count = 0; 10.360 + _region_vspace = 0; 10.361 + _region_data = 0; 10.362 + _region_count = 0; 10.363 } 10.364 10.365 bool ParallelCompactData::initialize(MemRegion covered_region) 10.366 @@ -387,18 +285,12 @@ 10.367 const size_t region_size = covered_region.word_size(); 10.368 DEBUG_ONLY(_region_end = _region_start + region_size;) 10.369 10.370 - assert(chunk_align_down(_region_start) == _region_start, 10.371 + assert(region_align_down(_region_start) == _region_start, 10.372 "region start not aligned"); 10.373 - assert((region_size & ChunkSizeOffsetMask) == 0, 10.374 - "region size not a multiple of ChunkSize"); 10.375 - 10.376 - bool result = initialize_chunk_data(region_size); 10.377 - 10.378 - // Initialize the block data if it will be used for updating pointers, or if 10.379 - // this is a debug build. 10.380 - if (!UseParallelOldGCChunkPointerCalc || trueInDebug) { 10.381 - result = result && initialize_block_data(region_size); 10.382 - } 10.383 + assert((region_size & RegionSizeOffsetMask) == 0, 10.384 + "region size not a multiple of RegionSize"); 10.385 + 10.386 + bool result = initialize_region_data(region_size); 10.387 10.388 return result; 10.389 } 10.390 @@ -429,64 +321,41 @@ 10.391 return 0; 10.392 } 10.393 10.394 -bool ParallelCompactData::initialize_chunk_data(size_t region_size) 10.395 +bool ParallelCompactData::initialize_region_data(size_t region_size) 10.396 { 10.397 - const size_t count = (region_size + ChunkSizeOffsetMask) >> Log2ChunkSize; 10.398 - _chunk_vspace = create_vspace(count, sizeof(ChunkData)); 10.399 - if (_chunk_vspace != 0) { 10.400 - _chunk_data = (ChunkData*)_chunk_vspace->reserved_low_addr(); 10.401 - _chunk_count = count; 10.402 + const size_t count = (region_size + RegionSizeOffsetMask) >> Log2RegionSize; 10.403 + _region_vspace = create_vspace(count, sizeof(RegionData)); 10.404 + if (_region_vspace != 0) { 10.405 + _region_data = (RegionData*)_region_vspace->reserved_low_addr(); 10.406 + _region_count = count; 10.407 return true; 10.408 } 10.409 return false; 10.410 } 10.411 10.412 -bool ParallelCompactData::initialize_block_data(size_t region_size) 10.413 -{ 10.414 - const size_t count = (region_size + BlockOffsetMask) >> Log2BlockSize; 10.415 - _block_vspace = create_vspace(count, sizeof(BlockData)); 10.416 - if (_block_vspace != 0) { 10.417 - _block_data = (BlockData*)_block_vspace->reserved_low_addr(); 10.418 - _block_count = count; 10.419 - return true; 10.420 - } 10.421 - return false; 10.422 -} 10.423 - 10.424 void ParallelCompactData::clear() 10.425 { 10.426 - if (_block_data) { 10.427 - memset(_block_data, 0, _block_vspace->committed_size()); 10.428 - } 10.429 - memset(_chunk_data, 0, _chunk_vspace->committed_size()); 10.430 + memset(_region_data, 0, _region_vspace->committed_size()); 10.431 } 10.432 10.433 -void ParallelCompactData::clear_range(size_t beg_chunk, size_t end_chunk) { 10.434 - assert(beg_chunk <= _chunk_count, "beg_chunk out of range"); 10.435 - assert(end_chunk <= _chunk_count, "end_chunk out of range"); 10.436 - assert(ChunkSize % BlockSize == 0, "ChunkSize not a multiple of BlockSize"); 10.437 - 10.438 - const size_t chunk_cnt = end_chunk - beg_chunk; 10.439 - 10.440 - if (_block_data) { 10.441 - const size_t blocks_per_chunk = ChunkSize / BlockSize; 10.442 - const size_t beg_block = beg_chunk * blocks_per_chunk; 10.443 - const size_t block_cnt = chunk_cnt * blocks_per_chunk; 10.444 - memset(_block_data + beg_block, 0, block_cnt * sizeof(BlockData)); 10.445 - } 10.446 - memset(_chunk_data + beg_chunk, 0, chunk_cnt * sizeof(ChunkData)); 10.447 +void ParallelCompactData::clear_range(size_t beg_region, size_t end_region) { 10.448 + assert(beg_region <= _region_count, "beg_region out of range"); 10.449 + assert(end_region <= _region_count, "end_region out of range"); 10.450 + 10.451 + const size_t region_cnt = end_region - beg_region; 10.452 + memset(_region_data + beg_region, 0, region_cnt * sizeof(RegionData)); 10.453 } 10.454 10.455 -HeapWord* ParallelCompactData::partial_obj_end(size_t chunk_idx) const 10.456 +HeapWord* ParallelCompactData::partial_obj_end(size_t region_idx) const 10.457 { 10.458 - const ChunkData* cur_cp = chunk(chunk_idx); 10.459 - const ChunkData* const end_cp = chunk(chunk_count() - 1); 10.460 - 10.461 - HeapWord* result = chunk_to_addr(chunk_idx); 10.462 + const RegionData* cur_cp = region(region_idx); 10.463 + const RegionData* const end_cp = region(region_count() - 1); 10.464 + 10.465 + HeapWord* result = region_to_addr(region_idx); 10.466 if (cur_cp < end_cp) { 10.467 do { 10.468 result += cur_cp->partial_obj_size(); 10.469 - } while (cur_cp->partial_obj_size() == ChunkSize && ++cur_cp < end_cp); 10.470 + } while (cur_cp->partial_obj_size() == RegionSize && ++cur_cp < end_cp); 10.471 } 10.472 return result; 10.473 } 10.474 @@ -494,56 +363,56 @@ 10.475 void ParallelCompactData::add_obj(HeapWord* addr, size_t len) 10.476 { 10.477 const size_t obj_ofs = pointer_delta(addr, _region_start); 10.478 - const size_t beg_chunk = obj_ofs >> Log2ChunkSize; 10.479 - const size_t end_chunk = (obj_ofs + len - 1) >> Log2ChunkSize; 10.480 + const size_t beg_region = obj_ofs >> Log2RegionSize; 10.481 + const size_t end_region = (obj_ofs + len - 1) >> Log2RegionSize; 10.482 10.483 DEBUG_ONLY(Atomic::inc_ptr(&add_obj_count);) 10.484 DEBUG_ONLY(Atomic::add_ptr(len, &add_obj_size);) 10.485 10.486 - if (beg_chunk == end_chunk) { 10.487 - // All in one chunk. 10.488 - _chunk_data[beg_chunk].add_live_obj(len); 10.489 + if (beg_region == end_region) { 10.490 + // All in one region. 10.491 + _region_data[beg_region].add_live_obj(len); 10.492 return; 10.493 } 10.494 10.495 - // First chunk. 10.496 - const size_t beg_ofs = chunk_offset(addr); 10.497 - _chunk_data[beg_chunk].add_live_obj(ChunkSize - beg_ofs); 10.498 + // First region. 10.499 + const size_t beg_ofs = region_offset(addr); 10.500 + _region_data[beg_region].add_live_obj(RegionSize - beg_ofs); 10.501 10.502 klassOop klass = ((oop)addr)->klass(); 10.503 - // Middle chunks--completely spanned by this object. 10.504 - for (size_t chunk = beg_chunk + 1; chunk < end_chunk; ++chunk) { 10.505 - _chunk_data[chunk].set_partial_obj_size(ChunkSize); 10.506 - _chunk_data[chunk].set_partial_obj_addr(addr); 10.507 + // Middle regions--completely spanned by this object. 10.508 + for (size_t region = beg_region + 1; region < end_region; ++region) { 10.509 + _region_data[region].set_partial_obj_size(RegionSize); 10.510 + _region_data[region].set_partial_obj_addr(addr); 10.511 } 10.512 10.513 - // Last chunk. 10.514 - const size_t end_ofs = chunk_offset(addr + len - 1); 10.515 - _chunk_data[end_chunk].set_partial_obj_size(end_ofs + 1); 10.516 - _chunk_data[end_chunk].set_partial_obj_addr(addr); 10.517 + // Last region. 10.518 + const size_t end_ofs = region_offset(addr + len - 1); 10.519 + _region_data[end_region].set_partial_obj_size(end_ofs + 1); 10.520 + _region_data[end_region].set_partial_obj_addr(addr); 10.521 } 10.522 10.523 void 10.524 ParallelCompactData::summarize_dense_prefix(HeapWord* beg, HeapWord* end) 10.525 { 10.526 - assert(chunk_offset(beg) == 0, "not ChunkSize aligned"); 10.527 - assert(chunk_offset(end) == 0, "not ChunkSize aligned"); 10.528 - 10.529 - size_t cur_chunk = addr_to_chunk_idx(beg); 10.530 - const size_t end_chunk = addr_to_chunk_idx(end); 10.531 + assert(region_offset(beg) == 0, "not RegionSize aligned"); 10.532 + assert(region_offset(end) == 0, "not RegionSize aligned"); 10.533 + 10.534 + size_t cur_region = addr_to_region_idx(beg); 10.535 + const size_t end_region = addr_to_region_idx(end); 10.536 HeapWord* addr = beg; 10.537 - while (cur_chunk < end_chunk) { 10.538 - _chunk_data[cur_chunk].set_destination(addr); 10.539 - _chunk_data[cur_chunk].set_destination_count(0); 10.540 - _chunk_data[cur_chunk].set_source_chunk(cur_chunk); 10.541 - _chunk_data[cur_chunk].set_data_location(addr); 10.542 - 10.543 - // Update live_obj_size so the chunk appears completely full. 10.544 - size_t live_size = ChunkSize - _chunk_data[cur_chunk].partial_obj_size(); 10.545 - _chunk_data[cur_chunk].set_live_obj_size(live_size); 10.546 - 10.547 - ++cur_chunk; 10.548 - addr += ChunkSize; 10.549 + while (cur_region < end_region) { 10.550 + _region_data[cur_region].set_destination(addr); 10.551 + _region_data[cur_region].set_destination_count(0); 10.552 + _region_data[cur_region].set_source_region(cur_region); 10.553 + _region_data[cur_region].set_data_location(addr); 10.554 + 10.555 + // Update live_obj_size so the region appears completely full. 10.556 + size_t live_size = RegionSize - _region_data[cur_region].partial_obj_size(); 10.557 + _region_data[cur_region].set_live_obj_size(live_size); 10.558 + 10.559 + ++cur_region; 10.560 + addr += RegionSize; 10.561 } 10.562 } 10.563 10.564 @@ -552,7 +421,7 @@ 10.565 HeapWord** target_next, 10.566 HeapWord** source_next) { 10.567 // This is too strict. 10.568 - // assert(chunk_offset(source_beg) == 0, "not ChunkSize aligned"); 10.569 + // assert(region_offset(source_beg) == 0, "not RegionSize aligned"); 10.570 10.571 if (TraceParallelOldGCSummaryPhase) { 10.572 tty->print_cr("tb=" PTR_FORMAT " te=" PTR_FORMAT " " 10.573 @@ -564,125 +433,93 @@ 10.574 source_next != 0 ? *source_next : (HeapWord*) 0); 10.575 } 10.576 10.577 - size_t cur_chunk = addr_to_chunk_idx(source_beg); 10.578 - const size_t end_chunk = addr_to_chunk_idx(chunk_align_up(source_end)); 10.579 + size_t cur_region = addr_to_region_idx(source_beg); 10.580 + const size_t end_region = addr_to_region_idx(region_align_up(source_end)); 10.581 10.582 HeapWord *dest_addr = target_beg; 10.583 - while (cur_chunk < end_chunk) { 10.584 - size_t words = _chunk_data[cur_chunk].data_size(); 10.585 + while (cur_region < end_region) { 10.586 + size_t words = _region_data[cur_region].data_size(); 10.587 10.588 #if 1 10.589 assert(pointer_delta(target_end, dest_addr) >= words, 10.590 "source region does not fit into target region"); 10.591 #else 10.592 - // XXX - need some work on the corner cases here. If the chunk does not 10.593 - // fit, then must either make sure any partial_obj from the chunk fits, or 10.594 - // 'undo' the initial part of the partial_obj that is in the previous chunk. 10.595 + // XXX - need some work on the corner cases here. If the region does not 10.596 + // fit, then must either make sure any partial_obj from the region fits, or 10.597 + // "undo" the initial part of the partial_obj that is in the previous 10.598 + // region. 10.599 if (dest_addr + words >= target_end) { 10.600 // Let the caller know where to continue. 10.601 *target_next = dest_addr; 10.602 - *source_next = chunk_to_addr(cur_chunk); 10.603 + *source_next = region_to_addr(cur_region); 10.604 return false; 10.605 } 10.606 #endif // #if 1 10.607 10.608 - _chunk_data[cur_chunk].set_destination(dest_addr); 10.609 - 10.610 - // Set the destination_count for cur_chunk, and if necessary, update 10.611 - // source_chunk for a destination chunk. The source_chunk field is updated 10.612 - // if cur_chunk is the first (left-most) chunk to be copied to a destination 10.613 - // chunk. 10.614 + _region_data[cur_region].set_destination(dest_addr); 10.615 + 10.616 + // Set the destination_count for cur_region, and if necessary, update 10.617 + // source_region for a destination region. The source_region field is 10.618 + // updated if cur_region is the first (left-most) region to be copied to a 10.619 + // destination region. 10.620 // 10.621 - // The destination_count calculation is a bit subtle. A chunk that has data 10.622 - // that compacts into itself does not count itself as a destination. This 10.623 - // maintains the invariant that a zero count means the chunk is available 10.624 - // and can be claimed and then filled. 10.625 + // The destination_count calculation is a bit subtle. A region that has 10.626 + // data that compacts into itself does not count itself as a destination. 10.627 + // This maintains the invariant that a zero count means the region is 10.628 + // available and can be claimed and then filled. 10.629 if (words > 0) { 10.630 HeapWord* const last_addr = dest_addr + words - 1; 10.631 - const size_t dest_chunk_1 = addr_to_chunk_idx(dest_addr); 10.632 - const size_t dest_chunk_2 = addr_to_chunk_idx(last_addr); 10.633 + const size_t dest_region_1 = addr_to_region_idx(dest_addr); 10.634 + const size_t dest_region_2 = addr_to_region_idx(last_addr); 10.635 #if 0 10.636 - // Initially assume that the destination chunks will be the same and 10.637 + // Initially assume that the destination regions will be the same and 10.638 // adjust the value below if necessary. Under this assumption, if 10.639 - // cur_chunk == dest_chunk_2, then cur_chunk will be compacted completely 10.640 - // into itself. 10.641 - uint destination_count = cur_chunk == dest_chunk_2 ? 0 : 1; 10.642 - if (dest_chunk_1 != dest_chunk_2) { 10.643 - // Destination chunks differ; adjust destination_count. 10.644 + // cur_region == dest_region_2, then cur_region will be compacted 10.645 + // completely into itself. 10.646 + uint destination_count = cur_region == dest_region_2 ? 0 : 1; 10.647 + if (dest_region_1 != dest_region_2) { 10.648 + // Destination regions differ; adjust destination_count. 10.649 destination_count += 1; 10.650 - // Data from cur_chunk will be copied to the start of dest_chunk_2. 10.651 - _chunk_data[dest_chunk_2].set_source_chunk(cur_chunk); 10.652 - } else if (chunk_offset(dest_addr) == 0) { 10.653 - // Data from cur_chunk will be copied to the start of the destination 10.654 - // chunk. 10.655 - _chunk_data[dest_chunk_1].set_source_chunk(cur_chunk); 10.656 + // Data from cur_region will be copied to the start of dest_region_2. 10.657 + _region_data[dest_region_2].set_source_region(cur_region); 10.658 + } else if (region_offset(dest_addr) == 0) { 10.659 + // Data from cur_region will be copied to the start of the destination 10.660 + // region. 10.661 + _region_data[dest_region_1].set_source_region(cur_region); 10.662 } 10.663 #else 10.664 - // Initially assume that the destination chunks will be different and 10.665 + // Initially assume that the destination regions will be different and 10.666 // adjust the value below if necessary. Under this assumption, if 10.667 - // cur_chunk == dest_chunk2, then cur_chunk will be compacted partially 10.668 - // into dest_chunk_1 and partially into itself. 10.669 - uint destination_count = cur_chunk == dest_chunk_2 ? 1 : 2; 10.670 - if (dest_chunk_1 != dest_chunk_2) { 10.671 - // Data from cur_chunk will be copied to the start of dest_chunk_2. 10.672 - _chunk_data[dest_chunk_2].set_source_chunk(cur_chunk); 10.673 + // cur_region == dest_region2, then cur_region will be compacted partially 10.674 + // into dest_region_1 and partially into itself. 10.675 + uint destination_count = cur_region == dest_region_2 ? 1 : 2; 10.676 + if (dest_region_1 != dest_region_2) { 10.677 + // Data from cur_region will be copied to the start of dest_region_2. 10.678 + _region_data[dest_region_2].set_source_region(cur_region); 10.679 } else { 10.680 - // Destination chunks are the same; adjust destination_count. 10.681 + // Destination regions are the same; adjust destination_count. 10.682 destination_count -= 1; 10.683 - if (chunk_offset(dest_addr) == 0) { 10.684 - // Data from cur_chunk will be copied to the start of the destination 10.685 - // chunk. 10.686 - _chunk_data[dest_chunk_1].set_source_chunk(cur_chunk); 10.687 + if (region_offset(dest_addr) == 0) { 10.688 + // Data from cur_region will be copied to the start of the destination 10.689 + // region. 10.690 + _region_data[dest_region_1].set_source_region(cur_region); 10.691 } 10.692 } 10.693 #endif // #if 0 10.694 10.695 - _chunk_data[cur_chunk].set_destination_count(destination_count); 10.696 - _chunk_data[cur_chunk].set_data_location(chunk_to_addr(cur_chunk)); 10.697 + _region_data[cur_region].set_destination_count(destination_count); 10.698 + _region_data[cur_region].set_data_location(region_to_addr(cur_region)); 10.699 dest_addr += words; 10.700 } 10.701 10.702 - ++cur_chunk; 10.703 + ++cur_region; 10.704 } 10.705 10.706 *target_next = dest_addr; 10.707 return true; 10.708 } 10.709 10.710 -bool ParallelCompactData::partial_obj_ends_in_block(size_t block_index) { 10.711 - HeapWord* block_addr = block_to_addr(block_index); 10.712 - HeapWord* block_end_addr = block_addr + BlockSize; 10.713 - size_t chunk_index = addr_to_chunk_idx(block_addr); 10.714 - HeapWord* partial_obj_end_addr = partial_obj_end(chunk_index); 10.715 - 10.716 - // An object that ends at the end of the block, ends 10.717 - // in the block (the last word of the object is to 10.718 - // the left of the end). 10.719 - if ((block_addr < partial_obj_end_addr) && 10.720 - (partial_obj_end_addr <= block_end_addr)) { 10.721 - return true; 10.722 - } 10.723 - 10.724 - return false; 10.725 -} 10.726 - 10.727 HeapWord* ParallelCompactData::calc_new_pointer(HeapWord* addr) { 10.728 - HeapWord* result = NULL; 10.729 - if (UseParallelOldGCChunkPointerCalc) { 10.730 - result = chunk_calc_new_pointer(addr); 10.731 - } else { 10.732 - result = block_calc_new_pointer(addr); 10.733 - } 10.734 - return result; 10.735 -} 10.736 - 10.737 -// This method is overly complicated (expensive) to be called 10.738 -// for every reference. 10.739 -// Try to restructure this so that a NULL is returned if 10.740 -// the object is dead. But don't wast the cycles to explicitly check 10.741 -// that it is dead since only live objects should be passed in. 10.742 - 10.743 -HeapWord* ParallelCompactData::chunk_calc_new_pointer(HeapWord* addr) { 10.744 assert(addr != NULL, "Should detect NULL oop earlier"); 10.745 assert(PSParallelCompact::gc_heap()->is_in(addr), "addr not in heap"); 10.746 #ifdef ASSERT 10.747 @@ -692,30 +529,30 @@ 10.748 #endif 10.749 assert(PSParallelCompact::mark_bitmap()->is_marked(addr), "obj not marked"); 10.750 10.751 - // Chunk covering the object. 10.752 - size_t chunk_index = addr_to_chunk_idx(addr); 10.753 - const ChunkData* const chunk_ptr = chunk(chunk_index); 10.754 - HeapWord* const chunk_addr = chunk_align_down(addr); 10.755 - 10.756 - assert(addr < chunk_addr + ChunkSize, "Chunk does not cover object"); 10.757 - assert(addr_to_chunk_ptr(chunk_addr) == chunk_ptr, "sanity check"); 10.758 - 10.759 - HeapWord* result = chunk_ptr->destination(); 10.760 - 10.761 - // If all the data in the chunk is live, then the new location of the object 10.762 - // can be calculated from the destination of the chunk plus the offset of the 10.763 - // object in the chunk. 10.764 - if (chunk_ptr->data_size() == ChunkSize) { 10.765 - result += pointer_delta(addr, chunk_addr); 10.766 + // Region covering the object. 10.767 + size_t region_index = addr_to_region_idx(addr); 10.768 + const RegionData* const region_ptr = region(region_index); 10.769 + HeapWord* const region_addr = region_align_down(addr); 10.770 + 10.771 + assert(addr < region_addr + RegionSize, "Region does not cover object"); 10.772 + assert(addr_to_region_ptr(region_addr) == region_ptr, "sanity check"); 10.773 + 10.774 + HeapWord* result = region_ptr->destination(); 10.775 + 10.776 + // If all the data in the region is live, then the new location of the object 10.777 + // can be calculated from the destination of the region plus the offset of the 10.778 + // object in the region. 10.779 + if (region_ptr->data_size() == RegionSize) { 10.780 + result += pointer_delta(addr, region_addr); 10.781 return result; 10.782 } 10.783 10.784 // The new location of the object is 10.785 - // chunk destination + 10.786 - // size of the partial object extending onto the chunk + 10.787 - // sizes of the live objects in the Chunk that are to the left of addr 10.788 - const size_t partial_obj_size = chunk_ptr->partial_obj_size(); 10.789 - HeapWord* const search_start = chunk_addr + partial_obj_size; 10.790 + // region destination + 10.791 + // size of the partial object extending onto the region + 10.792 + // sizes of the live objects in the Region that are to the left of addr 10.793 + const size_t partial_obj_size = region_ptr->partial_obj_size(); 10.794 + HeapWord* const search_start = region_addr + partial_obj_size; 10.795 10.796 const ParMarkBitMap* bitmap = PSParallelCompact::mark_bitmap(); 10.797 size_t live_to_left = bitmap->live_words_in_range(search_start, oop(addr)); 10.798 @@ -725,50 +562,6 @@ 10.799 return result; 10.800 } 10.801 10.802 -HeapWord* ParallelCompactData::block_calc_new_pointer(HeapWord* addr) { 10.803 - assert(addr != NULL, "Should detect NULL oop earlier"); 10.804 - assert(PSParallelCompact::gc_heap()->is_in(addr), "addr not in heap"); 10.805 -#ifdef ASSERT 10.806 - if (PSParallelCompact::mark_bitmap()->is_unmarked(addr)) { 10.807 - gclog_or_tty->print_cr("calc_new_pointer:: addr " PTR_FORMAT, addr); 10.808 - } 10.809 -#endif 10.810 - assert(PSParallelCompact::mark_bitmap()->is_marked(addr), "obj not marked"); 10.811 - 10.812 - // Chunk covering the object. 10.813 - size_t chunk_index = addr_to_chunk_idx(addr); 10.814 - const ChunkData* const chunk_ptr = chunk(chunk_index); 10.815 - HeapWord* const chunk_addr = chunk_align_down(addr); 10.816 - 10.817 - assert(addr < chunk_addr + ChunkSize, "Chunk does not cover object"); 10.818 - assert(addr_to_chunk_ptr(chunk_addr) == chunk_ptr, "sanity check"); 10.819 - 10.820 - HeapWord* result = chunk_ptr->destination(); 10.821 - 10.822 - // If all the data in the chunk is live, then the new location of the object 10.823 - // can be calculated from the destination of the chunk plus the offset of the 10.824 - // object in the chunk. 10.825 - if (chunk_ptr->data_size() == ChunkSize) { 10.826 - result += pointer_delta(addr, chunk_addr); 10.827 - return result; 10.828 - } 10.829 - 10.830 - // The new location of the object is 10.831 - // chunk destination + 10.832 - // block offset + 10.833 - // sizes of the live objects in the Block that are to the left of addr 10.834 - const size_t block_offset = addr_to_block_ptr(addr)->offset(); 10.835 - HeapWord* const search_start = chunk_addr + block_offset; 10.836 - 10.837 - const ParMarkBitMap* bitmap = PSParallelCompact::mark_bitmap(); 10.838 - size_t live_to_left = bitmap->live_words_in_range(search_start, oop(addr)); 10.839 - 10.840 - result += block_offset + live_to_left; 10.841 - assert(result <= addr, "object cannot move to the right"); 10.842 - assert(result == chunk_calc_new_pointer(addr), "Should match"); 10.843 - return result; 10.844 -} 10.845 - 10.846 klassOop ParallelCompactData::calc_new_klass(klassOop old_klass) { 10.847 klassOop updated_klass; 10.848 if (PSParallelCompact::should_update_klass(old_klass)) { 10.849 @@ -792,15 +585,14 @@ 10.850 10.851 void ParallelCompactData::verify_clear() 10.852 { 10.853 - verify_clear(_chunk_vspace); 10.854 - verify_clear(_block_vspace); 10.855 + verify_clear(_region_vspace); 10.856 } 10.857 #endif // #ifdef ASSERT 10.858 10.859 #ifdef NOT_PRODUCT 10.860 -ParallelCompactData::ChunkData* debug_chunk(size_t chunk_index) { 10.861 +ParallelCompactData::RegionData* debug_region(size_t region_index) { 10.862 ParallelCompactData& sd = PSParallelCompact::summary_data(); 10.863 - return sd.chunk(chunk_index); 10.864 + return sd.region(region_index); 10.865 } 10.866 #endif 10.867 10.868 @@ -953,10 +745,10 @@ 10.869 const idx_t end_bit = BitMap::word_align_up(_mark_bitmap.addr_to_bit(top)); 10.870 _mark_bitmap.clear_range(beg_bit, end_bit); 10.871 10.872 - const size_t beg_chunk = _summary_data.addr_to_chunk_idx(bot); 10.873 - const size_t end_chunk = 10.874 - _summary_data.addr_to_chunk_idx(_summary_data.chunk_align_up(max_top)); 10.875 - _summary_data.clear_range(beg_chunk, end_chunk); 10.876 + const size_t beg_region = _summary_data.addr_to_region_idx(bot); 10.877 + const size_t end_region = 10.878 + _summary_data.addr_to_region_idx(_summary_data.region_align_up(max_top)); 10.879 + _summary_data.clear_range(beg_region, end_region); 10.880 } 10.881 10.882 void PSParallelCompact::pre_compact(PreGCValues* pre_gc_values) 10.883 @@ -1072,19 +864,19 @@ 10.884 PSParallelCompact::compute_dense_prefix_via_density(const SpaceId id, 10.885 bool maximum_compaction) 10.886 { 10.887 - const size_t chunk_size = ParallelCompactData::ChunkSize; 10.888 + const size_t region_size = ParallelCompactData::RegionSize; 10.889 const ParallelCompactData& sd = summary_data(); 10.890 10.891 const MutableSpace* const space = _space_info[id].space(); 10.892 - HeapWord* const top_aligned_up = sd.chunk_align_up(space->top()); 10.893 - const ChunkData* const beg_cp = sd.addr_to_chunk_ptr(space->bottom()); 10.894 - const ChunkData* const end_cp = sd.addr_to_chunk_ptr(top_aligned_up); 10.895 - 10.896 - // Skip full chunks at the beginning of the space--they are necessarily part 10.897 + HeapWord* const top_aligned_up = sd.region_align_up(space->top()); 10.898 + const RegionData* const beg_cp = sd.addr_to_region_ptr(space->bottom()); 10.899 + const RegionData* const end_cp = sd.addr_to_region_ptr(top_aligned_up); 10.900 + 10.901 + // Skip full regions at the beginning of the space--they are necessarily part 10.902 // of the dense prefix. 10.903 size_t full_count = 0; 10.904 - const ChunkData* cp; 10.905 - for (cp = beg_cp; cp < end_cp && cp->data_size() == chunk_size; ++cp) { 10.906 + const RegionData* cp; 10.907 + for (cp = beg_cp; cp < end_cp && cp->data_size() == region_size; ++cp) { 10.908 ++full_count; 10.909 } 10.910 10.911 @@ -1093,7 +885,7 @@ 10.912 const bool interval_ended = gcs_since_max > HeapMaximumCompactionInterval; 10.913 if (maximum_compaction || cp == end_cp || interval_ended) { 10.914 _maximum_compaction_gc_num = total_invocations(); 10.915 - return sd.chunk_to_addr(cp); 10.916 + return sd.region_to_addr(cp); 10.917 } 10.918 10.919 HeapWord* const new_top = _space_info[id].new_top(); 10.920 @@ -1116,52 +908,53 @@ 10.921 } 10.922 10.923 // XXX - Use binary search? 10.924 - HeapWord* dense_prefix = sd.chunk_to_addr(cp); 10.925 - const ChunkData* full_cp = cp; 10.926 - const ChunkData* const top_cp = sd.addr_to_chunk_ptr(space->top() - 1); 10.927 + HeapWord* dense_prefix = sd.region_to_addr(cp); 10.928 + const RegionData* full_cp = cp; 10.929 + const RegionData* const top_cp = sd.addr_to_region_ptr(space->top() - 1); 10.930 while (cp < end_cp) { 10.931 - HeapWord* chunk_destination = cp->destination(); 10.932 - const size_t cur_deadwood = pointer_delta(dense_prefix, chunk_destination); 10.933 + HeapWord* region_destination = cp->destination(); 10.934 + const size_t cur_deadwood = pointer_delta(dense_prefix, region_destination); 10.935 if (TraceParallelOldGCDensePrefix && Verbose) { 10.936 tty->print_cr("c#=" SIZE_FORMAT_W(4) " dst=" PTR_FORMAT " " 10.937 "dp=" SIZE_FORMAT_W(8) " " "cdw=" SIZE_FORMAT_W(8), 10.938 - sd.chunk(cp), chunk_destination, 10.939 + sd.region(cp), region_destination, 10.940 dense_prefix, cur_deadwood); 10.941 } 10.942 10.943 if (cur_deadwood >= deadwood_goal) { 10.944 - // Found the chunk that has the correct amount of deadwood to the left. 10.945 - // This typically occurs after crossing a fairly sparse set of chunks, so 10.946 - // iterate backwards over those sparse chunks, looking for the chunk that 10.947 - // has the lowest density of live objects 'to the right.' 10.948 - size_t space_to_left = sd.chunk(cp) * chunk_size; 10.949 + // Found the region that has the correct amount of deadwood to the left. 10.950 + // This typically occurs after crossing a fairly sparse set of regions, so 10.951 + // iterate backwards over those sparse regions, looking for the region 10.952 + // that has the lowest density of live objects 'to the right.' 10.953 + size_t space_to_left = sd.region(cp) * region_size; 10.954 size_t live_to_left = space_to_left - cur_deadwood; 10.955 size_t space_to_right = space_capacity - space_to_left; 10.956 size_t live_to_right = space_live - live_to_left; 10.957 double density_to_right = double(live_to_right) / space_to_right; 10.958 while (cp > full_cp) { 10.959 --cp; 10.960 - const size_t prev_chunk_live_to_right = live_to_right - cp->data_size(); 10.961 - const size_t prev_chunk_space_to_right = space_to_right + chunk_size; 10.962 - double prev_chunk_density_to_right = 10.963 - double(prev_chunk_live_to_right) / prev_chunk_space_to_right; 10.964 - if (density_to_right <= prev_chunk_density_to_right) { 10.965 + const size_t prev_region_live_to_right = live_to_right - 10.966 + cp->data_size(); 10.967 + const size_t prev_region_space_to_right = space_to_right + region_size; 10.968 + double prev_region_density_to_right = 10.969 + double(prev_region_live_to_right) / prev_region_space_to_right; 10.970 + if (density_to_right <= prev_region_density_to_right) { 10.971 return dense_prefix; 10.972 } 10.973 if (TraceParallelOldGCDensePrefix && Verbose) { 10.974 tty->print_cr("backing up from c=" SIZE_FORMAT_W(4) " d2r=%10.8f " 10.975 - "pc_d2r=%10.8f", sd.chunk(cp), density_to_right, 10.976 - prev_chunk_density_to_right); 10.977 + "pc_d2r=%10.8f", sd.region(cp), density_to_right, 10.978 + prev_region_density_to_right); 10.979 } 10.980 - dense_prefix -= chunk_size; 10.981 - live_to_right = prev_chunk_live_to_right; 10.982 - space_to_right = prev_chunk_space_to_right; 10.983 - density_to_right = prev_chunk_density_to_right; 10.984 + dense_prefix -= region_size; 10.985 + live_to_right = prev_region_live_to_right; 10.986 + space_to_right = prev_region_space_to_right; 10.987 + density_to_right = prev_region_density_to_right; 10.988 } 10.989 return dense_prefix; 10.990 } 10.991 10.992 - dense_prefix += chunk_size; 10.993 + dense_prefix += region_size; 10.994 ++cp; 10.995 } 10.996 10.997 @@ -1174,8 +967,8 @@ 10.998 const bool maximum_compaction, 10.999 HeapWord* const addr) 10.1000 { 10.1001 - const size_t chunk_idx = summary_data().addr_to_chunk_idx(addr); 10.1002 - ChunkData* const cp = summary_data().chunk(chunk_idx); 10.1003 + const size_t region_idx = summary_data().addr_to_region_idx(addr); 10.1004 + RegionData* const cp = summary_data().region(region_idx); 10.1005 const MutableSpace* const space = _space_info[id].space(); 10.1006 HeapWord* const new_top = _space_info[id].new_top(); 10.1007 10.1008 @@ -1191,7 +984,7 @@ 10.1009 "d2l=" SIZE_FORMAT " d2l%%=%6.4f " 10.1010 "d2r=" SIZE_FORMAT " l2r=" SIZE_FORMAT 10.1011 " ratio=%10.8f", 10.1012 - algorithm, addr, chunk_idx, 10.1013 + algorithm, addr, region_idx, 10.1014 space_live, 10.1015 dead_to_left, dead_to_left_pct, 10.1016 dead_to_right, live_to_right, 10.1017 @@ -1253,52 +1046,52 @@ 10.1018 return MAX2(limit, 0.0); 10.1019 } 10.1020 10.1021 -ParallelCompactData::ChunkData* 10.1022 -PSParallelCompact::first_dead_space_chunk(const ChunkData* beg, 10.1023 - const ChunkData* end) 10.1024 +ParallelCompactData::RegionData* 10.1025 +PSParallelCompact::first_dead_space_region(const RegionData* beg, 10.1026 + const RegionData* end) 10.1027 { 10.1028 - const size_t chunk_size = ParallelCompactData::ChunkSize; 10.1029 + const size_t region_size = ParallelCompactData::RegionSize; 10.1030 ParallelCompactData& sd = summary_data(); 10.1031 - size_t left = sd.chunk(beg); 10.1032 - size_t right = end > beg ? sd.chunk(end) - 1 : left; 10.1033 + size_t left = sd.region(beg); 10.1034 + size_t right = end > beg ? sd.region(end) - 1 : left; 10.1035 10.1036 // Binary search. 10.1037 while (left < right) { 10.1038 // Equivalent to (left + right) / 2, but does not overflow. 10.1039 const size_t middle = left + (right - left) / 2; 10.1040 - ChunkData* const middle_ptr = sd.chunk(middle); 10.1041 + RegionData* const middle_ptr = sd.region(middle); 10.1042 HeapWord* const dest = middle_ptr->destination(); 10.1043 - HeapWord* const addr = sd.chunk_to_addr(middle); 10.1044 + HeapWord* const addr = sd.region_to_addr(middle); 10.1045 assert(dest != NULL, "sanity"); 10.1046 assert(dest <= addr, "must move left"); 10.1047 10.1048 if (middle > left && dest < addr) { 10.1049 right = middle - 1; 10.1050 - } else if (middle < right && middle_ptr->data_size() == chunk_size) { 10.1051 + } else if (middle < right && middle_ptr->data_size() == region_size) { 10.1052 left = middle + 1; 10.1053 } else { 10.1054 return middle_ptr; 10.1055 } 10.1056 } 10.1057 - return sd.chunk(left); 10.1058 + return sd.region(left); 10.1059 } 10.1060 10.1061 -ParallelCompactData::ChunkData* 10.1062 -PSParallelCompact::dead_wood_limit_chunk(const ChunkData* beg, 10.1063 - const ChunkData* end, 10.1064 - size_t dead_words) 10.1065 +ParallelCompactData::RegionData* 10.1066 +PSParallelCompact::dead_wood_limit_region(const RegionData* beg, 10.1067 + const RegionData* end, 10.1068 + size_t dead_words) 10.1069 { 10.1070 ParallelCompactData& sd = summary_data(); 10.1071 - size_t left = sd.chunk(beg); 10.1072 - size_t right = end > beg ? sd.chunk(end) - 1 : left; 10.1073 + size_t left = sd.region(beg); 10.1074 + size_t right = end > beg ? sd.region(end) - 1 : left; 10.1075 10.1076 // Binary search. 10.1077 while (left < right) { 10.1078 // Equivalent to (left + right) / 2, but does not overflow. 10.1079 const size_t middle = left + (right - left) / 2; 10.1080 - ChunkData* const middle_ptr = sd.chunk(middle); 10.1081 + RegionData* const middle_ptr = sd.region(middle); 10.1082 HeapWord* const dest = middle_ptr->destination(); 10.1083 - HeapWord* const addr = sd.chunk_to_addr(middle); 10.1084 + HeapWord* const addr = sd.region_to_addr(middle); 10.1085 assert(dest != NULL, "sanity"); 10.1086 assert(dest <= addr, "must move left"); 10.1087 10.1088 @@ -1311,13 +1104,13 @@ 10.1089 return middle_ptr; 10.1090 } 10.1091 } 10.1092 - return sd.chunk(left); 10.1093 + return sd.region(left); 10.1094 } 10.1095 10.1096 // The result is valid during the summary phase, after the initial summarization 10.1097 // of each space into itself, and before final summarization. 10.1098 inline double 10.1099 -PSParallelCompact::reclaimed_ratio(const ChunkData* const cp, 10.1100 +PSParallelCompact::reclaimed_ratio(const RegionData* const cp, 10.1101 HeapWord* const bottom, 10.1102 HeapWord* const top, 10.1103 HeapWord* const new_top) 10.1104 @@ -1331,12 +1124,13 @@ 10.1105 assert(top >= new_top, "summary data problem?"); 10.1106 assert(new_top > bottom, "space is empty; should not be here"); 10.1107 assert(new_top >= cp->destination(), "sanity"); 10.1108 - assert(top >= sd.chunk_to_addr(cp), "sanity"); 10.1109 + assert(top >= sd.region_to_addr(cp), "sanity"); 10.1110 10.1111 HeapWord* const destination = cp->destination(); 10.1112 const size_t dense_prefix_live = pointer_delta(destination, bottom); 10.1113 const size_t compacted_region_live = pointer_delta(new_top, destination); 10.1114 - const size_t compacted_region_used = pointer_delta(top, sd.chunk_to_addr(cp)); 10.1115 + const size_t compacted_region_used = pointer_delta(top, 10.1116 + sd.region_to_addr(cp)); 10.1117 const size_t reclaimable = compacted_region_used - compacted_region_live; 10.1118 10.1119 const double divisor = dense_prefix_live + 1.25 * compacted_region_live; 10.1120 @@ -1344,39 +1138,40 @@ 10.1121 } 10.1122 10.1123 // Return the address of the end of the dense prefix, a.k.a. the start of the 10.1124 -// compacted region. The address is always on a chunk boundary. 10.1125 +// compacted region. The address is always on a region boundary. 10.1126 // 10.1127 -// Completely full chunks at the left are skipped, since no compaction can occur 10.1128 -// in those chunks. Then the maximum amount of dead wood to allow is computed, 10.1129 -// based on the density (amount live / capacity) of the generation; the chunk 10.1130 -// with approximately that amount of dead space to the left is identified as the 10.1131 -// limit chunk. Chunks between the last completely full chunk and the limit 10.1132 -// chunk are scanned and the one that has the best (maximum) reclaimed_ratio() 10.1133 -// is selected. 10.1134 +// Completely full regions at the left are skipped, since no compaction can 10.1135 +// occur in those regions. Then the maximum amount of dead wood to allow is 10.1136 +// computed, based on the density (amount live / capacity) of the generation; 10.1137 +// the region with approximately that amount of dead space to the left is 10.1138 +// identified as the limit region. Regions between the last completely full 10.1139 +// region and the limit region are scanned and the one that has the best 10.1140 +// (maximum) reclaimed_ratio() is selected. 10.1141 HeapWord* 10.1142 PSParallelCompact::compute_dense_prefix(const SpaceId id, 10.1143 bool maximum_compaction) 10.1144 { 10.1145 - const size_t chunk_size = ParallelCompactData::ChunkSize; 10.1146 + const size_t region_size = ParallelCompactData::RegionSize; 10.1147 const ParallelCompactData& sd = summary_data(); 10.1148 10.1149 const MutableSpace* const space = _space_info[id].space(); 10.1150 HeapWord* const top = space->top(); 10.1151 - HeapWord* const top_aligned_up = sd.chunk_align_up(top); 10.1152 + HeapWord* const top_aligned_up = sd.region_align_up(top); 10.1153 HeapWord* const new_top = _space_info[id].new_top(); 10.1154 - HeapWord* const new_top_aligned_up = sd.chunk_align_up(new_top); 10.1155 + HeapWord* const new_top_aligned_up = sd.region_align_up(new_top); 10.1156 HeapWord* const bottom = space->bottom(); 10.1157 - const ChunkData* const beg_cp = sd.addr_to_chunk_ptr(bottom); 10.1158 - const ChunkData* const top_cp = sd.addr_to_chunk_ptr(top_aligned_up); 10.1159 - const ChunkData* const new_top_cp = sd.addr_to_chunk_ptr(new_top_aligned_up); 10.1160 - 10.1161 - // Skip full chunks at the beginning of the space--they are necessarily part 10.1162 + const RegionData* const beg_cp = sd.addr_to_region_ptr(bottom); 10.1163 + const RegionData* const top_cp = sd.addr_to_region_ptr(top_aligned_up); 10.1164 + const RegionData* const new_top_cp = 10.1165 + sd.addr_to_region_ptr(new_top_aligned_up); 10.1166 + 10.1167 + // Skip full regions at the beginning of the space--they are necessarily part 10.1168 // of the dense prefix. 10.1169 - const ChunkData* const full_cp = first_dead_space_chunk(beg_cp, new_top_cp); 10.1170 - assert(full_cp->destination() == sd.chunk_to_addr(full_cp) || 10.1171 + const RegionData* const full_cp = first_dead_space_region(beg_cp, new_top_cp); 10.1172 + assert(full_cp->destination() == sd.region_to_addr(full_cp) || 10.1173 space->is_empty(), "no dead space allowed to the left"); 10.1174 - assert(full_cp->data_size() < chunk_size || full_cp == new_top_cp - 1, 10.1175 - "chunk must have dead space"); 10.1176 + assert(full_cp->data_size() < region_size || full_cp == new_top_cp - 1, 10.1177 + "region must have dead space"); 10.1178 10.1179 // The gc number is saved whenever a maximum compaction is done, and used to 10.1180 // determine when the maximum compaction interval has expired. This avoids 10.1181 @@ -1387,7 +1182,7 @@ 10.1182 total_invocations() == HeapFirstMaximumCompactionCount; 10.1183 if (maximum_compaction || full_cp == top_cp || interval_ended) { 10.1184 _maximum_compaction_gc_num = total_invocations(); 10.1185 - return sd.chunk_to_addr(full_cp); 10.1186 + return sd.region_to_addr(full_cp); 10.1187 } 10.1188 10.1189 const size_t space_live = pointer_delta(new_top, bottom); 10.1190 @@ -1413,15 +1208,15 @@ 10.1191 dead_wood_max, dead_wood_limit); 10.1192 } 10.1193 10.1194 - // Locate the chunk with the desired amount of dead space to the left. 10.1195 - const ChunkData* const limit_cp = 10.1196 - dead_wood_limit_chunk(full_cp, top_cp, dead_wood_limit); 10.1197 - 10.1198 - // Scan from the first chunk with dead space to the limit chunk and find the 10.1199 + // Locate the region with the desired amount of dead space to the left. 10.1200 + const RegionData* const limit_cp = 10.1201 + dead_wood_limit_region(full_cp, top_cp, dead_wood_limit); 10.1202 + 10.1203 + // Scan from the first region with dead space to the limit region and find the 10.1204 // one with the best (largest) reclaimed ratio. 10.1205 double best_ratio = 0.0; 10.1206 - const ChunkData* best_cp = full_cp; 10.1207 - for (const ChunkData* cp = full_cp; cp < limit_cp; ++cp) { 10.1208 + const RegionData* best_cp = full_cp; 10.1209 + for (const RegionData* cp = full_cp; cp < limit_cp; ++cp) { 10.1210 double tmp_ratio = reclaimed_ratio(cp, bottom, top, new_top); 10.1211 if (tmp_ratio > best_ratio) { 10.1212 best_cp = cp; 10.1213 @@ -1430,18 +1225,18 @@ 10.1214 } 10.1215 10.1216 #if 0 10.1217 - // Something to consider: if the chunk with the best ratio is 'close to' the 10.1218 - // first chunk w/free space, choose the first chunk with free space 10.1219 - // ("first-free"). The first-free chunk is usually near the start of the 10.1220 + // Something to consider: if the region with the best ratio is 'close to' the 10.1221 + // first region w/free space, choose the first region with free space 10.1222 + // ("first-free"). The first-free region is usually near the start of the 10.1223 // heap, which means we are copying most of the heap already, so copy a bit 10.1224 // more to get complete compaction. 10.1225 - if (pointer_delta(best_cp, full_cp, sizeof(ChunkData)) < 4) { 10.1226 + if (pointer_delta(best_cp, full_cp, sizeof(RegionData)) < 4) { 10.1227 _maximum_compaction_gc_num = total_invocations(); 10.1228 best_cp = full_cp; 10.1229 } 10.1230 #endif // #if 0 10.1231 10.1232 - return sd.chunk_to_addr(best_cp); 10.1233 + return sd.region_to_addr(best_cp); 10.1234 } 10.1235 10.1236 void PSParallelCompact::summarize_spaces_quick() 10.1237 @@ -1459,9 +1254,9 @@ 10.1238 void PSParallelCompact::fill_dense_prefix_end(SpaceId id) 10.1239 { 10.1240 HeapWord* const dense_prefix_end = dense_prefix(id); 10.1241 - const ChunkData* chunk = _summary_data.addr_to_chunk_ptr(dense_prefix_end); 10.1242 + const RegionData* region = _summary_data.addr_to_region_ptr(dense_prefix_end); 10.1243 const idx_t dense_prefix_bit = _mark_bitmap.addr_to_bit(dense_prefix_end); 10.1244 - if (dead_space_crosses_boundary(chunk, dense_prefix_bit)) { 10.1245 + if (dead_space_crosses_boundary(region, dense_prefix_bit)) { 10.1246 // Only enough dead space is filled so that any remaining dead space to the 10.1247 // left is larger than the minimum filler object. (The remainder is filled 10.1248 // during the copy/update phase.) 10.1249 @@ -1552,7 +1347,7 @@ 10.1250 fill_dense_prefix_end(id); 10.1251 } 10.1252 10.1253 - // Compute the destination of each Chunk, and thus each object. 10.1254 + // Compute the destination of each Region, and thus each object. 10.1255 _summary_data.summarize_dense_prefix(space->bottom(), dense_prefix_end); 10.1256 _summary_data.summarize(dense_prefix_end, space->end(), 10.1257 dense_prefix_end, space->top(), 10.1258 @@ -1560,19 +1355,19 @@ 10.1259 } 10.1260 10.1261 if (TraceParallelOldGCSummaryPhase) { 10.1262 - const size_t chunk_size = ParallelCompactData::ChunkSize; 10.1263 + const size_t region_size = ParallelCompactData::RegionSize; 10.1264 HeapWord* const dense_prefix_end = _space_info[id].dense_prefix(); 10.1265 - const size_t dp_chunk = _summary_data.addr_to_chunk_idx(dense_prefix_end); 10.1266 + const size_t dp_region = _summary_data.addr_to_region_idx(dense_prefix_end); 10.1267 const size_t dp_words = pointer_delta(dense_prefix_end, space->bottom()); 10.1268 HeapWord* const new_top = _space_info[id].new_top(); 10.1269 - const HeapWord* nt_aligned_up = _summary_data.chunk_align_up(new_top); 10.1270 + const HeapWord* nt_aligned_up = _summary_data.region_align_up(new_top); 10.1271 const size_t cr_words = pointer_delta(nt_aligned_up, dense_prefix_end); 10.1272 tty->print_cr("id=%d cap=" SIZE_FORMAT " dp=" PTR_FORMAT " " 10.1273 - "dp_chunk=" SIZE_FORMAT " " "dp_count=" SIZE_FORMAT " " 10.1274 + "dp_region=" SIZE_FORMAT " " "dp_count=" SIZE_FORMAT " " 10.1275 "cr_count=" SIZE_FORMAT " " "nt=" PTR_FORMAT, 10.1276 id, space->capacity_in_words(), dense_prefix_end, 10.1277 - dp_chunk, dp_words / chunk_size, 10.1278 - cr_words / chunk_size, new_top); 10.1279 + dp_region, dp_words / region_size, 10.1280 + cr_words / region_size, new_top); 10.1281 } 10.1282 } 10.1283 10.1284 @@ -1584,11 +1379,6 @@ 10.1285 // trace("2"); 10.1286 10.1287 #ifdef ASSERT 10.1288 - if (VerifyParallelOldWithMarkSweep && 10.1289 - (PSParallelCompact::total_invocations() % 10.1290 - VerifyParallelOldWithMarkSweepInterval) == 0) { 10.1291 - verify_mark_bitmap(_mark_bitmap); 10.1292 - } 10.1293 if (TraceParallelOldGCMarkingPhase) { 10.1294 tty->print_cr("add_obj_count=" SIZE_FORMAT " " 10.1295 "add_obj_bytes=" SIZE_FORMAT, 10.1296 @@ -1605,7 +1395,7 @@ 10.1297 if (TraceParallelOldGCSummaryPhase) { 10.1298 tty->print_cr("summary_phase: after summarizing each space to self"); 10.1299 Universe::print(); 10.1300 - NOT_PRODUCT(print_chunk_ranges()); 10.1301 + NOT_PRODUCT(print_region_ranges()); 10.1302 if (Verbose) { 10.1303 NOT_PRODUCT(print_initial_summary_data(_summary_data, _space_info)); 10.1304 } 10.1305 @@ -1651,14 +1441,15 @@ 10.1306 space->bottom(), space->top(), 10.1307 new_top_addr); 10.1308 10.1309 - // Clear the source_chunk field for each chunk in the space. 10.1310 + // Clear the source_region field for each region in the space. 10.1311 HeapWord* const new_top = _space_info[id].new_top(); 10.1312 - HeapWord* const clear_end = _summary_data.chunk_align_up(new_top); 10.1313 - ChunkData* beg_chunk = _summary_data.addr_to_chunk_ptr(space->bottom()); 10.1314 - ChunkData* end_chunk = _summary_data.addr_to_chunk_ptr(clear_end); 10.1315 - while (beg_chunk < end_chunk) { 10.1316 - beg_chunk->set_source_chunk(0); 10.1317 - ++beg_chunk; 10.1318 + HeapWord* const clear_end = _summary_data.region_align_up(new_top); 10.1319 + RegionData* beg_region = 10.1320 + _summary_data.addr_to_region_ptr(space->bottom()); 10.1321 + RegionData* end_region = _summary_data.addr_to_region_ptr(clear_end); 10.1322 + while (beg_region < end_region) { 10.1323 + beg_region->set_source_region(0); 10.1324 + ++beg_region; 10.1325 } 10.1326 10.1327 // Reset the new_top value for the space. 10.1328 @@ -1666,243 +1457,16 @@ 10.1329 } 10.1330 } 10.1331 10.1332 - // Fill in the block data after any changes to the chunks have 10.1333 - // been made. 10.1334 -#ifdef ASSERT 10.1335 - summarize_blocks(cm, perm_space_id); 10.1336 - summarize_blocks(cm, old_space_id); 10.1337 -#else 10.1338 - if (!UseParallelOldGCChunkPointerCalc) { 10.1339 - summarize_blocks(cm, perm_space_id); 10.1340 - summarize_blocks(cm, old_space_id); 10.1341 - } 10.1342 -#endif 10.1343 - 10.1344 if (TraceParallelOldGCSummaryPhase) { 10.1345 tty->print_cr("summary_phase: after final summarization"); 10.1346 Universe::print(); 10.1347 - NOT_PRODUCT(print_chunk_ranges()); 10.1348 + NOT_PRODUCT(print_region_ranges()); 10.1349 if (Verbose) { 10.1350 NOT_PRODUCT(print_generic_summary_data(_summary_data, _space_info)); 10.1351 } 10.1352 } 10.1353 } 10.1354 10.1355 -// Fill in the BlockData. 10.1356 -// Iterate over the spaces and within each space iterate over 10.1357 -// the chunks and fill in the BlockData for each chunk. 10.1358 - 10.1359 -void PSParallelCompact::summarize_blocks(ParCompactionManager* cm, 10.1360 - SpaceId first_compaction_space_id) { 10.1361 -#if 0 10.1362 - DEBUG_ONLY(ParallelCompactData::BlockData::set_cur_phase(1);) 10.1363 - for (SpaceId cur_space_id = first_compaction_space_id; 10.1364 - cur_space_id != last_space_id; 10.1365 - cur_space_id = next_compaction_space_id(cur_space_id)) { 10.1366 - // Iterate over the chunks in the space 10.1367 - size_t start_chunk_index = 10.1368 - _summary_data.addr_to_chunk_idx(space(cur_space_id)->bottom()); 10.1369 - BitBlockUpdateClosure bbu(mark_bitmap(), 10.1370 - cm, 10.1371 - start_chunk_index); 10.1372 - // Iterate over blocks. 10.1373 - for (size_t chunk_index = start_chunk_index; 10.1374 - chunk_index < _summary_data.chunk_count() && 10.1375 - _summary_data.chunk_to_addr(chunk_index) < space(cur_space_id)->top(); 10.1376 - chunk_index++) { 10.1377 - 10.1378 - // Reset the closure for the new chunk. Note that the closure 10.1379 - // maintains some data that does not get reset for each chunk 10.1380 - // so a new instance of the closure is no appropriate. 10.1381 - bbu.reset_chunk(chunk_index); 10.1382 - 10.1383 - // Start the iteration with the first live object. This 10.1384 - // may return the end of the chunk. That is acceptable since 10.1385 - // it will properly limit the iterations. 10.1386 - ParMarkBitMap::idx_t left_offset = mark_bitmap()->addr_to_bit( 10.1387 - _summary_data.first_live_or_end_in_chunk(chunk_index)); 10.1388 - 10.1389 - // End the iteration at the end of the chunk. 10.1390 - HeapWord* chunk_addr = _summary_data.chunk_to_addr(chunk_index); 10.1391 - HeapWord* chunk_end = chunk_addr + ParallelCompactData::ChunkSize; 10.1392 - ParMarkBitMap::idx_t right_offset = 10.1393 - mark_bitmap()->addr_to_bit(chunk_end); 10.1394 - 10.1395 - // Blocks that have not objects starting in them can be 10.1396 - // skipped because their data will never be used. 10.1397 - if (left_offset < right_offset) { 10.1398 - 10.1399 - // Iterate through the objects in the chunk. 10.1400 - ParMarkBitMap::idx_t last_offset = 10.1401 - mark_bitmap()->pair_iterate(&bbu, left_offset, right_offset); 10.1402 - 10.1403 - // If last_offset is less than right_offset, then the iterations 10.1404 - // terminated while it was looking for an end bit. "last_offset" 10.1405 - // is then the offset for the last start bit. In this situation 10.1406 - // the "offset" field for the next block to the right (_cur_block + 1) 10.1407 - // will not have been update although there may be live data 10.1408 - // to the left of the chunk. 10.1409 - 10.1410 - size_t cur_block_plus_1 = bbu.cur_block() + 1; 10.1411 - HeapWord* cur_block_plus_1_addr = 10.1412 - _summary_data.block_to_addr(bbu.cur_block()) + 10.1413 - ParallelCompactData::BlockSize; 10.1414 - HeapWord* last_offset_addr = mark_bitmap()->bit_to_addr(last_offset); 10.1415 - #if 1 // This code works. The else doesn't but should. Why does it? 10.1416 - // The current block (cur_block()) has already been updated. 10.1417 - // The last block that may need to be updated is either the 10.1418 - // next block (current block + 1) or the block where the 10.1419 - // last object starts (which can be greater than the 10.1420 - // next block if there were no objects found in intervening 10.1421 - // blocks). 10.1422 - size_t last_block = 10.1423 - MAX2(bbu.cur_block() + 1, 10.1424 - _summary_data.addr_to_block_idx(last_offset_addr)); 10.1425 - #else 10.1426 - // The current block has already been updated. The only block 10.1427 - // that remains to be updated is the block where the last 10.1428 - // object in the chunk starts. 10.1429 - size_t last_block = _summary_data.addr_to_block_idx(last_offset_addr); 10.1430 - #endif 10.1431 - assert_bit_is_start(last_offset); 10.1432 - assert((last_block == _summary_data.block_count()) || 10.1433 - (_summary_data.block(last_block)->raw_offset() == 0), 10.1434 - "Should not have been set"); 10.1435 - // Is the last block still in the current chunk? If still 10.1436 - // in this chunk, update the last block (the counting that 10.1437 - // included the current block is meant for the offset of the last 10.1438 - // block). If not in this chunk, do nothing. Should not 10.1439 - // update a block in the next chunk. 10.1440 - if (ParallelCompactData::chunk_contains_block(bbu.chunk_index(), 10.1441 - last_block)) { 10.1442 - if (last_offset < right_offset) { 10.1443 - // The last object started in this chunk but ends beyond 10.1444 - // this chunk. Update the block for this last object. 10.1445 - assert(mark_bitmap()->is_marked(last_offset), "Should be marked"); 10.1446 - // No end bit was found. The closure takes care of 10.1447 - // the cases where 10.1448 - // an objects crosses over into the next block 10.1449 - // an objects starts and ends in the next block 10.1450 - // It does not handle the case where an object is 10.1451 - // the first object in a later block and extends 10.1452 - // past the end of the chunk (i.e., the closure 10.1453 - // only handles complete objects that are in the range 10.1454 - // it is given). That object is handed back here 10.1455 - // for any special consideration necessary. 10.1456 - // 10.1457 - // Is the first bit in the last block a start or end bit? 10.1458 - // 10.1459 - // If the partial object ends in the last block L, 10.1460 - // then the 1st bit in L may be an end bit. 10.1461 - // 10.1462 - // Else does the last object start in a block after the current 10.1463 - // block? A block AA will already have been updated if an 10.1464 - // object ends in the next block AA+1. An object found to end in 10.1465 - // the AA+1 is the trigger that updates AA. Objects are being 10.1466 - // counted in the current block for updaing a following 10.1467 - // block. An object may start in later block 10.1468 - // block but may extend beyond the last block in the chunk. 10.1469 - // Updates are only done when the end of an object has been 10.1470 - // found. If the last object (covered by block L) starts 10.1471 - // beyond the current block, then no object ends in L (otherwise 10.1472 - // L would be the current block). So the first bit in L is 10.1473 - // a start bit. 10.1474 - // 10.1475 - // Else the last objects start in the current block and ends 10.1476 - // beyond the chunk. The current block has already been 10.1477 - // updated and there is no later block (with an object 10.1478 - // starting in it) that needs to be updated. 10.1479 - // 10.1480 - if (_summary_data.partial_obj_ends_in_block(last_block)) { 10.1481 - _summary_data.block(last_block)->set_end_bit_offset( 10.1482 - bbu.live_data_left()); 10.1483 - } else if (last_offset_addr >= cur_block_plus_1_addr) { 10.1484 - // The start of the object is on a later block 10.1485 - // (to the right of the current block and there are no 10.1486 - // complete live objects to the left of this last object 10.1487 - // within the chunk. 10.1488 - // The first bit in the block is for the start of the 10.1489 - // last object. 10.1490 - _summary_data.block(last_block)->set_start_bit_offset( 10.1491 - bbu.live_data_left()); 10.1492 - } else { 10.1493 - // The start of the last object was found in 10.1494 - // the current chunk (which has already 10.1495 - // been updated). 10.1496 - assert(bbu.cur_block() == 10.1497 - _summary_data.addr_to_block_idx(last_offset_addr), 10.1498 - "Should be a block already processed"); 10.1499 - } 10.1500 -#ifdef ASSERT 10.1501 - // Is there enough block information to find this object? 10.1502 - // The destination of the chunk has not been set so the 10.1503 - // values returned by calc_new_pointer() and 10.1504 - // block_calc_new_pointer() will only be 10.1505 - // offsets. But they should agree. 10.1506 - HeapWord* moved_obj_with_chunks = 10.1507 - _summary_data.chunk_calc_new_pointer(last_offset_addr); 10.1508 - HeapWord* moved_obj_with_blocks = 10.1509 - _summary_data.calc_new_pointer(last_offset_addr); 10.1510 - assert(moved_obj_with_chunks == moved_obj_with_blocks, 10.1511 - "Block calculation is wrong"); 10.1512 -#endif 10.1513 - } else if (last_block < _summary_data.block_count()) { 10.1514 - // Iterations ended looking for a start bit (but 10.1515 - // did not run off the end of the block table). 10.1516 - _summary_data.block(last_block)->set_start_bit_offset( 10.1517 - bbu.live_data_left()); 10.1518 - } 10.1519 - } 10.1520 -#ifdef ASSERT 10.1521 - // Is there enough block information to find this object? 10.1522 - HeapWord* left_offset_addr = mark_bitmap()->bit_to_addr(left_offset); 10.1523 - HeapWord* moved_obj_with_chunks = 10.1524 - _summary_data.calc_new_pointer(left_offset_addr); 10.1525 - HeapWord* moved_obj_with_blocks = 10.1526 - _summary_data.calc_new_pointer(left_offset_addr); 10.1527 - assert(moved_obj_with_chunks == moved_obj_with_blocks, 10.1528 - "Block calculation is wrong"); 10.1529 -#endif 10.1530 - 10.1531 - // Is there another block after the end of this chunk? 10.1532 -#ifdef ASSERT 10.1533 - if (last_block < _summary_data.block_count()) { 10.1534 - // No object may have been found in a block. If that 10.1535 - // block is at the end of the chunk, the iteration will 10.1536 - // terminate without incrementing the current block so 10.1537 - // that the current block is not the last block in the 10.1538 - // chunk. That situation precludes asserting that the 10.1539 - // current block is the last block in the chunk. Assert 10.1540 - // the lesser condition that the current block does not 10.1541 - // exceed the chunk. 10.1542 - assert(_summary_data.block_to_addr(last_block) <= 10.1543 - (_summary_data.chunk_to_addr(chunk_index) + 10.1544 - ParallelCompactData::ChunkSize), 10.1545 - "Chunk and block inconsistency"); 10.1546 - assert(last_offset <= right_offset, "Iteration over ran end"); 10.1547 - } 10.1548 -#endif 10.1549 - } 10.1550 -#ifdef ASSERT 10.1551 - if (PrintGCDetails && Verbose) { 10.1552 - if (_summary_data.chunk(chunk_index)->partial_obj_size() == 1) { 10.1553 - size_t first_block = 10.1554 - chunk_index / ParallelCompactData::BlocksPerChunk; 10.1555 - gclog_or_tty->print_cr("first_block " PTR_FORMAT 10.1556 - " _offset " PTR_FORMAT 10.1557 - "_first_is_start_bit %d", 10.1558 - first_block, 10.1559 - _summary_data.block(first_block)->raw_offset(), 10.1560 - _summary_data.block(first_block)->first_is_start_bit()); 10.1561 - } 10.1562 - } 10.1563 -#endif 10.1564 - } 10.1565 - } 10.1566 - DEBUG_ONLY(ParallelCompactData::BlockData::set_cur_phase(16);) 10.1567 -#endif // #if 0 10.1568 -} 10.1569 - 10.1570 // This method should contain all heap-specific policy for invoking a full 10.1571 // collection. invoke_no_policy() will only attempt to compact the heap; it 10.1572 // will do nothing further. If we need to bail out for policy reasons, scavenge 10.1573 @@ -1937,18 +1501,9 @@ 10.1574 } 10.1575 } 10.1576 10.1577 -bool ParallelCompactData::chunk_contains(size_t chunk_index, HeapWord* addr) { 10.1578 - size_t addr_chunk_index = addr_to_chunk_idx(addr); 10.1579 - return chunk_index == addr_chunk_index; 10.1580 -} 10.1581 - 10.1582 -bool ParallelCompactData::chunk_contains_block(size_t chunk_index, 10.1583 - size_t block_index) { 10.1584 - size_t first_block_in_chunk = chunk_index * BlocksPerChunk; 10.1585 - size_t last_block_in_chunk = (chunk_index + 1) * BlocksPerChunk - 1; 10.1586 - 10.1587 - return (first_block_in_chunk <= block_index) && 10.1588 - (block_index <= last_block_in_chunk); 10.1589 +bool ParallelCompactData::region_contains(size_t region_index, HeapWord* addr) { 10.1590 + size_t addr_region_index = addr_to_region_idx(addr); 10.1591 + return region_index == addr_region_index; 10.1592 } 10.1593 10.1594 // This method contains no policy. You should probably 10.1595 @@ -2038,39 +1593,9 @@ 10.1596 } 10.1597 #endif // #ifndef PRODUCT 10.1598 10.1599 -#ifdef ASSERT 10.1600 - if (VerifyParallelOldWithMarkSweep && 10.1601 - (PSParallelCompact::total_invocations() % 10.1602 - VerifyParallelOldWithMarkSweepInterval) == 0) { 10.1603 - gclog_or_tty->print_cr("Verify marking with mark_sweep_phase1()"); 10.1604 - if (PrintGCDetails && Verbose) { 10.1605 - gclog_or_tty->print_cr("mark_sweep_phase1:"); 10.1606 - } 10.1607 - // Clear the discovered lists so that discovered objects 10.1608 - // don't look like they have been discovered twice. 10.1609 - ref_processor()->clear_discovered_references(); 10.1610 - 10.1611 - PSMarkSweep::allocate_stacks(); 10.1612 - MemRegion mr = Universe::heap()->reserved_region(); 10.1613 - PSMarkSweep::ref_processor()->enable_discovery(); 10.1614 - PSMarkSweep::mark_sweep_phase1(maximum_heap_compaction); 10.1615 - } 10.1616 -#endif 10.1617 - 10.1618 bool max_on_system_gc = UseMaximumCompactionOnSystemGC && is_system_gc; 10.1619 summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc); 10.1620 10.1621 -#ifdef ASSERT 10.1622 - if (VerifyParallelOldWithMarkSweep && 10.1623 - (PSParallelCompact::total_invocations() % 10.1624 - VerifyParallelOldWithMarkSweepInterval) == 0) { 10.1625 - if (PrintGCDetails && Verbose) { 10.1626 - gclog_or_tty->print_cr("mark_sweep_phase2:"); 10.1627 - } 10.1628 - PSMarkSweep::mark_sweep_phase2(); 10.1629 - } 10.1630 -#endif 10.1631 - 10.1632 COMPILER2_PRESENT(assert(DerivedPointerTable::is_active(), "Sanity")); 10.1633 COMPILER2_PRESENT(DerivedPointerTable::set_active(false)); 10.1634 10.1635 @@ -2078,28 +1603,6 @@ 10.1636 // needed by the compaction for filling holes in the dense prefix. 10.1637 adjust_roots(); 10.1638 10.1639 -#ifdef ASSERT 10.1640 - if (VerifyParallelOldWithMarkSweep && 10.1641 - (PSParallelCompact::total_invocations() % 10.1642 - VerifyParallelOldWithMarkSweepInterval) == 0) { 10.1643 - // Do a separate verify phase so that the verify 10.1644 - // code can use the the forwarding pointers to 10.1645 - // check the new pointer calculation. The restore_marks() 10.1646 - // has to be done before the real compact. 10.1647 - vmthread_cm->set_action(ParCompactionManager::VerifyUpdate); 10.1648 - compact_perm(vmthread_cm); 10.1649 - compact_serial(vmthread_cm); 10.1650 - vmthread_cm->set_action(ParCompactionManager::ResetObjects); 10.1651 - compact_perm(vmthread_cm); 10.1652 - compact_serial(vmthread_cm); 10.1653 - vmthread_cm->set_action(ParCompactionManager::UpdateAndCopy); 10.1654 - 10.1655 - // For debugging only 10.1656 - PSMarkSweep::restore_marks(); 10.1657 - PSMarkSweep::deallocate_stacks(); 10.1658 - } 10.1659 -#endif 10.1660 - 10.1661 compaction_start.update(); 10.1662 // Does the perm gen always have to be done serially because 10.1663 // klasses are used in the update of an object? 10.1664 @@ -2349,7 +1852,7 @@ 10.1665 10.1666 ParallelScavengeHeap* heap = gc_heap(); 10.1667 uint parallel_gc_threads = heap->gc_task_manager()->workers(); 10.1668 - TaskQueueSetSuper* qset = ParCompactionManager::chunk_array(); 10.1669 + TaskQueueSetSuper* qset = ParCompactionManager::region_array(); 10.1670 ParallelTaskTerminator terminator(parallel_gc_threads, qset); 10.1671 10.1672 PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); 10.1673 @@ -2487,8 +1990,9 @@ 10.1674 move_and_update(cm, perm_space_id); 10.1675 } 10.1676 10.1677 -void PSParallelCompact::enqueue_chunk_draining_tasks(GCTaskQueue* q, 10.1678 - uint parallel_gc_threads) { 10.1679 +void PSParallelCompact::enqueue_region_draining_tasks(GCTaskQueue* q, 10.1680 + uint parallel_gc_threads) 10.1681 +{ 10.1682 TraceTime tm("drain task setup", print_phases(), true, gclog_or_tty); 10.1683 10.1684 const unsigned int task_count = MAX2(parallel_gc_threads, 1U); 10.1685 @@ -2496,13 +2000,13 @@ 10.1686 q->enqueue(new DrainStacksCompactionTask()); 10.1687 } 10.1688 10.1689 - // Find all chunks that are available (can be filled immediately) and 10.1690 + // Find all regions that are available (can be filled immediately) and 10.1691 // distribute them to the thread stacks. The iteration is done in reverse 10.1692 - // order (high to low) so the chunks will be removed in ascending order. 10.1693 + // order (high to low) so the regions will be removed in ascending order. 10.1694 10.1695 const ParallelCompactData& sd = PSParallelCompact::summary_data(); 10.1696 10.1697 - size_t fillable_chunks = 0; // A count for diagnostic purposes. 10.1698 + size_t fillable_regions = 0; // A count for diagnostic purposes. 10.1699 unsigned int which = 0; // The worker thread number. 10.1700 10.1701 for (unsigned int id = to_space_id; id > perm_space_id; --id) { 10.1702 @@ -2510,25 +2014,26 @@ 10.1703 MutableSpace* const space = space_info->space(); 10.1704 HeapWord* const new_top = space_info->new_top(); 10.1705 10.1706 - const size_t beg_chunk = sd.addr_to_chunk_idx(space_info->dense_prefix()); 10.1707 - const size_t end_chunk = sd.addr_to_chunk_idx(sd.chunk_align_up(new_top)); 10.1708 - assert(end_chunk > 0, "perm gen cannot be empty"); 10.1709 - 10.1710 - for (size_t cur = end_chunk - 1; cur >= beg_chunk; --cur) { 10.1711 - if (sd.chunk(cur)->claim_unsafe()) { 10.1712 + const size_t beg_region = sd.addr_to_region_idx(space_info->dense_prefix()); 10.1713 + const size_t end_region = 10.1714 + sd.addr_to_region_idx(sd.region_align_up(new_top)); 10.1715 + assert(end_region > 0, "perm gen cannot be empty"); 10.1716 + 10.1717 + for (size_t cur = end_region - 1; cur >= beg_region; --cur) { 10.1718 + if (sd.region(cur)->claim_unsafe()) { 10.1719 ParCompactionManager* cm = ParCompactionManager::manager_array(which); 10.1720 cm->save_for_processing(cur); 10.1721 10.1722 if (TraceParallelOldGCCompactionPhase && Verbose) { 10.1723 - const size_t count_mod_8 = fillable_chunks & 7; 10.1724 + const size_t count_mod_8 = fillable_regions & 7; 10.1725 if (count_mod_8 == 0) gclog_or_tty->print("fillable: "); 10.1726 gclog_or_tty->print(" " SIZE_FORMAT_W(7), cur); 10.1727 if (count_mod_8 == 7) gclog_or_tty->cr(); 10.1728 } 10.1729 10.1730 - NOT_PRODUCT(++fillable_chunks;) 10.1731 - 10.1732 - // Assign chunks to threads in round-robin fashion. 10.1733 + NOT_PRODUCT(++fillable_regions;) 10.1734 + 10.1735 + // Assign regions to threads in round-robin fashion. 10.1736 if (++which == task_count) { 10.1737 which = 0; 10.1738 } 10.1739 @@ -2537,8 +2042,8 @@ 10.1740 } 10.1741 10.1742 if (TraceParallelOldGCCompactionPhase) { 10.1743 - if (Verbose && (fillable_chunks & 7) != 0) gclog_or_tty->cr(); 10.1744 - gclog_or_tty->print_cr("%u initially fillable chunks", fillable_chunks); 10.1745 + if (Verbose && (fillable_regions & 7) != 0) gclog_or_tty->cr(); 10.1746 + gclog_or_tty->print_cr("%u initially fillable regions", fillable_regions); 10.1747 } 10.1748 } 10.1749 10.1750 @@ -2551,7 +2056,7 @@ 10.1751 ParallelCompactData& sd = PSParallelCompact::summary_data(); 10.1752 10.1753 // Iterate over all the spaces adding tasks for updating 10.1754 - // chunks in the dense prefix. Assume that 1 gc thread 10.1755 + // regions in the dense prefix. Assume that 1 gc thread 10.1756 // will work on opening the gaps and the remaining gc threads 10.1757 // will work on the dense prefix. 10.1758 SpaceId space_id = old_space_id; 10.1759 @@ -2565,30 +2070,31 @@ 10.1760 continue; 10.1761 } 10.1762 10.1763 - // The dense prefix is before this chunk. 10.1764 - size_t chunk_index_end_dense_prefix = 10.1765 - sd.addr_to_chunk_idx(dense_prefix_end); 10.1766 - ChunkData* const dense_prefix_cp = sd.chunk(chunk_index_end_dense_prefix); 10.1767 + // The dense prefix is before this region. 10.1768 + size_t region_index_end_dense_prefix = 10.1769 + sd.addr_to_region_idx(dense_prefix_end); 10.1770 + RegionData* const dense_prefix_cp = 10.1771 + sd.region(region_index_end_dense_prefix); 10.1772 assert(dense_prefix_end == space->end() || 10.1773 dense_prefix_cp->available() || 10.1774 dense_prefix_cp->claimed(), 10.1775 - "The chunk after the dense prefix should always be ready to fill"); 10.1776 - 10.1777 - size_t chunk_index_start = sd.addr_to_chunk_idx(space->bottom()); 10.1778 + "The region after the dense prefix should always be ready to fill"); 10.1779 + 10.1780 + size_t region_index_start = sd.addr_to_region_idx(space->bottom()); 10.1781 10.1782 // Is there dense prefix work? 10.1783 - size_t total_dense_prefix_chunks = 10.1784 - chunk_index_end_dense_prefix - chunk_index_start; 10.1785 - // How many chunks of the dense prefix should be given to 10.1786 + size_t total_dense_prefix_regions = 10.1787 + region_index_end_dense_prefix - region_index_start; 10.1788 + // How many regions of the dense prefix should be given to 10.1789 // each thread? 10.1790 - if (total_dense_prefix_chunks > 0) { 10.1791 + if (total_dense_prefix_regions > 0) { 10.1792 uint tasks_for_dense_prefix = 1; 10.1793 if (UseParallelDensePrefixUpdate) { 10.1794 - if (total_dense_prefix_chunks <= 10.1795 + if (total_dense_prefix_regions <= 10.1796 (parallel_gc_threads * PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING)) { 10.1797 // Don't over partition. This assumes that 10.1798 // PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING is a small integer value 10.1799 - // so there are not many chunks to process. 10.1800 + // so there are not many regions to process. 10.1801 tasks_for_dense_prefix = parallel_gc_threads; 10.1802 } else { 10.1803 // Over partition 10.1804 @@ -2596,50 +2102,50 @@ 10.1805 PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING; 10.1806 } 10.1807 } 10.1808 - size_t chunks_per_thread = total_dense_prefix_chunks / 10.1809 + size_t regions_per_thread = total_dense_prefix_regions / 10.1810 tasks_for_dense_prefix; 10.1811 - // Give each thread at least 1 chunk. 10.1812 - if (chunks_per_thread == 0) { 10.1813 - chunks_per_thread = 1; 10.1814 + // Give each thread at least 1 region. 10.1815 + if (regions_per_thread == 0) { 10.1816 + regions_per_thread = 1; 10.1817 } 10.1818 10.1819 for (uint k = 0; k < tasks_for_dense_prefix; k++) { 10.1820 - if (chunk_index_start >= chunk_index_end_dense_prefix) { 10.1821 + if (region_index_start >= region_index_end_dense_prefix) { 10.1822 break; 10.1823 } 10.1824 - // chunk_index_end is not processed 10.1825 - size_t chunk_index_end = MIN2(chunk_index_start + chunks_per_thread, 10.1826 - chunk_index_end_dense_prefix); 10.1827 + // region_index_end is not processed 10.1828 + size_t region_index_end = MIN2(region_index_start + regions_per_thread, 10.1829 + region_index_end_dense_prefix); 10.1830 q->enqueue(new UpdateDensePrefixTask( 10.1831 space_id, 10.1832 - chunk_index_start, 10.1833 - chunk_index_end)); 10.1834 - chunk_index_start = chunk_index_end; 10.1835 + region_index_start, 10.1836 + region_index_end)); 10.1837 + region_index_start = region_index_end; 10.1838 } 10.1839 } 10.1840 // This gets any part of the dense prefix that did not 10.1841 // fit evenly. 10.1842 - if (chunk_index_start < chunk_index_end_dense_prefix) { 10.1843 + if (region_index_start < region_index_end_dense_prefix) { 10.1844 q->enqueue(new UpdateDensePrefixTask( 10.1845 space_id, 10.1846 - chunk_index_start, 10.1847 - chunk_index_end_dense_prefix)); 10.1848 + region_index_start, 10.1849 + region_index_end_dense_prefix)); 10.1850 } 10.1851 space_id = next_compaction_space_id(space_id); 10.1852 } // End tasks for dense prefix 10.1853 } 10.1854 10.1855 -void PSParallelCompact::enqueue_chunk_stealing_tasks( 10.1856 +void PSParallelCompact::enqueue_region_stealing_tasks( 10.1857 GCTaskQueue* q, 10.1858 ParallelTaskTerminator* terminator_ptr, 10.1859 uint parallel_gc_threads) { 10.1860 TraceTime tm("steal task setup", print_phases(), true, gclog_or_tty); 10.1861 10.1862 - // Once a thread has drained it's stack, it should try to steal chunks from 10.1863 + // Once a thread has drained it's stack, it should try to steal regions from 10.1864 // other threads. 10.1865 if (parallel_gc_threads > 1) { 10.1866 for (uint j = 0; j < parallel_gc_threads; j++) { 10.1867 - q->enqueue(new StealChunkCompactionTask(terminator_ptr)); 10.1868 + q->enqueue(new StealRegionCompactionTask(terminator_ptr)); 10.1869 } 10.1870 } 10.1871 } 10.1872 @@ -2654,13 +2160,13 @@ 10.1873 PSOldGen* old_gen = heap->old_gen(); 10.1874 old_gen->start_array()->reset(); 10.1875 uint parallel_gc_threads = heap->gc_task_manager()->workers(); 10.1876 - TaskQueueSetSuper* qset = ParCompactionManager::chunk_array(); 10.1877 + TaskQueueSetSuper* qset = ParCompactionManager::region_array(); 10.1878 ParallelTaskTerminator terminator(parallel_gc_threads, qset); 10.1879 10.1880 GCTaskQueue* q = GCTaskQueue::create(); 10.1881 - enqueue_chunk_draining_tasks(q, parallel_gc_threads); 10.1882 + enqueue_region_draining_tasks(q, parallel_gc_threads); 10.1883 enqueue_dense_prefix_tasks(q, parallel_gc_threads); 10.1884 - enqueue_chunk_stealing_tasks(q, &terminator, parallel_gc_threads); 10.1885 + enqueue_region_stealing_tasks(q, &terminator, parallel_gc_threads); 10.1886 10.1887 { 10.1888 TraceTime tm_pc("par compact", print_phases(), true, gclog_or_tty); 10.1889 @@ -2676,9 +2182,9 @@ 10.1890 WaitForBarrierGCTask::destroy(fin); 10.1891 10.1892 #ifdef ASSERT 10.1893 - // Verify that all chunks have been processed before the deferred updates. 10.1894 + // Verify that all regions have been processed before the deferred updates. 10.1895 // Note that perm_space_id is skipped; this type of verification is not 10.1896 - // valid until the perm gen is compacted by chunks. 10.1897 + // valid until the perm gen is compacted by regions. 10.1898 for (unsigned int id = old_space_id; id < last_space_id; ++id) { 10.1899 verify_complete(SpaceId(id)); 10.1900 } 10.1901 @@ -2697,42 +2203,42 @@ 10.1902 10.1903 #ifdef ASSERT 10.1904 void PSParallelCompact::verify_complete(SpaceId space_id) { 10.1905 - // All Chunks between space bottom() to new_top() should be marked as filled 10.1906 - // and all Chunks between new_top() and top() should be available (i.e., 10.1907 + // All Regions between space bottom() to new_top() should be marked as filled 10.1908 + // and all Regions between new_top() and top() should be available (i.e., 10.1909 // should have been emptied). 10.1910 ParallelCompactData& sd = summary_data(); 10.1911 SpaceInfo si = _space_info[space_id]; 10.1912 - HeapWord* new_top_addr = sd.chunk_align_up(si.new_top()); 10.1913 - HeapWord* old_top_addr = sd.chunk_align_up(si.space()->top()); 10.1914 - const size_t beg_chunk = sd.addr_to_chunk_idx(si.space()->bottom()); 10.1915 - const size_t new_top_chunk = sd.addr_to_chunk_idx(new_top_addr); 10.1916 - const size_t old_top_chunk = sd.addr_to_chunk_idx(old_top_addr); 10.1917 + HeapWord* new_top_addr = sd.region_align_up(si.new_top()); 10.1918 + HeapWord* old_top_addr = sd.region_align_up(si.space()->top()); 10.1919 + const size_t beg_region = sd.addr_to_region_idx(si.space()->bottom()); 10.1920 + const size_t new_top_region = sd.addr_to_region_idx(new_top_addr); 10.1921 + const size_t old_top_region = sd.addr_to_region_idx(old_top_addr); 10.1922 10.1923 bool issued_a_warning = false; 10.1924 10.1925 - size_t cur_chunk; 10.1926 - for (cur_chunk = beg_chunk; cur_chunk < new_top_chunk; ++cur_chunk) { 10.1927 - const ChunkData* const c = sd.chunk(cur_chunk); 10.1928 + size_t cur_region; 10.1929 + for (cur_region = beg_region; cur_region < new_top_region; ++cur_region) { 10.1930 + const RegionData* const c = sd.region(cur_region); 10.1931 if (!c->completed()) { 10.1932 - warning("chunk " SIZE_FORMAT " not filled: " 10.1933 + warning("region " SIZE_FORMAT " not filled: " 10.1934 "destination_count=" SIZE_FORMAT, 10.1935 - cur_chunk, c->destination_count()); 10.1936 + cur_region, c->destination_count()); 10.1937 issued_a_warning = true; 10.1938 } 10.1939 } 10.1940 10.1941 - for (cur_chunk = new_top_chunk; cur_chunk < old_top_chunk; ++cur_chunk) { 10.1942 - const ChunkData* const c = sd.chunk(cur_chunk); 10.1943 + for (cur_region = new_top_region; cur_region < old_top_region; ++cur_region) { 10.1944 + const RegionData* const c = sd.region(cur_region); 10.1945 if (!c->available()) { 10.1946 - warning("chunk " SIZE_FORMAT " not empty: " 10.1947 + warning("region " SIZE_FORMAT " not empty: " 10.1948 "destination_count=" SIZE_FORMAT, 10.1949 - cur_chunk, c->destination_count()); 10.1950 + cur_region, c->destination_count()); 10.1951 issued_a_warning = true; 10.1952 } 10.1953 } 10.1954 10.1955 if (issued_a_warning) { 10.1956 - print_chunk_ranges(); 10.1957 + print_region_ranges(); 10.1958 } 10.1959 } 10.1960 #endif // #ifdef ASSERT 10.1961 @@ -2933,46 +2439,47 @@ 10.1962 } 10.1963 #endif //VALIDATE_MARK_SWEEP 10.1964 10.1965 -// Update interior oops in the ranges of chunks [beg_chunk, end_chunk). 10.1966 +// Update interior oops in the ranges of regions [beg_region, end_region). 10.1967 void 10.1968 PSParallelCompact::update_and_deadwood_in_dense_prefix(ParCompactionManager* cm, 10.1969 SpaceId space_id, 10.1970 - size_t beg_chunk, 10.1971 - size_t end_chunk) { 10.1972 + size_t beg_region, 10.1973 + size_t end_region) { 10.1974 ParallelCompactData& sd = summary_data(); 10.1975 ParMarkBitMap* const mbm = mark_bitmap(); 10.1976 10.1977 - HeapWord* beg_addr = sd.chunk_to_addr(beg_chunk); 10.1978 - HeapWord* const end_addr = sd.chunk_to_addr(end_chunk); 10.1979 - assert(beg_chunk <= end_chunk, "bad chunk range"); 10.1980 + HeapWord* beg_addr = sd.region_to_addr(beg_region); 10.1981 + HeapWord* const end_addr = sd.region_to_addr(end_region); 10.1982 + assert(beg_region <= end_region, "bad region range"); 10.1983 assert(end_addr <= dense_prefix(space_id), "not in the dense prefix"); 10.1984 10.1985 #ifdef ASSERT 10.1986 - // Claim the chunks to avoid triggering an assert when they are marked as 10.1987 + // Claim the regions to avoid triggering an assert when they are marked as 10.1988 // filled. 10.1989 - for (size_t claim_chunk = beg_chunk; claim_chunk < end_chunk; ++claim_chunk) { 10.1990 - assert(sd.chunk(claim_chunk)->claim_unsafe(), "claim() failed"); 10.1991 + for (size_t claim_region = beg_region; claim_region < end_region; ++claim_region) { 10.1992 + assert(sd.region(claim_region)->claim_unsafe(), "claim() failed"); 10.1993 } 10.1994 #endif // #ifdef ASSERT 10.1995 10.1996 if (beg_addr != space(space_id)->bottom()) { 10.1997 // Find the first live object or block of dead space that *starts* in this 10.1998 - // range of chunks. If a partial object crosses onto the chunk, skip it; it 10.1999 - // will be marked for 'deferred update' when the object head is processed. 10.2000 - // If dead space crosses onto the chunk, it is also skipped; it will be 10.2001 - // filled when the prior chunk is processed. If neither of those apply, the 10.2002 - // first word in the chunk is the start of a live object or dead space. 10.2003 + // range of regions. If a partial object crosses onto the region, skip it; 10.2004 + // it will be marked for 'deferred update' when the object head is 10.2005 + // processed. If dead space crosses onto the region, it is also skipped; it 10.2006 + // will be filled when the prior region is processed. If neither of those 10.2007 + // apply, the first word in the region is the start of a live object or dead 10.2008 + // space. 10.2009 assert(beg_addr > space(space_id)->bottom(), "sanity"); 10.2010 - const ChunkData* const cp = sd.chunk(beg_chunk); 10.2011 + const RegionData* const cp = sd.region(beg_region); 10.2012 if (cp->partial_obj_size() != 0) { 10.2013 - beg_addr = sd.partial_obj_end(beg_chunk); 10.2014 + beg_addr = sd.partial_obj_end(beg_region); 10.2015 } else if (dead_space_crosses_boundary(cp, mbm->addr_to_bit(beg_addr))) { 10.2016 beg_addr = mbm->find_obj_beg(beg_addr, end_addr); 10.2017 } 10.2018 } 10.2019 10.2020 if (beg_addr < end_addr) { 10.2021 - // A live object or block of dead space starts in this range of Chunks. 10.2022 + // A live object or block of dead space starts in this range of Regions. 10.2023 HeapWord* const dense_prefix_end = dense_prefix(space_id); 10.2024 10.2025 // Create closures and iterate. 10.2026 @@ -2986,10 +2493,10 @@ 10.2027 } 10.2028 } 10.2029 10.2030 - // Mark the chunks as filled. 10.2031 - ChunkData* const beg_cp = sd.chunk(beg_chunk); 10.2032 - ChunkData* const end_cp = sd.chunk(end_chunk); 10.2033 - for (ChunkData* cp = beg_cp; cp < end_cp; ++cp) { 10.2034 + // Mark the regions as filled. 10.2035 + RegionData* const beg_cp = sd.region(beg_region); 10.2036 + RegionData* const end_cp = sd.region(end_region); 10.2037 + for (RegionData* cp = beg_cp; cp < end_cp; ++cp) { 10.2038 cp->set_completed(); 10.2039 } 10.2040 } 10.2041 @@ -3021,13 +2528,13 @@ 10.2042 const MutableSpace* const space = space_info->space(); 10.2043 assert(space_info->dense_prefix() >= space->bottom(), "dense_prefix not set"); 10.2044 HeapWord* const beg_addr = space_info->dense_prefix(); 10.2045 - HeapWord* const end_addr = sd.chunk_align_up(space_info->new_top()); 10.2046 - 10.2047 - const ChunkData* const beg_chunk = sd.addr_to_chunk_ptr(beg_addr); 10.2048 - const ChunkData* const end_chunk = sd.addr_to_chunk_ptr(end_addr); 10.2049 - const ChunkData* cur_chunk; 10.2050 - for (cur_chunk = beg_chunk; cur_chunk < end_chunk; ++cur_chunk) { 10.2051 - HeapWord* const addr = cur_chunk->deferred_obj_addr(); 10.2052 + HeapWord* const end_addr = sd.region_align_up(space_info->new_top()); 10.2053 + 10.2054 + const RegionData* const beg_region = sd.addr_to_region_ptr(beg_addr); 10.2055 + const RegionData* const end_region = sd.addr_to_region_ptr(end_addr); 10.2056 + const RegionData* cur_region; 10.2057 + for (cur_region = beg_region; cur_region < end_region; ++cur_region) { 10.2058 + HeapWord* const addr = cur_region->deferred_obj_addr(); 10.2059 if (addr != NULL) { 10.2060 if (start_array != NULL) { 10.2061 start_array->allocate_block(addr); 10.2062 @@ -3073,45 +2580,45 @@ 10.2063 10.2064 HeapWord* 10.2065 PSParallelCompact::first_src_addr(HeapWord* const dest_addr, 10.2066 - size_t src_chunk_idx) 10.2067 + size_t src_region_idx) 10.2068 { 10.2069 ParMarkBitMap* const bitmap = mark_bitmap(); 10.2070 const ParallelCompactData& sd = summary_data(); 10.2071 - const size_t ChunkSize = ParallelCompactData::ChunkSize; 10.2072 - 10.2073 - assert(sd.is_chunk_aligned(dest_addr), "not aligned"); 10.2074 - 10.2075 - const ChunkData* const src_chunk_ptr = sd.chunk(src_chunk_idx); 10.2076 - const size_t partial_obj_size = src_chunk_ptr->partial_obj_size(); 10.2077 - HeapWord* const src_chunk_destination = src_chunk_ptr->destination(); 10.2078 - 10.2079 - assert(dest_addr >= src_chunk_destination, "wrong src chunk"); 10.2080 - assert(src_chunk_ptr->data_size() > 0, "src chunk cannot be empty"); 10.2081 - 10.2082 - HeapWord* const src_chunk_beg = sd.chunk_to_addr(src_chunk_idx); 10.2083 - HeapWord* const src_chunk_end = src_chunk_beg + ChunkSize; 10.2084 - 10.2085 - HeapWord* addr = src_chunk_beg; 10.2086 - if (dest_addr == src_chunk_destination) { 10.2087 - // Return the first live word in the source chunk. 10.2088 + const size_t RegionSize = ParallelCompactData::RegionSize; 10.2089 + 10.2090 + assert(sd.is_region_aligned(dest_addr), "not aligned"); 10.2091 + 10.2092 + const RegionData* const src_region_ptr = sd.region(src_region_idx); 10.2093 + const size_t partial_obj_size = src_region_ptr->partial_obj_size(); 10.2094 + HeapWord* const src_region_destination = src_region_ptr->destination(); 10.2095 + 10.2096 + assert(dest_addr >= src_region_destination, "wrong src region"); 10.2097 + assert(src_region_ptr->data_size() > 0, "src region cannot be empty"); 10.2098 + 10.2099 + HeapWord* const src_region_beg = sd.region_to_addr(src_region_idx); 10.2100 + HeapWord* const src_region_end = src_region_beg + RegionSize; 10.2101 + 10.2102 + HeapWord* addr = src_region_beg; 10.2103 + if (dest_addr == src_region_destination) { 10.2104 + // Return the first live word in the source region. 10.2105 if (partial_obj_size == 0) { 10.2106 - addr = bitmap->find_obj_beg(addr, src_chunk_end); 10.2107 - assert(addr < src_chunk_end, "no objects start in src chunk"); 10.2108 + addr = bitmap->find_obj_beg(addr, src_region_end); 10.2109 + assert(addr < src_region_end, "no objects start in src region"); 10.2110 } 10.2111 return addr; 10.2112 } 10.2113 10.2114 // Must skip some live data. 10.2115 - size_t words_to_skip = dest_addr - src_chunk_destination; 10.2116 - assert(src_chunk_ptr->data_size() > words_to_skip, "wrong src chunk"); 10.2117 + size_t words_to_skip = dest_addr - src_region_destination; 10.2118 + assert(src_region_ptr->data_size() > words_to_skip, "wrong src region"); 10.2119 10.2120 if (partial_obj_size >= words_to_skip) { 10.2121 // All the live words to skip are part of the partial object. 10.2122 addr += words_to_skip; 10.2123 if (partial_obj_size == words_to_skip) { 10.2124 // Find the first live word past the partial object. 10.2125 - addr = bitmap->find_obj_beg(addr, src_chunk_end); 10.2126 - assert(addr < src_chunk_end, "wrong src chunk"); 10.2127 + addr = bitmap->find_obj_beg(addr, src_region_end); 10.2128 + assert(addr < src_region_end, "wrong src region"); 10.2129 } 10.2130 return addr; 10.2131 } 10.2132 @@ -3122,63 +2629,64 @@ 10.2133 addr += partial_obj_size; 10.2134 } 10.2135 10.2136 - // Skip over live words due to objects that start in the chunk. 10.2137 - addr = skip_live_words(addr, src_chunk_end, words_to_skip); 10.2138 - assert(addr < src_chunk_end, "wrong src chunk"); 10.2139 + // Skip over live words due to objects that start in the region. 10.2140 + addr = skip_live_words(addr, src_region_end, words_to_skip); 10.2141 + assert(addr < src_region_end, "wrong src region"); 10.2142 return addr; 10.2143 } 10.2144 10.2145 void PSParallelCompact::decrement_destination_counts(ParCompactionManager* cm, 10.2146 - size_t beg_chunk, 10.2147 + size_t beg_region, 10.2148 HeapWord* end_addr) 10.2149 { 10.2150 ParallelCompactData& sd = summary_data(); 10.2151 - ChunkData* const beg = sd.chunk(beg_chunk); 10.2152 - HeapWord* const end_addr_aligned_up = sd.chunk_align_up(end_addr); 10.2153 - ChunkData* const end = sd.addr_to_chunk_ptr(end_addr_aligned_up); 10.2154 - size_t cur_idx = beg_chunk; 10.2155 - for (ChunkData* cur = beg; cur < end; ++cur, ++cur_idx) { 10.2156 - assert(cur->data_size() > 0, "chunk must have live data"); 10.2157 + RegionData* const beg = sd.region(beg_region); 10.2158 + HeapWord* const end_addr_aligned_up = sd.region_align_up(end_addr); 10.2159 + RegionData* const end = sd.addr_to_region_ptr(end_addr_aligned_up); 10.2160 + size_t cur_idx = beg_region; 10.2161 + for (RegionData* cur = beg; cur < end; ++cur, ++cur_idx) { 10.2162 + assert(cur->data_size() > 0, "region must have live data"); 10.2163 cur->decrement_destination_count(); 10.2164 - if (cur_idx <= cur->source_chunk() && cur->available() && cur->claim()) { 10.2165 + if (cur_idx <= cur->source_region() && cur->available() && cur->claim()) { 10.2166 cm->save_for_processing(cur_idx); 10.2167 } 10.2168 } 10.2169 } 10.2170 10.2171 -size_t PSParallelCompact::next_src_chunk(MoveAndUpdateClosure& closure, 10.2172 - SpaceId& src_space_id, 10.2173 - HeapWord*& src_space_top, 10.2174 - HeapWord* end_addr) 10.2175 +size_t PSParallelCompact::next_src_region(MoveAndUpdateClosure& closure, 10.2176 + SpaceId& src_space_id, 10.2177 + HeapWord*& src_space_top, 10.2178 + HeapWord* end_addr) 10.2179 { 10.2180 - typedef ParallelCompactData::ChunkData ChunkData; 10.2181 + typedef ParallelCompactData::RegionData RegionData; 10.2182 10.2183 ParallelCompactData& sd = PSParallelCompact::summary_data(); 10.2184 - const size_t chunk_size = ParallelCompactData::ChunkSize; 10.2185 - 10.2186 - size_t src_chunk_idx = 0; 10.2187 - 10.2188 - // Skip empty chunks (if any) up to the top of the space. 10.2189 - HeapWord* const src_aligned_up = sd.chunk_align_up(end_addr); 10.2190 - ChunkData* src_chunk_ptr = sd.addr_to_chunk_ptr(src_aligned_up); 10.2191 - HeapWord* const top_aligned_up = sd.chunk_align_up(src_space_top); 10.2192 - const ChunkData* const top_chunk_ptr = sd.addr_to_chunk_ptr(top_aligned_up); 10.2193 - while (src_chunk_ptr < top_chunk_ptr && src_chunk_ptr->data_size() == 0) { 10.2194 - ++src_chunk_ptr; 10.2195 + const size_t region_size = ParallelCompactData::RegionSize; 10.2196 + 10.2197 + size_t src_region_idx = 0; 10.2198 + 10.2199 + // Skip empty regions (if any) up to the top of the space. 10.2200 + HeapWord* const src_aligned_up = sd.region_align_up(end_addr); 10.2201 + RegionData* src_region_ptr = sd.addr_to_region_ptr(src_aligned_up); 10.2202 + HeapWord* const top_aligned_up = sd.region_align_up(src_space_top); 10.2203 + const RegionData* const top_region_ptr = 10.2204 + sd.addr_to_region_ptr(top_aligned_up); 10.2205 + while (src_region_ptr < top_region_ptr && src_region_ptr->data_size() == 0) { 10.2206 + ++src_region_ptr; 10.2207 } 10.2208 10.2209 - if (src_chunk_ptr < top_chunk_ptr) { 10.2210 - // The next source chunk is in the current space. Update src_chunk_idx and 10.2211 - // the source address to match src_chunk_ptr. 10.2212 - src_chunk_idx = sd.chunk(src_chunk_ptr); 10.2213 - HeapWord* const src_chunk_addr = sd.chunk_to_addr(src_chunk_idx); 10.2214 - if (src_chunk_addr > closure.source()) { 10.2215 - closure.set_source(src_chunk_addr); 10.2216 + if (src_region_ptr < top_region_ptr) { 10.2217 + // The next source region is in the current space. Update src_region_idx 10.2218 + // and the source address to match src_region_ptr. 10.2219 + src_region_idx = sd.region(src_region_ptr); 10.2220 + HeapWord* const src_region_addr = sd.region_to_addr(src_region_idx); 10.2221 + if (src_region_addr > closure.source()) { 10.2222 + closure.set_source(src_region_addr); 10.2223 } 10.2224 - return src_chunk_idx; 10.2225 + return src_region_idx; 10.2226 } 10.2227 10.2228 - // Switch to a new source space and find the first non-empty chunk. 10.2229 + // Switch to a new source space and find the first non-empty region. 10.2230 unsigned int space_id = src_space_id + 1; 10.2231 assert(space_id < last_space_id, "not enough spaces"); 10.2232 10.2233 @@ -3187,14 +2695,14 @@ 10.2234 do { 10.2235 MutableSpace* space = _space_info[space_id].space(); 10.2236 HeapWord* const bottom = space->bottom(); 10.2237 - const ChunkData* const bottom_cp = sd.addr_to_chunk_ptr(bottom); 10.2238 + const RegionData* const bottom_cp = sd.addr_to_region_ptr(bottom); 10.2239 10.2240 // Iterate over the spaces that do not compact into themselves. 10.2241 if (bottom_cp->destination() != bottom) { 10.2242 - HeapWord* const top_aligned_up = sd.chunk_align_up(space->top()); 10.2243 - const ChunkData* const top_cp = sd.addr_to_chunk_ptr(top_aligned_up); 10.2244 - 10.2245 - for (const ChunkData* src_cp = bottom_cp; src_cp < top_cp; ++src_cp) { 10.2246 + HeapWord* const top_aligned_up = sd.region_align_up(space->top()); 10.2247 + const RegionData* const top_cp = sd.addr_to_region_ptr(top_aligned_up); 10.2248 + 10.2249 + for (const RegionData* src_cp = bottom_cp; src_cp < top_cp; ++src_cp) { 10.2250 if (src_cp->live_obj_size() > 0) { 10.2251 // Found it. 10.2252 assert(src_cp->destination() == destination, 10.2253 @@ -3204,9 +2712,9 @@ 10.2254 10.2255 src_space_id = SpaceId(space_id); 10.2256 src_space_top = space->top(); 10.2257 - const size_t src_chunk_idx = sd.chunk(src_cp); 10.2258 - closure.set_source(sd.chunk_to_addr(src_chunk_idx)); 10.2259 - return src_chunk_idx; 10.2260 + const size_t src_region_idx = sd.region(src_cp); 10.2261 + closure.set_source(sd.region_to_addr(src_region_idx)); 10.2262 + return src_region_idx; 10.2263 } else { 10.2264 assert(src_cp->data_size() == 0, "sanity"); 10.2265 } 10.2266 @@ -3214,38 +2722,38 @@ 10.2267 } 10.2268 } while (++space_id < last_space_id); 10.2269 10.2270 - assert(false, "no source chunk was found"); 10.2271 + assert(false, "no source region was found"); 10.2272 return 0; 10.2273 } 10.2274 10.2275 -void PSParallelCompact::fill_chunk(ParCompactionManager* cm, size_t chunk_idx) 10.2276 +void PSParallelCompact::fill_region(ParCompactionManager* cm, size_t region_idx) 10.2277 { 10.2278 typedef ParMarkBitMap::IterationStatus IterationStatus; 10.2279 - const size_t ChunkSize = ParallelCompactData::ChunkSize; 10.2280 + const size_t RegionSize = ParallelCompactData::RegionSize; 10.2281 ParMarkBitMap* const bitmap = mark_bitmap(); 10.2282 ParallelCompactData& sd = summary_data(); 10.2283 - ChunkData* const chunk_ptr = sd.chunk(chunk_idx); 10.2284 + RegionData* const region_ptr = sd.region(region_idx); 10.2285 10.2286 // Get the items needed to construct the closure. 10.2287 - HeapWord* dest_addr = sd.chunk_to_addr(chunk_idx); 10.2288 + HeapWord* dest_addr = sd.region_to_addr(region_idx); 10.2289 SpaceId dest_space_id = space_id(dest_addr); 10.2290 ObjectStartArray* start_array = _space_info[dest_space_id].start_array(); 10.2291 HeapWord* new_top = _space_info[dest_space_id].new_top(); 10.2292 assert(dest_addr < new_top, "sanity"); 10.2293 - const size_t words = MIN2(pointer_delta(new_top, dest_addr), ChunkSize); 10.2294 - 10.2295 - // Get the source chunk and related info. 10.2296 - size_t src_chunk_idx = chunk_ptr->source_chunk(); 10.2297 - SpaceId src_space_id = space_id(sd.chunk_to_addr(src_chunk_idx)); 10.2298 + const size_t words = MIN2(pointer_delta(new_top, dest_addr), RegionSize); 10.2299 + 10.2300 + // Get the source region and related info. 10.2301 + size_t src_region_idx = region_ptr->source_region(); 10.2302 + SpaceId src_space_id = space_id(sd.region_to_addr(src_region_idx)); 10.2303 HeapWord* src_space_top = _space_info[src_space_id].space()->top(); 10.2304 10.2305 MoveAndUpdateClosure closure(bitmap, cm, start_array, dest_addr, words); 10.2306 - closure.set_source(first_src_addr(dest_addr, src_chunk_idx)); 10.2307 - 10.2308 - // Adjust src_chunk_idx to prepare for decrementing destination counts (the 10.2309 - // destination count is not decremented when a chunk is copied to itself). 10.2310 - if (src_chunk_idx == chunk_idx) { 10.2311 - src_chunk_idx += 1; 10.2312 + closure.set_source(first_src_addr(dest_addr, src_region_idx)); 10.2313 + 10.2314 + // Adjust src_region_idx to prepare for decrementing destination counts (the 10.2315 + // destination count is not decremented when a region is copied to itself). 10.2316 + if (src_region_idx == region_idx) { 10.2317 + src_region_idx += 1; 10.2318 } 10.2319 10.2320 if (bitmap->is_unmarked(closure.source())) { 10.2321 @@ -3255,32 +2763,33 @@ 10.2322 HeapWord* const old_src_addr = closure.source(); 10.2323 closure.copy_partial_obj(); 10.2324 if (closure.is_full()) { 10.2325 - decrement_destination_counts(cm, src_chunk_idx, closure.source()); 10.2326 - chunk_ptr->set_deferred_obj_addr(NULL); 10.2327 - chunk_ptr->set_completed(); 10.2328 + decrement_destination_counts(cm, src_region_idx, closure.source()); 10.2329 + region_ptr->set_deferred_obj_addr(NULL); 10.2330 + region_ptr->set_completed(); 10.2331 return; 10.2332 } 10.2333 10.2334 - HeapWord* const end_addr = sd.chunk_align_down(closure.source()); 10.2335 - if (sd.chunk_align_down(old_src_addr) != end_addr) { 10.2336 - // The partial object was copied from more than one source chunk. 10.2337 - decrement_destination_counts(cm, src_chunk_idx, end_addr); 10.2338 - 10.2339 - // Move to the next source chunk, possibly switching spaces as well. All 10.2340 + HeapWord* const end_addr = sd.region_align_down(closure.source()); 10.2341 + if (sd.region_align_down(old_src_addr) != end_addr) { 10.2342 + // The partial object was copied from more than one source region. 10.2343 + decrement_destination_counts(cm, src_region_idx, end_addr); 10.2344 + 10.2345 + // Move to the next source region, possibly switching spaces as well. All 10.2346 // args except end_addr may be modified. 10.2347 - src_chunk_idx = next_src_chunk(closure, src_space_id, src_space_top, 10.2348 - end_addr); 10.2349 + src_region_idx = next_src_region(closure, src_space_id, src_space_top, 10.2350 + end_addr); 10.2351 } 10.2352 } 10.2353 10.2354 do { 10.2355 HeapWord* const cur_addr = closure.source(); 10.2356 - HeapWord* const end_addr = MIN2(sd.chunk_align_up(cur_addr + 1), 10.2357 + HeapWord* const end_addr = MIN2(sd.region_align_up(cur_addr + 1), 10.2358 src_space_top); 10.2359 IterationStatus status = bitmap->iterate(&closure, cur_addr, end_addr); 10.2360 10.2361 if (status == ParMarkBitMap::incomplete) { 10.2362 - // The last obj that starts in the source chunk does not end in the chunk. 10.2363 + // The last obj that starts in the source region does not end in the 10.2364 + // region. 10.2365 assert(closure.source() < end_addr, "sanity") 10.2366 HeapWord* const obj_beg = closure.source(); 10.2367 HeapWord* const range_end = MIN2(obj_beg + closure.words_remaining(), 10.2368 @@ -3299,28 +2808,28 @@ 10.2369 10.2370 if (status == ParMarkBitMap::would_overflow) { 10.2371 // The last object did not fit. Note that interior oop updates were 10.2372 - // deferred, then copy enough of the object to fill the chunk. 10.2373 - chunk_ptr->set_deferred_obj_addr(closure.destination()); 10.2374 + // deferred, then copy enough of the object to fill the region. 10.2375 + region_ptr->set_deferred_obj_addr(closure.destination()); 10.2376 status = closure.copy_until_full(); // copies from closure.source() 10.2377 10.2378 - decrement_destination_counts(cm, src_chunk_idx, closure.source()); 10.2379 - chunk_ptr->set_completed(); 10.2380 + decrement_destination_counts(cm, src_region_idx, closure.source()); 10.2381 + region_ptr->set_completed(); 10.2382 return; 10.2383 } 10.2384 10.2385 if (status == ParMarkBitMap::full) { 10.2386 - decrement_destination_counts(cm, src_chunk_idx, closure.source()); 10.2387 - chunk_ptr->set_deferred_obj_addr(NULL); 10.2388 - chunk_ptr->set_completed(); 10.2389 + decrement_destination_counts(cm, src_region_idx, closure.source()); 10.2390 + region_ptr->set_deferred_obj_addr(NULL); 10.2391 + region_ptr->set_completed(); 10.2392 return; 10.2393 } 10.2394 10.2395 - decrement_destination_counts(cm, src_chunk_idx, end_addr); 10.2396 - 10.2397 - // Move to the next source chunk, possibly switching spaces as well. All 10.2398 + decrement_destination_counts(cm, src_region_idx, end_addr); 10.2399 + 10.2400 + // Move to the next source region, possibly switching spaces as well. All 10.2401 // args except end_addr may be modified. 10.2402 - src_chunk_idx = next_src_chunk(closure, src_space_id, src_space_top, 10.2403 - end_addr); 10.2404 + src_region_idx = next_src_region(closure, src_space_id, src_space_top, 10.2405 + end_addr); 10.2406 } while (true); 10.2407 } 10.2408 10.2409 @@ -3352,15 +2861,15 @@ 10.2410 } 10.2411 #endif 10.2412 10.2413 - const size_t beg_chunk = sd.addr_to_chunk_idx(beg_addr); 10.2414 - const size_t dp_chunk = sd.addr_to_chunk_idx(dp_addr); 10.2415 - if (beg_chunk < dp_chunk) { 10.2416 - update_and_deadwood_in_dense_prefix(cm, space_id, beg_chunk, dp_chunk); 10.2417 + const size_t beg_region = sd.addr_to_region_idx(beg_addr); 10.2418 + const size_t dp_region = sd.addr_to_region_idx(dp_addr); 10.2419 + if (beg_region < dp_region) { 10.2420 + update_and_deadwood_in_dense_prefix(cm, space_id, beg_region, dp_region); 10.2421 } 10.2422 10.2423 - // The destination of the first live object that starts in the chunk is one 10.2424 - // past the end of the partial object entering the chunk (if any). 10.2425 - HeapWord* const dest_addr = sd.partial_obj_end(dp_chunk); 10.2426 + // The destination of the first live object that starts in the region is one 10.2427 + // past the end of the partial object entering the region (if any). 10.2428 + HeapWord* const dest_addr = sd.partial_obj_end(dp_region); 10.2429 HeapWord* const new_top = _space_info[space_id].new_top(); 10.2430 assert(new_top >= dest_addr, "bad new_top value"); 10.2431 const size_t words = pointer_delta(new_top, dest_addr); 10.2432 @@ -3469,172 +2978,6 @@ 10.2433 return ParMarkBitMap::incomplete; 10.2434 } 10.2435 10.2436 -BitBlockUpdateClosure::BitBlockUpdateClosure(ParMarkBitMap* mbm, 10.2437 - ParCompactionManager* cm, 10.2438 - size_t chunk_index) : 10.2439 - ParMarkBitMapClosure(mbm, cm), 10.2440 - _live_data_left(0), 10.2441 - _cur_block(0) { 10.2442 - _chunk_start = 10.2443 - PSParallelCompact::summary_data().chunk_to_addr(chunk_index); 10.2444 - _chunk_end = 10.2445 - PSParallelCompact::summary_data().chunk_to_addr(chunk_index) + 10.2446 - ParallelCompactData::ChunkSize; 10.2447 - _chunk_index = chunk_index; 10.2448 - _cur_block = 10.2449 - PSParallelCompact::summary_data().addr_to_block_idx(_chunk_start); 10.2450 -} 10.2451 - 10.2452 -bool BitBlockUpdateClosure::chunk_contains_cur_block() { 10.2453 - return ParallelCompactData::chunk_contains_block(_chunk_index, _cur_block); 10.2454 -} 10.2455 - 10.2456 -void BitBlockUpdateClosure::reset_chunk(size_t chunk_index) { 10.2457 - DEBUG_ONLY(ParallelCompactData::BlockData::set_cur_phase(7);) 10.2458 - ParallelCompactData& sd = PSParallelCompact::summary_data(); 10.2459 - _chunk_index = chunk_index; 10.2460 - _live_data_left = 0; 10.2461 - _chunk_start = sd.chunk_to_addr(chunk_index); 10.2462 - _chunk_end = sd.chunk_to_addr(chunk_index) + ParallelCompactData::ChunkSize; 10.2463 - 10.2464 - // The first block in this chunk 10.2465 - size_t first_block = sd.addr_to_block_idx(_chunk_start); 10.2466 - size_t partial_live_size = sd.chunk(chunk_index)->partial_obj_size(); 10.2467 - 10.2468 - // Set the offset to 0. By definition it should have that value 10.2469 - // but it may have been written while processing an earlier chunk. 10.2470 - if (partial_live_size == 0) { 10.2471 - // No live object extends onto the chunk. The first bit 10.2472 - // in the bit map for the first chunk must be a start bit. 10.2473 - // Although there may not be any marked bits, it is safe 10.2474 - // to set it as a start bit. 10.2475 - sd.block(first_block)->set_start_bit_offset(0); 10.2476 - sd.block(first_block)->set_first_is_start_bit(true); 10.2477 - } else if (sd.partial_obj_ends_in_block(first_block)) { 10.2478 - sd.block(first_block)->set_end_bit_offset(0); 10.2479 - sd.block(first_block)->set_first_is_start_bit(false); 10.2480 - } else { 10.2481 - // The partial object extends beyond the first block. 10.2482 - // There is no object starting in the first block 10.2483 - // so the offset and bit parity are not needed. 10.2484 - // Set the the bit parity to start bit so assertions 10.2485 - // work when not bit is found. 10.2486 - sd.block(first_block)->set_end_bit_offset(0); 10.2487 - sd.block(first_block)->set_first_is_start_bit(false); 10.2488 - } 10.2489 - _cur_block = first_block; 10.2490 -#ifdef ASSERT 10.2491 - if (sd.block(first_block)->first_is_start_bit()) { 10.2492 - assert(!sd.partial_obj_ends_in_block(first_block), 10.2493 - "Partial object cannot end in first block"); 10.2494 - } 10.2495 - 10.2496 - if (PrintGCDetails && Verbose) { 10.2497 - if (partial_live_size == 1) { 10.2498 - gclog_or_tty->print_cr("first_block " PTR_FORMAT 10.2499 - " _offset " PTR_FORMAT 10.2500 - " _first_is_start_bit %d", 10.2501 - first_block, 10.2502 - sd.block(first_block)->raw_offset(), 10.2503 - sd.block(first_block)->first_is_start_bit()); 10.2504 - } 10.2505 - } 10.2506 -#endif 10.2507 - DEBUG_ONLY(ParallelCompactData::BlockData::set_cur_phase(17);) 10.2508 -} 10.2509 - 10.2510 -// This method is called when a object has been found (both beginning 10.2511 -// and end of the object) in the range of iteration. This method is 10.2512 -// calculating the words of live data to the left of a block. That live 10.2513 -// data includes any object starting to the left of the block (i.e., 10.2514 -// the live-data-to-the-left of block AAA will include the full size 10.2515 -// of any object entering AAA). 10.2516 - 10.2517 -ParMarkBitMapClosure::IterationStatus 10.2518 -BitBlockUpdateClosure::do_addr(HeapWord* addr, size_t words) { 10.2519 - // add the size to the block data. 10.2520 - HeapWord* obj = addr; 10.2521 - ParallelCompactData& sd = PSParallelCompact::summary_data(); 10.2522 - 10.2523 - assert(bitmap()->obj_size(obj) == words, "bad size"); 10.2524 - assert(_chunk_start <= obj, "object is not in chunk"); 10.2525 - assert(obj + words <= _chunk_end, "object is not in chunk"); 10.2526 - 10.2527 - // Update the live data to the left 10.2528 - size_t prev_live_data_left = _live_data_left; 10.2529 - _live_data_left = _live_data_left + words; 10.2530 - 10.2531 - // Is this object in the current block. 10.2532 - size_t block_of_obj = sd.addr_to_block_idx(obj); 10.2533 - size_t block_of_obj_last = sd.addr_to_block_idx(obj + words - 1); 10.2534 - HeapWord* block_of_obj_last_addr = sd.block_to_addr(block_of_obj_last); 10.2535 - if (_cur_block < block_of_obj) { 10.2536 - 10.2537 - // 10.2538 - // No object crossed the block boundary and this object was found 10.2539 - // on the other side of the block boundary. Update the offset for 10.2540 - // the new block with the data size that does not include this object. 10.2541 - // 10.2542 - // The first bit in block_of_obj is a start bit except in the 10.2543 - // case where the partial object for the chunk extends into 10.2544 - // this block. 10.2545 - if (sd.partial_obj_ends_in_block(block_of_obj)) { 10.2546 - sd.block(block_of_obj)->set_end_bit_offset(prev_live_data_left); 10.2547 - } else { 10.2548 - sd.block(block_of_obj)->set_start_bit_offset(prev_live_data_left); 10.2549 - } 10.2550 - 10.2551 - // Does this object pass beyond the its block? 10.2552 - if (block_of_obj < block_of_obj_last) { 10.2553 - // Object crosses block boundary. Two blocks need to be udpated: 10.2554 - // the current block where the object started 10.2555 - // the block where the object ends 10.2556 - // 10.2557 - // The offset for blocks with no objects starting in them 10.2558 - // (e.g., blocks between _cur_block and block_of_obj_last) 10.2559 - // should not be needed. 10.2560 - // Note that block_of_obj_last may be in another chunk. If so, 10.2561 - // it should be overwritten later. This is a problem (writting 10.2562 - // into a block in a later chunk) for parallel execution. 10.2563 - assert(obj < block_of_obj_last_addr, 10.2564 - "Object should start in previous block"); 10.2565 - 10.2566 - // obj is crossing into block_of_obj_last so the first bit 10.2567 - // is and end bit. 10.2568 - sd.block(block_of_obj_last)->set_end_bit_offset(_live_data_left); 10.2569 - 10.2570 - _cur_block = block_of_obj_last; 10.2571 - } else { 10.2572 - // _first_is_start_bit has already been set correctly 10.2573 - // in the if-then-else above so don't reset it here. 10.2574 - _cur_block = block_of_obj; 10.2575 - } 10.2576 - } else { 10.2577 - // The current block only changes if the object extends beyound 10.2578 - // the block it starts in. 10.2579 - // 10.2580 - // The object starts in the current block. 10.2581 - // Does this object pass beyond the end of it? 10.2582 - if (block_of_obj < block_of_obj_last) { 10.2583 - // Object crosses block boundary. 10.2584 - // See note above on possible blocks between block_of_obj and 10.2585 - // block_of_obj_last 10.2586 - assert(obj < block_of_obj_last_addr, 10.2587 - "Object should start in previous block"); 10.2588 - 10.2589 - sd.block(block_of_obj_last)->set_end_bit_offset(_live_data_left); 10.2590 - 10.2591 - _cur_block = block_of_obj_last; 10.2592 - } 10.2593 - } 10.2594 - 10.2595 - // Return incomplete if there are more blocks to be done. 10.2596 - if (chunk_contains_cur_block()) { 10.2597 - return ParMarkBitMap::incomplete; 10.2598 - } 10.2599 - return ParMarkBitMap::complete; 10.2600 -} 10.2601 - 10.2602 // Verify the new location using the forwarding pointer 10.2603 // from MarkSweep::mark_sweep_phase2(). Set the mark_word 10.2604 // to the initial value. 10.2605 @@ -3707,12 +3050,3 @@ 10.2606 return last_space_id; 10.2607 } 10.2608 } 10.2609 - 10.2610 -// Here temporarily for debugging 10.2611 -#ifdef ASSERT 10.2612 - size_t ParallelCompactData::block_idx(BlockData* block) { 10.2613 - size_t index = pointer_delta(block, 10.2614 - PSParallelCompact::summary_data()._block_data, sizeof(BlockData)); 10.2615 - return index; 10.2616 - } 10.2617 -#endif
11.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Tue Sep 30 15:53:55 2008 -0700 11.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Wed Oct 01 15:05:06 2008 -0400 11.3 @@ -76,87 +76,80 @@ 11.4 { 11.5 public: 11.6 // Sizes are in HeapWords, unless indicated otherwise. 11.7 - static const size_t Log2ChunkSize; 11.8 - static const size_t ChunkSize; 11.9 - static const size_t ChunkSizeBytes; 11.10 + static const size_t Log2RegionSize; 11.11 + static const size_t RegionSize; 11.12 + static const size_t RegionSizeBytes; 11.13 11.14 - // Mask for the bits in a size_t to get an offset within a chunk. 11.15 - static const size_t ChunkSizeOffsetMask; 11.16 - // Mask for the bits in a pointer to get an offset within a chunk. 11.17 - static const size_t ChunkAddrOffsetMask; 11.18 - // Mask for the bits in a pointer to get the address of the start of a chunk. 11.19 - static const size_t ChunkAddrMask; 11.20 + // Mask for the bits in a size_t to get an offset within a region. 11.21 + static const size_t RegionSizeOffsetMask; 11.22 + // Mask for the bits in a pointer to get an offset within a region. 11.23 + static const size_t RegionAddrOffsetMask; 11.24 + // Mask for the bits in a pointer to get the address of the start of a region. 11.25 + static const size_t RegionAddrMask; 11.26 11.27 - static const size_t Log2BlockSize; 11.28 - static const size_t BlockSize; 11.29 - static const size_t BlockOffsetMask; 11.30 - static const size_t BlockMask; 11.31 - 11.32 - static const size_t BlocksPerChunk; 11.33 - 11.34 - class ChunkData 11.35 + class RegionData 11.36 { 11.37 public: 11.38 - // Destination address of the chunk. 11.39 + // Destination address of the region. 11.40 HeapWord* destination() const { return _destination; } 11.41 11.42 - // The first chunk containing data destined for this chunk. 11.43 - size_t source_chunk() const { return _source_chunk; } 11.44 + // The first region containing data destined for this region. 11.45 + size_t source_region() const { return _source_region; } 11.46 11.47 - // The object (if any) starting in this chunk and ending in a different 11.48 - // chunk that could not be updated during the main (parallel) compaction 11.49 + // The object (if any) starting in this region and ending in a different 11.50 + // region that could not be updated during the main (parallel) compaction 11.51 // phase. This is different from _partial_obj_addr, which is an object that 11.52 - // extends onto a source chunk. However, the two uses do not overlap in 11.53 + // extends onto a source region. However, the two uses do not overlap in 11.54 // time, so the same field is used to save space. 11.55 HeapWord* deferred_obj_addr() const { return _partial_obj_addr; } 11.56 11.57 - // The starting address of the partial object extending onto the chunk. 11.58 + // The starting address of the partial object extending onto the region. 11.59 HeapWord* partial_obj_addr() const { return _partial_obj_addr; } 11.60 11.61 - // Size of the partial object extending onto the chunk (words). 11.62 + // Size of the partial object extending onto the region (words). 11.63 size_t partial_obj_size() const { return _partial_obj_size; } 11.64 11.65 - // Size of live data that lies within this chunk due to objects that start 11.66 - // in this chunk (words). This does not include the partial object 11.67 - // extending onto the chunk (if any), or the part of an object that extends 11.68 - // onto the next chunk (if any). 11.69 + // Size of live data that lies within this region due to objects that start 11.70 + // in this region (words). This does not include the partial object 11.71 + // extending onto the region (if any), or the part of an object that extends 11.72 + // onto the next region (if any). 11.73 size_t live_obj_size() const { return _dc_and_los & los_mask; } 11.74 11.75 - // Total live data that lies within the chunk (words). 11.76 + // Total live data that lies within the region (words). 11.77 size_t data_size() const { return partial_obj_size() + live_obj_size(); } 11.78 11.79 - // The destination_count is the number of other chunks to which data from 11.80 - // this chunk will be copied. At the end of the summary phase, the valid 11.81 + // The destination_count is the number of other regions to which data from 11.82 + // this region will be copied. At the end of the summary phase, the valid 11.83 // values of destination_count are 11.84 // 11.85 - // 0 - data from the chunk will be compacted completely into itself, or the 11.86 - // chunk is empty. The chunk can be claimed and then filled. 11.87 - // 1 - data from the chunk will be compacted into 1 other chunk; some 11.88 - // data from the chunk may also be compacted into the chunk itself. 11.89 - // 2 - data from the chunk will be copied to 2 other chunks. 11.90 + // 0 - data from the region will be compacted completely into itself, or the 11.91 + // region is empty. The region can be claimed and then filled. 11.92 + // 1 - data from the region will be compacted into 1 other region; some 11.93 + // data from the region may also be compacted into the region itself. 11.94 + // 2 - data from the region will be copied to 2 other regions. 11.95 // 11.96 - // During compaction as chunks are emptied, the destination_count is 11.97 + // During compaction as regions are emptied, the destination_count is 11.98 // decremented (atomically) and when it reaches 0, it can be claimed and 11.99 // then filled. 11.100 // 11.101 - // A chunk is claimed for processing by atomically changing the 11.102 - // destination_count to the claimed value (dc_claimed). After a chunk has 11.103 + // A region is claimed for processing by atomically changing the 11.104 + // destination_count to the claimed value (dc_claimed). After a region has 11.105 // been filled, the destination_count should be set to the completed value 11.106 // (dc_completed). 11.107 inline uint destination_count() const; 11.108 inline uint destination_count_raw() const; 11.109 11.110 - // The location of the java heap data that corresponds to this chunk. 11.111 + // The location of the java heap data that corresponds to this region. 11.112 inline HeapWord* data_location() const; 11.113 11.114 - // The highest address referenced by objects in this chunk. 11.115 + // The highest address referenced by objects in this region. 11.116 inline HeapWord* highest_ref() const; 11.117 11.118 - // Whether this chunk is available to be claimed, has been claimed, or has 11.119 + // Whether this region is available to be claimed, has been claimed, or has 11.120 // been completed. 11.121 // 11.122 - // Minor subtlety: claimed() returns true if the chunk is marked 11.123 - // completed(), which is desirable since a chunk must be claimed before it 11.124 + // Minor subtlety: claimed() returns true if the region is marked 11.125 + // completed(), which is desirable since a region must be claimed before it 11.126 // can be completed. 11.127 bool available() const { return _dc_and_los < dc_one; } 11.128 bool claimed() const { return _dc_and_los >= dc_claimed; } 11.129 @@ -164,11 +157,11 @@ 11.130 11.131 // These are not atomic. 11.132 void set_destination(HeapWord* addr) { _destination = addr; } 11.133 - void set_source_chunk(size_t chunk) { _source_chunk = chunk; } 11.134 + void set_source_region(size_t region) { _source_region = region; } 11.135 void set_deferred_obj_addr(HeapWord* addr) { _partial_obj_addr = addr; } 11.136 void set_partial_obj_addr(HeapWord* addr) { _partial_obj_addr = addr; } 11.137 void set_partial_obj_size(size_t words) { 11.138 - _partial_obj_size = (chunk_sz_t) words; 11.139 + _partial_obj_size = (region_sz_t) words; 11.140 } 11.141 11.142 inline void set_destination_count(uint count); 11.143 @@ -184,129 +177,57 @@ 11.144 inline bool claim(); 11.145 11.146 private: 11.147 - // The type used to represent object sizes within a chunk. 11.148 - typedef uint chunk_sz_t; 11.149 + // The type used to represent object sizes within a region. 11.150 + typedef uint region_sz_t; 11.151 11.152 // Constants for manipulating the _dc_and_los field, which holds both the 11.153 // destination count and live obj size. The live obj size lives at the 11.154 // least significant end so no masking is necessary when adding. 11.155 - static const chunk_sz_t dc_shift; // Shift amount. 11.156 - static const chunk_sz_t dc_mask; // Mask for destination count. 11.157 - static const chunk_sz_t dc_one; // 1, shifted appropriately. 11.158 - static const chunk_sz_t dc_claimed; // Chunk has been claimed. 11.159 - static const chunk_sz_t dc_completed; // Chunk has been completed. 11.160 - static const chunk_sz_t los_mask; // Mask for live obj size. 11.161 + static const region_sz_t dc_shift; // Shift amount. 11.162 + static const region_sz_t dc_mask; // Mask for destination count. 11.163 + static const region_sz_t dc_one; // 1, shifted appropriately. 11.164 + static const region_sz_t dc_claimed; // Region has been claimed. 11.165 + static const region_sz_t dc_completed; // Region has been completed. 11.166 + static const region_sz_t los_mask; // Mask for live obj size. 11.167 11.168 - HeapWord* _destination; 11.169 - size_t _source_chunk; 11.170 - HeapWord* _partial_obj_addr; 11.171 - chunk_sz_t _partial_obj_size; 11.172 - chunk_sz_t volatile _dc_and_los; 11.173 + HeapWord* _destination; 11.174 + size_t _source_region; 11.175 + HeapWord* _partial_obj_addr; 11.176 + region_sz_t _partial_obj_size; 11.177 + region_sz_t volatile _dc_and_los; 11.178 #ifdef ASSERT 11.179 // These enable optimizations that are only partially implemented. Use 11.180 // debug builds to prevent the code fragments from breaking. 11.181 - HeapWord* _data_location; 11.182 - HeapWord* _highest_ref; 11.183 + HeapWord* _data_location; 11.184 + HeapWord* _highest_ref; 11.185 #endif // #ifdef ASSERT 11.186 11.187 #ifdef ASSERT 11.188 public: 11.189 - uint _pushed; // 0 until chunk is pushed onto a worker's stack 11.190 + uint _pushed; // 0 until region is pushed onto a worker's stack 11.191 private: 11.192 #endif 11.193 }; 11.194 11.195 - // 'Blocks' allow shorter sections of the bitmap to be searched. Each Block 11.196 - // holds an offset, which is the amount of live data in the Chunk to the left 11.197 - // of the first live object in the Block. This amount of live data will 11.198 - // include any object extending into the block. The first block in 11.199 - // a chunk does not include any partial object extending into the 11.200 - // the chunk. 11.201 - // 11.202 - // The offset also encodes the 11.203 - // 'parity' of the first 1 bit in the Block: a positive offset means the 11.204 - // first 1 bit marks the start of an object, a negative offset means the first 11.205 - // 1 bit marks the end of an object. 11.206 - class BlockData 11.207 - { 11.208 - public: 11.209 - typedef short int blk_ofs_t; 11.210 - 11.211 - blk_ofs_t offset() const { return _offset >= 0 ? _offset : -_offset; } 11.212 - blk_ofs_t raw_offset() const { return _offset; } 11.213 - void set_first_is_start_bit(bool v) { _first_is_start_bit = v; } 11.214 - 11.215 -#if 0 11.216 - // The need for this method was anticipated but it is 11.217 - // never actually used. Do not include it for now. If 11.218 - // it is needed, consider the problem of what is passed 11.219 - // as "v". To avoid warning errors the method set_start_bit_offset() 11.220 - // was changed to take a size_t as the parameter and to do the 11.221 - // check for the possible overflow. Doing the cast in these 11.222 - // methods better limits the potential problems because of 11.223 - // the size of the field to this class. 11.224 - void set_raw_offset(blk_ofs_t v) { _offset = v; } 11.225 -#endif 11.226 - void set_start_bit_offset(size_t val) { 11.227 - assert(val >= 0, "sanity"); 11.228 - _offset = (blk_ofs_t) val; 11.229 - assert(val == (size_t) _offset, "Value is too large"); 11.230 - _first_is_start_bit = true; 11.231 - } 11.232 - void set_end_bit_offset(size_t val) { 11.233 - assert(val >= 0, "sanity"); 11.234 - _offset = (blk_ofs_t) val; 11.235 - assert(val == (size_t) _offset, "Value is too large"); 11.236 - _offset = - _offset; 11.237 - _first_is_start_bit = false; 11.238 - } 11.239 - bool first_is_start_bit() { 11.240 - assert(_set_phase > 0, "Not initialized"); 11.241 - return _first_is_start_bit; 11.242 - } 11.243 - bool first_is_end_bit() { 11.244 - assert(_set_phase > 0, "Not initialized"); 11.245 - return !_first_is_start_bit; 11.246 - } 11.247 - 11.248 - private: 11.249 - blk_ofs_t _offset; 11.250 - // This is temporary until the mark_bitmap is separated into 11.251 - // a start bit array and an end bit array. 11.252 - bool _first_is_start_bit; 11.253 -#ifdef ASSERT 11.254 - short _set_phase; 11.255 - static short _cur_phase; 11.256 - public: 11.257 - static void set_cur_phase(short v) { _cur_phase = v; } 11.258 -#endif 11.259 - }; 11.260 - 11.261 public: 11.262 ParallelCompactData(); 11.263 bool initialize(MemRegion covered_region); 11.264 11.265 - size_t chunk_count() const { return _chunk_count; } 11.266 + size_t region_count() const { return _region_count; } 11.267 11.268 - // Convert chunk indices to/from ChunkData pointers. 11.269 - inline ChunkData* chunk(size_t chunk_idx) const; 11.270 - inline size_t chunk(const ChunkData* const chunk_ptr) const; 11.271 + // Convert region indices to/from RegionData pointers. 11.272 + inline RegionData* region(size_t region_idx) const; 11.273 + inline size_t region(const RegionData* const region_ptr) const; 11.274 11.275 - // Returns true if the given address is contained within the chunk 11.276 - bool chunk_contains(size_t chunk_index, HeapWord* addr); 11.277 - 11.278 - size_t block_count() const { return _block_count; } 11.279 - inline BlockData* block(size_t n) const; 11.280 - 11.281 - // Returns true if the given block is in the given chunk. 11.282 - static bool chunk_contains_block(size_t chunk_index, size_t block_index); 11.283 + // Returns true if the given address is contained within the region 11.284 + bool region_contains(size_t region_index, HeapWord* addr); 11.285 11.286 void add_obj(HeapWord* addr, size_t len); 11.287 void add_obj(oop p, size_t len) { add_obj((HeapWord*)p, len); } 11.288 11.289 - // Fill in the chunks covering [beg, end) so that no data moves; i.e., the 11.290 - // destination of chunk n is simply the start of chunk n. The argument beg 11.291 - // must be chunk-aligned; end need not be. 11.292 + // Fill in the regions covering [beg, end) so that no data moves; i.e., the 11.293 + // destination of region n is simply the start of region n. The argument beg 11.294 + // must be region-aligned; end need not be. 11.295 void summarize_dense_prefix(HeapWord* beg, HeapWord* end); 11.296 11.297 bool summarize(HeapWord* target_beg, HeapWord* target_end, 11.298 @@ -314,48 +235,33 @@ 11.299 HeapWord** target_next, HeapWord** source_next = 0); 11.300 11.301 void clear(); 11.302 - void clear_range(size_t beg_chunk, size_t end_chunk); 11.303 + void clear_range(size_t beg_region, size_t end_region); 11.304 void clear_range(HeapWord* beg, HeapWord* end) { 11.305 - clear_range(addr_to_chunk_idx(beg), addr_to_chunk_idx(end)); 11.306 + clear_range(addr_to_region_idx(beg), addr_to_region_idx(end)); 11.307 } 11.308 11.309 - // Return the number of words between addr and the start of the chunk 11.310 + // Return the number of words between addr and the start of the region 11.311 // containing addr. 11.312 - inline size_t chunk_offset(const HeapWord* addr) const; 11.313 + inline size_t region_offset(const HeapWord* addr) const; 11.314 11.315 - // Convert addresses to/from a chunk index or chunk pointer. 11.316 - inline size_t addr_to_chunk_idx(const HeapWord* addr) const; 11.317 - inline ChunkData* addr_to_chunk_ptr(const HeapWord* addr) const; 11.318 - inline HeapWord* chunk_to_addr(size_t chunk) const; 11.319 - inline HeapWord* chunk_to_addr(size_t chunk, size_t offset) const; 11.320 - inline HeapWord* chunk_to_addr(const ChunkData* chunk) const; 11.321 + // Convert addresses to/from a region index or region pointer. 11.322 + inline size_t addr_to_region_idx(const HeapWord* addr) const; 11.323 + inline RegionData* addr_to_region_ptr(const HeapWord* addr) const; 11.324 + inline HeapWord* region_to_addr(size_t region) const; 11.325 + inline HeapWord* region_to_addr(size_t region, size_t offset) const; 11.326 + inline HeapWord* region_to_addr(const RegionData* region) const; 11.327 11.328 - inline HeapWord* chunk_align_down(HeapWord* addr) const; 11.329 - inline HeapWord* chunk_align_up(HeapWord* addr) const; 11.330 - inline bool is_chunk_aligned(HeapWord* addr) const; 11.331 - 11.332 - // Analogous to chunk_offset() for blocks. 11.333 - size_t block_offset(const HeapWord* addr) const; 11.334 - size_t addr_to_block_idx(const HeapWord* addr) const; 11.335 - size_t addr_to_block_idx(const oop obj) const { 11.336 - return addr_to_block_idx((HeapWord*) obj); 11.337 - } 11.338 - inline BlockData* addr_to_block_ptr(const HeapWord* addr) const; 11.339 - inline HeapWord* block_to_addr(size_t block) const; 11.340 + inline HeapWord* region_align_down(HeapWord* addr) const; 11.341 + inline HeapWord* region_align_up(HeapWord* addr) const; 11.342 + inline bool is_region_aligned(HeapWord* addr) const; 11.343 11.344 // Return the address one past the end of the partial object. 11.345 - HeapWord* partial_obj_end(size_t chunk_idx) const; 11.346 + HeapWord* partial_obj_end(size_t region_idx) const; 11.347 11.348 // Return the new location of the object p after the 11.349 // the compaction. 11.350 HeapWord* calc_new_pointer(HeapWord* addr); 11.351 11.352 - // Same as calc_new_pointer() using blocks. 11.353 - HeapWord* block_calc_new_pointer(HeapWord* addr); 11.354 - 11.355 - // Same as calc_new_pointer() using chunks. 11.356 - HeapWord* chunk_calc_new_pointer(HeapWord* addr); 11.357 - 11.358 HeapWord* calc_new_pointer(oop p) { 11.359 return calc_new_pointer((HeapWord*) p); 11.360 } 11.361 @@ -363,22 +269,13 @@ 11.362 // Return the updated address for the given klass 11.363 klassOop calc_new_klass(klassOop); 11.364 11.365 - // Given a block returns true if the partial object for the 11.366 - // corresponding chunk ends in the block. Returns false, otherwise 11.367 - // If there is no partial object, returns false. 11.368 - bool partial_obj_ends_in_block(size_t block_index); 11.369 - 11.370 - // Returns the block index for the block 11.371 - static size_t block_idx(BlockData* block); 11.372 - 11.373 #ifdef ASSERT 11.374 void verify_clear(const PSVirtualSpace* vspace); 11.375 void verify_clear(); 11.376 #endif // #ifdef ASSERT 11.377 11.378 private: 11.379 - bool initialize_block_data(size_t region_size); 11.380 - bool initialize_chunk_data(size_t region_size); 11.381 + bool initialize_region_data(size_t region_size); 11.382 PSVirtualSpace* create_vspace(size_t count, size_t element_size); 11.383 11.384 private: 11.385 @@ -387,74 +284,70 @@ 11.386 HeapWord* _region_end; 11.387 #endif // #ifdef ASSERT 11.388 11.389 - PSVirtualSpace* _chunk_vspace; 11.390 - ChunkData* _chunk_data; 11.391 - size_t _chunk_count; 11.392 - 11.393 - PSVirtualSpace* _block_vspace; 11.394 - BlockData* _block_data; 11.395 - size_t _block_count; 11.396 + PSVirtualSpace* _region_vspace; 11.397 + RegionData* _region_data; 11.398 + size_t _region_count; 11.399 }; 11.400 11.401 inline uint 11.402 -ParallelCompactData::ChunkData::destination_count_raw() const 11.403 +ParallelCompactData::RegionData::destination_count_raw() const 11.404 { 11.405 return _dc_and_los & dc_mask; 11.406 } 11.407 11.408 inline uint 11.409 -ParallelCompactData::ChunkData::destination_count() const 11.410 +ParallelCompactData::RegionData::destination_count() const 11.411 { 11.412 return destination_count_raw() >> dc_shift; 11.413 } 11.414 11.415 inline void 11.416 -ParallelCompactData::ChunkData::set_destination_count(uint count) 11.417 +ParallelCompactData::RegionData::set_destination_count(uint count) 11.418 { 11.419 assert(count <= (dc_completed >> dc_shift), "count too large"); 11.420 - const chunk_sz_t live_sz = (chunk_sz_t) live_obj_size(); 11.421 + const region_sz_t live_sz = (region_sz_t) live_obj_size(); 11.422 _dc_and_los = (count << dc_shift) | live_sz; 11.423 } 11.424 11.425 -inline void ParallelCompactData::ChunkData::set_live_obj_size(size_t words) 11.426 +inline void ParallelCompactData::RegionData::set_live_obj_size(size_t words) 11.427 { 11.428 assert(words <= los_mask, "would overflow"); 11.429 - _dc_and_los = destination_count_raw() | (chunk_sz_t)words; 11.430 + _dc_and_los = destination_count_raw() | (region_sz_t)words; 11.431 } 11.432 11.433 -inline void ParallelCompactData::ChunkData::decrement_destination_count() 11.434 +inline void ParallelCompactData::RegionData::decrement_destination_count() 11.435 { 11.436 assert(_dc_and_los < dc_claimed, "already claimed"); 11.437 assert(_dc_and_los >= dc_one, "count would go negative"); 11.438 Atomic::add((int)dc_mask, (volatile int*)&_dc_and_los); 11.439 } 11.440 11.441 -inline HeapWord* ParallelCompactData::ChunkData::data_location() const 11.442 +inline HeapWord* ParallelCompactData::RegionData::data_location() const 11.443 { 11.444 DEBUG_ONLY(return _data_location;) 11.445 NOT_DEBUG(return NULL;) 11.446 } 11.447 11.448 -inline HeapWord* ParallelCompactData::ChunkData::highest_ref() const 11.449 +inline HeapWord* ParallelCompactData::RegionData::highest_ref() const 11.450 { 11.451 DEBUG_ONLY(return _highest_ref;) 11.452 NOT_DEBUG(return NULL;) 11.453 } 11.454 11.455 -inline void ParallelCompactData::ChunkData::set_data_location(HeapWord* addr) 11.456 +inline void ParallelCompactData::RegionData::set_data_location(HeapWord* addr) 11.457 { 11.458 DEBUG_ONLY(_data_location = addr;) 11.459 } 11.460 11.461 -inline void ParallelCompactData::ChunkData::set_completed() 11.462 +inline void ParallelCompactData::RegionData::set_completed() 11.463 { 11.464 assert(claimed(), "must be claimed first"); 11.465 - _dc_and_los = dc_completed | (chunk_sz_t) live_obj_size(); 11.466 + _dc_and_los = dc_completed | (region_sz_t) live_obj_size(); 11.467 } 11.468 11.469 -// MT-unsafe claiming of a chunk. Should only be used during single threaded 11.470 +// MT-unsafe claiming of a region. Should only be used during single threaded 11.471 // execution. 11.472 -inline bool ParallelCompactData::ChunkData::claim_unsafe() 11.473 +inline bool ParallelCompactData::RegionData::claim_unsafe() 11.474 { 11.475 if (available()) { 11.476 _dc_and_los |= dc_claimed; 11.477 @@ -463,13 +356,13 @@ 11.478 return false; 11.479 } 11.480 11.481 -inline void ParallelCompactData::ChunkData::add_live_obj(size_t words) 11.482 +inline void ParallelCompactData::RegionData::add_live_obj(size_t words) 11.483 { 11.484 assert(words <= (size_t)los_mask - live_obj_size(), "overflow"); 11.485 Atomic::add((int) words, (volatile int*) &_dc_and_los); 11.486 } 11.487 11.488 -inline void ParallelCompactData::ChunkData::set_highest_ref(HeapWord* addr) 11.489 +inline void ParallelCompactData::RegionData::set_highest_ref(HeapWord* addr) 11.490 { 11.491 #ifdef ASSERT 11.492 HeapWord* tmp = _highest_ref; 11.493 @@ -479,7 +372,7 @@ 11.494 #endif // #ifdef ASSERT 11.495 } 11.496 11.497 -inline bool ParallelCompactData::ChunkData::claim() 11.498 +inline bool ParallelCompactData::RegionData::claim() 11.499 { 11.500 const int los = (int) live_obj_size(); 11.501 const int old = Atomic::cmpxchg(dc_claimed | los, 11.502 @@ -487,119 +380,85 @@ 11.503 return old == los; 11.504 } 11.505 11.506 -inline ParallelCompactData::ChunkData* 11.507 -ParallelCompactData::chunk(size_t chunk_idx) const 11.508 +inline ParallelCompactData::RegionData* 11.509 +ParallelCompactData::region(size_t region_idx) const 11.510 { 11.511 - assert(chunk_idx <= chunk_count(), "bad arg"); 11.512 - return _chunk_data + chunk_idx; 11.513 + assert(region_idx <= region_count(), "bad arg"); 11.514 + return _region_data + region_idx; 11.515 } 11.516 11.517 inline size_t 11.518 -ParallelCompactData::chunk(const ChunkData* const chunk_ptr) const 11.519 +ParallelCompactData::region(const RegionData* const region_ptr) const 11.520 { 11.521 - assert(chunk_ptr >= _chunk_data, "bad arg"); 11.522 - assert(chunk_ptr <= _chunk_data + chunk_count(), "bad arg"); 11.523 - return pointer_delta(chunk_ptr, _chunk_data, sizeof(ChunkData)); 11.524 -} 11.525 - 11.526 -inline ParallelCompactData::BlockData* 11.527 -ParallelCompactData::block(size_t n) const { 11.528 - assert(n < block_count(), "bad arg"); 11.529 - return _block_data + n; 11.530 + assert(region_ptr >= _region_data, "bad arg"); 11.531 + assert(region_ptr <= _region_data + region_count(), "bad arg"); 11.532 + return pointer_delta(region_ptr, _region_data, sizeof(RegionData)); 11.533 } 11.534 11.535 inline size_t 11.536 -ParallelCompactData::chunk_offset(const HeapWord* addr) const 11.537 +ParallelCompactData::region_offset(const HeapWord* addr) const 11.538 { 11.539 assert(addr >= _region_start, "bad addr"); 11.540 assert(addr <= _region_end, "bad addr"); 11.541 - return (size_t(addr) & ChunkAddrOffsetMask) >> LogHeapWordSize; 11.542 + return (size_t(addr) & RegionAddrOffsetMask) >> LogHeapWordSize; 11.543 } 11.544 11.545 inline size_t 11.546 -ParallelCompactData::addr_to_chunk_idx(const HeapWord* addr) const 11.547 +ParallelCompactData::addr_to_region_idx(const HeapWord* addr) const 11.548 { 11.549 assert(addr >= _region_start, "bad addr"); 11.550 assert(addr <= _region_end, "bad addr"); 11.551 - return pointer_delta(addr, _region_start) >> Log2ChunkSize; 11.552 + return pointer_delta(addr, _region_start) >> Log2RegionSize; 11.553 } 11.554 11.555 -inline ParallelCompactData::ChunkData* 11.556 -ParallelCompactData::addr_to_chunk_ptr(const HeapWord* addr) const 11.557 +inline ParallelCompactData::RegionData* 11.558 +ParallelCompactData::addr_to_region_ptr(const HeapWord* addr) const 11.559 { 11.560 - return chunk(addr_to_chunk_idx(addr)); 11.561 + return region(addr_to_region_idx(addr)); 11.562 } 11.563 11.564 inline HeapWord* 11.565 -ParallelCompactData::chunk_to_addr(size_t chunk) const 11.566 +ParallelCompactData::region_to_addr(size_t region) const 11.567 { 11.568 - assert(chunk <= _chunk_count, "chunk out of range"); 11.569 - return _region_start + (chunk << Log2ChunkSize); 11.570 + assert(region <= _region_count, "region out of range"); 11.571 + return _region_start + (region << Log2RegionSize); 11.572 } 11.573 11.574 inline HeapWord* 11.575 -ParallelCompactData::chunk_to_addr(const ChunkData* chunk) const 11.576 +ParallelCompactData::region_to_addr(const RegionData* region) const 11.577 { 11.578 - return chunk_to_addr(pointer_delta(chunk, _chunk_data, sizeof(ChunkData))); 11.579 + return region_to_addr(pointer_delta(region, _region_data, 11.580 + sizeof(RegionData))); 11.581 } 11.582 11.583 inline HeapWord* 11.584 -ParallelCompactData::chunk_to_addr(size_t chunk, size_t offset) const 11.585 +ParallelCompactData::region_to_addr(size_t region, size_t offset) const 11.586 { 11.587 - assert(chunk <= _chunk_count, "chunk out of range"); 11.588 - assert(offset < ChunkSize, "offset too big"); // This may be too strict. 11.589 - return chunk_to_addr(chunk) + offset; 11.590 + assert(region <= _region_count, "region out of range"); 11.591 + assert(offset < RegionSize, "offset too big"); // This may be too strict. 11.592 + return region_to_addr(region) + offset; 11.593 } 11.594 11.595 inline HeapWord* 11.596 -ParallelCompactData::chunk_align_down(HeapWord* addr) const 11.597 +ParallelCompactData::region_align_down(HeapWord* addr) const 11.598 { 11.599 assert(addr >= _region_start, "bad addr"); 11.600 - assert(addr < _region_end + ChunkSize, "bad addr"); 11.601 - return (HeapWord*)(size_t(addr) & ChunkAddrMask); 11.602 + assert(addr < _region_end + RegionSize, "bad addr"); 11.603 + return (HeapWord*)(size_t(addr) & RegionAddrMask); 11.604 } 11.605 11.606 inline HeapWord* 11.607 -ParallelCompactData::chunk_align_up(HeapWord* addr) const 11.608 +ParallelCompactData::region_align_up(HeapWord* addr) const 11.609 { 11.610 assert(addr >= _region_start, "bad addr"); 11.611 assert(addr <= _region_end, "bad addr"); 11.612 - return chunk_align_down(addr + ChunkSizeOffsetMask); 11.613 + return region_align_down(addr + RegionSizeOffsetMask); 11.614 } 11.615 11.616 inline bool 11.617 -ParallelCompactData::is_chunk_aligned(HeapWord* addr) const 11.618 +ParallelCompactData::is_region_aligned(HeapWord* addr) const 11.619 { 11.620 - return chunk_offset(addr) == 0; 11.621 -} 11.622 - 11.623 -inline size_t 11.624 -ParallelCompactData::block_offset(const HeapWord* addr) const 11.625 -{ 11.626 - assert(addr >= _region_start, "bad addr"); 11.627 - assert(addr <= _region_end, "bad addr"); 11.628 - return pointer_delta(addr, _region_start) & BlockOffsetMask; 11.629 -} 11.630 - 11.631 -inline size_t 11.632 -ParallelCompactData::addr_to_block_idx(const HeapWord* addr) const 11.633 -{ 11.634 - assert(addr >= _region_start, "bad addr"); 11.635 - assert(addr <= _region_end, "bad addr"); 11.636 - return pointer_delta(addr, _region_start) >> Log2BlockSize; 11.637 -} 11.638 - 11.639 -inline ParallelCompactData::BlockData* 11.640 -ParallelCompactData::addr_to_block_ptr(const HeapWord* addr) const 11.641 -{ 11.642 - return block(addr_to_block_idx(addr)); 11.643 -} 11.644 - 11.645 -inline HeapWord* 11.646 -ParallelCompactData::block_to_addr(size_t block) const 11.647 -{ 11.648 - assert(block < _block_count, "block out of range"); 11.649 - return _region_start + (block << Log2BlockSize); 11.650 + return region_offset(addr) == 0; 11.651 } 11.652 11.653 // Abstract closure for use with ParMarkBitMap::iterate(), which will invoke the 11.654 @@ -687,45 +546,15 @@ 11.655 _words_remaining -= words; 11.656 } 11.657 11.658 -// Closure for updating the block data during the summary phase. 11.659 -class BitBlockUpdateClosure: public ParMarkBitMapClosure { 11.660 - // ParallelCompactData::BlockData::blk_ofs_t _live_data_left; 11.661 - size_t _live_data_left; 11.662 - size_t _cur_block; 11.663 - HeapWord* _chunk_start; 11.664 - HeapWord* _chunk_end; 11.665 - size_t _chunk_index; 11.666 - 11.667 - public: 11.668 - BitBlockUpdateClosure(ParMarkBitMap* mbm, 11.669 - ParCompactionManager* cm, 11.670 - size_t chunk_index); 11.671 - 11.672 - size_t cur_block() { return _cur_block; } 11.673 - size_t chunk_index() { return _chunk_index; } 11.674 - size_t live_data_left() { return _live_data_left; } 11.675 - // Returns true the first bit in the current block (cur_block) is 11.676 - // a start bit. 11.677 - // Returns true if the current block is within the chunk for the closure; 11.678 - bool chunk_contains_cur_block(); 11.679 - 11.680 - // Set the chunk index and related chunk values for 11.681 - // a new chunk. 11.682 - void reset_chunk(size_t chunk_index); 11.683 - 11.684 - virtual IterationStatus do_addr(HeapWord* addr, size_t words); 11.685 -}; 11.686 - 11.687 -// The UseParallelOldGC collector is a stop-the-world garbage 11.688 -// collector that does parts of the collection using parallel threads. 11.689 -// The collection includes the tenured generation and the young 11.690 -// generation. The permanent generation is collected at the same 11.691 -// time as the other two generations but the permanent generation 11.692 -// is collect by a single GC thread. The permanent generation is 11.693 -// collected serially because of the requirement that during the 11.694 -// processing of a klass AAA, any objects reference by AAA must 11.695 -// already have been processed. This requirement is enforced by 11.696 -// a left (lower address) to right (higher address) sliding compaction. 11.697 +// The UseParallelOldGC collector is a stop-the-world garbage collector that 11.698 +// does parts of the collection using parallel threads. The collection includes 11.699 +// the tenured generation and the young generation. The permanent generation is 11.700 +// collected at the same time as the other two generations but the permanent 11.701 +// generation is collect by a single GC thread. The permanent generation is 11.702 +// collected serially because of the requirement that during the processing of a 11.703 +// klass AAA, any objects reference by AAA must already have been processed. 11.704 +// This requirement is enforced by a left (lower address) to right (higher 11.705 +// address) sliding compaction. 11.706 // 11.707 // There are four phases of the collection. 11.708 // 11.709 @@ -740,81 +569,75 @@ 11.710 // - move the objects to their destination 11.711 // - update some references and reinitialize some variables 11.712 // 11.713 -// These three phases are invoked in PSParallelCompact::invoke_no_policy(). 11.714 -// The marking phase is implemented in PSParallelCompact::marking_phase() 11.715 -// and does a complete marking of the heap. 11.716 -// The summary phase is implemented in PSParallelCompact::summary_phase(). 11.717 -// The move and update phase is implemented in PSParallelCompact::compact(). 11.718 +// These three phases are invoked in PSParallelCompact::invoke_no_policy(). The 11.719 +// marking phase is implemented in PSParallelCompact::marking_phase() and does a 11.720 +// complete marking of the heap. The summary phase is implemented in 11.721 +// PSParallelCompact::summary_phase(). The move and update phase is implemented 11.722 +// in PSParallelCompact::compact(). 11.723 // 11.724 -// A space that is being collected is divided into chunks and with 11.725 -// each chunk is associated an object of type ParallelCompactData. 11.726 -// Each chunk is of a fixed size and typically will contain more than 11.727 -// 1 object and may have parts of objects at the front and back of the 11.728 -// chunk. 11.729 +// A space that is being collected is divided into regions and with each region 11.730 +// is associated an object of type ParallelCompactData. Each region is of a 11.731 +// fixed size and typically will contain more than 1 object and may have parts 11.732 +// of objects at the front and back of the region. 11.733 // 11.734 -// chunk -----+---------------------+---------- 11.735 +// region -----+---------------------+---------- 11.736 // objects covered [ AAA )[ BBB )[ CCC )[ DDD ) 11.737 // 11.738 -// The marking phase does a complete marking of all live objects in the 11.739 -// heap. The marking also compiles the size of the data for 11.740 -// all live objects covered by the chunk. This size includes the 11.741 -// part of any live object spanning onto the chunk (part of AAA 11.742 -// if it is live) from the front, all live objects contained in the chunk 11.743 -// (BBB and/or CCC if they are live), and the part of any live objects 11.744 -// covered by the chunk that extends off the chunk (part of DDD if it is 11.745 -// live). The marking phase uses multiple GC threads and marking is 11.746 -// done in a bit array of type ParMarkBitMap. The marking of the 11.747 -// bit map is done atomically as is the accumulation of the size of the 11.748 -// live objects covered by a chunk. 11.749 +// The marking phase does a complete marking of all live objects in the heap. 11.750 +// The marking also compiles the size of the data for all live objects covered 11.751 +// by the region. This size includes the part of any live object spanning onto 11.752 +// the region (part of AAA if it is live) from the front, all live objects 11.753 +// contained in the region (BBB and/or CCC if they are live), and the part of 11.754 +// any live objects covered by the region that extends off the region (part of 11.755 +// DDD if it is live). The marking phase uses multiple GC threads and marking 11.756 +// is done in a bit array of type ParMarkBitMap. The marking of the bit map is 11.757 +// done atomically as is the accumulation of the size of the live objects 11.758 +// covered by a region. 11.759 // 11.760 -// The summary phase calculates the total live data to the left of 11.761 -// each chunk XXX. Based on that total and the bottom of the space, 11.762 -// it can calculate the starting location of the live data in XXX. 11.763 -// The summary phase calculates for each chunk XXX quantites such as 11.764 +// The summary phase calculates the total live data to the left of each region 11.765 +// XXX. Based on that total and the bottom of the space, it can calculate the 11.766 +// starting location of the live data in XXX. The summary phase calculates for 11.767 +// each region XXX quantites such as 11.768 // 11.769 -// - the amount of live data at the beginning of a chunk from an object 11.770 -// entering the chunk. 11.771 -// - the location of the first live data on the chunk 11.772 -// - a count of the number of chunks receiving live data from XXX. 11.773 +// - the amount of live data at the beginning of a region from an object 11.774 +// entering the region. 11.775 +// - the location of the first live data on the region 11.776 +// - a count of the number of regions receiving live data from XXX. 11.777 // 11.778 // See ParallelCompactData for precise details. The summary phase also 11.779 -// calculates the dense prefix for the compaction. The dense prefix 11.780 -// is a portion at the beginning of the space that is not moved. The 11.781 -// objects in the dense prefix do need to have their object references 11.782 -// updated. See method summarize_dense_prefix(). 11.783 +// calculates the dense prefix for the compaction. The dense prefix is a 11.784 +// portion at the beginning of the space that is not moved. The objects in the 11.785 +// dense prefix do need to have their object references updated. See method 11.786 +// summarize_dense_prefix(). 11.787 // 11.788 // The summary phase is done using 1 GC thread. 11.789 // 11.790 -// The compaction phase moves objects to their new location and updates 11.791 -// all references in the object. 11.792 +// The compaction phase moves objects to their new location and updates all 11.793 +// references in the object. 11.794 // 11.795 -// A current exception is that objects that cross a chunk boundary 11.796 -// are moved but do not have their references updated. References are 11.797 -// not updated because it cannot easily be determined if the klass 11.798 -// pointer KKK for the object AAA has been updated. KKK likely resides 11.799 -// in a chunk to the left of the chunk containing AAA. These AAA's 11.800 -// have there references updated at the end in a clean up phase. 11.801 -// See the method PSParallelCompact::update_deferred_objects(). An 11.802 -// alternate strategy is being investigated for this deferral of updating. 11.803 +// A current exception is that objects that cross a region boundary are moved 11.804 +// but do not have their references updated. References are not updated because 11.805 +// it cannot easily be determined if the klass pointer KKK for the object AAA 11.806 +// has been updated. KKK likely resides in a region to the left of the region 11.807 +// containing AAA. These AAA's have there references updated at the end in a 11.808 +// clean up phase. See the method PSParallelCompact::update_deferred_objects(). 11.809 +// An alternate strategy is being investigated for this deferral of updating. 11.810 // 11.811 -// Compaction is done on a chunk basis. A chunk that is ready to be 11.812 -// filled is put on a ready list and GC threads take chunk off the list 11.813 -// and fill them. A chunk is ready to be filled if it 11.814 -// empty of live objects. Such a chunk may have been initially 11.815 -// empty (only contained 11.816 -// dead objects) or may have had all its live objects copied out already. 11.817 -// A chunk that compacts into itself is also ready for filling. The 11.818 -// ready list is initially filled with empty chunks and chunks compacting 11.819 -// into themselves. There is always at least 1 chunk that can be put on 11.820 -// the ready list. The chunks are atomically added and removed from 11.821 -// the ready list. 11.822 -// 11.823 +// Compaction is done on a region basis. A region that is ready to be filled is 11.824 +// put on a ready list and GC threads take region off the list and fill them. A 11.825 +// region is ready to be filled if it empty of live objects. Such a region may 11.826 +// have been initially empty (only contained dead objects) or may have had all 11.827 +// its live objects copied out already. A region that compacts into itself is 11.828 +// also ready for filling. The ready list is initially filled with empty 11.829 +// regions and regions compacting into themselves. There is always at least 1 11.830 +// region that can be put on the ready list. The regions are atomically added 11.831 +// and removed from the ready list. 11.832 + 11.833 class PSParallelCompact : AllStatic { 11.834 public: 11.835 // Convenient access to type names. 11.836 typedef ParMarkBitMap::idx_t idx_t; 11.837 - typedef ParallelCompactData::ChunkData ChunkData; 11.838 - typedef ParallelCompactData::BlockData BlockData; 11.839 + typedef ParallelCompactData::RegionData RegionData; 11.840 11.841 typedef enum { 11.842 perm_space_id, old_space_id, eden_space_id, 11.843 @@ -977,26 +800,26 @@ 11.844 // not reclaimed). 11.845 static double dead_wood_limiter(double density, size_t min_percent); 11.846 11.847 - // Find the first (left-most) chunk in the range [beg, end) that has at least 11.848 + // Find the first (left-most) region in the range [beg, end) that has at least 11.849 // dead_words of dead space to the left. The argument beg must be the first 11.850 - // chunk in the space that is not completely live. 11.851 - static ChunkData* dead_wood_limit_chunk(const ChunkData* beg, 11.852 - const ChunkData* end, 11.853 - size_t dead_words); 11.854 + // region in the space that is not completely live. 11.855 + static RegionData* dead_wood_limit_region(const RegionData* beg, 11.856 + const RegionData* end, 11.857 + size_t dead_words); 11.858 11.859 - // Return a pointer to the first chunk in the range [beg, end) that is not 11.860 + // Return a pointer to the first region in the range [beg, end) that is not 11.861 // completely full. 11.862 - static ChunkData* first_dead_space_chunk(const ChunkData* beg, 11.863 - const ChunkData* end); 11.864 + static RegionData* first_dead_space_region(const RegionData* beg, 11.865 + const RegionData* end); 11.866 11.867 // Return a value indicating the benefit or 'yield' if the compacted region 11.868 // were to start (or equivalently if the dense prefix were to end) at the 11.869 - // candidate chunk. Higher values are better. 11.870 + // candidate region. Higher values are better. 11.871 // 11.872 // The value is based on the amount of space reclaimed vs. the costs of (a) 11.873 // updating references in the dense prefix plus (b) copying objects and 11.874 // updating references in the compacted region. 11.875 - static inline double reclaimed_ratio(const ChunkData* const candidate, 11.876 + static inline double reclaimed_ratio(const RegionData* const candidate, 11.877 HeapWord* const bottom, 11.878 HeapWord* const top, 11.879 HeapWord* const new_top); 11.880 @@ -1005,9 +828,9 @@ 11.881 static HeapWord* compute_dense_prefix(const SpaceId id, 11.882 bool maximum_compaction); 11.883 11.884 - // Return true if dead space crosses onto the specified Chunk; bit must be the 11.885 - // bit index corresponding to the first word of the Chunk. 11.886 - static inline bool dead_space_crosses_boundary(const ChunkData* chunk, 11.887 + // Return true if dead space crosses onto the specified Region; bit must be 11.888 + // the bit index corresponding to the first word of the Region. 11.889 + static inline bool dead_space_crosses_boundary(const RegionData* region, 11.890 idx_t bit); 11.891 11.892 // Summary phase utility routine to fill dead space (if any) at the dense 11.893 @@ -1019,12 +842,6 @@ 11.894 static void summarize_space(SpaceId id, bool maximum_compaction); 11.895 static void summary_phase(ParCompactionManager* cm, bool maximum_compaction); 11.896 11.897 - static bool block_first_offset(size_t block_index, idx_t* block_offset_ptr); 11.898 - 11.899 - // Fill in the BlockData 11.900 - static void summarize_blocks(ParCompactionManager* cm, 11.901 - SpaceId first_compaction_space_id); 11.902 - 11.903 // The space that is compacted after space_id. 11.904 static SpaceId next_compaction_space_id(SpaceId space_id); 11.905 11.906 @@ -1038,16 +855,16 @@ 11.907 static void compact_perm(ParCompactionManager* cm); 11.908 static void compact(); 11.909 11.910 - // Add available chunks to the stack and draining tasks to the task queue. 11.911 - static void enqueue_chunk_draining_tasks(GCTaskQueue* q, 11.912 - uint parallel_gc_threads); 11.913 + // Add available regions to the stack and draining tasks to the task queue. 11.914 + static void enqueue_region_draining_tasks(GCTaskQueue* q, 11.915 + uint parallel_gc_threads); 11.916 11.917 // Add dense prefix update tasks to the task queue. 11.918 static void enqueue_dense_prefix_tasks(GCTaskQueue* q, 11.919 uint parallel_gc_threads); 11.920 11.921 - // Add chunk stealing tasks to the task queue. 11.922 - static void enqueue_chunk_stealing_tasks( 11.923 + // Add region stealing tasks to the task queue. 11.924 + static void enqueue_region_stealing_tasks( 11.925 GCTaskQueue* q, 11.926 ParallelTaskTerminator* terminator_ptr, 11.927 uint parallel_gc_threads); 11.928 @@ -1154,56 +971,56 @@ 11.929 // Move and update the live objects in the specified space. 11.930 static void move_and_update(ParCompactionManager* cm, SpaceId space_id); 11.931 11.932 - // Process the end of the given chunk range in the dense prefix. 11.933 + // Process the end of the given region range in the dense prefix. 11.934 // This includes saving any object not updated. 11.935 - static void dense_prefix_chunks_epilogue(ParCompactionManager* cm, 11.936 - size_t chunk_start_index, 11.937 - size_t chunk_end_index, 11.938 - idx_t exiting_object_offset, 11.939 - idx_t chunk_offset_start, 11.940 - idx_t chunk_offset_end); 11.941 + static void dense_prefix_regions_epilogue(ParCompactionManager* cm, 11.942 + size_t region_start_index, 11.943 + size_t region_end_index, 11.944 + idx_t exiting_object_offset, 11.945 + idx_t region_offset_start, 11.946 + idx_t region_offset_end); 11.947 11.948 - // Update a chunk in the dense prefix. For each live object 11.949 - // in the chunk, update it's interior references. For each 11.950 + // Update a region in the dense prefix. For each live object 11.951 + // in the region, update it's interior references. For each 11.952 // dead object, fill it with deadwood. Dead space at the end 11.953 - // of a chunk range will be filled to the start of the next 11.954 - // live object regardless of the chunk_index_end. None of the 11.955 + // of a region range will be filled to the start of the next 11.956 + // live object regardless of the region_index_end. None of the 11.957 // objects in the dense prefix move and dead space is dead 11.958 // (holds only dead objects that don't need any processing), so 11.959 // dead space can be filled in any order. 11.960 static void update_and_deadwood_in_dense_prefix(ParCompactionManager* cm, 11.961 SpaceId space_id, 11.962 - size_t chunk_index_start, 11.963 - size_t chunk_index_end); 11.964 + size_t region_index_start, 11.965 + size_t region_index_end); 11.966 11.967 // Return the address of the count + 1st live word in the range [beg, end). 11.968 static HeapWord* skip_live_words(HeapWord* beg, HeapWord* end, size_t count); 11.969 11.970 // Return the address of the word to be copied to dest_addr, which must be 11.971 - // aligned to a chunk boundary. 11.972 + // aligned to a region boundary. 11.973 static HeapWord* first_src_addr(HeapWord* const dest_addr, 11.974 - size_t src_chunk_idx); 11.975 + size_t src_region_idx); 11.976 11.977 - // Determine the next source chunk, set closure.source() to the start of the 11.978 - // new chunk return the chunk index. Parameter end_addr is the address one 11.979 + // Determine the next source region, set closure.source() to the start of the 11.980 + // new region return the region index. Parameter end_addr is the address one 11.981 // beyond the end of source range just processed. If necessary, switch to a 11.982 // new source space and set src_space_id (in-out parameter) and src_space_top 11.983 // (out parameter) accordingly. 11.984 - static size_t next_src_chunk(MoveAndUpdateClosure& closure, 11.985 - SpaceId& src_space_id, 11.986 - HeapWord*& src_space_top, 11.987 - HeapWord* end_addr); 11.988 + static size_t next_src_region(MoveAndUpdateClosure& closure, 11.989 + SpaceId& src_space_id, 11.990 + HeapWord*& src_space_top, 11.991 + HeapWord* end_addr); 11.992 11.993 - // Decrement the destination count for each non-empty source chunk in the 11.994 - // range [beg_chunk, chunk(chunk_align_up(end_addr))). 11.995 + // Decrement the destination count for each non-empty source region in the 11.996 + // range [beg_region, region(region_align_up(end_addr))). 11.997 static void decrement_destination_counts(ParCompactionManager* cm, 11.998 - size_t beg_chunk, 11.999 + size_t beg_region, 11.1000 HeapWord* end_addr); 11.1001 11.1002 - // Fill a chunk, copying objects from one or more source chunks. 11.1003 - static void fill_chunk(ParCompactionManager* cm, size_t chunk_idx); 11.1004 - static void fill_and_update_chunk(ParCompactionManager* cm, size_t chunk) { 11.1005 - fill_chunk(cm, chunk); 11.1006 + // Fill a region, copying objects from one or more source regions. 11.1007 + static void fill_region(ParCompactionManager* cm, size_t region_idx); 11.1008 + static void fill_and_update_region(ParCompactionManager* cm, size_t region) { 11.1009 + fill_region(cm, region); 11.1010 } 11.1011 11.1012 // Update the deferred objects in the space. 11.1013 @@ -1259,7 +1076,7 @@ 11.1014 #ifndef PRODUCT 11.1015 // Debugging support. 11.1016 static const char* space_names[last_space_id]; 11.1017 - static void print_chunk_ranges(); 11.1018 + static void print_region_ranges(); 11.1019 static void print_dense_prefix_stats(const char* const algorithm, 11.1020 const SpaceId id, 11.1021 const bool maximum_compaction, 11.1022 @@ -1267,7 +1084,7 @@ 11.1023 #endif // #ifndef PRODUCT 11.1024 11.1025 #ifdef ASSERT 11.1026 - // Verify that all the chunks have been emptied. 11.1027 + // Verify that all the regions have been emptied. 11.1028 static void verify_complete(SpaceId space_id); 11.1029 #endif // #ifdef ASSERT 11.1030 }; 11.1031 @@ -1376,17 +1193,17 @@ 11.1032 } 11.1033 11.1034 inline bool 11.1035 -PSParallelCompact::dead_space_crosses_boundary(const ChunkData* chunk, 11.1036 +PSParallelCompact::dead_space_crosses_boundary(const RegionData* region, 11.1037 idx_t bit) 11.1038 { 11.1039 - assert(bit > 0, "cannot call this for the first bit/chunk"); 11.1040 - assert(_summary_data.chunk_to_addr(chunk) == _mark_bitmap.bit_to_addr(bit), 11.1041 + assert(bit > 0, "cannot call this for the first bit/region"); 11.1042 + assert(_summary_data.region_to_addr(region) == _mark_bitmap.bit_to_addr(bit), 11.1043 "sanity check"); 11.1044 11.1045 // Dead space crosses the boundary if (1) a partial object does not extend 11.1046 - // onto the chunk, (2) an object does not start at the beginning of the chunk, 11.1047 - // and (3) an object does not end at the end of the prior chunk. 11.1048 - return chunk->partial_obj_size() == 0 && 11.1049 + // onto the region, (2) an object does not start at the beginning of the 11.1050 + // region, and (3) an object does not end at the end of the prior region. 11.1051 + return region->partial_obj_size() == 0 && 11.1052 !_mark_bitmap.is_obj_beg(bit) && 11.1053 !_mark_bitmap.is_obj_end(bit - 1); 11.1054 }
12.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psPermGen.cpp Tue Sep 30 15:53:55 2008 -0700 12.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psPermGen.cpp Wed Oct 01 15:05:06 2008 -0400 12.3 @@ -123,8 +123,6 @@ 12.4 12.5 void PSPermGen::precompact() { 12.6 // Reset start array first. 12.7 - debug_only(if (!UseParallelOldGC || !VerifyParallelOldWithMarkSweep) {) 12.8 _start_array.reset(); 12.9 - debug_only(}) 12.10 object_mark_sweep()->precompact(); 12.11 }
13.1 --- a/src/share/vm/gc_implementation/shared/immutableSpace.hpp Tue Sep 30 15:53:55 2008 -0700 13.2 +++ b/src/share/vm/gc_implementation/shared/immutableSpace.hpp Wed Oct 01 15:05:06 2008 -0400 13.3 @@ -50,7 +50,8 @@ 13.4 size_t capacity_in_bytes() const { return capacity_in_words() * HeapWordSize; } 13.5 13.6 // Size computations. Sizes are in heapwords. 13.7 - size_t capacity_in_words() const { return pointer_delta(end(), bottom()); } 13.8 + size_t capacity_in_words() const { return pointer_delta(end(), bottom()); } 13.9 + virtual size_t capacity_in_words(Thread*) const { return capacity_in_words(); } 13.10 13.11 // Iteration. 13.12 virtual void oop_iterate(OopClosure* cl);
14.1 --- a/src/share/vm/gc_implementation/shared/markSweep.inline.hpp Tue Sep 30 15:53:55 2008 -0700 14.2 +++ b/src/share/vm/gc_implementation/shared/markSweep.inline.hpp Wed Oct 01 15:05:06 2008 -0400 14.3 @@ -23,13 +23,6 @@ 14.4 */ 14.5 14.6 inline void MarkSweep::mark_object(oop obj) { 14.7 -#ifndef SERIALGC 14.8 - if (UseParallelOldGC && VerifyParallelOldWithMarkSweep) { 14.9 - assert(PSParallelCompact::mark_bitmap()->is_marked(obj), 14.10 - "Should be marked in the marking bitmap"); 14.11 - } 14.12 -#endif // SERIALGC 14.13 - 14.14 // some marks may contain information we need to preserve so we store them away 14.15 // and overwrite the mark. We'll restore it at the end of markSweep. 14.16 markOop mark = obj->mark();
15.1 --- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Tue Sep 30 15:53:55 2008 -0700 15.2 +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Wed Oct 01 15:05:06 2008 -0400 15.3 @@ -181,6 +181,25 @@ 15.4 return lgrp_spaces()->at(i)->space()->free_in_bytes(); 15.5 } 15.6 15.7 + 15.8 +size_t MutableNUMASpace::capacity_in_words(Thread* thr) const { 15.9 + guarantee(thr != NULL, "No thread"); 15.10 + int lgrp_id = thr->lgrp_id(); 15.11 + if (lgrp_id == -1) { 15.12 + if (lgrp_spaces()->length() > 0) { 15.13 + return capacity_in_words() / lgrp_spaces()->length(); 15.14 + } else { 15.15 + assert(false, "There should be at least one locality group"); 15.16 + return 0; 15.17 + } 15.18 + } 15.19 + int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals); 15.20 + if (i == -1) { 15.21 + return 0; 15.22 + } 15.23 + return lgrp_spaces()->at(i)->space()->capacity_in_words(); 15.24 +} 15.25 + 15.26 // Check if the NUMA topology has changed. Add and remove spaces if needed. 15.27 // The update can be forced by setting the force parameter equal to true. 15.28 bool MutableNUMASpace::update_layout(bool force) { 15.29 @@ -722,7 +741,8 @@ 15.30 i = os::random() % lgrp_spaces()->length(); 15.31 } 15.32 15.33 - MutableSpace *s = lgrp_spaces()->at(i)->space(); 15.34 + LGRPSpace* ls = lgrp_spaces()->at(i); 15.35 + MutableSpace *s = ls->space(); 15.36 HeapWord *p = s->allocate(size); 15.37 15.38 if (p != NULL) { 15.39 @@ -743,6 +763,9 @@ 15.40 *(int*)i = 0; 15.41 } 15.42 } 15.43 + if (p == NULL) { 15.44 + ls->set_allocation_failed(); 15.45 + } 15.46 return p; 15.47 } 15.48 15.49 @@ -761,7 +784,8 @@ 15.50 if (i == -1) { 15.51 i = os::random() % lgrp_spaces()->length(); 15.52 } 15.53 - MutableSpace *s = lgrp_spaces()->at(i)->space(); 15.54 + LGRPSpace *ls = lgrp_spaces()->at(i); 15.55 + MutableSpace *s = ls->space(); 15.56 HeapWord *p = s->cas_allocate(size); 15.57 if (p != NULL) { 15.58 size_t remainder = pointer_delta(s->end(), p + size); 15.59 @@ -790,6 +814,9 @@ 15.60 *(int*)i = 0; 15.61 } 15.62 } 15.63 + if (p == NULL) { 15.64 + ls->set_allocation_failed(); 15.65 + } 15.66 return p; 15.67 } 15.68
16.1 --- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Tue Sep 30 15:53:55 2008 -0700 16.2 +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Wed Oct 01 15:05:06 2008 -0400 16.3 @@ -60,6 +60,7 @@ 16.4 MutableSpace* _space; 16.5 MemRegion _invalid_region; 16.6 AdaptiveWeightedAverage *_alloc_rate; 16.7 + bool _allocation_failed; 16.8 16.9 struct SpaceStats { 16.10 size_t _local_space, _remote_space, _unbiased_space, _uncommited_space; 16.11 @@ -81,7 +82,7 @@ 16.12 char* last_page_scanned() { return _last_page_scanned; } 16.13 void set_last_page_scanned(char* p) { _last_page_scanned = p; } 16.14 public: 16.15 - LGRPSpace(int l) : _lgrp_id(l), _last_page_scanned(NULL) { 16.16 + LGRPSpace(int l) : _lgrp_id(l), _last_page_scanned(NULL), _allocation_failed(false) { 16.17 _space = new MutableSpace(); 16.18 _alloc_rate = new AdaptiveWeightedAverage(NUMAChunkResizeWeight); 16.19 } 16.20 @@ -103,8 +104,21 @@ 16.21 return *(int*)lgrp_id_value == p->lgrp_id(); 16.22 } 16.23 16.24 + // Report a failed allocation. 16.25 + void set_allocation_failed() { _allocation_failed = true; } 16.26 + 16.27 void sample() { 16.28 - alloc_rate()->sample(space()->used_in_bytes()); 16.29 + // If there was a failed allocation make allocation rate equal 16.30 + // to the size of the whole chunk. This ensures the progress of 16.31 + // the adaptation process. 16.32 + size_t alloc_rate_sample; 16.33 + if (_allocation_failed) { 16.34 + alloc_rate_sample = space()->capacity_in_bytes(); 16.35 + _allocation_failed = false; 16.36 + } else { 16.37 + alloc_rate_sample = space()->used_in_bytes(); 16.38 + } 16.39 + alloc_rate()->sample(alloc_rate_sample); 16.40 } 16.41 16.42 MemRegion invalid_region() const { return _invalid_region; } 16.43 @@ -190,6 +204,9 @@ 16.44 virtual void ensure_parsability(); 16.45 virtual size_t used_in_words() const; 16.46 virtual size_t free_in_words() const; 16.47 + 16.48 + using MutableSpace::capacity_in_words; 16.49 + virtual size_t capacity_in_words(Thread* thr) const; 16.50 virtual size_t tlab_capacity(Thread* thr) const; 16.51 virtual size_t unsafe_max_tlab_alloc(Thread* thr) const; 16.52
17.1 --- a/src/share/vm/runtime/globals.hpp Tue Sep 30 15:53:55 2008 -0700 17.2 +++ b/src/share/vm/runtime/globals.hpp Wed Oct 01 15:05:06 2008 -0400 17.3 @@ -1157,10 +1157,6 @@ 17.4 "In the Parallel Old garbage collector use parallel dense" \ 17.5 " prefix update") \ 17.6 \ 17.7 - develop(bool, UseParallelOldGCChunkPointerCalc, true, \ 17.8 - "In the Parallel Old garbage collector use chucks to calculate" \ 17.9 - " new object locations") \ 17.10 - \ 17.11 product(uintx, HeapMaximumCompactionInterval, 20, \ 17.12 "How often should we maximally compact the heap (not allowing " \ 17.13 "any dead space)") \ 17.14 @@ -1189,21 +1185,14 @@ 17.15 product(uintx, ParallelCMSThreads, 0, \ 17.16 "Max number of threads CMS will use for concurrent work") \ 17.17 \ 17.18 - develop(bool, VerifyParallelOldWithMarkSweep, false, \ 17.19 - "Use the MarkSweep code to verify phases of Parallel Old") \ 17.20 - \ 17.21 - develop(uintx, VerifyParallelOldWithMarkSweepInterval, 1, \ 17.22 - "Interval at which the MarkSweep code is used to verify " \ 17.23 - "phases of Parallel Old") \ 17.24 - \ 17.25 develop(bool, ParallelOldMTUnsafeMarkBitMap, false, \ 17.26 "Use the Parallel Old MT unsafe in marking the bitmap") \ 17.27 \ 17.28 develop(bool, ParallelOldMTUnsafeUpdateLiveData, false, \ 17.29 "Use the Parallel Old MT unsafe in update of live size") \ 17.30 \ 17.31 - develop(bool, TraceChunkTasksQueuing, false, \ 17.32 - "Trace the queuing of the chunk tasks") \ 17.33 + develop(bool, TraceRegionTasksQueuing, false, \ 17.34 + "Trace the queuing of the region tasks") \ 17.35 \ 17.36 product(uintx, ParallelMarkingThreads, 0, \ 17.37 "Number of marking threads concurrent gc will use") \
18.1 --- a/src/share/vm/utilities/taskqueue.cpp Tue Sep 30 15:53:55 2008 -0700 18.2 +++ b/src/share/vm/utilities/taskqueue.cpp Wed Oct 01 15:05:06 2008 -0400 18.3 @@ -109,72 +109,72 @@ 18.4 } 18.5 } 18.6 18.7 -bool ChunkTaskQueueWithOverflow::is_empty() { 18.8 - return (_chunk_queue.size() == 0) && 18.9 +bool RegionTaskQueueWithOverflow::is_empty() { 18.10 + return (_region_queue.size() == 0) && 18.11 (_overflow_stack->length() == 0); 18.12 } 18.13 18.14 -bool ChunkTaskQueueWithOverflow::stealable_is_empty() { 18.15 - return _chunk_queue.size() == 0; 18.16 +bool RegionTaskQueueWithOverflow::stealable_is_empty() { 18.17 + return _region_queue.size() == 0; 18.18 } 18.19 18.20 -bool ChunkTaskQueueWithOverflow::overflow_is_empty() { 18.21 +bool RegionTaskQueueWithOverflow::overflow_is_empty() { 18.22 return _overflow_stack->length() == 0; 18.23 } 18.24 18.25 -void ChunkTaskQueueWithOverflow::initialize() { 18.26 - _chunk_queue.initialize(); 18.27 +void RegionTaskQueueWithOverflow::initialize() { 18.28 + _region_queue.initialize(); 18.29 assert(_overflow_stack == 0, "Creating memory leak"); 18.30 _overflow_stack = 18.31 - new (ResourceObj::C_HEAP) GrowableArray<ChunkTask>(10, true); 18.32 + new (ResourceObj::C_HEAP) GrowableArray<RegionTask>(10, true); 18.33 } 18.34 18.35 -void ChunkTaskQueueWithOverflow::save(ChunkTask t) { 18.36 - if (TraceChunkTasksQueuing && Verbose) { 18.37 +void RegionTaskQueueWithOverflow::save(RegionTask t) { 18.38 + if (TraceRegionTasksQueuing && Verbose) { 18.39 gclog_or_tty->print_cr("CTQ: save " PTR_FORMAT, t); 18.40 } 18.41 - if(!_chunk_queue.push(t)) { 18.42 + if(!_region_queue.push(t)) { 18.43 _overflow_stack->push(t); 18.44 } 18.45 } 18.46 18.47 -// Note that using this method will retrieve all chunks 18.48 +// Note that using this method will retrieve all regions 18.49 // that have been saved but that it will always check 18.50 // the overflow stack. It may be more efficient to 18.51 // check the stealable queue and the overflow stack 18.52 // separately. 18.53 -bool ChunkTaskQueueWithOverflow::retrieve(ChunkTask& chunk_task) { 18.54 - bool result = retrieve_from_overflow(chunk_task); 18.55 +bool RegionTaskQueueWithOverflow::retrieve(RegionTask& region_task) { 18.56 + bool result = retrieve_from_overflow(region_task); 18.57 if (!result) { 18.58 - result = retrieve_from_stealable_queue(chunk_task); 18.59 + result = retrieve_from_stealable_queue(region_task); 18.60 } 18.61 - if (TraceChunkTasksQueuing && Verbose && result) { 18.62 + if (TraceRegionTasksQueuing && Verbose && result) { 18.63 gclog_or_tty->print_cr(" CTQ: retrieve " PTR_FORMAT, result); 18.64 } 18.65 return result; 18.66 } 18.67 18.68 -bool ChunkTaskQueueWithOverflow::retrieve_from_stealable_queue( 18.69 - ChunkTask& chunk_task) { 18.70 - bool result = _chunk_queue.pop_local(chunk_task); 18.71 - if (TraceChunkTasksQueuing && Verbose) { 18.72 - gclog_or_tty->print_cr("CTQ: retrieve_stealable " PTR_FORMAT, chunk_task); 18.73 +bool RegionTaskQueueWithOverflow::retrieve_from_stealable_queue( 18.74 + RegionTask& region_task) { 18.75 + bool result = _region_queue.pop_local(region_task); 18.76 + if (TraceRegionTasksQueuing && Verbose) { 18.77 + gclog_or_tty->print_cr("CTQ: retrieve_stealable " PTR_FORMAT, region_task); 18.78 } 18.79 return result; 18.80 } 18.81 18.82 -bool ChunkTaskQueueWithOverflow::retrieve_from_overflow( 18.83 - ChunkTask& chunk_task) { 18.84 +bool 18.85 +RegionTaskQueueWithOverflow::retrieve_from_overflow(RegionTask& region_task) { 18.86 bool result; 18.87 if (!_overflow_stack->is_empty()) { 18.88 - chunk_task = _overflow_stack->pop(); 18.89 + region_task = _overflow_stack->pop(); 18.90 result = true; 18.91 } else { 18.92 - chunk_task = (ChunkTask) NULL; 18.93 + region_task = (RegionTask) NULL; 18.94 result = false; 18.95 } 18.96 - if (TraceChunkTasksQueuing && Verbose) { 18.97 - gclog_or_tty->print_cr("CTQ: retrieve_stealable " PTR_FORMAT, chunk_task); 18.98 + if (TraceRegionTasksQueuing && Verbose) { 18.99 + gclog_or_tty->print_cr("CTQ: retrieve_stealable " PTR_FORMAT, region_task); 18.100 } 18.101 return result; 18.102 }
19.1 --- a/src/share/vm/utilities/taskqueue.hpp Tue Sep 30 15:53:55 2008 -0700 19.2 +++ b/src/share/vm/utilities/taskqueue.hpp Wed Oct 01 15:05:06 2008 -0400 19.3 @@ -557,32 +557,32 @@ 19.4 typedef GenericTaskQueue<StarTask> OopStarTaskQueue; 19.5 typedef GenericTaskQueueSet<StarTask> OopStarTaskQueueSet; 19.6 19.7 -typedef size_t ChunkTask; // index for chunk 19.8 -typedef GenericTaskQueue<ChunkTask> ChunkTaskQueue; 19.9 -typedef GenericTaskQueueSet<ChunkTask> ChunkTaskQueueSet; 19.10 +typedef size_t RegionTask; // index for region 19.11 +typedef GenericTaskQueue<RegionTask> RegionTaskQueue; 19.12 +typedef GenericTaskQueueSet<RegionTask> RegionTaskQueueSet; 19.13 19.14 -class ChunkTaskQueueWithOverflow: public CHeapObj { 19.15 +class RegionTaskQueueWithOverflow: public CHeapObj { 19.16 protected: 19.17 - ChunkTaskQueue _chunk_queue; 19.18 - GrowableArray<ChunkTask>* _overflow_stack; 19.19 + RegionTaskQueue _region_queue; 19.20 + GrowableArray<RegionTask>* _overflow_stack; 19.21 19.22 public: 19.23 - ChunkTaskQueueWithOverflow() : _overflow_stack(NULL) {} 19.24 + RegionTaskQueueWithOverflow() : _overflow_stack(NULL) {} 19.25 // Initialize both stealable queue and overflow 19.26 void initialize(); 19.27 // Save first to stealable queue and then to overflow 19.28 - void save(ChunkTask t); 19.29 + void save(RegionTask t); 19.30 // Retrieve first from overflow and then from stealable queue 19.31 - bool retrieve(ChunkTask& chunk_index); 19.32 + bool retrieve(RegionTask& region_index); 19.33 // Retrieve from stealable queue 19.34 - bool retrieve_from_stealable_queue(ChunkTask& chunk_index); 19.35 + bool retrieve_from_stealable_queue(RegionTask& region_index); 19.36 // Retrieve from overflow 19.37 - bool retrieve_from_overflow(ChunkTask& chunk_index); 19.38 + bool retrieve_from_overflow(RegionTask& region_index); 19.39 bool is_empty(); 19.40 bool stealable_is_empty(); 19.41 bool overflow_is_empty(); 19.42 - juint stealable_size() { return _chunk_queue.size(); } 19.43 - ChunkTaskQueue* task_queue() { return &_chunk_queue; } 19.44 + juint stealable_size() { return _region_queue.size(); } 19.45 + RegionTaskQueue* task_queue() { return &_region_queue; } 19.46 }; 19.47 19.48 -#define USE_ChunkTaskQueueWithOverflow 19.49 +#define USE_RegionTaskQueueWithOverflow