src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp

Tue, 08 Aug 2017 15:57:29 +0800

author
aoqi
date
Tue, 08 Aug 2017 15:57:29 +0800
changeset 6876
710a3c8b516e
parent 6680
78bbf4d43a14
parent 0
f90c822e73f8
child 7535
7ae4e26cb1e0
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #include "precompiled.hpp"
aoqi@0 26 #include "classfile/systemDictionary.hpp"
aoqi@0 27 #include "code/codeCache.hpp"
aoqi@0 28 #include "gc_implementation/parallelScavenge/pcTasks.hpp"
aoqi@0 29 #include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
aoqi@0 30 #include "gc_implementation/shared/gcTimer.hpp"
aoqi@0 31 #include "gc_implementation/shared/gcTraceTime.hpp"
aoqi@0 32 #include "gc_interface/collectedHeap.hpp"
aoqi@0 33 #include "memory/universe.hpp"
aoqi@0 34 #include "oops/objArrayKlass.inline.hpp"
aoqi@0 35 #include "oops/oop.inline.hpp"
aoqi@0 36 #include "oops/oop.pcgc.inline.hpp"
aoqi@0 37 #include "prims/jvmtiExport.hpp"
aoqi@0 38 #include "runtime/fprofiler.hpp"
aoqi@0 39 #include "runtime/jniHandles.hpp"
aoqi@0 40 #include "runtime/thread.hpp"
aoqi@0 41 #include "runtime/vmThread.hpp"
aoqi@0 42 #include "services/management.hpp"
aoqi@0 43
aoqi@0 44 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
aoqi@0 45
aoqi@0 46 //
aoqi@0 47 // ThreadRootsMarkingTask
aoqi@0 48 //
aoqi@0 49
aoqi@0 50 void ThreadRootsMarkingTask::do_it(GCTaskManager* manager, uint which) {
aoqi@0 51 assert(Universe::heap()->is_gc_active(), "called outside gc");
aoqi@0 52
aoqi@0 53 ResourceMark rm;
aoqi@0 54
aoqi@0 55 NOT_PRODUCT(GCTraceTime tm("ThreadRootsMarkingTask",
aoqi@0 56 PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
aoqi@0 57 ParCompactionManager* cm =
aoqi@0 58 ParCompactionManager::gc_thread_compaction_manager(which);
aoqi@0 59
aoqi@0 60 PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
aoqi@0 61 CLDToOopClosure mark_and_push_from_clds(&mark_and_push_closure, true);
aoqi@0 62 CodeBlobToOopClosure mark_and_push_in_blobs(&mark_and_push_closure, /*do_marking=*/ true);
aoqi@0 63
aoqi@0 64 if (_java_thread != NULL)
aoqi@0 65 _java_thread->oops_do(
aoqi@0 66 &mark_and_push_closure,
aoqi@0 67 &mark_and_push_from_clds,
aoqi@0 68 &mark_and_push_in_blobs);
aoqi@0 69
aoqi@0 70 if (_vm_thread != NULL)
aoqi@0 71 _vm_thread->oops_do(
aoqi@0 72 &mark_and_push_closure,
aoqi@0 73 &mark_and_push_from_clds,
aoqi@0 74 &mark_and_push_in_blobs);
aoqi@0 75
aoqi@0 76 // Do the real work
aoqi@0 77 cm->follow_marking_stacks();
aoqi@0 78 }
aoqi@0 79
aoqi@0 80
aoqi@0 81 void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
aoqi@0 82 assert(Universe::heap()->is_gc_active(), "called outside gc");
aoqi@0 83
aoqi@0 84 NOT_PRODUCT(GCTraceTime tm("MarkFromRootsTask",
aoqi@0 85 PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
aoqi@0 86 ParCompactionManager* cm =
aoqi@0 87 ParCompactionManager::gc_thread_compaction_manager(which);
aoqi@0 88 PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
aoqi@0 89 PSParallelCompact::FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
aoqi@0 90
aoqi@0 91 switch (_root_type) {
aoqi@0 92 case universe:
aoqi@0 93 Universe::oops_do(&mark_and_push_closure);
aoqi@0 94 break;
aoqi@0 95
aoqi@0 96 case jni_handles:
aoqi@0 97 JNIHandles::oops_do(&mark_and_push_closure);
aoqi@0 98 break;
aoqi@0 99
aoqi@0 100 case threads:
aoqi@0 101 {
aoqi@0 102 ResourceMark rm;
aoqi@0 103 CodeBlobToOopClosure each_active_code_blob(&mark_and_push_closure, /*do_marking=*/ true);
aoqi@0 104 CLDToOopClosure mark_and_push_from_cld(&mark_and_push_closure);
aoqi@0 105 Threads::oops_do(&mark_and_push_closure, &mark_and_push_from_cld, &each_active_code_blob);
aoqi@0 106 }
aoqi@0 107 break;
aoqi@0 108
aoqi@0 109 case object_synchronizer:
aoqi@0 110 ObjectSynchronizer::oops_do(&mark_and_push_closure);
aoqi@0 111 break;
aoqi@0 112
aoqi@0 113 case flat_profiler:
aoqi@0 114 FlatProfiler::oops_do(&mark_and_push_closure);
aoqi@0 115 break;
aoqi@0 116
aoqi@0 117 case management:
aoqi@0 118 Management::oops_do(&mark_and_push_closure);
aoqi@0 119 break;
aoqi@0 120
aoqi@0 121 case jvmti:
aoqi@0 122 JvmtiExport::oops_do(&mark_and_push_closure);
aoqi@0 123 break;
aoqi@0 124
aoqi@0 125 case system_dictionary:
aoqi@0 126 SystemDictionary::always_strong_oops_do(&mark_and_push_closure);
aoqi@0 127 break;
aoqi@0 128
aoqi@0 129 case class_loader_data:
aoqi@0 130 ClassLoaderDataGraph::always_strong_oops_do(&mark_and_push_closure, &follow_klass_closure, true);
aoqi@0 131 break;
aoqi@0 132
aoqi@0 133 case code_cache:
aoqi@0 134 // Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
aoqi@0 135 //CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(&mark_and_push_closure));
aoqi@0 136 break;
aoqi@0 137
aoqi@0 138 default:
aoqi@0 139 fatal("Unknown root type");
aoqi@0 140 }
aoqi@0 141
aoqi@0 142 // Do the real work
aoqi@0 143 cm->follow_marking_stacks();
aoqi@0 144 }
aoqi@0 145
aoqi@0 146
aoqi@0 147 //
aoqi@0 148 // RefProcTaskProxy
aoqi@0 149 //
aoqi@0 150
aoqi@0 151 void RefProcTaskProxy::do_it(GCTaskManager* manager, uint which)
aoqi@0 152 {
aoqi@0 153 assert(Universe::heap()->is_gc_active(), "called outside gc");
aoqi@0 154
aoqi@0 155 NOT_PRODUCT(GCTraceTime tm("RefProcTask",
aoqi@0 156 PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
aoqi@0 157 ParCompactionManager* cm =
aoqi@0 158 ParCompactionManager::gc_thread_compaction_manager(which);
aoqi@0 159 PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
aoqi@0 160 PSParallelCompact::FollowStackClosure follow_stack_closure(cm);
aoqi@0 161 _rp_task.work(_work_id, *PSParallelCompact::is_alive_closure(),
aoqi@0 162 mark_and_push_closure, follow_stack_closure);
aoqi@0 163 }
aoqi@0 164
aoqi@0 165 //
aoqi@0 166 // RefProcTaskExecutor
aoqi@0 167 //
aoqi@0 168
aoqi@0 169 void RefProcTaskExecutor::execute(ProcessTask& task)
aoqi@0 170 {
aoqi@0 171 ParallelScavengeHeap* heap = PSParallelCompact::gc_heap();
aoqi@0 172 uint parallel_gc_threads = heap->gc_task_manager()->workers();
aoqi@0 173 uint active_gc_threads = heap->gc_task_manager()->active_workers();
aoqi@0 174 RegionTaskQueueSet* qset = ParCompactionManager::region_array();
aoqi@0 175 ParallelTaskTerminator terminator(active_gc_threads, qset);
aoqi@0 176 GCTaskQueue* q = GCTaskQueue::create();
aoqi@0 177 for(uint i=0; i<parallel_gc_threads; i++) {
aoqi@0 178 q->enqueue(new RefProcTaskProxy(task, i));
aoqi@0 179 }
aoqi@0 180 if (task.marks_oops_alive()) {
aoqi@0 181 if (parallel_gc_threads>1) {
aoqi@0 182 for (uint j=0; j<active_gc_threads; j++) {
aoqi@0 183 q->enqueue(new StealMarkingTask(&terminator));
aoqi@0 184 }
aoqi@0 185 }
aoqi@0 186 }
aoqi@0 187 PSParallelCompact::gc_task_manager()->execute_and_wait(q);
aoqi@0 188 }
aoqi@0 189
aoqi@0 190 void RefProcTaskExecutor::execute(EnqueueTask& task)
aoqi@0 191 {
aoqi@0 192 ParallelScavengeHeap* heap = PSParallelCompact::gc_heap();
aoqi@0 193 uint parallel_gc_threads = heap->gc_task_manager()->workers();
aoqi@0 194 GCTaskQueue* q = GCTaskQueue::create();
aoqi@0 195 for(uint i=0; i<parallel_gc_threads; i++) {
aoqi@0 196 q->enqueue(new RefEnqueueTaskProxy(task, i));
aoqi@0 197 }
aoqi@0 198 PSParallelCompact::gc_task_manager()->execute_and_wait(q);
aoqi@0 199 }
aoqi@0 200
aoqi@0 201 //
aoqi@0 202 // StealMarkingTask
aoqi@0 203 //
aoqi@0 204
aoqi@0 205 StealMarkingTask::StealMarkingTask(ParallelTaskTerminator* t) :
aoqi@0 206 _terminator(t) {}
aoqi@0 207
aoqi@0 208 void StealMarkingTask::do_it(GCTaskManager* manager, uint which) {
aoqi@0 209 assert(Universe::heap()->is_gc_active(), "called outside gc");
aoqi@0 210
aoqi@0 211 NOT_PRODUCT(GCTraceTime tm("StealMarkingTask",
aoqi@0 212 PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
aoqi@0 213
aoqi@0 214 ParCompactionManager* cm =
aoqi@0 215 ParCompactionManager::gc_thread_compaction_manager(which);
aoqi@0 216 PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
aoqi@0 217
aoqi@0 218 oop obj = NULL;
aoqi@0 219 ObjArrayTask task;
aoqi@0 220 int random_seed = 17;
aoqi@0 221 do {
aoqi@0 222 while (ParCompactionManager::steal_objarray(which, &random_seed, task)) {
aoqi@0 223 ObjArrayKlass* k = (ObjArrayKlass*)task.obj()->klass();
aoqi@0 224 k->oop_follow_contents(cm, task.obj(), task.index());
aoqi@0 225 cm->follow_marking_stacks();
aoqi@0 226 }
aoqi@0 227 while (ParCompactionManager::steal(which, &random_seed, obj)) {
aoqi@0 228 obj->follow_contents(cm);
aoqi@0 229 cm->follow_marking_stacks();
aoqi@0 230 }
aoqi@0 231 } while (!terminator()->offer_termination());
aoqi@0 232 }
aoqi@0 233
aoqi@0 234 //
aoqi@0 235 // StealRegionCompactionTask
aoqi@0 236 //
aoqi@0 237
aoqi@0 238 StealRegionCompactionTask::StealRegionCompactionTask(ParallelTaskTerminator* t):
aoqi@0 239 _terminator(t) {}
aoqi@0 240
aoqi@0 241 void StealRegionCompactionTask::do_it(GCTaskManager* manager, uint which) {
aoqi@0 242 assert(Universe::heap()->is_gc_active(), "called outside gc");
aoqi@0 243
aoqi@0 244 NOT_PRODUCT(GCTraceTime tm("StealRegionCompactionTask",
aoqi@0 245 PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
aoqi@0 246
aoqi@0 247 ParCompactionManager* cm =
aoqi@0 248 ParCompactionManager::gc_thread_compaction_manager(which);
aoqi@0 249
aoqi@0 250
aoqi@0 251 // If not all threads are active, get a draining stack
aoqi@0 252 // from the list. Else, just use this threads draining stack.
aoqi@0 253 uint which_stack_index;
aoqi@0 254 bool use_all_workers = manager->all_workers_active();
aoqi@0 255 if (use_all_workers) {
aoqi@0 256 which_stack_index = which;
aoqi@0 257 assert(manager->active_workers() == ParallelGCThreads,
aoqi@0 258 err_msg("all_workers_active has been incorrectly set: "
aoqi@0 259 " active %d ParallelGCThreads %d", manager->active_workers(),
aoqi@0 260 ParallelGCThreads));
aoqi@0 261 } else {
aoqi@0 262 which_stack_index = ParCompactionManager::pop_recycled_stack_index();
aoqi@0 263 }
aoqi@0 264
aoqi@0 265 cm->set_region_stack_index(which_stack_index);
aoqi@0 266 cm->set_region_stack(ParCompactionManager::region_list(which_stack_index));
aoqi@0 267 if (TraceDynamicGCThreads) {
aoqi@0 268 gclog_or_tty->print_cr("StealRegionCompactionTask::do_it "
aoqi@0 269 "region_stack_index %d region_stack = 0x%x "
aoqi@0 270 " empty (%d) use all workers %d",
aoqi@0 271 which_stack_index, ParCompactionManager::region_list(which_stack_index),
aoqi@0 272 cm->region_stack()->is_empty(),
aoqi@0 273 use_all_workers);
aoqi@0 274 }
aoqi@0 275
aoqi@0 276 // Has to drain stacks first because there may be regions on
aoqi@0 277 // preloaded onto the stack and this thread may never have
aoqi@0 278 // done a draining task. Are the draining tasks needed?
aoqi@0 279
aoqi@0 280 cm->drain_region_stacks();
aoqi@0 281
aoqi@0 282 size_t region_index = 0;
aoqi@0 283 int random_seed = 17;
aoqi@0 284
aoqi@0 285 // If we're the termination task, try 10 rounds of stealing before
aoqi@0 286 // setting the termination flag
aoqi@0 287
aoqi@0 288 while(true) {
aoqi@0 289 if (ParCompactionManager::steal(which, &random_seed, region_index)) {
aoqi@0 290 PSParallelCompact::fill_and_update_region(cm, region_index);
aoqi@0 291 cm->drain_region_stacks();
aoqi@0 292 } else {
aoqi@0 293 if (terminator()->offer_termination()) {
aoqi@0 294 break;
aoqi@0 295 }
aoqi@0 296 // Go around again.
aoqi@0 297 }
aoqi@0 298 }
aoqi@0 299 return;
aoqi@0 300 }
aoqi@0 301
aoqi@0 302 UpdateDensePrefixTask::UpdateDensePrefixTask(
aoqi@0 303 PSParallelCompact::SpaceId space_id,
aoqi@0 304 size_t region_index_start,
aoqi@0 305 size_t region_index_end) :
aoqi@0 306 _space_id(space_id), _region_index_start(region_index_start),
aoqi@0 307 _region_index_end(region_index_end) {}
aoqi@0 308
aoqi@0 309 void UpdateDensePrefixTask::do_it(GCTaskManager* manager, uint which) {
aoqi@0 310
aoqi@0 311 NOT_PRODUCT(GCTraceTime tm("UpdateDensePrefixTask",
aoqi@0 312 PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
aoqi@0 313
aoqi@0 314 ParCompactionManager* cm =
aoqi@0 315 ParCompactionManager::gc_thread_compaction_manager(which);
aoqi@0 316
aoqi@0 317 PSParallelCompact::update_and_deadwood_in_dense_prefix(cm,
aoqi@0 318 _space_id,
aoqi@0 319 _region_index_start,
aoqi@0 320 _region_index_end);
aoqi@0 321 }
aoqi@0 322
aoqi@0 323 void DrainStacksCompactionTask::do_it(GCTaskManager* manager, uint which) {
aoqi@0 324 assert(Universe::heap()->is_gc_active(), "called outside gc");
aoqi@0 325
aoqi@0 326 NOT_PRODUCT(GCTraceTime tm("DrainStacksCompactionTask",
aoqi@0 327 PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
aoqi@0 328
aoqi@0 329 ParCompactionManager* cm =
aoqi@0 330 ParCompactionManager::gc_thread_compaction_manager(which);
aoqi@0 331
aoqi@0 332 uint which_stack_index;
aoqi@0 333 bool use_all_workers = manager->all_workers_active();
aoqi@0 334 if (use_all_workers) {
aoqi@0 335 which_stack_index = which;
aoqi@0 336 assert(manager->active_workers() == ParallelGCThreads,
aoqi@0 337 err_msg("all_workers_active has been incorrectly set: "
aoqi@0 338 " active %d ParallelGCThreads %d", manager->active_workers(),
aoqi@0 339 ParallelGCThreads));
aoqi@0 340 } else {
aoqi@0 341 which_stack_index = stack_index();
aoqi@0 342 }
aoqi@0 343
aoqi@0 344 cm->set_region_stack(ParCompactionManager::region_list(which_stack_index));
aoqi@0 345 if (TraceDynamicGCThreads) {
aoqi@0 346 gclog_or_tty->print_cr("DrainStacksCompactionTask::do_it which = %d "
aoqi@0 347 "which_stack_index = %d/empty(%d) "
aoqi@0 348 "use all workers %d",
aoqi@0 349 which, which_stack_index,
aoqi@0 350 cm->region_stack()->is_empty(),
aoqi@0 351 use_all_workers);
aoqi@0 352 }
aoqi@0 353
aoqi@0 354 cm->set_region_stack_index(which_stack_index);
aoqi@0 355
aoqi@0 356 // Process any regions already in the compaction managers stacks.
aoqi@0 357 cm->drain_region_stacks();
aoqi@0 358
aoqi@0 359 assert(cm->region_stack()->is_empty(), "Not empty");
aoqi@0 360
aoqi@0 361 if (!use_all_workers) {
aoqi@0 362 // Always give up the region stack.
aoqi@0 363 assert(cm->region_stack() ==
aoqi@0 364 ParCompactionManager::region_list(cm->region_stack_index()),
aoqi@0 365 "region_stack and region_stack_index are inconsistent");
aoqi@0 366 ParCompactionManager::push_recycled_stack_index(cm->region_stack_index());
aoqi@0 367
aoqi@0 368 if (TraceDynamicGCThreads) {
aoqi@0 369 void* old_region_stack = (void*) cm->region_stack();
aoqi@0 370 int old_region_stack_index = cm->region_stack_index();
aoqi@0 371 gclog_or_tty->print_cr("Pushing region stack 0x%x/%d",
aoqi@0 372 old_region_stack, old_region_stack_index);
aoqi@0 373 }
aoqi@0 374
aoqi@0 375 cm->set_region_stack(NULL);
aoqi@0 376 cm->set_region_stack_index((uint)max_uintx);
aoqi@0 377 }
aoqi@0 378 }

mercurial