author | tschatzl |
Wed, 19 Aug 2015 13:59:39 +0200 | |
changeset 32379 | aa14adafaf0f |
parent 26201 | 40a873d21081 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
14342
8435a30053c1
7197491: update copyright year to match last edit in jdk8 jdk repository
alanb
parents:
10292
diff
changeset
|
2 |
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
* |
|
5506 | 15 |
* - Neither the name of Oracle nor the names of its |
2 | 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 |
||
10292
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
32 |
/* |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
33 |
* This source code is provided to illustrate the usage of a given feature |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
34 |
* or technique and has been deliberately simplified. Additional steps |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
35 |
* required for a production-quality application, such as security checks, |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
36 |
* input validation and proper error handling, might not be present in |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
37 |
* this sample code. |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
38 |
*/ |
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
39 |
|
ed7db6a12c2a
7067811: Update demo/sample code to state it should not be used for production
nloodin
parents:
5506
diff
changeset
|
40 |
|
2 | 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 |
} |