1 /*
2  * Copyright (c) 2018, 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 #ifndef SHARE_VM_GC_SHARED_WEAKPROCESSOR_INLINE_HPP
26 #define SHARE_VM_GC_SHARED_WEAKPROCESSOR_INLINE_HPP
27 
28 #include "gc/shared/oopStorage.inline.hpp"
29 #include "gc/shared/oopStorageParState.inline.hpp"
30 #include "gc/shared/weakProcessor.hpp"
31 #include "gc/shared/weakProcessorPhases.hpp"
32 #include "gc/shared/weakProcessorPhaseTimes.hpp"
33 #include "gc/shared/workgroup.hpp"
34 #include "utilities/debug.hpp"
35 
36 class BoolObjectClosure;
37 class OopClosure;
38 
39 template<typename IsAlive, typename KeepAlive>
work(uint worker_id,IsAlive * is_alive,KeepAlive * keep_alive)40 void WeakProcessor::Task::work(uint worker_id,
41                                IsAlive* is_alive,
42                                KeepAlive* keep_alive) {
43   assert(worker_id < _nworkers,
44          "worker_id (%u) exceeds task's configured workers (%u)",
45          worker_id, _nworkers);
46 
47   FOR_EACH_WEAK_PROCESSOR_PHASE(phase) {
48     if (WeakProcessorPhases::is_serial(phase)) {
49       uint serial_index = WeakProcessorPhases::serial_index(phase);
50       if (_serial_phases_done.try_claim_task(serial_index)) {
51         WeakProcessorPhaseTimeTracker pt(_phase_times, phase);
52         WeakProcessorPhases::processor(phase)(is_alive, keep_alive);
53       }
54     } else {
55       WeakProcessorPhaseTimeTracker pt(_phase_times, phase, worker_id);
56       uint storage_index = WeakProcessorPhases::oop_storage_index(phase);
57       _storage_states[storage_index].weak_oops_do(is_alive, keep_alive);
58     }
59   }
60 
61   _serial_phases_done.all_tasks_completed(_nworkers);
62 }
63 
64 class WeakProcessor::GangTask : public AbstractGangTask {
65   Task _task;
66   BoolObjectClosure* _is_alive;
67   OopClosure* _keep_alive;
68   void (*_erased_do_work)(GangTask* task, uint worker_id);
69 
70   template<typename IsAlive, typename KeepAlive>
erased_do_work(GangTask * task,uint worker_id)71   static void erased_do_work(GangTask* task, uint worker_id) {
72     task->_task.work(worker_id,
73                      static_cast<IsAlive*>(task->_is_alive),
74                      static_cast<KeepAlive*>(task->_keep_alive));
75   }
76 
77 public:
78   template<typename IsAlive, typename KeepAlive>
GangTask(const char * name,IsAlive * is_alive,KeepAlive * keep_alive,WeakProcessorPhaseTimes * phase_times,uint nworkers)79   GangTask(const char* name,
80            IsAlive* is_alive,
81            KeepAlive* keep_alive,
82            WeakProcessorPhaseTimes* phase_times,
83            uint nworkers) :
84     AbstractGangTask(name),
85     _task(phase_times, nworkers),
86     _is_alive(is_alive),
87     _keep_alive(keep_alive),
88     _erased_do_work(&erased_do_work<IsAlive, KeepAlive>)
89   {}
90 
91   virtual void work(uint worker_id);
92 };
93 
94 template<typename IsAlive, typename KeepAlive>
weak_oops_do(WorkGang * workers,IsAlive * is_alive,KeepAlive * keep_alive,WeakProcessorPhaseTimes * phase_times)95 void WeakProcessor::weak_oops_do(WorkGang* workers,
96                                  IsAlive* is_alive,
97                                  KeepAlive* keep_alive,
98                                  WeakProcessorPhaseTimes* phase_times) {
99   WeakProcessorTimeTracker tt(phase_times);
100 
101   uint nworkers = ergo_workers(MIN2(workers->active_workers(),
102                                     phase_times->max_threads()));
103 
104   GangTask task("Weak Processor", is_alive, keep_alive, phase_times, nworkers);
105   workers->run_task(&task, nworkers);
106 }
107 
108 template<typename IsAlive, typename KeepAlive>
weak_oops_do(WorkGang * workers,IsAlive * is_alive,KeepAlive * keep_alive,uint indent_log)109 void WeakProcessor::weak_oops_do(WorkGang* workers,
110                                  IsAlive* is_alive,
111                                  KeepAlive* keep_alive,
112                                  uint indent_log) {
113   uint nworkers = ergo_workers(workers->active_workers());
114   WeakProcessorPhaseTimes pt(nworkers);
115   weak_oops_do(workers, is_alive, keep_alive, &pt);
116   pt.log_print_phases(indent_log);
117 }
118 
119 #endif // SHARE_VM_GC_SHARED_WEAKPROCESSOR_INLINE_HPP
120