Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp
38920 views
/*1* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "classfile/systemDictionary.hpp"26#include "gc_implementation/parallelScavenge/gcTaskManager.hpp"27#include "gc_implementation/parallelScavenge/objectStartArray.hpp"28#include "gc_implementation/parallelScavenge/parMarkBitMap.hpp"29#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"30#include "gc_implementation/parallelScavenge/psCompactionManager.hpp"31#include "gc_implementation/parallelScavenge/psOldGen.hpp"32#include "gc_implementation/parallelScavenge/psParallelCompact.hpp"33#include "oops/objArrayKlass.inline.hpp"34#include "oops/oop.inline.hpp"35#include "oops/oop.pcgc.inline.hpp"36#include "utilities/stack.inline.hpp"3738PSOldGen* ParCompactionManager::_old_gen = NULL;39ParCompactionManager** ParCompactionManager::_manager_array = NULL;4041RegionTaskQueue** ParCompactionManager::_region_list = NULL;4243OopTaskQueueSet* ParCompactionManager::_stack_array = NULL;44ParCompactionManager::ObjArrayTaskQueueSet*45ParCompactionManager::_objarray_queues = NULL;46ObjectStartArray* ParCompactionManager::_start_array = NULL;47ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL;48RegionTaskQueueSet* ParCompactionManager::_region_array = NULL;4950uint* ParCompactionManager::_recycled_stack_index = NULL;51int ParCompactionManager::_recycled_top = -1;52int ParCompactionManager::_recycled_bottom = -1;5354ParCompactionManager::ParCompactionManager() :55_action(CopyAndUpdate),56_region_stack(NULL),57_region_stack_index((uint)max_uintx) {5859ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();60assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");6162_old_gen = heap->old_gen();63_start_array = old_gen()->start_array();6465marking_stack()->initialize();66_objarray_stack.initialize();67}6869ParCompactionManager::~ParCompactionManager() {70delete _recycled_stack_index;71}7273void ParCompactionManager::initialize(ParMarkBitMap* mbm) {74assert(PSParallelCompact::gc_task_manager() != NULL,75"Needed for initialization");7677_mark_bitmap = mbm;7879uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers();8081assert(_manager_array == NULL, "Attempt to initialize twice");82_manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1, mtGC);83guarantee(_manager_array != NULL, "Could not allocate manager_array");8485_region_list = NEW_C_HEAP_ARRAY(RegionTaskQueue*,86parallel_gc_threads+1, mtGC);87guarantee(_region_list != NULL, "Could not initialize promotion manager");8889_recycled_stack_index = NEW_C_HEAP_ARRAY(uint, parallel_gc_threads, mtGC);9091// parallel_gc-threads + 1 to be consistent with the number of92// compaction managers.93for(uint i=0; i<parallel_gc_threads + 1; i++) {94_region_list[i] = new RegionTaskQueue();95region_list(i)->initialize();96}9798_stack_array = new OopTaskQueueSet(parallel_gc_threads);99guarantee(_stack_array != NULL, "Could not allocate stack_array");100_objarray_queues = new ObjArrayTaskQueueSet(parallel_gc_threads);101guarantee(_objarray_queues != NULL, "Could not allocate objarray_queues");102_region_array = new RegionTaskQueueSet(parallel_gc_threads);103guarantee(_region_array != NULL, "Could not allocate region_array");104105// Create and register the ParCompactionManager(s) for the worker threads.106for(uint i=0; i<parallel_gc_threads; i++) {107_manager_array[i] = new ParCompactionManager();108guarantee(_manager_array[i] != NULL, "Could not create ParCompactionManager");109stack_array()->register_queue(i, _manager_array[i]->marking_stack());110_objarray_queues->register_queue(i, &_manager_array[i]->_objarray_stack);111region_array()->register_queue(i, region_list(i));112}113114// The VMThread gets its own ParCompactionManager, which is not available115// for work stealing.116_manager_array[parallel_gc_threads] = new ParCompactionManager();117guarantee(_manager_array[parallel_gc_threads] != NULL,118"Could not create ParCompactionManager");119assert(PSParallelCompact::gc_task_manager()->workers() != 0,120"Not initialized?");121}122123int ParCompactionManager::pop_recycled_stack_index() {124assert(_recycled_bottom <= _recycled_top, "list is empty");125// Get the next available index126if (_recycled_bottom < _recycled_top) {127uint cur, next, last;128do {129cur = _recycled_bottom;130next = cur + 1;131last = Atomic::cmpxchg(next, &_recycled_bottom, cur);132} while (cur != last);133return _recycled_stack_index[next];134} else {135return -1;136}137}138139void ParCompactionManager::push_recycled_stack_index(uint v) {140// Get the next available index141int cur = Atomic::add(1, &_recycled_top);142_recycled_stack_index[cur] = v;143assert(_recycled_bottom <= _recycled_top, "list top and bottom are wrong");144}145146bool ParCompactionManager::should_update() {147assert(action() != NotValid, "Action is not set");148return (action() == ParCompactionManager::Update) ||149(action() == ParCompactionManager::CopyAndUpdate) ||150(action() == ParCompactionManager::UpdateAndCopy);151}152153bool ParCompactionManager::should_copy() {154assert(action() != NotValid, "Action is not set");155return (action() == ParCompactionManager::Copy) ||156(action() == ParCompactionManager::CopyAndUpdate) ||157(action() == ParCompactionManager::UpdateAndCopy);158}159160void ParCompactionManager::region_list_push(uint list_index,161size_t region_index) {162region_list(list_index)->push(region_index);163}164165void ParCompactionManager::verify_region_list_empty(uint list_index) {166assert(region_list(list_index)->is_empty(), "Not empty");167}168169ParCompactionManager*170ParCompactionManager::gc_thread_compaction_manager(int index) {171assert(index >= 0 && index < (int)ParallelGCThreads, "index out of range");172assert(_manager_array != NULL, "Sanity");173return _manager_array[index];174}175176void ParCompactionManager::follow_marking_stacks() {177do {178// Drain the overflow stack first, to allow stealing from the marking stack.179oop obj;180while (marking_stack()->pop_overflow(obj)) {181obj->follow_contents(this);182}183while (marking_stack()->pop_local(obj)) {184obj->follow_contents(this);185}186187// Process ObjArrays one at a time to avoid marking stack bloat.188ObjArrayTask task;189if (_objarray_stack.pop_overflow(task) || _objarray_stack.pop_local(task)) {190ObjArrayKlass* k = (ObjArrayKlass*)task.obj()->klass();191k->oop_follow_contents(this, task.obj(), task.index());192}193} while (!marking_stacks_empty());194195assert(marking_stacks_empty(), "Sanity");196}197198void ParCompactionManager::drain_region_stacks() {199do {200// Drain overflow stack first so other threads can steal.201size_t region_index;202while (region_stack()->pop_overflow(region_index)) {203PSParallelCompact::fill_and_update_region(this, region_index);204}205206while (region_stack()->pop_local(region_index)) {207PSParallelCompact::fill_and_update_region(this, region_index);208}209} while (!region_stack()->is_empty());210}211212213