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

object_dump.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <cls.h>
#include <hash.h>
#include <jmp.h>
#include <ui.h>
#include <method.h>
#include <arena.h>
#include <cls.h>
#include <obj.h>
#include <jthread.h>
#include <mvector.h>
#include <methodtime.h>
#include <heap_dump.h>
#include <gtkutils.h>
#include <jmp-config.h>
#include <instance_owners.h>

static char* Q = "?";
static char* SYS_INIT = "[system init]";
static char sarena[64];
static char buf[64];

static obj* last_selected_object;

enum {
    OD_CLASS,
    OD_ARENA,
    OD_IS_ARRAY,
    OD_SIZE,
    OD_TENURE,
    OD_ALLOC_CLASS,
    OD_ALLOC_METHOD,
    OD_VARIABLE,
    OD_OBJECT,
    ODN_COLUMNS
};

enum {
    OS_CLASS,
    OS_INSTANCES,
    OS_SIZE,
    OSN_COLUMNS
};

typedef struct {
    GtkWidget *window;
    GtkTreeStore *clist;
    gint       row;
    int        level;
    void      *data;
} wret;

typedef struct {
    GtkTreeStore *clist;
    gint       row;    
} col_click_info;

static gint sort_by_class_name (GtkTreeModel *model,
                        GtkTreeIter *a,
                        GtkTreeIter *b,
                        gpointer user_data) {
    obj* o1;
    obj* o2;
    cls* cp1;
    cls* cp2;
    char* cn1;
    char* cn2;

    gtk_tree_model_get (model, a, OD_OBJECT, &o1, -1);
    gtk_tree_model_get (model, b, OD_OBJECT, &o2, -1); 
    cp1 = get_class (obj_get_class_id (o1));
    cp2 = get_class (obj_get_class_id (o2));
    cn1 = cp1 ? cp1->name : Q;
    cn2 = cp2 ? cp2->name : Q;
    return (strcmp (cn1, cn2));    
}


static gint sort_by_arena (GtkTreeModel *model,
                     GtkTreeIter *a,
                     GtkTreeIter *b,
                     gpointer user_data) {
    obj* o1;
    obj* o2;
    gtk_tree_model_get (model, a, OD_OBJECT, &o1, -1);
    gtk_tree_model_get (model, b, OD_OBJECT, &o2, -1); 
    return o1->arena_id - o2->arena_id;
}

static gint sort_by_is_array (GtkTreeModel *model,
                        GtkTreeIter *a,
                        GtkTreeIter *b,
                        gpointer user_data) {
    obj* o1;
    obj* o2;
    gtk_tree_model_get (model, a, OD_OBJECT, &o1, -1);
    gtk_tree_model_get (model, b, OD_OBJECT, &o2, -1); 
    return o1->is_array - o2->is_array;
}

static gint sort_by_size (GtkTreeModel *model,
                    GtkTreeIter *a,
                    GtkTreeIter *b,
                    gpointer user_data) {
    obj* o1;
    obj* o2;
    gtk_tree_model_get (model, a, OD_OBJECT, &o1, -1);
    gtk_tree_model_get (model, b, OD_OBJECT, &o2, -1); 
    return o1->size - o2->size;
}

static gint sort_by_tenure (GtkTreeModel *model,
                      GtkTreeIter *a,
                      GtkTreeIter *b,
                      gpointer user_data) {
    obj* o1;
    obj* o2;
    gtk_tree_model_get (model, a, OD_OBJECT, &o1, -1);
    gtk_tree_model_get (model, b, OD_OBJECT, &o2, -1); 
    return obj_get_gc_level (o2) - obj_get_gc_level (o1);
}

static gint sort_by_alloc_class_and_method (GtkTreeModel *model,
                                  GtkTreeIter *a,
                                  GtkTreeIter *b,
                                  gpointer user_data) {
    cls* c1 = NULL;
    cls* c2 = NULL;
    char* cn1;
    char* cn2;
    int i;
    obj* o1;
    obj* o2;
    method* m1;
    method* m2;
    gtk_tree_model_get (model, a, OD_OBJECT, &o1, -1);
    gtk_tree_model_get (model, b, OD_OBJECT, &o2, -1); 
    m1 = o1->method;
    m2 = o2->method;
    if (m1)
      c1 = m1->owner;
    if (m2)
      c2 = m2->owner;    
    cn1 = c1 ? c1->name : Q;
    cn2 = c2 ? c2->name : Q;
    i = strcmp (cn1, cn2);
    if (i)
      return i;
    cn1 = m1 ? m1->jmpname : SYS_INIT;
    cn2 = m2 ? m2->jmpname : SYS_INIT;
    i = strcmp (cn1, cn2);
    return i;
}

