Logo Search packages:      
Sourcecode: jmp version File versions  Download package

heap_dump.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <jmp.h>
#ifdef unix
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <netinet/in.h>
#endif /* unix */
#include <heap_dump.h>
#include <obj.h>
#include <cls.h>
#include <hash.h>
#include <ui.h>
#include <jthread.h>

#ifdef _WIN32
/* TODO get theese from some header instead. */
unsigned long int ntohl (unsigned long int x) {
    asm ("xchgb %b0,%h0\n\t"  
       "rorl $16,%0\n\t"      
       "xchgb %b0,%h0"        
       :"=q" (x)
       : "0" (x));
    return x;
}

unsigned short int ntohs (unsigned short int x) {
    asm ("xchgb %b0,%h0" 
       : "=q" (x)
       :  "0" (x));
    return x;
}
#endif /* _WIN32 */


/* id of last heap dump file. */
static int heap_dump_id = -1;
static hashtab* last_heap = NULL;
static char buf[256];

/* down links.. */
static down_link* last_down_link = NULL;

#ifdef JMPDEBUG
/** Method that can be used to generate binary dumps for use in 
 *  the simulator.
 */
static void generate_bin_dump (char* file_name, char* begin, char* end) {
    fprintf (stdout, "generate_bin_dump: %s\n", file_name);
    FILE* fp = fopen (file_name, "w");
    fwrite (begin, 1, end - begin, fp);
    fclose (fp);
}
#endif /* JMPDEBUG */

static int heap_jmphash_cmp (void* ol1, void* ol2) {
    object_link* o1 = (object_link*)ol1;
    object_link* o2 = (object_link*)ol2;
    if (o1->obj == o2->obj)
      return 0;
    return (int)(o1->obj) - (int)(o2->obj);
}

static size_t heap_jmphash_f (void* obj, size_t size) {
    object_link* ol = (object_link*)obj;
    return ((size_t)ol->obj) % size;
}

static int monitor_jmphash_cmp (void* mi1, void* mi2) {
    monitor_info* m1 = (monitor_info*)mi1;
    monitor_info* m2 = (monitor_info*)mi2;
    if (m1->id == m2->id)
      return 0;
    return (int)(m1->id) - (int)(m2->id);
}

static size_t monitor_jmphash_f (void* obj, size_t size) {
    monitor_info* mi = (monitor_info*)obj;
    return ((size_t)mi->id) % size;
}

static FILE* get_heap_dump_file (char* dumpdir) {
    FILE* fp;
    char buf2[256];
    snprintf (buf, 256, "%s/jmp_heap_dump_%d", 
            (dumpdir == NULL ? "./" : dumpdir), ++heap_dump_id);
    fp = fopen (buf, "w");
    snprintf (buf2, 256, _("createing heap dump file: %s"), buf);
    set_status (buf2);
    return fp;
}

static void clear_and_set_last_heap (hashtab* heap_hash) {
    if (last_heap) {
      jmphash_for_each (free, last_heap);
      jmphash_free (last_heap);
    }
    last_heap = heap_hash;
}

obj* get_object_hard (jobjectID o) {
    obj* jmpobj = get_object (o);
    if (!jmpobj) {     /* try to get object allocation.. */
      get_object_alloc (o);   
    }
    return get_object (o);
}


static void link_object (jobjectID obj, jobjectID parent, jobjectID clz, 
                   int type, jint variable, jint index, 
                   hashtab* heap_hash) {
    object_link* ol = malloc (sizeof (object_link));
    ol->obj = obj;
    ol->parent = parent;
    ol->clz = clz;
    ol->next = jmphash_search (ol, heap_hash);
    ol->type = type;
    ol->variable = variable;
    ol->index = index;
    jmphash_insert (ol, heap_hash);    
}

static void* get_pointer (char** p) {
    jobjectID oid;
    memcpy (&oid, *p, sizeof (void*));
    *p += sizeof (void*);    
    return oid;
}

