/*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/* Allocation site table. */
/*
* Every object allocation will have a place where it was allocated,
* this is the purpose of the SiteIndex.
*
* The allocation site or SiteIndex is unique via a (class,trace) pair.
*
* The allocation statistics are accumulated in the SiteInfo for each
* site.
*
* This file also contains the heap iterate logic, which is closely
* associated with the site table, the object table, and the
* reference table. Each object has an element in the object table
* and as the heap is traversed, and information contained in each
* object is saved as a linked list of references.
*
*/
#include "hprof.h"
typedef struct SiteKey {
} SiteKey;
typedef struct SiteInfo {
} SiteInfo;
typedef struct IterateInfo {
int count;
int changed_only;
} IterateInfo;
/* Private internal functions. */
static SiteKey*
{
void *key_ptr;
int key_len;
}
{
}
{
return pkey->trace_index;
}
static SiteInfo *
{
return info;
}
static void
{
} else {
n_alloced_instances = 0;
n_alloced_bytes = 0;
n_live_instances = 0;
n_live_bytes = 0;
}
debug_message( "Site 0x%08x: class=0x%08x, trace=0x%08x, "
"Ninst=(%d,%d), Nbytes=(%d,%d), "
"Nlive=(%d,%d), NliveBytes=(%d,%d)\n",
i,
}
static void
{
if ( iterate->changed_only ) {
return;
}
}
}
static void
{
}
}
static int
{
}
static int
{
}
static ClassIndex
{
return cnum;
}
/* Create tag and object entry for an untagged object (should be rare) */
static jlong
{
*pindex = object_index;
}
}
return tag_create(object_index);
}
/* Setup tag on root object, if tagged return object index and site index */
static void
{
}
}
} else {
/* Create and set the tag. */
}
}
/* External interfaces */
{
HPROF_ASSERT(cnum!=0);
HPROF_ASSERT(trace_index!=0);
return index;
}
void
site_init(void)
{
}
void
site_list(void)
{
"--------------------- Site Table ------------------------\n");
"----------------------------------------------------------\n");
}
void
site_cleanup(void)
{
}
void
{
if ( size > 0 ) {
}
}
/* Output allocation sites, up to the given cut-off point, and according
* to the given flags:
*
* SITE_DUMP_INCREMENTAL only dump what's changed since last dump.
* SITE_SORT_BY_ALLOC sort sites by total allocation rather
* than live data.
* SITE_FORCE_GC force a GC before the site dump.
*/
void
{
if (flags & SITE_FORCE_GC) {
runGC();
}
int site_table_size;
double accum_percent;
void * comment_str;
int i;
int cutoff_count;
int nbytes;
accum_percent = 0;
if ( nbytes > 0 ) {
}
if (flags & SITE_SORT_BY_ALLOC) {
comment_str = "allocated bytes";
} else {
comment_str = "live bytes";
}
cutoff_count = 0;
for (i = 0; i < site_table_size; i++) {
double ratio;
HPROF_ASSERT(index!=0);
break;
}
cutoff_count++;
}
for (i = 0; i < cutoff_count; i++) {
char *class_signature;
double ratio;
accum_percent += ratio;
io_write_sites_elem(i + 1,
}
}
}
/* Primitive array data callback for FollowReferences */
{
/* We can't do anything with a class_tag==0, just skip it */
return JVMTI_VISIT_OBJECTS;
}
/* Assume object has been tagged, get object index */
/* Save string data */
return JVMTI_VISIT_OBJECTS;
}
/* Primitive field data callback for FollowReferences */
void* user_data)
{
/* We can't do anything with a class_tag==0, just skip it */
return JVMTI_VISIT_OBJECTS;
}
/* If the field is 0, just skip it, we assume 0 */
return JVMTI_VISIT_OBJECTS;
}
/* Get field index */
/* We assume the object was tagged */
/* Save primitive field data */
return JVMTI_VISIT_OBJECTS;
}
static SerialNumber
{
return thread_serial_num;
}
return thread_serial_num;
}
return gdata->unknown_thread_serial_num;
}
/* Get the object index and thread serial number for this local object */
static void
{
} else {
if ( thread_tag != (jlong)0 ) {
} else {
}
/* Create and set the tag. */
}
HPROF_ASSERT(object_index!=0);
}
/* Store away plain object reference information */
static jint
const jvmtiHeapReferenceInfo* reference_info,
{
/* We can't do anything with a class_tag==0, just skip it */
return JVMTI_VISIT_OBJECTS;
}
switch ( reference_kind ) {
default:
/* Currently we don't need these */
return JVMTI_VISIT_OBJECTS;
break;
break;
break;
reference_index = 0;
break;
}
/* We assume the referrer is tagged */
/* Now check the referree */
object_tag = *tag_ptr;
if ( object_tag != (jlong)0 ) {
} else {
/* Create and set the tag. */
&object_index, NULL);
*tag_ptr = object_tag;
}
HPROF_ASSERT(object_index!=0);
/* Save reference information */
return JVMTI_VISIT_OBJECTS;
}
/* FollowReferences heap_reference_callback */
const jvmtiHeapReferenceInfo* reference_info,
{
/* Only calls to Allocate, Deallocate, RawMonitorEnter & RawMonitorExit
* are allowed here (see the JVMTI Spec).
*/
/* We can't do anything with a class_tag==0, just skip it */
return JVMTI_VISIT_OBJECTS;
}
switch ( reference_kind ) {
case JVMTI_HEAP_REFERENCE_JNI_GLOBAL: {
if ( object_site_index != 0 ) {
} else {
}
}
break;
char *sig;
sig = "Unknown";
class_serial_num = 0;
if ( object_site_index != 0 ) {
}
}
break;
&object_index, NULL);
break;
case JVMTI_HEAP_REFERENCE_STACK_LOCAL: {
}
break;
case JVMTI_HEAP_REFERENCE_JNI_LOCAL: {
}
break;
case JVMTI_HEAP_REFERENCE_THREAD: {
/* It is assumed that tag_ptr is referring to a
* java.lang.Thread object here.
*/
/* Hopefully the ThreadStart event put this thread's
* correct serial number on it's object.
*/
} else {
/* Rare situation that a Thread object is not tagged.
* Create special unique thread serial number in this
* case, probably means we never saw a thread start
* or thread end, or even an allocation of the thread
* object.
*/
}
/* Get tls_index and set in_heap_dump, if we find it. */
if ( tls_index != 0 ) {
}
/* Issue thread object (must be before thread root) */
/* Issue thread root */
}
break;
&object_index, NULL);
break;
default:
/* Ignore anything else */
break;
}
return JVMTI_VISIT_OBJECTS;
}
void
{
/* Remove class dumped status, all classes must be dumped */
/* Clear in_heap_dump flag */
/* Dump the last thread traces and get the lists back we need */
/* Write header for heap dump */
/* Setup a clean reference table */
/* Walk over all reachable objects and dump out roots */
/* Issue thread object for fake non-existent unknown thread
* just in case someone refers to it. Real threads are handled
* during iterate over reachable objects.
*/
/* Iterate over heap and get the real stuff */
/* Select callbacks */
}
}
/* Process reference information. */
/* Dump the last thread traces and get the lists back we need */
/* Write out footer for heap dump */
}