|
1 /* |
|
2 * Copyright 2005-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 |
|
26 // Tasks for parallel compaction of the old generation |
|
27 // |
|
28 // Tasks are created and enqueued on a task queue. The |
|
29 // tasks for parallel old collector for marking objects |
|
30 // are MarkFromRootsTask and ThreadRootsMarkingTask. |
|
31 // |
|
32 // MarkFromRootsTask's are created |
|
33 // with a root group (e.g., jni_handles) and when the do_it() |
|
34 // method of a MarkFromRootsTask is executed, it starts marking |
|
35 // form it's root group. |
|
36 // |
|
37 // ThreadRootsMarkingTask's are created for each Java thread. When |
|
38 // the do_it() method of a ThreadRootsMarkingTask is executed, it |
|
39 // starts marking from the thread's roots. |
|
40 // |
|
41 // The enqueuing of the MarkFromRootsTask and ThreadRootsMarkingTask |
|
42 // do little more than create the task and put it on a queue. The |
|
43 // queue is a GCTaskQueue and threads steal tasks from this GCTaskQueue. |
|
44 // |
|
45 // In addition to the MarkFromRootsTask and ThreadRootsMarkingTask |
|
46 // tasks there are StealMarkingTask tasks. The StealMarkingTask's |
|
47 // steal a reference from the marking stack of another |
|
48 // thread and transitively marks the object of the reference |
|
49 // and internal references. After successfully stealing a reference |
|
50 // and marking it, the StealMarkingTask drains its marking stack |
|
51 // stack before attempting another steal. |
|
52 // |
|
53 // ThreadRootsMarkingTask |
|
54 // |
|
55 // This task marks from the roots of a single thread. This task |
|
56 // enables marking of thread roots in parallel. |
|
57 // |
|
58 |
|
59 class ParallelTaskTerminator; |
|
60 |
|
61 class ThreadRootsMarkingTask : public GCTask { |
|
62 private: |
|
63 JavaThread* _java_thread; |
|
64 VMThread* _vm_thread; |
|
65 public: |
|
66 ThreadRootsMarkingTask(JavaThread* root) : _java_thread(root), _vm_thread(NULL) {} |
|
67 ThreadRootsMarkingTask(VMThread* root) : _java_thread(NULL), _vm_thread(root) {} |
|
68 |
|
69 char* name() { return (char *)"thread-roots-marking-task"; } |
|
70 |
|
71 virtual void do_it(GCTaskManager* manager, uint which); |
|
72 }; |
|
73 |
|
74 |
|
75 // |
|
76 // MarkFromRootsTask |
|
77 // |
|
78 // This task marks from all the roots to all live |
|
79 // objects. |
|
80 // |
|
81 // |
|
82 |
|
83 class MarkFromRootsTask : public GCTask { |
|
84 public: |
|
85 enum RootType { |
|
86 universe = 1, |
|
87 jni_handles = 2, |
|
88 threads = 3, |
|
89 object_synchronizer = 4, |
|
90 flat_profiler = 5, |
|
91 management = 6, |
|
92 jvmti = 7, |
|
93 system_dictionary = 8, |
|
94 vm_symbols = 9, |
|
95 reference_processing = 10 |
|
96 }; |
|
97 private: |
|
98 RootType _root_type; |
|
99 public: |
|
100 MarkFromRootsTask(RootType value) : _root_type(value) {} |
|
101 |
|
102 char* name() { return (char *)"mark-from-roots-task"; } |
|
103 |
|
104 virtual void do_it(GCTaskManager* manager, uint which); |
|
105 }; |
|
106 |
|
107 // |
|
108 // RefProcTaskProxy |
|
109 // |
|
110 // This task is used as a proxy to parallel reference processing tasks . |
|
111 // |
|
112 |
|
113 class RefProcTaskProxy : public GCTask { |
|
114 typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; |
|
115 ProcessTask & _rp_task; |
|
116 uint _work_id; |
|
117 public: |
|
118 RefProcTaskProxy(ProcessTask & rp_task, uint work_id) |
|
119 : _rp_task(rp_task), |
|
120 _work_id(work_id) |
|
121 { } |
|
122 |
|
123 private: |
|
124 virtual char* name() { return (char *)"Process referents by policy in parallel"; } |
|
125 |
|
126 virtual void do_it(GCTaskManager* manager, uint which); |
|
127 }; |
|
128 |
|
129 |
|
130 |
|
131 // |
|
132 // RefEnqueueTaskProxy |
|
133 // |
|
134 // This task is used as a proxy to parallel reference processing tasks . |
|
135 // |
|
136 |
|
137 class RefEnqueueTaskProxy: public GCTask { |
|
138 typedef AbstractRefProcTaskExecutor::EnqueueTask EnqueueTask; |
|
139 EnqueueTask& _enq_task; |
|
140 uint _work_id; |
|
141 |
|
142 public: |
|
143 RefEnqueueTaskProxy(EnqueueTask& enq_task, uint work_id) |
|
144 : _enq_task(enq_task), |
|
145 _work_id(work_id) |
|
146 { } |
|
147 |
|
148 virtual char* name() { return (char *)"Enqueue reference objects in parallel"; } |
|
149 virtual void do_it(GCTaskManager* manager, uint which) |
|
150 { |
|
151 _enq_task.work(_work_id); |
|
152 } |
|
153 }; |
|
154 |
|
155 |
|
156 // |
|
157 // RefProcTaskExecutor |
|
158 // |
|
159 // Task executor is an interface for the reference processor to run |
|
160 // tasks using GCTaskManager. |
|
161 // |
|
162 |
|
163 class RefProcTaskExecutor: public AbstractRefProcTaskExecutor { |
|
164 virtual void execute(ProcessTask& task); |
|
165 virtual void execute(EnqueueTask& task); |
|
166 }; |
|
167 |
|
168 |
|
169 // |
|
170 // StealMarkingTask |
|
171 // |
|
172 // This task is used to distribute work to idle threads. |
|
173 // |
|
174 |
|
175 class StealMarkingTask : public GCTask { |
|
176 private: |
|
177 ParallelTaskTerminator* const _terminator; |
|
178 private: |
|
179 |
|
180 public: |
|
181 char* name() { return (char *)"steal-marking-task"; } |
|
182 |
|
183 StealMarkingTask(ParallelTaskTerminator* t); |
|
184 |
|
185 ParallelTaskTerminator* terminator() { return _terminator; } |
|
186 |
|
187 virtual void do_it(GCTaskManager* manager, uint which); |
|
188 }; |
|
189 |
|
190 // |
|
191 // StealChunkCompactionTask |
|
192 // |
|
193 // This task is used to distribute work to idle threads. |
|
194 // |
|
195 |
|
196 class StealChunkCompactionTask : public GCTask { |
|
197 private: |
|
198 ParallelTaskTerminator* const _terminator; |
|
199 public: |
|
200 StealChunkCompactionTask(ParallelTaskTerminator* t); |
|
201 |
|
202 char* name() { return (char *)"steal-chunk-task"; } |
|
203 ParallelTaskTerminator* terminator() { return _terminator; } |
|
204 |
|
205 virtual void do_it(GCTaskManager* manager, uint which); |
|
206 }; |
|
207 |
|
208 // |
|
209 // UpdateDensePrefixTask |
|
210 // |
|
211 // This task is used to update the dense prefix |
|
212 // of a space. |
|
213 // |
|
214 |
|
215 class UpdateDensePrefixTask : public GCTask { |
|
216 private: |
|
217 PSParallelCompact::SpaceId _space_id; |
|
218 size_t _chunk_index_start; |
|
219 size_t _chunk_index_end; |
|
220 |
|
221 public: |
|
222 char* name() { return (char *)"update-dense_prefix-task"; } |
|
223 |
|
224 UpdateDensePrefixTask(PSParallelCompact::SpaceId space_id, |
|
225 size_t chunk_index_start, |
|
226 size_t chunk_index_end); |
|
227 |
|
228 virtual void do_it(GCTaskManager* manager, uint which); |
|
229 }; |
|
230 |
|
231 // |
|
232 // DrainStacksCompactionTask |
|
233 // |
|
234 // This task processes chunks that have been added to the stacks of each |
|
235 // compaction manager. |
|
236 // |
|
237 // Trying to use one draining thread does not work because there are no |
|
238 // guarantees about which task will be picked up by which thread. For example, |
|
239 // if thread A gets all the preloaded chunks, thread A may not get a draining |
|
240 // task (they may all be done by other threads). |
|
241 // |
|
242 |
|
243 class DrainStacksCompactionTask : public GCTask { |
|
244 public: |
|
245 char* name() { return (char *)"drain-chunk-task"; } |
|
246 virtual void do_it(GCTaskManager* manager, uint which); |
|
247 }; |