static jint get_u4 (char** p) {
    jint i;
    memcpy (&i, *p, sizeof (i));
    *p += sizeof (i);
    return ntohl (i);
}

static jint get_u2 (char** p) {
    unsigned short u2;
    memcpy (&u2, *p, sizeof (u2));
    *p += sizeof (u2);
    return ntohs (u2);
}

static unsigned char get_u1 (char** p) {
    unsigned char u1;
    memcpy (&u1, *p, sizeof (u1));
    *p += sizeof (u1);
    return u1;
}

static void dump_triplet (FILE* fp, char* prefix, char** p) {
    jobjectID oid = get_pointer (p);
    JNIEnv* env = get_pointer (p);
    jint u4 = get_u4 (p);
    fprintf (fp, "%s: oid=%p, env=%p, frame#=%d\n", prefix, oid, env, u4);
}

static void dump_booleans (FILE* fp, jobjectID oid, jint size, char** p) {
    int i;
    fprintf (fp, "oid=%p[%d] => Z{", oid, size);
    for (i = 0; i < size; i++) {  
      unsigned char u1 = get_u1 (p);
      if (i > 0)
          fprintf (fp, ", ");
      fprintf (fp, "%d", u1);
    }
    fprintf (fp, "}\n");
}

static void dump_bytes (FILE* fp, jobjectID oid, jint size, char** p) {
    int i;
    fprintf (fp, "oid=%p[%d] => B{", oid, size);
    for (i = 0; i < size; i++) {  
      unsigned char u1 = get_u1 (p);
      if (i > 0)
          fprintf (fp, ", ");
      fprintf (fp, "%d", u1);
    }
    fprintf (fp, "}\n");
}

static void dump_chars (FILE* fp, jobjectID oid, jint size, char** p) {
    int i;
    fprintf (fp, "oid=%p[%d] => C{", oid, size);
    for (i = 0; i < size; i++) {  
      unsigned short u2 = get_u2 (p);
      if (i > 0)
          fprintf (fp, ", ");
      fprintf (fp, "%d", u2);
    }
    fprintf (fp, "}\n");    
}

static void dump_shorts (FILE* fp, jobjectID oid, jint size, char** p) {
    int i;
    fprintf (fp, "oid=%p[%d] => S{", oid, size);
    for (i = 0; i < size; i++) {  
      unsigned short u2 = get_u2 (p);
      if (i > 0)
          fprintf (fp, ", ");
      fprintf (fp, "%d", u2);
    }
    fprintf (fp, "}\n"); 
}

static void dump_ints (FILE* fp, jobjectID oid, jint size, char** p) {
    int i;
    fprintf (fp, "oid=%p[%d] => I{", oid, size);
    for (i = 0; i < size; i++) {  
      jint u4 = get_u4 (p);
      if (i > 0)
          fprintf (fp, ", ");
      fprintf (fp, "%d", u4);
    }
    fprintf (fp, "}\n"); 
}

static void dump_longs (FILE* fp, jobjectID oid, jint size, char** p) {
    int i;
    fprintf (fp, "oid=%p[%d] => J{", oid, size);
    for (i = 0; i < size; i++) {  
      jint u41 = get_u4 (p);
      jint u42 = get_u4 (p);
      if (i > 0)
          fprintf (fp, ", ");
      if (u42 != 0) 
          fprintf (fp, "0x%08x%08x", u42, u41);
      else
          fprintf (fp, "0x%d", u41);
    }
    fprintf (fp, "}\n"); 
}

static void dump_floats (FILE* fp, jobjectID oid, jint size, char** p) {
    int i;
    fprintf (fp, "oid=%p[%d] => F{", oid, size);
    for (i = 0; i < size; i++) {  
      jint u4 = get_u4 (p);
      if (i > 0)
          fprintf (fp, ", ");
      fprintf (fp, "%f", (float)u4);
    }
    fprintf (fp, "}\n");     
}