static gint sort_by_variable (GtkTreeModel *model,
                        GtkTreeIter *a,
                        GtkTreeIter *b,
                        gpointer user_data) {
    char* v1;
    char* v2;
    gtk_tree_model_get (model, a, OD_VARIABLE, &v1, -1);
    gtk_tree_model_get (model, b, OD_VARIABLE, &v2, -1); 
    return strcmp (v1, v2);
}

static compr_func obj_comprs[] = { 
    sort_by_class_name,
    sort_by_arena, 
    sort_by_is_array,          /* is_array */
    sort_by_size,              /* size */
    sort_by_tenure, 
    sort_by_alloc_class_and_method,  /* alloc_class */
    sort_by_alloc_class_and_method,   /* alloc_method */
    sort_by_variable                  /* variable */
};

static void append_object (GtkTreeStore* list, GtkTreeIter* iter, GtkTreeIter* parent, 
                     obj* o, char* variable) {
    cls* c = NULL;
    arena* a = NULL;
    cls* cp = get_class (obj_get_class_id (o));

    /* titles = { "Class name", "arena", "is array", "size", "allocating class", "allocating method"};*/    
    gchar *text[ODN_COLUMNS];
    method* m = o->method;
    if (m != NULL)
      c = m->owner;
    text[OD_CLASS] = (cp ? cp->name : Q);
    a = get_arena (o->arena_id);
    if (a) {
      text[OD_ARENA] = a->arena_name;
    } else {
      snprintf (sarena, 64, "%d", o->arena_id);
      text[OD_ARENA] = sarena;
    }
    /*
    snprintf (size, 64, "%d", o->size);
    text[3] = size;
    */
    text[4] = (c ? c->name : Q);
    text[5] = (m ? m->jmpname : SYS_INIT);
    text[OD_VARIABLE] = variable;
    
    gtk_tree_store_append (list, iter, parent);
    gtk_tree_store_set (list, iter,
                  OD_CLASS, text[OD_CLASS],
                  OD_ARENA, text[1],
                  OD_IS_ARRAY, o->is_array,
                  OD_SIZE, obj_get_size (o),
                  OD_TENURE, get_current_gc_level () - obj_get_gc_level (o), 
                  OD_ALLOC_CLASS, text[4],
                  OD_ALLOC_METHOD, text[5],
                  OD_VARIABLE, text[OD_VARIABLE],
                  OD_OBJECT, o,
                  -1);
}

static void append_string (GtkTreeStore* list, GtkTreeIter* iter, GtkTreeIter* parent, 
                     unsigned char* txt, int len) {
    /* titles = { "Class name", "arena", "is array", "size", "allocating class", "allocating method"};*/    
    glong items_read;
    glong items_written;
    gchar *text[ODN_COLUMNS];
    GError* err = NULL;

    /* I'm not sure if it really is utf16, but that seems to work quite ok */
    gchar* converted_text = 
      g_utf16_to_utf8 ((gunichar2*)txt, len, &items_read, 
                   &items_written, &err);
    if (err != NULL) {
      fprintf (stderr, "Unable to convert text: %s\n", err->message);   
      g_error_free (err);
      return;
    }
    text[OD_CLASS] = converted_text;
    text[OD_ARENA] = "";
    text[OD_IS_ARRAY] = "";
    text[OD_SIZE] = "";
    text[OD_TENURE] = "";
    text[OD_ALLOC_CLASS] = "";
    text[OD_ALLOC_METHOD] = "";
    text[OD_VARIABLE] = "";

    gtk_tree_store_append (list, iter, parent);
    gtk_tree_store_set (list, iter,
                  OD_CLASS, text[OD_CLASS],
                  OD_ARENA, text[OD_ARENA],
                  OD_IS_ARRAY, 1,
                  OD_SIZE, len,
                  OD_TENURE, 0,
                  OD_ALLOC_CLASS, text[OD_ALLOC_CLASS],
                  OD_ALLOC_METHOD, text[OD_ALLOC_METHOD],
                  OD_VARIABLE, text[OD_VARIABLE],
                  OD_OBJECT, NULL,
                  -1);
    g_free (converted_text);
}

