1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,211 @@ 1.4 +/* 1.5 + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "classfile/systemDictionary.hpp" 1.30 +#include "gc_implementation/parallelScavenge/gcTaskManager.hpp" 1.31 +#include "gc_implementation/parallelScavenge/objectStartArray.hpp" 1.32 +#include "gc_implementation/parallelScavenge/parMarkBitMap.hpp" 1.33 +#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" 1.34 +#include "gc_implementation/parallelScavenge/psCompactionManager.hpp" 1.35 +#include "gc_implementation/parallelScavenge/psOldGen.hpp" 1.36 +#include "gc_implementation/parallelScavenge/psParallelCompact.hpp" 1.37 +#include "oops/objArrayKlass.inline.hpp" 1.38 +#include "oops/oop.inline.hpp" 1.39 +#include "oops/oop.pcgc.inline.hpp" 1.40 +#include "utilities/stack.inline.hpp" 1.41 + 1.42 +PSOldGen* ParCompactionManager::_old_gen = NULL; 1.43 +ParCompactionManager** ParCompactionManager::_manager_array = NULL; 1.44 + 1.45 +RegionTaskQueue** ParCompactionManager::_region_list = NULL; 1.46 + 1.47 +OopTaskQueueSet* ParCompactionManager::_stack_array = NULL; 1.48 +ParCompactionManager::ObjArrayTaskQueueSet* 1.49 + ParCompactionManager::_objarray_queues = NULL; 1.50 +ObjectStartArray* ParCompactionManager::_start_array = NULL; 1.51 +ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL; 1.52 +RegionTaskQueueSet* ParCompactionManager::_region_array = NULL; 1.53 + 1.54 +uint* ParCompactionManager::_recycled_stack_index = NULL; 1.55 +int ParCompactionManager::_recycled_top = -1; 1.56 +int ParCompactionManager::_recycled_bottom = -1; 1.57 + 1.58 +ParCompactionManager::ParCompactionManager() : 1.59 + _action(CopyAndUpdate), 1.60 + _region_stack(NULL), 1.61 + _region_stack_index((uint)max_uintx) { 1.62 + 1.63 + ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); 1.64 + assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); 1.65 + 1.66 + _old_gen = heap->old_gen(); 1.67 + _start_array = old_gen()->start_array(); 1.68 + 1.69 + marking_stack()->initialize(); 1.70 + _objarray_stack.initialize(); 1.71 +} 1.72 + 1.73 +ParCompactionManager::~ParCompactionManager() { 1.74 + delete _recycled_stack_index; 1.75 +} 1.76 + 1.77 +void ParCompactionManager::initialize(ParMarkBitMap* mbm) { 1.78 + assert(PSParallelCompact::gc_task_manager() != NULL, 1.79 + "Needed for initialization"); 1.80 + 1.81 + _mark_bitmap = mbm; 1.82 + 1.83 + uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers(); 1.84 + 1.85 + assert(_manager_array == NULL, "Attempt to initialize twice"); 1.86 + _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1, mtGC); 1.87 + guarantee(_manager_array != NULL, "Could not allocate manager_array"); 1.88 + 1.89 + _region_list = NEW_C_HEAP_ARRAY(RegionTaskQueue*, 1.90 + parallel_gc_threads+1, mtGC); 1.91 + guarantee(_region_list != NULL, "Could not initialize promotion manager"); 1.92 + 1.93 + _recycled_stack_index = NEW_C_HEAP_ARRAY(uint, parallel_gc_threads, mtGC); 1.94 + 1.95 + // parallel_gc-threads + 1 to be consistent with the number of 1.96 + // compaction managers. 1.97 + for(uint i=0; i<parallel_gc_threads + 1; i++) { 1.98 + _region_list[i] = new RegionTaskQueue(); 1.99 + region_list(i)->initialize(); 1.100 + } 1.101 + 1.102 + _stack_array = new OopTaskQueueSet(parallel_gc_threads); 1.103 + guarantee(_stack_array != NULL, "Could not allocate stack_array"); 1.104 + _objarray_queues = new ObjArrayTaskQueueSet(parallel_gc_threads); 1.105 + guarantee(_objarray_queues != NULL, "Could not allocate objarray_queues"); 1.106 + _region_array = new RegionTaskQueueSet(parallel_gc_threads); 1.107 + guarantee(_region_array != NULL, "Could not allocate region_array"); 1.108 + 1.109 + // Create and register the ParCompactionManager(s) for the worker threads. 1.110 + for(uint i=0; i<parallel_gc_threads; i++) { 1.111 + _manager_array[i] = new ParCompactionManager(); 1.112 + guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager"); 1.113 + stack_array()->register_queue(i, _manager_array[i]->marking_stack()); 1.114 + _objarray_queues->register_queue(i, &_manager_array[i]->_objarray_stack); 1.115 + region_array()->register_queue(i, region_list(i)); 1.116 + } 1.117 + 1.118 + // The VMThread gets its own ParCompactionManager, which is not available 1.119 + // for work stealing. 1.120 + _manager_array[parallel_gc_threads] = new ParCompactionManager(); 1.121 + guarantee(_manager_array[parallel_gc_threads] != NULL, 1.122 + "Could not create ParCompactionManager"); 1.123 + assert(PSParallelCompact::gc_task_manager()->workers() != 0, 1.124 + "Not initialized?"); 1.125 +} 1.126 + 1.127 +int ParCompactionManager::pop_recycled_stack_index() { 1.128 + assert(_recycled_bottom <= _recycled_top, "list is empty"); 1.129 + // Get the next available index 1.130 + if (_recycled_bottom < _recycled_top) { 1.131 + uint cur, next, last; 1.132 + do { 1.133 + cur = _recycled_bottom; 1.134 + next = cur + 1; 1.135 + last = Atomic::cmpxchg(next, &_recycled_bottom, cur); 1.136 + } while (cur != last); 1.137 + return _recycled_stack_index[next]; 1.138 + } else { 1.139 + return -1; 1.140 + } 1.141 +} 1.142 + 1.143 +void ParCompactionManager::push_recycled_stack_index(uint v) { 1.144 + // Get the next available index 1.145 + int cur = Atomic::add(1, &_recycled_top); 1.146 + _recycled_stack_index[cur] = v; 1.147 + assert(_recycled_bottom <= _recycled_top, "list top and bottom are wrong"); 1.148 +} 1.149 + 1.150 +bool ParCompactionManager::should_update() { 1.151 + assert(action() != NotValid, "Action is not set"); 1.152 + return (action() == ParCompactionManager::Update) || 1.153 + (action() == ParCompactionManager::CopyAndUpdate) || 1.154 + (action() == ParCompactionManager::UpdateAndCopy); 1.155 +} 1.156 + 1.157 +bool ParCompactionManager::should_copy() { 1.158 + assert(action() != NotValid, "Action is not set"); 1.159 + return (action() == ParCompactionManager::Copy) || 1.160 + (action() == ParCompactionManager::CopyAndUpdate) || 1.161 + (action() == ParCompactionManager::UpdateAndCopy); 1.162 +} 1.163 + 1.164 +void ParCompactionManager::region_list_push(uint list_index, 1.165 + size_t region_index) { 1.166 + region_list(list_index)->push(region_index); 1.167 +} 1.168 + 1.169 +void ParCompactionManager::verify_region_list_empty(uint list_index) { 1.170 + assert(region_list(list_index)->is_empty(), "Not empty"); 1.171 +} 1.172 + 1.173 +ParCompactionManager* 1.174 +ParCompactionManager::gc_thread_compaction_manager(int index) { 1.175 + assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range"); 1.176 + assert(_manager_array != NULL, "Sanity"); 1.177 + return _manager_array[index]; 1.178 +} 1.179 + 1.180 +void ParCompactionManager::follow_marking_stacks() { 1.181 + do { 1.182 + // Drain the overflow stack first, to allow stealing from the marking stack. 1.183 + oop obj; 1.184 + while (marking_stack()->pop_overflow(obj)) { 1.185 + obj->follow_contents(this); 1.186 + } 1.187 + while (marking_stack()->pop_local(obj)) { 1.188 + obj->follow_contents(this); 1.189 + } 1.190 + 1.191 + // Process ObjArrays one at a time to avoid marking stack bloat. 1.192 + ObjArrayTask task; 1.193 + if (_objarray_stack.pop_overflow(task) || _objarray_stack.pop_local(task)) { 1.194 + ObjArrayKlass* k = (ObjArrayKlass*)task.obj()->klass(); 1.195 + k->oop_follow_contents(this, task.obj(), task.index()); 1.196 + } 1.197 + } while (!marking_stacks_empty()); 1.198 + 1.199 + assert(marking_stacks_empty(), "Sanity"); 1.200 +} 1.201 + 1.202 +void ParCompactionManager::drain_region_stacks() { 1.203 + do { 1.204 + // Drain overflow stack first so other threads can steal. 1.205 + size_t region_index; 1.206 + while (region_stack()->pop_overflow(region_index)) { 1.207 + PSParallelCompact::fill_and_update_region(this, region_index); 1.208 + } 1.209 + 1.210 + while (region_stack()->pop_local(region_index)) { 1.211 + PSParallelCompact::fill_and_update_region(this, region_index); 1.212 + } 1.213 + } while (!region_stack()->is_empty()); 1.214 +}