duke@435: /* xdono@631: * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: #ifndef SERVICES_KERNEL duke@435: duke@435: duke@435: // HeapInspection duke@435: duke@435: // KlassInfoTable is a bucket hash table that duke@435: // maps klassOops to extra information: duke@435: // instance count and instance word size. duke@435: // duke@435: // A KlassInfoBucket is the head of a link list duke@435: // of KlassInfoEntry's duke@435: // duke@435: // KlassInfoHisto is a growable array of pointers duke@435: // to KlassInfoEntry's and is used to sort duke@435: // the entries. duke@435: duke@435: class KlassInfoEntry: public CHeapObj { duke@435: private: duke@435: KlassInfoEntry* _next; duke@435: klassOop _klass; duke@435: long _instance_count; duke@435: size_t _instance_words; duke@435: duke@435: public: duke@435: KlassInfoEntry(klassOop k, KlassInfoEntry* next) : duke@435: _klass(k), _instance_count(0), _instance_words(0), _next(next) duke@435: {} duke@435: KlassInfoEntry* next() { return _next; } duke@435: bool is_equal(klassOop k) { return k == _klass; } duke@435: klassOop klass() { return _klass; } duke@435: long count() { return _instance_count; } duke@435: void set_count(long ct) { _instance_count = ct; } duke@435: size_t words() { return _instance_words; } duke@435: void set_words(size_t wds) { _instance_words = wds; } duke@435: int compare(KlassInfoEntry* e1, KlassInfoEntry* e2); duke@435: void print_on(outputStream* st) const; duke@435: }; duke@435: duke@435: class KlassInfoClosure: public StackObj { duke@435: public: duke@435: // Called for each KlassInfoEntry. duke@435: virtual void do_cinfo(KlassInfoEntry* cie) = 0; duke@435: }; duke@435: duke@435: class KlassInfoBucket: public CHeapObj { duke@435: private: duke@435: KlassInfoEntry* _list; duke@435: KlassInfoEntry* list() { return _list; } duke@435: void set_list(KlassInfoEntry* l) { _list = l; } duke@435: public: duke@435: KlassInfoEntry* lookup(const klassOop k); duke@435: void initialize() { _list = NULL; } duke@435: void empty(); duke@435: void iterate(KlassInfoClosure* cic); duke@435: }; duke@435: duke@435: class KlassInfoTable: public StackObj { duke@435: private: duke@435: int _size; duke@435: duke@435: // An aligned reference address (typically the least duke@435: // address in the perm gen) used for hashing klass duke@435: // objects. duke@435: HeapWord* _ref; duke@435: duke@435: KlassInfoBucket* _buckets; duke@435: uint hash(klassOop p); duke@435: KlassInfoEntry* lookup(const klassOop k); duke@435: duke@435: public: duke@435: // Table size duke@435: enum { duke@435: cit_size = 20011 duke@435: }; duke@435: KlassInfoTable(int size, HeapWord* ref); duke@435: ~KlassInfoTable(); ysr@446: bool record_instance(const oop obj); duke@435: void iterate(KlassInfoClosure* cic); ysr@446: bool allocation_failed() { return _buckets == NULL; } duke@435: }; duke@435: duke@435: class KlassInfoHisto : public StackObj { duke@435: private: duke@435: GrowableArray* _elements; duke@435: GrowableArray* elements() const { return _elements; } duke@435: const char* _title; duke@435: const char* title() const { return _title; } duke@435: static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2); duke@435: void print_elements(outputStream* st) const; duke@435: public: duke@435: enum { duke@435: histo_initial_size = 1000 duke@435: }; duke@435: KlassInfoHisto(const char* title, duke@435: int estimatedCount); duke@435: ~KlassInfoHisto(); duke@435: void add(KlassInfoEntry* cie); duke@435: void print_on(outputStream* st) const; duke@435: void sort(); duke@435: }; duke@435: duke@435: #endif // SERVICES_KERNEL duke@435: duke@435: class HeapInspection : public AllStatic { duke@435: public: ysr@1050: static void heap_inspection(outputStream* st, bool need_prologue) KERNEL_RETURN; duke@435: static void find_instances_at_safepoint(klassOop k, GrowableArray* result) KERNEL_RETURN; duke@435: };