static void append_object_dump (obj* o, wret* w) {
    GtkTreeIter   iter;
    append_object (w->clist, &iter, NULL, o, "");
}

static void print_if_method (obj* o, wret* w) {
    if (o->method == (method*)w->data && 
      w->level <= obj_get_reset_level (o))
      append_object_dump (o, w);
}

static void print_if_class (obj* o, wret* w) {
    if (obj_get_class_id (o) == ((cls*)w->data)->class_id && 
      w->level <= obj_get_reset_level (o))
      append_object_dump (o, w);
}

static void sort_column_clicked (GtkWidget *treeviewcolumn, gpointer user_data, compr_func sorter[]) {
    GtkTreeView* tree;
    GtkTreeModel* clist;
    int column;
    tree = GTK_TREE_VIEW (user_data);
    clist = gtk_tree_view_get_model (tree);
    for (column = 0; ; column++) {
      if (treeviewcolumn == (GtkWidget*)gtk_tree_view_get_column (tree, column))
          break;
    }
    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (clist), column, GTK_SORT_ASCENDING);
    gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (clist), column, sorter[column], NULL, NULL);
}

static void od_column_clicked (GtkWidget *treeviewcolumn, gpointer user_data) {
    sort_column_clicked (treeviewcolumn, user_data, obj_comprs);
}

static void instance_row_changed (GtkTreeSelection *selection, gpointer data) {
    GtkTreeIter iter;
    GtkTreeModel *model;
    
    if (gtk_tree_selection_get_selected (selection, &model, &iter)) 
      gtk_tree_model_get (model, &iter, OD_OBJECT, 
                      &last_selected_object, -1);
    else 
      last_selected_object = NULL;
}

static char* get_field (down_link* dl) {
    if (dl->fld)
      return dl->fld->field_name;
    snprintf (buf, 64, "%d", dl->pos);
    return buf;
}

/** request to show all live objects by a certain class. */
static void inspect_instance (GtkObject* list) {
    if (last_selected_object != NULL) {
      GtkTreeIter iter;
      GtkTreeIter parent;
      GtkTreeModel *model;
      GtkTreeSelection *selection;
      down_link* dl;
      get_instance_info (last_selected_object);
      dl = get_last_down_link ();
      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (list));
      if (gtk_tree_selection_get_selected (selection, &model, &parent)) {
          GtkTreeStore *treestore = (GtkTreeStore*)gtk_tree_view_get_model (GTK_TREE_VIEW (list));
          remove_children (treestore, &parent);
          while (dl != NULL) {
            switch (dl->type) {
            case JVMPI_NORMAL_OBJECT: {
                obj* o = get_object (dl->value.o);
                if (o) {
                  append_object (treestore, &iter, &parent, o, get_field (dl));
                  expand_node (treestore, list, &parent);
                }
                break;
            }
            case JVMPI_CLASS: {
                obj* o = get_object (dl->value.o);
                if (o) {
                  append_object (treestore, &iter, &parent, o, get_field (dl));
                  expand_node (treestore, list, &parent);
                }
                break;
            }
            case JVMPI_BOOLEAN: 
                /*fprintf (stderr, "%s", dl->value.u1 ? _("true") : _("false"));*/
                break;
            case JVMPI_BYTE: 
                /*fprintf (stderr, "%d", dl->value.u1);*/
                break;
            case JVMPI_CHAR: 
                /*fprintf (stderr, "%d (%c)", dl->value.u2, (char)dl->value.u2);*/
                break;
            case JVMPI_SHORT: 
                /*fprintf (stderr, "%d", dl->value.u2);*/
                break;
            case JVMPI_INT: 
                /*fprintf (stderr, "%d", dl->value.u4);*/
                break;
            case JVMPI_LONG: 
                /*fprintf (stderr, "%lld", dl->value.u8);*/
                break;
            case JVMPI_FLOAT:
                /*fprintf (stderr, "%f", (float)dl->value.u4);*/
                break;
            case JVMPI_DOUBLE: 
                /*fprintf (stderr, "%f", (jdouble)dl->value.u4);*/
                break;
            case JVMPI_GC_PRIM_ARRAY_DUMP:
                append_string (treestore, &iter, &parent, dl->value.txt, dl->pos);
                expand_node (treestore, list, &parent);
            }         
            dl = dl->next;
          }
      }
      free_last_down_link ();
    }
}

