src/os/solaris/dtrace/libjvm_db.c
Print this page
*** 98,107 ****
--- 98,110 ----
#define COMP_METHOD_SIGN '*'
#define MAX_VFRAMES_CNT 256
+ // Number of code heaps in the code cache
+ #define HEAP_CNT 3
+
typedef struct vframe {
uint64_t method;
int32_t sender_decode_offset;
int32_t methodIdx;
int32_t bci;
*** 148,167 ****
uint64_t Method_vtbl;
uint64_t Use_Compressed_Oops_address;
uint64_t Universe_narrow_oop_base_address;
uint64_t Universe_narrow_oop_shift_address;
! uint64_t CodeCache_heap_address;
/* Volatiles */
uint8_t Use_Compressed_Oops;
uint64_t Universe_narrow_oop_base;
uint32_t Universe_narrow_oop_shift;
! uint64_t CodeCache_low;
! uint64_t CodeCache_high;
! uint64_t CodeCache_segmap_low;
! uint64_t CodeCache_segmap_high;
int32_t SIZE_CodeCache_log2_segment;
uint64_t methodPtr;
uint64_t bcx;
--- 151,171 ----
uint64_t Method_vtbl;
uint64_t Use_Compressed_Oops_address;
uint64_t Universe_narrow_oop_base_address;
uint64_t Universe_narrow_oop_shift_address;
! uint64_t CodeCache_heap_address[HEAP_CNT];
/* Volatiles */
uint8_t Use_Compressed_Oops;
uint64_t Universe_narrow_oop_base;
uint32_t Universe_narrow_oop_shift;
! // Code cache heaps
! uint64_t Heap_low[HEAP_CNT];
! uint64_t Heap_high[HEAP_CNT];
! uint64_t Heap_segmap_low[HEAP_CNT];
! uint64_t Heap_segmap_high[HEAP_CNT];
int32_t SIZE_CodeCache_log2_segment;
uint64_t methodPtr;
uint64_t bcx;
*** 273,284 ****
if (err != PS_OK || vmp->typeName == NULL) {
break;
}
if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) {
! if (strcmp("_heap", vmp->fieldName) == 0) {
! err = read_pointer(J, vmp->address, &J->CodeCache_heap_address);
}
} else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) {
if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
J->Universe_narrow_oop_base_address = vmp->address;
}
--- 277,293 ----
if (err != PS_OK || vmp->typeName == NULL) {
break;
}
if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) {
! // Read addresses of code cache heaps
! if (strcmp("_heap_non_method", vmp->fieldName) == 0) {
! err = read_pointer(J, vmp->address, &J->CodeCache_heap_address[0]);
! } else if (strcmp("_heap_non_profiled", vmp->fieldName) == 0) {
! err = read_pointer(J, vmp->address, &J->CodeCache_heap_address[1]);
! } else if (strcmp("_heap_profiled", vmp->fieldName) == 0) {
! err = read_pointer(J, vmp->address, &J->CodeCache_heap_address[2]);
}
} else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) {
if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
J->Universe_narrow_oop_base_address = vmp->address;
}
*** 329,401 ****
err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base);
CHECK_FAIL(err);
err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t));
CHECK_FAIL(err);
! err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
! OFFSET_VirtualSpace_low, &J->CodeCache_low);
CHECK_FAIL(err);
! err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
! OFFSET_VirtualSpace_high, &J->CodeCache_high);
CHECK_FAIL(err);
! err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap +
! OFFSET_VirtualSpace_low, &J->CodeCache_segmap_low);
CHECK_FAIL(err);
! err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap +
! OFFSET_VirtualSpace_high, &J->CodeCache_segmap_high);
CHECK_FAIL(err);
! err = ps_pread(J->P, J->CodeCache_heap_address + OFFSET_CodeHeap_log2_segment_size,
&J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment));
CHECK_FAIL(err);
return PS_OK;
fail:
return err;
}
static int codecache_contains(jvm_agent_t* J, uint64_t ptr) {
! /* make sure the code cache is up to date */
! return (J->CodeCache_low <= ptr && ptr < J->CodeCache_high);
}
! static uint64_t segment_for(jvm_agent_t* J, uint64_t p) {
! return (p - J->CodeCache_low) >> J->SIZE_CodeCache_log2_segment;
}
! static uint64_t block_at(jvm_agent_t* J, int i) {
! return J->CodeCache_low + (i << J->SIZE_CodeCache_log2_segment);
}
static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
int err;
*startp = 0;
! if (J->CodeCache_low <= ptr && ptr < J->CodeCache_high) {
int32_t used;
! uint64_t segment = segment_for(J, ptr);
! uint64_t block = J->CodeCache_segmap_low;
uint8_t tag;
err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
CHECK_FAIL(err);
if (tag == 0xff)
return PS_OK;
while (tag > 0) {
err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
CHECK_FAIL(err);
segment -= tag;
}
! block = block_at(J, segment);
err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used));
CHECK_FAIL(err);
if (used) {
*startp = block + SIZE_HeapBlockHeader;
}
}
return PS_OK;
fail:
return -1;
}
--- 338,424 ----
err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base);
CHECK_FAIL(err);
err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t));
CHECK_FAIL(err);
! /* Read code heap information */
! int i;
! for (i = 0; i < HEAP_CNT; ++i) {
! err = read_pointer(J, J->CodeCache_heap_address[i] + OFFSET_CodeHeap_memory +
! OFFSET_VirtualSpace_low, &J->Heap_low[i]);
CHECK_FAIL(err);
! err = read_pointer(J, J->CodeCache_heap_address[i] + OFFSET_CodeHeap_memory +
! OFFSET_VirtualSpace_high, &J->Heap_low[i]);
CHECK_FAIL(err);
! err = read_pointer(J, J->CodeCache_heap_address[i] + OFFSET_CodeHeap_segmap +
! OFFSET_VirtualSpace_low, &J->Heap_segmap_low[i]);
CHECK_FAIL(err);
! err = read_pointer(J, J->CodeCache_heap_address[i] + OFFSET_CodeHeap_segmap +
! OFFSET_VirtualSpace_high, &J->Heap_segmap_high[i]);
CHECK_FAIL(err);
+ }
! err = ps_pread(J->P, J->CodeCache_heap_address[0] + OFFSET_CodeHeap_log2_segment_size,
&J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment));
CHECK_FAIL(err);
return PS_OK;
fail:
return err;
}
+ static int codeheap_contains(int heap_num, jvm_agent_t* J, uint64_t ptr) {
+ return (J->Heap_low[heap_num] <= ptr && ptr < J->Heap_high[heap_num]);
+ }
static int codecache_contains(jvm_agent_t* J, uint64_t ptr) {
! int i;
! for (i = 0; i < HEAP_CNT; ++i) {
! if (codeheap_contains(i, J, ptr)) {
! return 1;
! }
! }
! return 0;
}
! static uint64_t segment_for(int heap_num, jvm_agent_t* J, uint64_t p) {
! return (p - J->Heap_low[heap_num]) >> J->SIZE_CodeCache_log2_segment;
}
! static uint64_t block_at(int heap_num, jvm_agent_t* J, int i) {
! return J->Heap_low[heap_num] + (i << J->SIZE_CodeCache_log2_segment);
}
static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
int err;
+ for (int i = 0; i < HEAP_CNT; ++i) {
*startp = 0;
! if (codeheap_contains(i, J, ptr)) {
int32_t used;
! uint64_t segment = segment_for(i, J, ptr);
! uint64_t block = J->Heap_segmap_low[i];
uint8_t tag;
err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
CHECK_FAIL(err);
if (tag == 0xff)
return PS_OK;
while (tag > 0) {
err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
CHECK_FAIL(err);
segment -= tag;
}
! block = block_at(i, J, segment);
err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used));
CHECK_FAIL(err);
if (used) {
*startp = block + SIZE_HeapBlockHeader;
}
}
return PS_OK;
+ }
fail:
return -1;
}