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