LoaderIndex loader_find_or_create(JNIEnv *env, jobject loader) { LoaderIndex index; /* See if we remembered the system loader */ if ( loader==NULL && gdata->system_loader != 0 ) { return gdata->system_loader; } if ( loader==NULL ) { env = NULL; } index = search(env, loader); if ( index == 0 ) { static LoaderInfo empty_info; LoaderInfo info; info = empty_info; if ( loader != NULL ) { HPROF_ASSERT(env!=NULL); info.globalref = newWeakGlobalReference(env, loader); info.object_index = 0; } index = table_create_entry(gdata->loader_table, NULL, 0, (void*)&info); } HPROF_ASSERT(search(env,loader)==index); /* Remember the system loader */ if ( loader==NULL && gdata->system_loader == 0 ) { gdata->system_loader = index; } return index; }
/* Allocate bytes from a Blocks area. */ void * blocks_alloc(Blocks *blocks, int nbytes) { BlockHeader *block; int pos; void *ptr; HPROF_ASSERT(blocks!=NULL); HPROF_ASSERT(nbytes>=0); if ( nbytes == 0 ) { return NULL; } block = blocks->current_block; nbytes = real_size(blocks->alignment, nbytes); if ( block == NULL || block->bytes_left < nbytes ) { add_block(blocks, nbytes); block = blocks->current_block; } pos = block->next_pos; ptr = (void*)(((char*)block)+pos); block->next_pos += nbytes; block->bytes_left -= nbytes; return ptr; }
static void search_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg) { LoaderInfo *info; SearchData *data; HPROF_ASSERT(info_ptr!=NULL); HPROF_ASSERT(arg!=NULL); info = (LoaderInfo*)info_ptr; data = (SearchData*)arg; if ( data->loader == info->globalref ) { /* Covers when looking for NULL too. */ HPROF_ASSERT(data->found==0); /* Did we find more than one? */ data->found = index; } else if ( data->env != NULL && data->loader != NULL && info->globalref != NULL ) { jobject lref; lref = newLocalReference(data->env, info->globalref); if ( lref == NULL ) { /* Object went away, free reference and entry */ free_entry(data->env, index); } else if ( isSameObject(data->env, data->loader, lref) ) { HPROF_ASSERT(data->found==0); /* Did we find more than one? */ data->found = index; } if ( lref != NULL ) { deleteLocalReference(data->env, lref); } } }
/* Primitive array data callback for FollowReferences */ static jint JNICALL cbPrimArrayData(jlong class_tag, jlong size, jlong* tag_ptr, jint element_count, jvmtiPrimitiveType element_type, const void* elements, void* user_data) { ObjectIndex object_index; RefIndex ref_index; RefIndex prev_ref_index; HPROF_ASSERT(tag_ptr!=NULL); HPROF_ASSERT(class_tag!=(jlong)0); HPROF_ASSERT((*tag_ptr)!=(jlong)0); if ( class_tag == (jlong)0 || (*tag_ptr) == (jlong)0 ) { /* We can't do anything with a class_tag==0, just skip it */ return JVMTI_VISIT_OBJECTS; } /* Assume object has been tagged, get object index */ object_index = tag_extract((*tag_ptr)); /* Save string data */ prev_ref_index = object_get_references(object_index); ref_index = reference_prim_array(prev_ref_index, element_type, elements, element_count); object_set_references(object_index, ref_index); return JVMTI_VISIT_OBJECTS; }
/* Add a new current_block to the Blocks* chain, adjust size if nbytes big. */ static void add_block(Blocks *blocks, int nbytes) { int header_size; int block_size; BlockHeader *block_header; HPROF_ASSERT(blocks!=NULL); HPROF_ASSERT(nbytes>0); header_size = real_size(blocks->alignment, sizeof(BlockHeader)); block_size = blocks->elem_size*blocks->population; if ( nbytes > block_size ) { block_size = real_size(blocks->alignment, nbytes); } block_header = (BlockHeader*)HPROF_MALLOC(block_size+header_size); block_header->next = NULL; block_header->bytes_left = block_size; block_header->next_pos = header_size; /* Link in new block */ if ( blocks->current_block != NULL ) { blocks->current_block->next = block_header; } blocks->current_block = block_header; if ( blocks->first_block == NULL ) { blocks->first_block = block_header; } }
static SiteKey* get_pkey(SiteIndex index) { void *key_ptr; int key_len; table_get_key(gdata->site_table, index, &key_ptr, &key_len); HPROF_ASSERT(key_len==sizeof(SiteKey)); HPROF_ASSERT(key_ptr!=NULL); return (SiteKey*)key_ptr; }
/* JVMTI callback function. */ static jvmtiIterationControl JNICALL stack_object(jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong thread_tag, jint depth, jmethodID method, jint slot, void *user_data) { /* Only calls to Allocate, Deallocate, RawMonitorEnter & RawMonitorExit * are allowed here (see the JVMTI Spec). */ ObjectIndex object_index; SerialNumber thread_serial_num; HPROF_ASSERT(tag_ptr!=NULL); if ( (*tag_ptr) != (jlong)0 ) { object_index = tag_extract(*tag_ptr); thread_serial_num = object_get_thread_serial_number(object_index); thread_serial_num = checkThreadSerialNumber(thread_serial_num); } else { SiteIndex site_index; site_index = site_find_or_create(find_cnum(class_tag), gdata->system_trace_index); if ( thread_tag != (jlong)0 ) { ObjectIndex thread_object_index; thread_object_index = tag_extract(thread_tag); thread_serial_num = object_get_thread_serial_number(thread_object_index); thread_serial_num = checkThreadSerialNumber(thread_serial_num); } else { thread_serial_num = gdata->unknown_thread_serial_num; } object_index = object_new(site_index, (jint)size, OBJECT_SYSTEM, thread_serial_num); /* Create and set the tag. */ *tag_ptr = tag_create(object_index); } HPROF_ASSERT(thread_serial_num!=0); HPROF_ASSERT(object_index!=0); switch ( root_kind ) { case JVMTI_HEAP_ROOT_STACK_LOCAL: io_heap_root_java_frame(object_index, thread_serial_num, depth); break; case JVMTI_HEAP_ROOT_JNI_LOCAL: io_heap_root_jni_local(object_index, thread_serial_num, depth); break; default: break; } return JVMTI_ITERATION_CONTINUE; }
static ObjectKey* get_pkey(ObjectIndex index) { void *key_ptr; int key_len; table_get_key(gdata->object_table, index, (void*)&key_ptr, &key_len); HPROF_ASSERT(key_len==(int)sizeof(ObjectKey)); HPROF_ASSERT(key_ptr!=NULL); return (ObjectKey*)key_ptr; }
static void mark_unchanged_iterator(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg) { SiteInfo *info; HPROF_ASSERT(key_ptr!=NULL); HPROF_ASSERT(key_len==sizeof(SiteKey)); info = (SiteInfo *)info_ptr; if ( info != NULL ) { info->changed = 0; } }
static void delete_globalref(JNIEnv *env, LoaderInfo *info) { jobject ref; HPROF_ASSERT(env!=NULL); HPROF_ASSERT(info!=NULL); ref = info->globalref; info->globalref = NULL; if ( ref != NULL ) { deleteWeakGlobalReference(env, ref); } info->object_index = 0; }
/* Fill in a field value, making sure the index is safe */ static void fill_in_field_value(RefIndex list, FieldInfo *fields, jvalue *fvalues, int n_fields, jint index, jvalue value, jvmtiPrimitiveType primType) { HPROF_ASSERT(fvalues != NULL); HPROF_ASSERT(n_fields > 0); HPROF_ASSERT(index < n_fields); HPROF_ASSERT(index >= 0 ); HPROF_ASSERT(fvalues[index].j==(jlong)0); verify_field(list, fields, fvalues, n_fields, index, value, primType); if (index >= 0 && index < n_fields) { fvalues[index] = value; } }
void reference_init(void) { HPROF_ASSERT(gdata->reference_table==NULL); gdata->reference_table = table_initialize("Ref", 2048, 4096, 0, (int)sizeof(RefInfo)); }
static int qsort_compare_live_bytes(const void *p_site1, const void *p_site2) { SiteIndex site1; SiteIndex site2; SiteInfo *info1; SiteInfo *info2; HPROF_ASSERT(p_site1!=NULL); HPROF_ASSERT(p_site2!=NULL); site1 = *(SiteIndex *)p_site1; site2 = *(SiteIndex *)p_site2; info1 = get_info(site1); info2 = get_info(site2); return info2->n_live_bytes - info1->n_live_bytes; }
void site_init(void) { HPROF_ASSERT(gdata->site_table==NULL); gdata->site_table = table_initialize("Site", 1024, 1024, 511, (int)sizeof(SiteInfo)); }
/* Add a instance field information to this cmap. */ static void add_inst_field_to_cmap(CmapInfo *cmap, HprofId id, HprofType ty) { int i; HPROF_ASSERT(cmap!=NULL); i = cmap->n_finfo++; if ( i+1 >= cmap->max_finfo ) { int osize; Finfo *new_finfo; osize = cmap->max_finfo; cmap->max_finfo += 12; new_finfo = (Finfo*)HPROF_MALLOC(cmap->max_finfo*(int)sizeof(Finfo)); (void)memset(new_finfo,0,cmap->max_finfo*(int)sizeof(Finfo)); if ( i == 0 ) { cmap->finfo = new_finfo; } else { (void)memcpy(new_finfo,cmap->finfo,osize*(int)sizeof(Finfo)); HPROF_FREE(cmap->finfo); cmap->finfo = new_finfo; } } cmap->finfo[i].id = id; cmap->finfo[i].ty = ty; }
SiteIndex site_find_or_create(ClassIndex cnum, TraceIndex trace_index) { SiteIndex index; static SiteKey empty_key; SiteKey key; key = empty_key; HPROF_ASSERT(cnum!=0); HPROF_ASSERT(trace_index!=0); key.cnum = cnum; key.trace_index = trace_index; index = table_find_or_create_entry(gdata->site_table, &key, (int)sizeof(key), NULL, NULL); return index; }
/* JVMTI callback function. */ static jvmtiIterationControl JNICALL reference_object(jvmtiObjectReferenceKind reference_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong referrer_tag, jint referrer_index, void *user_data) { /* Only calls to Allocate, Deallocate, RawMonitorEnter & RawMonitorExit * are allowed here (see the JVMTI Spec). */ RefIndex ref_index; RefIndex prev_ref_index; ObjectIndex referrer_object_index; ObjectIndex object_index; jlong object_tag; HPROF_ASSERT(tag_ptr!=NULL); HPROF_ASSERT(referrer_tag!=(jlong)0); if ( referrer_tag != (jlong)0 ) { referrer_object_index = tag_extract(referrer_tag); } else { return JVMTI_ITERATION_CONTINUE; } object_tag = *tag_ptr; if ( object_tag != (jlong)0 ) { object_index = tag_extract(object_tag); } else { SiteIndex site_index; site_index = site_find_or_create(find_cnum(class_tag), gdata->system_trace_index); object_index = object_new(site_index, (jint)size, OBJECT_SYSTEM, gdata->system_thread_serial_num); object_tag = tag_create(object_index); *tag_ptr = object_tag; } /* Save reference information */ prev_ref_index = object_get_references(referrer_object_index); ref_index = reference_new(prev_ref_index, reference_kind, class_tag, size, object_tag, referrer_index); object_set_references(referrer_object_index, ref_index); return JVMTI_ITERATION_CONTINUE; }
static void list_item(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg) { FrameKey key; FrameInfo *info; HPROF_ASSERT(key_ptr!=NULL); HPROF_ASSERT(key_len==sizeof(FrameKey)); HPROF_ASSERT(info_ptr!=NULL); key = *((FrameKey*)key_ptr); info = (FrameInfo*)info_ptr; debug_message( "Frame 0x%08x: method=%p, location=%d, lineno=%d(%d), status=%d \n", i, (void*)key.method, (jint)key.location, info->lineno, info->lineno_state, info->status); }
/* Get a void* elements array that was stored as the key. */ static void * get_key_elements(RefIndex index, jvmtiPrimitiveType primType, jint *nelements, jint *nbytes) { void *key; jint byteLen; HPROF_ASSERT(nelements!=NULL); HPROF_ASSERT(nbytes!=NULL); table_get_key(gdata->reference_table, index, &key, &byteLen); HPROF_ASSERT(byteLen>=0); HPROF_ASSERT(byteLen!=0?key!=NULL:key==NULL); *nbytes = byteLen; *nelements = byteLen / get_prim_size(primType); return key; }
/* Initialize a new Blocks */ Blocks * blocks_init(int alignment, int elem_size, int population) { Blocks *blocks; HPROF_ASSERT(alignment>0); HPROF_ASSERT(elem_size>0); HPROF_ASSERT(population>0); blocks = (Blocks*)HPROF_MALLOC(sizeof(Blocks)); blocks->alignment = alignment; blocks->elem_size = elem_size; blocks->population = population; blocks->first_block = NULL; blocks->current_block = NULL; return blocks; }
static void dump_instance_references(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg) { ObjectInfo *info; HPROF_ASSERT(info_ptr!=NULL); info = (ObjectInfo *)info_ptr; reference_dump_instance((JNIEnv*)arg, i, info->references); }
static void clear_references(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg) { ObjectInfo *info; HPROF_ASSERT(info_ptr!=NULL); info = (ObjectInfo *)info_ptr; info->references = 0; }
static void list_item(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg) { ObjectKey *pkey; ObjectInfo *info; HPROF_ASSERT(key_ptr!=NULL); HPROF_ASSERT(key_len!=0); HPROF_ASSERT(info_ptr!=NULL); info = (ObjectInfo*)info_ptr; pkey = (ObjectKey*)key_ptr; debug_message( "Object 0x%08x: site=0x%08x, SN=%u, " " size=%d, kind=%d, refs=0x%x, threadSN=%u\n", i, pkey->site_index, pkey->serial_num, pkey->size, pkey->kind, info->references, info->thread_serial_num); }
int string_get_len(StringIndex index) { void *key; int key_len; table_get_key(gdata->string_table, index, &key, &key_len); HPROF_ASSERT(key_len>0); return key_len-1; }
/* Get a jvalue that was stored as the key. */ static jvalue get_key_value(RefIndex index) { void *key; int len; jvalue value; static jvalue empty_value; key = NULL; table_get_key(gdata->reference_table, index, &key, &len); HPROF_ASSERT(key!=NULL); HPROF_ASSERT(len==(int)sizeof(jvalue)); if ( key != NULL ) { (void)memcpy(&value, key, (int)sizeof(jvalue)); } else { value = empty_value; } return value; }
char * string_get(StringIndex index) { void *key; int key_len; table_get_key(gdata->string_table, index, &key, &key_len); HPROF_ASSERT(key_len>0); return (char*)key; }
/* Write to a fd */ static void system_write(int fd, void *buf, int len) { int res; HPROF_ASSERT(fd>=0); res = md_write(fd, buf, len); if (res < 0 || res!=len) { system_error("write", res, errno); } }
static void collect_iterator(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg) { IterateInfo *iterate; HPROF_ASSERT(key_ptr!=NULL); HPROF_ASSERT(key_len==sizeof(SiteKey)); HPROF_ASSERT(arg!=NULL); iterate = (IterateInfo *)arg; if ( iterate->changed_only ) { SiteInfo *info; info = (SiteInfo *)info_ptr; if ( info==NULL || !info->changed ) { return; } } iterate->site_nums[iterate->count++] = i; }
static void list_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg) { LoaderInfo *info; HPROF_ASSERT(info_ptr!=NULL); info = (LoaderInfo*)info_ptr; debug_message( "Loader 0x%08x: globalref=%p, object_index=%d\n", index, (void*)info->globalref, info->object_index); }
static void list_item(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg) { SiteKey *pkey; jlong n_alloced_instances; jlong n_alloced_bytes; jlong n_live_instances; jlong n_live_bytes; HPROF_ASSERT(key_ptr!=NULL); HPROF_ASSERT(key_len==sizeof(SiteKey)); pkey = (SiteKey*)key_ptr; if ( info_ptr != NULL ) { SiteInfo *info; info = (SiteInfo *)info_ptr; n_alloced_instances = info->n_alloced_instances; n_alloced_bytes = info->n_alloced_bytes; n_live_instances = info->n_live_instances; n_live_bytes = info->n_live_bytes; } else { n_alloced_instances = 0; n_alloced_bytes = 0; n_live_instances = 0; n_live_bytes = 0; } debug_message( "Site 0x%08x: class=0x%08x, trace=0x%08x, " "Ninst=(%d,%d), Nbytes=(%d,%d), " "Nlive=(%d,%d), NliveBytes=(%d,%d)\n", i, pkey->cnum, pkey->trace_index, jlong_high(n_alloced_instances), jlong_low(n_alloced_instances), jlong_high(n_alloced_bytes), jlong_low(n_alloced_bytes), jlong_high(n_live_instances), jlong_low(n_live_instances), jlong_high(n_live_bytes), jlong_low(n_live_bytes)); }