Thu, 12 Jun 2008 13:50:55 -0700
Merge
1 /*
2 * Copyright 2000-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 */
25 # include "incls/_precompiled.incl"
26 # include "incls/_sharedHeap.cpp.incl"
28 SharedHeap* SharedHeap::_sh;
30 // The set of potentially parallel tasks in strong root scanning.
31 enum SH_process_strong_roots_tasks {
32 SH_PS_Universe_oops_do,
33 SH_PS_JNIHandles_oops_do,
34 SH_PS_ObjectSynchronizer_oops_do,
35 SH_PS_FlatProfiler_oops_do,
36 SH_PS_Management_oops_do,
37 SH_PS_SystemDictionary_oops_do,
38 SH_PS_jvmti_oops_do,
39 SH_PS_vmSymbols_oops_do,
40 SH_PS_SymbolTable_oops_do,
41 SH_PS_StringTable_oops_do,
42 SH_PS_CodeCache_oops_do,
43 // Leave this one last.
44 SH_PS_NumElements
45 };
47 SharedHeap::SharedHeap(CollectorPolicy* policy_) :
48 CollectedHeap(),
49 _collector_policy(policy_),
50 _perm_gen(NULL), _rem_set(NULL),
51 _strong_roots_parity(0),
52 _process_strong_tasks(new SubTasksDone(SH_PS_NumElements)),
53 _workers(NULL), _n_par_threads(0)
54 {
55 if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) {
56 vm_exit_during_initialization("Failed necessary allocation.");
57 }
58 _sh = this; // ch is static, should be set only once.
59 if ((UseParNewGC ||
60 (UseConcMarkSweepGC && CMSParallelRemarkEnabled) ||
61 UseG1GC) &&
62 ParallelGCThreads > 0) {
63 _workers = new WorkGang("Parallel GC Threads", ParallelGCThreads,
64 /* are_GC_task_threads */true,
65 /* are_ConcurrentGC_threads */false);
66 if (_workers == NULL) {
67 vm_exit_during_initialization("Failed necessary allocation.");
68 }
69 }
70 }
72 bool SharedHeap::heap_lock_held_for_gc() {
73 Thread* t = Thread::current();
74 return Heap_lock->owned_by_self()
75 || ( (t->is_GC_task_thread() || t->is_VM_thread())
76 && _thread_holds_heap_lock_for_gc);
77 }
79 void SharedHeap::set_par_threads(int t) {
80 _n_par_threads = t;
81 _process_strong_tasks->set_par_threads(t);
82 }
84 class AssertIsPermClosure: public OopClosure {
85 public:
86 virtual void do_oop(oop* p) {
87 assert((*p) == NULL || (*p)->is_perm(), "Referent should be perm.");
88 }
89 virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
90 };
91 static AssertIsPermClosure assert_is_perm_closure;
93 void SharedHeap::change_strong_roots_parity() {
94 // Also set the new collection parity.
95 assert(_strong_roots_parity >= 0 && _strong_roots_parity <= 2,
96 "Not in range.");
97 _strong_roots_parity++;
98 if (_strong_roots_parity == 3) _strong_roots_parity = 1;
99 assert(_strong_roots_parity >= 1 && _strong_roots_parity <= 2,
100 "Not in range.");
101 }
103 void SharedHeap::process_strong_roots(bool collecting_perm_gen,
104 ScanningOption so,
105 OopClosure* roots,
106 OopsInGenClosure* perm_blk) {
107 // General strong roots.
108 if (n_par_threads() == 0) change_strong_roots_parity();
109 if (!_process_strong_tasks->is_task_claimed(SH_PS_Universe_oops_do)) {
110 Universe::oops_do(roots);
111 ReferenceProcessor::oops_do(roots);
112 // Consider perm-gen discovered lists to be strong.
113 perm_gen()->ref_processor()->weak_oops_do(roots);
114 }
115 // Global (strong) JNI handles
116 if (!_process_strong_tasks->is_task_claimed(SH_PS_JNIHandles_oops_do))
117 JNIHandles::oops_do(roots);
118 // All threads execute this; the individual threads are task groups.
119 if (ParallelGCThreads > 0) {
120 Threads::possibly_parallel_oops_do(roots);
121 } else {
122 Threads::oops_do(roots);
123 }
124 if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do))
125 ObjectSynchronizer::oops_do(roots);
126 if (!_process_strong_tasks->is_task_claimed(SH_PS_FlatProfiler_oops_do))
127 FlatProfiler::oops_do(roots);
128 if (!_process_strong_tasks->is_task_claimed(SH_PS_Management_oops_do))
129 Management::oops_do(roots);
130 if (!_process_strong_tasks->is_task_claimed(SH_PS_jvmti_oops_do))
131 JvmtiExport::oops_do(roots);
133 if (!_process_strong_tasks->is_task_claimed(SH_PS_SystemDictionary_oops_do)) {
134 if (so & SO_AllClasses) {
135 SystemDictionary::oops_do(roots);
136 } else
137 if (so & SO_SystemClasses) {
138 SystemDictionary::always_strong_oops_do(roots);
139 }
140 }
142 if (!_process_strong_tasks->is_task_claimed(SH_PS_SymbolTable_oops_do)) {
143 if (so & SO_Symbols) {
144 SymbolTable::oops_do(roots);
145 }
146 // Verify if the symbol table contents are in the perm gen
147 NOT_PRODUCT(SymbolTable::oops_do(&assert_is_perm_closure));
148 }
150 if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) {
151 if (so & SO_Strings) {
152 StringTable::oops_do(roots);
153 }
154 // Verify if the string table contents are in the perm gen
155 NOT_PRODUCT(StringTable::oops_do(&assert_is_perm_closure));
156 }
158 if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) {
159 if (so & SO_CodeCache) {
160 CodeCache::oops_do(roots);
161 }
162 // Verify if the code cache contents are in the perm gen
163 NOT_PRODUCT(CodeCache::oops_do(&assert_is_perm_closure));
164 }
166 // Roots that should point only into permanent generation.
167 {
168 OopClosure* blk = NULL;
169 if (collecting_perm_gen) {
170 blk = roots;
171 } else {
172 debug_only(blk = &assert_is_perm_closure);
173 }
174 if (blk != NULL) {
175 if (!_process_strong_tasks->is_task_claimed(SH_PS_vmSymbols_oops_do))
176 vmSymbols::oops_do(blk);
177 }
178 }
180 if (!collecting_perm_gen) {
181 // All threads perform this; coordination is handled internally.
183 rem_set()->younger_refs_iterate(perm_gen(), perm_blk);
184 }
185 _process_strong_tasks->all_tasks_completed();
186 }
188 class AlwaysTrueClosure: public BoolObjectClosure {
189 public:
190 void do_object(oop p) { ShouldNotReachHere(); }
191 bool do_object_b(oop p) { return true; }
192 };
193 static AlwaysTrueClosure always_true;
195 class SkipAdjustingSharedStrings: public OopClosure {
196 OopClosure* _clo;
197 public:
198 SkipAdjustingSharedStrings(OopClosure* clo) : _clo(clo) {}
200 virtual void do_oop(oop* p) {
201 oop o = (*p);
202 if (!o->is_shared_readwrite()) {
203 _clo->do_oop(p);
204 }
205 }
206 virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
207 };
209 // Unmarked shared Strings in the StringTable (which got there due to
210 // being in the constant pools of as-yet unloaded shared classes) were
211 // not marked and therefore did not have their mark words preserved.
212 // These entries are also deliberately not purged from the string
213 // table during unloading of unmarked strings. If an identity hash
214 // code was computed for any of these objects, it will not have been
215 // cleared to zero during the forwarding process or by the
216 // RecursiveAdjustSharedObjectClosure, and will be confused by the
217 // adjusting process as a forwarding pointer. We need to skip
218 // forwarding StringTable entries which contain unmarked shared
219 // Strings. Actually, since shared strings won't be moving, we can
220 // just skip adjusting any shared entries in the string table.
222 void SharedHeap::process_weak_roots(OopClosure* root_closure,
223 OopClosure* non_root_closure) {
224 // Global (weak) JNI handles
225 JNIHandles::weak_oops_do(&always_true, root_closure);
227 CodeCache::oops_do(non_root_closure);
228 SymbolTable::oops_do(root_closure);
229 if (UseSharedSpaces && !DumpSharedSpaces) {
230 SkipAdjustingSharedStrings skip_closure(root_closure);
231 StringTable::oops_do(&skip_closure);
232 } else {
233 StringTable::oops_do(root_closure);
234 }
235 }
237 void SharedHeap::set_barrier_set(BarrierSet* bs) {
238 _barrier_set = bs;
239 // Cached barrier set for fast access in oops
240 oopDesc::set_bs(bs);
241 }
243 void SharedHeap::post_initialize() {
244 ref_processing_init();
245 }
247 void SharedHeap::ref_processing_init() {
248 perm_gen()->ref_processor_init();
249 }
251 void SharedHeap::fill_region_with_object(MemRegion mr) {
252 // Disable the posting of JVMTI VMObjectAlloc events as we
253 // don't want the filling of tlabs with filler arrays to be
254 // reported to the profiler.
255 NoJvmtiVMObjectAllocMark njm;
257 // Disable low memory detector because there is no real allocation.
258 LowMemoryDetectorDisabler lmd_dis;
260 // It turns out that post_allocation_setup_array takes a handle, so the
261 // call below contains an implicit conversion. Best to free that handle
262 // as soon as possible.
263 HandleMark hm;
265 size_t word_size = mr.word_size();
266 size_t aligned_array_header_size =
267 align_object_size(typeArrayOopDesc::header_size(T_INT));
269 if (word_size >= aligned_array_header_size) {
270 const size_t array_length =
271 pointer_delta(mr.end(), mr.start()) -
272 typeArrayOopDesc::header_size(T_INT);
273 const size_t array_length_words =
274 array_length * (HeapWordSize/sizeof(jint));
275 post_allocation_setup_array(Universe::intArrayKlassObj(),
276 mr.start(),
277 mr.word_size(),
278 (int)array_length_words);
279 #ifdef ASSERT
280 HeapWord* elt_words = (mr.start() + typeArrayOopDesc::header_size(T_INT));
281 Copy::fill_to_words(elt_words, array_length, 0xDEAFBABE);
282 #endif
283 } else {
284 assert(word_size == (size_t)oopDesc::header_size(), "Unaligned?");
285 post_allocation_setup_obj(SystemDictionary::object_klass(),
286 mr.start(),
287 mr.word_size());
288 }
289 }
291 // Some utilities.
292 void SharedHeap::print_size_transition(outputStream* out,
293 size_t bytes_before,
294 size_t bytes_after,
295 size_t capacity) {
296 out->print(" %d%s->%d%s(%d%s)",
297 byte_size_in_proper_unit(bytes_before),
298 proper_unit_for_byte_size(bytes_before),
299 byte_size_in_proper_unit(bytes_after),
300 proper_unit_for_byte_size(bytes_after),
301 byte_size_in_proper_unit(capacity),
302 proper_unit_for_byte_size(capacity));
303 }