Mercurial > hg > truffle
comparison src/share/vm/memory/heapInspection.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 | d2a62e0f25eb |
children | 16fb9f942703 db9981fd3124 |
comparison
equal
deleted
inserted
replaced
6724:36d1d483d5d6 | 6725:da91efe96a93 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2002, 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. |
25 #include "precompiled.hpp" | 25 #include "precompiled.hpp" |
26 #include "gc_interface/collectedHeap.hpp" | 26 #include "gc_interface/collectedHeap.hpp" |
27 #include "memory/genCollectedHeap.hpp" | 27 #include "memory/genCollectedHeap.hpp" |
28 #include "memory/heapInspection.hpp" | 28 #include "memory/heapInspection.hpp" |
29 #include "memory/resourceArea.hpp" | 29 #include "memory/resourceArea.hpp" |
30 #include "oops/klassOop.hpp" | |
31 #include "runtime/os.hpp" | 30 #include "runtime/os.hpp" |
32 #include "utilities/globalDefinitions.hpp" | 31 #include "utilities/globalDefinitions.hpp" |
33 #ifndef SERIALGC | 32 #ifndef SERIALGC |
34 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" | 33 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" |
35 #endif | 34 #endif |
46 } | 45 } |
47 | 46 |
48 void KlassInfoEntry::print_on(outputStream* st) const { | 47 void KlassInfoEntry::print_on(outputStream* st) const { |
49 ResourceMark rm; | 48 ResourceMark rm; |
50 const char* name;; | 49 const char* name;; |
51 if (_klass->klass_part()->name() != NULL) { | 50 if (_klass->name() != NULL) { |
52 name = _klass->klass_part()->external_name(); | 51 name = _klass->external_name(); |
53 } else { | 52 } else { |
54 if (_klass == Universe::klassKlassObj()) name = "<klassKlass>"; else | |
55 if (_klass == Universe::arrayKlassKlassObj()) name = "<arrayKlassKlass>"; else | |
56 if (_klass == Universe::objArrayKlassKlassObj()) name = "<objArrayKlassKlass>"; else | |
57 if (_klass == Universe::instanceKlassKlassObj()) name = "<instanceKlassKlass>"; else | |
58 if (_klass == Universe::typeArrayKlassKlassObj()) name = "<typeArrayKlassKlass>"; else | |
59 if (_klass == Universe::boolArrayKlassObj()) name = "<boolArrayKlass>"; else | 53 if (_klass == Universe::boolArrayKlassObj()) name = "<boolArrayKlass>"; else |
60 if (_klass == Universe::charArrayKlassObj()) name = "<charArrayKlass>"; else | 54 if (_klass == Universe::charArrayKlassObj()) name = "<charArrayKlass>"; else |
61 if (_klass == Universe::singleArrayKlassObj()) name = "<singleArrayKlass>"; else | 55 if (_klass == Universe::singleArrayKlassObj()) name = "<singleArrayKlass>"; else |
62 if (_klass == Universe::doubleArrayKlassObj()) name = "<doubleArrayKlass>"; else | 56 if (_klass == Universe::doubleArrayKlassObj()) name = "<doubleArrayKlass>"; else |
63 if (_klass == Universe::byteArrayKlassObj()) name = "<byteArrayKlass>"; else | 57 if (_klass == Universe::byteArrayKlassObj()) name = "<byteArrayKlass>"; else |
64 if (_klass == Universe::shortArrayKlassObj()) name = "<shortArrayKlass>"; else | 58 if (_klass == Universe::shortArrayKlassObj()) name = "<shortArrayKlass>"; else |
65 if (_klass == Universe::intArrayKlassObj()) name = "<intArrayKlass>"; else | 59 if (_klass == Universe::intArrayKlassObj()) name = "<intArrayKlass>"; else |
66 if (_klass == Universe::longArrayKlassObj()) name = "<longArrayKlass>"; else | 60 if (_klass == Universe::longArrayKlassObj()) name = "<longArrayKlass>"; else |
67 if (_klass == Universe::methodKlassObj()) name = "<methodKlass>"; else | |
68 if (_klass == Universe::constMethodKlassObj()) name = "<constMethodKlass>"; else | |
69 if (_klass == Universe::methodDataKlassObj()) name = "<methodDataKlass>"; else | |
70 if (_klass == Universe::constantPoolKlassObj()) name = "<constantPoolKlass>"; else | |
71 if (_klass == Universe::constantPoolCacheKlassObj()) name = "<constantPoolCacheKlass>"; else | |
72 if (_klass == Universe::compiledICHolderKlassObj()) name = "<compiledICHolderKlass>"; else | |
73 name = "<no name>"; | 61 name = "<no name>"; |
74 } | 62 } |
75 // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit | 63 // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit |
76 st->print_cr(INT64_FORMAT_W(13) " " UINT64_FORMAT_W(13) " %s", | 64 st->print_cr(INT64_FORMAT_W(13) " " UINT64_FORMAT_W(13) " %s", |
77 (jlong) _instance_count, | 65 (jlong) _instance_count, |
78 (julong) _instance_words * HeapWordSize, | 66 (julong) _instance_words * HeapWordSize, |
79 name); | 67 name); |
80 } | 68 } |
81 | 69 |
82 KlassInfoEntry* KlassInfoBucket::lookup(const klassOop k) { | 70 KlassInfoEntry* KlassInfoBucket::lookup(Klass* const k) { |
83 KlassInfoEntry* elt = _list; | 71 KlassInfoEntry* elt = _list; |
84 while (elt != NULL) { | 72 while (elt != NULL) { |
85 if (elt->is_equal(k)) { | 73 if (elt->is_equal(k)) { |
86 return elt; | 74 return elt; |
87 } | 75 } |
133 FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets, mtInternal); | 121 FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets, mtInternal); |
134 _size = 0; | 122 _size = 0; |
135 } | 123 } |
136 } | 124 } |
137 | 125 |
138 uint KlassInfoTable::hash(klassOop p) { | 126 uint KlassInfoTable::hash(Klass* p) { |
139 assert(Universe::heap()->is_in_permanent((HeapWord*)p), "all klasses in permgen"); | 127 assert(p->is_metadata(), "all klasses are metadata"); |
140 return (uint)(((uintptr_t)p - (uintptr_t)_ref) >> 2); | 128 return (uint)(((uintptr_t)p - (uintptr_t)_ref) >> 2); |
141 } | 129 } |
142 | 130 |
143 KlassInfoEntry* KlassInfoTable::lookup(const klassOop k) { | 131 KlassInfoEntry* KlassInfoTable::lookup(Klass* const k) { |
144 uint idx = hash(k) % _size; | 132 uint idx = hash(k) % _size; |
145 assert(_buckets != NULL, "Allocation failure should have been caught"); | 133 assert(_buckets != NULL, "Allocation failure should have been caught"); |
146 KlassInfoEntry* e = _buckets[idx].lookup(k); | 134 KlassInfoEntry* e = _buckets[idx].lookup(k); |
147 // Lookup may fail if this is a new klass for which we | 135 // Lookup may fail if this is a new klass for which we |
148 // could not allocate space for an new entry. | 136 // could not allocate space for an new entry. |
151 } | 139 } |
152 | 140 |
153 // Return false if the entry could not be recorded on account | 141 // Return false if the entry could not be recorded on account |
154 // of running out of space required to create a new entry. | 142 // of running out of space required to create a new entry. |
155 bool KlassInfoTable::record_instance(const oop obj) { | 143 bool KlassInfoTable::record_instance(const oop obj) { |
156 klassOop k = obj->klass(); | 144 Klass* k = obj->klass(); |
157 KlassInfoEntry* elt = lookup(k); | 145 KlassInfoEntry* elt = lookup(k); |
158 // elt may be NULL if it's a new klass for which we | 146 // elt may be NULL if it's a new klass for which we |
159 // could not allocate space for a new entry in the hashtable. | 147 // could not allocate space for a new entry in the hashtable. |
160 if (elt != NULL) { | 148 if (elt != NULL) { |
161 elt->set_count(elt->count() + 1); | 149 elt->set_count(elt->count() + 1); |
241 size_t missed_count() { return _missed_count; } | 229 size_t missed_count() { return _missed_count; } |
242 }; | 230 }; |
243 | 231 |
244 void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { | 232 void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { |
245 ResourceMark rm; | 233 ResourceMark rm; |
246 HeapWord* ref; | 234 // Get some random number for ref (the hash key) |
247 | 235 HeapWord* ref = (HeapWord*) Universe::boolArrayKlassObj(); |
248 CollectedHeap* heap = Universe::heap(); | 236 CollectedHeap* heap = Universe::heap(); |
249 bool is_shared_heap = false; | 237 bool is_shared_heap = false; |
250 switch (heap->kind()) { | 238 |
251 case CollectedHeap::G1CollectedHeap: | |
252 case CollectedHeap::GenCollectedHeap: { | |
253 is_shared_heap = true; | |
254 SharedHeap* sh = (SharedHeap*)heap; | |
255 if (need_prologue) { | |
256 sh->gc_prologue(false /* !full */); // get any necessary locks, etc. | |
257 } | |
258 ref = sh->perm_gen()->used_region().start(); | |
259 break; | |
260 } | |
261 #ifndef SERIALGC | |
262 case CollectedHeap::ParallelScavengeHeap: { | |
263 ParallelScavengeHeap* psh = (ParallelScavengeHeap*)heap; | |
264 ref = psh->perm_gen()->object_space()->used_region().start(); | |
265 break; | |
266 } | |
267 #endif // SERIALGC | |
268 default: | |
269 ShouldNotReachHere(); // Unexpected heap kind for this op | |
270 } | |
271 // Collect klass instance info | 239 // Collect klass instance info |
272 KlassInfoTable cit(KlassInfoTable::cit_size, ref); | 240 KlassInfoTable cit(KlassInfoTable::cit_size, ref); |
273 if (!cit.allocation_failed()) { | 241 if (!cit.allocation_failed()) { |
274 // Iterate over objects in the heap | 242 // Iterate over objects in the heap |
275 RecordInstanceClosure ric(&cit); | 243 RecordInstanceClosure ric(&cit); |
276 // If this operation encounters a bad object when using CMS, | |
277 // consider using safe_object_iterate() which avoids perm gen | |
278 // objects that may contain bad references. | |
279 Universe::heap()->object_iterate(&ric); | 244 Universe::heap()->object_iterate(&ric); |
280 | 245 |
281 // Report if certain classes are not counted because of | 246 // Report if certain classes are not counted because of |
282 // running out of C-heap for the histogram. | 247 // running out of C-heap for the histogram. |
283 size_t missed_count = ric.missed_count(); | 248 size_t missed_count = ric.missed_count(); |
306 } | 271 } |
307 } | 272 } |
308 | 273 |
309 class FindInstanceClosure : public ObjectClosure { | 274 class FindInstanceClosure : public ObjectClosure { |
310 private: | 275 private: |
311 klassOop _klass; | 276 Klass* _klass; |
312 GrowableArray<oop>* _result; | 277 GrowableArray<oop>* _result; |
313 | 278 |
314 public: | 279 public: |
315 FindInstanceClosure(klassOop k, GrowableArray<oop>* result) : _klass(k), _result(result) {}; | 280 FindInstanceClosure(Klass* k, GrowableArray<oop>* result) : _klass(k), _result(result) {}; |
316 | 281 |
317 void do_object(oop obj) { | 282 void do_object(oop obj) { |
318 if (obj->is_a(_klass)) { | 283 if (obj->is_a(_klass)) { |
319 _result->append(obj); | 284 _result->append(obj); |
320 } | 285 } |
321 } | 286 } |
322 }; | 287 }; |
323 | 288 |
324 void HeapInspection::find_instances_at_safepoint(klassOop k, GrowableArray<oop>* result) { | 289 void HeapInspection::find_instances_at_safepoint(Klass* k, GrowableArray<oop>* result) { |
325 assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped"); | 290 assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped"); |
326 assert(Heap_lock->is_locked(), "should have the Heap_lock"); | 291 assert(Heap_lock->is_locked(), "should have the Heap_lock"); |
327 | 292 |
328 // Ensure that the heap is parsable | 293 // Ensure that the heap is parsable |
329 Universe::heap()->ensure_parsability(false); // no need to retire TALBs | 294 Universe::heap()->ensure_parsability(false); // no need to retire TALBs |
330 | 295 |
331 // Iterate over objects in the heap | 296 // Iterate over objects in the heap |
332 FindInstanceClosure fic(k, result); | 297 FindInstanceClosure fic(k, result); |
333 // If this operation encounters a bad object when using CMS, | 298 // If this operation encounters a bad object when using CMS, |
334 // consider using safe_object_iterate() which avoids perm gen | 299 // consider using safe_object_iterate() which avoids metadata |
335 // objects that may contain bad references. | 300 // objects that may contain bad references. |
336 Universe::heap()->object_iterate(&fic); | 301 Universe::heap()->object_iterate(&fic); |
337 } | 302 } |