jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.c
changeset 32249 ba2c9c7773b6
parent 32248 13967da712ff
parent 32247 9f3dd33507b9
child 32253 637b00638ed6
equal deleted inserted replaced
32248:13967da712ff 32249:ba2c9c7773b6
     1 /*
       
     2  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  *
       
     8  *   - Redistributions of source code must retain the above copyright
       
     9  *     notice, this list of conditions and the following disclaimer.
       
    10  *
       
    11  *   - Redistributions in binary form must reproduce the above copyright
       
    12  *     notice, this list of conditions and the following disclaimer in the
       
    13  *     documentation and/or other materials provided with the distribution.
       
    14  *
       
    15  *   - Neither the name of Oracle nor the names of its
       
    16  *     contributors may be used to endorse or promote products derived
       
    17  *     from this software without specific prior written permission.
       
    18  *
       
    19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
       
    20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
       
    21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
       
    23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
       
    27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
       
    28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
       
    29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    30  */
       
    31 
       
    32 /*
       
    33  * This source code is provided to illustrate the usage of a given feature
       
    34  * or technique and has been deliberately simplified. Additional steps
       
    35  * required for a production-quality application, such as security checks,
       
    36  * input validation and proper error handling, might not be present in
       
    37  * this sample code.
       
    38  */
       
    39 
       
    40 
       
    41 /* All I/O functionality for hprof. */
       
    42 
       
    43 /*
       
    44  * The hprof agent has many forms of output:
       
    45  *
       
    46  *   format=b   gdata->output_format=='b'
       
    47  *      Binary format. Defined below. This is used by HAT.
       
    48  *      This is NOT the same format as emitted by JVMPI.
       
    49  *
       
    50  *   format=a   gdata->output_format=='a'
       
    51  *      Ascii format. Not exactly an ascii representation of the binary format.
       
    52  *
       
    53  * And many forms of dumps:
       
    54  *
       
    55  *    heap=dump
       
    56  *        A large dump that in this implementation is written to a separate
       
    57  *        file first before being placed in the output file. Several reasons,
       
    58  *        the binary form needs a byte count of the length in the header, and
       
    59  *        references in this dump to other items need to be emitted first.
       
    60  *        So it's two pass, or use a temp file and copy.
       
    61  *    heap=sites
       
    62  *        Dumps the sites in the order of most allocations.
       
    63  *    cpu=samples
       
    64  *        Dumps the traces in order of most hits
       
    65  *    cpu=times
       
    66  *        Dumps the traces in the order of most time spent there.
       
    67  *    cpu=old   (format=a only)
       
    68  *        Dumps out an older form of cpu output (old -prof format)
       
    69  *    monitor=y (format=a only)
       
    70  *        Dumps out a list of monitors in order of most contended.
       
    71  *
       
    72  * This file also includes a binary format check function that will read
       
    73  *   back in the hprof binary format and verify the syntax looks correct.
       
    74  *
       
    75  * WARNING: Besides the comments below, there is little format spec on this,
       
    76  *          however see:
       
    77  *           http://java.sun.com/j2se/1.4.2/docs/guide/jvmpi/jvmpi.html#hprof
       
    78  */
       
    79 
       
    80 #include "hprof.h"
       
    81 
       
    82 typedef TableIndex HprofId;
       
    83 
       
    84 #include "hprof_ioname.h"
       
    85 #include "hprof_b_spec.h"
       
    86 
       
    87 static int type_size[ /*HprofType*/ ] =  HPROF_TYPE_SIZES;
       
    88 
       
    89 static void dump_heap_segment_and_reset(jlong segment_size);
       
    90 
       
    91 static void
       
    92 not_implemented(void)
       
    93 {
       
    94 }
       
    95 
       
    96 static IoNameIndex
       
    97 get_name_index(char *name)
       
    98 {
       
    99     if (name != NULL && gdata->output_format == 'b') {
       
   100         return ioname_find_or_create(name, NULL);
       
   101     }
       
   102     return 0;
       
   103 }
       
   104 
       
   105 static char *
       
   106 signature_to_name(char *sig)
       
   107 {
       
   108     char *ptr;
       
   109     char *basename;
       
   110     char *name;
       
   111     int i;
       
   112     int len;
       
   113     int name_len;
       
   114 
       
   115     if ( sig != NULL ) {
       
   116         switch ( sig[0] ) {
       
   117             case JVM_SIGNATURE_CLASS:
       
   118                 ptr = strchr(sig+1, JVM_SIGNATURE_ENDCLASS);
       
   119                 if ( ptr == NULL ) {
       
   120                     basename = "Unknown_class";
       
   121                     break;
       
   122                 }
       
   123                 /*LINTED*/
       
   124                 name_len = (jint)(ptr - (sig+1));
       
   125                 name = HPROF_MALLOC(name_len+1);
       
   126                 (void)memcpy(name, sig+1, name_len);
       
   127                 name[name_len] = 0;
       
   128                 for ( i = 0 ; i < name_len ; i++ ) {
       
   129                     if ( name[i] == '/' ) name[i] = '.';
       
   130                 }
       
   131                 return name;
       
   132             case JVM_SIGNATURE_ARRAY:
       
   133                 basename = signature_to_name(sig+1);
       
   134                 len = (int)strlen(basename);
       
   135                 name_len = len+2;
       
   136                 name = HPROF_MALLOC(name_len+1);
       
   137                 (void)memcpy(name, basename, len);
       
   138                 (void)memcpy(name+len, "[]", 2);
       
   139                 name[name_len] = 0;
       
   140                 HPROF_FREE(basename);
       
   141                 return name;
       
   142             case JVM_SIGNATURE_FUNC:
       
   143                 ptr = strchr(sig+1, JVM_SIGNATURE_ENDFUNC);
       
   144                 if ( ptr == NULL ) {
       
   145                     basename = "Unknown_method";
       
   146                     break;
       
   147                 }
       
   148                 basename = "()"; /* Someday deal with method signatures */
       
   149                 break;
       
   150             case JVM_SIGNATURE_BYTE:
       
   151                 basename = "byte";
       
   152                 break;
       
   153             case JVM_SIGNATURE_CHAR:
       
   154                 basename = "char";
       
   155                 break;
       
   156             case JVM_SIGNATURE_ENUM:
       
   157                 basename = "enum";
       
   158                 break;
       
   159             case JVM_SIGNATURE_FLOAT:
       
   160                 basename = "float";
       
   161                 break;
       
   162             case JVM_SIGNATURE_DOUBLE:
       
   163                 basename = "double";
       
   164                 break;
       
   165             case JVM_SIGNATURE_INT:
       
   166                 basename = "int";
       
   167                 break;
       
   168             case JVM_SIGNATURE_LONG:
       
   169                 basename = "long";
       
   170                 break;
       
   171             case JVM_SIGNATURE_SHORT:
       
   172                 basename = "short";
       
   173                 break;
       
   174             case JVM_SIGNATURE_VOID:
       
   175                 basename = "void";
       
   176                 break;
       
   177             case JVM_SIGNATURE_BOOLEAN:
       
   178                 basename = "boolean";
       
   179                 break;
       
   180             default:
       
   181                 basename = "Unknown_class";
       
   182                 break;
       
   183         }
       
   184     } else {
       
   185         basename = "Unknown_class";
       
   186     }
       
   187 
       
   188     /* Simple basename */
       
   189     name_len = (int)strlen(basename);
       
   190     name = HPROF_MALLOC(name_len+1);
       
   191     (void)strcpy(name, basename);
       
   192     return name;
       
   193 }
       
   194 
       
   195 static int
       
   196 size_from_field_info(int size)
       
   197 {
       
   198     if ( size == 0 ) {
       
   199         size = (int)sizeof(HprofId);
       
   200     }
       
   201     return size;
       
   202 }
       
   203 
       
   204 static void
       
   205 type_from_signature(const char *sig, HprofType *kind, jint *size)
       
   206 {
       
   207     *kind = HPROF_NORMAL_OBJECT;
       
   208     *size = 0;
       
   209     switch ( sig[0] ) {
       
   210         case JVM_SIGNATURE_ENUM:
       
   211         case JVM_SIGNATURE_CLASS:
       
   212         case JVM_SIGNATURE_ARRAY:
       
   213             *kind = HPROF_NORMAL_OBJECT;
       
   214             break;
       
   215         case JVM_SIGNATURE_BOOLEAN:
       
   216             *kind = HPROF_BOOLEAN;
       
   217             break;
       
   218         case JVM_SIGNATURE_CHAR:
       
   219             *kind = HPROF_CHAR;
       
   220             break;
       
   221         case JVM_SIGNATURE_FLOAT:
       
   222             *kind = HPROF_FLOAT;
       
   223             break;
       
   224         case JVM_SIGNATURE_DOUBLE:
       
   225             *kind = HPROF_DOUBLE;
       
   226             break;
       
   227         case JVM_SIGNATURE_BYTE:
       
   228             *kind = HPROF_BYTE;
       
   229             break;
       
   230         case JVM_SIGNATURE_SHORT:
       
   231             *kind = HPROF_SHORT;
       
   232             break;
       
   233         case JVM_SIGNATURE_INT:
       
   234             *kind = HPROF_INT;
       
   235             break;
       
   236         case JVM_SIGNATURE_LONG:
       
   237             *kind = HPROF_LONG;
       
   238             break;
       
   239         default:
       
   240             HPROF_ASSERT(0);
       
   241             break;
       
   242     }
       
   243     *size = type_size[*kind];
       
   244 }
       
   245 
       
   246 static void
       
   247 type_array(const char *sig, HprofType *kind, jint *elem_size)
       
   248 {
       
   249     *kind = 0;
       
   250     *elem_size = 0;
       
   251     switch ( sig[0] ) {
       
   252         case JVM_SIGNATURE_ARRAY:
       
   253             type_from_signature(sig+1, kind, elem_size);
       
   254             break;
       
   255     }
       
   256 }
       
   257 
       
   258 static void
       
   259 system_error(const char *system_call, int rc, int errnum)
       
   260 {
       
   261     char buf[256];
       
   262     char details[256];
       
   263 
       
   264     details[0] = 0;
       
   265     if ( errnum != 0 ) {
       
   266         md_system_error(details, (int)sizeof(details));
       
   267     } else if ( rc >= 0 ) {
       
   268         (void)strcpy(details,"Only part of buffer processed");
       
   269     }
       
   270     if ( details[0] == 0 ) {
       
   271         (void)strcpy(details,"Unknown system error condition");
       
   272     }
       
   273     (void)md_snprintf(buf, sizeof(buf), "System %s failed: %s\n",
       
   274                             system_call, details);
       
   275     HPROF_ERROR(JNI_TRUE, buf);
       
   276 }
       
   277 
       
   278 static void
       
   279 system_write(int fd, void *buf, int len, jboolean socket)
       
   280 {
       
   281     int res;
       
   282 
       
   283     HPROF_ASSERT(fd>=0);
       
   284     if (socket) {
       
   285         res = md_send(fd, buf, len, 0);
       
   286         if (res < 0 || res!=len) {
       
   287             system_error("send", res, errno);
       
   288         }
       
   289     } else {
       
   290         res = md_write(fd, buf, len);
       
   291         if (res < 0 || res!=len) {
       
   292             system_error("write", res, errno);
       
   293         }
       
   294     }
       
   295 }
       
   296 
       
   297 static void
       
   298 write_flush(void)
       
   299 {
       
   300     HPROF_ASSERT(gdata->fd >= 0);
       
   301     if (gdata->write_buffer_index) {
       
   302         system_write(gdata->fd, gdata->write_buffer, gdata->write_buffer_index,
       
   303                                 gdata->socket);
       
   304         gdata->write_buffer_index = 0;
       
   305     }
       
   306 }
       
   307 
       
   308 static void
       
   309 heap_flush(void)
       
   310 {
       
   311     HPROF_ASSERT(gdata->heap_fd >= 0);
       
   312     if (gdata->heap_buffer_index) {
       
   313         gdata->heap_write_count += (jlong)gdata->heap_buffer_index;
       
   314         system_write(gdata->heap_fd, gdata->heap_buffer, gdata->heap_buffer_index,
       
   315                                 JNI_FALSE);
       
   316         gdata->heap_buffer_index = 0;
       
   317     }
       
   318 }
       
   319 
       
   320 static void
       
   321 write_raw(void *buf, int len)
       
   322 {
       
   323     HPROF_ASSERT(gdata->fd >= 0);
       
   324     if (gdata->write_buffer_index + len > gdata->write_buffer_size) {
       
   325         write_flush();
       
   326         if (len > gdata->write_buffer_size) {
       
   327             system_write(gdata->fd, buf, len, gdata->socket);
       
   328             return;
       
   329         }
       
   330     }
       
   331     (void)memcpy(gdata->write_buffer + gdata->write_buffer_index, buf, len);
       
   332     gdata->write_buffer_index += len;
       
   333 }
       
   334 
       
   335 static void
       
   336 write_u4(unsigned i)
       
   337 {
       
   338     i = md_htonl(i);
       
   339     write_raw(&i, (jint)sizeof(unsigned));
       
   340 }
       
   341 
       
   342 static void
       
   343 write_u8(jlong t)
       
   344 {
       
   345     write_u4((jint)jlong_high(t));
       
   346     write_u4((jint)jlong_low(t));
       
   347 }
       
   348 
       
   349 static void
       
   350 write_u2(unsigned short i)
       
   351 {
       
   352     i = md_htons(i);
       
   353     write_raw(&i, (jint)sizeof(unsigned short));
       
   354 }
       
   355 
       
   356 static void
       
   357 write_u1(unsigned char i)
       
   358 {
       
   359     write_raw(&i, (jint)sizeof(unsigned char));
       
   360 }
       
   361 
       
   362 static void
       
   363 write_id(HprofId i)
       
   364 {
       
   365     write_u4(i);
       
   366 }
       
   367 
       
   368 static void
       
   369 write_current_ticks(void)
       
   370 {
       
   371     write_u4((jint)(md_get_microsecs() - gdata->micro_sec_ticks));
       
   372 }
       
   373 
       
   374 static void
       
   375 write_header(unsigned char type, jint length)
       
   376 {
       
   377     write_u1(type);
       
   378     write_current_ticks();
       
   379     write_u4(length);
       
   380 }
       
   381 
       
   382 static void
       
   383 write_index_id(HprofId index)
       
   384 {
       
   385     write_id(index);
       
   386 }
       
   387 
       
   388 static IoNameIndex
       
   389 write_name_first(char *name)
       
   390 {
       
   391     if ( name == NULL ) {
       
   392         return 0;
       
   393     }
       
   394     if (gdata->output_format == 'b') {
       
   395         IoNameIndex name_index;
       
   396         jboolean    new_one;
       
   397 
       
   398         new_one = JNI_FALSE;
       
   399         name_index = ioname_find_or_create(name, &new_one);
       
   400         if ( new_one ) {
       
   401             int      len;
       
   402 
       
   403             len = (int)strlen(name);
       
   404             write_header(HPROF_UTF8, len + (jint)sizeof(HprofId));
       
   405             write_index_id(name_index);
       
   406             write_raw(name, len);
       
   407 
       
   408         }
       
   409         return name_index;
       
   410     }
       
   411     return 0;
       
   412 }
       
   413 
       
   414 static void
       
   415 write_printf(char *fmt, ...)
       
   416 {
       
   417     char buf[1024];
       
   418     va_list args;
       
   419     va_start(args, fmt);
       
   420     (void)md_vsnprintf(buf, sizeof(buf), fmt, args);
       
   421     buf[sizeof(buf)-1] = 0;
       
   422     write_raw(buf, (int)strlen(buf));
       
   423     va_end(args);
       
   424 }
       
   425 
       
   426 static void
       
   427 write_thread_serial_number(SerialNumber thread_serial_num, int with_comma)
       
   428 {
       
   429     if ( thread_serial_num != 0 ) {
       
   430         CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
   431         if ( with_comma ) {
       
   432             write_printf(" thread %d,", thread_serial_num);
       
   433         } else {
       
   434             write_printf(" thread %d", thread_serial_num);
       
   435         }
       
   436     } else {
       
   437         if ( with_comma ) {
       
   438             write_printf(" <unknown thread>,");
       
   439         } else {
       
   440             write_printf(" <unknown thread>");
       
   441         }
       
   442     }
       
   443 }
       
   444 
       
   445 static void
       
   446 heap_raw(void *buf, int len)
       
   447 {
       
   448     HPROF_ASSERT(gdata->heap_fd >= 0);
       
   449     if (gdata->heap_buffer_index + len > gdata->heap_buffer_size) {
       
   450         heap_flush();
       
   451         if (len > gdata->heap_buffer_size) {
       
   452             gdata->heap_write_count += (jlong)len;
       
   453             system_write(gdata->heap_fd, buf, len, JNI_FALSE);
       
   454             return;
       
   455         }
       
   456     }
       
   457     (void)memcpy(gdata->heap_buffer + gdata->heap_buffer_index, buf, len);
       
   458     gdata->heap_buffer_index += len;
       
   459 }
       
   460 
       
   461 static void
       
   462 heap_u4(unsigned i)
       
   463 {
       
   464     i = md_htonl(i);
       
   465     heap_raw(&i, (jint)sizeof(unsigned));
       
   466 }
       
   467 
       
   468 static void
       
   469 heap_u8(jlong i)
       
   470 {
       
   471     heap_u4((jint)jlong_high(i));
       
   472     heap_u4((jint)jlong_low(i));
       
   473 }
       
   474 
       
   475 static void
       
   476 heap_u2(unsigned short i)
       
   477 {
       
   478     i = md_htons(i);
       
   479     heap_raw(&i, (jint)sizeof(unsigned short));
       
   480 }
       
   481 
       
   482 static void
       
   483 heap_u1(unsigned char i)
       
   484 {
       
   485     heap_raw(&i, (jint)sizeof(unsigned char));
       
   486 }
       
   487 
       
   488 /* Write out the first byte of a heap tag */
       
   489 static void
       
   490 heap_tag(unsigned char tag)
       
   491 {
       
   492     jlong pos;
       
   493 
       
   494     /* Current position in virtual heap dump file */
       
   495     pos = gdata->heap_write_count + (jlong)gdata->heap_buffer_index;
       
   496     if ( gdata->segmented == JNI_TRUE ) { /* 1.0.2 */
       
   497         if ( pos >= gdata->maxHeapSegment ) {
       
   498             /* Flush all bytes to the heap dump file */
       
   499             heap_flush();
       
   500 
       
   501             /* Send out segment (up to last tag written out) */
       
   502             dump_heap_segment_and_reset(gdata->heap_last_tag_position);
       
   503 
       
   504             /* Get new current position */
       
   505             pos = gdata->heap_write_count + (jlong)gdata->heap_buffer_index;
       
   506         }
       
   507     }
       
   508     /* Save position of this tag */
       
   509     gdata->heap_last_tag_position = pos;
       
   510     /* Write out this tag */
       
   511     heap_u1(tag);
       
   512 }
       
   513 
       
   514 static void
       
   515 heap_id(HprofId i)
       
   516 {
       
   517     heap_u4(i);
       
   518 }
       
   519 
       
   520 static void
       
   521 heap_index_id(HprofId index)
       
   522 {
       
   523     heap_id(index);
       
   524 }
       
   525 
       
   526 static void
       
   527 heap_name(char *name)
       
   528 {
       
   529     heap_index_id(get_name_index(name));
       
   530 }
       
   531 
       
   532 static void
       
   533 heap_printf(char *fmt, ...)
       
   534 {
       
   535     char buf[1024];
       
   536     va_list args;
       
   537     va_start(args, fmt);
       
   538     (void)md_vsnprintf(buf, sizeof(buf), fmt, args);
       
   539     buf[sizeof(buf)-1] = 0;
       
   540     heap_raw(buf, (int)strlen(buf));
       
   541     va_end(args);
       
   542 }
       
   543 
       
   544 static void
       
   545 heap_element(HprofType kind, jint size, jvalue value)
       
   546 {
       
   547     if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) {
       
   548         HPROF_ASSERT(size==4);
       
   549         heap_id((HprofId)value.i);
       
   550     } else {
       
   551         switch ( size ) {
       
   552             case 8:
       
   553                 HPROF_ASSERT(size==8);
       
   554                 HPROF_ASSERT(kind==HPROF_LONG || kind==HPROF_DOUBLE);
       
   555                 heap_u8(value.j);
       
   556                 break;
       
   557             case 4:
       
   558                 HPROF_ASSERT(size==4);
       
   559                 HPROF_ASSERT(kind==HPROF_INT || kind==HPROF_FLOAT);
       
   560                 heap_u4(value.i);
       
   561                 break;
       
   562             case 2:
       
   563                 HPROF_ASSERT(size==2);
       
   564                 HPROF_ASSERT(kind==HPROF_SHORT || kind==HPROF_CHAR);
       
   565                 heap_u2(value.s);
       
   566                 break;
       
   567             case 1:
       
   568                 HPROF_ASSERT(size==1);
       
   569                 HPROF_ASSERT(kind==HPROF_BOOLEAN || kind==HPROF_BYTE);
       
   570                 HPROF_ASSERT(kind==HPROF_BOOLEAN?(value.b==0 || value.b==1):1);
       
   571                 heap_u1(value.b);
       
   572                 break;
       
   573             default:
       
   574                 HPROF_ASSERT(0);
       
   575                 break;
       
   576         }
       
   577     }
       
   578 }
       
   579 
       
   580 /* Dump out all elements of an array, objects in jvalues, prims packed */
       
   581 static void
       
   582 heap_elements(HprofType kind, jint num_elements, jint elem_size, void *elements)
       
   583 {
       
   584     int     i;
       
   585     jvalue  val;
       
   586     static jvalue empty_val;
       
   587 
       
   588     if ( num_elements == 0 ) {
       
   589         return;
       
   590     }
       
   591 
       
   592     switch ( kind ) {
       
   593         case 0:
       
   594         case HPROF_ARRAY_OBJECT:
       
   595         case HPROF_NORMAL_OBJECT:
       
   596             for (i = 0; i < num_elements; i++) {
       
   597                 val   = empty_val;
       
   598                 val.i = ((ObjectIndex*)elements)[i];
       
   599                 heap_element(kind, elem_size, val);
       
   600             }
       
   601             break;
       
   602         case HPROF_BYTE:
       
   603         case HPROF_BOOLEAN:
       
   604             HPROF_ASSERT(elem_size==1);
       
   605             for (i = 0; i < num_elements; i++) {
       
   606                 val   = empty_val;
       
   607                 val.b = ((jboolean*)elements)[i];
       
   608                 heap_element(kind, elem_size, val);
       
   609             }
       
   610             break;
       
   611         case HPROF_CHAR:
       
   612         case HPROF_SHORT:
       
   613             HPROF_ASSERT(elem_size==2);
       
   614             for (i = 0; i < num_elements; i++) {
       
   615                 val   = empty_val;
       
   616                 val.s = ((jshort*)elements)[i];
       
   617                 heap_element(kind, elem_size, val);
       
   618             }
       
   619             break;
       
   620         case HPROF_FLOAT:
       
   621         case HPROF_INT:
       
   622             HPROF_ASSERT(elem_size==4);
       
   623             for (i = 0; i < num_elements; i++) {
       
   624                 val   = empty_val;
       
   625                 val.i = ((jint*)elements)[i];
       
   626                 heap_element(kind, elem_size, val);
       
   627             }
       
   628             break;
       
   629         case HPROF_DOUBLE:
       
   630         case HPROF_LONG:
       
   631             HPROF_ASSERT(elem_size==8);
       
   632             for (i = 0; i < num_elements; i++) {
       
   633                 val   = empty_val;
       
   634                 val.j = ((jlong*)elements)[i];
       
   635                 heap_element(kind, elem_size, val);
       
   636             }
       
   637             break;
       
   638     }
       
   639 }
       
   640 
       
   641 /* ------------------------------------------------------------------ */
       
   642 
       
   643 void
       
   644 io_flush(void)
       
   645 {
       
   646     HPROF_ASSERT(gdata->header!=NULL);
       
   647     write_flush();
       
   648 }
       
   649 
       
   650 void
       
   651 io_setup(void)
       
   652 {
       
   653     gdata->write_buffer_size = FILE_IO_BUFFER_SIZE;
       
   654     gdata->write_buffer = HPROF_MALLOC(gdata->write_buffer_size);
       
   655     gdata->write_buffer_index = 0;
       
   656 
       
   657     gdata->heap_write_count = (jlong)0;
       
   658     gdata->heap_last_tag_position = (jlong)0;
       
   659     gdata->heap_buffer_size = FILE_IO_BUFFER_SIZE;
       
   660     gdata->heap_buffer = HPROF_MALLOC(gdata->heap_buffer_size);
       
   661     gdata->heap_buffer_index = 0;
       
   662 
       
   663     if ( gdata->logflags & LOG_CHECK_BINARY ) {
       
   664         gdata->check_buffer_size = FILE_IO_BUFFER_SIZE;
       
   665         gdata->check_buffer = HPROF_MALLOC(gdata->check_buffer_size);
       
   666         gdata->check_buffer_index = 0;
       
   667     }
       
   668 
       
   669     ioname_init();
       
   670 }
       
   671 
       
   672 void
       
   673 io_cleanup(void)
       
   674 {
       
   675     if ( gdata->write_buffer != NULL ) {
       
   676         HPROF_FREE(gdata->write_buffer);
       
   677     }
       
   678     gdata->write_buffer_size = 0;
       
   679     gdata->write_buffer = NULL;
       
   680     gdata->write_buffer_index = 0;
       
   681 
       
   682     if ( gdata->heap_buffer != NULL ) {
       
   683         HPROF_FREE(gdata->heap_buffer);
       
   684     }
       
   685     gdata->heap_write_count = (jlong)0;
       
   686     gdata->heap_last_tag_position = (jlong)0;
       
   687     gdata->heap_buffer_size = 0;
       
   688     gdata->heap_buffer = NULL;
       
   689     gdata->heap_buffer_index = 0;
       
   690 
       
   691     if ( gdata->logflags & LOG_CHECK_BINARY ) {
       
   692         if ( gdata->check_buffer != NULL ) {
       
   693             HPROF_FREE(gdata->check_buffer);
       
   694         }
       
   695         gdata->check_buffer_size = 0;
       
   696         gdata->check_buffer = NULL;
       
   697         gdata->check_buffer_index = 0;
       
   698     }
       
   699 
       
   700     ioname_cleanup();
       
   701 }
       
   702 
       
   703 void
       
   704 io_write_file_header(void)
       
   705 {
       
   706     HPROF_ASSERT(gdata->header!=NULL);
       
   707     if (gdata->output_format == 'b') {
       
   708         jint settings;
       
   709         jlong t;
       
   710 
       
   711         settings = 0;
       
   712         if (gdata->heap_dump || gdata->alloc_sites) {
       
   713             settings |= 1;
       
   714         }
       
   715         if (gdata->cpu_sampling) {
       
   716             settings |= 2;
       
   717         }
       
   718         t = md_get_timemillis();
       
   719 
       
   720         write_raw(gdata->header, (int)strlen(gdata->header) + 1);
       
   721         write_u4((jint)sizeof(HprofId));
       
   722         write_u8(t);
       
   723 
       
   724         write_header(HPROF_CONTROL_SETTINGS, 4 + 2);
       
   725         write_u4(settings);
       
   726         write_u2((unsigned short)gdata->max_trace_depth);
       
   727 
       
   728     } else if ((!gdata->cpu_timing) || (!gdata->old_timing_format)) {
       
   729         /* We don't want the prelude file for the old prof output format */
       
   730         time_t t;
       
   731         char prelude_file[FILENAME_MAX];
       
   732         int prelude_fd;
       
   733         int nbytes;
       
   734 
       
   735         t = time(0);
       
   736 
       
   737         md_get_prelude_path(prelude_file, sizeof(prelude_file), PRELUDE_FILE);
       
   738 
       
   739         prelude_fd = md_open(prelude_file);
       
   740         if (prelude_fd < 0) {
       
   741             char buf[FILENAME_MAX+80];
       
   742 
       
   743             (void)md_snprintf(buf, sizeof(buf), "Can't open %s", prelude_file);
       
   744             buf[sizeof(buf)-1] = 0;
       
   745             HPROF_ERROR(JNI_TRUE, buf);
       
   746         }
       
   747 
       
   748         write_printf("%s, created %s\n", gdata->header, ctime(&t));
       
   749 
       
   750         do {
       
   751             char buf[1024]; /* File is small, small buffer ok here */
       
   752 
       
   753             nbytes = md_read(prelude_fd, buf, sizeof(buf));
       
   754             if ( nbytes < 0 ) {
       
   755                 system_error("read", nbytes, errno);
       
   756                 break;
       
   757             }
       
   758             if (nbytes == 0) {
       
   759                 break;
       
   760             }
       
   761             write_raw(buf, nbytes);
       
   762         } while ( nbytes > 0 );
       
   763 
       
   764         md_close(prelude_fd);
       
   765 
       
   766         write_printf("\n--------\n\n");
       
   767 
       
   768         write_flush();
       
   769     }
       
   770 }
       
   771 
       
   772 void
       
   773 io_write_file_footer(void)
       
   774 {
       
   775     HPROF_ASSERT(gdata->header!=NULL);
       
   776 }
       
   777 
       
   778 void
       
   779 io_write_class_load(SerialNumber class_serial_num, ObjectIndex index,
       
   780                     SerialNumber trace_serial_num, char *sig)
       
   781 {
       
   782     CHECK_CLASS_SERIAL_NO(class_serial_num);
       
   783     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
   784     if (gdata->output_format == 'b') {
       
   785         IoNameIndex name_index;
       
   786         char *class_name;
       
   787 
       
   788         class_name = signature_to_name(sig);
       
   789         name_index = write_name_first(class_name);
       
   790         write_header(HPROF_LOAD_CLASS, (2 * (jint)sizeof(HprofId)) + (4 * 2));
       
   791         write_u4(class_serial_num);
       
   792         write_index_id(index);
       
   793         write_u4(trace_serial_num);
       
   794         write_index_id(name_index);
       
   795         HPROF_FREE(class_name);
       
   796     }
       
   797 }
       
   798 
       
   799 void
       
   800 io_write_class_unload(SerialNumber class_serial_num, ObjectIndex index)
       
   801 {
       
   802     CHECK_CLASS_SERIAL_NO(class_serial_num);
       
   803     if (gdata->output_format == 'b') {
       
   804         write_header(HPROF_UNLOAD_CLASS, 4);
       
   805         write_u4(class_serial_num);
       
   806     }
       
   807 }
       
   808 
       
   809 void
       
   810 io_write_sites_header(const char * comment_str, jint flags, double cutoff,
       
   811                     jint total_live_bytes, jint total_live_instances,
       
   812                     jlong total_alloced_bytes, jlong total_alloced_instances,
       
   813                     jint count)
       
   814 {
       
   815     if ( gdata->output_format == 'b') {
       
   816         write_header(HPROF_ALLOC_SITES, 2 + (8 * 4) + (count * (4 * 6 + 1)));
       
   817         write_u2((unsigned short)flags);
       
   818         write_u4(*(int *)(&cutoff));
       
   819         write_u4(total_live_bytes);
       
   820         write_u4(total_live_instances);
       
   821         write_u8(total_alloced_bytes);
       
   822         write_u8(total_alloced_instances);
       
   823         write_u4(count);
       
   824     } else {
       
   825         time_t t;
       
   826 
       
   827         t = time(0);
       
   828         write_printf("SITES BEGIN (ordered by %s) %s", comment_str, ctime(&t));
       
   829         write_printf(
       
   830             "          percent          live          alloc'ed  stack class\n");
       
   831         write_printf(
       
   832             " rank   self  accum     bytes objs     bytes  objs trace name\n");
       
   833     }
       
   834 }
       
   835 
       
   836 void
       
   837 io_write_sites_elem(jint index, double ratio, double accum_percent,
       
   838                 char *sig, SerialNumber class_serial_num,
       
   839                 SerialNumber trace_serial_num, jint n_live_bytes,
       
   840                 jint n_live_instances, jint n_alloced_bytes,
       
   841                 jint n_alloced_instances)
       
   842 {
       
   843     CHECK_CLASS_SERIAL_NO(class_serial_num);
       
   844     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
   845     if ( gdata->output_format == 'b') {
       
   846         HprofType kind;
       
   847         jint size;
       
   848 
       
   849         type_array(sig, &kind, &size);
       
   850         write_u1(kind);
       
   851         write_u4(class_serial_num);
       
   852         write_u4(trace_serial_num);
       
   853         write_u4(n_live_bytes);
       
   854         write_u4(n_live_instances);
       
   855         write_u4(n_alloced_bytes);
       
   856         write_u4(n_alloced_instances);
       
   857     } else {
       
   858         char *class_name;
       
   859 
       
   860         class_name = signature_to_name(sig);
       
   861         write_printf("%5u %5.2f%% %5.2f%% %9u %4u %9u %5u %5u %s\n",
       
   862                      index,
       
   863                      ratio * 100.0,
       
   864                      accum_percent * 100.0,
       
   865                      n_live_bytes,
       
   866                      n_live_instances,
       
   867                      n_alloced_bytes,
       
   868                      n_alloced_instances,
       
   869                      trace_serial_num,
       
   870                      class_name);
       
   871         HPROF_FREE(class_name);
       
   872     }
       
   873 }
       
   874 
       
   875 void
       
   876 io_write_sites_footer(void)
       
   877 {
       
   878     if (gdata->output_format == 'b') {
       
   879         not_implemented();
       
   880     } else {
       
   881         write_printf("SITES END\n");
       
   882     }
       
   883 }
       
   884 
       
   885 void
       
   886 io_write_thread_start(SerialNumber thread_serial_num,
       
   887                         ObjectIndex thread_obj_id,
       
   888                         SerialNumber trace_serial_num, char *thread_name,
       
   889                         char *thread_group_name, char *thread_parent_name)
       
   890 {
       
   891     CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
   892     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
   893     if (gdata->output_format == 'b') {
       
   894         IoNameIndex tname_index;
       
   895         IoNameIndex gname_index;
       
   896         IoNameIndex pname_index;
       
   897 
       
   898         tname_index = write_name_first(thread_name);
       
   899         gname_index = write_name_first(thread_group_name);
       
   900         pname_index = write_name_first(thread_parent_name);
       
   901         write_header(HPROF_START_THREAD, ((jint)sizeof(HprofId) * 4) + (4 * 2));
       
   902         write_u4(thread_serial_num);
       
   903         write_index_id(thread_obj_id);
       
   904         write_u4(trace_serial_num);
       
   905         write_index_id(tname_index);
       
   906         write_index_id(gname_index);
       
   907         write_index_id(pname_index);
       
   908 
       
   909     } else if ( (!gdata->cpu_timing) || (!gdata->old_timing_format)) {
       
   910         /* We don't want thread info for the old prof output format */
       
   911         write_printf("THREAD START "
       
   912                      "(obj=%x, id = %d, name=\"%s\", group=\"%s\")\n",
       
   913                      thread_obj_id, thread_serial_num,
       
   914                      (thread_name==NULL?"":thread_name),
       
   915                      (thread_group_name==NULL?"":thread_group_name));
       
   916     }
       
   917 }
       
   918 
       
   919 void
       
   920 io_write_thread_end(SerialNumber thread_serial_num)
       
   921 {
       
   922     CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
   923     if (gdata->output_format == 'b') {
       
   924         write_header(HPROF_END_THREAD, 4);
       
   925         write_u4(thread_serial_num);
       
   926 
       
   927     } else if ( (!gdata->cpu_timing) || (!gdata->old_timing_format)) {
       
   928         /* we don't want thread info for the old prof output format */
       
   929         write_printf("THREAD END (id = %d)\n", thread_serial_num);
       
   930     }
       
   931 }
       
   932 
       
   933 void
       
   934 io_write_frame(FrameIndex index, SerialNumber frame_serial_num,
       
   935                char *mname, char *msig, char *sname,
       
   936                SerialNumber class_serial_num, jint lineno)
       
   937 {
       
   938     CHECK_CLASS_SERIAL_NO(class_serial_num);
       
   939     if (gdata->output_format == 'b') {
       
   940         IoNameIndex mname_index;
       
   941         IoNameIndex msig_index;
       
   942         IoNameIndex sname_index;
       
   943 
       
   944         mname_index = write_name_first(mname);
       
   945         msig_index  = write_name_first(msig);
       
   946         sname_index = write_name_first(sname);
       
   947 
       
   948         write_header(HPROF_FRAME, ((jint)sizeof(HprofId) * 4) + (4 * 2));
       
   949         write_index_id(index);
       
   950         write_index_id(mname_index);
       
   951         write_index_id(msig_index);
       
   952         write_index_id(sname_index);
       
   953         write_u4(class_serial_num);
       
   954         write_u4(lineno);
       
   955     }
       
   956 }
       
   957 
       
   958 void
       
   959 io_write_trace_header(SerialNumber trace_serial_num,
       
   960                 SerialNumber thread_serial_num, jint n_frames, char *phase_str)
       
   961 {
       
   962     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
   963     if (gdata->output_format == 'b') {
       
   964         write_header(HPROF_TRACE, ((jint)sizeof(HprofId) * n_frames) + (4 * 3));
       
   965         write_u4(trace_serial_num);
       
   966         write_u4(thread_serial_num);
       
   967         write_u4(n_frames);
       
   968     } else {
       
   969         write_printf("TRACE %u:", trace_serial_num);
       
   970         if (thread_serial_num) {
       
   971             write_printf(" (thread=%d)", thread_serial_num);
       
   972         }
       
   973         if ( phase_str != NULL ) {
       
   974             write_printf(" (from %s phase of JVM)", phase_str);
       
   975         }
       
   976         write_printf("\n");
       
   977         if (n_frames == 0) {
       
   978             write_printf("\t<empty>\n");
       
   979         }
       
   980     }
       
   981 }
       
   982 
       
   983 void
       
   984 io_write_trace_elem(SerialNumber trace_serial_num, FrameIndex frame_index,
       
   985                     SerialNumber frame_serial_num,
       
   986                     char *csig, char *mname, char *sname, jint lineno)
       
   987 {
       
   988     if (gdata->output_format == 'b') {
       
   989         write_index_id(frame_index);
       
   990     } else {
       
   991         char *class_name;
       
   992         char linebuf[32];
       
   993 
       
   994         if (lineno == -2) {
       
   995             (void)md_snprintf(linebuf, sizeof(linebuf), "Compiled method");
       
   996         } else if (lineno == -3) {
       
   997             (void)md_snprintf(linebuf, sizeof(linebuf), "Native method");
       
   998         } else if (lineno == -1) {
       
   999             (void)md_snprintf(linebuf, sizeof(linebuf), "Unknown line");
       
  1000         } else {
       
  1001             (void)md_snprintf(linebuf, sizeof(linebuf), "%d", lineno);
       
  1002         }
       
  1003         linebuf[sizeof(linebuf)-1] = 0;
       
  1004         class_name = signature_to_name(csig);
       
  1005         if ( mname == NULL ) {
       
  1006             mname = "<Unknown Method>";
       
  1007         }
       
  1008         if ( sname == NULL ) {
       
  1009             sname = "<Unknown Source>";
       
  1010         }
       
  1011         write_printf("\t%s.%s(%s:%s)\n", class_name, mname, sname, linebuf);
       
  1012         HPROF_FREE(class_name);
       
  1013     }
       
  1014 }
       
  1015 
       
  1016 void
       
  1017 io_write_trace_footer(SerialNumber trace_serial_num,
       
  1018                 SerialNumber thread_serial_num, jint n_frames)
       
  1019 {
       
  1020 }
       
  1021 
       
  1022 #define CPU_SAMPLES_RECORD_NAME ("CPU SAMPLES")
       
  1023 #define CPU_TIMES_RECORD_NAME ("CPU TIME (ms)")
       
  1024 
       
  1025 void
       
  1026 io_write_cpu_samples_header(jlong total_cost, jint n_items)
       
  1027 {
       
  1028 
       
  1029     if (gdata->output_format == 'b') {
       
  1030         write_header(HPROF_CPU_SAMPLES, (n_items * (4 * 2)) + (4 * 2));
       
  1031         write_u4((jint)total_cost);
       
  1032         write_u4(n_items);
       
  1033     } else {
       
  1034         time_t t;
       
  1035         char *record_name;
       
  1036 
       
  1037         if ( gdata->cpu_sampling ) {
       
  1038             record_name = CPU_SAMPLES_RECORD_NAME;
       
  1039         } else {
       
  1040             record_name = CPU_TIMES_RECORD_NAME;
       
  1041         }
       
  1042         t = time(0);
       
  1043         write_printf("%s BEGIN (total = %d) %s", record_name,
       
  1044                      /*jlong*/(int)total_cost, ctime(&t));
       
  1045         if ( n_items > 0 ) {
       
  1046             write_printf("rank   self  accum   count trace method\n");
       
  1047         }
       
  1048     }
       
  1049 }
       
  1050 
       
  1051 void
       
  1052 io_write_cpu_samples_elem(jint index, double percent, double accum,
       
  1053                 jint num_hits, jlong cost, SerialNumber trace_serial_num,
       
  1054                 jint n_frames, char *csig, char *mname)
       
  1055 {
       
  1056     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
  1057     if (gdata->output_format == 'b') {
       
  1058         write_u4((jint)cost);
       
  1059         write_u4(trace_serial_num);
       
  1060     } else {
       
  1061         write_printf("%4u %5.2f%% %5.2f%% %7u %5u",
       
  1062                      index, percent, accum, num_hits,
       
  1063                      trace_serial_num);
       
  1064         if (n_frames > 0) {
       
  1065             char * class_name;
       
  1066 
       
  1067             class_name = signature_to_name(csig);
       
  1068             write_printf(" %s.%s\n", class_name, mname);
       
  1069             HPROF_FREE(class_name);
       
  1070         } else {
       
  1071             write_printf(" <empty trace>\n");
       
  1072         }
       
  1073     }
       
  1074 }
       
  1075 
       
  1076 void
       
  1077 io_write_cpu_samples_footer(void)
       
  1078 {
       
  1079     if (gdata->output_format == 'b') {
       
  1080         not_implemented();
       
  1081     } else {
       
  1082         char *record_name;
       
  1083 
       
  1084         if ( gdata->cpu_sampling ) {
       
  1085             record_name = CPU_SAMPLES_RECORD_NAME;
       
  1086         } else {
       
  1087             record_name = CPU_TIMES_RECORD_NAME;
       
  1088         }
       
  1089         write_printf("%s END\n", record_name);
       
  1090     }
       
  1091 }
       
  1092 
       
  1093 void
       
  1094 io_write_heap_summary(jlong total_live_bytes, jlong total_live_instances,
       
  1095                 jlong total_alloced_bytes, jlong total_alloced_instances)
       
  1096 {
       
  1097     if (gdata->output_format == 'b') {
       
  1098         write_header(HPROF_HEAP_SUMMARY, 4 * 6);
       
  1099         write_u4((jint)total_live_bytes);
       
  1100         write_u4((jint)total_live_instances);
       
  1101         write_u8(total_alloced_bytes);
       
  1102         write_u8(total_alloced_instances);
       
  1103     }
       
  1104 }
       
  1105 
       
  1106 void
       
  1107 io_write_oldprof_header(void)
       
  1108 {
       
  1109     if ( gdata->old_timing_format ) {
       
  1110         write_printf("count callee caller time\n");
       
  1111     }
       
  1112 }
       
  1113 
       
  1114 void
       
  1115 io_write_oldprof_elem(jint num_hits, jint num_frames, char *csig_callee,
       
  1116             char *mname_callee, char *msig_callee, char *csig_caller,
       
  1117             char *mname_caller, char *msig_caller, jlong cost)
       
  1118 {
       
  1119     if ( gdata->old_timing_format ) {
       
  1120         char * class_name_callee;
       
  1121         char * class_name_caller;
       
  1122 
       
  1123         class_name_callee = signature_to_name(csig_callee);
       
  1124         class_name_caller = signature_to_name(csig_caller);
       
  1125         write_printf("%d ", num_hits);
       
  1126         if (num_frames >= 1) {
       
  1127             write_printf("%s.%s%s ", class_name_callee,
       
  1128                  mname_callee,  msig_callee);
       
  1129         } else {
       
  1130             write_printf("%s ", "<unknown callee>");
       
  1131         }
       
  1132         if (num_frames > 1) {
       
  1133             write_printf("%s.%s%s ", class_name_caller,
       
  1134                  mname_caller,  msig_caller);
       
  1135         } else {
       
  1136             write_printf("%s ", "<unknown caller>");
       
  1137         }
       
  1138         write_printf("%d\n", (int)cost);
       
  1139         HPROF_FREE(class_name_callee);
       
  1140         HPROF_FREE(class_name_caller);
       
  1141     }
       
  1142 }
       
  1143 
       
  1144 void
       
  1145 io_write_oldprof_footer(void)
       
  1146 {
       
  1147 }
       
  1148 
       
  1149 void
       
  1150 io_write_monitor_header(jlong total_time)
       
  1151 {
       
  1152     if (gdata->output_format == 'b') {
       
  1153         not_implemented();
       
  1154     } else {
       
  1155         time_t t = time(0);
       
  1156 
       
  1157         t = time(0);
       
  1158         write_printf("MONITOR TIME BEGIN (total = %u ms) %s",
       
  1159                                 (int)total_time, ctime(&t));
       
  1160         if (total_time > 0) {
       
  1161             write_printf("rank   self  accum   count trace monitor\n");
       
  1162         }
       
  1163     }
       
  1164 }
       
  1165 
       
  1166 void
       
  1167 io_write_monitor_elem(jint index, double percent, double accum,
       
  1168             jint num_hits, SerialNumber trace_serial_num, char *sig)
       
  1169 {
       
  1170     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
  1171     if (gdata->output_format == 'b') {
       
  1172         not_implemented();
       
  1173     } else {
       
  1174         char *class_name;
       
  1175 
       
  1176         class_name = signature_to_name(sig);
       
  1177         write_printf("%4u %5.2f%% %5.2f%% %7u %5u %s (Java)\n",
       
  1178                      index, percent, accum, num_hits,
       
  1179                      trace_serial_num, class_name);
       
  1180         HPROF_FREE(class_name);
       
  1181     }
       
  1182 }
       
  1183 
       
  1184 void
       
  1185 io_write_monitor_footer(void)
       
  1186 {
       
  1187     if (gdata->output_format == 'b') {
       
  1188         not_implemented();
       
  1189     } else {
       
  1190         write_printf("MONITOR TIME END\n");
       
  1191     }
       
  1192 }
       
  1193 
       
  1194 void
       
  1195 io_write_monitor_sleep(jlong timeout, SerialNumber thread_serial_num)
       
  1196 {
       
  1197     if (gdata->output_format == 'b') {
       
  1198         not_implemented();
       
  1199     } else {
       
  1200         if ( thread_serial_num == 0 ) {
       
  1201             write_printf("SLEEP: timeout=%d, <unknown thread>\n",
       
  1202                         (int)timeout);
       
  1203         } else {
       
  1204             CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
  1205             write_printf("SLEEP: timeout=%d, thread %d\n",
       
  1206                         (int)timeout, thread_serial_num);
       
  1207         }
       
  1208     }
       
  1209 }
       
  1210 
       
  1211 void
       
  1212 io_write_monitor_wait(char *sig, jlong timeout,
       
  1213                 SerialNumber thread_serial_num)
       
  1214 {
       
  1215     if (gdata->output_format == 'b') {
       
  1216         not_implemented();
       
  1217     } else {
       
  1218         if ( thread_serial_num == 0 ) {
       
  1219             write_printf("WAIT: MONITOR %s, timeout=%d, <unknown thread>\n",
       
  1220                         sig, (int)timeout);
       
  1221         } else {
       
  1222             CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
  1223             write_printf("WAIT: MONITOR %s, timeout=%d, thread %d\n",
       
  1224                         sig, (int)timeout, thread_serial_num);
       
  1225         }
       
  1226     }
       
  1227 }
       
  1228 
       
  1229 void
       
  1230 io_write_monitor_waited(char *sig, jlong time_waited,
       
  1231                 SerialNumber thread_serial_num)
       
  1232 {
       
  1233     if (gdata->output_format == 'b') {
       
  1234         not_implemented();
       
  1235     } else {
       
  1236         if ( thread_serial_num == 0 ) {
       
  1237             write_printf("WAITED: MONITOR %s, time_waited=%d, <unknown thread>\n",
       
  1238                         sig, (int)time_waited);
       
  1239         } else {
       
  1240             CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
  1241             write_printf("WAITED: MONITOR %s, time_waited=%d, thread %d\n",
       
  1242                         sig, (int)time_waited, thread_serial_num);
       
  1243         }
       
  1244     }
       
  1245 }
       
  1246 
       
  1247 void
       
  1248 io_write_monitor_exit(char *sig, SerialNumber thread_serial_num)
       
  1249 {
       
  1250     if (gdata->output_format == 'b') {
       
  1251         not_implemented();
       
  1252     } else {
       
  1253         if ( thread_serial_num == 0 ) {
       
  1254             write_printf("EXIT: MONITOR %s, <unknown thread>\n", sig);
       
  1255         } else {
       
  1256             CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
  1257             write_printf("EXIT: MONITOR %s, thread %d\n",
       
  1258                         sig, thread_serial_num);
       
  1259         }
       
  1260     }
       
  1261 }
       
  1262 
       
  1263 void
       
  1264 io_write_monitor_dump_header(void)
       
  1265 {
       
  1266     if (gdata->output_format == 'b') {
       
  1267         not_implemented();
       
  1268     } else {
       
  1269         write_printf("MONITOR DUMP BEGIN\n");
       
  1270     }
       
  1271 }
       
  1272 
       
  1273 void
       
  1274 io_write_monitor_dump_thread_state(SerialNumber thread_serial_num,
       
  1275                       SerialNumber trace_serial_num,
       
  1276                       jint threadState)
       
  1277 {
       
  1278     CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
  1279     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
  1280     if (gdata->output_format == 'b') {
       
  1281         not_implemented();
       
  1282     } else {
       
  1283         char tstate[20];
       
  1284 
       
  1285         tstate[0] = 0;
       
  1286 
       
  1287         if (threadState & JVMTI_THREAD_STATE_SUSPENDED) {
       
  1288             (void)strcat(tstate,"S|");
       
  1289         }
       
  1290         if (threadState & JVMTI_THREAD_STATE_INTERRUPTED) {
       
  1291             (void)strcat(tstate,"intr|");
       
  1292         }
       
  1293         if (threadState & JVMTI_THREAD_STATE_IN_NATIVE) {
       
  1294             (void)strcat(tstate,"native|");
       
  1295         }
       
  1296         if ( ! ( threadState & JVMTI_THREAD_STATE_ALIVE ) ) {
       
  1297             if ( threadState & JVMTI_THREAD_STATE_TERMINATED ) {
       
  1298                 (void)strcat(tstate,"ZO");
       
  1299             } else {
       
  1300                 (void)strcat(tstate,"NS");
       
  1301             }
       
  1302         } else {
       
  1303             if ( threadState & JVMTI_THREAD_STATE_SLEEPING ) {
       
  1304                 (void)strcat(tstate,"SL");
       
  1305             } else if ( threadState & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER ) {
       
  1306                 (void)strcat(tstate,"MW");
       
  1307             } else if ( threadState & JVMTI_THREAD_STATE_WAITING ) {
       
  1308                 (void)strcat(tstate,"CW");
       
  1309             } else if ( threadState & JVMTI_THREAD_STATE_RUNNABLE ) {
       
  1310                 (void)strcat(tstate,"R");
       
  1311             } else {
       
  1312                 (void)strcat(tstate,"UN");
       
  1313             }
       
  1314         }
       
  1315         write_printf("    THREAD %d, trace %d, status: %s\n",
       
  1316                      thread_serial_num, trace_serial_num, tstate);
       
  1317     }
       
  1318 }
       
  1319 
       
  1320 void
       
  1321 io_write_monitor_dump_state(char *sig, SerialNumber thread_serial_num,
       
  1322                     jint entry_count,
       
  1323                     SerialNumber *waiters, jint waiter_count,
       
  1324                     SerialNumber *notify_waiters, jint notify_waiter_count)
       
  1325 {
       
  1326     if (gdata->output_format == 'b') {
       
  1327         not_implemented();
       
  1328     } else {
       
  1329         int i;
       
  1330 
       
  1331         if ( thread_serial_num != 0 ) {
       
  1332             CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
  1333             write_printf("    MONITOR %s\n", sig);
       
  1334             write_printf("\towner: thread %d, entry count: %d\n",
       
  1335                 thread_serial_num, entry_count);
       
  1336         } else {
       
  1337             write_printf("    MONITOR %s unowned\n", sig);
       
  1338         }
       
  1339         write_printf("\twaiting to enter:");
       
  1340         for (i = 0; i < waiter_count; i++) {
       
  1341             write_thread_serial_number(waiters[i],
       
  1342                                 (i != (waiter_count-1)));
       
  1343         }
       
  1344         write_printf("\n");
       
  1345         write_printf("\twaiting to be notified:");
       
  1346         for (i = 0; i < notify_waiter_count; i++) {
       
  1347             write_thread_serial_number(notify_waiters[i],
       
  1348                                 (i != (notify_waiter_count-1)));
       
  1349         }
       
  1350         write_printf("\n");
       
  1351     }
       
  1352 }
       
  1353 
       
  1354 void
       
  1355 io_write_monitor_dump_footer(void)
       
  1356 {
       
  1357     if (gdata->output_format == 'b') {
       
  1358         not_implemented();
       
  1359     } else {
       
  1360         write_printf("MONITOR DUMP END\n");
       
  1361     }
       
  1362 }
       
  1363 
       
  1364 /* ----------------------------------------------------------------- */
       
  1365 /* These functions write to a separate file */
       
  1366 
       
  1367 void
       
  1368 io_heap_header(jlong total_live_instances, jlong total_live_bytes)
       
  1369 {
       
  1370     if (gdata->output_format != 'b') {
       
  1371         time_t t;
       
  1372 
       
  1373         t = time(0);
       
  1374         heap_printf("HEAP DUMP BEGIN (%u objects, %u bytes) %s",
       
  1375                         /*jlong*/(int)total_live_instances,
       
  1376                         /*jlong*/(int)total_live_bytes, ctime(&t));
       
  1377     }
       
  1378 }
       
  1379 
       
  1380 void
       
  1381 io_heap_root_thread_object(ObjectIndex thread_obj_id,
       
  1382                 SerialNumber thread_serial_num, SerialNumber trace_serial_num)
       
  1383 {
       
  1384     CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
  1385     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
  1386     if (gdata->output_format == 'b') {
       
  1387          heap_tag(HPROF_GC_ROOT_THREAD_OBJ);
       
  1388          heap_id(thread_obj_id);
       
  1389          heap_u4(thread_serial_num);
       
  1390          heap_u4(trace_serial_num);
       
  1391     } else {
       
  1392         heap_printf("ROOT %x (kind=<thread>, id=%u, trace=%u)\n",
       
  1393                      thread_obj_id, thread_serial_num, trace_serial_num);
       
  1394     }
       
  1395 }
       
  1396 
       
  1397 void
       
  1398 io_heap_root_unknown(ObjectIndex obj_id)
       
  1399 {
       
  1400     if (gdata->output_format == 'b') {
       
  1401         heap_tag(HPROF_GC_ROOT_UNKNOWN);
       
  1402         heap_id(obj_id);
       
  1403     } else {
       
  1404         heap_printf("ROOT %x (kind=<unknown>)\n", obj_id);
       
  1405     }
       
  1406 }
       
  1407 
       
  1408 void
       
  1409 io_heap_root_jni_global(ObjectIndex obj_id, SerialNumber gref_serial_num,
       
  1410                          SerialNumber trace_serial_num)
       
  1411 {
       
  1412     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
  1413     if (gdata->output_format == 'b') {
       
  1414         heap_tag(HPROF_GC_ROOT_JNI_GLOBAL);
       
  1415         heap_id(obj_id);
       
  1416         heap_id(gref_serial_num);
       
  1417     } else {
       
  1418         heap_printf("ROOT %x (kind=<JNI global ref>, "
       
  1419                      "id=%x, trace=%u)\n",
       
  1420                      obj_id, gref_serial_num, trace_serial_num);
       
  1421     }
       
  1422 }
       
  1423 
       
  1424 void
       
  1425 io_heap_root_jni_local(ObjectIndex obj_id, SerialNumber thread_serial_num,
       
  1426         jint frame_depth)
       
  1427 {
       
  1428     CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
  1429     if (gdata->output_format == 'b') {
       
  1430         heap_tag(HPROF_GC_ROOT_JNI_LOCAL);
       
  1431         heap_id(obj_id);
       
  1432         heap_u4(thread_serial_num);
       
  1433         heap_u4(frame_depth);
       
  1434     } else {
       
  1435         heap_printf("ROOT %x (kind=<JNI local ref>, "
       
  1436                      "thread=%u, frame=%d)\n",
       
  1437                      obj_id, thread_serial_num, frame_depth);
       
  1438     }
       
  1439 }
       
  1440 
       
  1441 void
       
  1442 io_heap_root_system_class(ObjectIndex obj_id, char *sig, SerialNumber class_serial_num)
       
  1443 {
       
  1444     if (gdata->output_format == 'b') {
       
  1445         heap_tag(HPROF_GC_ROOT_STICKY_CLASS);
       
  1446         heap_id(obj_id);
       
  1447     } else {
       
  1448         char *class_name;
       
  1449 
       
  1450         class_name = signature_to_name(sig);
       
  1451         heap_printf("ROOT %x (kind=<system class>, name=%s)\n",
       
  1452                      obj_id, class_name);
       
  1453         HPROF_FREE(class_name);
       
  1454     }
       
  1455 }
       
  1456 
       
  1457 void
       
  1458 io_heap_root_monitor(ObjectIndex obj_id)
       
  1459 {
       
  1460     if (gdata->output_format == 'b') {
       
  1461         heap_tag(HPROF_GC_ROOT_MONITOR_USED);
       
  1462         heap_id(obj_id);
       
  1463     } else {
       
  1464         heap_printf("ROOT %x (kind=<busy monitor>)\n", obj_id);
       
  1465     }
       
  1466 }
       
  1467 
       
  1468 void
       
  1469 io_heap_root_thread(ObjectIndex obj_id, SerialNumber thread_serial_num)
       
  1470 {
       
  1471     CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
  1472     if (gdata->output_format == 'b') {
       
  1473         heap_tag(HPROF_GC_ROOT_THREAD_BLOCK);
       
  1474         heap_id(obj_id);
       
  1475         heap_u4(thread_serial_num);
       
  1476     } else {
       
  1477         heap_printf("ROOT %x (kind=<thread block>, thread=%u)\n",
       
  1478                      obj_id, thread_serial_num);
       
  1479     }
       
  1480 }
       
  1481 
       
  1482 void
       
  1483 io_heap_root_java_frame(ObjectIndex obj_id, SerialNumber thread_serial_num,
       
  1484         jint frame_depth)
       
  1485 {
       
  1486     CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
  1487     if (gdata->output_format == 'b') {
       
  1488         heap_tag(HPROF_GC_ROOT_JAVA_FRAME);
       
  1489         heap_id(obj_id);
       
  1490         heap_u4(thread_serial_num);
       
  1491         heap_u4(frame_depth);
       
  1492     } else {
       
  1493         heap_printf("ROOT %x (kind=<Java stack>, "
       
  1494                      "thread=%u, frame=%d)\n",
       
  1495                      obj_id, thread_serial_num, frame_depth);
       
  1496     }
       
  1497 }
       
  1498 
       
  1499 void
       
  1500 io_heap_root_native_stack(ObjectIndex obj_id, SerialNumber thread_serial_num)
       
  1501 {
       
  1502     CHECK_THREAD_SERIAL_NO(thread_serial_num);
       
  1503     if (gdata->output_format == 'b') {
       
  1504         heap_tag(HPROF_GC_ROOT_NATIVE_STACK);
       
  1505         heap_id(obj_id);
       
  1506         heap_u4(thread_serial_num);
       
  1507     } else {
       
  1508         heap_printf("ROOT %x (kind=<native stack>, thread=%u)\n",
       
  1509                      obj_id, thread_serial_num);
       
  1510     }
       
  1511 }
       
  1512 
       
  1513 static jboolean
       
  1514 is_static_field(jint modifiers)
       
  1515 {
       
  1516     if ( modifiers & JVM_ACC_STATIC ) {
       
  1517         return JNI_TRUE;
       
  1518     }
       
  1519     return JNI_FALSE;
       
  1520 }
       
  1521 
       
  1522 static jboolean
       
  1523 is_inst_field(jint modifiers)
       
  1524 {
       
  1525     if ( modifiers & JVM_ACC_STATIC ) {
       
  1526         return JNI_FALSE;
       
  1527     }
       
  1528     return JNI_TRUE;
       
  1529 }
       
  1530 
       
  1531 void
       
  1532 io_heap_class_dump(ClassIndex cnum, char *sig, ObjectIndex class_id,
       
  1533                 SerialNumber trace_serial_num,
       
  1534                 ObjectIndex super_id, ObjectIndex loader_id,
       
  1535                 ObjectIndex signers_id, ObjectIndex domain_id,
       
  1536                 jint size,
       
  1537                 jint n_cpool, ConstantPoolValue *cpool,
       
  1538                 jint n_fields, FieldInfo *fields, jvalue *fvalues)
       
  1539 {
       
  1540     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
  1541     if (gdata->output_format == 'b') {
       
  1542         int  i;
       
  1543         jint n_static_fields;
       
  1544         jint n_inst_fields;
       
  1545         jint inst_size;
       
  1546         jint saved_inst_size;
       
  1547 
       
  1548         n_static_fields = 0;
       
  1549         n_inst_fields = 0;
       
  1550         inst_size = 0;
       
  1551 
       
  1552         /* These do NOT go into the heap output */
       
  1553         for ( i = 0 ; i < n_fields ; i++ ) {
       
  1554             if ( fields[i].cnum == cnum &&
       
  1555                  is_static_field(fields[i].modifiers) ) {
       
  1556                 char *field_name;
       
  1557 
       
  1558                 field_name = string_get(fields[i].name_index);
       
  1559                 (void)write_name_first(field_name);
       
  1560                 n_static_fields++;
       
  1561             }
       
  1562             if ( is_inst_field(fields[i].modifiers) ) {
       
  1563                 inst_size += size_from_field_info(fields[i].primSize);
       
  1564                 if ( fields[i].cnum == cnum ) {
       
  1565                     char *field_name;
       
  1566 
       
  1567                     field_name = string_get(fields[i].name_index);
       
  1568                     (void)write_name_first(field_name);
       
  1569                     n_inst_fields++;
       
  1570                 }
       
  1571             }
       
  1572         }
       
  1573 
       
  1574         /* Verify that the instance size we have calculated as we went
       
  1575          *   through the fields, matches what is saved away with this
       
  1576          *   class.
       
  1577          */
       
  1578         if ( size >= 0 ) {
       
  1579             saved_inst_size = class_get_inst_size(cnum);
       
  1580             if ( saved_inst_size == -1 ) {
       
  1581                 class_set_inst_size(cnum, inst_size);
       
  1582             } else if ( saved_inst_size != inst_size ) {
       
  1583                 HPROF_ERROR(JNI_TRUE, "Mis-match on instance size in class dump");
       
  1584             }
       
  1585         }
       
  1586 
       
  1587         heap_tag(HPROF_GC_CLASS_DUMP);
       
  1588         heap_id(class_id);
       
  1589         heap_u4(trace_serial_num);
       
  1590         heap_id(super_id);
       
  1591         heap_id(loader_id);
       
  1592         heap_id(signers_id);
       
  1593         heap_id(domain_id);
       
  1594         heap_id(0);
       
  1595         heap_id(0);
       
  1596         heap_u4(inst_size); /* Must match inst_size in instance dump */
       
  1597 
       
  1598         heap_u2((unsigned short)n_cpool);
       
  1599         for ( i = 0 ; i < n_cpool ; i++ ) {
       
  1600             HprofType kind;
       
  1601             jint size;
       
  1602 
       
  1603             type_from_signature(string_get(cpool[i].sig_index),
       
  1604                             &kind, &size);
       
  1605             heap_u2((unsigned short)(cpool[i].constant_pool_index));
       
  1606             heap_u1(kind);
       
  1607             HPROF_ASSERT(!HPROF_TYPE_IS_PRIMITIVE(kind));
       
  1608             heap_element(kind, size, cpool[i].value);
       
  1609         }
       
  1610 
       
  1611         heap_u2((unsigned short)n_static_fields);
       
  1612         for ( i = 0 ; i < n_fields ; i++ ) {
       
  1613             if ( fields[i].cnum == cnum &&
       
  1614                  is_static_field(fields[i].modifiers) ) {
       
  1615                 char *field_name;
       
  1616                 HprofType kind;
       
  1617                 jint size;
       
  1618 
       
  1619                 type_from_signature(string_get(fields[i].sig_index),
       
  1620                                 &kind, &size);
       
  1621                 field_name = string_get(fields[i].name_index);
       
  1622                 heap_name(field_name);
       
  1623                 heap_u1(kind);
       
  1624                 heap_element(kind, size, fvalues[i]);
       
  1625             }
       
  1626         }
       
  1627 
       
  1628         heap_u2((unsigned short)n_inst_fields); /* Does not include super class */
       
  1629         for ( i = 0 ; i < n_fields ; i++ ) {
       
  1630             if ( fields[i].cnum == cnum &&
       
  1631                  is_inst_field(fields[i].modifiers) ) {
       
  1632                 HprofType kind;
       
  1633                 jint size;
       
  1634                 char *field_name;
       
  1635 
       
  1636                 field_name = string_get(fields[i].name_index);
       
  1637                 type_from_signature(string_get(fields[i].sig_index),
       
  1638                             &kind, &size);
       
  1639                 heap_name(field_name);
       
  1640                 heap_u1(kind);
       
  1641             }
       
  1642         }
       
  1643     } else {
       
  1644         char * class_name;
       
  1645         int i;
       
  1646 
       
  1647         class_name = signature_to_name(sig);
       
  1648         heap_printf("CLS %x (name=%s, trace=%u)\n",
       
  1649                      class_id, class_name, trace_serial_num);
       
  1650         HPROF_FREE(class_name);
       
  1651         if (super_id) {
       
  1652             heap_printf("\tsuper\t\t%x\n", super_id);
       
  1653         }
       
  1654         if (loader_id) {
       
  1655             heap_printf("\tloader\t\t%x\n", loader_id);
       
  1656         }
       
  1657         if (signers_id) {
       
  1658             heap_printf("\tsigners\t\t%x\n", signers_id);
       
  1659         }
       
  1660         if (domain_id) {
       
  1661             heap_printf("\tdomain\t\t%x\n", domain_id);
       
  1662         }
       
  1663         for ( i = 0 ; i < n_fields ; i++ ) {
       
  1664             if ( fields[i].cnum == cnum &&
       
  1665                  is_static_field(fields[i].modifiers) ) {
       
  1666                 HprofType kind;
       
  1667                 jint size;
       
  1668 
       
  1669                 type_from_signature(string_get(fields[i].sig_index),
       
  1670                                 &kind, &size);
       
  1671                 if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) {
       
  1672                     if (fvalues[i].i != 0 ) {
       
  1673                         char *field_name;
       
  1674 
       
  1675                         field_name = string_get(fields[i].name_index);
       
  1676                         heap_printf("\tstatic %s\t%x\n", field_name,
       
  1677                             fvalues[i].i);
       
  1678                     }
       
  1679                 }
       
  1680             }
       
  1681         }
       
  1682         for ( i = 0 ; i < n_cpool ; i++ ) {
       
  1683             HprofType kind;
       
  1684             jint size;
       
  1685 
       
  1686             type_from_signature(string_get(cpool[i].sig_index), &kind, &size);
       
  1687             if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) {
       
  1688                 if (cpool[i].value.i != 0 ) {
       
  1689                     heap_printf("\tconstant pool entry %d\t%x\n",
       
  1690                             cpool[i].constant_pool_index, cpool[i].value.i);
       
  1691                 }
       
  1692             }
       
  1693         }
       
  1694     }
       
  1695 }
       
  1696 
       
  1697 /* Dump the instance fields in the right order. */
       
  1698 static int
       
  1699 dump_instance_fields(ClassIndex cnum,
       
  1700                      FieldInfo *fields, jvalue *fvalues, jint n_fields)
       
  1701 {
       
  1702     ClassIndex super_cnum;
       
  1703     int        i;
       
  1704     int        nbytes;
       
  1705 
       
  1706     HPROF_ASSERT(cnum!=0);
       
  1707 
       
  1708     nbytes = 0;
       
  1709     for (i = 0; i < n_fields; i++) {
       
  1710         if ( fields[i].cnum == cnum &&
       
  1711              is_inst_field(fields[i].modifiers) ) {
       
  1712             HprofType kind;
       
  1713             int size;
       
  1714 
       
  1715             type_from_signature(string_get(fields[i].sig_index),
       
  1716                             &kind, &size);
       
  1717             heap_element(kind, size, fvalues[i]);
       
  1718             nbytes += size;
       
  1719         }
       
  1720     }
       
  1721 
       
  1722     super_cnum = class_get_super(cnum);
       
  1723     if ( super_cnum != 0 ) {
       
  1724         nbytes += dump_instance_fields(super_cnum, fields, fvalues, n_fields);
       
  1725     }
       
  1726     return nbytes;
       
  1727 }
       
  1728 
       
  1729 void
       
  1730 io_heap_instance_dump(ClassIndex cnum, ObjectIndex obj_id,
       
  1731                 SerialNumber trace_serial_num,
       
  1732                 ObjectIndex class_id, jint size, char *sig,
       
  1733                 FieldInfo *fields, jvalue *fvalues, jint n_fields)
       
  1734 {
       
  1735     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
  1736     if (gdata->output_format == 'b') {
       
  1737         jint inst_size;
       
  1738         jint saved_inst_size;
       
  1739         int  i;
       
  1740         int  nbytes;
       
  1741 
       
  1742         inst_size = 0;
       
  1743         for (i = 0; i < n_fields; i++) {
       
  1744             if ( is_inst_field(fields[i].modifiers) ) {
       
  1745                 inst_size += size_from_field_info(fields[i].primSize);
       
  1746             }
       
  1747         }
       
  1748 
       
  1749         /* Verify that the instance size we have calculated as we went
       
  1750          *   through the fields, matches what is saved away with this
       
  1751          *   class.
       
  1752          */
       
  1753         saved_inst_size = class_get_inst_size(cnum);
       
  1754         if ( saved_inst_size == -1 ) {
       
  1755             class_set_inst_size(cnum, inst_size);
       
  1756         } else if ( saved_inst_size != inst_size ) {
       
  1757             HPROF_ERROR(JNI_TRUE, "Mis-match on instance size in instance dump");
       
  1758         }
       
  1759 
       
  1760         heap_tag(HPROF_GC_INSTANCE_DUMP);
       
  1761         heap_id(obj_id);
       
  1762         heap_u4(trace_serial_num);
       
  1763         heap_id(class_id);
       
  1764         heap_u4(inst_size); /* Must match inst_size in class dump */
       
  1765 
       
  1766         /* Order must be class, super, super's super, ... */
       
  1767         nbytes = dump_instance_fields(cnum, fields, fvalues, n_fields);
       
  1768         HPROF_ASSERT(nbytes==inst_size);
       
  1769     } else {
       
  1770         char * class_name;
       
  1771         int i;
       
  1772 
       
  1773         class_name = signature_to_name(sig);
       
  1774         heap_printf("OBJ %x (sz=%u, trace=%u, class=%s@%x)\n",
       
  1775                      obj_id, size, trace_serial_num, class_name, class_id);
       
  1776         HPROF_FREE(class_name);
       
  1777 
       
  1778         for (i = 0; i < n_fields; i++) {
       
  1779             if ( is_inst_field(fields[i].modifiers) ) {
       
  1780                 HprofType kind;
       
  1781                 int size;
       
  1782 
       
  1783                 type_from_signature(string_get(fields[i].sig_index),
       
  1784                             &kind, &size);
       
  1785                 if ( !HPROF_TYPE_IS_PRIMITIVE(kind) ) {
       
  1786                     if (fvalues[i].i != 0 ) {
       
  1787                         char *sep;
       
  1788                         ObjectIndex val_id;
       
  1789                         char *field_name;
       
  1790 
       
  1791                         field_name = string_get(fields[i].name_index);
       
  1792                         val_id =  (ObjectIndex)(fvalues[i].i);
       
  1793                         sep = (int)strlen(field_name) < 8 ? "\t" : "";
       
  1794                         heap_printf("\t%s\t%s%x\n", field_name, sep, val_id);
       
  1795                     }
       
  1796                 }
       
  1797             }
       
  1798         }
       
  1799     }
       
  1800 }
       
  1801 
       
  1802 void
       
  1803 io_heap_object_array(ObjectIndex obj_id, SerialNumber trace_serial_num,
       
  1804                 jint size, jint num_elements, char *sig, ObjectIndex *values,
       
  1805                 ObjectIndex class_id)
       
  1806 {
       
  1807     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
  1808     if (gdata->output_format == 'b') {
       
  1809 
       
  1810         heap_tag(HPROF_GC_OBJ_ARRAY_DUMP);
       
  1811         heap_id(obj_id);
       
  1812         heap_u4(trace_serial_num);
       
  1813         heap_u4(num_elements);
       
  1814         heap_id(class_id);
       
  1815         heap_elements(HPROF_NORMAL_OBJECT, num_elements,
       
  1816                 (jint)sizeof(HprofId), (void*)values);
       
  1817     } else {
       
  1818         char *name;
       
  1819         int i;
       
  1820 
       
  1821         name = signature_to_name(sig);
       
  1822         heap_printf("ARR %x (sz=%u, trace=%u, nelems=%u, elem type=%s@%x)\n",
       
  1823                      obj_id, size, trace_serial_num, num_elements,
       
  1824                      name, class_id);
       
  1825         for (i = 0; i < num_elements; i++) {
       
  1826             ObjectIndex id;
       
  1827 
       
  1828             id = values[i];
       
  1829             if (id != 0) {
       
  1830                 heap_printf("\t[%u]\t\t%x\n", i, id);
       
  1831             }
       
  1832         }
       
  1833         HPROF_FREE(name);
       
  1834     }
       
  1835 }
       
  1836 
       
  1837 void
       
  1838 io_heap_prim_array(ObjectIndex obj_id, SerialNumber trace_serial_num,
       
  1839               jint size, jint num_elements, char *sig, void *elements)
       
  1840 {
       
  1841     CHECK_TRACE_SERIAL_NO(trace_serial_num);
       
  1842     if (gdata->output_format == 'b') {
       
  1843         HprofType kind;
       
  1844         jint  esize;
       
  1845 
       
  1846         type_array(sig, &kind, &esize);
       
  1847         HPROF_ASSERT(HPROF_TYPE_IS_PRIMITIVE(kind));
       
  1848         heap_tag(HPROF_GC_PRIM_ARRAY_DUMP);
       
  1849         heap_id(obj_id);
       
  1850         heap_u4(trace_serial_num);
       
  1851         heap_u4(num_elements);
       
  1852         heap_u1(kind);
       
  1853         heap_elements(kind, num_elements, esize, elements);
       
  1854     } else {
       
  1855         char *name;
       
  1856 
       
  1857         name = signature_to_name(sig);
       
  1858         heap_printf("ARR %x (sz=%u, trace=%u, nelems=%u, elem type=%s)\n",
       
  1859                      obj_id, size, trace_serial_num, num_elements, name);
       
  1860         HPROF_FREE(name);
       
  1861     }
       
  1862 }
       
  1863 
       
  1864 /* Move file bytes into supplied raw interface */
       
  1865 static void
       
  1866 write_raw_from_file(int fd, jlong byteCount, void (*raw_interface)(void *,int))
       
  1867 {
       
  1868     char *buf;
       
  1869     int   buf_len;
       
  1870     int   left;
       
  1871     int   nbytes;
       
  1872 
       
  1873     HPROF_ASSERT(fd >= 0);
       
  1874 
       
  1875     /* Move contents of this file into output file. */
       
  1876     buf_len = FILE_IO_BUFFER_SIZE*2; /* Twice as big! */
       
  1877     buf = HPROF_MALLOC(buf_len);
       
  1878     HPROF_ASSERT(buf!=NULL);
       
  1879 
       
  1880     /* Keep track of how many we have left */
       
  1881     left = (int)byteCount;
       
  1882     do {
       
  1883         int count;
       
  1884 
       
  1885         count = buf_len;
       
  1886         if ( count > left ) count = left;
       
  1887         nbytes = md_read(fd, buf, count);
       
  1888         if (nbytes < 0) {
       
  1889             system_error("read", nbytes, errno);
       
  1890             break;
       
  1891         }
       
  1892         if (nbytes == 0) {
       
  1893             break;
       
  1894         }
       
  1895         if ( nbytes > 0 ) {
       
  1896             (*raw_interface)(buf, nbytes);
       
  1897             left -= nbytes;
       
  1898         }
       
  1899     } while ( left > 0 );
       
  1900 
       
  1901     if (left > 0 && nbytes == 0) {
       
  1902         HPROF_ERROR(JNI_TRUE, "File size is smaller than bytes written");
       
  1903     }
       
  1904     HPROF_FREE(buf);
       
  1905 }
       
  1906 
       
  1907 /* Write out a heap segment, and copy remainder to top of file. */
       
  1908 static void
       
  1909 dump_heap_segment_and_reset(jlong segment_size)
       
  1910 {
       
  1911     int   fd;
       
  1912     jlong last_chunk_len;
       
  1913 
       
  1914     HPROF_ASSERT(gdata->heap_fd >= 0);
       
  1915 
       
  1916     /* Flush all bytes to the heap dump file */
       
  1917     heap_flush();
       
  1918 
       
  1919     /* Last segment? */
       
  1920     last_chunk_len = gdata->heap_write_count - segment_size;
       
  1921     HPROF_ASSERT(last_chunk_len>=0);
       
  1922 
       
  1923     /* Re-open in proper way, binary vs. ascii is important */
       
  1924     if (gdata->output_format == 'b') {
       
  1925         int   tag;
       
  1926 
       
  1927         if ( gdata->segmented == JNI_TRUE ) { /* 1.0.2 */
       
  1928             tag = HPROF_HEAP_DUMP_SEGMENT; /* 1.0.2 */
       
  1929         } else {
       
  1930             tag = HPROF_HEAP_DUMP; /* Just one segment */
       
  1931             HPROF_ASSERT(last_chunk_len==0);
       
  1932         }
       
  1933 
       
  1934         /* Write header for binary heap dump (don't know size until now) */
       
  1935         write_header(tag, (jint)segment_size);
       
  1936 
       
  1937         fd = md_open_binary(gdata->heapfilename);
       
  1938     } else {
       
  1939         fd = md_open(gdata->heapfilename);
       
  1940     }
       
  1941 
       
  1942     /* Move file bytes into hprof dump file */
       
  1943     write_raw_from_file(fd, segment_size, &write_raw);
       
  1944 
       
  1945     /* Clear the byte count and reset the heap file. */
       
  1946     if ( md_seek(gdata->heap_fd, (jlong)0) != (jlong)0 ) {
       
  1947         HPROF_ERROR(JNI_TRUE, "Cannot seek to beginning of heap info file");
       
  1948     }
       
  1949     gdata->heap_write_count = (jlong)0;
       
  1950     gdata->heap_last_tag_position = (jlong)0;
       
  1951 
       
  1952     /* Move trailing bytes from heap dump file to beginning of file */
       
  1953     if ( last_chunk_len > 0 ) {
       
  1954         write_raw_from_file(fd, last_chunk_len, &heap_raw);
       
  1955     }
       
  1956 
       
  1957     /* Close the temp file handle */
       
  1958     md_close(fd);
       
  1959 }
       
  1960 
       
  1961 void
       
  1962 io_heap_footer(void)
       
  1963 {
       
  1964     HPROF_ASSERT(gdata->heap_fd >= 0);
       
  1965 
       
  1966     /* Flush all bytes to the heap dump file */
       
  1967     heap_flush();
       
  1968 
       
  1969     /* Send out the last (or maybe only) segment */
       
  1970     dump_heap_segment_and_reset(gdata->heap_write_count);
       
  1971 
       
  1972     /* Write out the last tag */
       
  1973     if (gdata->output_format != 'b') {
       
  1974         write_printf("HEAP DUMP END\n");
       
  1975     } else {
       
  1976         if ( gdata->segmented == JNI_TRUE ) { /* 1.0.2 */
       
  1977             write_header(HPROF_HEAP_DUMP_END, 0);
       
  1978         }
       
  1979     }
       
  1980 }