Mercurial > hg > truffle
comparison src/os/solaris/dtrace/libjvm_db.c @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | d68b1274b9ba |
children | fd94cbe7c5da |
comparison
equal
deleted
inserted
replaced
6724:36d1d483d5d6 | 6725:da91efe96a93 |
---|---|
99 #define COMP_METHOD_SIGN '*' | 99 #define COMP_METHOD_SIGN '*' |
100 | 100 |
101 #define MAX_VFRAMES_CNT 256 | 101 #define MAX_VFRAMES_CNT 256 |
102 | 102 |
103 typedef struct vframe { | 103 typedef struct vframe { |
104 uint64_t methodOop; | 104 uint64_t method; |
105 int32_t sender_decode_offset; | 105 int32_t sender_decode_offset; |
106 int32_t methodIdx; | 106 int32_t methodIdx; |
107 int32_t bci; | 107 int32_t bci; |
108 int32_t line; | 108 int32_t line; |
109 } Vframe_t; | 109 } Vframe_t; |
127 int32_t instrs_beg; /* _code_offset */ | 127 int32_t instrs_beg; /* _code_offset */ |
128 int32_t instrs_end; | 128 int32_t instrs_end; |
129 int32_t deopt_beg; /* _deoptimize_offset */ | 129 int32_t deopt_beg; /* _deoptimize_offset */ |
130 int32_t scopes_data_beg; /* _scopes_data_offset */ | 130 int32_t scopes_data_beg; /* _scopes_data_offset */ |
131 int32_t scopes_data_end; | 131 int32_t scopes_data_end; |
132 int32_t oops_beg; /* _oops_offset */ | 132 int32_t metadata_beg; /* _metadata_offset */ |
133 int32_t oops_end; | 133 int32_t metadata_end; |
134 int32_t scopes_pcs_beg; /* _scopes_pcs_offset */ | 134 int32_t scopes_pcs_beg; /* _scopes_pcs_offset */ |
135 int32_t scopes_pcs_end; | 135 int32_t scopes_pcs_end; |
136 | 136 |
137 int vf_cnt; | 137 int vf_cnt; |
138 Vframe_t vframes[MAX_VFRAMES_CNT]; | 138 Vframe_t vframes[MAX_VFRAMES_CNT]; |
143 | 143 |
144 uint64_t nmethod_vtbl; | 144 uint64_t nmethod_vtbl; |
145 uint64_t CodeBlob_vtbl; | 145 uint64_t CodeBlob_vtbl; |
146 uint64_t BufferBlob_vtbl; | 146 uint64_t BufferBlob_vtbl; |
147 uint64_t RuntimeStub_vtbl; | 147 uint64_t RuntimeStub_vtbl; |
148 uint64_t Method_vtbl; | |
148 | 149 |
149 uint64_t Use_Compressed_Oops_address; | 150 uint64_t Use_Compressed_Oops_address; |
150 uint64_t Universe_methodKlassObj_address; | |
151 uint64_t Universe_narrow_oop_base_address; | 151 uint64_t Universe_narrow_oop_base_address; |
152 uint64_t Universe_narrow_oop_shift_address; | 152 uint64_t Universe_narrow_oop_shift_address; |
153 uint64_t CodeCache_heap_address; | 153 uint64_t CodeCache_heap_address; |
154 | 154 |
155 /* Volatiles */ | 155 /* Volatiles */ |
156 uint8_t Use_Compressed_Oops; | 156 uint8_t Use_Compressed_Oops; |
157 uint64_t Universe_methodKlassObj; | |
158 uint64_t Universe_narrow_oop_base; | 157 uint64_t Universe_narrow_oop_base; |
159 uint32_t Universe_narrow_oop_shift; | 158 uint32_t Universe_narrow_oop_shift; |
160 uint64_t CodeCache_low; | 159 uint64_t CodeCache_low; |
161 uint64_t CodeCache_high; | 160 uint64_t CodeCache_high; |
162 uint64_t CodeCache_segmap_low; | 161 uint64_t CodeCache_segmap_low; |
163 uint64_t CodeCache_segmap_high; | 162 uint64_t CodeCache_segmap_high; |
164 | 163 |
165 int32_t SIZE_CodeCache_log2_segment; | 164 int32_t SIZE_CodeCache_log2_segment; |
166 | 165 |
167 uint64_t methodOopPtr; | 166 uint64_t methodPtr; |
168 uint64_t bcx; | 167 uint64_t bcx; |
169 | 168 |
170 Nmethod_t *N; /*Inlined methods support */ | 169 Nmethod_t *N; /*Inlined methods support */ |
171 Frame_t prev_fr; | 170 Frame_t prev_fr; |
172 Frame_t curr_fr; | 171 Frame_t curr_fr; |
278 if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) { | 277 if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) { |
279 if (strcmp("_heap", vmp->fieldName) == 0) { | 278 if (strcmp("_heap", vmp->fieldName) == 0) { |
280 err = read_pointer(J, vmp->address, &J->CodeCache_heap_address); | 279 err = read_pointer(J, vmp->address, &J->CodeCache_heap_address); |
281 } | 280 } |
282 } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) { | 281 } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) { |
283 if (strcmp("_methodKlassObj", vmp->fieldName) == 0) { | |
284 J->Universe_methodKlassObj_address = vmp->address; | |
285 } | |
286 if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) { | 282 if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) { |
287 J->Universe_narrow_oop_base_address = vmp->address; | 283 J->Universe_narrow_oop_base_address = vmp->address; |
288 } | 284 } |
289 if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) { | 285 if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) { |
290 J->Universe_narrow_oop_shift_address = vmp->address; | 286 J->Universe_narrow_oop_shift_address = vmp->address; |
327 err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t)); | 323 err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t)); |
328 CHECK_FAIL(err); | 324 CHECK_FAIL(err); |
329 } else { | 325 } else { |
330 J->Use_Compressed_Oops = 0; | 326 J->Use_Compressed_Oops = 0; |
331 } | 327 } |
332 | |
333 err = read_pointer(J, J->Universe_methodKlassObj_address, &J->Universe_methodKlassObj); | |
334 CHECK_FAIL(err); | |
335 | 328 |
336 err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base); | 329 err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base); |
337 CHECK_FAIL(err); | 330 CHECK_FAIL(err); |
338 err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t)); | 331 err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t)); |
339 CHECK_FAIL(err); | 332 CHECK_FAIL(err); |
453 if (err != PS_OK) J->BufferBlob_vtbl = 0; | 446 if (err != PS_OK) J->BufferBlob_vtbl = 0; |
454 err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl); | 447 err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl); |
455 CHECK_FAIL(err); | 448 CHECK_FAIL(err); |
456 err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl); | 449 err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl); |
457 CHECK_FAIL(err); | 450 CHECK_FAIL(err); |
451 err = find_symbol(J, "__1cGMethodG__vtbl_", &J->Method_vtbl); | |
452 CHECK_FAIL(err); | |
458 | 453 |
459 err = parse_vmstructs(J); | 454 err = parse_vmstructs(J); |
460 CHECK_FAIL(err); | 455 CHECK_FAIL(err); |
461 err = read_volatiles(J); | 456 err = read_volatiles(J); |
462 CHECK_FAIL(err); | 457 CHECK_FAIL(err); |
472 if (J != NULL) { | 467 if (J != NULL) { |
473 free(J); | 468 free(J); |
474 } | 469 } |
475 } | 470 } |
476 | 471 |
477 static int is_methodOop(jvm_agent_t* J, uint64_t methodOopPtr) { | 472 static int is_method(jvm_agent_t* J, uint64_t methodPtr) { |
478 uint64_t klass; | 473 uint64_t klass; |
479 int err; | 474 int err = read_pointer(J, methodPtr, &klass); |
480 // If UseCompressedOops, this was a compressed oop. | |
481 if (J->Use_Compressed_Oops != 0) { | |
482 uint32_t cklass; | |
483 err = read_compressed_pointer(J, methodOopPtr + OFFSET_oopDesc_metadata, | |
484 &cklass); | |
485 // decode heap oop, same as oop.inline.hpp | |
486 klass = (uint64_t)((uintptr_t)J->Universe_narrow_oop_base + | |
487 ((uintptr_t)cklass << J->Universe_narrow_oop_shift)); | |
488 } else { | |
489 err = read_pointer(J, methodOopPtr + OFFSET_oopDesc_metadata, &klass); | |
490 } | |
491 if (err != PS_OK) goto fail; | 475 if (err != PS_OK) goto fail; |
492 return klass == J->Universe_methodKlassObj; | 476 return klass == J->Method_vtbl; |
493 | 477 |
494 fail: | 478 fail: |
495 return 0; | 479 return 0; |
496 } | 480 } |
497 | 481 |
498 static int | 482 static int |
499 name_for_methodOop(jvm_agent_t* J, uint64_t methodOopPtr, char * result, size_t size) | 483 name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t size) |
500 { | 484 { |
501 short nameIndex; | 485 short nameIndex; |
502 short signatureIndex; | 486 short signatureIndex; |
503 uint64_t constantPool; | 487 uint64_t constantPool; |
504 uint64_t constMethod; | 488 uint64_t constMethod; |
512 char * nameString = NULL; | 496 char * nameString = NULL; |
513 char * klassString = NULL; | 497 char * klassString = NULL; |
514 char * signatureString = NULL; | 498 char * signatureString = NULL; |
515 int err; | 499 int err; |
516 | 500 |
517 err = read_pointer(J, methodOopPtr + OFFSET_methodOopDesc_constMethod, &constMethod); | 501 err = read_pointer(J, methodPtr + OFFSET_Method_constMethod, &constMethod); |
518 CHECK_FAIL(err); | 502 CHECK_FAIL(err); |
519 err = read_pointer(J, constMethod + OFFSET_constMethodOopDesc_constants, &constantPool); | 503 err = read_pointer(J, constMethod + OFFSET_ConstMethod_constants, &constantPool); |
520 CHECK_FAIL(err); | 504 CHECK_FAIL(err); |
521 | 505 |
522 /* To get name string */ | 506 /* To get name string */ |
523 err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_name_index, &nameIndex, 2); | 507 err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_name_index, &nameIndex, 2); |
524 CHECK_FAIL(err); | 508 CHECK_FAIL(err); |
525 err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &nameSymbol); | 509 err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_ConstantPool, &nameSymbol); |
526 CHECK_FAIL(err); | 510 CHECK_FAIL(err); |
527 // The symbol is a CPSlot and has lower bit set to indicate metadata | 511 // The symbol is a CPSlot and has lower bit set to indicate metadata |
528 nameSymbol &= (~1); // remove metadata lsb | 512 nameSymbol &= (~1); // remove metadata lsb |
529 err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2); | 513 err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2); |
530 CHECK_FAIL(err); | 514 CHECK_FAIL(err); |
531 nameString = (char*)calloc(nameSymbolLength + 1, 1); | 515 nameString = (char*)calloc(nameSymbolLength + 1, 1); |
532 err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength); | 516 err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength); |
533 CHECK_FAIL(err); | 517 CHECK_FAIL(err); |
534 | 518 |
535 /* To get signature string */ | 519 /* To get signature string */ |
536 err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_signature_index, &signatureIndex, 2); | 520 err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_signature_index, &signatureIndex, 2); |
537 CHECK_FAIL(err); | 521 CHECK_FAIL(err); |
538 err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &signatureSymbol); | 522 err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol); |
539 CHECK_FAIL(err); | 523 CHECK_FAIL(err); |
540 signatureSymbol &= (~1); // remove metadata lsb | 524 signatureSymbol &= (~1); // remove metadata lsb |
541 err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2); | 525 err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2); |
542 CHECK_FAIL(err); | 526 CHECK_FAIL(err); |
543 signatureString = (char*)calloc(signatureSymbolLength + 1, 1); | 527 signatureString = (char*)calloc(signatureSymbolLength + 1, 1); |
544 err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength); | 528 err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength); |
545 CHECK_FAIL(err); | 529 CHECK_FAIL(err); |
546 | 530 |
547 /* To get klass string */ | 531 /* To get klass string */ |
548 err = read_pointer(J, constantPool + OFFSET_constantPoolOopDesc_pool_holder, &klassPtr); | 532 err = read_pointer(J, constantPool + OFFSET_ConstantPool_pool_holder, &klassPtr); |
549 CHECK_FAIL(err); | 533 CHECK_FAIL(err); |
550 err = read_pointer(J, klassPtr + OFFSET_Klass_name + SIZE_oopDesc, &klassSymbol); | 534 err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol); |
551 CHECK_FAIL(err); | 535 CHECK_FAIL(err); |
552 err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2); | 536 err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2); |
553 CHECK_FAIL(err); | 537 CHECK_FAIL(err); |
554 klassString = (char*)calloc(klassSymbolLength + 1, 1); | 538 klassString = (char*)calloc(klassSymbolLength + 1, 1); |
555 err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength); | 539 err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength); |
570 | 554 |
571 return PS_OK; | 555 return PS_OK; |
572 | 556 |
573 fail: | 557 fail: |
574 if (debug) { | 558 if (debug) { |
575 fprintf(stderr, "name_for_methodOop: FAIL \n\n"); | 559 fprintf(stderr, "name_for_methodPtr: FAIL \n\n"); |
576 } | 560 } |
577 if (nameString != NULL) free(nameString); | 561 if (nameString != NULL) free(nameString); |
578 if (klassString != NULL) free(klassString); | 562 if (klassString != NULL) free(klassString); |
579 if (signatureString != NULL) free(signatureString); | 563 if (signatureString != NULL) free(signatureString); |
580 return -1; | 564 return -1; |
597 err = ps_pread(J->P, nm + OFFSET_nmethod_deoptimize_offset, &N->deopt_beg, SZ32); | 581 err = ps_pread(J->P, nm + OFFSET_nmethod_deoptimize_offset, &N->deopt_beg, SZ32); |
598 CHECK_FAIL(err); | 582 CHECK_FAIL(err); |
599 err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32); | 583 err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32); |
600 CHECK_FAIL(err); | 584 CHECK_FAIL(err); |
601 | 585 |
602 /* Oops */ | 586 /* Metadata */ |
603 err = ps_pread(J->P, nm + OFFSET_nmethod_oops_offset, &N->oops_beg, SZ32); | 587 err = ps_pread(J->P, nm + OFFSET_nmethod_metadata_offset, &N->metadata_beg, SZ32); |
604 CHECK_FAIL(err); | 588 CHECK_FAIL(err); |
605 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->oops_end, SZ32); | 589 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->metadata_end, SZ32); |
606 CHECK_FAIL(err); | 590 CHECK_FAIL(err); |
607 | 591 |
608 /* scopes_pcs */ | 592 /* scopes_pcs */ |
609 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32); | 593 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32); |
610 CHECK_FAIL(err); | 594 CHECK_FAIL(err); |
625 N->deopt_beg); | 609 N->deopt_beg); |
626 | 610 |
627 fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n", | 611 fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n", |
628 N->orig_pc_offset); | 612 N->orig_pc_offset); |
629 | 613 |
630 fprintf(stderr, "\t nmethod_info: oops_beg: %#x, oops_end: %#x\n", | 614 fprintf(stderr, "\t nmethod_info: metadata_beg: %#x, metadata_end: %#x\n", |
631 N->oops_beg, N->oops_end); | 615 N->metadata_beg, N->metadata_end); |
632 | 616 |
633 fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n", | 617 fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n", |
634 N->scopes_data_beg, N->scopes_data_end); | 618 N->scopes_data_beg, N->scopes_data_end); |
635 | 619 |
636 fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n", | 620 fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n", |
764 int32_t stream_line = 0; | 748 int32_t stream_line = 0; |
765 int32_t err; | 749 int32_t err; |
766 | 750 |
767 if (debug > 2) { | 751 if (debug > 2) { |
768 char name[256]; | 752 char name[256]; |
769 err = name_for_methodOop(J, vf->methodOop, name, 256); | 753 err = name_for_methodPtr(J, vf->method, name, 256); |
770 CHECK_FAIL(err); | 754 CHECK_FAIL(err); |
771 fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n", | 755 fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n", |
772 name, vf->bci); | 756 name, vf->bci); |
773 } | 757 } |
774 | 758 |
775 err = read_pointer(J, vf->methodOop + OFFSET_methodOopDesc_constMethod, &constMethod); | 759 err = read_pointer(J, vf->method + OFFSET_Method_constMethod, &constMethod); |
776 CHECK_FAIL(err); | 760 CHECK_FAIL(err); |
777 | 761 |
778 vf->line = 0; | 762 vf->line = 0; |
779 err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_flags, &access_flags, sizeof(int8_t)); | 763 err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_flags, &access_flags, sizeof(int8_t)); |
780 CHECK_FAIL(err); | 764 CHECK_FAIL(err); |
781 | 765 |
782 if (!(access_flags & constMethodOopDesc_has_linenumber_table)) { | 766 if (!(access_flags & ConstMethod_has_linenumber_table)) { |
783 if (debug > 2) | 767 if (debug > 2) |
784 fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n"); | 768 fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n"); |
785 return PS_OK; | 769 return PS_OK; |
786 } | 770 } |
787 | 771 |
788 /* The line numbers are a short array of 2-tuples [start_pc, line_number]. | 772 /* The line numbers are a short array of 2-tuples [start_pc, line_number]. |
789 * Not necessarily sorted and not necessarily one-to-one. | 773 * Not necessarily sorted and not necessarily one-to-one. |
790 */ | 774 */ |
791 | 775 |
792 err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_code_size, &code_size, SZ16); | 776 err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_code_size, &code_size, SZ16); |
793 CHECK_FAIL(err); | 777 CHECK_FAIL(err); |
794 | 778 |
795 /* inlined_table_start() */ | 779 /* inlined_table_start() */ |
796 code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0; | 780 code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0; |
797 buffer = constMethod + (uint64_t) SIZE_constMethodOopDesc + (uint64_t) code_size + code_end_delta; | 781 buffer = constMethod + (uint64_t) SIZE_ConstMethod + (uint64_t) code_size + code_end_delta; |
798 | 782 |
799 if (debug > 2) { | 783 if (debug > 2) { |
800 fprintf(stderr, "\t\t line_number_from_bci: methodOop: %#llx, native: %d\n", | 784 fprintf(stderr, "\t\t line_number_from_bci: method: %#llx, native: %d\n", |
801 vf->methodOop, (access_flags & AccessFlags_NATIVE)); | 785 vf->method, (access_flags & AccessFlags_NATIVE)); |
802 fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n", | 786 fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n", |
803 buffer, (int) code_size); | 787 buffer, (int) code_size); |
804 } | 788 } |
805 | 789 |
806 while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) { | 790 while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) { |
960 } | 944 } |
961 | 945 |
962 err = scope_desc_at(N, decode_offset, vf); | 946 err = scope_desc_at(N, decode_offset, vf); |
963 CHECK_FAIL(err); | 947 CHECK_FAIL(err); |
964 | 948 |
965 if (vf->methodIdx > ((N->oops_end - N->oops_beg) / POINTER_SIZE)) { | 949 if (vf->methodIdx > ((N->metadata_end - N->metadata_beg) / POINTER_SIZE)) { |
966 fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops length) !\n"); | 950 fprintf(stderr, "\t scopeDesc_chain: (methodIdx > metadata length) !\n"); |
967 return -1; | 951 return -1; |
968 } | 952 } |
969 err = read_pointer(N->J, N->nm + N->oops_beg + (vf->methodIdx-1)*POINTER_SIZE, | 953 err = read_pointer(N->J, N->nm + N->metadata_beg + (vf->methodIdx-1)*POINTER_SIZE, |
970 &vf->methodOop); | 954 &vf->method); |
971 CHECK_FAIL(err); | 955 CHECK_FAIL(err); |
972 | 956 |
973 if (vf->methodOop) { | 957 if (vf->method) { |
974 N->vf_cnt++; | 958 N->vf_cnt++; |
975 err = line_number_from_bci(N->J, vf); | 959 err = line_number_from_bci(N->J, vf); |
976 CHECK_FAIL(err); | 960 CHECK_FAIL(err); |
977 if (debug > 2) { | 961 if (debug > 2) { |
978 fprintf(stderr, "\t scopeDesc_chain: methodOop: %#8llx, line: %ld\n", | 962 fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %ld\n", |
979 vf->methodOop, vf->line); | 963 vf->method, vf->line); |
980 } | 964 } |
981 } | 965 } |
982 decode_offset = vf->sender_decode_offset; | 966 decode_offset = vf->sender_decode_offset; |
983 } | 967 } |
984 if (debug > 2) { | 968 if (debug > 2) { |
996 | 980 |
997 static int | 981 static int |
998 name_for_nmethod(jvm_agent_t* J, | 982 name_for_nmethod(jvm_agent_t* J, |
999 uint64_t nm, | 983 uint64_t nm, |
1000 uint64_t pc, | 984 uint64_t pc, |
1001 uint64_t methodOop, | 985 uint64_t method, |
1002 char *result, | 986 char *result, |
1003 size_t size, | 987 size_t size, |
1004 Jframe_t *jframe | 988 Jframe_t *jframe |
1005 ) { | 989 ) { |
1006 Nmethod_t *N; | 990 Nmethod_t *N; |
1060 vf = &N->vframes[0]; | 1044 vf = &N->vframes[0]; |
1061 if (N->vf_cnt > 0) { | 1045 if (N->vf_cnt > 0) { |
1062 jframe->vf_cnt = N->vf_cnt; | 1046 jframe->vf_cnt = N->vf_cnt; |
1063 jframe->bci = vf->bci; | 1047 jframe->bci = vf->bci; |
1064 jframe->line = vf->line; | 1048 jframe->line = vf->line; |
1065 err = name_for_methodOop(J, N->vframes[0].methodOop, result+1, size-1); | 1049 err = name_for_methodPtr(J, N->vframes[0].method, result+1, size-1); |
1066 CHECK_FAIL(err); | 1050 CHECK_FAIL(err); |
1067 } else { | 1051 } else { |
1068 err = name_for_methodOop(J, methodOop, result+1, size-1); | 1052 err = name_for_methodPtr(J, method, result+1, size-1); |
1069 CHECK_FAIL(err); | 1053 CHECK_FAIL(err); |
1070 } | 1054 } |
1071 if (deoptimized) { | 1055 if (deoptimized) { |
1072 strncat(result + 1, " [deoptimized frame]; ", size-1); | 1056 strncat(result + 1, " [deoptimized frame]; ", size-1); |
1073 } else { | 1057 } else { |
1095 } | 1079 } |
1096 | 1080 |
1097 static int | 1081 static int |
1098 name_for_imethod(jvm_agent_t* J, | 1082 name_for_imethod(jvm_agent_t* J, |
1099 uint64_t bcx, | 1083 uint64_t bcx, |
1100 uint64_t methodOop, | 1084 uint64_t method, |
1101 char *result, | 1085 char *result, |
1102 size_t size, | 1086 size_t size, |
1103 Jframe_t *jframe | 1087 Jframe_t *jframe |
1104 ) { | 1088 ) { |
1105 uint64_t bci; | 1089 uint64_t bci; |
1106 uint64_t constMethod; | 1090 uint64_t constMethod; |
1107 Vframe_t vframe = {0}; | 1091 Vframe_t vframe = {0}; |
1108 Vframe_t *vf = &vframe; | 1092 Vframe_t *vf = &vframe; |
1109 int32_t err; | 1093 int32_t err; |
1110 | 1094 |
1111 err = read_pointer(J, methodOop + OFFSET_methodOopDesc_constMethod, &constMethod); | 1095 err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod); |
1112 CHECK_FAIL(err); | 1096 CHECK_FAIL(err); |
1113 | 1097 |
1114 bci = is_bci(bcx) ? bcx : bcx - (constMethod + (uint64_t) SIZE_constMethodOopDesc); | 1098 bci = is_bci(bcx) ? bcx : bcx - (constMethod + (uint64_t) SIZE_ConstMethod); |
1115 | 1099 |
1116 if (debug) | 1100 if (debug) |
1117 fprintf(stderr, "\t name_for_imethod: BEGIN: methodOop: %#llx\n", methodOop); | 1101 fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method); |
1118 | 1102 |
1119 err = name_for_methodOop(J, methodOop, result, size); | 1103 err = name_for_methodPtr(J, method, result, size); |
1120 CHECK_FAIL(err); | 1104 CHECK_FAIL(err); |
1121 if (debug) | 1105 if (debug) |
1122 fprintf(stderr, "\t name_for_imethod: method name: %s\n", result); | 1106 fprintf(stderr, "\t name_for_imethod: method name: %s\n", result); |
1123 | 1107 |
1124 if (bci > 0) { | 1108 if (bci > 0) { |
1125 vf->methodOop = methodOop; | 1109 vf->method = method; |
1126 vf->bci = bci; | 1110 vf->bci = bci; |
1127 err = line_number_from_bci(J, vf); | 1111 err = line_number_from_bci(J, vf); |
1128 CHECK_FAIL(err); | 1112 CHECK_FAIL(err); |
1129 } | 1113 } |
1130 jframe->bci = vf->bci; | 1114 jframe->bci = vf->bci; |
1159 | 1143 |
1160 err = read_pointer(J, start, &vtbl); | 1144 err = read_pointer(J, start, &vtbl); |
1161 CHECK_FAIL(err); | 1145 CHECK_FAIL(err); |
1162 | 1146 |
1163 if (vtbl == J->nmethod_vtbl) { | 1147 if (vtbl == J->nmethod_vtbl) { |
1164 uint64_t methodOop; | 1148 uint64_t method; |
1165 | 1149 |
1166 err = read_pointer(J, start + OFFSET_nmethod_method, &methodOop); | 1150 err = read_pointer(J, start + OFFSET_nmethod_method, &method); |
1167 CHECK_FAIL(err); | 1151 CHECK_FAIL(err); |
1168 | 1152 |
1169 if (debug) { | 1153 if (debug) { |
1170 fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, methodOop: %#8llx \n", | 1154 fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n", |
1171 start, pc, methodOop); | 1155 start, pc, method); |
1172 } | 1156 } |
1173 err = name_for_nmethod(J, start, pc, methodOop, result, size, jframe); | 1157 err = name_for_nmethod(J, start, pc, method, result, size, jframe); |
1174 CHECK_FAIL(err); | 1158 CHECK_FAIL(err); |
1175 } else if (vtbl == J->BufferBlob_vtbl) { | 1159 } else if (vtbl == J->BufferBlob_vtbl) { |
1176 const char * name; | 1160 const char * name; |
1177 | 1161 |
1178 err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name); | 1162 err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name); |
1182 * We need some other way to distinguish "StubRoutines" | 1166 * We need some other way to distinguish "StubRoutines" |
1183 * and regular interpreted frames. | 1167 * and regular interpreted frames. |
1184 */ | 1168 */ |
1185 if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) { | 1169 if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) { |
1186 *is_interpreted = 1; | 1170 *is_interpreted = 1; |
1187 if (is_methodOop(J, J->methodOopPtr)) { | 1171 if (is_method(J, J->methodPtr)) { |
1188 return name_for_imethod(J, J->bcx, J->methodOopPtr, result, size, jframe); | 1172 return name_for_imethod(J, J->bcx, J->methodPtr, result, size, jframe); |
1189 } | 1173 } |
1190 } | 1174 } |
1191 | 1175 |
1192 if (err == PS_OK) { | 1176 if (err == PS_OK) { |
1193 strncpy(result, name, size); | 1177 strncpy(result, name, size); |
1313 (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no); | 1297 (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no); |
1314 return -1; | 1298 return -1; |
1315 } | 1299 } |
1316 vf = N->vframes + vframe_no; | 1300 vf = N->vframes + vframe_no; |
1317 name[0] = COMP_METHOD_SIGN; | 1301 name[0] = COMP_METHOD_SIGN; |
1318 err = name_for_methodOop(J, vf->methodOop, name + 1, size); | 1302 err = name_for_methodPtr(J, vf->method, name + 1, size); |
1319 CHECK_FAIL(err); | 1303 CHECK_FAIL(err); |
1320 | 1304 |
1321 jframe->bci = vf->bci; | 1305 jframe->bci = vf->bci; |
1322 jframe->line = vf->line; | 1306 jframe->line = vf->line; |
1323 if (debug) { | 1307 if (debug) { |
1338 int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name, | 1322 int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name, |
1339 size_t size, Jframe_t *jframe) { | 1323 size_t size, Jframe_t *jframe) { |
1340 uintptr_t fp; | 1324 uintptr_t fp; |
1341 uintptr_t pc; | 1325 uintptr_t pc; |
1342 /* arguments given to read_pointer need to be worst case sized */ | 1326 /* arguments given to read_pointer need to be worst case sized */ |
1343 uint64_t methodOopPtr = 0; | 1327 uint64_t methodPtr = 0; |
1344 uint64_t sender_sp; | 1328 uint64_t sender_sp; |
1345 uint64_t bcx = 0; | 1329 uint64_t bcx = 0; |
1346 int is_interpreted = 0; | 1330 int is_interpreted = 0; |
1347 int result = PS_OK; | 1331 int result = PS_OK; |
1348 int err = PS_OK; | 1332 int err = PS_OK; |
1372 * In the pcDesc structure return pc offset is recorded for CALL instructions. | 1356 * In the pcDesc structure return pc offset is recorded for CALL instructions. |
1373 * regs[R_PC] contains a CALL instruction pc offset. | 1357 * regs[R_PC] contains a CALL instruction pc offset. |
1374 */ | 1358 */ |
1375 pc += 8; | 1359 pc += 8; |
1376 bcx = (uintptr_t) regs[R_L1]; | 1360 bcx = (uintptr_t) regs[R_L1]; |
1377 methodOopPtr = (uintptr_t) regs[R_L2]; | 1361 methodPtr = (uintptr_t) regs[R_L2]; |
1378 sender_sp = regs[R_I5]; | 1362 sender_sp = regs[R_I5]; |
1379 if (debug > 2) { | 1363 if (debug > 2) { |
1380 fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n", | 1364 fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n", |
1381 regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]); | 1365 regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]); |
1382 } | 1366 } |
1393 } | 1377 } |
1394 if (debug > 2) { | 1378 if (debug > 2) { |
1395 printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp); | 1379 printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp); |
1396 } | 1380 } |
1397 | 1381 |
1398 if (read_pointer(J, fp + OFFSET_interpreter_frame_method, &methodOopPtr) != PS_OK) { | 1382 if (read_pointer(J, fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) { |
1399 methodOopPtr = 0; | 1383 methodPtr = 0; |
1400 } | 1384 } |
1401 if (read_pointer(J, fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) { | 1385 if (read_pointer(J, fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) { |
1402 sender_sp = 0; | 1386 sender_sp = 0; |
1403 } | 1387 } |
1404 if (read_pointer(J, fp + OFFSET_interpreter_frame_bcx_offset, &bcx) != PS_OK) { | 1388 if (read_pointer(J, fp + OFFSET_interpreter_frame_bcx_offset, &bcx) != PS_OK) { |
1405 bcx = 0; | 1389 bcx = 0; |
1406 } | 1390 } |
1407 #endif /* i386 */ | 1391 #endif /* i386 */ |
1408 | 1392 |
1409 J->methodOopPtr = methodOopPtr; | 1393 J->methodPtr = methodPtr; |
1410 J->bcx = bcx; | 1394 J->bcx = bcx; |
1411 | 1395 |
1412 /* On x86 with C2 JVM: native frame may have wrong regs[R_FP] | 1396 /* On x86 with C2 JVM: native frame may have wrong regs[R_FP] |
1413 * For example: JVM_SuspendThread frame poins to the top interpreted frame. | 1397 * For example: JVM_SuspendThread frame poins to the top interpreted frame. |
1414 * If we call is_methodOop(J, methodOopPtr) before codecache_contains(J, pc) | 1398 * If we call is_method(J, methodPtr) before codecache_contains(J, pc) |
1415 * then we go over and omit both: nmethod and I2CAdapter frames. | 1399 * then we go over and omit both: nmethod and I2CAdapter frames. |
1416 * Note, that regs[R_PC] is always correct if frame defined correctly. | 1400 * Note, that regs[R_PC] is always correct if frame defined correctly. |
1417 * So it is better to call codecache_contains(J, pc) from the beginning. | 1401 * So it is better to call codecache_contains(J, pc) from the beginning. |
1418 */ | 1402 */ |
1419 #ifndef X86_COMPILER2 | 1403 #ifndef X86_COMPILER2 |
1420 if (is_methodOop(J, J->methodOopPtr)) { | 1404 if (is_method(J, J->methodPtr)) { |
1421 result = name_for_imethod(J, bcx, J->methodOopPtr, name, size, jframe); | 1405 result = name_for_imethod(J, bcx, J->methodPtr, name, size, jframe); |
1422 /* If the methodOopPtr is a method then this is highly likely to be | 1406 /* If the methodPtr is a method then this is highly likely to be |
1423 an interpreter frame */ | 1407 an interpreter frame */ |
1424 if (result >= 0) { | 1408 if (result >= 0) { |
1425 is_interpreted = 1; | 1409 is_interpreted = 1; |
1426 } | 1410 } |
1427 } else | 1411 } else |
1429 | 1413 |
1430 if (codecache_contains(J, pc)) { | 1414 if (codecache_contains(J, pc)) { |
1431 result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted); | 1415 result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted); |
1432 } | 1416 } |
1433 #ifdef X86_COMPILER2 | 1417 #ifdef X86_COMPILER2 |
1434 else if (is_methodOop(J, J->methodOopPtr)) { | 1418 else if (is_method(J, J->methodPtr)) { |
1435 result = name_for_imethod(J, bcx, J->methodOopPtr, name, size, jframe); | 1419 result = name_for_imethod(J, bcx, J->methodPtr, name, size, jframe); |
1436 /* If the methodOopPtr is a method then this is highly likely to be | 1420 /* If the methodPtr is a method then this is highly likely to be |
1437 an interpreter frame */ | 1421 an interpreter frame */ |
1438 if (result >= 0) { | 1422 if (result >= 0) { |
1439 is_interpreted = 1; | 1423 is_interpreted = 1; |
1440 } | 1424 } |
1441 } | 1425 } |