static void dump_doubles (FILE* fp, jobjectID oid, jint size, char** p) {
    int i;
    fprintf (fp, "oid=%p[%d] => D{", oid, size);
    for (i = 0; i < size; i++) {  
      jint u41 = get_u4 (p);
      jint u42 = get_u4 (p);
      if (i > 0)
          fprintf (fp, ", ");
      fprintf (fp, "0x%d%d", u42, u41);
    }
    fprintf (fp, "}\n");     
}

static void dump_objects (FILE* fp, jobjectID oid, jobjectID clz, 
                    jint size, char** p, hashtab* heap_hash) {
    int i;
    cls* c = get_class (clz);
    fprintf (fp, "oid=%p[%d] => %p,%s{", oid, size, clz, c ? c->name : "<unknown>");
    for (i = 0; i < size; i++) {  
      jobjectID o = get_pointer (p);
      if (i > 0)
          fprintf (fp, ", ");
      if (o)
          link_object (o, oid, clz, ARRAY, -1, i, heap_hash);
      fprintf (fp, "%p", o);
    }
    fprintf (fp, "}\n");     
}

static jobjectID get_variable (FILE* fp, char** p, field* f) {
    jobjectID o = NULL;
    fprintf (fp, "%s -> ", f->field_name);
    switch (f->type) {
    case JVMPI_NORMAL_OBJECT: {
      o = get_pointer (p);
      fprintf (fp, "L%p", o);
      break;
    }
    case JVMPI_CLASS: {
      o = get_pointer (p);
      fprintf (fp, "L[]%p", o);
      break;
    }
    case JVMPI_BOOLEAN: {
      unsigned char u1;
      u1 = get_u1 (p);
      fprintf (fp, "Z%d", u1);
      break;
    }
    case JVMPI_BYTE: {
      unsigned char u1;
      u1 = get_u1 (p);
      fprintf (fp, "B%d", u1);
      break;
    }
    case JVMPI_CHAR: {
      jshort u2;
      u2 = get_u2 (p);
      fprintf (fp, "C%d", u2);
      break;
    }
    case JVMPI_SHORT: {
      jshort u2;
      u2 = get_u2 (p);
      fprintf (fp, "S%d", u2);
      break;
    }
    case JVMPI_INT: {
      jint u4;
      u4 = get_u4 (p);
      fprintf (fp, "I%d", u4);
      break;
    }
    case JVMPI_LONG: {
      jint  u41, u42;
      u41 = get_u4 (p);
      u42 = get_u4 (p);
      fprintf (fp, "J%08x%08x", u42, u41);
      break;
    }
    case JVMPI_FLOAT: {
      jfloat u4;
      u4 = get_u4 (p);
      fprintf (fp, "F%f", u4);
      break;
    }
    case JVMPI_DOUBLE: {
      jint  u41, u42;
      u41 = get_u4 (p);
      u42 = get_u4 (p);
      fprintf (fp, "D%x%x", u42, u41);
      break;
    }
    }
    fprintf (fp, "\n");
    return o;
}

void free_monitor_info (monitor_info* mi) {
    if (mi == NULL)
      return;
    free (mi->waiting_to_enter);
    free (mi->waiting_for_notify);
    free (mi);
}

void heap_dump_0 (int dump_level,
              char *begin,
              char *end,
              jint num_traces,
              JVMPI_CallTrace *traces) {
    char type;
    jobjectID oid;
    obj* o;
    size_t c = 0;
    char *p = begin;
    
    while (p < end) {   
      type = *p++;
      oid = get_pointer (&p);
      o = get_object_hard (oid);
      c++;
    }    
    check_objects (c);
}

void heap_dump_1 (char* dumpdir,
              int dump_level,
              char* begin,
              char* end,
              jint num_traces,
              JVMPI_CallTrace *traces) {
    heap_dump_2 (dumpdir, dump_level, begin, end, num_traces, traces);
}

