2009-02-17 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / profiler / mono-profiler-logging.c
index 1f96554ebe65094ec805f08293b7cefd71a59d38..7aa8c5f6b2b31df1e5b300a3ef6aaa48b4ba3d94 100644 (file)
@@ -2564,12 +2564,6 @@ executable_file_close (ProfilerExecutableMemoryRegionData *region);
 
 static void
 profiler_executable_memory_region_destroy (ProfilerExecutableMemoryRegionData *data) {
-       if (data->file_name != NULL) {
-               g_free (data->file_name);
-       }
-       if (data->symbols != NULL) {
-               g_free (data->symbols);
-       }
        if (data->file != NULL) {
                executable_file_close (data);
                data->file = NULL;
@@ -2664,19 +2658,35 @@ append_region (ProfilerExecutableMemoryRegions *regions, gpointer *start, gpoint
        regions->next_id ++;
 }
 
+static gboolean
+regions_are_equivalent (ProfilerExecutableMemoryRegionData *region1, ProfilerExecutableMemoryRegionData *region2) {
+       if ((region1->start == region2->start) &&
+                       (region1->end == region2->end) &&
+                       (region1->file_offset == region2->file_offset) &&
+                       ! strcmp (region1->file_name, region2->file_name)) {
+               return TRUE;
+       } else {
+               return FALSE;
+       }
+}
+
+static int
+compare_regions (const void *a1, const void *a2) {
+       ProfilerExecutableMemoryRegionData *r1 = * (ProfilerExecutableMemoryRegionData**) a1;
+       ProfilerExecutableMemoryRegionData *r2 = * (ProfilerExecutableMemoryRegionData**) a2;
+       return (r1->start < r2->start)? -1 : ((r1->start > r2->start)? 1 : 0);
+}
+
 static void
 restore_old_regions (ProfilerExecutableMemoryRegions *old_regions, ProfilerExecutableMemoryRegions *new_regions) {
        int old_i;
        int new_i;
        
-       for (old_i = 0; old_i < old_regions->regions_count; old_i++) {
-               ProfilerExecutableMemoryRegionData *old_region = old_regions->regions [old_i];
-               for (new_i = 0; new_i < new_regions->regions_count; new_i++) {
-                       ProfilerExecutableMemoryRegionData *new_region = new_regions->regions [new_i];
-                       if ((old_region->start == new_region->start) &&
-                                       (old_region->end == new_region->end) &&
-                                       (old_region->file_offset == new_region->file_offset) &&
-                                       ! strcmp (old_region->file_name, new_region->file_name)) {
+       for (new_i = 0; new_i < new_regions->regions_count; new_i++) {
+               ProfilerExecutableMemoryRegionData *new_region = new_regions->regions [new_i];
+               for (old_i = 0; old_i < old_regions->regions_count; old_i++) {
+                       ProfilerExecutableMemoryRegionData *old_region = old_regions->regions [old_i];
+                       if ( regions_are_equivalent (old_region, new_region)) {
                                new_regions->regions [new_i] = old_region;
                                old_regions->regions [old_i] = new_region;
                                
@@ -2687,16 +2697,49 @@ restore_old_regions (ProfilerExecutableMemoryRegions *old_regions, ProfilerExecu
        }
 }
 
-static int
-compare_regions (const void *a1, const void *a2) {
-       ProfilerExecutableMemoryRegionData *r1 = * (ProfilerExecutableMemoryRegionData**) a1;
-       ProfilerExecutableMemoryRegionData *r2 = * (ProfilerExecutableMemoryRegionData**) a2;
-       return (r1->start < r2->start)? -1 : ((r1->start > r2->start)? 1 : 0);
+static void
+sort_regions (ProfilerExecutableMemoryRegions *regions) {
+       if (regions->regions_count > 1) {
+               int i;
+               
+               qsort (regions->regions, regions->regions_count, sizeof (ProfilerExecutableMemoryRegionData *), compare_regions);
+               
+               i = 1;
+               while (i < regions->regions_count) {
+                       ProfilerExecutableMemoryRegionData *current_region = regions->regions [i];
+                       ProfilerExecutableMemoryRegionData *previous_region = regions->regions [i - 1];
+                       
+                       if (regions_are_equivalent (previous_region, current_region)) {
+                               int j;
+                               
+                               if (! current_region->is_new) {
+                                       profiler_executable_memory_region_destroy (previous_region);
+                                       regions->regions [i - 1] = current_region;
+                               } else {
+                                       profiler_executable_memory_region_destroy (current_region);
+                               }
+                               
+                               for (j = i + 1; j < regions->regions_count; j++) {
+                                       regions->regions [j - 1] = regions->regions [j];
+                               }
+                               
+                               regions->regions_count --;
+                       } else {
+                               i++;
+                       }
+               }
+       }
 }
 
 static void
-sort_regions (ProfilerExecutableMemoryRegions *regions) {
-       qsort (regions->regions, regions->regions_count, sizeof (ProfilerExecutableMemoryRegionData *), compare_regions);
+fix_region_references (ProfilerExecutableMemoryRegions *regions) {
+       int i;
+       for (i = 0; i < regions->regions_count; i++) {
+               ProfilerExecutableMemoryRegionData *region = regions->regions [i];
+               if (region->file_region_reference != NULL) {
+                       region->file_region_reference->region = region;
+               }
+       }
 }
 
 static void
@@ -2728,7 +2771,6 @@ executable_file_open (ProfilerExecutableMemoryRegionData *region) {
                
                if (file == NULL) {
                        guint16 test = 0x0102;
-                       int file_name_length = strlen (region->file_name);
                        struct stat stat_buffer;
                        int symtab_index = 0;
                        int strtab_index = 0;
@@ -2746,12 +2788,6 @@ executable_file_open (ProfilerExecutableMemoryRegionData *region) {
                        file->next_new_file = files->new_files;
                        files->new_files = file;
                        
-                       /* Skip files whose name doesn't end in ".so" */
-                       if ((region->file_name [file_name_length - 1] != 'o') || (region->file_name [file_name_length - 2] != 's') || (region->file_name [file_name_length - 3] != '.')) {
-                               file->fd = -1;
-                               return file;
-                       }
-                       
                        file->fd = open (region->file_name, O_RDONLY);
                        if (file->fd == -1) {
                                //g_warning ("Cannot open file '%s': '%s'", region->file_name, strerror (errno));
@@ -2869,10 +2905,6 @@ executable_file_open (ProfilerExecutableMemoryRegionData *region) {
                executable_file_add_region_reference (file, region);
        }
        
-       if (file->next_new_file == NULL) {
-               file->next_new_file = files->new_files;
-               files->new_files = file;
-       }
        return file;
 }
 
@@ -2890,6 +2922,7 @@ executable_file_free (ProfilerExecutableFile* file) {
        }
        if (file->section_regions != NULL) {
                g_free (file->section_regions);
+               file->section_regions = NULL;
        }
        g_free (file);
 }
@@ -3303,8 +3336,9 @@ refresh_memory_regions (void) {
        
        LOG_WRITER_THREAD ("Refreshing memory regions...");
        scan_process_regions (new_regions);
-       restore_old_regions (old_regions, new_regions);
        sort_regions (new_regions);
+       restore_old_regions (old_regions, new_regions);
+       fix_region_references (new_regions);
        LOG_WRITER_THREAD ("Refreshed memory regions.");
        
        LOG_WRITER_THREAD ("Building symbol tables...");
@@ -5010,6 +5044,8 @@ setup_user_options (const char *arguments) {
                                } else {
                                        profiler->flags &= ~MONO_PROFILE_STATISTICAL;
                                }
+                       } else if (! (strcmp (argument, "save-allocation-caller") && strcmp (argument, "sac"))) {
+                               profiler->action_flags.save_allocation_caller = TRUE_IF_NOT_MINUS;
                        } else if (! (strcmp (argument, "save-allocation-stack") && strcmp (argument, "sas"))) {
                                profiler->action_flags.save_allocation_stack = TRUE_IF_NOT_MINUS;
                        } else if (! (strcmp (argument, "allocations-carry-id") && strcmp (argument, "aci"))) {