diff -r 13967da712ff -r ba2c9c7773b6 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.c --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.c Thu Aug 20 11:38:20 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1980 +0,0 @@ -/* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * - * 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 - * documentation and/or other materials provided with the distribution. - * - * - 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. - */ - - -/* All I/O functionality for hprof. */ - -/* - * The hprof agent has many forms of output: - * - * format=b gdata->output_format=='b' - * Binary format. Defined below. This is used by HAT. - * This is NOT the same format as emitted by JVMPI. - * - * format=a gdata->output_format=='a' - * Ascii format. Not exactly an ascii representation of the binary format. - * - * And many forms of dumps: - * - * heap=dump - * A large dump that in this implementation is written to a separate - * file first before being placed in the output file. Several reasons, - * the binary form needs a byte count of the length in the header, and - * references in this dump to other items need to be emitted first. - * So it's two pass, or use a temp file and copy. - * heap=sites - * Dumps the sites in the order of most allocations. - * cpu=samples - * Dumps the traces in order of most hits - * cpu=times - * Dumps the traces in the order of most time spent there. - * cpu=old (format=a only) - * Dumps out an older form of cpu output (old -prof format) - * monitor=y (format=a only) - * Dumps out a list of monitors in order of most contended. - * - * This file also includes a binary format check function that will read - * back in the hprof binary format and verify the syntax looks correct. - * - * WARNING: Besides the comments below, there is little format spec on this, - * however see: - * http://java.sun.com/j2se/1.4.2/docs/guide/jvmpi/jvmpi.html#hprof - */ - -#include "hprof.h" - -typedef TableIndex HprofId; - -#include "hprof_ioname.h" -#include "hprof_b_spec.h" - -static int type_size[ /*HprofType*/ ] = HPROF_TYPE_SIZES; - -static void dump_heap_segment_and_reset(jlong segment_size); - -static void -not_implemented(void) -{ -} - -static IoNameIndex -get_name_index(char *name) -{ - if (name != NULL && gdata->output_format == 'b') { - return ioname_find_or_create(name, NULL); - } - return 0; -} - -static char * -signature_to_name(char *sig) -{ - char *ptr; - char *basename; - char *name; - int i; - int len; - int name_len; - - if ( sig != NULL ) { - switch ( sig[0] ) { - case JVM_SIGNATURE_CLASS: - ptr = strchr(sig+1, JVM_SIGNATURE_ENDCLASS); - if ( ptr == NULL ) { - basename = "Unknown_class"; - break; - } - /*LINTED*/ - name_len = (jint)(ptr - (sig+1)); - name = HPROF_MALLOC(name_len+1); - (void)memcpy(name, sig+1, name_len); - name[name_len] = 0; - for ( i = 0 ; i < name_len ; i++ ) { - if ( name[i] == '/' ) name[i] = '.'; - } - return name; - case JVM_SIGNATURE_ARRAY: - basename = signature_to_name(sig+1); - len = (int)strlen(basename); - name_len = len+2; - name = HPROF_MALLOC(name_len+1); - (void)memcpy(name, basename, len); - (void)memcpy(name+len, "[]", 2); - name[name_len] = 0; - HPROF_FREE(basename); - return name; - case JVM_SIGNATURE_FUNC: - ptr = strchr(sig+1, JVM_SIGNATURE_ENDFUNC); - if ( ptr == NULL ) { - basename = "Unknown_method"; - break; - } - basename = "()"; /* Someday deal with method signatures */ - break; - case JVM_SIGNATURE_BYTE: - basename = "byte"; - break; - case JVM_SIGNATURE_CHAR: - basename = "char"; - break; - case JVM_SIGNATURE_ENUM: - basename = "enum"; - break; - case JVM_SIGNATURE_FLOAT: - basename = "float"; - break; - case JVM_SIGNATURE_DOUBLE: - basename = "double"; - break; - case JVM_SIGNATURE_INT: - basename = "int"; - break; - case JVM_SIGNATURE_LONG: - basename = "long"; - break; - case JVM_SIGNATURE_SHORT: - basename = "short"; - break; - case JVM_SIGNATURE_VOID: - basename = "void"; - break; - case JVM_SIGNATURE_BOOLEAN: - basename = "boolean"; - break; - default: - basename = "Unknown_class"; - break; - } - } else { - basename = "Unknown_class"; - } - - /* Simple basename */ - name_len = (int)strlen(basename); - name = HPROF_MALLOC(name_len+1); - (void)strcpy(name, basename); - return name; -} - -static int -size_from_field_info(int size) -{ - if ( size == 0 ) { - size = (int)sizeof(HprofId); - } - return size; -} - -static void -type_from_signature(const char *sig, HprofType *kind, jint *size) -{ - *kind = HPROF_NORMAL_OBJECT; - *size = 0; - switch ( sig[0] ) { - case JVM_SIGNATURE_ENUM: - case JVM_SIGNATURE_CLASS: - case JVM_SIGNATURE_ARRAY: - *kind = HPROF_NORMAL_OBJECT; - break; - case JVM_SIGNATURE_BOOLEAN: - *kind = HPROF_BOOLEAN; - break; - case JVM_SIGNATURE_CHAR: - *kind = HPROF_CHAR; - break; - case JVM_SIGNATURE_FLOAT: - *kind = HPROF_FLOAT; - break; - case JVM_SIGNATURE_DOUBLE: - *kind = HPROF_DOUBLE; - break; - case JVM_SIGNATURE_BYTE: - *kind = HPROF_BYTE; - break; - case JVM_SIGNATURE_SHORT: - *kind = HPROF_SHORT; - break; - case JVM_SIGNATURE_INT: - *kind = HPROF_INT; - break; - case JVM_SIGNATURE_LONG: - *kind = HPROF_LONG; - break; - default: - HPROF_ASSERT(0); - break; - } - *size = type_size[*kind]; -} - -static void -type_array(const char *sig, HprofType *kind, jint *elem_size) -{ - *kind = 0; - *elem_size = 0; - switch ( sig[0] ) { - case JVM_SIGNATURE_ARRAY: - type_from_signature(sig+1, kind, elem_size); - break; - } -} - -static void -system_error(const char *system_call, int rc, int errnum) -{ - char buf[256]; - char details[256]; - - details[0] = 0; - if ( errnum != 0 ) { - md_system_error(details, (int)sizeof(details)); - } else if ( rc >= 0 ) { - (void)strcpy(details,"Only part of buffer processed"); - } - if ( details[0] == 0 ) { - (void)strcpy(details,"Unknown system error condition"); - } - (void)md_snprintf(buf, sizeof(buf), "System %s failed: %s\n", - system_call, details); - HPROF_ERROR(JNI_TRUE, buf); -} - -static void -system_write(int fd, void *buf, int len, jboolean socket) -{ - int res; - - HPROF_ASSERT(fd>=0); - if (socket) { - res = md_send(fd, buf, len, 0); - if (res < 0 || res!=len) { - system_error("send", res, errno); - } - } else { - res = md_write(fd, buf, len); - if (res < 0 || res!=len) { - system_error("write", res, errno); - } - } -} - -static void -write_flush(void) -{ - HPROF_ASSERT(gdata->fd >= 0); - if (gdata->write_buffer_index) { - system_write(gdata->fd, gdata->write_buffer, gdata->write_buffer_index, - gdata->socket); - gdata->write_buffer_index = 0; - } -} - -static void -heap_flush(void) -{ - HPROF_ASSERT(gdata->heap_fd >= 0); - if (gdata->heap_buffer_index) { - gdata->heap_write_count += (jlong)gdata->heap_buffer_index; - system_write(gdata->heap_fd, gdata->heap_buffer, gdata->heap_buffer_index, - JNI_FALSE); - gdata->heap_buffer_index = 0; - } -} - -static void -write_raw(void *buf, int len) -{ - HPROF_ASSERT(gdata->fd >= 0); - if (gdata->write_buffer_index + len > gdata->write_buffer_size) { - write_flush(); - if (len > gdata->write_buffer_size) { - system_write(gdata->fd, buf, len, gdata->socket); - return; - } - } - (void)memcpy(gdata->write_buffer + gdata->write_buffer_index, buf, len); - gdata->write_buffer_index += len; -} - -static void -write_u4(unsigned i) -{ - i = md_htonl(i); - write_raw(&i, (jint)sizeof(unsigned)); -} - -static void -write_u8(jlong t) -{ - write_u4((jint)jlong_high(t)); - write_u4((jint)jlong_low(t)); -} - -static void -write_u2(unsigned short i) -{ - i = md_htons(i); - write_raw(&i, (jint)sizeof(unsigned short)); -} - -static void -write_u1(unsigned char i) -{ - write_raw(&i, (jint)sizeof(unsigned char)); -} - -static void -write_id(HprofId i) -{ - write_u4(i); -} - -static void -write_current_ticks(void) -{ - write_u4((jint)(md_get_microsecs() - gdata->micro_sec_ticks)); -} - -static void -write_header(unsigned char type, jint length) -{ - write_u1(type); - write_current_ticks(); - write_u4(length); -} - -static void -write_index_id(HprofId index) -{ - write_id(index); -} - -static IoNameIndex -write_name_first(char *name) -{ - if ( name == NULL ) { - return 0; - } - if (gdata->output_format == 'b') { - IoNameIndex name_index; - jboolean new_one; - - new_one = JNI_FALSE; - name_index = ioname_find_or_create(name, &new_one); - if ( new_one ) { - int len; - - len = (int)strlen(name); - write_header(HPROF_UTF8, len + (jint)sizeof(HprofId)); - write_index_id(name_index); - write_raw(name, len); - - } - return name_index; - } - return 0; -} - -static void -write_printf(char *fmt, ...) -{ - char buf[1024]; - va_list args; - va_start(args, fmt); - (void)md_vsnprintf(buf, sizeof(buf), fmt, args); - buf[sizeof(buf)-1] = 0; - write_raw(buf, (int)strlen(buf)); - va_end(args); -} - -static void -write_thread_serial_number(SerialNumber thread_serial_num, int with_comma) -{ - if ( thread_serial_num != 0 ) { - CHECK_THREAD_SERIAL_NO(thread_serial_num); - if ( with_comma ) { - write_printf(" thread %d,", thread_serial_num); - } else { - write_printf(" thread %d", thread_serial_num); - } - } else { - if ( with_comma ) { - write_printf(" ,"); - } else { - write_printf(" "); - } - } -} - -static void -heap_raw(void *buf, int len) -{ - HPROF_ASSERT(gdata->heap_fd >= 0); - if (gdata->heap_buffer_index + len > gdata->heap_buffer_size) { - heap_flush(); - if (len > gdata->heap_buffer_size) { - gdata->heap_write_count += (jlong)len; - system_write(gdata->heap_fd, buf, len, JNI_FALSE); - return; - } - } - (void)memcpy(gdata->heap_buffer + gdata->heap_buffer_index, buf, len); - gdata->heap_buffer_index += len; -} - -static void -heap_u4(unsigned i) -{ - i = md_htonl(i); - heap_raw(&i, (jint)sizeof(unsigned)); -} - -static void -heap_u8(jlong i) -{ - heap_u4((jint)jlong_high(i)); - heap_u4((jint)jlong_low(i)); -} - -static void -heap_u2(unsigned short i) -{ - i = md_htons(i); - heap_raw(&i, (jint)sizeof(unsigned short)); -} - -static void -heap_u1(unsigned char i) -{ - heap_raw(&i, (jint)sizeof(unsigned char)); -} - -/* Write out the first byte of a heap tag */ -static void -heap_tag(unsigned char tag) -{ - jlong pos; - - /* Current position in virtual heap dump file */ - pos = gdata->heap_write_count + (jlong)gdata->heap_buffer_index; - if ( gdata->segmented == JNI_TRUE ) { /* 1.0.2 */ - if ( pos >= gdata->maxHeapSegment ) { - /* Flush all bytes to the heap dump file */ - heap_flush(); - - /* Send out segment (up to last tag written out) */ - dump_heap_segment_and_reset(gdata->heap_last_tag_position); - - /* Get new current position */ - pos = gdata->heap_write_count + (jlong)gdata->heap_buffer_index; - } - } - /* Save position of this tag */ - gdata->heap_last_tag_position = pos; - /* Write out this tag */ - heap_u1(tag); -} - -static void -heap_id(HprofId i) -{ - heap_u4(i); -} - -static void -heap_index_id(HprofId index) -{ - heap_id(index); -} - -static void -heap_name(char *name) -{ - heap_index_id(get_name_index(name)); -} - -static void -heap_printf(char *fmt, ...) -{ - char buf[1024]; - va_list args; - va_start(args, fmt); - (void)md_vsnprintf(buf, sizeof(buf), fmt, args); - buf[sizeof(buf)-1] = 0; - heap_raw(buf, (int)strlen(buf)); - va_end(args); -} - -static void -heap_element(HprofType kind, jint size, jvalue value) -{ - if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) { - HPROF_ASSERT(size==4); - heap_id((HprofId)value.i); - } else { - switch ( size ) { - case 8: - HPROF_ASSERT(size==8); - HPROF_ASSERT(kind==HPROF_LONG || kind==HPROF_DOUBLE); - heap_u8(value.j); - break; - case 4: - HPROF_ASSERT(size==4); - HPROF_ASSERT(kind==HPROF_INT || kind==HPROF_FLOAT); - heap_u4(value.i); - break; - case 2: - HPROF_ASSERT(size==2); - HPROF_ASSERT(kind==HPROF_SHORT || kind==HPROF_CHAR); - heap_u2(value.s); - break; - case 1: - HPROF_ASSERT(size==1); - HPROF_ASSERT(kind==HPROF_BOOLEAN || kind==HPROF_BYTE); - HPROF_ASSERT(kind==HPROF_BOOLEAN?(value.b==0 || value.b==1):1); - heap_u1(value.b); - break; - default: - HPROF_ASSERT(0); - break; - } - } -} - -/* Dump out all elements of an array, objects in jvalues, prims packed */ -static void -heap_elements(HprofType kind, jint num_elements, jint elem_size, void *elements) -{ - int i; - jvalue val; - static jvalue empty_val; - - if ( num_elements == 0 ) { - return; - } - - switch ( kind ) { - case 0: - case HPROF_ARRAY_OBJECT: - case HPROF_NORMAL_OBJECT: - for (i = 0; i < num_elements; i++) { - val = empty_val; - val.i = ((ObjectIndex*)elements)[i]; - heap_element(kind, elem_size, val); - } - break; - case HPROF_BYTE: - case HPROF_BOOLEAN: - HPROF_ASSERT(elem_size==1); - for (i = 0; i < num_elements; i++) { - val = empty_val; - val.b = ((jboolean*)elements)[i]; - heap_element(kind, elem_size, val); - } - break; - case HPROF_CHAR: - case HPROF_SHORT: - HPROF_ASSERT(elem_size==2); - for (i = 0; i < num_elements; i++) { - val = empty_val; - val.s = ((jshort*)elements)[i]; - heap_element(kind, elem_size, val); - } - break; - case HPROF_FLOAT: - case HPROF_INT: - HPROF_ASSERT(elem_size==4); - for (i = 0; i < num_elements; i++) { - val = empty_val; - val.i = ((jint*)elements)[i]; - heap_element(kind, elem_size, val); - } - break; - case HPROF_DOUBLE: - case HPROF_LONG: - HPROF_ASSERT(elem_size==8); - for (i = 0; i < num_elements; i++) { - val = empty_val; - val.j = ((jlong*)elements)[i]; - heap_element(kind, elem_size, val); - } - break; - } -} - -/* ------------------------------------------------------------------ */ - -void -io_flush(void) -{ - HPROF_ASSERT(gdata->header!=NULL); - write_flush(); -} - -void -io_setup(void) -{ - gdata->write_buffer_size = FILE_IO_BUFFER_SIZE; - gdata->write_buffer = HPROF_MALLOC(gdata->write_buffer_size); - gdata->write_buffer_index = 0; - - gdata->heap_write_count = (jlong)0; - gdata->heap_last_tag_position = (jlong)0; - gdata->heap_buffer_size = FILE_IO_BUFFER_SIZE; - gdata->heap_buffer = HPROF_MALLOC(gdata->heap_buffer_size); - gdata->heap_buffer_index = 0; - - if ( gdata->logflags & LOG_CHECK_BINARY ) { - gdata->check_buffer_size = FILE_IO_BUFFER_SIZE; - gdata->check_buffer = HPROF_MALLOC(gdata->check_buffer_size); - gdata->check_buffer_index = 0; - } - - ioname_init(); -} - -void -io_cleanup(void) -{ - if ( gdata->write_buffer != NULL ) { - HPROF_FREE(gdata->write_buffer); - } - gdata->write_buffer_size = 0; - gdata->write_buffer = NULL; - gdata->write_buffer_index = 0; - - if ( gdata->heap_buffer != NULL ) { - HPROF_FREE(gdata->heap_buffer); - } - gdata->heap_write_count = (jlong)0; - gdata->heap_last_tag_position = (jlong)0; - gdata->heap_buffer_size = 0; - gdata->heap_buffer = NULL; - gdata->heap_buffer_index = 0; - - if ( gdata->logflags & LOG_CHECK_BINARY ) { - if ( gdata->check_buffer != NULL ) { - HPROF_FREE(gdata->check_buffer); - } - gdata->check_buffer_size = 0; - gdata->check_buffer = NULL; - gdata->check_buffer_index = 0; - } - - ioname_cleanup(); -} - -void -io_write_file_header(void) -{ - HPROF_ASSERT(gdata->header!=NULL); - if (gdata->output_format == 'b') { - jint settings; - jlong t; - - settings = 0; - if (gdata->heap_dump || gdata->alloc_sites) { - settings |= 1; - } - if (gdata->cpu_sampling) { - settings |= 2; - } - t = md_get_timemillis(); - - write_raw(gdata->header, (int)strlen(gdata->header) + 1); - write_u4((jint)sizeof(HprofId)); - write_u8(t); - - write_header(HPROF_CONTROL_SETTINGS, 4 + 2); - write_u4(settings); - write_u2((unsigned short)gdata->max_trace_depth); - - } else if ((!gdata->cpu_timing) || (!gdata->old_timing_format)) { - /* We don't want the prelude file for the old prof output format */ - time_t t; - char prelude_file[FILENAME_MAX]; - int prelude_fd; - int nbytes; - - t = time(0); - - md_get_prelude_path(prelude_file, sizeof(prelude_file), PRELUDE_FILE); - - prelude_fd = md_open(prelude_file); - if (prelude_fd < 0) { - char buf[FILENAME_MAX+80]; - - (void)md_snprintf(buf, sizeof(buf), "Can't open %s", prelude_file); - buf[sizeof(buf)-1] = 0; - HPROF_ERROR(JNI_TRUE, buf); - } - - write_printf("%s, created %s\n", gdata->header, ctime(&t)); - - do { - char buf[1024]; /* File is small, small buffer ok here */ - - nbytes = md_read(prelude_fd, buf, sizeof(buf)); - if ( nbytes < 0 ) { - system_error("read", nbytes, errno); - break; - } - if (nbytes == 0) { - break; - } - write_raw(buf, nbytes); - } while ( nbytes > 0 ); - - md_close(prelude_fd); - - write_printf("\n--------\n\n"); - - write_flush(); - } -} - -void -io_write_file_footer(void) -{ - HPROF_ASSERT(gdata->header!=NULL); -} - -void -io_write_class_load(SerialNumber class_serial_num, ObjectIndex index, - SerialNumber trace_serial_num, char *sig) -{ - CHECK_CLASS_SERIAL_NO(class_serial_num); - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if (gdata->output_format == 'b') { - IoNameIndex name_index; - char *class_name; - - class_name = signature_to_name(sig); - name_index = write_name_first(class_name); - write_header(HPROF_LOAD_CLASS, (2 * (jint)sizeof(HprofId)) + (4 * 2)); - write_u4(class_serial_num); - write_index_id(index); - write_u4(trace_serial_num); - write_index_id(name_index); - HPROF_FREE(class_name); - } -} - -void -io_write_class_unload(SerialNumber class_serial_num, ObjectIndex index) -{ - CHECK_CLASS_SERIAL_NO(class_serial_num); - if (gdata->output_format == 'b') { - write_header(HPROF_UNLOAD_CLASS, 4); - write_u4(class_serial_num); - } -} - -void -io_write_sites_header(const char * comment_str, jint flags, double cutoff, - jint total_live_bytes, jint total_live_instances, - jlong total_alloced_bytes, jlong total_alloced_instances, - jint count) -{ - if ( gdata->output_format == 'b') { - write_header(HPROF_ALLOC_SITES, 2 + (8 * 4) + (count * (4 * 6 + 1))); - write_u2((unsigned short)flags); - write_u4(*(int *)(&cutoff)); - write_u4(total_live_bytes); - write_u4(total_live_instances); - write_u8(total_alloced_bytes); - write_u8(total_alloced_instances); - write_u4(count); - } else { - time_t t; - - t = time(0); - write_printf("SITES BEGIN (ordered by %s) %s", comment_str, ctime(&t)); - write_printf( - " percent live alloc'ed stack class\n"); - write_printf( - " rank self accum bytes objs bytes objs trace name\n"); - } -} - -void -io_write_sites_elem(jint index, double ratio, double accum_percent, - char *sig, SerialNumber class_serial_num, - SerialNumber trace_serial_num, jint n_live_bytes, - jint n_live_instances, jint n_alloced_bytes, - jint n_alloced_instances) -{ - CHECK_CLASS_SERIAL_NO(class_serial_num); - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if ( gdata->output_format == 'b') { - HprofType kind; - jint size; - - type_array(sig, &kind, &size); - write_u1(kind); - write_u4(class_serial_num); - write_u4(trace_serial_num); - write_u4(n_live_bytes); - write_u4(n_live_instances); - write_u4(n_alloced_bytes); - write_u4(n_alloced_instances); - } else { - char *class_name; - - class_name = signature_to_name(sig); - write_printf("%5u %5.2f%% %5.2f%% %9u %4u %9u %5u %5u %s\n", - index, - ratio * 100.0, - accum_percent * 100.0, - n_live_bytes, - n_live_instances, - n_alloced_bytes, - n_alloced_instances, - trace_serial_num, - class_name); - HPROF_FREE(class_name); - } -} - -void -io_write_sites_footer(void) -{ - if (gdata->output_format == 'b') { - not_implemented(); - } else { - write_printf("SITES END\n"); - } -} - -void -io_write_thread_start(SerialNumber thread_serial_num, - ObjectIndex thread_obj_id, - SerialNumber trace_serial_num, char *thread_name, - char *thread_group_name, char *thread_parent_name) -{ - CHECK_THREAD_SERIAL_NO(thread_serial_num); - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if (gdata->output_format == 'b') { - IoNameIndex tname_index; - IoNameIndex gname_index; - IoNameIndex pname_index; - - tname_index = write_name_first(thread_name); - gname_index = write_name_first(thread_group_name); - pname_index = write_name_first(thread_parent_name); - write_header(HPROF_START_THREAD, ((jint)sizeof(HprofId) * 4) + (4 * 2)); - write_u4(thread_serial_num); - write_index_id(thread_obj_id); - write_u4(trace_serial_num); - write_index_id(tname_index); - write_index_id(gname_index); - write_index_id(pname_index); - - } else if ( (!gdata->cpu_timing) || (!gdata->old_timing_format)) { - /* We don't want thread info for the old prof output format */ - write_printf("THREAD START " - "(obj=%x, id = %d, name=\"%s\", group=\"%s\")\n", - thread_obj_id, thread_serial_num, - (thread_name==NULL?"":thread_name), - (thread_group_name==NULL?"":thread_group_name)); - } -} - -void -io_write_thread_end(SerialNumber thread_serial_num) -{ - CHECK_THREAD_SERIAL_NO(thread_serial_num); - if (gdata->output_format == 'b') { - write_header(HPROF_END_THREAD, 4); - write_u4(thread_serial_num); - - } else if ( (!gdata->cpu_timing) || (!gdata->old_timing_format)) { - /* we don't want thread info for the old prof output format */ - write_printf("THREAD END (id = %d)\n", thread_serial_num); - } -} - -void -io_write_frame(FrameIndex index, SerialNumber frame_serial_num, - char *mname, char *msig, char *sname, - SerialNumber class_serial_num, jint lineno) -{ - CHECK_CLASS_SERIAL_NO(class_serial_num); - if (gdata->output_format == 'b') { - IoNameIndex mname_index; - IoNameIndex msig_index; - IoNameIndex sname_index; - - mname_index = write_name_first(mname); - msig_index = write_name_first(msig); - sname_index = write_name_first(sname); - - write_header(HPROF_FRAME, ((jint)sizeof(HprofId) * 4) + (4 * 2)); - write_index_id(index); - write_index_id(mname_index); - write_index_id(msig_index); - write_index_id(sname_index); - write_u4(class_serial_num); - write_u4(lineno); - } -} - -void -io_write_trace_header(SerialNumber trace_serial_num, - SerialNumber thread_serial_num, jint n_frames, char *phase_str) -{ - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if (gdata->output_format == 'b') { - write_header(HPROF_TRACE, ((jint)sizeof(HprofId) * n_frames) + (4 * 3)); - write_u4(trace_serial_num); - write_u4(thread_serial_num); - write_u4(n_frames); - } else { - write_printf("TRACE %u:", trace_serial_num); - if (thread_serial_num) { - write_printf(" (thread=%d)", thread_serial_num); - } - if ( phase_str != NULL ) { - write_printf(" (from %s phase of JVM)", phase_str); - } - write_printf("\n"); - if (n_frames == 0) { - write_printf("\t\n"); - } - } -} - -void -io_write_trace_elem(SerialNumber trace_serial_num, FrameIndex frame_index, - SerialNumber frame_serial_num, - char *csig, char *mname, char *sname, jint lineno) -{ - if (gdata->output_format == 'b') { - write_index_id(frame_index); - } else { - char *class_name; - char linebuf[32]; - - if (lineno == -2) { - (void)md_snprintf(linebuf, sizeof(linebuf), "Compiled method"); - } else if (lineno == -3) { - (void)md_snprintf(linebuf, sizeof(linebuf), "Native method"); - } else if (lineno == -1) { - (void)md_snprintf(linebuf, sizeof(linebuf), "Unknown line"); - } else { - (void)md_snprintf(linebuf, sizeof(linebuf), "%d", lineno); - } - linebuf[sizeof(linebuf)-1] = 0; - class_name = signature_to_name(csig); - if ( mname == NULL ) { - mname = ""; - } - if ( sname == NULL ) { - sname = ""; - } - write_printf("\t%s.%s(%s:%s)\n", class_name, mname, sname, linebuf); - HPROF_FREE(class_name); - } -} - -void -io_write_trace_footer(SerialNumber trace_serial_num, - SerialNumber thread_serial_num, jint n_frames) -{ -} - -#define CPU_SAMPLES_RECORD_NAME ("CPU SAMPLES") -#define CPU_TIMES_RECORD_NAME ("CPU TIME (ms)") - -void -io_write_cpu_samples_header(jlong total_cost, jint n_items) -{ - - if (gdata->output_format == 'b') { - write_header(HPROF_CPU_SAMPLES, (n_items * (4 * 2)) + (4 * 2)); - write_u4((jint)total_cost); - write_u4(n_items); - } else { - time_t t; - char *record_name; - - if ( gdata->cpu_sampling ) { - record_name = CPU_SAMPLES_RECORD_NAME; - } else { - record_name = CPU_TIMES_RECORD_NAME; - } - t = time(0); - write_printf("%s BEGIN (total = %d) %s", record_name, - /*jlong*/(int)total_cost, ctime(&t)); - if ( n_items > 0 ) { - write_printf("rank self accum count trace method\n"); - } - } -} - -void -io_write_cpu_samples_elem(jint index, double percent, double accum, - jint num_hits, jlong cost, SerialNumber trace_serial_num, - jint n_frames, char *csig, char *mname) -{ - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if (gdata->output_format == 'b') { - write_u4((jint)cost); - write_u4(trace_serial_num); - } else { - write_printf("%4u %5.2f%% %5.2f%% %7u %5u", - index, percent, accum, num_hits, - trace_serial_num); - if (n_frames > 0) { - char * class_name; - - class_name = signature_to_name(csig); - write_printf(" %s.%s\n", class_name, mname); - HPROF_FREE(class_name); - } else { - write_printf(" \n"); - } - } -} - -void -io_write_cpu_samples_footer(void) -{ - if (gdata->output_format == 'b') { - not_implemented(); - } else { - char *record_name; - - if ( gdata->cpu_sampling ) { - record_name = CPU_SAMPLES_RECORD_NAME; - } else { - record_name = CPU_TIMES_RECORD_NAME; - } - write_printf("%s END\n", record_name); - } -} - -void -io_write_heap_summary(jlong total_live_bytes, jlong total_live_instances, - jlong total_alloced_bytes, jlong total_alloced_instances) -{ - if (gdata->output_format == 'b') { - write_header(HPROF_HEAP_SUMMARY, 4 * 6); - write_u4((jint)total_live_bytes); - write_u4((jint)total_live_instances); - write_u8(total_alloced_bytes); - write_u8(total_alloced_instances); - } -} - -void -io_write_oldprof_header(void) -{ - if ( gdata->old_timing_format ) { - write_printf("count callee caller time\n"); - } -} - -void -io_write_oldprof_elem(jint num_hits, jint num_frames, char *csig_callee, - char *mname_callee, char *msig_callee, char *csig_caller, - char *mname_caller, char *msig_caller, jlong cost) -{ - if ( gdata->old_timing_format ) { - char * class_name_callee; - char * class_name_caller; - - class_name_callee = signature_to_name(csig_callee); - class_name_caller = signature_to_name(csig_caller); - write_printf("%d ", num_hits); - if (num_frames >= 1) { - write_printf("%s.%s%s ", class_name_callee, - mname_callee, msig_callee); - } else { - write_printf("%s ", ""); - } - if (num_frames > 1) { - write_printf("%s.%s%s ", class_name_caller, - mname_caller, msig_caller); - } else { - write_printf("%s ", ""); - } - write_printf("%d\n", (int)cost); - HPROF_FREE(class_name_callee); - HPROF_FREE(class_name_caller); - } -} - -void -io_write_oldprof_footer(void) -{ -} - -void -io_write_monitor_header(jlong total_time) -{ - if (gdata->output_format == 'b') { - not_implemented(); - } else { - time_t t = time(0); - - t = time(0); - write_printf("MONITOR TIME BEGIN (total = %u ms) %s", - (int)total_time, ctime(&t)); - if (total_time > 0) { - write_printf("rank self accum count trace monitor\n"); - } - } -} - -void -io_write_monitor_elem(jint index, double percent, double accum, - jint num_hits, SerialNumber trace_serial_num, char *sig) -{ - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if (gdata->output_format == 'b') { - not_implemented(); - } else { - char *class_name; - - class_name = signature_to_name(sig); - write_printf("%4u %5.2f%% %5.2f%% %7u %5u %s (Java)\n", - index, percent, accum, num_hits, - trace_serial_num, class_name); - HPROF_FREE(class_name); - } -} - -void -io_write_monitor_footer(void) -{ - if (gdata->output_format == 'b') { - not_implemented(); - } else { - write_printf("MONITOR TIME END\n"); - } -} - -void -io_write_monitor_sleep(jlong timeout, SerialNumber thread_serial_num) -{ - if (gdata->output_format == 'b') { - not_implemented(); - } else { - if ( thread_serial_num == 0 ) { - write_printf("SLEEP: timeout=%d, \n", - (int)timeout); - } else { - CHECK_THREAD_SERIAL_NO(thread_serial_num); - write_printf("SLEEP: timeout=%d, thread %d\n", - (int)timeout, thread_serial_num); - } - } -} - -void -io_write_monitor_wait(char *sig, jlong timeout, - SerialNumber thread_serial_num) -{ - if (gdata->output_format == 'b') { - not_implemented(); - } else { - if ( thread_serial_num == 0 ) { - write_printf("WAIT: MONITOR %s, timeout=%d, \n", - sig, (int)timeout); - } else { - CHECK_THREAD_SERIAL_NO(thread_serial_num); - write_printf("WAIT: MONITOR %s, timeout=%d, thread %d\n", - sig, (int)timeout, thread_serial_num); - } - } -} - -void -io_write_monitor_waited(char *sig, jlong time_waited, - SerialNumber thread_serial_num) -{ - if (gdata->output_format == 'b') { - not_implemented(); - } else { - if ( thread_serial_num == 0 ) { - write_printf("WAITED: MONITOR %s, time_waited=%d, \n", - sig, (int)time_waited); - } else { - CHECK_THREAD_SERIAL_NO(thread_serial_num); - write_printf("WAITED: MONITOR %s, time_waited=%d, thread %d\n", - sig, (int)time_waited, thread_serial_num); - } - } -} - -void -io_write_monitor_exit(char *sig, SerialNumber thread_serial_num) -{ - if (gdata->output_format == 'b') { - not_implemented(); - } else { - if ( thread_serial_num == 0 ) { - write_printf("EXIT: MONITOR %s, \n", sig); - } else { - CHECK_THREAD_SERIAL_NO(thread_serial_num); - write_printf("EXIT: MONITOR %s, thread %d\n", - sig, thread_serial_num); - } - } -} - -void -io_write_monitor_dump_header(void) -{ - if (gdata->output_format == 'b') { - not_implemented(); - } else { - write_printf("MONITOR DUMP BEGIN\n"); - } -} - -void -io_write_monitor_dump_thread_state(SerialNumber thread_serial_num, - SerialNumber trace_serial_num, - jint threadState) -{ - CHECK_THREAD_SERIAL_NO(thread_serial_num); - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if (gdata->output_format == 'b') { - not_implemented(); - } else { - char tstate[20]; - - tstate[0] = 0; - - if (threadState & JVMTI_THREAD_STATE_SUSPENDED) { - (void)strcat(tstate,"S|"); - } - if (threadState & JVMTI_THREAD_STATE_INTERRUPTED) { - (void)strcat(tstate,"intr|"); - } - if (threadState & JVMTI_THREAD_STATE_IN_NATIVE) { - (void)strcat(tstate,"native|"); - } - if ( ! ( threadState & JVMTI_THREAD_STATE_ALIVE ) ) { - if ( threadState & JVMTI_THREAD_STATE_TERMINATED ) { - (void)strcat(tstate,"ZO"); - } else { - (void)strcat(tstate,"NS"); - } - } else { - if ( threadState & JVMTI_THREAD_STATE_SLEEPING ) { - (void)strcat(tstate,"SL"); - } else if ( threadState & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER ) { - (void)strcat(tstate,"MW"); - } else if ( threadState & JVMTI_THREAD_STATE_WAITING ) { - (void)strcat(tstate,"CW"); - } else if ( threadState & JVMTI_THREAD_STATE_RUNNABLE ) { - (void)strcat(tstate,"R"); - } else { - (void)strcat(tstate,"UN"); - } - } - write_printf(" THREAD %d, trace %d, status: %s\n", - thread_serial_num, trace_serial_num, tstate); - } -} - -void -io_write_monitor_dump_state(char *sig, SerialNumber thread_serial_num, - jint entry_count, - SerialNumber *waiters, jint waiter_count, - SerialNumber *notify_waiters, jint notify_waiter_count) -{ - if (gdata->output_format == 'b') { - not_implemented(); - } else { - int i; - - if ( thread_serial_num != 0 ) { - CHECK_THREAD_SERIAL_NO(thread_serial_num); - write_printf(" MONITOR %s\n", sig); - write_printf("\towner: thread %d, entry count: %d\n", - thread_serial_num, entry_count); - } else { - write_printf(" MONITOR %s unowned\n", sig); - } - write_printf("\twaiting to enter:"); - for (i = 0; i < waiter_count; i++) { - write_thread_serial_number(waiters[i], - (i != (waiter_count-1))); - } - write_printf("\n"); - write_printf("\twaiting to be notified:"); - for (i = 0; i < notify_waiter_count; i++) { - write_thread_serial_number(notify_waiters[i], - (i != (notify_waiter_count-1))); - } - write_printf("\n"); - } -} - -void -io_write_monitor_dump_footer(void) -{ - if (gdata->output_format == 'b') { - not_implemented(); - } else { - write_printf("MONITOR DUMP END\n"); - } -} - -/* ----------------------------------------------------------------- */ -/* These functions write to a separate file */ - -void -io_heap_header(jlong total_live_instances, jlong total_live_bytes) -{ - if (gdata->output_format != 'b') { - time_t t; - - t = time(0); - heap_printf("HEAP DUMP BEGIN (%u objects, %u bytes) %s", - /*jlong*/(int)total_live_instances, - /*jlong*/(int)total_live_bytes, ctime(&t)); - } -} - -void -io_heap_root_thread_object(ObjectIndex thread_obj_id, - SerialNumber thread_serial_num, SerialNumber trace_serial_num) -{ - CHECK_THREAD_SERIAL_NO(thread_serial_num); - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if (gdata->output_format == 'b') { - heap_tag(HPROF_GC_ROOT_THREAD_OBJ); - heap_id(thread_obj_id); - heap_u4(thread_serial_num); - heap_u4(trace_serial_num); - } else { - heap_printf("ROOT %x (kind=, id=%u, trace=%u)\n", - thread_obj_id, thread_serial_num, trace_serial_num); - } -} - -void -io_heap_root_unknown(ObjectIndex obj_id) -{ - if (gdata->output_format == 'b') { - heap_tag(HPROF_GC_ROOT_UNKNOWN); - heap_id(obj_id); - } else { - heap_printf("ROOT %x (kind=)\n", obj_id); - } -} - -void -io_heap_root_jni_global(ObjectIndex obj_id, SerialNumber gref_serial_num, - SerialNumber trace_serial_num) -{ - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if (gdata->output_format == 'b') { - heap_tag(HPROF_GC_ROOT_JNI_GLOBAL); - heap_id(obj_id); - heap_id(gref_serial_num); - } else { - heap_printf("ROOT %x (kind=, " - "id=%x, trace=%u)\n", - obj_id, gref_serial_num, trace_serial_num); - } -} - -void -io_heap_root_jni_local(ObjectIndex obj_id, SerialNumber thread_serial_num, - jint frame_depth) -{ - CHECK_THREAD_SERIAL_NO(thread_serial_num); - if (gdata->output_format == 'b') { - heap_tag(HPROF_GC_ROOT_JNI_LOCAL); - heap_id(obj_id); - heap_u4(thread_serial_num); - heap_u4(frame_depth); - } else { - heap_printf("ROOT %x (kind=, " - "thread=%u, frame=%d)\n", - obj_id, thread_serial_num, frame_depth); - } -} - -void -io_heap_root_system_class(ObjectIndex obj_id, char *sig, SerialNumber class_serial_num) -{ - if (gdata->output_format == 'b') { - heap_tag(HPROF_GC_ROOT_STICKY_CLASS); - heap_id(obj_id); - } else { - char *class_name; - - class_name = signature_to_name(sig); - heap_printf("ROOT %x (kind=, name=%s)\n", - obj_id, class_name); - HPROF_FREE(class_name); - } -} - -void -io_heap_root_monitor(ObjectIndex obj_id) -{ - if (gdata->output_format == 'b') { - heap_tag(HPROF_GC_ROOT_MONITOR_USED); - heap_id(obj_id); - } else { - heap_printf("ROOT %x (kind=)\n", obj_id); - } -} - -void -io_heap_root_thread(ObjectIndex obj_id, SerialNumber thread_serial_num) -{ - CHECK_THREAD_SERIAL_NO(thread_serial_num); - if (gdata->output_format == 'b') { - heap_tag(HPROF_GC_ROOT_THREAD_BLOCK); - heap_id(obj_id); - heap_u4(thread_serial_num); - } else { - heap_printf("ROOT %x (kind=, thread=%u)\n", - obj_id, thread_serial_num); - } -} - -void -io_heap_root_java_frame(ObjectIndex obj_id, SerialNumber thread_serial_num, - jint frame_depth) -{ - CHECK_THREAD_SERIAL_NO(thread_serial_num); - if (gdata->output_format == 'b') { - heap_tag(HPROF_GC_ROOT_JAVA_FRAME); - heap_id(obj_id); - heap_u4(thread_serial_num); - heap_u4(frame_depth); - } else { - heap_printf("ROOT %x (kind=, " - "thread=%u, frame=%d)\n", - obj_id, thread_serial_num, frame_depth); - } -} - -void -io_heap_root_native_stack(ObjectIndex obj_id, SerialNumber thread_serial_num) -{ - CHECK_THREAD_SERIAL_NO(thread_serial_num); - if (gdata->output_format == 'b') { - heap_tag(HPROF_GC_ROOT_NATIVE_STACK); - heap_id(obj_id); - heap_u4(thread_serial_num); - } else { - heap_printf("ROOT %x (kind=, thread=%u)\n", - obj_id, thread_serial_num); - } -} - -static jboolean -is_static_field(jint modifiers) -{ - if ( modifiers & JVM_ACC_STATIC ) { - return JNI_TRUE; - } - return JNI_FALSE; -} - -static jboolean -is_inst_field(jint modifiers) -{ - if ( modifiers & JVM_ACC_STATIC ) { - return JNI_FALSE; - } - return JNI_TRUE; -} - -void -io_heap_class_dump(ClassIndex cnum, char *sig, ObjectIndex class_id, - SerialNumber trace_serial_num, - ObjectIndex super_id, ObjectIndex loader_id, - ObjectIndex signers_id, ObjectIndex domain_id, - jint size, - jint n_cpool, ConstantPoolValue *cpool, - jint n_fields, FieldInfo *fields, jvalue *fvalues) -{ - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if (gdata->output_format == 'b') { - int i; - jint n_static_fields; - jint n_inst_fields; - jint inst_size; - jint saved_inst_size; - - n_static_fields = 0; - n_inst_fields = 0; - inst_size = 0; - - /* These do NOT go into the heap output */ - for ( i = 0 ; i < n_fields ; i++ ) { - if ( fields[i].cnum == cnum && - is_static_field(fields[i].modifiers) ) { - char *field_name; - - field_name = string_get(fields[i].name_index); - (void)write_name_first(field_name); - n_static_fields++; - } - if ( is_inst_field(fields[i].modifiers) ) { - inst_size += size_from_field_info(fields[i].primSize); - if ( fields[i].cnum == cnum ) { - char *field_name; - - field_name = string_get(fields[i].name_index); - (void)write_name_first(field_name); - n_inst_fields++; - } - } - } - - /* Verify that the instance size we have calculated as we went - * through the fields, matches what is saved away with this - * class. - */ - if ( size >= 0 ) { - saved_inst_size = class_get_inst_size(cnum); - if ( saved_inst_size == -1 ) { - class_set_inst_size(cnum, inst_size); - } else if ( saved_inst_size != inst_size ) { - HPROF_ERROR(JNI_TRUE, "Mis-match on instance size in class dump"); - } - } - - heap_tag(HPROF_GC_CLASS_DUMP); - heap_id(class_id); - heap_u4(trace_serial_num); - heap_id(super_id); - heap_id(loader_id); - heap_id(signers_id); - heap_id(domain_id); - heap_id(0); - heap_id(0); - heap_u4(inst_size); /* Must match inst_size in instance dump */ - - heap_u2((unsigned short)n_cpool); - for ( i = 0 ; i < n_cpool ; i++ ) { - HprofType kind; - jint size; - - type_from_signature(string_get(cpool[i].sig_index), - &kind, &size); - heap_u2((unsigned short)(cpool[i].constant_pool_index)); - heap_u1(kind); - HPROF_ASSERT(!HPROF_TYPE_IS_PRIMITIVE(kind)); - heap_element(kind, size, cpool[i].value); - } - - heap_u2((unsigned short)n_static_fields); - for ( i = 0 ; i < n_fields ; i++ ) { - if ( fields[i].cnum == cnum && - is_static_field(fields[i].modifiers) ) { - char *field_name; - HprofType kind; - jint size; - - type_from_signature(string_get(fields[i].sig_index), - &kind, &size); - field_name = string_get(fields[i].name_index); - heap_name(field_name); - heap_u1(kind); - heap_element(kind, size, fvalues[i]); - } - } - - heap_u2((unsigned short)n_inst_fields); /* Does not include super class */ - for ( i = 0 ; i < n_fields ; i++ ) { - if ( fields[i].cnum == cnum && - is_inst_field(fields[i].modifiers) ) { - HprofType kind; - jint size; - char *field_name; - - field_name = string_get(fields[i].name_index); - type_from_signature(string_get(fields[i].sig_index), - &kind, &size); - heap_name(field_name); - heap_u1(kind); - } - } - } else { - char * class_name; - int i; - - class_name = signature_to_name(sig); - heap_printf("CLS %x (name=%s, trace=%u)\n", - class_id, class_name, trace_serial_num); - HPROF_FREE(class_name); - if (super_id) { - heap_printf("\tsuper\t\t%x\n", super_id); - } - if (loader_id) { - heap_printf("\tloader\t\t%x\n", loader_id); - } - if (signers_id) { - heap_printf("\tsigners\t\t%x\n", signers_id); - } - if (domain_id) { - heap_printf("\tdomain\t\t%x\n", domain_id); - } - for ( i = 0 ; i < n_fields ; i++ ) { - if ( fields[i].cnum == cnum && - is_static_field(fields[i].modifiers) ) { - HprofType kind; - jint size; - - type_from_signature(string_get(fields[i].sig_index), - &kind, &size); - if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) { - if (fvalues[i].i != 0 ) { - char *field_name; - - field_name = string_get(fields[i].name_index); - heap_printf("\tstatic %s\t%x\n", field_name, - fvalues[i].i); - } - } - } - } - for ( i = 0 ; i < n_cpool ; i++ ) { - HprofType kind; - jint size; - - type_from_signature(string_get(cpool[i].sig_index), &kind, &size); - if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) { - if (cpool[i].value.i != 0 ) { - heap_printf("\tconstant pool entry %d\t%x\n", - cpool[i].constant_pool_index, cpool[i].value.i); - } - } - } - } -} - -/* Dump the instance fields in the right order. */ -static int -dump_instance_fields(ClassIndex cnum, - FieldInfo *fields, jvalue *fvalues, jint n_fields) -{ - ClassIndex super_cnum; - int i; - int nbytes; - - HPROF_ASSERT(cnum!=0); - - nbytes = 0; - for (i = 0; i < n_fields; i++) { - if ( fields[i].cnum == cnum && - is_inst_field(fields[i].modifiers) ) { - HprofType kind; - int size; - - type_from_signature(string_get(fields[i].sig_index), - &kind, &size); - heap_element(kind, size, fvalues[i]); - nbytes += size; - } - } - - super_cnum = class_get_super(cnum); - if ( super_cnum != 0 ) { - nbytes += dump_instance_fields(super_cnum, fields, fvalues, n_fields); - } - return nbytes; -} - -void -io_heap_instance_dump(ClassIndex cnum, ObjectIndex obj_id, - SerialNumber trace_serial_num, - ObjectIndex class_id, jint size, char *sig, - FieldInfo *fields, jvalue *fvalues, jint n_fields) -{ - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if (gdata->output_format == 'b') { - jint inst_size; - jint saved_inst_size; - int i; - int nbytes; - - inst_size = 0; - for (i = 0; i < n_fields; i++) { - if ( is_inst_field(fields[i].modifiers) ) { - inst_size += size_from_field_info(fields[i].primSize); - } - } - - /* Verify that the instance size we have calculated as we went - * through the fields, matches what is saved away with this - * class. - */ - saved_inst_size = class_get_inst_size(cnum); - if ( saved_inst_size == -1 ) { - class_set_inst_size(cnum, inst_size); - } else if ( saved_inst_size != inst_size ) { - HPROF_ERROR(JNI_TRUE, "Mis-match on instance size in instance dump"); - } - - heap_tag(HPROF_GC_INSTANCE_DUMP); - heap_id(obj_id); - heap_u4(trace_serial_num); - heap_id(class_id); - heap_u4(inst_size); /* Must match inst_size in class dump */ - - /* Order must be class, super, super's super, ... */ - nbytes = dump_instance_fields(cnum, fields, fvalues, n_fields); - HPROF_ASSERT(nbytes==inst_size); - } else { - char * class_name; - int i; - - class_name = signature_to_name(sig); - heap_printf("OBJ %x (sz=%u, trace=%u, class=%s@%x)\n", - obj_id, size, trace_serial_num, class_name, class_id); - HPROF_FREE(class_name); - - for (i = 0; i < n_fields; i++) { - if ( is_inst_field(fields[i].modifiers) ) { - HprofType kind; - int size; - - type_from_signature(string_get(fields[i].sig_index), - &kind, &size); - if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) { - if (fvalues[i].i != 0 ) { - char *sep; - ObjectIndex val_id; - char *field_name; - - field_name = string_get(fields[i].name_index); - val_id = (ObjectIndex)(fvalues[i].i); - sep = (int)strlen(field_name) < 8 ? "\t" : ""; - heap_printf("\t%s\t%s%x\n", field_name, sep, val_id); - } - } - } - } - } -} - -void -io_heap_object_array(ObjectIndex obj_id, SerialNumber trace_serial_num, - jint size, jint num_elements, char *sig, ObjectIndex *values, - ObjectIndex class_id) -{ - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if (gdata->output_format == 'b') { - - heap_tag(HPROF_GC_OBJ_ARRAY_DUMP); - heap_id(obj_id); - heap_u4(trace_serial_num); - heap_u4(num_elements); - heap_id(class_id); - heap_elements(HPROF_NORMAL_OBJECT, num_elements, - (jint)sizeof(HprofId), (void*)values); - } else { - char *name; - int i; - - name = signature_to_name(sig); - heap_printf("ARR %x (sz=%u, trace=%u, nelems=%u, elem type=%s@%x)\n", - obj_id, size, trace_serial_num, num_elements, - name, class_id); - for (i = 0; i < num_elements; i++) { - ObjectIndex id; - - id = values[i]; - if (id != 0) { - heap_printf("\t[%u]\t\t%x\n", i, id); - } - } - HPROF_FREE(name); - } -} - -void -io_heap_prim_array(ObjectIndex obj_id, SerialNumber trace_serial_num, - jint size, jint num_elements, char *sig, void *elements) -{ - CHECK_TRACE_SERIAL_NO(trace_serial_num); - if (gdata->output_format == 'b') { - HprofType kind; - jint esize; - - type_array(sig, &kind, &esize); - HPROF_ASSERT(HPROF_TYPE_IS_PRIMITIVE(kind)); - heap_tag(HPROF_GC_PRIM_ARRAY_DUMP); - heap_id(obj_id); - heap_u4(trace_serial_num); - heap_u4(num_elements); - heap_u1(kind); - heap_elements(kind, num_elements, esize, elements); - } else { - char *name; - - name = signature_to_name(sig); - heap_printf("ARR %x (sz=%u, trace=%u, nelems=%u, elem type=%s)\n", - obj_id, size, trace_serial_num, num_elements, name); - HPROF_FREE(name); - } -} - -/* Move file bytes into supplied raw interface */ -static void -write_raw_from_file(int fd, jlong byteCount, void (*raw_interface)(void *,int)) -{ - char *buf; - int buf_len; - int left; - int nbytes; - - HPROF_ASSERT(fd >= 0); - - /* Move contents of this file into output file. */ - buf_len = FILE_IO_BUFFER_SIZE*2; /* Twice as big! */ - buf = HPROF_MALLOC(buf_len); - HPROF_ASSERT(buf!=NULL); - - /* Keep track of how many we have left */ - left = (int)byteCount; - do { - int count; - - count = buf_len; - if ( count > left ) count = left; - nbytes = md_read(fd, buf, count); - if (nbytes < 0) { - system_error("read", nbytes, errno); - break; - } - if (nbytes == 0) { - break; - } - if ( nbytes > 0 ) { - (*raw_interface)(buf, nbytes); - left -= nbytes; - } - } while ( left > 0 ); - - if (left > 0 && nbytes == 0) { - HPROF_ERROR(JNI_TRUE, "File size is smaller than bytes written"); - } - HPROF_FREE(buf); -} - -/* Write out a heap segment, and copy remainder to top of file. */ -static void -dump_heap_segment_and_reset(jlong segment_size) -{ - int fd; - jlong last_chunk_len; - - HPROF_ASSERT(gdata->heap_fd >= 0); - - /* Flush all bytes to the heap dump file */ - heap_flush(); - - /* Last segment? */ - last_chunk_len = gdata->heap_write_count - segment_size; - HPROF_ASSERT(last_chunk_len>=0); - - /* Re-open in proper way, binary vs. ascii is important */ - if (gdata->output_format == 'b') { - int tag; - - if ( gdata->segmented == JNI_TRUE ) { /* 1.0.2 */ - tag = HPROF_HEAP_DUMP_SEGMENT; /* 1.0.2 */ - } else { - tag = HPROF_HEAP_DUMP; /* Just one segment */ - HPROF_ASSERT(last_chunk_len==0); - } - - /* Write header for binary heap dump (don't know size until now) */ - write_header(tag, (jint)segment_size); - - fd = md_open_binary(gdata->heapfilename); - } else { - fd = md_open(gdata->heapfilename); - } - - /* Move file bytes into hprof dump file */ - write_raw_from_file(fd, segment_size, &write_raw); - - /* Clear the byte count and reset the heap file. */ - if ( md_seek(gdata->heap_fd, (jlong)0) != (jlong)0 ) { - HPROF_ERROR(JNI_TRUE, "Cannot seek to beginning of heap info file"); - } - gdata->heap_write_count = (jlong)0; - gdata->heap_last_tag_position = (jlong)0; - - /* Move trailing bytes from heap dump file to beginning of file */ - if ( last_chunk_len > 0 ) { - write_raw_from_file(fd, last_chunk_len, &heap_raw); - } - - /* Close the temp file handle */ - md_close(fd); -} - -void -io_heap_footer(void) -{ - HPROF_ASSERT(gdata->heap_fd >= 0); - - /* Flush all bytes to the heap dump file */ - heap_flush(); - - /* Send out the last (or maybe only) segment */ - dump_heap_segment_and_reset(gdata->heap_write_count); - - /* Write out the last tag */ - if (gdata->output_format != 'b') { - write_printf("HEAP DUMP END\n"); - } else { - if ( gdata->segmented == JNI_TRUE ) { /* 1.0.2 */ - write_header(HPROF_HEAP_DUMP_END, 0); - } - } -}