void heap_dump_2 (char* dumpdir,
              int dump_level,
              char* begin,
              char* end,
              jint num_traces,
              JVMPI_CallTrace* traces) {

    unsigned char type, ty;
    
    jobjectID oid, clz;
    jobject jobj;
    jint u4, i;
    JNIEnv* env;
    cls* c;
    hashtab* heap_hash;
    size_t counter = 0;
    char* p = begin;    
    size_t instances = 0;
    FILE* fp = get_heap_dump_file (dumpdir);
    
    fprintf (fp, "heap_dump: %d, %p, %p, %d, %p\n", 
           dump_level, begin, end, num_traces, traces);
    fprintf (fp, "void*; %d, u4: %d, u2: %d, u1: %d\n", 
           sizeof (void*), sizeof (jint), sizeof (unsigned short), sizeof (unsigned char));
    
    heap_hash = jmphash_new (20000, heap_jmphash_f, heap_jmphash_cmp, "heap_hash");
    while (p < end) {
      /* make the ui somewhat responsible...*/
      if ((counter++ % 100) == 0 && events_pending ()) 
          ui_iteration ();
      type = *p++;
      fprintf (fp, "**********************************\n"
             "%x: p = %p (end: %p) type: %d\n", (p - begin), p, end, type);
      fflush (fp);
      switch (type) {
      case JVMPI_GC_ROOT_UNKNOWN:
          oid = get_pointer (&p);
          get_object_hard (oid);
          fprintf (fp, "gc_root_unknown: oid=%p\n", oid);
          break;
      case JVMPI_GC_ROOT_JNI_GLOBAL:
          oid = get_pointer (&p);
          get_object_hard (oid);
          jobj = get_pointer (&p);  
          fprintf (fp, "gc_root_jni_global: oid=%p, object=%p\n", oid, jobj);
          break;
      case JVMPI_GC_ROOT_JNI_LOCAL:
          dump_triplet (fp, "gc_root_jni_local", &p);
          break;
      case JVMPI_GC_ROOT_JAVA_FRAME:
          dump_triplet (fp, "gc_root_java_frame", &p);
          break;
      case JVMPI_GC_ROOT_NATIVE_STACK:
          oid = get_pointer (&p);
          get_object_hard (oid);
          env = get_pointer (&p);
          fprintf (fp, "gc_root_native_stack: oid=%p, env=%p\n", oid, env);
          break;
      case JVMPI_GC_ROOT_STICKY_CLASS:
          oid = get_pointer (&p);
          get_object_hard (oid);
          fprintf (fp, "gc_root_sticky_class: oid=%p\n", oid);        
          break;
      case JVMPI_GC_ROOT_THREAD_BLOCK:
          oid = get_pointer (&p);
          get_object_hard (oid);
          env = get_pointer (&p);
          fprintf (fp, "gc_root_thread_block: oid=%p, env=%p\n", oid, env);
          break;
      case JVMPI_GC_ROOT_MONITOR_USED:
          oid = get_pointer (&p);
          get_object_hard (oid);
          fprintf (fp, "gc_root_monitor_used: oid=%p\n", oid);
          break;
      case JVMPI_GC_ROOT_THREAD_OBJ:
          fprintf (fp, "gc_root_thread_obj is undocumented\n");
          break;
      case JVMPI_GC_CLASS_DUMP: {
          jobjectID super, cls_loader, signers;
          jobjectID protection_domain, class_name, ifacep;
          void* reserved;
          jint instance_size;
          jshort constant_pool_size;
          cls* supercls;
          cls* iface;

          instances++;
          clz = get_pointer (&p);
          c = get_class (clz);
          if (c == NULL) {
            if (clz != NULL)
                get_class_load (clz);
            c = get_class (clz);
            if (c == NULL) {
                fprintf (stderr, "doh, bad class in heap dump... %p\n", clz);
                p = end;  /* force quit, but nicely so we can cleanup... */
                break;
            }
          }
          get_object_hard (clz);
          super = get_pointer (&p);
          supercls = get_class (super);
          cls_set_super (c, supercls);
          cls_loader = get_pointer (&p);
          signers = get_pointer (&p);
          protection_domain = get_pointer (&p);
          class_name = get_pointer (&p);
          reserved = get_pointer (&p);
          instance_size = get_u4 (&p);
          
          fprintf (fp, "class_dump: class %p (%p) => %s, %p => %s, %d\n", 
                 clz, c, c->name,  super, (supercls ? supercls->name : ""), 
                 instance_size);
          /* read the interfaces. */
          for (i = 0; i < c->n_interfaces; i++) {
            ifacep = get_pointer (&p);
            iface = get_class (ifacep);
            fprintf (fp, "\t%p => %s\n", ifacep, 
                   (iface ? iface->name : "?"));
            c->interfaces[i] = iface;
          }     

          constant_pool_size = get_u2 (&p);
          fprintf (fp, "\tconstant pool size: %d\n", constant_pool_size);
          for (i = 0; i < constant_pool_size; i++) {
            jobjectID const_pool_obj;
            jshort constant_pool_index = get_u2 (&p);
            ty = get_u1 (&p);
            const_pool_obj = get_pointer (&p);
            fprintf (fp, "\tconstant pool[%d] => %d, %p\n", i, 
                   constant_pool_index, const_pool_obj);
          }
          
          fprintf (fp, "static variables\n");
          for (i = 0; i < c->n_statics; i++) {
            jobjectID sobj = get_variable (fp, &p, &c->statics[i]);
            if (sobj) 
                link_object (sobj, clz, clz, STATIC_VARIABLE, i, -1, heap_hash);
          }
          fprintf (fp, "class done\n");
          break;
      }
      case JVMPI_GC_INSTANCE_DUMP: {
          obj* jmpobj;
          char* pe;
          cls* supercls;
          instances++;
          oid = get_pointer (&p);
          jmpobj = get_object_hard (oid);
          clz = get_pointer (&p);
          c = get_class (clz);
          if (c == NULL) {
            get_class_load (clz);
            c = get_class (clz);
            if (c == NULL)
                fprintf (stderr, "class is null for %p....\n", clz);
          }
          u4 = get_u4 (&p);
          pe = p + u4;
          fprintf (fp, "instance dump (%p): %p => %s, %d\n", 
                 oid, clz, (c ? c->name : "?"), u4);
          while (c != NULL) {
            jobjectID sobj;
            if (c->n_instances > 0) {
                fprintf (fp, "class '%s' has %d variables...\n", 
                       c->name, c->n_instances);
            }
            for (i = 0; i < c->n_instances; i++) {
                sobj = get_variable (fp, &p, &c->instances[i]);
                if (sobj)
                  link_object (sobj, oid, c->class_id, VARIABLE, i, -1, heap_hash);
            }
            supercls = cls_get_super (c);
            if (supercls == NULL) 
                get_super_class (c);
            c = cls_get_super (c);
          }
          if (p != pe) {
            fprintf (stderr, "doh, failed to read instance variables size: %d.....\n", u4);
            p = pe;
          }
          break;
      }
      case JVMPI_GC_OBJ_ARRAY_DUMP:
          instances++;
          oid = get_pointer (&p);
          get_object_hard (oid);
          u4 = get_u4 (&p);
          clz = get_pointer (&p);
          dump_objects (fp, oid, clz, u4, &p, heap_hash);
          break;
      case JVMPI_GC_PRIM_ARRAY_DUMP:
          instances++;
          oid = get_pointer (&p);
          get_object_hard (oid);
          u4 = get_u4 (&p);
          ty = get_u1 (&p);
          switch (ty) {
          case JVMPI_BOOLEAN:
            dump_booleans (fp, oid, u4, &p);
            break;
          case JVMPI_BYTE:
            dump_bytes (fp, oid, u4, &p);
            break;
          case JVMPI_CHAR:
            dump_chars (fp, oid, u4, &p);
            break;
          case JVMPI_SHORT:
            dump_shorts (fp, oid, u4, &p);
            break;
          case JVMPI_INT:
            dump_ints (fp, oid, u4, &p);
            break;
          case JVMPI_LONG:
            dump_longs (fp, oid, u4, &p);
            break;
          case JVMPI_FLOAT:
            dump_floats (fp, oid, u4, &p);
            break;
          case JVMPI_DOUBLE:
            dump_doubles (fp, oid, u4, &p);
            break;
          }
          break;
      default:
          fprintf (fp, "unknown type..."); 
          exit (-1);
      }
      fflush (fp);
    }
    fclose (fp);
    fprintf (stderr, "heap_hash has: %d entries...\n", jmphash_cardinal (heap_hash));
    clear_and_set_last_heap (heap_hash);
    check_objects (instances);
}

