Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/hprof/hprof_trace.c
38829 views
/*1* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* - Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* - Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* - Neither the name of Oracle nor the names of its15* contributors may be used to endorse or promote products derived16* from this software without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS19* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,20* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR22* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,23* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,24* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR25* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS28* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This source code is provided to illustrate the usage of a given feature33* or technique and has been deliberately simplified. Additional steps34* required for a production-quality application, such as security checks,35* input validation and proper error handling, might not be present in36* this sample code.37*/383940/* Trace table. */4142/*43* A trace is an optional thread serial number plus N frames.44*45* The thread serial number is added to the key only if the user asks for46* threads in traces, which will cause many more traces to be created.47* Without it all threads share the traces.48*49* This is a variable length Key, depending on the number of frames.50* The frames are FrameIndex values into the frame table.51*52* It is important that the thread serial number is used and not the53* TlsIndex, threads come and go, and TlsIndex values are re-used54* but the thread serial number is unique per thread.55*56* The cpu=times and cpu=samples dumps rely heavily on traces, the trace57* dump preceeds the cpu information and uses the trace information.58* Depending on the cpu= request, different sorts are applied to the59* traces that are dumped.60*61*/6263#include "hprof.h"6465typedef struct TraceKey {66SerialNumber thread_serial_num; /* Thread serial number */67short n_frames; /* Number of frames that follow. */68jvmtiPhase phase : 8; /* Makes some traces unique */69FrameIndex frames[1]; /* Variable length */70} TraceKey;7172typedef struct TraceInfo {73SerialNumber serial_num; /* Trace serial number */74jint num_hits; /* Number of hits this trace has */75jlong total_cost; /* Total cost associated with trace */76jlong self_cost; /* Total cost without children cost */77jint status; /* Status of dump of trace */78} TraceInfo;7980typedef struct IterateInfo {81TraceIndex* traces;82int count;83jlong grand_total_cost;84} IterateInfo;8586/* Private internal functions. */8788static TraceKey*89get_pkey(TraceIndex index)90{91void * pkey;92int key_len;9394table_get_key(gdata->trace_table, index, &pkey, &key_len);95HPROF_ASSERT(pkey!=NULL);96HPROF_ASSERT(key_len>=(int)sizeof(TraceKey));97HPROF_ASSERT(((TraceKey*)pkey)->n_frames<=1?key_len==(int)sizeof(TraceKey) :98key_len==(int)sizeof(TraceKey)+99(int)sizeof(FrameIndex)*(((TraceKey*)pkey)->n_frames-1));100return (TraceKey*)pkey;101}102103static TraceInfo *104get_info(TraceIndex index)105{106TraceInfo * info;107108info = (TraceInfo*)table_get_info(gdata->trace_table, index);109return info;110}111112static TraceIndex113find_or_create(SerialNumber thread_serial_num, jint n_frames,114FrameIndex *frames, jvmtiPhase phase, TraceKey *trace_key_buffer)115{116TraceInfo * info;117TraceKey * pkey;118int key_len;119TraceIndex index;120jboolean new_one;121static TraceKey empty_key;122123HPROF_ASSERT(frames!=NULL);124HPROF_ASSERT(trace_key_buffer!=NULL);125key_len = (int)sizeof(TraceKey);126if ( n_frames > 1 ) {127key_len += (int)((n_frames-1)*(int)sizeof(FrameIndex));128}129pkey = trace_key_buffer;130*pkey = empty_key;131pkey->thread_serial_num = (gdata->thread_in_traces ? thread_serial_num : 0);132pkey->n_frames = (short)n_frames;133pkey->phase = phase;134if ( n_frames > 0 ) {135(void)memcpy(pkey->frames, frames, (n_frames*(int)sizeof(FrameIndex)));136}137138new_one = JNI_FALSE;139index = table_find_or_create_entry(gdata->trace_table,140pkey, key_len, &new_one, NULL);141if ( new_one ) {142info = get_info(index);143info->serial_num = gdata->trace_serial_number_counter++;144}145return index;146}147148static void149list_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)150{151TraceInfo *info;152TraceKey *key;153int i;154155HPROF_ASSERT(key_ptr!=NULL);156HPROF_ASSERT(key_len>0);157HPROF_ASSERT(info_ptr!=NULL);158key = (TraceKey*)key_ptr;159info = (TraceInfo *)info_ptr;160161debug_message( "Trace 0x%08x: SN=%u, threadSN=%u, n_frames=%d, frames=(",162index,163info->serial_num,164key->thread_serial_num,165key->n_frames);166for ( i = 0 ; i < key->n_frames ; i++ ) {167debug_message( "0x%08x, ", key->frames[i]);168}169debug_message( "), traceSN=%u, num_hits=%d, self_cost=(%d,%d), "170"total_cost=(%d,%d), status=0x%08x\n",171info->serial_num,172info->num_hits,173jlong_high(info->self_cost),174jlong_low(info->self_cost),175jlong_high(info->total_cost),176jlong_low(info->total_cost),177info->status);178}179180static void181clear_cost(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg)182{183TraceInfo *info;184185HPROF_ASSERT(key_ptr!=NULL);186HPROF_ASSERT(key_len>0);187HPROF_ASSERT(info_ptr!=NULL);188info = (TraceInfo *)info_ptr;189info->num_hits = 0;190info->total_cost = 0;191info->self_cost = 0;192}193194/* Get the names for a frame in order to dump it. */195static void196get_frame_details(JNIEnv *env, FrameIndex frame_index,197SerialNumber *frame_serial_num, char **pcsig, ClassIndex *pcnum,198char **pmname, char **pmsig, char **psname, jint *plineno)199{200jmethodID method;201jlocation location;202jint lineno;203204HPROF_ASSERT(frame_index!=0);205*pmname = NULL;206*pmsig = NULL;207*pcsig = NULL;208if ( psname != NULL ) {209*psname = NULL;210}211if ( plineno != NULL ) {212*plineno = -1;213}214if ( pcnum != NULL ) {215*pcnum = 0;216}217frame_get_location(frame_index, frame_serial_num, &method, &location, &lineno);218if ( plineno != NULL ) {219*plineno = lineno;220}221WITH_LOCAL_REFS(env, 1) {222jclass klass;223224getMethodClass(method, &klass);225getClassSignature(klass, pcsig, NULL);226if ( pcnum != NULL ) {227LoaderIndex loader_index;228jobject loader;229230loader = getClassLoader(klass);231loader_index = loader_find_or_create(env, loader);232*pcnum = class_find_or_create(*pcsig, loader_index);233(void)class_new_classref(env, *pcnum, klass);234}235if ( psname != NULL ) {236getSourceFileName(klass, psname);237}238} END_WITH_LOCAL_REFS;239getMethodName(method, pmname, pmsig);240}241242/* Write out a stack trace. */243static void244output_trace(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)245{246TraceKey *key;247TraceInfo *info;248SerialNumber serial_num;249SerialNumber thread_serial_num;250jint n_frames;251JNIEnv *env;252int i;253char *phase_str;254struct FrameNames {255SerialNumber serial_num;256char * sname;257char * csig;258char * mname;259int lineno;260} *finfo;261262info = (TraceInfo*)info_ptr;263if ( info->status != 0 ) {264return;265}266267env = (JNIEnv*)arg;268269key = (TraceKey*)key_ptr;270thread_serial_num = key->thread_serial_num;271serial_num = info->serial_num;272info->status = 1;273finfo = NULL;274275n_frames = (jint)key->n_frames;276if ( n_frames > 0 ) {277finfo = (struct FrameNames *)HPROF_MALLOC(n_frames*(int)sizeof(struct FrameNames));278279/* Write frames, but save information for trace later */280for (i = 0; i < n_frames; i++) {281FrameIndex frame_index;282char *msig;283ClassIndex cnum;284285frame_index = key->frames[i];286get_frame_details(env, frame_index, &finfo[i].serial_num,287&finfo[i].csig, &cnum,288&finfo[i].mname, &msig, &finfo[i].sname, &finfo[i].lineno);289290if (frame_get_status(frame_index) == 0) {291io_write_frame(frame_index, finfo[i].serial_num,292finfo[i].mname, msig,293finfo[i].sname, class_get_serial_number(cnum),294finfo[i].lineno);295frame_set_status(frame_index, 1);296}297jvmtiDeallocate(msig);298}299}300301/* Find phase string */302if ( key->phase == JVMTI_PHASE_LIVE ) {303phase_str = NULL; /* Normal trace, no phase annotation */304} else {305phase_str = phaseString(key->phase);306}307308io_write_trace_header(serial_num, thread_serial_num, n_frames, phase_str);309310for (i = 0; i < n_frames; i++) {311io_write_trace_elem(serial_num, key->frames[i], finfo[i].serial_num,312finfo[i].csig,313finfo[i].mname, finfo[i].sname, finfo[i].lineno);314jvmtiDeallocate(finfo[i].csig);315jvmtiDeallocate(finfo[i].mname);316jvmtiDeallocate(finfo[i].sname);317}318319io_write_trace_footer(serial_num, thread_serial_num, n_frames);320321if ( finfo != NULL ) {322HPROF_FREE(finfo);323}324}325326/* Output a specific list of traces. */327static void328output_list(JNIEnv *env, TraceIndex *list, jint count)329{330rawMonitorEnter(gdata->data_access_lock); {331int i;332333for ( i = 0; i < count ; i++ ) {334TraceIndex index;335TraceInfo *info;336void * pkey;337int key_len;338339index = list[i];340table_get_key(gdata->trace_table, index, &pkey, &key_len);341info = get_info(index);342output_trace(index, pkey, key_len, info, (void*)env);343}344} rawMonitorExit(gdata->data_access_lock);345}346347static void348collect_iterator(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)349{350TraceInfo *info;351IterateInfo *iterate;352353HPROF_ASSERT(key_ptr!=NULL);354HPROF_ASSERT(key_len>0);355HPROF_ASSERT(arg!=NULL);356HPROF_ASSERT(info_ptr!=NULL);357iterate = (IterateInfo *)arg;358info = (TraceInfo *)info_ptr;359iterate->traces[iterate->count++] = index;360iterate->grand_total_cost += info->self_cost;361}362363static int364qsort_compare_cost(const void *p_trace1, const void *p_trace2)365{366TraceIndex trace1;367TraceIndex trace2;368TraceInfo * info1;369TraceInfo * info2;370371HPROF_ASSERT(p_trace1!=NULL);372HPROF_ASSERT(p_trace2!=NULL);373trace1 = *(TraceIndex *)p_trace1;374trace2 = *(TraceIndex *)p_trace2;375info1 = get_info(trace1);376info2 = get_info(trace2);377/*LINTED*/378return (int)(info2->self_cost - info1->self_cost);379}380381static int382qsort_compare_num_hits(const void *p_trace1, const void *p_trace2)383{384TraceIndex trace1;385TraceIndex trace2;386TraceInfo * info1;387TraceInfo * info2;388389HPROF_ASSERT(p_trace1!=NULL);390HPROF_ASSERT(p_trace2!=NULL);391trace1 = *(TraceIndex *)p_trace1;392trace2 = *(TraceIndex *)p_trace2;393info1 = get_info(trace1);394info2 = get_info(trace2);395return info2->num_hits - info1->num_hits;396}397398/* External interfaces. */399400void401trace_init(void)402{403gdata->trace_table = table_initialize("Trace",404256, 256, 511, (int)sizeof(TraceInfo));405}406407void408trace_list(void)409{410debug_message(411"--------------------- Trace Table ------------------------\n");412table_walk_items(gdata->trace_table, &list_item, NULL);413debug_message(414"----------------------------------------------------------\n");415}416417void418trace_cleanup(void)419{420table_cleanup(gdata->trace_table, NULL, NULL);421gdata->trace_table = NULL;422}423424SerialNumber425trace_get_serial_number(TraceIndex index)426{427TraceInfo *info;428429if ( index == 0 ) {430return 0;431}432info = get_info(index);433return info->serial_num;434}435436void437trace_increment_cost(TraceIndex index, jint num_hits, jlong self_cost, jlong total_cost)438{439TraceInfo *info;440441table_lock_enter(gdata->trace_table); {442info = get_info(index);443info->num_hits += num_hits;444info->self_cost += self_cost;445info->total_cost += total_cost;446} table_lock_exit(gdata->trace_table);447}448449TraceIndex450trace_find_or_create(SerialNumber thread_serial_num, jint n_frames, FrameIndex *frames, jvmtiFrameInfo *jframes_buffer)451{452return find_or_create(thread_serial_num, n_frames, frames, getPhase(),453(TraceKey*)jframes_buffer);454}455456/* We may need to ask for more frames than the user asked for */457static int458get_real_depth(int depth, jboolean skip_init)459{460int extra_frames;461462extra_frames = 0;463/* This is only needed if we are doing BCI */464if ( gdata->bci && depth > 0 ) {465/* Account for Java and native Tracker methods */466extra_frames = 2;467if ( skip_init ) {468/* Also allow for ignoring the java.lang.Object.<init> method */469extra_frames += 1;470}471}472return depth + extra_frames;473}474475/* Fill in FrameIndex array from jvmtiFrameInfo array, return n_frames */476static int477fill_frame_buffer(int depth, int real_depth,478int frame_count, jboolean skip_init,479jvmtiFrameInfo *jframes_buffer, FrameIndex *frames_buffer)480{481int n_frames;482jint topframe;483484/* If real_depth is 0, just return 0 */485if ( real_depth == 0 ) {486return 0;487}488489/* Assume top frame index is 0 for now */490topframe = 0;491492/* Possible top frames belong to the hprof Tracker class, remove them */493if ( gdata->bci ) {494while ( ( ( frame_count - topframe ) > 0 ) &&495( topframe < (real_depth-depth) ) &&496( tracker_method(jframes_buffer[topframe].method) ||497( skip_init498&& jframes_buffer[topframe].method==gdata->object_init_method ) )499) {500topframe++;501}502}503504/* Adjust count to match depth request */505if ( ( frame_count - topframe ) > depth ) {506frame_count = depth + topframe;507}508509/* The actual frame count we will process */510n_frames = frame_count - topframe;511if ( n_frames > 0 ) {512int i;513514for (i = 0; i < n_frames; i++) {515jmethodID method;516jlocation location;517518method = jframes_buffer[i+topframe].method;519location = jframes_buffer[i+topframe].location;520frames_buffer[i] = frame_find_or_create(method, location);521}522}523return n_frames;524}525526/* Get the trace for the supplied thread */527TraceIndex528trace_get_current(jthread thread, SerialNumber thread_serial_num,529int depth, jboolean skip_init,530FrameIndex *frames_buffer,531jvmtiFrameInfo *jframes_buffer)532{533TraceIndex index;534jint frame_count;535int real_depth;536int n_frames;537538HPROF_ASSERT(thread!=NULL);539HPROF_ASSERT(frames_buffer!=NULL);540HPROF_ASSERT(jframes_buffer!=NULL);541542/* We may need to ask for more frames than the user asked for */543real_depth = get_real_depth(depth, skip_init);544545/* Get the stack trace for this one thread */546frame_count = 0;547if ( real_depth > 0 ) {548getStackTrace(thread, jframes_buffer, real_depth, &frame_count);549}550551/* Create FrameIndex's */552n_frames = fill_frame_buffer(depth, real_depth, frame_count, skip_init,553jframes_buffer, frames_buffer);554555/* Lookup or create new TraceIndex */556index = find_or_create(thread_serial_num, n_frames, frames_buffer,557getPhase(), (TraceKey*)jframes_buffer);558return index;559}560561/* Get traces for all threads in list (traces[i]==0 if thread not running) */562void563trace_get_all_current(jint thread_count, jthread *threads,564SerialNumber *thread_serial_nums,565int depth, jboolean skip_init,566TraceIndex *traces, jboolean always_care)567{568jvmtiStackInfo *stack_info;569int nbytes;570int real_depth;571int i;572FrameIndex *frames_buffer;573TraceKey *trace_key_buffer;574jvmtiPhase phase;575576HPROF_ASSERT(threads!=NULL);577HPROF_ASSERT(thread_serial_nums!=NULL);578HPROF_ASSERT(traces!=NULL);579HPROF_ASSERT(thread_count > 0);580581/* Find out what the phase is for all these traces */582phase = getPhase();583584/* We may need to ask for more frames than the user asked for */585real_depth = get_real_depth(depth, skip_init);586587/* Get the stack traces for all the threads */588getThreadListStackTraces(thread_count, threads, real_depth, &stack_info);589590/* Allocate a frames_buffer and trace key buffer */591nbytes = (int)sizeof(FrameIndex)*real_depth;592frames_buffer = (FrameIndex*)HPROF_MALLOC(nbytes);593nbytes += (int)sizeof(TraceKey);594trace_key_buffer = (TraceKey*)HPROF_MALLOC(nbytes);595596/* Loop over the stack traces we have for these 'thread_count' threads */597for ( i = 0 ; i < thread_count ; i++ ) {598int n_frames;599600/* Assume 0 at first (no trace) */601traces[i] = 0;602603/* If thread has frames, is runnable, and isn't suspended, we care */604if ( always_care ||605( stack_info[i].frame_count > 0606&& (stack_info[i].state & JVMTI_THREAD_STATE_RUNNABLE)!=0607&& (stack_info[i].state & JVMTI_THREAD_STATE_SUSPENDED)==0608&& (stack_info[i].state & JVMTI_THREAD_STATE_INTERRUPTED)==0 )609) {610611/* Create FrameIndex's */612n_frames = fill_frame_buffer(depth, real_depth,613stack_info[i].frame_count,614skip_init,615stack_info[i].frame_buffer,616frames_buffer);617618/* Lookup or create new TraceIndex */619traces[i] = find_or_create(thread_serial_nums[i],620n_frames, frames_buffer, phase, trace_key_buffer);621}622}623624/* Make sure we free the space */625HPROF_FREE(frames_buffer);626HPROF_FREE(trace_key_buffer);627jvmtiDeallocate(stack_info);628}629630/* Increment the trace costs for all the threads (for cpu=samples) */631void632trace_increment_all_sample_costs(jint thread_count, jthread *threads,633SerialNumber *thread_serial_nums,634int depth, jboolean skip_init)635{636TraceIndex *traces;637int nbytes;638639HPROF_ASSERT(threads!=NULL);640HPROF_ASSERT(thread_serial_nums!=NULL);641HPROF_ASSERT(thread_count > 0);642HPROF_ASSERT(depth >= 0);643644if ( depth == 0 ) {645return;646}647648/* Allocate a traces array */649nbytes = (int)sizeof(TraceIndex)*thread_count;650traces = (TraceIndex*)HPROF_MALLOC(nbytes);651652/* Get all the current traces for these threads */653trace_get_all_current(thread_count, threads, thread_serial_nums,654depth, skip_init, traces, JNI_FALSE);655656/* Increment the cpu=samples cost on these traces */657table_lock_enter(gdata->trace_table); {658int i;659660for ( i = 0 ; i < thread_count ; i++ ) {661/* Each trace gets a hit and an increment of it's total cost */662if ( traces[i] != 0 ) {663TraceInfo *info;664665info = get_info(traces[i]);666info->num_hits += 1;667info->self_cost += (jlong)1;668info->total_cost += (jlong)1;669}670}671} table_lock_exit(gdata->trace_table);672673/* Free up the memory allocated */674HPROF_FREE(traces);675}676677void678trace_output_unmarked(JNIEnv *env)679{680rawMonitorEnter(gdata->data_access_lock); {681table_walk_items(gdata->trace_table, &output_trace, (void*)env);682} rawMonitorExit(gdata->data_access_lock);683}684685/* output info on the cost associated with traces */686void687trace_output_cost(JNIEnv *env, double cutoff)688{689IterateInfo iterate;690int i, trace_table_size, n_items;691double accum;692int n_entries;693694rawMonitorEnter(gdata->data_access_lock); {695696n_entries = table_element_count(gdata->trace_table);697iterate.traces = HPROF_MALLOC(n_entries*(int)sizeof(TraceIndex)+1);698iterate.count = 0;699iterate.grand_total_cost = 0;700table_walk_items(gdata->trace_table, &collect_iterator, &iterate);701702trace_table_size = iterate.count;703704/* sort all the traces according to the cost */705qsort(iterate.traces, trace_table_size, sizeof(TraceIndex),706&qsort_compare_cost);707708n_items = 0;709for (i = 0; i < trace_table_size; i++) {710TraceInfo *info;711TraceIndex trace_index;712double percent;713714trace_index = iterate.traces[i];715info = get_info(trace_index);716/* As soon as a trace with zero hits is seen, we need no others */717if (info->num_hits == 0 ) {718break;719}720percent = (double)info->self_cost / (double)iterate.grand_total_cost;721if (percent < cutoff) {722break;723}724n_items++;725}726727/* Now write all trace we might refer to. */728output_list(env, iterate.traces, n_items);729730io_write_cpu_samples_header(iterate.grand_total_cost, n_items);731732accum = 0;733734for (i = 0; i < n_items; i++) {735SerialNumber frame_serial_num;736TraceInfo *info;737TraceKey *key;738TraceIndex trace_index;739double percent;740char *csig;741char *mname;742char *msig;743744trace_index = iterate.traces[i];745info = get_info(trace_index);746key = get_pkey(trace_index);747percent = ((double)info->self_cost / (double)iterate.grand_total_cost) * 100.0;748accum += percent;749750csig = NULL;751mname = NULL;752msig = NULL;753754if (key->n_frames > 0) {755get_frame_details(env, key->frames[0], &frame_serial_num,756&csig, NULL, &mname, &msig, NULL, NULL);757}758759io_write_cpu_samples_elem(i+1, percent, accum, info->num_hits,760(jint)info->self_cost, info->serial_num,761key->n_frames, csig, mname);762763jvmtiDeallocate(csig);764jvmtiDeallocate(mname);765jvmtiDeallocate(msig);766}767768io_write_cpu_samples_footer();769770HPROF_FREE(iterate.traces);771772} rawMonitorExit(gdata->data_access_lock);773774}775776/* output the trace cost in old prof format */777void778trace_output_cost_in_prof_format(JNIEnv *env)779{780IterateInfo iterate;781int i, trace_table_size;782int n_entries;783784rawMonitorEnter(gdata->data_access_lock); {785786n_entries = table_element_count(gdata->trace_table);787iterate.traces = HPROF_MALLOC(n_entries*(int)sizeof(TraceIndex)+1);788iterate.count = 0;789iterate.grand_total_cost = 0;790table_walk_items(gdata->trace_table, &collect_iterator, &iterate);791792trace_table_size = iterate.count;793794/* sort all the traces according to the number of hits */795qsort(iterate.traces, trace_table_size, sizeof(TraceIndex),796&qsort_compare_num_hits);797798io_write_oldprof_header();799800for (i = 0; i < trace_table_size; i++) {801SerialNumber frame_serial_num;802TraceInfo *info;803TraceKey *key;804TraceIndex trace_index;805int num_frames;806int num_hits;807char *csig_callee;808char *mname_callee;809char *msig_callee;810char *csig_caller;811char *mname_caller;812char *msig_caller;813814trace_index = iterate.traces[i];815key = get_pkey(trace_index);816info = get_info(trace_index);817num_hits = info->num_hits;818819if (num_hits == 0) {820break;821}822823csig_callee = NULL;824mname_callee = NULL;825msig_callee = NULL;826csig_caller = NULL;827mname_caller = NULL;828msig_caller = NULL;829830num_frames = (int)key->n_frames;831832if (num_frames >= 1) {833get_frame_details(env, key->frames[0], &frame_serial_num,834&csig_callee, NULL,835&mname_callee, &msig_callee, NULL, NULL);836}837838if (num_frames > 1) {839get_frame_details(env, key->frames[1], &frame_serial_num,840&csig_caller, NULL,841&mname_caller, &msig_caller, NULL, NULL);842}843844io_write_oldprof_elem(info->num_hits, num_frames,845csig_callee, mname_callee, msig_callee,846csig_caller, mname_caller, msig_caller,847(int)info->total_cost);848849jvmtiDeallocate(csig_callee);850jvmtiDeallocate(mname_callee);851jvmtiDeallocate(msig_callee);852jvmtiDeallocate(csig_caller);853jvmtiDeallocate(mname_caller);854jvmtiDeallocate(msig_caller);855}856857io_write_oldprof_footer();858859HPROF_FREE(iterate.traces);860861} rawMonitorExit(gdata->data_access_lock);862}863864void865trace_clear_cost(void)866{867table_walk_items(gdata->trace_table, &clear_cost, NULL);868}869870871