Merge pull request #1304 from slluis/mac-proxy-autoconfig
[mono.git] / tools / sgen / sgen-grep-binprot.c
index 8027b3a9879ffed6024e8b2d98490122d25927cd..ea416b7e3a33cb17ef5e3d875b9d249124ad3a4a 100644 (file)
@@ -10,6 +10,9 @@
 
 #define SGEN_PROTOCOL_EOF      255
 
+#define TYPE(t)                ((t) & 0x7f)
+#define WORKER(t)      ((t) & 0x80)
+
 static int
 read_entry (FILE *in, void **data)
 {
@@ -18,9 +21,16 @@ read_entry (FILE *in, void **data)
 
        if (fread (&type, 1, 1, in) != 1)
                return SGEN_PROTOCOL_EOF;
-       switch (type) {
+       switch (TYPE (type)) {
+       case SGEN_PROTOCOL_COLLECTION_FORCE: size = sizeof (SGenProtocolCollectionForce); break;
        case SGEN_PROTOCOL_COLLECTION_BEGIN: size = sizeof (SGenProtocolCollection); break;
        case SGEN_PROTOCOL_COLLECTION_END: size = sizeof (SGenProtocolCollection); break;
+       case SGEN_PROTOCOL_CONCURRENT_START: size = 0; break;
+       case SGEN_PROTOCOL_CONCURRENT_UPDATE_FINISH: size = 0; break;
+       case SGEN_PROTOCOL_WORLD_STOPPING: size = sizeof (SGenProtocolWorldStopping); break;
+       case SGEN_PROTOCOL_WORLD_STOPPED: size = sizeof (SGenProtocolWorldStopped); break;
+       case SGEN_PROTOCOL_WORLD_RESTARTING: size = sizeof (SGenProtocolWorldRestarting); break;
+       case SGEN_PROTOCOL_WORLD_RESTARTED: size = sizeof (SGenProtocolWorldRestarted); break;
        case SGEN_PROTOCOL_ALLOC: size = sizeof (SGenProtocolAlloc); break;
        case SGEN_PROTOCOL_ALLOC_PINNED: size = sizeof (SGenProtocolAlloc); break;
        case SGEN_PROTOCOL_ALLOC_DEGRADED: size = sizeof (SGenProtocolAlloc); break;
@@ -43,6 +53,12 @@ read_entry (FILE *in, void **data)
        case SGEN_PROTOCOL_CEMENT: size = sizeof (SGenProtocolCement); break;
        case SGEN_PROTOCOL_CEMENT_RESET: size = 0; break;
        case SGEN_PROTOCOL_DISLINK_UPDATE: size = sizeof (SGenProtocolDislinkUpdate); break;
+       case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: size = sizeof (SGenProtocolDislinkUpdateStaged); break;
+       case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: size = sizeof (SGenProtocolDislinkProcessStaged); break;
+       case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN: size = sizeof (SGenProtocolDomainUnload); break;
+       case SGEN_PROTOCOL_DOMAIN_UNLOAD_END: size = sizeof (SGenProtocolDomainUnload); break;
+       case SGEN_PROTOCOL_GRAY_ENQUEUE: size = sizeof (SGenProtocolGrayQueue); break;
+       case SGEN_PROTOCOL_GRAY_DEQUEUE: size = sizeof (SGenProtocolGrayQueue); break;
        default: assert (0);
        }
 
@@ -57,10 +73,48 @@ read_entry (FILE *in, void **data)
        return (int)type;
 }
 
+static gboolean
+is_always_match (int type)
+{
+       switch (TYPE (type)) {
+       case SGEN_PROTOCOL_COLLECTION_FORCE:
+       case SGEN_PROTOCOL_COLLECTION_BEGIN:
+       case SGEN_PROTOCOL_COLLECTION_END:
+       case SGEN_PROTOCOL_CONCURRENT_START:
+       case SGEN_PROTOCOL_CONCURRENT_UPDATE_FINISH:
+       case SGEN_PROTOCOL_WORLD_STOPPING:
+       case SGEN_PROTOCOL_WORLD_STOPPED:
+       case SGEN_PROTOCOL_WORLD_RESTARTING:
+       case SGEN_PROTOCOL_WORLD_RESTARTED:
+       case SGEN_PROTOCOL_THREAD_SUSPEND:
+       case SGEN_PROTOCOL_THREAD_RESTART:
+       case SGEN_PROTOCOL_THREAD_REGISTER:
+       case SGEN_PROTOCOL_THREAD_UNREGISTER:
+       case SGEN_PROTOCOL_CEMENT_RESET:
+       case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN:
+       case SGEN_PROTOCOL_DOMAIN_UNLOAD_END:
+       case SGEN_PROTOCOL_GRAY_ENQUEUE:
+       case SGEN_PROTOCOL_GRAY_DEQUEUE:
+               return TRUE;
+       default:
+               return FALSE;
+       }
+}
+
+#define WORKER_PREFIX(t)       (WORKER ((t)) ? "w" : " ")
+
 static void
 print_entry (int type, void *data)
 {
-       switch (type) {
+       const char *always_prefix = is_always_match (type) ? "  " : "";
+       printf ("%s%s ", WORKER_PREFIX (type), always_prefix);
+
+       switch (TYPE (type)) {
+       case SGEN_PROTOCOL_COLLECTION_FORCE: {
+               SGenProtocolCollectionForce *entry = data;
+               printf ("collection force generation %d\n", entry->generation);
+               break;
+       }
        case SGEN_PROTOCOL_COLLECTION_BEGIN: {
                SGenProtocolCollection *entry = data;
                printf ("collection begin %d generation %d\n", entry->index, entry->generation);
@@ -71,6 +125,38 @@ print_entry (int type, void *data)
                printf ("collection end %d generation %d\n", entry->index, entry->generation);
                break;
        }
+       case SGEN_PROTOCOL_CONCURRENT_START: {
+               printf ("concurrent start\n");
+               break;
+       }
+       case SGEN_PROTOCOL_CONCURRENT_UPDATE_FINISH: {
+               printf ("concurrent update or finish\n");
+               break;
+       }
+       case SGEN_PROTOCOL_WORLD_STOPPING: {
+               SGenProtocolWorldStopping *entry = data;
+               printf ("world stopping timestamp %lld\n", entry->timestamp);
+               break;
+       }
+       case SGEN_PROTOCOL_WORLD_STOPPED: {
+               SGenProtocolWorldStopped *entry = data;
+               long long total = entry->total_major_cards + entry->total_los_cards;
+               long long marked = entry->marked_major_cards + entry->marked_los_cards;
+               printf ("world stopped timestamp %lld total %lld marked %lld %0.2f%%\n", entry->timestamp, total, marked, 100.0 * (double) marked / (double) total);
+               break;
+       }
+       case SGEN_PROTOCOL_WORLD_RESTARTING: {
+               SGenProtocolWorldRestarting *entry = data;
+               long long total = entry->total_major_cards + entry->total_los_cards;
+               long long marked = entry->marked_major_cards + entry->marked_los_cards;
+               printf ("world restarting generation %d timestamp %lld total %lld marked %lld %0.2f%%\n", entry->generation, entry->timestamp, total, marked, 100.0 * (double) marked / (double) total);
+               break;
+       }
+       case SGEN_PROTOCOL_WORLD_RESTARTED: {
+               SGenProtocolWorldRestarted *entry = data;
+               printf ("world restarted generation %d timestamp %lld\n", entry->generation, entry->timestamp);
+               break;
+       }
        case SGEN_PROTOCOL_ALLOC: {
                SGenProtocolAlloc *entry = data;
                printf ("alloc obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
@@ -176,15 +262,50 @@ print_entry (int type, void *data)
        case SGEN_PROTOCOL_CEMENT_RESET: {
                printf ("cement_reset\n");
                break;
+       }
        case SGEN_PROTOCOL_DISLINK_UPDATE: {
                SGenProtocolDislinkUpdate *entry = data;
-               printf ("dislink_update link %p obj %p", entry->link, entry->obj);
+               printf ("dislink_update link %p obj %p staged %d", entry->link, entry->obj, entry->staged);
+               if (entry->obj)
+                       printf (" track %d\n", entry->track);
+               else
+                       printf ("\n");
+               break;
+       }
+       case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: {
+               SGenProtocolDislinkUpdateStaged *entry = data;
+               printf ("dislink_update_staged link %p obj %p index %d", entry->link, entry->obj, entry->index);
                if (entry->obj)
                        printf (" track %d\n", entry->track);
                else
                        printf ("\n");
                break;
        }
+       case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: {
+               SGenProtocolDislinkProcessStaged *entry = data;
+               printf ("dislink_process_staged link %p obj %p index %d\n", entry->link, entry->obj, entry->index);
+               break;
+       }
+       case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN: {
+               SGenProtocolDomainUnload *entry = data;
+               printf ("dislink_unload_begin domain %p\n", entry->domain);
+               break;
+       }
+       case SGEN_PROTOCOL_DOMAIN_UNLOAD_END: {
+               SGenProtocolDomainUnload *entry = data;
+               printf ("dislink_unload_end domain %p\n", entry->domain);
+               break;
+       }
+       case SGEN_PROTOCOL_GRAY_ENQUEUE: {
+               SGenProtocolGrayQueue *entry = data;
+               printf ("enqueue queue %p cursor %p value %p\n", entry->queue, entry->cursor, entry->value);
+               break;
+       }
+       case SGEN_PROTOCOL_GRAY_DEQUEUE: {
+               SGenProtocolGrayQueue *entry = data;
+               printf ("dequeue queue %p cursor %p value %p\n", entry->queue, entry->cursor, entry->value);
+               break;
+       }
        default:
                assert (0);
        }
@@ -199,15 +320,7 @@ matches_interval (gpointer ptr, gpointer start, int size)
 static gboolean
 is_match (gpointer ptr, int type, void *data)
 {
-       switch (type) {
-       case SGEN_PROTOCOL_COLLECTION_BEGIN:
-       case SGEN_PROTOCOL_COLLECTION_END:
-       case SGEN_PROTOCOL_THREAD_SUSPEND:
-       case SGEN_PROTOCOL_THREAD_RESTART:
-       case SGEN_PROTOCOL_THREAD_REGISTER:
-       case SGEN_PROTOCOL_THREAD_UNREGISTER:
-       case SGEN_PROTOCOL_CEMENT_RESET:
-               return TRUE;
+       switch (TYPE (type)) {
        case SGEN_PROTOCOL_ALLOC:
        case SGEN_PROTOCOL_ALLOC_PINNED:
        case SGEN_PROTOCOL_ALLOC_DEGRADED: {
@@ -272,33 +385,165 @@ is_match (gpointer ptr, int type, void *data)
                SGenProtocolDislinkUpdate *entry = data;
                return ptr == entry->obj || ptr == entry->link;
        }
+       case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: {
+               SGenProtocolDislinkUpdateStaged *entry = data;
+               return ptr == entry->obj || ptr == entry->link;
+       }
+       case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: {
+               SGenProtocolDislinkProcessStaged *entry = data;
+               return ptr == entry->obj || ptr == entry->link;
+       }
+       case SGEN_PROTOCOL_GRAY_ENQUEUE: {
+               SGenProtocolGrayQueue *entry = data;
+               return ptr == entry->cursor || ptr == entry->value;
+       }
+       case SGEN_PROTOCOL_GRAY_DEQUEUE: {
+               SGenProtocolGrayQueue *entry = data;
+               return ptr == entry->cursor || ptr == entry->value;
+       }
        default:
+               if (is_always_match (type))
+                       return TRUE;
                assert (0);
        }
 }
 
+static gboolean
+is_vtable_match (gpointer ptr, int type, void *data)
+{
+       switch (TYPE (type)) {
+       case SGEN_PROTOCOL_ALLOC:
+       case SGEN_PROTOCOL_ALLOC_PINNED:
+       case SGEN_PROTOCOL_ALLOC_DEGRADED: {
+               SGenProtocolAlloc *entry = data;
+               return ptr == entry->vtable;
+       }
+       case SGEN_PROTOCOL_COPY: {
+               SGenProtocolCopy *entry = data;
+               return ptr == entry->vtable;
+       }
+       case SGEN_PROTOCOL_PIN: {
+               SGenProtocolPin *entry = data;
+               return ptr == entry->vtable;
+       }
+       case SGEN_PROTOCOL_SCAN_BEGIN: {
+               SGenProtocolScanBegin *entry = data;
+               return ptr == entry->vtable;
+       }
+       case SGEN_PROTOCOL_WBARRIER: {
+               SGenProtocolWBarrier *entry = data;
+               return ptr == entry->value_vtable;
+       }
+       case SGEN_PROTOCOL_GLOBAL_REMSET: {
+               SGenProtocolGlobalRemset *entry = data;
+               return ptr == entry->value_vtable;
+       }
+       case SGEN_PROTOCOL_PTR_UPDATE: {
+               SGenProtocolPtrUpdate *entry = data;
+               return ptr == entry->vtable;
+       }
+       case SGEN_PROTOCOL_CLEANUP: {
+               SGenProtocolCleanup *entry = data;
+               return ptr == entry->vtable;
+       }
+       case SGEN_PROTOCOL_MISSING_REMSET: {
+               SGenProtocolMissingRemset *entry = data;
+               return ptr == entry->obj_vtable || ptr == entry->value_vtable;
+       }
+       case SGEN_PROTOCOL_CEMENT: {
+               SGenProtocolCement *entry = data;
+               return ptr == entry->vtable;
+       }
+       default:
+               return FALSE;
+       }
+}
+
 int
 main (int argc, char *argv[])
 {
        int type;
        void *data;
-       int num_nums = argc - 1;
+       int num_args = argc - 1;
+       int num_nums = 0;
+       int num_vtables = 0;
        int i;
-       long nums [num_nums];
+       long nums [num_args];
+       long vtables [num_args];
+       gboolean dump_all = FALSE;
+       gboolean pause_times = FALSE;
+       gboolean pause_times_stopped = FALSE;
+       gboolean pause_times_concurrent = FALSE;
+       long long pause_times_ts = 0;
+
+       for (i = 0; i < num_args; ++i) {
+               char *arg = argv [i + 1];
+               char *next_arg = argv [i + 2];
+               if (!strcmp (arg, "--all")) {
+                       dump_all = TRUE;
+               } else if (!strcmp (arg, "--pause-times")) {
+                       pause_times = TRUE;
+               } else if (!strcmp (arg, "-v") || !strcmp (arg, "--vtable")) {
+                       vtables [num_vtables++] = strtoul (next_arg, NULL, 16);
+                       ++i;
+               } else {
+                       nums [num_nums++] = strtoul (arg, NULL, 16);
+               }
+       }
 
-       for (i = 0; i < num_nums; ++i)
-               nums [i] = strtoul (argv [i + 1], NULL, 16);
+       if (dump_all)
+               assert (!pause_times);
+       if (pause_times)
+               assert (!dump_all);
 
        while ((type = read_entry (stdin, &data)) != SGEN_PROTOCOL_EOF) {
-               gboolean match = FALSE;
-               for (i = 0; i < num_nums; ++i) {
-                       if (is_match ((gpointer) nums [i], type, data)) {
-                               match = TRUE;
+               if (pause_times) {
+                       switch (type) {
+                       case SGEN_PROTOCOL_WORLD_STOPPING: {
+                               SGenProtocolWorldStopping *entry = data;
+                               assert (!pause_times_stopped);
+                               pause_times_concurrent = FALSE;
+                               pause_times_ts = entry->timestamp;
+                               pause_times_stopped = TRUE;
                                break;
                        }
+                       case SGEN_PROTOCOL_CONCURRENT_START:
+                       case SGEN_PROTOCOL_CONCURRENT_UPDATE_FINISH:
+                               pause_times_concurrent = TRUE;
+                               break;
+                       case SGEN_PROTOCOL_WORLD_RESTARTED: {
+                               SGenProtocolWorldRestarted *entry = data;
+                               assert (pause_times_stopped);
+                               printf ("pause-time %d %d %lld %lld\n",
+                                               entry->generation,
+                                               pause_times_concurrent,
+                                               entry->timestamp - pause_times_ts,
+                                               pause_times_ts);
+                               pause_times_stopped = FALSE;
+                               break;
+                       }
+                       }
+               } else {
+                       gboolean match = num_nums == 0 ? is_match (NULL, type, data) : FALSE;
+                       for (i = 0; i < num_nums; ++i) {
+                               if (is_match ((gpointer) nums [i], type, data)) {
+                                       match = TRUE;
+                                       break;
+                               }
+                       }
+                       if (!match) {
+                               for (i = 0; i < num_vtables; ++i) {
+                                       if (is_vtable_match ((gpointer) vtables [i], type, data)) {
+                                               match = TRUE;
+                                               break;
+                                       }
+                               }
+                       }
+                       if (dump_all)
+                               printf (match ? "* " : "  ");
+                       if (match || dump_all)
+                               print_entry (type, data);
                }
-               if (match)
-                       print_entry (type, data);
                free (data);
        }