static down_link* down_link_object (char** p, field* f) {
    jlong u8;
    down_link* dl;
    dl = malloc (sizeof (*dl));
    dl->type = f->type;
    dl->fld = f;
    dl->next = NULL;
    
    switch (f->type) {            
    case JVMPI_NORMAL_OBJECT: 
      dl->value.o = get_pointer (p);
      break;
    case JVMPI_CLASS: 
      dl->value.o = get_pointer (p);
      break;
    case JVMPI_BOOLEAN: 
      dl->value.u1 = get_u1 (p);
      break;
    case JVMPI_BYTE: 
      dl->value.u1 = get_u1 (p);
      break;
    case JVMPI_CHAR: 
      dl->value.u2 = get_u2 (p);
      break;
    case JVMPI_SHORT: 
      dl->value.u2 = get_u2 (p);
      break;
    case JVMPI_INT: 
      dl->value.u4 = get_u4 (p);
      break;
    case JVMPI_LONG: 
      u8 = (((jlong)get_u4 (p))<<32);
      u8 |= get_u4 (p);
      dl->value.u8 = u8;
      break;
    case JVMPI_FLOAT:
      dl->value.u4 = get_u4 (p);
      break;
    case JVMPI_DOUBLE: 
      u8 = (((jlong)get_u4 (p))<<32);
      u8 |= get_u4 (p);
      dl->value.u8 = u8;
      break;
    }
    return dl;
}