struct obj_list {
    obj* data;
    struct obj_list* next;
};

struct class_statistic {
    cls* clz;
    size_t count;
    jint   byte_usage;
};

static size_t cls_statistic_jmphash_func (void* c, size_t len) {
    struct class_statistic* cs = (struct class_statistic*)c;
    return cls_jmphash_func (cs->clz, len);
}

static int cls_statistic_cmp_func (void* c1, void* c2) {
    struct class_statistic* cs1 = (struct class_statistic*)c1;
    struct class_statistic* cs2 = (struct class_statistic*)c2;
    return cls_cmp_func (cs1->clz, cs2->clz);
}

static int still_untraced (obj* o, hashtab* traced) {
    void* v = jmphash_search (o, traced);
    return (v == NULL);
}

static void update_statistics (hashtab* statistics, obj* o, 
                         struct class_statistic* total) {
    struct class_statistic* csr = NULL;
    struct class_statistic* cs = calloc (1, sizeof (*cs));
    cs->clz = obj_get_class (o);
    csr = jmphash_search (cs, statistics);
    if (csr != NULL) {
      csr->count++;
      csr->byte_usage += obj_get_size (o);
      total->count++;
      total->byte_usage += obj_get_size (o);
      free (cs);
    } else {
      cs->count = 1; 
      cs->byte_usage = obj_get_size (o);
      total->count++;
      total->byte_usage += obj_get_size (o);
      jmphash_insert (cs, statistics);
    }   
}

static void handle_object (obj* o, struct obj_list* current,
                     hashtab* traced, hashtab* statistics, 
                     struct class_statistic* total) {
    if (o != NULL) {
      if (still_untraced (o, traced)) {
          struct obj_list* ut;
                      
          /* mark for tracing */
          jmphash_insert (o, traced);
                      
          /* add it to trace list */
          ut = calloc (1, sizeof (*ut));
          ut->data = o;
          ut->next = current->next;
          current->next = ut;
                      
          update_statistics (statistics, o, total);
      }
    }

}

static void add_statistics_object (struct class_statistic* stats, GtkListStore* clist) {
    GtkTreeIter iter;
    gtk_list_store_append (clist, &iter);
    gtk_list_store_set (clist, &iter, 
                  OS_CLASS, cls_get_name (stats->clz), 
                  OS_INSTANCES, stats->count,
                  OS_SIZE, stats->byte_usage, 
                  -1);
}

static gint sort_stats_by_class_name (GtkTreeModel *model,
                              GtkTreeIter *a,
                              GtkTreeIter *b,
                              gpointer user_data) {
    char* cn1 = NULL;
    char* cn2 = NULL;
    gtk_tree_model_get (model, a, OS_CLASS, &cn1, -1);
    gtk_tree_model_get (model, b, OS_CLASS, &cn2, -1); 
    return (strcmp (cn1, cn2));    
}

static gint sort_stats_by_instances (GtkTreeModel *model,
                             GtkTreeIter *a,
                             GtkTreeIter *b,
                             gpointer user_data) {
    glong cn1;
    glong cn2;
    gtk_tree_model_get (model, a, OS_INSTANCES, &cn1, -1);
    gtk_tree_model_get (model, b, OS_INSTANCES, &cn2, -1); 
    return cn2 - cn1;
}

static gint sort_stats_by_size  (GtkTreeModel *model,
                         GtkTreeIter *a,
                         GtkTreeIter *b,
                         gpointer user_data) {
    glong cn1;
    glong cn2;
    gtk_tree_model_get (model, a, OS_SIZE, &cn1, -1);
    gtk_tree_model_get (model, b, OS_SIZE, &cn2, -1); 
    return cn2 - cn1;
}

static compr_func stats_comprs[] = { 
    sort_stats_by_class_name,
    sort_stats_by_instances, 
    sort_stats_by_size
};

static void os_column_clicked (GtkWidget *treeviewcolumn, gpointer user_data) {
    sort_column_clicked (treeviewcolumn, user_data, stats_comprs);
}


