Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/hprof/hprof_reference.c
38829 views
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
/* Object references table (used in hprof_object.c). */
42
43
/*
44
* This table is used by the object table to store object reference
45
* and primitive data information obtained from iterations over the
46
* heap (see hprof_site.c).
47
*
48
* Most of these table entries have no Key, but the key is used to store
49
* the primitive array and primitive field jvalue. None of these entries
50
* are ever looked up, there will be no hash table, use of the
51
* LookupTable was just an easy way to handle a unbounded table of
52
* entries. The object table (see hprof_object.c) will completely
53
* free this reference table after each heap dump or after processing the
54
* references and primitive data.
55
*
56
* The hprof format required this accumulation of all heap iteration
57
* references and primitive data from objects in order to compose an
58
* hprof records for it.
59
*
60
* This file contains detailed understandings of how an hprof CLASS
61
* and INSTANCE dump is constructed, most of this is derived from the
62
* original hprof code, but some has been derived by reading the HAT
63
* code that accepts this format.
64
*
65
*/
66
67
#include "hprof.h"
68
69
/* The flavor of data being saved in the RefInfo */
70
enum {
71
INFO_OBJECT_REF_DATA = 1,
72
INFO_PRIM_FIELD_DATA = 2,
73
INFO_PRIM_ARRAY_DATA = 3
74
};
75
76
/* Reference information, object reference or primitive data information */
77
typedef struct RefInfo {
78
ObjectIndex object_index; /* If an object reference, the referree index */
79
jint index; /* If array or field, array or field index */
80
jint length; /* If array the element count, if not -1 */
81
RefIndex next; /* The next table element */
82
unsigned flavor : 8; /* INFO_*, flavor of RefInfo */
83
unsigned refKind : 8; /* The kind of reference */
84
unsigned primType : 8; /* If primitive data involved, it's type */
85
} RefInfo;
86
87
/* Private internal functions. */
88
89
/* Get the RefInfo structure from an entry */
90
static RefInfo *
91
get_info(RefIndex index)
92
{
93
RefInfo *info;
94
95
info = (RefInfo*)table_get_info(gdata->reference_table, index);
96
return info;
97
}
98
99
/* Get a jvalue that was stored as the key. */
100
static jvalue
101
get_key_value(RefIndex index)
102
{
103
void *key;
104
int len;
105
jvalue value;
106
static jvalue empty_value;
107
108
key = NULL;
109
table_get_key(gdata->reference_table, index, &key, &len);
110
HPROF_ASSERT(key!=NULL);
111
HPROF_ASSERT(len==(int)sizeof(jvalue));
112
if ( key != NULL ) {
113
(void)memcpy(&value, key, (int)sizeof(jvalue));
114
} else {
115
value = empty_value;
116
}
117
return value;
118
}
119
120
/* Get size of a primitive type */
121
static jint
122
get_prim_size(jvmtiPrimitiveType primType)
123
{
124
jint size;
125
126
switch ( primType ) {
127
case JVMTI_PRIMITIVE_TYPE_BOOLEAN:
128
size = (jint)sizeof(jboolean);
129
break;
130
case JVMTI_PRIMITIVE_TYPE_BYTE:
131
size = (jint)sizeof(jbyte);
132
break;
133
case JVMTI_PRIMITIVE_TYPE_CHAR:
134
size = (jint)sizeof(jchar);
135
break;
136
case JVMTI_PRIMITIVE_TYPE_SHORT:
137
size = (jint)sizeof(jshort);
138
break;
139
case JVMTI_PRIMITIVE_TYPE_INT:
140
size = (jint)sizeof(jint);
141
break;
142
case JVMTI_PRIMITIVE_TYPE_FLOAT:
143
size = (jint)sizeof(jfloat);
144
break;
145
case JVMTI_PRIMITIVE_TYPE_LONG:
146
size = (jint)sizeof(jlong);
147
break;
148
case JVMTI_PRIMITIVE_TYPE_DOUBLE:
149
size = (jint)sizeof(jdouble);
150
break;
151
default:
152
HPROF_ASSERT(0);
153
size = 1;
154
break;
155
}
156
return size;
157
}
158
159
/* Get a void* elements array that was stored as the key. */
160
static void *
161
get_key_elements(RefIndex index, jvmtiPrimitiveType primType,
162
jint *nelements, jint *nbytes)
163
{
164
void *key;
165
jint byteLen;
166
167
HPROF_ASSERT(nelements!=NULL);
168
HPROF_ASSERT(nbytes!=NULL);
169
170
table_get_key(gdata->reference_table, index, &key, &byteLen);
171
HPROF_ASSERT(byteLen>=0);
172
HPROF_ASSERT(byteLen!=0?key!=NULL:key==NULL);
173
*nbytes = byteLen;
174
*nelements = byteLen / get_prim_size(primType);
175
return key;
176
}
177
178
/* Dump a RefInfo* structure */
179
static void
180
dump_ref_info(RefInfo *info)
181
{
182
debug_message("[%d]: flavor=%d"
183
", refKind=%d"
184
", primType=%d"
185
", object_index=0x%x"
186
", length=%d"
187
", next=0x%x"
188
"\n",
189
info->index,
190
info->flavor,
191
info->refKind,
192
info->primType,
193
info->object_index,
194
info->length,
195
info->next);
196
}
197
198
/* Dump a RefIndex list */
199
static void
200
dump_ref_list(RefIndex list)
201
{
202
RefInfo *info;
203
RefIndex index;
204
205
debug_message("\nFOLLOW REFERENCES RETURNED:\n");
206
index = list;
207
while ( index != 0 ) {
208
info = get_info(index);
209
dump_ref_info(info);
210
index = info->next;
211
}
212
}
213
214
/* Dump information about a field and what ref data we had on it */
215
static void
216
dump_field(FieldInfo *fields, jvalue *fvalues, int n_fields,
217
jint index, jvalue value, jvmtiPrimitiveType primType)
218
{
219
ClassIndex cnum;
220
StringIndex name;
221
StringIndex sig;
222
223
cnum = fields[index].cnum;
224
name = fields[index].name_index;
225
sig = fields[index].sig_index;
226
debug_message("[%d] %s \"%s\" \"%s\"",
227
index,
228
cnum!=0?string_get(class_get_signature(cnum)):"?",
229
name!=0?string_get(name):"?",
230
sig!=0?string_get(sig):"?");
231
if ( fields[index].primType!=0 || fields[index].primType!=primType ) {
232
debug_message(" (primType=%d(%c)",
233
fields[index].primType,
234
primTypeToSigChar(fields[index].primType));
235
if ( primType != fields[index].primType ) {
236
debug_message(", got %d(%c)",
237
primType,
238
primTypeToSigChar(primType));
239
}
240
debug_message(")");
241
} else {
242
debug_message("(ty=OBJ)");
243
}
244
if ( value.j != (jlong)0 || fvalues[index].j != (jlong)0 ) {
245
debug_message(" val=[0x%08x,0x%08x] or [0x%08x,0x%08x]",
246
jlong_high(value.j), jlong_low(value.j),
247
jlong_high(fvalues[index].j), jlong_low(fvalues[index].j));
248
}
249
debug_message("\n");
250
}
251
252
/* Dump all the fields of interest */
253
static void
254
dump_fields(RefIndex list, FieldInfo *fields, jvalue *fvalues, int n_fields)
255
{
256
int i;
257
258
debug_message("\nHPROF LIST OF ALL FIELDS:\n");
259
for ( i = 0 ; i < n_fields ; i++ ) {
260
if ( fields[i].name_index != 0 ) {
261
dump_field(fields, fvalues, n_fields, i, fvalues[i], fields[i].primType);
262
}
263
}
264
dump_ref_list(list);
265
}
266
267
/* Verify field data */
268
static void
269
verify_field(RefIndex list, FieldInfo *fields, jvalue *fvalues, int n_fields,
270
jint index, jvalue value, jvmtiPrimitiveType primType)
271
{
272
HPROF_ASSERT(fvalues != NULL);
273
HPROF_ASSERT(n_fields > 0);
274
HPROF_ASSERT(index < n_fields);
275
HPROF_ASSERT(index >= 0 );
276
if ( primType!=fields[index].primType ) {
277
dump_fields(list, fields, fvalues, n_fields);
278
debug_message("\nPROBLEM WITH:\n");
279
dump_field(fields, fvalues, n_fields, index, value, primType);
280
debug_message("\n");
281
HPROF_ERROR(JNI_FALSE, "Trouble with fields and heap data");
282
}
283
if ( primType == JVMTI_PRIMITIVE_TYPE_BOOLEAN &&
284
( value.b != 1 && value.b != 0 ) ) {
285
dump_fields(list, fields, fvalues, n_fields);
286
debug_message("\nPROBLEM WITH:\n");
287
dump_field(fields, fvalues, n_fields, index, value, primType);
288
debug_message("\n");
289
HPROF_ERROR(JNI_FALSE, "Trouble with fields and heap data");
290
}
291
}
292
293
/* Fill in a field value, making sure the index is safe */
294
static void
295
fill_in_field_value(RefIndex list, FieldInfo *fields, jvalue *fvalues,
296
int n_fields, jint index, jvalue value,
297
jvmtiPrimitiveType primType)
298
{
299
HPROF_ASSERT(fvalues != NULL);
300
HPROF_ASSERT(n_fields > 0);
301
HPROF_ASSERT(index < n_fields);
302
HPROF_ASSERT(index >= 0 );
303
HPROF_ASSERT(fvalues[index].j==(jlong)0);
304
verify_field(list, fields, fvalues, n_fields, index, value, primType);
305
if (index >= 0 && index < n_fields) {
306
fvalues[index] = value;
307
}
308
}
309
310
/* Walk all references for an ObjectIndex and construct the hprof CLASS dump. */
311
static void
312
dump_class_and_supers(JNIEnv *env, ObjectIndex object_index, RefIndex list)
313
{
314
SiteIndex site_index;
315
SerialNumber trace_serial_num;
316
RefIndex index;
317
ClassIndex super_cnum;
318
ObjectIndex super_index;
319
LoaderIndex loader_index;
320
ObjectIndex signers_index;
321
ObjectIndex domain_index;
322
FieldInfo *fields;
323
jvalue *fvalues;
324
jint n_fields;
325
jboolean skip_fields;
326
jint n_fields_set;
327
jlong size;
328
ClassIndex cnum;
329
char *sig;
330
ObjectKind kind;
331
TraceIndex trace_index;
332
Stack *cpool_values;
333
ConstantPoolValue *cpool;
334
jint cpool_count;
335
336
HPROF_ASSERT(object_index!=0);
337
kind = object_get_kind(object_index);
338
if ( kind != OBJECT_CLASS ) {
339
return;
340
}
341
site_index = object_get_site(object_index);
342
HPROF_ASSERT(site_index!=0);
343
cnum = site_get_class_index(site_index);
344
HPROF_ASSERT(cnum!=0);
345
if ( class_get_status(cnum) & CLASS_DUMPED ) {
346
return;
347
}
348
class_add_status(cnum, CLASS_DUMPED);
349
size = (jlong)object_get_size(object_index);
350
351
super_index = 0;
352
super_cnum = class_get_super(cnum);
353
if ( super_cnum != 0 ) {
354
super_index = class_get_object_index(super_cnum);
355
if ( super_index != 0 ) {
356
dump_class_and_supers(env, super_index,
357
object_get_references(super_index));
358
}
359
}
360
361
trace_index = site_get_trace_index(site_index);
362
HPROF_ASSERT(trace_index!=0);
363
trace_serial_num = trace_get_serial_number(trace_index);
364
sig = string_get(class_get_signature(cnum));
365
loader_index = class_get_loader(cnum);
366
signers_index = 0;
367
domain_index = 0;
368
369
/* Get field information */
370
n_fields = 0;
371
skip_fields = JNI_FALSE;
372
n_fields_set = 0;
373
fields = NULL;
374
fvalues = NULL;
375
if ( class_get_all_fields(env, cnum, &n_fields, &fields) == 1 ) {
376
/* Problems getting all the fields, can't trust field index values */
377
skip_fields = JNI_TRUE;
378
/* Class with no references at all? (ok to be unprepared if list==0?) */
379
if ( list != 0 ) {
380
/* It is assumed that the reason why we didn't get the fields
381
* was because the class is not prepared.
382
*/
383
if ( gdata->debugflags & DEBUGFLAG_UNPREPARED_CLASSES ) {
384
dump_ref_list(list);
385
debug_message("Unprepared class with references: %s\n",
386
sig);
387
}
388
HPROF_ERROR(JNI_FALSE, "Trouble with unprepared classes");
389
}
390
/* Why would an unprepared class contain references? */
391
}
392
if ( n_fields > 0 ) {
393
fvalues = (jvalue*)HPROF_MALLOC(n_fields*(int)sizeof(jvalue));
394
(void)memset(fvalues, 0, n_fields*(int)sizeof(jvalue));
395
}
396
397
/* We use a Stack just because it will automatically expand as needed */
398
cpool_values = stack_init(16, 16, sizeof(ConstantPoolValue));
399
cpool = NULL;
400
cpool_count = 0;
401
402
index = list;
403
while ( index != 0 ) {
404
RefInfo *info;
405
jvalue ovalue;
406
static jvalue empty_value;
407
408
info = get_info(index);
409
410
switch ( info->flavor ) {
411
case INFO_OBJECT_REF_DATA:
412
switch ( info->refKind ) {
413
case JVMTI_HEAP_REFERENCE_FIELD:
414
case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT:
415
/* Should never be seen on a class dump */
416
HPROF_ASSERT(0);
417
break;
418
case JVMTI_HEAP_REFERENCE_STATIC_FIELD:
419
if ( skip_fields == JNI_TRUE ) {
420
break;
421
}
422
ovalue = empty_value;
423
ovalue.i = info->object_index;
424
fill_in_field_value(list, fields, fvalues, n_fields,
425
info->index, ovalue, 0);
426
n_fields_set++;
427
HPROF_ASSERT(n_fields_set <= n_fields);
428
break;
429
case JVMTI_HEAP_REFERENCE_CONSTANT_POOL: {
430
ConstantPoolValue cpv;
431
ObjectIndex cp_object_index;
432
SiteIndex cp_site_index;
433
ClassIndex cp_cnum;
434
435
cp_object_index = info->object_index;
436
HPROF_ASSERT(cp_object_index!=0);
437
cp_site_index = object_get_site(cp_object_index);
438
HPROF_ASSERT(cp_site_index!=0);
439
cp_cnum = site_get_class_index(cp_site_index);
440
cpv.constant_pool_index = info->index;
441
cpv.sig_index = class_get_signature(cp_cnum);
442
cpv.value.i = cp_object_index;
443
stack_push(cpool_values, (void*)&cpv);
444
cpool_count++;
445
break;
446
}
447
case JVMTI_HEAP_REFERENCE_SIGNERS:
448
signers_index = info->object_index;
449
break;
450
case JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN:
451
domain_index = info->object_index;
452
break;
453
case JVMTI_HEAP_REFERENCE_CLASS_LOADER:
454
case JVMTI_HEAP_REFERENCE_INTERFACE:
455
default:
456
/* Ignore, not needed */
457
break;
458
}
459
break;
460
case INFO_PRIM_FIELD_DATA:
461
if ( skip_fields == JNI_TRUE ) {
462
break;
463
}
464
HPROF_ASSERT(info->primType!=0);
465
HPROF_ASSERT(info->length==-1);
466
HPROF_ASSERT(info->refKind==JVMTI_HEAP_REFERENCE_STATIC_FIELD);
467
ovalue = get_key_value(index);
468
fill_in_field_value(list, fields, fvalues, n_fields,
469
info->index, ovalue, info->primType);
470
n_fields_set++;
471
HPROF_ASSERT(n_fields_set <= n_fields);
472
break;
473
case INFO_PRIM_ARRAY_DATA:
474
default:
475
/* Should never see these */
476
HPROF_ASSERT(0);
477
break;
478
}
479
480
index = info->next;
481
}
482
483
/* Get constant pool data if we have any */
484
HPROF_ASSERT(cpool_count==stack_depth(cpool_values));
485
if ( cpool_count > 0 ) {
486
cpool = (ConstantPoolValue*)stack_element(cpool_values, 0);
487
}
488
io_heap_class_dump(cnum, sig, object_index, trace_serial_num,
489
super_index,
490
loader_object_index(env, loader_index),
491
signers_index, domain_index,
492
(jint)size, cpool_count, cpool, n_fields, fields, fvalues);
493
494
stack_term(cpool_values);
495
if ( fvalues != NULL ) {
496
HPROF_FREE(fvalues);
497
}
498
}
499
500
/* Walk all references for an ObjectIndex and construct the hprof INST dump. */
501
static void
502
dump_instance(JNIEnv *env, ObjectIndex object_index, RefIndex list)
503
{
504
jvmtiPrimitiveType primType;
505
SiteIndex site_index;
506
SerialNumber trace_serial_num;
507
RefIndex index;
508
ObjectIndex class_index;
509
jlong size;
510
ClassIndex cnum;
511
char *sig;
512
void *elements;
513
jint num_elements;
514
jint num_bytes;
515
ObjectIndex *values;
516
FieldInfo *fields;
517
jvalue *fvalues;
518
jint n_fields;
519
jboolean skip_fields;
520
jint n_fields_set;
521
ObjectKind kind;
522
TraceIndex trace_index;
523
jboolean is_array;
524
jboolean is_prim_array;
525
526
HPROF_ASSERT(object_index!=0);
527
kind = object_get_kind(object_index);
528
if ( kind == OBJECT_CLASS ) {
529
return;
530
}
531
site_index = object_get_site(object_index);
532
HPROF_ASSERT(site_index!=0);
533
cnum = site_get_class_index(site_index);
534
HPROF_ASSERT(cnum!=0);
535
size = (jlong)object_get_size(object_index);
536
trace_index = site_get_trace_index(site_index);
537
HPROF_ASSERT(trace_index!=0);
538
trace_serial_num = trace_get_serial_number(trace_index);
539
sig = string_get(class_get_signature(cnum));
540
class_index = class_get_object_index(cnum);
541
542
values = NULL;
543
elements = NULL;
544
num_elements = 0;
545
num_bytes = 0;
546
547
n_fields = 0;
548
skip_fields = JNI_FALSE;
549
n_fields_set = 0;
550
fields = NULL;
551
fvalues = NULL;
552
553
index = list;
554
555
is_array = JNI_FALSE;
556
is_prim_array = JNI_FALSE;
557
558
if ( sig[0] != JVM_SIGNATURE_ARRAY ) {
559
if ( class_get_all_fields(env, cnum, &n_fields, &fields) == 1 ) {
560
/* Trouble getting all the fields, can't trust field index values */
561
skip_fields = JNI_TRUE;
562
/* It is assumed that the reason why we didn't get the fields
563
* was because the class is not prepared.
564
*/
565
if ( gdata->debugflags & DEBUGFLAG_UNPREPARED_CLASSES ) {
566
if ( list != 0 ) {
567
dump_ref_list(list);
568
debug_message("Instance of unprepared class with refs: %s\n",
569
sig);
570
} else {
571
debug_message("Instance of unprepared class without refs: %s\n",
572
sig);
573
}
574
HPROF_ERROR(JNI_FALSE, "Big Trouble with unprepared class instances");
575
}
576
}
577
if ( n_fields > 0 ) {
578
fvalues = (jvalue*)HPROF_MALLOC(n_fields*(int)sizeof(jvalue));
579
(void)memset(fvalues, 0, n_fields*(int)sizeof(jvalue));
580
}
581
} else {
582
is_array = JNI_TRUE;
583
if ( sig[0] != 0 && sigToPrimSize(sig+1) != 0 ) {
584
is_prim_array = JNI_TRUE;
585
}
586
}
587
588
while ( index != 0 ) {
589
RefInfo *info;
590
jvalue ovalue;
591
static jvalue empty_value;
592
593
info = get_info(index);
594
595
/* Process reference objects, many not used right now. */
596
switch ( info->flavor ) {
597
case INFO_OBJECT_REF_DATA:
598
switch ( info->refKind ) {
599
case JVMTI_HEAP_REFERENCE_SIGNERS:
600
case JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN:
601
case JVMTI_HEAP_REFERENCE_CLASS_LOADER:
602
case JVMTI_HEAP_REFERENCE_INTERFACE:
603
case JVMTI_HEAP_REFERENCE_STATIC_FIELD:
604
case JVMTI_HEAP_REFERENCE_CONSTANT_POOL:
605
/* Should never be seen on an instance dump */
606
HPROF_ASSERT(0);
607
break;
608
case JVMTI_HEAP_REFERENCE_FIELD:
609
if ( skip_fields == JNI_TRUE ) {
610
break;
611
}
612
HPROF_ASSERT(is_array!=JNI_TRUE);
613
ovalue = empty_value;
614
ovalue.i = info->object_index;
615
fill_in_field_value(list, fields, fvalues, n_fields,
616
info->index, ovalue, 0);
617
n_fields_set++;
618
HPROF_ASSERT(n_fields_set <= n_fields);
619
break;
620
case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT:
621
/* We get each object element one at a time. */
622
HPROF_ASSERT(is_array==JNI_TRUE);
623
HPROF_ASSERT(is_prim_array!=JNI_TRUE);
624
if ( num_elements <= info->index ) {
625
int nbytes;
626
627
if ( values == NULL ) {
628
num_elements = info->index + 1;
629
nbytes = num_elements*(int)sizeof(ObjectIndex);
630
values = (ObjectIndex*)HPROF_MALLOC(nbytes);
631
(void)memset(values, 0, nbytes);
632
} else {
633
void *new_values;
634
int new_size;
635
int obytes;
636
637
obytes = num_elements*(int)sizeof(ObjectIndex);
638
new_size = info->index + 1;
639
nbytes = new_size*(int)sizeof(ObjectIndex);
640
new_values = (void*)HPROF_MALLOC(nbytes);
641
(void)memcpy(new_values, values, obytes);
642
(void)memset(((char*)new_values)+obytes, 0,
643
nbytes-obytes);
644
HPROF_FREE(values);
645
num_elements = new_size;
646
values = new_values;
647
}
648
}
649
HPROF_ASSERT(values[info->index]==0);
650
values[info->index] = info->object_index;
651
break;
652
default:
653
/* Ignore, not needed */
654
break;
655
}
656
break;
657
case INFO_PRIM_FIELD_DATA:
658
if ( skip_fields == JNI_TRUE ) {
659
break;
660
}
661
HPROF_ASSERT(info->primType!=0);
662
HPROF_ASSERT(info->length==-1);
663
HPROF_ASSERT(info->refKind==JVMTI_HEAP_REFERENCE_FIELD);
664
HPROF_ASSERT(is_array!=JNI_TRUE);
665
ovalue = get_key_value(index);
666
fill_in_field_value(list, fields, fvalues, n_fields,
667
info->index, ovalue, info->primType);
668
n_fields_set++;
669
HPROF_ASSERT(n_fields_set <= n_fields);
670
break;
671
case INFO_PRIM_ARRAY_DATA:
672
/* Should only be one, and it's handled below */
673
HPROF_ASSERT(info->refKind==0);
674
/* We assert that nothing else was saved with this array */
675
HPROF_ASSERT(index==list&&info->next==0);
676
HPROF_ASSERT(is_array==JNI_TRUE);
677
HPROF_ASSERT(is_prim_array==JNI_TRUE);
678
primType = info->primType;
679
elements = get_key_elements(index, primType,
680
&num_elements, &num_bytes);
681
HPROF_ASSERT(info->length==num_elements);
682
size = num_bytes;
683
break;
684
default:
685
HPROF_ASSERT(0);
686
break;
687
}
688
index = info->next;
689
}
690
691
if ( is_array == JNI_TRUE ) {
692
if ( is_prim_array == JNI_TRUE ) {
693
HPROF_ASSERT(values==NULL);
694
io_heap_prim_array(object_index, trace_serial_num,
695
(jint)size, num_elements, sig, elements);
696
} else {
697
HPROF_ASSERT(elements==NULL);
698
io_heap_object_array(object_index, trace_serial_num,
699
(jint)size, num_elements, sig, values, class_index);
700
}
701
} else {
702
io_heap_instance_dump(cnum, object_index, trace_serial_num,
703
class_index, (jint)size, sig, fields, fvalues, n_fields);
704
}
705
if ( values != NULL ) {
706
HPROF_FREE(values);
707
}
708
if ( fvalues != NULL ) {
709
HPROF_FREE(fvalues);
710
}
711
if ( elements != NULL ) {
712
/* Do NOT free elements, it's a key in the table, leave it be */
713
}
714
}
715
716
/* External interfaces. */
717
718
void
719
reference_init(void)
720
{
721
HPROF_ASSERT(gdata->reference_table==NULL);
722
gdata->reference_table = table_initialize("Ref", 2048, 4096, 0,
723
(int)sizeof(RefInfo));
724
}
725
726
/* Save away a reference to an object */
727
RefIndex
728
reference_obj(RefIndex next, jvmtiHeapReferenceKind refKind,
729
ObjectIndex object_index, jint index, jint length)
730
{
731
static RefInfo empty_info;
732
RefIndex entry;
733
RefInfo info;
734
735
info = empty_info;
736
info.flavor = INFO_OBJECT_REF_DATA;
737
info.refKind = refKind;
738
info.object_index = object_index;
739
info.index = index;
740
info.length = length;
741
info.next = next;
742
entry = table_create_entry(gdata->reference_table, NULL, 0, (void*)&info);
743
return entry;
744
}
745
746
/* Save away some primitive field data */
747
RefIndex
748
reference_prim_field(RefIndex next, jvmtiHeapReferenceKind refKind,
749
jvmtiPrimitiveType primType, jvalue field_value, jint field_index)
750
{
751
static RefInfo empty_info;
752
RefIndex entry;
753
RefInfo info;
754
755
HPROF_ASSERT(primType==JVMTI_PRIMITIVE_TYPE_BOOLEAN?(field_value.b==1||field_value.b==0):1);
756
757
info = empty_info;
758
info.flavor = INFO_PRIM_FIELD_DATA;
759
info.refKind = refKind;
760
info.primType = primType;
761
info.index = field_index;
762
info.length = -1;
763
info.next = next;
764
entry = table_create_entry(gdata->reference_table,
765
(void*)&field_value, (int)sizeof(jvalue), (void*)&info);
766
return entry;
767
}
768
769
/* Save away some primitive array data */
770
RefIndex
771
reference_prim_array(RefIndex next, jvmtiPrimitiveType primType,
772
const void *elements, jint elementCount)
773
{
774
static RefInfo empty_info;
775
RefIndex entry;
776
RefInfo info;
777
778
HPROF_ASSERT(next == 0);
779
HPROF_ASSERT(elementCount >= 0);
780
HPROF_ASSERT(elements != NULL);
781
782
info = empty_info;
783
info.flavor = INFO_PRIM_ARRAY_DATA;
784
info.refKind = 0;
785
info.primType = primType;
786
info.index = 0;
787
info.length = elementCount;
788
info.next = next;
789
entry = table_create_entry(gdata->reference_table, (void*)elements,
790
elementCount * get_prim_size(primType), (void*)&info);
791
return entry;
792
}
793
794
void
795
reference_cleanup(void)
796
{
797
if ( gdata->reference_table == NULL ) {
798
return;
799
}
800
table_cleanup(gdata->reference_table, NULL, NULL);
801
gdata->reference_table = NULL;
802
}
803
804
void
805
reference_dump_instance(JNIEnv *env, ObjectIndex object_index, RefIndex list)
806
{
807
dump_instance(env, object_index, list);
808
}
809
810
void
811
reference_dump_class(JNIEnv *env, ObjectIndex object_index, RefIndex list)
812
{
813
dump_class_and_supers(env, object_index, list);
814
}
815
816