/** Handle object dumps
 */
void object_dump (jint data_len, char *data) {
    jobjectID oid;
    jobjectID clz;
    jint u4;
    jint instance_size;
    unsigned char type;
    obj* jmpobj;
    char* p = data;
    jint i;

    if (!p) {
      fprintf (stderr, "object_dump: got NULL data (%p), data_len=%d\n", p, data_len);
      return;
    }

    type = *p++;
    switch (type) {     
    case JVMPI_GC_CLASS_DUMP: {
      jobjectID cls_loader, signers;
      jobjectID protection_domain, class_name, ifacep;
      void* reserved;
      cls* iface;
      cls* c = NULL, * s = NULL;
      jobjectID oc = get_pointer (&p);
      jobjectID os = get_pointer (&p);
      c = get_class (oc);
      if (os != NULL) {
          s = get_class (os);
          if (s == NULL) {
            /*fprintf (stderr, "unknown class (%p).. requesting..\n", os);*/
            get_class_load (os);
            s = get_class (os);
          }
      }
      if (c == NULL) {
          fprintf (stderr, "doh: %p => no class found...\n", oc);
      } else {
          cls_set_super (c, s);
          cls_loader = get_pointer (&p);
          signers = get_pointer (&p);
          protection_domain = get_pointer (&p);
          class_name = get_pointer (&p);
          reserved = get_pointer (&p);
          instance_size = get_u4 (&p);
          for (i = 0; i < c->n_interfaces; i++) {
            ifacep = get_pointer (&p);
            iface = get_class (ifacep);
            c->interfaces[i] = iface;
          }
      }
      break;
    } case JVMPI_GC_INSTANCE_DUMP: {
      char* pe;
      cls* supercls;
      cls* c;
      jobjectID clz;
      jint u4;
      jobjectID oid = get_pointer (&p);
      jmpobj = get_object_hard (oid);
      clz = get_pointer (&p);
      c = get_class (clz);
      if (c == NULL) {
          get_class_load (clz);
          c = get_class (clz);
          if (c == NULL)
            fprintf (stderr, "class is null for %p....\n", clz);
      }
      u4 = get_u4 (&p);
      pe = p + u4;
      free_last_down_link ();
      while (c != NULL) {
          for (i = 0; i < c->n_instances; i++) {
            down_link* dl = down_link_object (&p, &c->instances[i]);
            dl->next = last_down_link;
            last_down_link = dl;
          }
          supercls = cls_get_super (c);
          if (supercls == NULL) 
            get_super_class (c);
          c = cls_get_super (c);
      }
      if (p != pe) {
          fprintf (stderr, "doh, failed to read instance variables size: %d.....\n", u4);
          p = pe;
      }
      break;
    } case JVMPI_GC_OBJ_ARRAY_DUMP: {
      oid = get_pointer (&p);
      jmpobj = get_object_hard (oid);
      u4 = get_u4 (&p);
      clz = get_pointer (&p);
      for (i = u4 - 1; i >= 0; i--) {  
          jobjectID o = get_pointer (&p);
          if (o) {            
            down_link* dl;
            dl = malloc (sizeof (*dl));
            dl->type = JVMPI_NORMAL_OBJECT;
            dl->fld = NULL;
            dl->pos = i;
            dl->next = last_down_link;
            dl->value.o = o;
            last_down_link = dl;
          }
      }
      break;
    } case JVMPI_GC_PRIM_ARRAY_DUMP: {
      /* TODO figure out something nice to do here.. */
      int ty;
      oid = get_pointer (&p);
      jmpobj = get_object_hard (oid);
      u4 = get_u4 (&p);
      ty = get_u1 (&p);
      switch (ty) {
      case JVMPI_BOOLEAN:
          /*dump_booleans (fp, oid, u4, &p);*/
          break;
      case JVMPI_BYTE:
          /*dump_bytes (fp, oid, u4, &p);*/
          break;
      case JVMPI_CHAR: {
          down_link* dl;
          unsigned char* txt = calloc (u4 + 1, sizeof(unsigned short));
          unsigned char* otxt = txt;
          for (i = 0; i < u4; i++) {
            unsigned short u2 = get_u2 (&p);
            /* this seems to be utf-16/ucs-2, but Im not sure... */
            *txt++ = (char)(u2 & 0xff);
            *txt++ = (char)((u2 & 0xff00) >> 8);
          }
          *txt++ = '\0';
          *txt++ = '\0';
          dl = malloc (sizeof (*dl));
          dl->type = JVMPI_GC_PRIM_ARRAY_DUMP;
          dl->fld = NULL;
          dl->pos = u4;
          dl->next = last_down_link;
          dl->value.txt = otxt;
          last_down_link = dl;
          break;
      } case JVMPI_SHORT:
          /*dump_shorts (fp, oid, u4, &p);*/
          break;
      case JVMPI_INT:
          /*dump_ints (fp, oid, u4, &p);*/
          break;
      case JVMPI_LONG:
          /*dump_longs (fp, oid, u4, &p);*/
          break;
      case JVMPI_FLOAT:
          /*dump_floats (fp, oid, u4, &p);*/
          break;
      case JVMPI_DOUBLE:
          /*dump_doubles (fp, oid, u4, &p);*/
          break;
      }     
      break;
    }
    }
}