static void show_statistics_window (hashtab* statistics) {
    GtkWidget* scrolledwindow;
    GtkListStore* clist;
    GtkWidget* tree;
    GtkWidget* statistics_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (statistics_window), _("Owned object statistics"));
    scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
    gtk_container_add (GTK_CONTAINER (statistics_window), scrolledwindow);
    clist = gtk_list_store_new (OSN_COLUMNS, G_TYPE_STRING, 
                        G_TYPE_LONG, G_TYPE_LONG);
    tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (clist));
    add_column (tree, _("Class"), OS_CLASS, (gpointer)tree, os_column_clicked, 200, 0);
    add_column (tree, _("Instances"), OS_INSTANCES, (gpointer)tree, os_column_clicked, 80, 1);
    add_column (tree, _("Size"), OS_SIZE, (gpointer)tree, os_column_clicked, 80, 1);
    gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (tree), TRUE);
    gtk_container_add (GTK_CONTAINER (scrolledwindow), tree);

    jmphash_for_each_with_arg ((jmphash_iter_fa)add_statistics_object, statistics, clist);
    gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (clist), 0, GTK_SORT_ASCENDING);
    gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (clist), 0, 
                             sort_stats_by_size, NULL, NULL);
    gtk_tree_sortable_sort_column_changed (GTK_TREE_SORTABLE (clist));
    gtk_widget_set_usize (statistics_window, 600, 200);
    gtk_widget_show_all (statistics_window);
}

void free_statistics_object (void* v) {
    struct class_statistic* csr = (struct class_statistic*)v;
    free (csr);
}

static void list_all_owned_objects (GtkObject* list) {
    /* TODO: error handling... */
    if (last_selected_object != NULL) {
      down_link* dl;
      struct obj_list* untraced;  /* list of objects to trace */       
      struct class_statistic* total; /* a sum of all data */
      hashtab* statistics = 
          jmphash_new (42, cls_statistic_jmphash_func,
                   cls_statistic_cmp_func, _("statistics"));

      /* list of objects that have been traced or have been 
         marked for tracing. */
      hashtab* traced = jmphash_new (42, obj_jmphash_func, 
                               obj_cmp_func, _("traced"));

      total = calloc (1, sizeof (*total));
      total->clz = cls_new (_("Total"), _("Total"), NULL, 0, 0, NULL, 0, NULL);
      jmphash_insert (total, statistics);
      
      update_statistics (statistics, last_selected_object, total);

      /* avoid circular objects... */
      jmphash_insert (last_selected_object, traced);  
      
      untraced = calloc (1, sizeof (*untraced));
      untraced->data = last_selected_object;
      
      while (untraced != NULL) {
          struct obj_list* current = untraced;
          /* useful for debugging. */ 
          /*
          fprintf (stderr, "tracing, current = %p, %s\n", 
                 current->data, 
                 current->data ? current->data->clz->name : "<NULL>");
          */
          get_instance_info (untraced->data);
          dl = get_last_down_link ();
          while (dl != NULL) {
            switch (dl->type) {
            case JVMPI_NORMAL_OBJECT:
                /* fallthrough */
            case JVMPI_CLASS: {
                obj* o = get_object (dl->value.o);
                handle_object (o, current, traced, statistics, total);
                break;
            }
            }
            dl = dl->next;
          }
          
          untraced = untraced->next;
          free (current);
      }

      show_statistics_window (statistics);
      cls_free (total->clz);
      jmphash_for_each ((jmphash_iter_f)free_statistics_object, statistics);
      jmphash_free (statistics);
      jmphash_free (traced);
    }
}

static GtkWidget *build_menu (GtkWidget* object_list) {
    GtkWidget *omenu = gtk_menu_new ();
    GtkWidget* menuitem = gtk_menu_item_new_with_label (_("inspect instance"));
    gtk_menu_append (GTK_MENU (omenu), menuitem);
    gtk_signal_connect_object (GTK_OBJECT (menuitem), "activate",
                         GTK_SIGNAL_FUNC (inspect_instance),
                         GTK_OBJECT (object_list));
    
    menuitem = gtk_menu_item_new_with_label (_("owned object statistics"));
    gtk_menu_append (GTK_MENU (omenu), menuitem);
    gtk_signal_connect_object (GTK_OBJECT (menuitem), "activate",
                         GTK_SIGNAL_FUNC (list_all_owned_objects),
                         GTK_OBJECT (object_list));
    
    menuitem = gtk_menu_item_new_with_label (_("show owner"));
    gtk_menu_append (GTK_MENU (omenu), menuitem);
    gtk_signal_connect_object (GTK_OBJECT (menuitem), "activate",
                         GTK_SIGNAL_FUNC (show_owner),
                         obj_get_object_id (last_selected_object)); 

    gtk_widget_show_all (omenu);
    return omenu;
}

