1/*
2 * Copyright (c) 2005, 2016, 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 "aot/aotLoader.hpp"
27#include "classfile/systemDictionary.hpp"
28#include "code/codeCache.hpp"
29#include "gc/parallel/parallelScavengeHeap.hpp"
30#include "gc/parallel/pcTasks.hpp"
31#include "gc/parallel/psCompactionManager.inline.hpp"
32#include "gc/parallel/psParallelCompact.hpp"
33#include "gc/shared/collectedHeap.hpp"
34#include "gc/shared/gcTimer.hpp"
35#include "gc/shared/gcTraceTime.inline.hpp"
36#include "logging/log.hpp"
37#include "memory/resourceArea.hpp"
38#include "memory/universe.hpp"
39#include "oops/objArrayKlass.inline.hpp"
40#include "oops/oop.inline.hpp"
41#include "prims/jvmtiExport.hpp"
42#include "runtime/fprofiler.hpp"
43#include "runtime/jniHandles.hpp"
44#include "runtime/thread.hpp"
45#include "runtime/vmThread.hpp"
46#include "services/management.hpp"
47#include "utilities/stack.inline.hpp"
48
49//
50// ThreadRootsMarkingTask
51//
52
53void ThreadRootsMarkingTask::do_it(GCTaskManager* manager, uint which) {
54  assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
55
56  ResourceMark rm;
57
58  ParCompactionManager* cm =
59    ParCompactionManager::gc_thread_compaction_manager(which);
60
61  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
62  MarkingCodeBlobClosure mark_and_push_in_blobs(&mark_and_push_closure, !CodeBlobToOopClosure::FixRelocations);
63
64  if (_java_thread != NULL)
65    _java_thread->oops_do(
66        &mark_and_push_closure,
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_in_blobs);
73
74  // Do the real work
75  cm->follow_marking_stacks();
76}
77
78
79void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
80  assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
81
82  ParCompactionManager* cm =
83    ParCompactionManager::gc_thread_compaction_manager(which);
84  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
85  ParCompactionManager::FollowKlassClosure follow_klass_closure(&mark_and_push_closure);
86
87  switch (_root_type) {
88    case universe:
89      Universe::oops_do(&mark_and_push_closure);
90      break;
91
92    case jni_handles:
93      JNIHandles::oops_do(&mark_and_push_closure);
94      break;
95
96    case threads:
97    {
98      ResourceMark rm;
99      MarkingCodeBlobClosure each_active_code_blob(&mark_and_push_closure, !CodeBlobToOopClosure::FixRelocations);
100      Threads::oops_do(&mark_and_push_closure, &each_active_code_blob);
101    }
102    break;
103
104    case object_synchronizer:
105      ObjectSynchronizer::oops_do(&mark_and_push_closure);
106      break;
107
108    case flat_profiler:
109      FlatProfiler::oops_do(&mark_and_push_closure);
110      break;
111
112    case management:
113      Management::oops_do(&mark_and_push_closure);
114      break;
115
116    case jvmti:
117      JvmtiExport::oops_do(&mark_and_push_closure);
118      break;
119
120    case system_dictionary:
121      SystemDictionary::always_strong_oops_do(&mark_and_push_closure);
122      break;
123
124    case class_loader_data:
125      ClassLoaderDataGraph::always_strong_oops_do(&mark_and_push_closure, &follow_klass_closure, true);
126      break;
127
128    case code_cache:
129      // Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
130      //CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(&mark_and_push_closure));
131      AOTLoader::oops_do(&mark_and_push_closure);
132      break;
133
134    default:
135      fatal("Unknown root type");
136  }
137
138  // Do the real work
139  cm->follow_marking_stacks();
140}
141
142
143//
144// RefProcTaskProxy
145//
146
147void RefProcTaskProxy::do_it(GCTaskManager* manager, uint which)
148{
149  assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
150
151  ParCompactionManager* cm =
152    ParCompactionManager::gc_thread_compaction_manager(which);
153  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
154  ParCompactionManager::FollowStackClosure follow_stack_closure(cm);
155  _rp_task.work(_work_id, *PSParallelCompact::is_alive_closure(),
156                mark_and_push_closure, follow_stack_closure);
157}
158
159//
160// RefProcTaskExecutor
161//
162
163void RefProcTaskExecutor::execute(ProcessTask& task)
164{
165  ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
166  uint parallel_gc_threads = heap->gc_task_manager()->workers();
167  uint active_gc_threads = heap->gc_task_manager()->active_workers();
168  OopTaskQueueSet* qset = ParCompactionManager::stack_array();
169  ParallelTaskTerminator terminator(active_gc_threads, qset);
170  GCTaskQueue* q = GCTaskQueue::create();
171  for(uint i=0; i<parallel_gc_threads; i++) {
172    q->enqueue(new RefProcTaskProxy(task, i));
173  }
174  if (task.marks_oops_alive()) {
175    if (parallel_gc_threads>1) {
176      for (uint j=0; j<active_gc_threads; j++) {
177        q->enqueue(new StealMarkingTask(&terminator));
178      }
179    }
180  }
181  PSParallelCompact::gc_task_manager()->execute_and_wait(q);
182}
183
184void RefProcTaskExecutor::execute(EnqueueTask& task)
185{
186  ParallelScavengeHeap* heap = ParallelScavengeHeap::heap();
187  uint parallel_gc_threads = heap->gc_task_manager()->workers();
188  GCTaskQueue* q = GCTaskQueue::create();
189  for(uint i=0; i<parallel_gc_threads; i++) {
190    q->enqueue(new RefEnqueueTaskProxy(task, i));
191  }
192  PSParallelCompact::gc_task_manager()->execute_and_wait(q);
193}
194
195//
196// StealMarkingTask
197//
198
199StealMarkingTask::StealMarkingTask(ParallelTaskTerminator* t) :
200  _terminator(t) {}
201
202void StealMarkingTask::do_it(GCTaskManager* manager, uint which) {
203  assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
204
205  ParCompactionManager* cm =
206    ParCompactionManager::gc_thread_compaction_manager(which);
207  ParCompactionManager::MarkAndPushClosure mark_and_push_closure(cm);
208
209  oop obj = NULL;
210  ObjArrayTask task;
211  int random_seed = 17;
212  do {
213    while (ParCompactionManager::steal_objarray(which, &random_seed, task)) {
214      cm->follow_contents((objArrayOop)task.obj(), task.index());
215      cm->follow_marking_stacks();
216    }
217    while (ParCompactionManager::steal(which, &random_seed, obj)) {
218      cm->follow_contents(obj);
219      cm->follow_marking_stacks();
220    }
221  } while (!terminator()->offer_termination());
222}
223
224//
225// CompactionWithStealingTask
226//
227
228CompactionWithStealingTask::CompactionWithStealingTask(ParallelTaskTerminator* t):
229  _terminator(t) {}
230
231void CompactionWithStealingTask::do_it(GCTaskManager* manager, uint which) {
232  assert(ParallelScavengeHeap::heap()->is_gc_active(), "called outside gc");
233
234  ParCompactionManager* cm =
235    ParCompactionManager::gc_thread_compaction_manager(which);
236
237  // Drain the stacks that have been preloaded with regions
238  // that are ready to fill.
239
240  cm->drain_region_stacks();
241
242  guarantee(cm->region_stack()->is_empty(), "Not empty");
243
244  size_t region_index = 0;
245  int random_seed = 17;
246
247  while(true) {
248    if (ParCompactionManager::steal(which, &random_seed, region_index)) {
249      PSParallelCompact::fill_and_update_region(cm, region_index);
250      cm->drain_region_stacks();
251    } else {
252      if (terminator()->offer_termination()) {
253        break;
254      }
255      // Go around again.
256    }
257  }
258  return;
259}
260
261UpdateDensePrefixTask::UpdateDensePrefixTask(
262                                   PSParallelCompact::SpaceId space_id,
263                                   size_t region_index_start,
264                                   size_t region_index_end) :
265  _space_id(space_id), _region_index_start(region_index_start),
266  _region_index_end(region_index_end) {}
267
268void UpdateDensePrefixTask::do_it(GCTaskManager* manager, uint which) {
269
270  ParCompactionManager* cm =
271    ParCompactionManager::gc_thread_compaction_manager(which);
272
273  PSParallelCompact::update_and_deadwood_in_dense_prefix(cm,
274                                                         _space_id,
275                                                         _region_index_start,
276                                                         _region_index_end);
277}
278