Mercurial > hg > truffle
comparison src/share/vm/memory/sharedHeap.cpp @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | 441e946dc1af |
children | d0aa87f04bd5 |
comparison
equal
deleted
inserted
replaced
6724:36d1d483d5d6 | 6725:da91efe96a93 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
53 }; | 53 }; |
54 | 54 |
55 SharedHeap::SharedHeap(CollectorPolicy* policy_) : | 55 SharedHeap::SharedHeap(CollectorPolicy* policy_) : |
56 CollectedHeap(), | 56 CollectedHeap(), |
57 _collector_policy(policy_), | 57 _collector_policy(policy_), |
58 _perm_gen(NULL), _rem_set(NULL), | 58 _rem_set(NULL), |
59 _strong_roots_parity(0), | 59 _strong_roots_parity(0), |
60 _process_strong_tasks(new SubTasksDone(SH_PS_NumElements)), | 60 _process_strong_tasks(new SubTasksDone(SH_PS_NumElements)), |
61 _workers(NULL) | 61 _workers(NULL) |
62 { | 62 { |
63 if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) { | 63 if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) { |
98 assert(t == 0 || !UseSerialGC, "Cannot have parallel threads"); | 98 assert(t == 0 || !UseSerialGC, "Cannot have parallel threads"); |
99 _n_par_threads = t; | 99 _n_par_threads = t; |
100 _process_strong_tasks->set_n_threads(t); | 100 _process_strong_tasks->set_n_threads(t); |
101 } | 101 } |
102 | 102 |
103 class AssertIsPermClosure: public OopClosure { | |
104 public: | |
105 virtual void do_oop(oop* p) { | |
106 assert((*p) == NULL || (*p)->is_perm(), "Referent should be perm."); | |
107 } | |
108 virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } | |
109 }; | |
110 static AssertIsPermClosure assert_is_perm_closure; | |
111 | |
112 #ifdef ASSERT | 103 #ifdef ASSERT |
113 class AssertNonScavengableClosure: public OopClosure { | 104 class AssertNonScavengableClosure: public OopClosure { |
114 public: | 105 public: |
115 virtual void do_oop(oop* p) { | 106 virtual void do_oop(oop* p) { |
116 assert(!Universe::heap()->is_in_partial_collection(*p), | 107 assert(!Universe::heap()->is_in_partial_collection(*p), |
141 SharedHeap::StrongRootsScope::~StrongRootsScope() { | 132 SharedHeap::StrongRootsScope::~StrongRootsScope() { |
142 // nothing particular | 133 // nothing particular |
143 } | 134 } |
144 | 135 |
145 void SharedHeap::process_strong_roots(bool activate_scope, | 136 void SharedHeap::process_strong_roots(bool activate_scope, |
146 bool collecting_perm_gen, | 137 bool is_scavenging, |
147 ScanningOption so, | 138 ScanningOption so, |
148 OopClosure* roots, | 139 OopClosure* roots, |
149 CodeBlobClosure* code_roots, | 140 CodeBlobClosure* code_roots, |
150 OopsInGenClosure* perm_blk) { | 141 KlassClosure* klass_closure) { |
151 StrongRootsScope srs(this, activate_scope); | 142 StrongRootsScope srs(this, activate_scope); |
143 | |
152 // General strong roots. | 144 // General strong roots. |
153 assert(_strong_roots_parity != 0, "must have called prologue code"); | 145 assert(_strong_roots_parity != 0, "must have called prologue code"); |
154 // _n_termination for _process_strong_tasks should be set up stream | 146 // _n_termination for _process_strong_tasks should be set up stream |
155 // in a method not running in a GC worker. Otherwise the GC worker | 147 // in a method not running in a GC worker. Otherwise the GC worker |
156 // could be trying to change the termination condition while the task | 148 // could be trying to change the termination condition while the task |
157 // is executing in another GC worker. | 149 // is executing in another GC worker. |
158 if (!_process_strong_tasks->is_task_claimed(SH_PS_Universe_oops_do)) { | 150 if (!_process_strong_tasks->is_task_claimed(SH_PS_Universe_oops_do)) { |
159 Universe::oops_do(roots); | 151 Universe::oops_do(roots); |
160 // Consider perm-gen discovered lists to be strong. | |
161 perm_gen()->ref_processor()->weak_oops_do(roots); | |
162 } | 152 } |
163 // Global (strong) JNI handles | 153 // Global (strong) JNI handles |
164 if (!_process_strong_tasks->is_task_claimed(SH_PS_JNIHandles_oops_do)) | 154 if (!_process_strong_tasks->is_task_claimed(SH_PS_JNIHandles_oops_do)) |
165 JNIHandles::oops_do(roots); | 155 JNIHandles::oops_do(roots); |
166 // All threads execute this; the individual threads are task groups. | 156 // All threads execute this; the individual threads are task groups. |
179 JvmtiExport::oops_do(roots); | 169 JvmtiExport::oops_do(roots); |
180 | 170 |
181 if (!_process_strong_tasks->is_task_claimed(SH_PS_SystemDictionary_oops_do)) { | 171 if (!_process_strong_tasks->is_task_claimed(SH_PS_SystemDictionary_oops_do)) { |
182 if (so & SO_AllClasses) { | 172 if (so & SO_AllClasses) { |
183 SystemDictionary::oops_do(roots); | 173 SystemDictionary::oops_do(roots); |
174 ClassLoaderDataGraph::oops_do(roots, klass_closure, !is_scavenging); | |
184 } else if (so & SO_SystemClasses) { | 175 } else if (so & SO_SystemClasses) { |
185 SystemDictionary::always_strong_oops_do(roots); | 176 SystemDictionary::always_strong_oops_do(roots); |
177 ClassLoaderDataGraph::always_strong_oops_do(roots, klass_closure, !is_scavenging); | |
178 } else { | |
179 ShouldNotReachHere2("We should always have selected either SO_AllClasses or SO_SystemClasses"); | |
186 } | 180 } |
187 } | 181 } |
188 | 182 |
189 if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) { | 183 if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) { |
190 if (so & SO_Strings || (!collecting_perm_gen && !JavaObjectsInPerm)) { | 184 if (so & SO_Strings) { |
191 StringTable::oops_do(roots); | 185 StringTable::oops_do(roots); |
192 } | |
193 if (JavaObjectsInPerm) { | |
194 // Verify the string table contents are in the perm gen | |
195 NOT_PRODUCT(StringTable::oops_do(&assert_is_perm_closure)); | |
196 } | 186 } |
197 } | 187 } |
198 | 188 |
199 if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) { | 189 if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) { |
200 if (so & SO_CodeCache) { | 190 if (so & SO_CodeCache) { |
201 // (Currently, CMSCollector uses this to do intermediate-strength collections.) | |
202 assert(collecting_perm_gen, "scanning all of code cache"); | |
203 assert(code_roots != NULL, "must supply closure for code cache"); | 191 assert(code_roots != NULL, "must supply closure for code cache"); |
204 if (code_roots != NULL) { | 192 |
193 if (is_scavenging) { | |
194 // We only visit parts of the CodeCache when scavenging. | |
195 CodeCache::scavenge_root_nmethods_do(code_roots); | |
196 } else { | |
197 // CMSCollector uses this to do intermediate-strength collections. | |
198 // We scan the entire code cache, since CodeCache::do_unloading is not called. | |
205 CodeCache::blobs_do(code_roots); | 199 CodeCache::blobs_do(code_roots); |
206 } | |
207 } else if (so & (SO_SystemClasses|SO_AllClasses)) { | |
208 if (!collecting_perm_gen) { | |
209 // If we are collecting from class statics, but we are not going to | |
210 // visit all of the CodeCache, collect from the non-perm roots if any. | |
211 // This makes the code cache function temporarily as a source of strong | |
212 // roots for oops, until the next major collection. | |
213 // | |
214 // If collecting_perm_gen is true, we require that this phase will call | |
215 // CodeCache::do_unloading. This will kill off nmethods with expired | |
216 // weak references, such as stale invokedynamic targets. | |
217 CodeCache::scavenge_root_nmethods_do(code_roots); | |
218 } | 200 } |
219 } | 201 } |
220 // Verify that the code cache contents are not subject to | 202 // Verify that the code cache contents are not subject to |
221 // movement by a scavenging collection. | 203 // movement by a scavenging collection. |
222 DEBUG_ONLY(CodeBlobToOopClosure assert_code_is_non_scavengable(&assert_is_non_scavengable_closure, /*do_marking=*/ false)); | 204 DEBUG_ONLY(CodeBlobToOopClosure assert_code_is_non_scavengable(&assert_is_non_scavengable_closure, /*do_marking=*/ false)); |
223 DEBUG_ONLY(CodeCache::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable)); | 205 DEBUG_ONLY(CodeCache::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable)); |
224 } | 206 } |
225 | 207 |
226 if (!collecting_perm_gen) { | |
227 // All threads perform this; coordination is handled internally. | |
228 | |
229 rem_set()->younger_refs_iterate(perm_gen(), perm_blk); | |
230 } | |
231 _process_strong_tasks->all_tasks_completed(); | 208 _process_strong_tasks->all_tasks_completed(); |
232 } | 209 } |
233 | 210 |
234 class AlwaysTrueClosure: public BoolObjectClosure { | 211 class AlwaysTrueClosure: public BoolObjectClosure { |
235 public: | 212 public: |
236 void do_object(oop p) { ShouldNotReachHere(); } | 213 void do_object(oop p) { ShouldNotReachHere(); } |
237 bool do_object_b(oop p) { return true; } | 214 bool do_object_b(oop p) { return true; } |
238 }; | 215 }; |
239 static AlwaysTrueClosure always_true; | 216 static AlwaysTrueClosure always_true; |
240 | 217 |
241 class SkipAdjustingSharedStrings: public OopClosure { | |
242 OopClosure* _clo; | |
243 public: | |
244 SkipAdjustingSharedStrings(OopClosure* clo) : _clo(clo) {} | |
245 | |
246 virtual void do_oop(oop* p) { | |
247 oop o = (*p); | |
248 if (!o->is_shared_readwrite()) { | |
249 _clo->do_oop(p); | |
250 } | |
251 } | |
252 virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } | |
253 }; | |
254 | |
255 // Unmarked shared Strings in the StringTable (which got there due to | |
256 // being in the constant pools of as-yet unloaded shared classes) were | |
257 // not marked and therefore did not have their mark words preserved. | |
258 // These entries are also deliberately not purged from the string | |
259 // table during unloading of unmarked strings. If an identity hash | |
260 // code was computed for any of these objects, it will not have been | |
261 // cleared to zero during the forwarding process or by the | |
262 // RecursiveAdjustSharedObjectClosure, and will be confused by the | |
263 // adjusting process as a forwarding pointer. We need to skip | |
264 // forwarding StringTable entries which contain unmarked shared | |
265 // Strings. Actually, since shared strings won't be moving, we can | |
266 // just skip adjusting any shared entries in the string table. | |
267 | |
268 void SharedHeap::process_weak_roots(OopClosure* root_closure, | 218 void SharedHeap::process_weak_roots(OopClosure* root_closure, |
269 CodeBlobClosure* code_roots, | 219 CodeBlobClosure* code_roots, |
270 OopClosure* non_root_closure) { | 220 OopClosure* non_root_closure) { |
271 // Global (weak) JNI handles | 221 // Global (weak) JNI handles |
272 JNIHandles::weak_oops_do(&always_true, root_closure); | 222 JNIHandles::weak_oops_do(&always_true, root_closure); |
273 | 223 |
274 CodeCache::blobs_do(code_roots); | 224 CodeCache::blobs_do(code_roots); |
275 if (UseSharedSpaces && !DumpSharedSpaces) { | |
276 SkipAdjustingSharedStrings skip_closure(root_closure); | |
277 StringTable::oops_do(&skip_closure); | |
278 } else { | |
279 StringTable::oops_do(root_closure); | 225 StringTable::oops_do(root_closure); |
280 } | 226 } |
281 } | |
282 | 227 |
283 void SharedHeap::set_barrier_set(BarrierSet* bs) { | 228 void SharedHeap::set_barrier_set(BarrierSet* bs) { |
284 _barrier_set = bs; | 229 _barrier_set = bs; |
285 // Cached barrier set for fast access in oops | 230 // Cached barrier set for fast access in oops |
286 oopDesc::set_bs(bs); | 231 oopDesc::set_bs(bs); |
288 | 233 |
289 void SharedHeap::post_initialize() { | 234 void SharedHeap::post_initialize() { |
290 ref_processing_init(); | 235 ref_processing_init(); |
291 } | 236 } |
292 | 237 |
293 void SharedHeap::ref_processing_init() { | 238 void SharedHeap::ref_processing_init() {} |
294 perm_gen()->ref_processor_init(); | |
295 } | |
296 | 239 |
297 // Some utilities. | 240 // Some utilities. |
298 void SharedHeap::print_size_transition(outputStream* out, | 241 void SharedHeap::print_size_transition(outputStream* out, |
299 size_t bytes_before, | 242 size_t bytes_before, |
300 size_t bytes_after, | 243 size_t bytes_after, |