/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_MEMORY_HEAPINSPECTION_HPP
#define SHARE_VM_MEMORY_HEAPINSPECTION_HPP
#include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp"
// HeapInspection
// KlassInfoTable is a bucket hash table that
// maps klassOops to extra information:
// instance count and instance word size.
//
// A KlassInfoBucket is the head of a link list
// of KlassInfoEntry's
//
// KlassInfoHisto is a growable array of pointers
// to KlassInfoEntry's and is used to sort
// the entries.
class KlassInfoEntry: public CHeapObj<mtInternal> {
private:
KlassInfoEntry* _next;
klassOop _klass;
long _instance_count;
size_t _instance_words;
public:
KlassInfoEntry(klassOop k, KlassInfoEntry* next) :
_klass(k), _instance_count(0), _instance_words(0), _next(next)
{}
KlassInfoEntry* next() { return _next; }
bool is_equal(klassOop k) { return k == _klass; }
klassOop klass() const { return _klass; }
long count() const { return _instance_count; }
void set_count(long ct) { _instance_count = ct; }
size_t words() const { return _instance_words; }
void set_words(size_t wds) { _instance_words = wds; }
int compare(KlassInfoEntry* e1, KlassInfoEntry* e2);
void print_on(outputStream* st) const;
};
class KlassInfoClosure : public StackObj {
public:
// Called for each KlassInfoEntry.
virtual void do_cinfo(KlassInfoEntry* cie) = 0;
};
class KlassInfoBucket: public CHeapObj<mtInternal> {
private:
KlassInfoEntry* _list;
KlassInfoEntry* list() { return _list; }
void set_list(KlassInfoEntry* l) { _list = l; }
public:
KlassInfoEntry* lookup(const klassOop k);
void initialize() { _list = NULL; }
void empty();
void iterate(KlassInfoClosure* cic);
};
class KlassInfoTable: public StackObj {
private:
int _size;
static const int _num_buckets = 20011;
size_t _size_of_instances_in_words;
// An aligned reference address (typically the least
// address in the perm gen) used for hashing klass
// objects.
HeapWord* _ref;
KlassInfoBucket* _buckets;
uint hash(klassOop p);
KlassInfoEntry* lookup(const klassOop k);
public:
KlassInfoTable(HeapWord* ref);
~KlassInfoTable();
bool record_instance(const oop obj);
void iterate(KlassInfoClosure* cic);
bool allocation_failed() { return _buckets == NULL; }
size_t size_of_instances_in_words() const;
};
class KlassInfoHisto : public StackObj {
private:
GrowableArray<KlassInfoEntry*>* _elements;
GrowableArray<KlassInfoEntry*>* elements() const { return _elements; }
const char* _title;
const char* title() const { return _title; }
static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2);
void print_elements(outputStream* st) const;
static const int _histo_initial_size = 1000;
public:
KlassInfoHisto(const char* title);
~KlassInfoHisto();
void add(KlassInfoEntry* cie);
void print_on(outputStream* st) const;
void sort();
};
class HeapInspection : public AllStatic {
public:
static void heap_inspection(outputStream* st, bool need_prologue);
static size_t populate_table(KlassInfoTable* cit,
bool need_prologue,
BoolObjectClosure* filter = NULL);
static HeapWord* start_of_perm_gen();
static void find_instances_at_safepoint(klassOop k, GrowableArray<oop>* result);
private:
static bool is_shared_heap();
static void prologue();
static void epilogue();
};
#endif // SHARE_VM_MEMORY_HEAPINSPECTION_HPP