/** Get the owners of the given object at the last heap dump.
 * @param obj the object to get the owners for.
 * @return an linked list of object_link containing the owners of obj.
 */
object_link* get_owners (jobjectID obj) {
    object_link ol;
    object_link* ret;
    if (last_heap == NULL)
      return NULL;
    ol.obj = obj;
    ret = jmphash_search (&ol, last_heap);
    return ret;
}

int is_get_owners_possible () {
    return last_heap != NULL;
}

void remove_owners_information () {
    clear_and_set_last_heap (NULL);
}

down_link* get_last_down_link () {
    return last_down_link;
}

void free_last_down_link () {
    if (last_down_link != NULL) {
      down_link* dl = last_down_link;
      while (dl != NULL) {
          down_link* next = dl->next;
          if (dl->type == JVMPI_GC_PRIM_ARRAY_DUMP)
            free (dl->value.txt);
          free (dl);
          dl = next;
      }
      last_down_link = NULL;
    }
}

hashtab* monitor_dump (char* begin,
                   char* end,
                   jint num_traces,
                   JVMPI_CallTrace* traces,
                   jint* threads_status) {
    JNIEnv* owner;
    jint i;
    unsigned char type;
    char* p = begin;
    monitor_info* mi;
    hashtab* monitor_hash = jmphash_new (10, 
                               monitor_jmphash_f, 
                               monitor_jmphash_cmp, 
                               "monitor_hash");

    while (p < end) {
      type = *p++;
      mi = malloc (sizeof(*mi));
      if (mi == NULL)
          return NULL;
      switch (type) {
      case JVMPI_MONITOR_JAVA: {
          jobjectID oid = get_pointer (&p);
          obj* jmpobj = get_object_hard (oid);
          mi->name = jmpobj ? cls_get_name (obj_get_class (jmpobj)) : "<unknown>";
          mi->id = oid;
          break;
      }
      case JVMPI_MONITOR_RAW:
          mi->name = get_pointer (&p);
          mi->id = get_pointer (&p);
          break;      
      }
      owner = get_pointer (&p);
      mi->owner = get_jthread (owner);
      mi->entry_count = get_u4 (&p);
      mi->num_waiting_to_enter = get_u4 (&p);
      if (mi->num_waiting_to_enter) {
          mi->waiting_to_enter = 
            malloc (sizeof (*mi->waiting_to_enter) * mi->num_waiting_to_enter);
          for (i = 0; i < mi->num_waiting_to_enter; i++) {
            JNIEnv* waiting_thread = get_pointer (&p);
            mi->waiting_to_enter[i] = get_jthread (waiting_thread);
          }
      } else {
          mi->waiting_to_enter = NULL;
      }
      mi->num_waiting_for_notify = get_u4 (&p);
      if (mi->num_waiting_for_notify) {
          mi->waiting_for_notify = 
            malloc (sizeof (*mi->waiting_to_enter) * mi->num_waiting_for_notify);
          for (i = 0; i < mi->num_waiting_for_notify; i++) {
            JNIEnv* waiting_thread = get_pointer (&p);
            mi->waiting_for_notify[i] = get_jthread (waiting_thread);
          }
      } else {
          mi->waiting_for_notify = NULL;
      }
      jmphash_insert (mi, monitor_hash);
    }
    return monitor_hash;
}


/* Emacs Local Variables: */
/* Emacs mode:C */
/* Emacs c-indentation-style:"gnu" */
/* Emacs c-hanging-braces-alist:((brace-list-open)(brace-entry-open)(defun-open after)(substatement-open after)(block-close . c-snug-do-while)(extern-lang-open after)) */
/* Emacs c-cleanup-list:(brace-else-brace brace-elseif-brace space-before-funcall) */
/* Emacs c-basic-offset:4 */
/* Emacs End: */

Generated by  Doxygen 1.6.0   Back to index