Merge pull request #1304 from slluis/mac-proxy-autoconfig
[mono.git] / tools / sgen / sgen-grep-binprot.c
index 2195f4ff3fbf5ed228850597b27bbaee2c1e5bf9..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,14 +21,24 @@ read_entry (FILE *in, void **data)
 
        if (fread (&type, 1, 1, in) != 1)
                return SGEN_PROTOCOL_EOF;
-       switch (type) {
-       case SGEN_PROTOCOL_COLLECTION: size = sizeof (SGenProtocolCollection); break;
+       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;
        case SGEN_PROTOCOL_COPY: size = sizeof (SGenProtocolCopy); break;
        case SGEN_PROTOCOL_PIN: size = sizeof (SGenProtocolPin); break;
        case SGEN_PROTOCOL_MARK: size = sizeof (SGenProtocolMark); break;
+       case SGEN_PROTOCOL_SCAN_BEGIN: size = sizeof (SGenProtocolScanBegin); break;
+       case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: size = sizeof (SGenProtocolScanVTypeBegin); break;
        case SGEN_PROTOCOL_WBARRIER: size = sizeof (SGenProtocolWBarrier); break;
        case SGEN_PROTOCOL_GLOBAL_REMSET: size = sizeof (SGenProtocolGlobalRemset); break;
        case SGEN_PROTOCOL_PTR_UPDATE: size = sizeof (SGenProtocolPtrUpdate); break;
@@ -36,23 +49,112 @@ read_entry (FILE *in, void **data)
        case SGEN_PROTOCOL_THREAD_REGISTER: size = sizeof (SGenProtocolThreadRegister); break;
        case SGEN_PROTOCOL_THREAD_UNREGISTER: size = sizeof (SGenProtocolThreadUnregister); break;
        case SGEN_PROTOCOL_MISSING_REMSET: size = sizeof (SGenProtocolMissingRemset); break;
+       case SGEN_PROTOCOL_CARD_SCAN: size = sizeof (SGenProtocolCardScan); break;
+       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);
        }
 
-       *data = malloc (size);
-       if (fread (*data, size, 1, in) != 1)
-               assert (0);
+       if (size) {
+               *data = malloc (size);
+               if (fread (*data, size, 1, in) != 1)
+                       assert (0);
+       } else {
+               *data = NULL;
+       }
 
        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) {
-       case SGEN_PROTOCOL_COLLECTION: {
+       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);
+               break;
+       }
+       case SGEN_PROTOCOL_COLLECTION_END: {
                SGenProtocolCollection *entry = data;
-               printf ("collection %d generation %d\n", entry->index, entry->generation);
+               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: {
@@ -85,6 +187,16 @@ print_entry (int type, void *data)
                printf ("mark obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
                break;
        }
+       case SGEN_PROTOCOL_SCAN_BEGIN: {
+               SGenProtocolScanBegin *entry = data;
+               printf ("scan_begin obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
+               break;
+       }
+       case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: {
+               SGenProtocolScanVTypeBegin *entry = data;
+               printf ("scan_vtype_begin obj %p size %d\n", entry->obj, entry->size);
+               break;
+       }
        case SGEN_PROTOCOL_WBARRIER: {
                SGenProtocolWBarrier *entry = data;
                printf ("wbarrier ptr %p value %p value_vtable %p\n", entry->ptr, entry->value, entry->value_vtable);
@@ -137,6 +249,63 @@ print_entry (int type, void *data)
                                entry->obj, entry->obj_vtable, entry->offset, entry->value, entry->value_vtable, entry->value_pinned);
                break;
        }
+       case SGEN_PROTOCOL_CARD_SCAN: {
+               SGenProtocolCardScan *entry = data;
+               printf ("card_scan start %p size %d\n", entry->start, entry->size);
+               break;
+       }
+       case SGEN_PROTOCOL_CEMENT: {
+               SGenProtocolCement *entry = data;
+               printf ("cement obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
+               break;
+       }
+       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 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);
        }
@@ -151,13 +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:
-       case SGEN_PROTOCOL_THREAD_SUSPEND:
-       case SGEN_PROTOCOL_THREAD_RESTART:
-       case SGEN_PROTOCOL_THREAD_REGISTER:
-       case SGEN_PROTOCOL_THREAD_UNREGISTER:
-               return TRUE;
+       switch (TYPE (type)) {
        case SGEN_PROTOCOL_ALLOC:
        case SGEN_PROTOCOL_ALLOC_PINNED:
        case SGEN_PROTOCOL_ALLOC_DEGRADED: {
@@ -176,6 +339,14 @@ is_match (gpointer ptr, int type, void *data)
                SGenProtocolMark *entry = data;
                return matches_interval (ptr, entry->obj, entry->size);
        }
+       case SGEN_PROTOCOL_SCAN_BEGIN: {
+               SGenProtocolScanBegin *entry = data;
+               return matches_interval (ptr, entry->obj, entry->size);
+       }
+       case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: {
+               SGenProtocolScanVTypeBegin *entry = data;
+               return matches_interval (ptr, entry->obj, entry->size);
+       }
        case SGEN_PROTOCOL_WBARRIER: {
                SGenProtocolWBarrier *entry = data;
                return ptr == entry->ptr || ptr == entry->value;
@@ -202,33 +373,177 @@ is_match (gpointer ptr, int type, void *data)
                SGenProtocolMissingRemset *entry = data;
                return ptr == entry->obj || ptr == entry->value || ptr == (char*)entry->obj + entry->offset;
        }
+       case SGEN_PROTOCOL_CARD_SCAN: {
+               SGenProtocolCardScan *entry = data;
+               return matches_interval (ptr, entry->start, entry->size);
+       }
+       case SGEN_PROTOCOL_CEMENT: {
+               SGenProtocolCement *entry = data;
+               return matches_interval (ptr, entry->obj, entry->size);
+       }
+       case SGEN_PROTOCOL_DISLINK_UPDATE: {
+               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);
        }