Now we add instrumentation to gather the dynamic counts. For the first pass we'll use a clean call to increment the counters from each block. However this approach is very slow since for each basic block execution a context switch out of the cache will occur. We'll look at other approaches next.

#include "dr_api.h"

#ifdef WINDOWS
# define DISPLAY_STRING(msg) dr_messagebox(msg)
#else
# define DISPLAY_STRING(msg) dr_printf("%s\n", msg)
#endif

typedef struct bb_counts { 
   uint64 blocks;
   uint64 total_size;
} bb_counts;

static bb_counts counts_as_built;
void *as_built_lock;

+ static bb_counts counts_dynamic;
+ void *count_lock;

static void
event_exit(void);
static dr_emit_flags_t
event_basic_block(void *drcontext, void *tag, instrlist_t *bb,
                  bool for_trace, bool translating);
+ static void
+ clean_call(uint instruction_count);

DR_EXPORT void 
dr_init(client_id_t id)
{
    /* register events */
    dr_register_exit_event(event_exit);
    dr_register_bb_event(event_basic_block);

    /* initialize lock */
    as_built_lock = dr_mutex_create();
+     count_lock = dr_mutex_create();
}

static void
event_exit(void)
{
    /* Display results - we must first snpritnf the string as on windows
 dr_printf(), dr_messagebox() and dr_fprintf() can't print floats. */
    char msg[512];
    int len;
    len = snprintf(msg, sizeof(msg)/sizeof(msg[0]),
                   "Number of blocks built : %"UINT64_FORMAT_CODE"\n"
                   "     Average size      : %5.2lf instructions\n"
+                    "Number of blocks executed  : %"UINT64_FORMAT_CODE"\n"
+                    "     Average weighted size : %5.2lf instructions\n",
                   counts_as_built.blocks,
                   counts_as_built.total_size / (double)counts_as_built.blocks,
+                    counts_dynamic.blocks,
+                    counts_dynamic.total_size / (double)counts_dynamic.blocks);
    DR_ASSERT(len > 0);
    msg[sizeof(msg)/sizeof(msg[0])-1] = '\0';
    DISPLAY_STRING(msg);

    /* free mutex */
    dr_mutex_destroy(as_built_lock);
+     dr_mutex_destroy(count_lock);
}

+ static void
+ clean_call(uint instruction_count)
+ {
+     dr_mutex_lock(count_lock);
+     counts_dynamic.blocks++;
+     counts_dynamic.total_size += instruction_count;
+     dr_mutex_unlock(count_lock);
+ }

static dr_emit_flags_t
event_basic_block(void *drcontext, void *tag, instrlist_t *bb,
                  bool for_trace, bool translating)
{
    uint num_instructions = 0;
    instr_t *instr;

    /* count the number of instructions in this block */
    for (instr = instrlist_first(bb); instr != NULL; instr = instr_get_next(instr)) {
        num_instructions++;
    }

    /* update the as-built counts */
    dr_mutex_lock(as_built_lock);
    counts_as_built.blocks++;
    counts_as_built.total_size += num_instructions;
    dr_mutex_unlock(as_built_lock);

+     /* insert clean call */
+     dr_insert_clean_call(drcontext, bb, instrlist_first(bb), clean_call, false, 1,
+                          OPND_CREATE_INT32(num_instructions));
+ 
    return DR_EMIT_DEFAULT;
}

[ prev | next ]


  DynamoRIO API version 2.0.0 --- Thu Apr 22 00:18:20 2010