Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/hprof/hprof_io.c
38829 views
/*1* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* - Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* - Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* - Neither the name of Oracle nor the names of its15* contributors may be used to endorse or promote products derived16* from this software without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS19* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,20* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR22* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,23* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,24* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR25* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS28* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This source code is provided to illustrate the usage of a given feature33* or technique and has been deliberately simplified. Additional steps34* required for a production-quality application, such as security checks,35* input validation and proper error handling, might not be present in36* this sample code.37*/383940/* All I/O functionality for hprof. */4142/*43* The hprof agent has many forms of output:44*45* format=b gdata->output_format=='b'46* Binary format. Defined below. This is used by HAT.47* This is NOT the same format as emitted by JVMPI.48*49* format=a gdata->output_format=='a'50* Ascii format. Not exactly an ascii representation of the binary format.51*52* And many forms of dumps:53*54* heap=dump55* A large dump that in this implementation is written to a separate56* file first before being placed in the output file. Several reasons,57* the binary form needs a byte count of the length in the header, and58* references in this dump to other items need to be emitted first.59* So it's two pass, or use a temp file and copy.60* heap=sites61* Dumps the sites in the order of most allocations.62* cpu=samples63* Dumps the traces in order of most hits64* cpu=times65* Dumps the traces in the order of most time spent there.66* cpu=old (format=a only)67* Dumps out an older form of cpu output (old -prof format)68* monitor=y (format=a only)69* Dumps out a list of monitors in order of most contended.70*71* This file also includes a binary format check function that will read72* back in the hprof binary format and verify the syntax looks correct.73*74* WARNING: Besides the comments below, there is little format spec on this,75* however see:76* http://java.sun.com/j2se/1.4.2/docs/guide/jvmpi/jvmpi.html#hprof77*/7879#include "hprof.h"8081typedef TableIndex HprofId;8283#include "hprof_ioname.h"84#include "hprof_b_spec.h"8586static int type_size[ /*HprofType*/ ] = HPROF_TYPE_SIZES;8788static void dump_heap_segment_and_reset(jlong segment_size);8990static void91not_implemented(void)92{93}9495static IoNameIndex96get_name_index(char *name)97{98if (name != NULL && gdata->output_format == 'b') {99return ioname_find_or_create(name, NULL);100}101return 0;102}103104static char *105signature_to_name(char *sig)106{107char *ptr;108char *basename;109char *name;110int i;111int len;112int name_len;113114if ( sig != NULL ) {115switch ( sig[0] ) {116case JVM_SIGNATURE_CLASS:117ptr = strchr(sig+1, JVM_SIGNATURE_ENDCLASS);118if ( ptr == NULL ) {119basename = "Unknown_class";120break;121}122/*LINTED*/123name_len = (jint)(ptr - (sig+1));124name = HPROF_MALLOC(name_len+1);125(void)memcpy(name, sig+1, name_len);126name[name_len] = 0;127for ( i = 0 ; i < name_len ; i++ ) {128if ( name[i] == '/' ) name[i] = '.';129}130return name;131case JVM_SIGNATURE_ARRAY:132basename = signature_to_name(sig+1);133len = (int)strlen(basename);134name_len = len+2;135name = HPROF_MALLOC(name_len+1);136(void)memcpy(name, basename, len);137(void)memcpy(name+len, "[]", 2);138name[name_len] = 0;139HPROF_FREE(basename);140return name;141case JVM_SIGNATURE_FUNC:142ptr = strchr(sig+1, JVM_SIGNATURE_ENDFUNC);143if ( ptr == NULL ) {144basename = "Unknown_method";145break;146}147basename = "()"; /* Someday deal with method signatures */148break;149case JVM_SIGNATURE_BYTE:150basename = "byte";151break;152case JVM_SIGNATURE_CHAR:153basename = "char";154break;155case JVM_SIGNATURE_ENUM:156basename = "enum";157break;158case JVM_SIGNATURE_FLOAT:159basename = "float";160break;161case JVM_SIGNATURE_DOUBLE:162basename = "double";163break;164case JVM_SIGNATURE_INT:165basename = "int";166break;167case JVM_SIGNATURE_LONG:168basename = "long";169break;170case JVM_SIGNATURE_SHORT:171basename = "short";172break;173case JVM_SIGNATURE_VOID:174basename = "void";175break;176case JVM_SIGNATURE_BOOLEAN:177basename = "boolean";178break;179default:180basename = "Unknown_class";181break;182}183} else {184basename = "Unknown_class";185}186187/* Simple basename */188name_len = (int)strlen(basename);189name = HPROF_MALLOC(name_len+1);190(void)strcpy(name, basename);191return name;192}193194static int195size_from_field_info(int size)196{197if ( size == 0 ) {198size = (int)sizeof(HprofId);199}200return size;201}202203static void204type_from_signature(const char *sig, HprofType *kind, jint *size)205{206*kind = HPROF_NORMAL_OBJECT;207*size = 0;208switch ( sig[0] ) {209case JVM_SIGNATURE_ENUM:210case JVM_SIGNATURE_CLASS:211case JVM_SIGNATURE_ARRAY:212*kind = HPROF_NORMAL_OBJECT;213break;214case JVM_SIGNATURE_BOOLEAN:215*kind = HPROF_BOOLEAN;216break;217case JVM_SIGNATURE_CHAR:218*kind = HPROF_CHAR;219break;220case JVM_SIGNATURE_FLOAT:221*kind = HPROF_FLOAT;222break;223case JVM_SIGNATURE_DOUBLE:224*kind = HPROF_DOUBLE;225break;226case JVM_SIGNATURE_BYTE:227*kind = HPROF_BYTE;228break;229case JVM_SIGNATURE_SHORT:230*kind = HPROF_SHORT;231break;232case JVM_SIGNATURE_INT:233*kind = HPROF_INT;234break;235case JVM_SIGNATURE_LONG:236*kind = HPROF_LONG;237break;238default:239HPROF_ASSERT(0);240break;241}242*size = type_size[*kind];243}244245static void246type_array(const char *sig, HprofType *kind, jint *elem_size)247{248*kind = 0;249*elem_size = 0;250switch ( sig[0] ) {251case JVM_SIGNATURE_ARRAY:252type_from_signature(sig+1, kind, elem_size);253break;254}255}256257static void258system_error(const char *system_call, int rc, int errnum)259{260char buf[256];261char details[256];262263details[0] = 0;264if ( errnum != 0 ) {265md_system_error(details, (int)sizeof(details));266} else if ( rc >= 0 ) {267(void)strcpy(details,"Only part of buffer processed");268}269if ( details[0] == 0 ) {270(void)strcpy(details,"Unknown system error condition");271}272(void)md_snprintf(buf, sizeof(buf), "System %s failed: %s\n",273system_call, details);274HPROF_ERROR(JNI_TRUE, buf);275}276277static void278system_write(int fd, void *buf, int len, jboolean socket)279{280int res;281282HPROF_ASSERT(fd>=0);283if (socket) {284res = md_send(fd, buf, len, 0);285if (res < 0 || res!=len) {286system_error("send", res, errno);287}288} else {289res = md_write(fd, buf, len);290if (res < 0 || res!=len) {291system_error("write", res, errno);292}293}294}295296static void297write_flush(void)298{299HPROF_ASSERT(gdata->fd >= 0);300if (gdata->write_buffer_index) {301system_write(gdata->fd, gdata->write_buffer, gdata->write_buffer_index,302gdata->socket);303gdata->write_buffer_index = 0;304}305}306307static void308heap_flush(void)309{310HPROF_ASSERT(gdata->heap_fd >= 0);311if (gdata->heap_buffer_index) {312gdata->heap_write_count += (jlong)gdata->heap_buffer_index;313system_write(gdata->heap_fd, gdata->heap_buffer, gdata->heap_buffer_index,314JNI_FALSE);315gdata->heap_buffer_index = 0;316}317}318319static void320write_raw(void *buf, int len)321{322HPROF_ASSERT(gdata->fd >= 0);323if (gdata->write_buffer_index + len > gdata->write_buffer_size) {324write_flush();325if (len > gdata->write_buffer_size) {326system_write(gdata->fd, buf, len, gdata->socket);327return;328}329}330(void)memcpy(gdata->write_buffer + gdata->write_buffer_index, buf, len);331gdata->write_buffer_index += len;332}333334static void335write_u4(unsigned i)336{337i = md_htonl(i);338write_raw(&i, (jint)sizeof(unsigned));339}340341static void342write_u8(jlong t)343{344write_u4((jint)jlong_high(t));345write_u4((jint)jlong_low(t));346}347348static void349write_u2(unsigned short i)350{351i = md_htons(i);352write_raw(&i, (jint)sizeof(unsigned short));353}354355static void356write_u1(unsigned char i)357{358write_raw(&i, (jint)sizeof(unsigned char));359}360361static void362write_id(HprofId i)363{364write_u4(i);365}366367static void368write_current_ticks(void)369{370write_u4((jint)(md_get_microsecs() - gdata->micro_sec_ticks));371}372373static void374write_header(unsigned char type, jint length)375{376write_u1(type);377write_current_ticks();378write_u4(length);379}380381static void382write_index_id(HprofId index)383{384write_id(index);385}386387static IoNameIndex388write_name_first(char *name)389{390if ( name == NULL ) {391return 0;392}393if (gdata->output_format == 'b') {394IoNameIndex name_index;395jboolean new_one;396397new_one = JNI_FALSE;398name_index = ioname_find_or_create(name, &new_one);399if ( new_one ) {400int len;401402len = (int)strlen(name);403write_header(HPROF_UTF8, len + (jint)sizeof(HprofId));404write_index_id(name_index);405write_raw(name, len);406407}408return name_index;409}410return 0;411}412413static void414write_printf(char *fmt, ...)415{416char buf[1024];417va_list args;418va_start(args, fmt);419(void)md_vsnprintf(buf, sizeof(buf), fmt, args);420buf[sizeof(buf)-1] = 0;421write_raw(buf, (int)strlen(buf));422va_end(args);423}424425static void426write_thread_serial_number(SerialNumber thread_serial_num, int with_comma)427{428if ( thread_serial_num != 0 ) {429CHECK_THREAD_SERIAL_NO(thread_serial_num);430if ( with_comma ) {431write_printf(" thread %d,", thread_serial_num);432} else {433write_printf(" thread %d", thread_serial_num);434}435} else {436if ( with_comma ) {437write_printf(" <unknown thread>,");438} else {439write_printf(" <unknown thread>");440}441}442}443444static void445heap_raw(void *buf, int len)446{447HPROF_ASSERT(gdata->heap_fd >= 0);448if (gdata->heap_buffer_index + len > gdata->heap_buffer_size) {449heap_flush();450if (len > gdata->heap_buffer_size) {451gdata->heap_write_count += (jlong)len;452system_write(gdata->heap_fd, buf, len, JNI_FALSE);453return;454}455}456(void)memcpy(gdata->heap_buffer + gdata->heap_buffer_index, buf, len);457gdata->heap_buffer_index += len;458}459460static void461heap_u4(unsigned i)462{463i = md_htonl(i);464heap_raw(&i, (jint)sizeof(unsigned));465}466467static void468heap_u8(jlong i)469{470heap_u4((jint)jlong_high(i));471heap_u4((jint)jlong_low(i));472}473474static void475heap_u2(unsigned short i)476{477i = md_htons(i);478heap_raw(&i, (jint)sizeof(unsigned short));479}480481static void482heap_u1(unsigned char i)483{484heap_raw(&i, (jint)sizeof(unsigned char));485}486487/* Write out the first byte of a heap tag */488static void489heap_tag(unsigned char tag)490{491jlong pos;492493/* Current position in virtual heap dump file */494pos = gdata->heap_write_count + (jlong)gdata->heap_buffer_index;495if ( gdata->segmented == JNI_TRUE ) { /* 1.0.2 */496if ( pos >= gdata->maxHeapSegment ) {497/* Flush all bytes to the heap dump file */498heap_flush();499500/* Send out segment (up to last tag written out) */501dump_heap_segment_and_reset(gdata->heap_last_tag_position);502503/* Get new current position */504pos = gdata->heap_write_count + (jlong)gdata->heap_buffer_index;505}506}507/* Save position of this tag */508gdata->heap_last_tag_position = pos;509/* Write out this tag */510heap_u1(tag);511}512513static void514heap_id(HprofId i)515{516heap_u4(i);517}518519static void520heap_index_id(HprofId index)521{522heap_id(index);523}524525static void526heap_name(char *name)527{528heap_index_id(get_name_index(name));529}530531static void532heap_printf(char *fmt, ...)533{534char buf[1024];535va_list args;536va_start(args, fmt);537(void)md_vsnprintf(buf, sizeof(buf), fmt, args);538buf[sizeof(buf)-1] = 0;539heap_raw(buf, (int)strlen(buf));540va_end(args);541}542543static void544heap_element(HprofType kind, jint size, jvalue value)545{546if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) {547HPROF_ASSERT(size==4);548heap_id((HprofId)value.i);549} else {550switch ( size ) {551case 8:552HPROF_ASSERT(size==8);553HPROF_ASSERT(kind==HPROF_LONG || kind==HPROF_DOUBLE);554heap_u8(value.j);555break;556case 4:557HPROF_ASSERT(size==4);558HPROF_ASSERT(kind==HPROF_INT || kind==HPROF_FLOAT);559heap_u4(value.i);560break;561case 2:562HPROF_ASSERT(size==2);563HPROF_ASSERT(kind==HPROF_SHORT || kind==HPROF_CHAR);564heap_u2(value.s);565break;566case 1:567HPROF_ASSERT(size==1);568HPROF_ASSERT(kind==HPROF_BOOLEAN || kind==HPROF_BYTE);569HPROF_ASSERT(kind==HPROF_BOOLEAN?(value.b==0 || value.b==1):1);570heap_u1(value.b);571break;572default:573HPROF_ASSERT(0);574break;575}576}577}578579/* Dump out all elements of an array, objects in jvalues, prims packed */580static void581heap_elements(HprofType kind, jint num_elements, jint elem_size, void *elements)582{583int i;584jvalue val;585static jvalue empty_val;586587if ( num_elements == 0 ) {588return;589}590591switch ( kind ) {592case 0:593case HPROF_ARRAY_OBJECT:594case HPROF_NORMAL_OBJECT:595for (i = 0; i < num_elements; i++) {596val = empty_val;597val.i = ((ObjectIndex*)elements)[i];598heap_element(kind, elem_size, val);599}600break;601case HPROF_BYTE:602case HPROF_BOOLEAN:603HPROF_ASSERT(elem_size==1);604for (i = 0; i < num_elements; i++) {605val = empty_val;606val.b = ((jboolean*)elements)[i];607heap_element(kind, elem_size, val);608}609break;610case HPROF_CHAR:611case HPROF_SHORT:612HPROF_ASSERT(elem_size==2);613for (i = 0; i < num_elements; i++) {614val = empty_val;615val.s = ((jshort*)elements)[i];616heap_element(kind, elem_size, val);617}618break;619case HPROF_FLOAT:620case HPROF_INT:621HPROF_ASSERT(elem_size==4);622for (i = 0; i < num_elements; i++) {623val = empty_val;624val.i = ((jint*)elements)[i];625heap_element(kind, elem_size, val);626}627break;628case HPROF_DOUBLE:629case HPROF_LONG:630HPROF_ASSERT(elem_size==8);631for (i = 0; i < num_elements; i++) {632val = empty_val;633val.j = ((jlong*)elements)[i];634heap_element(kind, elem_size, val);635}636break;637}638}639640/* ------------------------------------------------------------------ */641642void643io_flush(void)644{645HPROF_ASSERT(gdata->header!=NULL);646write_flush();647}648649void650io_setup(void)651{652gdata->write_buffer_size = FILE_IO_BUFFER_SIZE;653gdata->write_buffer = HPROF_MALLOC(gdata->write_buffer_size);654gdata->write_buffer_index = 0;655656gdata->heap_write_count = (jlong)0;657gdata->heap_last_tag_position = (jlong)0;658gdata->heap_buffer_size = FILE_IO_BUFFER_SIZE;659gdata->heap_buffer = HPROF_MALLOC(gdata->heap_buffer_size);660gdata->heap_buffer_index = 0;661662if ( gdata->logflags & LOG_CHECK_BINARY ) {663gdata->check_buffer_size = FILE_IO_BUFFER_SIZE;664gdata->check_buffer = HPROF_MALLOC(gdata->check_buffer_size);665gdata->check_buffer_index = 0;666}667668ioname_init();669}670671void672io_cleanup(void)673{674if ( gdata->write_buffer != NULL ) {675HPROF_FREE(gdata->write_buffer);676}677gdata->write_buffer_size = 0;678gdata->write_buffer = NULL;679gdata->write_buffer_index = 0;680681if ( gdata->heap_buffer != NULL ) {682HPROF_FREE(gdata->heap_buffer);683}684gdata->heap_write_count = (jlong)0;685gdata->heap_last_tag_position = (jlong)0;686gdata->heap_buffer_size = 0;687gdata->heap_buffer = NULL;688gdata->heap_buffer_index = 0;689690if ( gdata->logflags & LOG_CHECK_BINARY ) {691if ( gdata->check_buffer != NULL ) {692HPROF_FREE(gdata->check_buffer);693}694gdata->check_buffer_size = 0;695gdata->check_buffer = NULL;696gdata->check_buffer_index = 0;697}698699ioname_cleanup();700}701702void703io_write_file_header(void)704{705HPROF_ASSERT(gdata->header!=NULL);706if (gdata->output_format == 'b') {707jint settings;708jlong t;709710settings = 0;711if (gdata->heap_dump || gdata->alloc_sites) {712settings |= 1;713}714if (gdata->cpu_sampling) {715settings |= 2;716}717t = md_get_timemillis();718719write_raw(gdata->header, (int)strlen(gdata->header) + 1);720write_u4((jint)sizeof(HprofId));721write_u8(t);722723write_header(HPROF_CONTROL_SETTINGS, 4 + 2);724write_u4(settings);725write_u2((unsigned short)gdata->max_trace_depth);726727} else if ((!gdata->cpu_timing) || (!gdata->old_timing_format)) {728/* We don't want the prelude file for the old prof output format */729time_t t;730char prelude_file[FILENAME_MAX];731int prelude_fd;732int nbytes;733734t = time(0);735736md_get_prelude_path(prelude_file, sizeof(prelude_file), PRELUDE_FILE);737738prelude_fd = md_open(prelude_file);739if (prelude_fd < 0) {740char buf[FILENAME_MAX+80];741742(void)md_snprintf(buf, sizeof(buf), "Can't open %s", prelude_file);743buf[sizeof(buf)-1] = 0;744HPROF_ERROR(JNI_TRUE, buf);745}746747write_printf("%s, created %s\n", gdata->header, ctime(&t));748749do {750char buf[1024]; /* File is small, small buffer ok here */751752nbytes = md_read(prelude_fd, buf, sizeof(buf));753if ( nbytes < 0 ) {754system_error("read", nbytes, errno);755break;756}757if (nbytes == 0) {758break;759}760write_raw(buf, nbytes);761} while ( nbytes > 0 );762763md_close(prelude_fd);764765write_printf("\n--------\n\n");766767write_flush();768}769}770771void772io_write_file_footer(void)773{774HPROF_ASSERT(gdata->header!=NULL);775}776777void778io_write_class_load(SerialNumber class_serial_num, ObjectIndex index,779SerialNumber trace_serial_num, char *sig)780{781CHECK_CLASS_SERIAL_NO(class_serial_num);782CHECK_TRACE_SERIAL_NO(trace_serial_num);783if (gdata->output_format == 'b') {784IoNameIndex name_index;785char *class_name;786787class_name = signature_to_name(sig);788name_index = write_name_first(class_name);789write_header(HPROF_LOAD_CLASS, (2 * (jint)sizeof(HprofId)) + (4 * 2));790write_u4(class_serial_num);791write_index_id(index);792write_u4(trace_serial_num);793write_index_id(name_index);794HPROF_FREE(class_name);795}796}797798void799io_write_class_unload(SerialNumber class_serial_num, ObjectIndex index)800{801CHECK_CLASS_SERIAL_NO(class_serial_num);802if (gdata->output_format == 'b') {803write_header(HPROF_UNLOAD_CLASS, 4);804write_u4(class_serial_num);805}806}807808void809io_write_sites_header(const char * comment_str, jint flags, double cutoff,810jint total_live_bytes, jint total_live_instances,811jlong total_alloced_bytes, jlong total_alloced_instances,812jint count)813{814if ( gdata->output_format == 'b') {815write_header(HPROF_ALLOC_SITES, 2 + (8 * 4) + (count * (4 * 6 + 1)));816write_u2((unsigned short)flags);817write_u4(*(int *)(&cutoff));818write_u4(total_live_bytes);819write_u4(total_live_instances);820write_u8(total_alloced_bytes);821write_u8(total_alloced_instances);822write_u4(count);823} else {824time_t t;825826t = time(0);827write_printf("SITES BEGIN (ordered by %s) %s", comment_str, ctime(&t));828write_printf(829" percent live alloc'ed stack class\n");830write_printf(831" rank self accum bytes objs bytes objs trace name\n");832}833}834835void836io_write_sites_elem(jint index, double ratio, double accum_percent,837char *sig, SerialNumber class_serial_num,838SerialNumber trace_serial_num, jint n_live_bytes,839jint n_live_instances, jint n_alloced_bytes,840jint n_alloced_instances)841{842CHECK_CLASS_SERIAL_NO(class_serial_num);843CHECK_TRACE_SERIAL_NO(trace_serial_num);844if ( gdata->output_format == 'b') {845HprofType kind;846jint size;847848type_array(sig, &kind, &size);849write_u1(kind);850write_u4(class_serial_num);851write_u4(trace_serial_num);852write_u4(n_live_bytes);853write_u4(n_live_instances);854write_u4(n_alloced_bytes);855write_u4(n_alloced_instances);856} else {857char *class_name;858859class_name = signature_to_name(sig);860write_printf("%5u %5.2f%% %5.2f%% %9u %4u %9u %5u %5u %s\n",861index,862ratio * 100.0,863accum_percent * 100.0,864n_live_bytes,865n_live_instances,866n_alloced_bytes,867n_alloced_instances,868trace_serial_num,869class_name);870HPROF_FREE(class_name);871}872}873874void875io_write_sites_footer(void)876{877if (gdata->output_format == 'b') {878not_implemented();879} else {880write_printf("SITES END\n");881}882}883884void885io_write_thread_start(SerialNumber thread_serial_num,886ObjectIndex thread_obj_id,887SerialNumber trace_serial_num, char *thread_name,888char *thread_group_name, char *thread_parent_name)889{890CHECK_THREAD_SERIAL_NO(thread_serial_num);891CHECK_TRACE_SERIAL_NO(trace_serial_num);892if (gdata->output_format == 'b') {893IoNameIndex tname_index;894IoNameIndex gname_index;895IoNameIndex pname_index;896897tname_index = write_name_first(thread_name);898gname_index = write_name_first(thread_group_name);899pname_index = write_name_first(thread_parent_name);900write_header(HPROF_START_THREAD, ((jint)sizeof(HprofId) * 4) + (4 * 2));901write_u4(thread_serial_num);902write_index_id(thread_obj_id);903write_u4(trace_serial_num);904write_index_id(tname_index);905write_index_id(gname_index);906write_index_id(pname_index);907908} else if ( (!gdata->cpu_timing) || (!gdata->old_timing_format)) {909/* We don't want thread info for the old prof output format */910write_printf("THREAD START "911"(obj=%x, id = %d, name=\"%s\", group=\"%s\")\n",912thread_obj_id, thread_serial_num,913(thread_name==NULL?"":thread_name),914(thread_group_name==NULL?"":thread_group_name));915}916}917918void919io_write_thread_end(SerialNumber thread_serial_num)920{921CHECK_THREAD_SERIAL_NO(thread_serial_num);922if (gdata->output_format == 'b') {923write_header(HPROF_END_THREAD, 4);924write_u4(thread_serial_num);925926} else if ( (!gdata->cpu_timing) || (!gdata->old_timing_format)) {927/* we don't want thread info for the old prof output format */928write_printf("THREAD END (id = %d)\n", thread_serial_num);929}930}931932void933io_write_frame(FrameIndex index, SerialNumber frame_serial_num,934char *mname, char *msig, char *sname,935SerialNumber class_serial_num, jint lineno)936{937CHECK_CLASS_SERIAL_NO(class_serial_num);938if (gdata->output_format == 'b') {939IoNameIndex mname_index;940IoNameIndex msig_index;941IoNameIndex sname_index;942943mname_index = write_name_first(mname);944msig_index = write_name_first(msig);945sname_index = write_name_first(sname);946947write_header(HPROF_FRAME, ((jint)sizeof(HprofId) * 4) + (4 * 2));948write_index_id(index);949write_index_id(mname_index);950write_index_id(msig_index);951write_index_id(sname_index);952write_u4(class_serial_num);953write_u4(lineno);954}955}956957void958io_write_trace_header(SerialNumber trace_serial_num,959SerialNumber thread_serial_num, jint n_frames, char *phase_str)960{961CHECK_TRACE_SERIAL_NO(trace_serial_num);962if (gdata->output_format == 'b') {963write_header(HPROF_TRACE, ((jint)sizeof(HprofId) * n_frames) + (4 * 3));964write_u4(trace_serial_num);965write_u4(thread_serial_num);966write_u4(n_frames);967} else {968write_printf("TRACE %u:", trace_serial_num);969if (thread_serial_num) {970write_printf(" (thread=%d)", thread_serial_num);971}972if ( phase_str != NULL ) {973write_printf(" (from %s phase of JVM)", phase_str);974}975write_printf("\n");976if (n_frames == 0) {977write_printf("\t<empty>\n");978}979}980}981982void983io_write_trace_elem(SerialNumber trace_serial_num, FrameIndex frame_index,984SerialNumber frame_serial_num,985char *csig, char *mname, char *sname, jint lineno)986{987if (gdata->output_format == 'b') {988write_index_id(frame_index);989} else {990char *class_name;991char linebuf[32];992993if (lineno == -2) {994(void)md_snprintf(linebuf, sizeof(linebuf), "Compiled method");995} else if (lineno == -3) {996(void)md_snprintf(linebuf, sizeof(linebuf), "Native method");997} else if (lineno == -1) {998(void)md_snprintf(linebuf, sizeof(linebuf), "Unknown line");999} else {1000(void)md_snprintf(linebuf, sizeof(linebuf), "%d", lineno);1001}1002linebuf[sizeof(linebuf)-1] = 0;1003class_name = signature_to_name(csig);1004if ( mname == NULL ) {1005mname = "<Unknown Method>";1006}1007if ( sname == NULL ) {1008sname = "<Unknown Source>";1009}1010write_printf("\t%s.%s(%s:%s)\n", class_name, mname, sname, linebuf);1011HPROF_FREE(class_name);1012}1013}10141015void1016io_write_trace_footer(SerialNumber trace_serial_num,1017SerialNumber thread_serial_num, jint n_frames)1018{1019}10201021#define CPU_SAMPLES_RECORD_NAME ("CPU SAMPLES")1022#define CPU_TIMES_RECORD_NAME ("CPU TIME (ms)")10231024void1025io_write_cpu_samples_header(jlong total_cost, jint n_items)1026{10271028if (gdata->output_format == 'b') {1029write_header(HPROF_CPU_SAMPLES, (n_items * (4 * 2)) + (4 * 2));1030write_u4((jint)total_cost);1031write_u4(n_items);1032} else {1033time_t t;1034char *record_name;10351036if ( gdata->cpu_sampling ) {1037record_name = CPU_SAMPLES_RECORD_NAME;1038} else {1039record_name = CPU_TIMES_RECORD_NAME;1040}1041t = time(0);1042write_printf("%s BEGIN (total = %d) %s", record_name,1043/*jlong*/(int)total_cost, ctime(&t));1044if ( n_items > 0 ) {1045write_printf("rank self accum count trace method\n");1046}1047}1048}10491050void1051io_write_cpu_samples_elem(jint index, double percent, double accum,1052jint num_hits, jlong cost, SerialNumber trace_serial_num,1053jint n_frames, char *csig, char *mname)1054{1055CHECK_TRACE_SERIAL_NO(trace_serial_num);1056if (gdata->output_format == 'b') {1057write_u4((jint)cost);1058write_u4(trace_serial_num);1059} else {1060write_printf("%4u %5.2f%% %5.2f%% %7u %5u",1061index, percent, accum, num_hits,1062trace_serial_num);1063if (n_frames > 0) {1064char * class_name;10651066class_name = signature_to_name(csig);1067write_printf(" %s.%s\n", class_name, mname);1068HPROF_FREE(class_name);1069} else {1070write_printf(" <empty trace>\n");1071}1072}1073}10741075void1076io_write_cpu_samples_footer(void)1077{1078if (gdata->output_format == 'b') {1079not_implemented();1080} else {1081char *record_name;10821083if ( gdata->cpu_sampling ) {1084record_name = CPU_SAMPLES_RECORD_NAME;1085} else {1086record_name = CPU_TIMES_RECORD_NAME;1087}1088write_printf("%s END\n", record_name);1089}1090}10911092void1093io_write_heap_summary(jlong total_live_bytes, jlong total_live_instances,1094jlong total_alloced_bytes, jlong total_alloced_instances)1095{1096if (gdata->output_format == 'b') {1097write_header(HPROF_HEAP_SUMMARY, 4 * 6);1098write_u4((jint)total_live_bytes);1099write_u4((jint)total_live_instances);1100write_u8(total_alloced_bytes);1101write_u8(total_alloced_instances);1102}1103}11041105void1106io_write_oldprof_header(void)1107{1108if ( gdata->old_timing_format ) {1109write_printf("count callee caller time\n");1110}1111}11121113void1114io_write_oldprof_elem(jint num_hits, jint num_frames, char *csig_callee,1115char *mname_callee, char *msig_callee, char *csig_caller,1116char *mname_caller, char *msig_caller, jlong cost)1117{1118if ( gdata->old_timing_format ) {1119char * class_name_callee;1120char * class_name_caller;11211122class_name_callee = signature_to_name(csig_callee);1123class_name_caller = signature_to_name(csig_caller);1124write_printf("%d ", num_hits);1125if (num_frames >= 1) {1126write_printf("%s.%s%s ", class_name_callee,1127mname_callee, msig_callee);1128} else {1129write_printf("%s ", "<unknown callee>");1130}1131if (num_frames > 1) {1132write_printf("%s.%s%s ", class_name_caller,1133mname_caller, msig_caller);1134} else {1135write_printf("%s ", "<unknown caller>");1136}1137write_printf("%d\n", (int)cost);1138HPROF_FREE(class_name_callee);1139HPROF_FREE(class_name_caller);1140}1141}11421143void1144io_write_oldprof_footer(void)1145{1146}11471148void1149io_write_monitor_header(jlong total_time)1150{1151if (gdata->output_format == 'b') {1152not_implemented();1153} else {1154time_t t = time(0);11551156t = time(0);1157write_printf("MONITOR TIME BEGIN (total = %u ms) %s",1158(int)total_time, ctime(&t));1159if (total_time > 0) {1160write_printf("rank self accum count trace monitor\n");1161}1162}1163}11641165void1166io_write_monitor_elem(jint index, double percent, double accum,1167jint num_hits, SerialNumber trace_serial_num, char *sig)1168{1169CHECK_TRACE_SERIAL_NO(trace_serial_num);1170if (gdata->output_format == 'b') {1171not_implemented();1172} else {1173char *class_name;11741175class_name = signature_to_name(sig);1176write_printf("%4u %5.2f%% %5.2f%% %7u %5u %s (Java)\n",1177index, percent, accum, num_hits,1178trace_serial_num, class_name);1179HPROF_FREE(class_name);1180}1181}11821183void1184io_write_monitor_footer(void)1185{1186if (gdata->output_format == 'b') {1187not_implemented();1188} else {1189write_printf("MONITOR TIME END\n");1190}1191}11921193void1194io_write_monitor_sleep(jlong timeout, SerialNumber thread_serial_num)1195{1196if (gdata->output_format == 'b') {1197not_implemented();1198} else {1199if ( thread_serial_num == 0 ) {1200write_printf("SLEEP: timeout=%d, <unknown thread>\n",1201(int)timeout);1202} else {1203CHECK_THREAD_SERIAL_NO(thread_serial_num);1204write_printf("SLEEP: timeout=%d, thread %d\n",1205(int)timeout, thread_serial_num);1206}1207}1208}12091210void1211io_write_monitor_wait(char *sig, jlong timeout,1212SerialNumber thread_serial_num)1213{1214if (gdata->output_format == 'b') {1215not_implemented();1216} else {1217if ( thread_serial_num == 0 ) {1218write_printf("WAIT: MONITOR %s, timeout=%d, <unknown thread>\n",1219sig, (int)timeout);1220} else {1221CHECK_THREAD_SERIAL_NO(thread_serial_num);1222write_printf("WAIT: MONITOR %s, timeout=%d, thread %d\n",1223sig, (int)timeout, thread_serial_num);1224}1225}1226}12271228void1229io_write_monitor_waited(char *sig, jlong time_waited,1230SerialNumber thread_serial_num)1231{1232if (gdata->output_format == 'b') {1233not_implemented();1234} else {1235if ( thread_serial_num == 0 ) {1236write_printf("WAITED: MONITOR %s, time_waited=%d, <unknown thread>\n",1237sig, (int)time_waited);1238} else {1239CHECK_THREAD_SERIAL_NO(thread_serial_num);1240write_printf("WAITED: MONITOR %s, time_waited=%d, thread %d\n",1241sig, (int)time_waited, thread_serial_num);1242}1243}1244}12451246void1247io_write_monitor_exit(char *sig, SerialNumber thread_serial_num)1248{1249if (gdata->output_format == 'b') {1250not_implemented();1251} else {1252if ( thread_serial_num == 0 ) {1253write_printf("EXIT: MONITOR %s, <unknown thread>\n", sig);1254} else {1255CHECK_THREAD_SERIAL_NO(thread_serial_num);1256write_printf("EXIT: MONITOR %s, thread %d\n",1257sig, thread_serial_num);1258}1259}1260}12611262void1263io_write_monitor_dump_header(void)1264{1265if (gdata->output_format == 'b') {1266not_implemented();1267} else {1268write_printf("MONITOR DUMP BEGIN\n");1269}1270}12711272void1273io_write_monitor_dump_thread_state(SerialNumber thread_serial_num,1274SerialNumber trace_serial_num,1275jint threadState)1276{1277CHECK_THREAD_SERIAL_NO(thread_serial_num);1278CHECK_TRACE_SERIAL_NO(trace_serial_num);1279if (gdata->output_format == 'b') {1280not_implemented();1281} else {1282char tstate[20];12831284tstate[0] = 0;12851286if (threadState & JVMTI_THREAD_STATE_SUSPENDED) {1287(void)strcat(tstate,"S|");1288}1289if (threadState & JVMTI_THREAD_STATE_INTERRUPTED) {1290(void)strcat(tstate,"intr|");1291}1292if (threadState & JVMTI_THREAD_STATE_IN_NATIVE) {1293(void)strcat(tstate,"native|");1294}1295if ( ! ( threadState & JVMTI_THREAD_STATE_ALIVE ) ) {1296if ( threadState & JVMTI_THREAD_STATE_TERMINATED ) {1297(void)strcat(tstate,"ZO");1298} else {1299(void)strcat(tstate,"NS");1300}1301} else {1302if ( threadState & JVMTI_THREAD_STATE_SLEEPING ) {1303(void)strcat(tstate,"SL");1304} else if ( threadState & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER ) {1305(void)strcat(tstate,"MW");1306} else if ( threadState & JVMTI_THREAD_STATE_WAITING ) {1307(void)strcat(tstate,"CW");1308} else if ( threadState & JVMTI_THREAD_STATE_RUNNABLE ) {1309(void)strcat(tstate,"R");1310} else {1311(void)strcat(tstate,"UN");1312}1313}1314write_printf(" THREAD %d, trace %d, status: %s\n",1315thread_serial_num, trace_serial_num, tstate);1316}1317}13181319void1320io_write_monitor_dump_state(char *sig, SerialNumber thread_serial_num,1321jint entry_count,1322SerialNumber *waiters, jint waiter_count,1323SerialNumber *notify_waiters, jint notify_waiter_count)1324{1325if (gdata->output_format == 'b') {1326not_implemented();1327} else {1328int i;13291330if ( thread_serial_num != 0 ) {1331CHECK_THREAD_SERIAL_NO(thread_serial_num);1332write_printf(" MONITOR %s\n", sig);1333write_printf("\towner: thread %d, entry count: %d\n",1334thread_serial_num, entry_count);1335} else {1336write_printf(" MONITOR %s unowned\n", sig);1337}1338write_printf("\twaiting to enter:");1339for (i = 0; i < waiter_count; i++) {1340write_thread_serial_number(waiters[i],1341(i != (waiter_count-1)));1342}1343write_printf("\n");1344write_printf("\twaiting to be notified:");1345for (i = 0; i < notify_waiter_count; i++) {1346write_thread_serial_number(notify_waiters[i],1347(i != (notify_waiter_count-1)));1348}1349write_printf("\n");1350}1351}13521353void1354io_write_monitor_dump_footer(void)1355{1356if (gdata->output_format == 'b') {1357not_implemented();1358} else {1359write_printf("MONITOR DUMP END\n");1360}1361}13621363/* ----------------------------------------------------------------- */1364/* These functions write to a separate file */13651366void1367io_heap_header(jlong total_live_instances, jlong total_live_bytes)1368{1369if (gdata->output_format != 'b') {1370time_t t;13711372t = time(0);1373heap_printf("HEAP DUMP BEGIN (%u objects, %u bytes) %s",1374/*jlong*/(int)total_live_instances,1375/*jlong*/(int)total_live_bytes, ctime(&t));1376}1377}13781379void1380io_heap_root_thread_object(ObjectIndex thread_obj_id,1381SerialNumber thread_serial_num, SerialNumber trace_serial_num)1382{1383CHECK_THREAD_SERIAL_NO(thread_serial_num);1384CHECK_TRACE_SERIAL_NO(trace_serial_num);1385if (gdata->output_format == 'b') {1386heap_tag(HPROF_GC_ROOT_THREAD_OBJ);1387heap_id(thread_obj_id);1388heap_u4(thread_serial_num);1389heap_u4(trace_serial_num);1390} else {1391heap_printf("ROOT %x (kind=<thread>, id=%u, trace=%u)\n",1392thread_obj_id, thread_serial_num, trace_serial_num);1393}1394}13951396void1397io_heap_root_unknown(ObjectIndex obj_id)1398{1399if (gdata->output_format == 'b') {1400heap_tag(HPROF_GC_ROOT_UNKNOWN);1401heap_id(obj_id);1402} else {1403heap_printf("ROOT %x (kind=<unknown>)\n", obj_id);1404}1405}14061407void1408io_heap_root_jni_global(ObjectIndex obj_id, SerialNumber gref_serial_num,1409SerialNumber trace_serial_num)1410{1411CHECK_TRACE_SERIAL_NO(trace_serial_num);1412if (gdata->output_format == 'b') {1413heap_tag(HPROF_GC_ROOT_JNI_GLOBAL);1414heap_id(obj_id);1415heap_id(gref_serial_num);1416} else {1417heap_printf("ROOT %x (kind=<JNI global ref>, "1418"id=%x, trace=%u)\n",1419obj_id, gref_serial_num, trace_serial_num);1420}1421}14221423void1424io_heap_root_jni_local(ObjectIndex obj_id, SerialNumber thread_serial_num,1425jint frame_depth)1426{1427CHECK_THREAD_SERIAL_NO(thread_serial_num);1428if (gdata->output_format == 'b') {1429heap_tag(HPROF_GC_ROOT_JNI_LOCAL);1430heap_id(obj_id);1431heap_u4(thread_serial_num);1432heap_u4(frame_depth);1433} else {1434heap_printf("ROOT %x (kind=<JNI local ref>, "1435"thread=%u, frame=%d)\n",1436obj_id, thread_serial_num, frame_depth);1437}1438}14391440void1441io_heap_root_system_class(ObjectIndex obj_id, char *sig, SerialNumber class_serial_num)1442{1443if (gdata->output_format == 'b') {1444heap_tag(HPROF_GC_ROOT_STICKY_CLASS);1445heap_id(obj_id);1446} else {1447char *class_name;14481449class_name = signature_to_name(sig);1450heap_printf("ROOT %x (kind=<system class>, name=%s)\n",1451obj_id, class_name);1452HPROF_FREE(class_name);1453}1454}14551456void1457io_heap_root_monitor(ObjectIndex obj_id)1458{1459if (gdata->output_format == 'b') {1460heap_tag(HPROF_GC_ROOT_MONITOR_USED);1461heap_id(obj_id);1462} else {1463heap_printf("ROOT %x (kind=<busy monitor>)\n", obj_id);1464}1465}14661467void1468io_heap_root_thread(ObjectIndex obj_id, SerialNumber thread_serial_num)1469{1470CHECK_THREAD_SERIAL_NO(thread_serial_num);1471if (gdata->output_format == 'b') {1472heap_tag(HPROF_GC_ROOT_THREAD_BLOCK);1473heap_id(obj_id);1474heap_u4(thread_serial_num);1475} else {1476heap_printf("ROOT %x (kind=<thread block>, thread=%u)\n",1477obj_id, thread_serial_num);1478}1479}14801481void1482io_heap_root_java_frame(ObjectIndex obj_id, SerialNumber thread_serial_num,1483jint frame_depth)1484{1485CHECK_THREAD_SERIAL_NO(thread_serial_num);1486if (gdata->output_format == 'b') {1487heap_tag(HPROF_GC_ROOT_JAVA_FRAME);1488heap_id(obj_id);1489heap_u4(thread_serial_num);1490heap_u4(frame_depth);1491} else {1492heap_printf("ROOT %x (kind=<Java stack>, "1493"thread=%u, frame=%d)\n",1494obj_id, thread_serial_num, frame_depth);1495}1496}14971498void1499io_heap_root_native_stack(ObjectIndex obj_id, SerialNumber thread_serial_num)1500{1501CHECK_THREAD_SERIAL_NO(thread_serial_num);1502if (gdata->output_format == 'b') {1503heap_tag(HPROF_GC_ROOT_NATIVE_STACK);1504heap_id(obj_id);1505heap_u4(thread_serial_num);1506} else {1507heap_printf("ROOT %x (kind=<native stack>, thread=%u)\n",1508obj_id, thread_serial_num);1509}1510}15111512static jboolean1513is_static_field(jint modifiers)1514{1515if ( modifiers & JVM_ACC_STATIC ) {1516return JNI_TRUE;1517}1518return JNI_FALSE;1519}15201521static jboolean1522is_inst_field(jint modifiers)1523{1524if ( modifiers & JVM_ACC_STATIC ) {1525return JNI_FALSE;1526}1527return JNI_TRUE;1528}15291530void1531io_heap_class_dump(ClassIndex cnum, char *sig, ObjectIndex class_id,1532SerialNumber trace_serial_num,1533ObjectIndex super_id, ObjectIndex loader_id,1534ObjectIndex signers_id, ObjectIndex domain_id,1535jint size,1536jint n_cpool, ConstantPoolValue *cpool,1537jint n_fields, FieldInfo *fields, jvalue *fvalues)1538{1539CHECK_TRACE_SERIAL_NO(trace_serial_num);1540if (gdata->output_format == 'b') {1541int i;1542jint n_static_fields;1543jint n_inst_fields;1544jint inst_size;1545jint saved_inst_size;15461547n_static_fields = 0;1548n_inst_fields = 0;1549inst_size = 0;15501551/* These do NOT go into the heap output */1552for ( i = 0 ; i < n_fields ; i++ ) {1553if ( fields[i].cnum == cnum &&1554is_static_field(fields[i].modifiers) ) {1555char *field_name;15561557field_name = string_get(fields[i].name_index);1558(void)write_name_first(field_name);1559n_static_fields++;1560}1561if ( is_inst_field(fields[i].modifiers) ) {1562inst_size += size_from_field_info(fields[i].primSize);1563if ( fields[i].cnum == cnum ) {1564char *field_name;15651566field_name = string_get(fields[i].name_index);1567(void)write_name_first(field_name);1568n_inst_fields++;1569}1570}1571}15721573/* Verify that the instance size we have calculated as we went1574* through the fields, matches what is saved away with this1575* class.1576*/1577if ( size >= 0 ) {1578saved_inst_size = class_get_inst_size(cnum);1579if ( saved_inst_size == -1 ) {1580class_set_inst_size(cnum, inst_size);1581} else if ( saved_inst_size != inst_size ) {1582HPROF_ERROR(JNI_TRUE, "Mis-match on instance size in class dump");1583}1584}15851586heap_tag(HPROF_GC_CLASS_DUMP);1587heap_id(class_id);1588heap_u4(trace_serial_num);1589heap_id(super_id);1590heap_id(loader_id);1591heap_id(signers_id);1592heap_id(domain_id);1593heap_id(0);1594heap_id(0);1595heap_u4(inst_size); /* Must match inst_size in instance dump */15961597heap_u2((unsigned short)n_cpool);1598for ( i = 0 ; i < n_cpool ; i++ ) {1599HprofType kind;1600jint size;16011602type_from_signature(string_get(cpool[i].sig_index),1603&kind, &size);1604heap_u2((unsigned short)(cpool[i].constant_pool_index));1605heap_u1(kind);1606HPROF_ASSERT(!HPROF_TYPE_IS_PRIMITIVE(kind));1607heap_element(kind, size, cpool[i].value);1608}16091610heap_u2((unsigned short)n_static_fields);1611for ( i = 0 ; i < n_fields ; i++ ) {1612if ( fields[i].cnum == cnum &&1613is_static_field(fields[i].modifiers) ) {1614char *field_name;1615HprofType kind;1616jint size;16171618type_from_signature(string_get(fields[i].sig_index),1619&kind, &size);1620field_name = string_get(fields[i].name_index);1621heap_name(field_name);1622heap_u1(kind);1623heap_element(kind, size, fvalues[i]);1624}1625}16261627heap_u2((unsigned short)n_inst_fields); /* Does not include super class */1628for ( i = 0 ; i < n_fields ; i++ ) {1629if ( fields[i].cnum == cnum &&1630is_inst_field(fields[i].modifiers) ) {1631HprofType kind;1632jint size;1633char *field_name;16341635field_name = string_get(fields[i].name_index);1636type_from_signature(string_get(fields[i].sig_index),1637&kind, &size);1638heap_name(field_name);1639heap_u1(kind);1640}1641}1642} else {1643char * class_name;1644int i;16451646class_name = signature_to_name(sig);1647heap_printf("CLS %x (name=%s, trace=%u)\n",1648class_id, class_name, trace_serial_num);1649HPROF_FREE(class_name);1650if (super_id) {1651heap_printf("\tsuper\t\t%x\n", super_id);1652}1653if (loader_id) {1654heap_printf("\tloader\t\t%x\n", loader_id);1655}1656if (signers_id) {1657heap_printf("\tsigners\t\t%x\n", signers_id);1658}1659if (domain_id) {1660heap_printf("\tdomain\t\t%x\n", domain_id);1661}1662for ( i = 0 ; i < n_fields ; i++ ) {1663if ( fields[i].cnum == cnum &&1664is_static_field(fields[i].modifiers) ) {1665HprofType kind;1666jint size;16671668type_from_signature(string_get(fields[i].sig_index),1669&kind, &size);1670if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) {1671if (fvalues[i].i != 0 ) {1672char *field_name;16731674field_name = string_get(fields[i].name_index);1675heap_printf("\tstatic %s\t%x\n", field_name,1676fvalues[i].i);1677}1678}1679}1680}1681for ( i = 0 ; i < n_cpool ; i++ ) {1682HprofType kind;1683jint size;16841685type_from_signature(string_get(cpool[i].sig_index), &kind, &size);1686if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) {1687if (cpool[i].value.i != 0 ) {1688heap_printf("\tconstant pool entry %d\t%x\n",1689cpool[i].constant_pool_index, cpool[i].value.i);1690}1691}1692}1693}1694}16951696/* Dump the instance fields in the right order. */1697static int1698dump_instance_fields(ClassIndex cnum,1699FieldInfo *fields, jvalue *fvalues, jint n_fields)1700{1701ClassIndex super_cnum;1702int i;1703int nbytes;17041705HPROF_ASSERT(cnum!=0);17061707nbytes = 0;1708for (i = 0; i < n_fields; i++) {1709if ( fields[i].cnum == cnum &&1710is_inst_field(fields[i].modifiers) ) {1711HprofType kind;1712int size;17131714type_from_signature(string_get(fields[i].sig_index),1715&kind, &size);1716heap_element(kind, size, fvalues[i]);1717nbytes += size;1718}1719}17201721super_cnum = class_get_super(cnum);1722if ( super_cnum != 0 ) {1723nbytes += dump_instance_fields(super_cnum, fields, fvalues, n_fields);1724}1725return nbytes;1726}17271728void1729io_heap_instance_dump(ClassIndex cnum, ObjectIndex obj_id,1730SerialNumber trace_serial_num,1731ObjectIndex class_id, jint size, char *sig,1732FieldInfo *fields, jvalue *fvalues, jint n_fields)1733{1734CHECK_TRACE_SERIAL_NO(trace_serial_num);1735if (gdata->output_format == 'b') {1736jint inst_size;1737jint saved_inst_size;1738int i;1739int nbytes;17401741inst_size = 0;1742for (i = 0; i < n_fields; i++) {1743if ( is_inst_field(fields[i].modifiers) ) {1744inst_size += size_from_field_info(fields[i].primSize);1745}1746}17471748/* Verify that the instance size we have calculated as we went1749* through the fields, matches what is saved away with this1750* class.1751*/1752saved_inst_size = class_get_inst_size(cnum);1753if ( saved_inst_size == -1 ) {1754class_set_inst_size(cnum, inst_size);1755} else if ( saved_inst_size != inst_size ) {1756HPROF_ERROR(JNI_TRUE, "Mis-match on instance size in instance dump");1757}17581759heap_tag(HPROF_GC_INSTANCE_DUMP);1760heap_id(obj_id);1761heap_u4(trace_serial_num);1762heap_id(class_id);1763heap_u4(inst_size); /* Must match inst_size in class dump */17641765/* Order must be class, super, super's super, ... */1766nbytes = dump_instance_fields(cnum, fields, fvalues, n_fields);1767HPROF_ASSERT(nbytes==inst_size);1768} else {1769char * class_name;1770int i;17711772class_name = signature_to_name(sig);1773heap_printf("OBJ %x (sz=%u, trace=%u, class=%s@%x)\n",1774obj_id, size, trace_serial_num, class_name, class_id);1775HPROF_FREE(class_name);17761777for (i = 0; i < n_fields; i++) {1778if ( is_inst_field(fields[i].modifiers) ) {1779HprofType kind;1780int size;17811782type_from_signature(string_get(fields[i].sig_index),1783&kind, &size);1784if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) {1785if (fvalues[i].i != 0 ) {1786char *sep;1787ObjectIndex val_id;1788char *field_name;17891790field_name = string_get(fields[i].name_index);1791val_id = (ObjectIndex)(fvalues[i].i);1792sep = (int)strlen(field_name) < 8 ? "\t" : "";1793heap_printf("\t%s\t%s%x\n", field_name, sep, val_id);1794}1795}1796}1797}1798}1799}18001801void1802io_heap_object_array(ObjectIndex obj_id, SerialNumber trace_serial_num,1803jint size, jint num_elements, char *sig, ObjectIndex *values,1804ObjectIndex class_id)1805{1806CHECK_TRACE_SERIAL_NO(trace_serial_num);1807if (gdata->output_format == 'b') {18081809heap_tag(HPROF_GC_OBJ_ARRAY_DUMP);1810heap_id(obj_id);1811heap_u4(trace_serial_num);1812heap_u4(num_elements);1813heap_id(class_id);1814heap_elements(HPROF_NORMAL_OBJECT, num_elements,1815(jint)sizeof(HprofId), (void*)values);1816} else {1817char *name;1818int i;18191820name = signature_to_name(sig);1821heap_printf("ARR %x (sz=%u, trace=%u, nelems=%u, elem type=%s@%x)\n",1822obj_id, size, trace_serial_num, num_elements,1823name, class_id);1824for (i = 0; i < num_elements; i++) {1825ObjectIndex id;18261827id = values[i];1828if (id != 0) {1829heap_printf("\t[%u]\t\t%x\n", i, id);1830}1831}1832HPROF_FREE(name);1833}1834}18351836void1837io_heap_prim_array(ObjectIndex obj_id, SerialNumber trace_serial_num,1838jint size, jint num_elements, char *sig, void *elements)1839{1840CHECK_TRACE_SERIAL_NO(trace_serial_num);1841if (gdata->output_format == 'b') {1842HprofType kind;1843jint esize;18441845type_array(sig, &kind, &esize);1846HPROF_ASSERT(HPROF_TYPE_IS_PRIMITIVE(kind));1847heap_tag(HPROF_GC_PRIM_ARRAY_DUMP);1848heap_id(obj_id);1849heap_u4(trace_serial_num);1850heap_u4(num_elements);1851heap_u1(kind);1852heap_elements(kind, num_elements, esize, elements);1853} else {1854char *name;18551856name = signature_to_name(sig);1857heap_printf("ARR %x (sz=%u, trace=%u, nelems=%u, elem type=%s)\n",1858obj_id, size, trace_serial_num, num_elements, name);1859HPROF_FREE(name);1860}1861}18621863/* Move file bytes into supplied raw interface */1864static void1865write_raw_from_file(int fd, jlong byteCount, void (*raw_interface)(void *,int))1866{1867char *buf;1868int buf_len;1869int left;1870int nbytes;18711872HPROF_ASSERT(fd >= 0);18731874/* Move contents of this file into output file. */1875buf_len = FILE_IO_BUFFER_SIZE*2; /* Twice as big! */1876buf = HPROF_MALLOC(buf_len);1877HPROF_ASSERT(buf!=NULL);18781879/* Keep track of how many we have left */1880left = (int)byteCount;1881do {1882int count;18831884count = buf_len;1885if ( count > left ) count = left;1886nbytes = md_read(fd, buf, count);1887if (nbytes < 0) {1888system_error("read", nbytes, errno);1889break;1890}1891if (nbytes == 0) {1892break;1893}1894if ( nbytes > 0 ) {1895(*raw_interface)(buf, nbytes);1896left -= nbytes;1897}1898} while ( left > 0 );18991900if (left > 0 && nbytes == 0) {1901HPROF_ERROR(JNI_TRUE, "File size is smaller than bytes written");1902}1903HPROF_FREE(buf);1904}19051906/* Write out a heap segment, and copy remainder to top of file. */1907static void1908dump_heap_segment_and_reset(jlong segment_size)1909{1910int fd;1911jlong last_chunk_len;19121913HPROF_ASSERT(gdata->heap_fd >= 0);19141915/* Flush all bytes to the heap dump file */1916heap_flush();19171918/* Last segment? */1919last_chunk_len = gdata->heap_write_count - segment_size;1920HPROF_ASSERT(last_chunk_len>=0);19211922/* Re-open in proper way, binary vs. ascii is important */1923if (gdata->output_format == 'b') {1924int tag;19251926if ( gdata->segmented == JNI_TRUE ) { /* 1.0.2 */1927tag = HPROF_HEAP_DUMP_SEGMENT; /* 1.0.2 */1928} else {1929tag = HPROF_HEAP_DUMP; /* Just one segment */1930HPROF_ASSERT(last_chunk_len==0);1931}19321933/* Write header for binary heap dump (don't know size until now) */1934write_header(tag, (jint)segment_size);19351936fd = md_open_binary(gdata->heapfilename);1937} else {1938fd = md_open(gdata->heapfilename);1939}19401941/* Move file bytes into hprof dump file */1942write_raw_from_file(fd, segment_size, &write_raw);19431944/* Clear the byte count and reset the heap file. */1945if ( md_seek(gdata->heap_fd, (jlong)0) != (jlong)0 ) {1946HPROF_ERROR(JNI_TRUE, "Cannot seek to beginning of heap info file");1947}1948gdata->heap_write_count = (jlong)0;1949gdata->heap_last_tag_position = (jlong)0;19501951/* Move trailing bytes from heap dump file to beginning of file */1952if ( last_chunk_len > 0 ) {1953write_raw_from_file(fd, last_chunk_len, &heap_raw);1954}19551956/* Close the temp file handle */1957md_close(fd);1958}19591960void1961io_heap_footer(void)1962{1963HPROF_ASSERT(gdata->heap_fd >= 0);19641965/* Flush all bytes to the heap dump file */1966heap_flush();19671968/* Send out the last (or maybe only) segment */1969dump_heap_segment_and_reset(gdata->heap_write_count);19701971/* Write out the last tag */1972if (gdata->output_format != 'b') {1973write_printf("HEAP DUMP END\n");1974} else {1975if ( gdata->segmented == JNI_TRUE ) { /* 1.0.2 */1976write_header(HPROF_HEAP_DUMP_END, 0);1977}1978}1979}198019811982