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 } |
|