static gint instance_button_handler (GtkWidget *widget,
                             GdkEventButton *event,
                             gpointer  callback_data) {
    if (event->button == 3 && last_selected_object != NULL) {
      GtkWidget* imenu = build_menu (widget);
      gtk_menu_popup (GTK_MENU (imenu), NULL, NULL, NULL, NULL,
                        event->button, event->time);  
      return TRUE;
    }
    return FALSE;
}

wret create_object_dump_window () {
    GtkWidget *obj_dump;
    GtkWidget *scrolledwindow;
    GtkWidget *tree;
    GtkTreeStore *clist1;
    GtkTreeSelection *select;
    wret ret;

    obj_dump = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title (GTK_WINDOW (obj_dump), _("Object dump"));
    scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
    gtk_container_add (GTK_CONTAINER (obj_dump), scrolledwindow);
    clist1 = gtk_tree_store_new (ODN_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, 
                         G_TYPE_BOOLEAN, G_TYPE_LONG, G_TYPE_LONG, 
                         G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, 
                         G_TYPE_POINTER);
    tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (clist1));
    add_column (tree, _("Class"), OD_CLASS, (gpointer)tree, od_column_clicked, 200, 0);
    add_column (tree, _("Arena"), OD_ARENA, (gpointer)tree, od_column_clicked, 80, 0);
    add_column (tree, _("Is array"), OD_IS_ARRAY, (gpointer)tree, od_column_clicked, 80, 0);
    add_column (tree, _("Size"), OD_SIZE, (gpointer)tree, od_column_clicked, 80, 0);
    add_column (tree, _("Tenure"), OD_TENURE, (gpointer)tree, od_column_clicked, 80, 0);
    add_column (tree, _("Allocating class"), OD_ALLOC_CLASS, (gpointer)tree, od_column_clicked, 200, 0);
    add_column (tree, _("Allocating method"), OD_ALLOC_METHOD, (gpointer)tree, od_column_clicked, 200, 0);
    add_column (tree, _("Variable"), OD_VARIABLE, (gpointer)tree, od_column_clicked, 200, 0);
    gtk_tree_view_set_headers_clickable (GTK_TREE_VIEW (tree), TRUE);
    gtk_container_add (GTK_CONTAINER (scrolledwindow), tree);    
    select = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
    g_signal_connect (G_OBJECT (select), "changed",
                  G_CALLBACK (instance_row_changed),
                  clist1);
    gtk_signal_connect (GTK_OBJECT(tree), "button_press_event",
                  GTK_SIGNAL_FUNC (instance_button_handler), 
                  clist1);
    gtk_widget_set_usize (obj_dump, 800, 200);
    ret.window = obj_dump;
    ret.clist = clist1;
    ret.data = 0; 
    ret.level = 0;
    ret.row = 0;
    return ret;
}

void show_objects_alloced_by_method (hashtab* objects, method* m, int minimum_level) {
    wret w = create_object_dump_window ();
    w.data = m;
    w.row = 0;
    w.level = minimum_level;
    jmphash_lock (objects);
    jmphash_for_each_with_arg ((jmphash_iter_fa)print_if_method, objects, &w);
    jmphash_unlock (objects);
    gtk_widget_show_all (w.window);
}

void show_objects_alloced_by_class (hashtab* objects, cls* c, int minimum_level) {
    wret w = create_object_dump_window ();
    w.data = c;
    w.row = 0;
    w.level = minimum_level;
    jmphash_lock (objects);
    jmphash_for_each_with_arg ((jmphash_iter_fa)print_if_class, objects, &w);
    jmphash_unlock (objects);
    gtk_widget_show_all (w.window);
}

void show_object (obj* o) {
    wret w = create_object_dump_window ();
    w.data = o;
    w.row = 0;
    w.level = 0;
    append_object_dump (o, &w);    
    gtk_widget_show_all (w.window);
}

/* 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