6 #define SGEN_BINARY_PROTOCOL
9 #include <mono/metadata/sgen-protocol.h>
11 #define SGEN_PROTOCOL_EOF 255
13 #define TYPE(t) ((t) & 0x7f)
14 #define WORKER(t) ((t) & 0x80)
17 read_entry (FILE *in, void **data)
22 if (fread (&type, 1, 1, in) != 1)
23 return SGEN_PROTOCOL_EOF;
24 switch (TYPE (type)) {
25 case SGEN_PROTOCOL_COLLECTION_FORCE: size = sizeof (SGenProtocolCollectionForce); break;
26 case SGEN_PROTOCOL_COLLECTION_BEGIN: size = sizeof (SGenProtocolCollectionBegin); break;
27 case SGEN_PROTOCOL_COLLECTION_END: size = sizeof (SGenProtocolCollectionEnd); break;
28 case SGEN_PROTOCOL_CONCURRENT_START: size = 0; break;
29 case SGEN_PROTOCOL_CONCURRENT_UPDATE: size = 0; break;
30 case SGEN_PROTOCOL_CONCURRENT_FINISH: size = 0; break;
31 case SGEN_PROTOCOL_WORLD_STOPPING: size = sizeof (SGenProtocolWorldStopping); break;
32 case SGEN_PROTOCOL_WORLD_STOPPED: size = sizeof (SGenProtocolWorldStopped); break;
33 case SGEN_PROTOCOL_WORLD_RESTARTING: size = sizeof (SGenProtocolWorldRestarting); break;
34 case SGEN_PROTOCOL_WORLD_RESTARTED: size = sizeof (SGenProtocolWorldRestarted); break;
35 case SGEN_PROTOCOL_ALLOC: size = sizeof (SGenProtocolAlloc); break;
36 case SGEN_PROTOCOL_ALLOC_PINNED: size = sizeof (SGenProtocolAlloc); break;
37 case SGEN_PROTOCOL_ALLOC_DEGRADED: size = sizeof (SGenProtocolAlloc); break;
38 case SGEN_PROTOCOL_COPY: size = sizeof (SGenProtocolCopy); break;
39 case SGEN_PROTOCOL_PIN_STAGE: size = sizeof (SGenProtocolPinStage); break;
40 case SGEN_PROTOCOL_PIN: size = sizeof (SGenProtocolPin); break;
41 case SGEN_PROTOCOL_MARK: size = sizeof (SGenProtocolMark); break;
42 case SGEN_PROTOCOL_SCAN_BEGIN: size = sizeof (SGenProtocolScanBegin); break;
43 case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: size = sizeof (SGenProtocolScanVTypeBegin); break;
44 case SGEN_PROTOCOL_SCAN_PROCESS_REFERENCE: size = sizeof (SGenProtocolScanProcessReference); break;
45 case SGEN_PROTOCOL_WBARRIER: size = sizeof (SGenProtocolWBarrier); break;
46 case SGEN_PROTOCOL_GLOBAL_REMSET: size = sizeof (SGenProtocolGlobalRemset); break;
47 case SGEN_PROTOCOL_PTR_UPDATE: size = sizeof (SGenProtocolPtrUpdate); break;
48 case SGEN_PROTOCOL_CLEANUP: size = sizeof (SGenProtocolCleanup); break;
49 case SGEN_PROTOCOL_EMPTY: size = sizeof (SGenProtocolEmpty); break;
50 case SGEN_PROTOCOL_THREAD_SUSPEND: size = sizeof (SGenProtocolThreadSuspend); break;
51 case SGEN_PROTOCOL_THREAD_RESTART: size = sizeof (SGenProtocolThreadRestart); break;
52 case SGEN_PROTOCOL_THREAD_REGISTER: size = sizeof (SGenProtocolThreadRegister); break;
53 case SGEN_PROTOCOL_THREAD_UNREGISTER: size = sizeof (SGenProtocolThreadUnregister); break;
54 case SGEN_PROTOCOL_MISSING_REMSET: size = sizeof (SGenProtocolMissingRemset); break;
55 case SGEN_PROTOCOL_CARD_SCAN: size = sizeof (SGenProtocolCardScan); break;
56 case SGEN_PROTOCOL_CEMENT: size = sizeof (SGenProtocolCement); break;
57 case SGEN_PROTOCOL_CEMENT_RESET: size = 0; break;
58 case SGEN_PROTOCOL_DISLINK_UPDATE: size = sizeof (SGenProtocolDislinkUpdate); break;
59 case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: size = sizeof (SGenProtocolDislinkUpdateStaged); break;
60 case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: size = sizeof (SGenProtocolDislinkProcessStaged); break;
61 case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN: size = sizeof (SGenProtocolDomainUnload); break;
62 case SGEN_PROTOCOL_DOMAIN_UNLOAD_END: size = sizeof (SGenProtocolDomainUnload); break;
63 case SGEN_PROTOCOL_GRAY_ENQUEUE: size = sizeof (SGenProtocolGrayQueue); break;
64 case SGEN_PROTOCOL_GRAY_DEQUEUE: size = sizeof (SGenProtocolGrayQueue); break;
69 *data = malloc (size);
70 if (fread (*data, size, 1, in) != 1)
80 is_always_match (int type)
82 switch (TYPE (type)) {
83 case SGEN_PROTOCOL_COLLECTION_FORCE:
84 case SGEN_PROTOCOL_COLLECTION_BEGIN:
85 case SGEN_PROTOCOL_COLLECTION_END:
86 case SGEN_PROTOCOL_CONCURRENT_START:
87 case SGEN_PROTOCOL_CONCURRENT_UPDATE:
88 case SGEN_PROTOCOL_CONCURRENT_FINISH:
89 case SGEN_PROTOCOL_WORLD_STOPPING:
90 case SGEN_PROTOCOL_WORLD_STOPPED:
91 case SGEN_PROTOCOL_WORLD_RESTARTING:
92 case SGEN_PROTOCOL_WORLD_RESTARTED:
93 case SGEN_PROTOCOL_THREAD_SUSPEND:
94 case SGEN_PROTOCOL_THREAD_RESTART:
95 case SGEN_PROTOCOL_THREAD_REGISTER:
96 case SGEN_PROTOCOL_THREAD_UNREGISTER:
97 case SGEN_PROTOCOL_CEMENT_RESET:
98 case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN:
99 case SGEN_PROTOCOL_DOMAIN_UNLOAD_END:
106 #define WORKER_PREFIX(t) (WORKER ((t)) ? "w" : " ")
109 print_entry (int type, void *data)
111 const char *always_prefix = is_always_match (type) ? " " : "";
112 printf ("%s%s ", WORKER_PREFIX (type), always_prefix);
114 switch (TYPE (type)) {
115 case SGEN_PROTOCOL_COLLECTION_FORCE: {
116 SGenProtocolCollectionForce *entry = data;
117 printf ("collection force generation %d\n", entry->generation);
120 case SGEN_PROTOCOL_COLLECTION_BEGIN: {
121 SGenProtocolCollectionBegin *entry = data;
122 printf ("collection begin %d generation %d\n", entry->index, entry->generation);
125 case SGEN_PROTOCOL_COLLECTION_END: {
126 SGenProtocolCollectionEnd *entry = data;
127 long long scanned = entry->num_scanned_objects;
128 long long unique = entry->num_unique_scanned_objects;
129 printf ("collection end %d generation %d scanned %lld unique %lld %0.2f%%\n", entry->index, entry->generation, scanned, unique, unique ? 100.0 * (double) scanned / (double) unique : 0.0);
132 case SGEN_PROTOCOL_CONCURRENT_START: {
133 printf ("concurrent start\n");
136 case SGEN_PROTOCOL_CONCURRENT_UPDATE: {
137 printf ("concurrent update\n");
140 case SGEN_PROTOCOL_CONCURRENT_FINISH: {
141 printf ("concurrent finish\n");
144 case SGEN_PROTOCOL_WORLD_STOPPING: {
145 SGenProtocolWorldStopping *entry = data;
146 printf ("world stopping timestamp %lld\n", entry->timestamp);
149 case SGEN_PROTOCOL_WORLD_STOPPED: {
150 SGenProtocolWorldStopped *entry = data;
151 long long total = entry->total_major_cards + entry->total_los_cards;
152 long long marked = entry->marked_major_cards + entry->marked_los_cards;
153 printf ("world stopped timestamp %lld total %lld marked %lld %0.2f%%\n", entry->timestamp, total, marked, 100.0 * (double) marked / (double) total);
156 case SGEN_PROTOCOL_WORLD_RESTARTING: {
157 SGenProtocolWorldRestarting *entry = data;
158 long long total = entry->total_major_cards + entry->total_los_cards;
159 long long marked = entry->marked_major_cards + entry->marked_los_cards;
160 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);
163 case SGEN_PROTOCOL_WORLD_RESTARTED: {
164 SGenProtocolWorldRestarted *entry = data;
165 printf ("world restarted generation %d timestamp %lld\n", entry->generation, entry->timestamp);
168 case SGEN_PROTOCOL_ALLOC: {
169 SGenProtocolAlloc *entry = data;
170 printf ("alloc obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
173 case SGEN_PROTOCOL_ALLOC_PINNED: {
174 SGenProtocolAlloc *entry = data;
175 printf ("alloc pinned obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
178 case SGEN_PROTOCOL_ALLOC_DEGRADED: {
179 SGenProtocolAlloc *entry = data;
180 printf ("alloc degraded obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
183 case SGEN_PROTOCOL_COPY: {
184 SGenProtocolCopy *entry = data;
185 printf ("copy from %p to %p vtable %p size %d\n", entry->from, entry->to, entry->vtable, entry->size);
188 case SGEN_PROTOCOL_PIN_STAGE: {
189 SGenProtocolPinStage *entry = data;
190 printf ("pin stage addr ptr %p addr %p\n", entry->addr_ptr, entry->addr);
193 case SGEN_PROTOCOL_PIN: {
194 SGenProtocolPin *entry = data;
195 printf ("pin obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
198 case SGEN_PROTOCOL_MARK: {
199 SGenProtocolMark *entry = data;
200 printf ("mark obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
203 case SGEN_PROTOCOL_SCAN_BEGIN: {
204 SGenProtocolScanBegin *entry = data;
205 printf ("scan_begin obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
208 case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: {
209 SGenProtocolScanVTypeBegin *entry = data;
210 printf ("scan_vtype_begin obj %p size %d\n", entry->obj, entry->size);
213 case SGEN_PROTOCOL_SCAN_PROCESS_REFERENCE: {
214 SGenProtocolScanProcessReference *entry = data;
215 printf ("scan_process_reference obj %p ptr %p value %p\n", entry->obj, entry->ptr, entry->value);
218 case SGEN_PROTOCOL_WBARRIER: {
219 SGenProtocolWBarrier *entry = data;
220 printf ("wbarrier ptr %p value %p value_vtable %p\n", entry->ptr, entry->value, entry->value_vtable);
223 case SGEN_PROTOCOL_GLOBAL_REMSET: {
224 SGenProtocolGlobalRemset *entry = data;
225 printf ("global_remset ptr %p value %p value_vtable %p\n", entry->ptr, entry->value, entry->value_vtable);
228 case SGEN_PROTOCOL_PTR_UPDATE: {
229 SGenProtocolPtrUpdate *entry = data;
230 printf ("ptr_update ptr %p old_value %p new_value %p vtable %p size %d\n",
231 entry->ptr, entry->old_value, entry->new_value, entry->vtable, entry->size);
234 case SGEN_PROTOCOL_CLEANUP: {
235 SGenProtocolCleanup *entry = data;
236 printf ("cleanup ptr %p vtable %p size %d\n", entry->ptr, entry->vtable, entry->size);
239 case SGEN_PROTOCOL_EMPTY: {
240 SGenProtocolEmpty *entry = data;
241 printf ("empty start %p size %d\n", entry->start, entry->size);
244 case SGEN_PROTOCOL_THREAD_SUSPEND: {
245 SGenProtocolThreadSuspend *entry = data;
246 printf ("thread_suspend thread %p ip %p\n", entry->thread, entry->stopped_ip);
249 case SGEN_PROTOCOL_THREAD_RESTART: {
250 SGenProtocolThreadRestart *entry = data;
251 printf ("thread_restart thread %p\n", entry->thread);
254 case SGEN_PROTOCOL_THREAD_REGISTER: {
255 SGenProtocolThreadRegister *entry = data;
256 printf ("thread_register thread %p\n", entry->thread);
259 case SGEN_PROTOCOL_THREAD_UNREGISTER: {
260 SGenProtocolThreadUnregister *entry = data;
261 printf ("thread_unregister thread %p\n", entry->thread);
264 case SGEN_PROTOCOL_MISSING_REMSET: {
265 SGenProtocolMissingRemset *entry = data;
266 printf ("missing_remset obj %p obj_vtable %p offset %d value %p value_vtable %p value_pinned %d\n",
267 entry->obj, entry->obj_vtable, entry->offset, entry->value, entry->value_vtable, entry->value_pinned);
270 case SGEN_PROTOCOL_CARD_SCAN: {
271 SGenProtocolCardScan *entry = data;
272 printf ("card_scan start %p size %d\n", entry->start, entry->size);
275 case SGEN_PROTOCOL_CEMENT: {
276 SGenProtocolCement *entry = data;
277 printf ("cement obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
280 case SGEN_PROTOCOL_CEMENT_RESET: {
281 printf ("cement_reset\n");
284 case SGEN_PROTOCOL_DISLINK_UPDATE: {
285 SGenProtocolDislinkUpdate *entry = data;
286 printf ("dislink_update link %p obj %p staged %d", entry->link, entry->obj, entry->staged);
288 printf (" track %d\n", entry->track);
293 case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: {
294 SGenProtocolDislinkUpdateStaged *entry = data;
295 printf ("dislink_update_staged link %p obj %p index %d", entry->link, entry->obj, entry->index);
297 printf (" track %d\n", entry->track);
302 case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: {
303 SGenProtocolDislinkProcessStaged *entry = data;
304 printf ("dislink_process_staged link %p obj %p index %d\n", entry->link, entry->obj, entry->index);
307 case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN: {
308 SGenProtocolDomainUnload *entry = data;
309 printf ("dislink_unload_begin domain %p\n", entry->domain);
312 case SGEN_PROTOCOL_DOMAIN_UNLOAD_END: {
313 SGenProtocolDomainUnload *entry = data;
314 printf ("dislink_unload_end domain %p\n", entry->domain);
317 case SGEN_PROTOCOL_GRAY_ENQUEUE: {
318 SGenProtocolGrayQueue *entry = data;
319 printf ("enqueue queue %p cursor %p value %p\n", entry->queue, entry->cursor, entry->value);
322 case SGEN_PROTOCOL_GRAY_DEQUEUE: {
323 SGenProtocolGrayQueue *entry = data;
324 printf ("dequeue queue %p cursor %p value %p\n", entry->queue, entry->cursor, entry->value);
333 matches_interval (gpointer ptr, gpointer start, int size)
335 return ptr >= start && (char*)ptr < (char*)start + size;
339 is_match (gpointer ptr, int type, void *data)
341 switch (TYPE (type)) {
342 case SGEN_PROTOCOL_ALLOC:
343 case SGEN_PROTOCOL_ALLOC_PINNED:
344 case SGEN_PROTOCOL_ALLOC_DEGRADED: {
345 SGenProtocolAlloc *entry = data;
346 return matches_interval (ptr, entry->obj, entry->size);
348 case SGEN_PROTOCOL_COPY: {
349 SGenProtocolCopy *entry = data;
350 return matches_interval (ptr, entry->from, entry->size) || matches_interval (ptr, entry->to, entry->size);
352 case SGEN_PROTOCOL_PIN_STAGE: {
353 SGenProtocolPinStage *entry = data;
354 return ptr == entry->addr_ptr || ptr == entry->addr;
356 case SGEN_PROTOCOL_PIN: {
357 SGenProtocolPin *entry = data;
358 return matches_interval (ptr, entry->obj, entry->size);
360 case SGEN_PROTOCOL_MARK: {
361 SGenProtocolMark *entry = data;
362 return matches_interval (ptr, entry->obj, entry->size);
364 case SGEN_PROTOCOL_SCAN_BEGIN: {
365 SGenProtocolScanBegin *entry = data;
366 return matches_interval (ptr, entry->obj, entry->size);
368 case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: {
369 SGenProtocolScanVTypeBegin *entry = data;
370 return matches_interval (ptr, entry->obj, entry->size);
372 case SGEN_PROTOCOL_SCAN_PROCESS_REFERENCE: {
373 SGenProtocolScanProcessReference *entry = data;
374 return ptr == entry->obj || ptr == entry->ptr || ptr == entry->value;
376 case SGEN_PROTOCOL_WBARRIER: {
377 SGenProtocolWBarrier *entry = data;
378 return ptr == entry->ptr || ptr == entry->value;
380 case SGEN_PROTOCOL_GLOBAL_REMSET: {
381 SGenProtocolGlobalRemset *entry = data;
382 return ptr == entry->ptr || ptr == entry->value;
384 case SGEN_PROTOCOL_PTR_UPDATE: {
385 SGenProtocolPtrUpdate *entry = data;
386 return ptr == entry->ptr ||
387 matches_interval (ptr, entry->old_value, entry->size) ||
388 matches_interval (ptr, entry->new_value, entry->size);
390 case SGEN_PROTOCOL_CLEANUP: {
391 SGenProtocolCleanup *entry = data;
392 return matches_interval (ptr, entry->ptr, entry->size);
394 case SGEN_PROTOCOL_EMPTY: {
395 SGenProtocolEmpty *entry = data;
396 return matches_interval (ptr, entry->start, entry->size);
398 case SGEN_PROTOCOL_MISSING_REMSET: {
399 SGenProtocolMissingRemset *entry = data;
400 return ptr == entry->obj || ptr == entry->value || ptr == (char*)entry->obj + entry->offset;
402 case SGEN_PROTOCOL_CARD_SCAN: {
403 SGenProtocolCardScan *entry = data;
404 return matches_interval (ptr, entry->start, entry->size);
406 case SGEN_PROTOCOL_CEMENT: {
407 SGenProtocolCement *entry = data;
408 return matches_interval (ptr, entry->obj, entry->size);
410 case SGEN_PROTOCOL_DISLINK_UPDATE: {
411 SGenProtocolDislinkUpdate *entry = data;
412 return ptr == entry->obj || ptr == entry->link;
414 case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: {
415 SGenProtocolDislinkUpdateStaged *entry = data;
416 return ptr == entry->obj || ptr == entry->link;
418 case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: {
419 SGenProtocolDislinkProcessStaged *entry = data;
420 return ptr == entry->obj || ptr == entry->link;
422 case SGEN_PROTOCOL_GRAY_ENQUEUE: {
423 SGenProtocolGrayQueue *entry = data;
424 return ptr == entry->cursor || ptr == entry->value;
426 case SGEN_PROTOCOL_GRAY_DEQUEUE: {
427 SGenProtocolGrayQueue *entry = data;
428 return ptr == entry->cursor || ptr == entry->value;
431 if (is_always_match (type))
438 is_vtable_match (gpointer ptr, int type, void *data)
440 switch (TYPE (type)) {
441 case SGEN_PROTOCOL_ALLOC:
442 case SGEN_PROTOCOL_ALLOC_PINNED:
443 case SGEN_PROTOCOL_ALLOC_DEGRADED: {
444 SGenProtocolAlloc *entry = data;
445 return ptr == entry->vtable;
447 case SGEN_PROTOCOL_COPY: {
448 SGenProtocolCopy *entry = data;
449 return ptr == entry->vtable;
451 case SGEN_PROTOCOL_PIN: {
452 SGenProtocolPin *entry = data;
453 return ptr == entry->vtable;
455 case SGEN_PROTOCOL_SCAN_BEGIN: {
456 SGenProtocolScanBegin *entry = data;
457 return ptr == entry->vtable;
459 case SGEN_PROTOCOL_WBARRIER: {
460 SGenProtocolWBarrier *entry = data;
461 return ptr == entry->value_vtable;
463 case SGEN_PROTOCOL_GLOBAL_REMSET: {
464 SGenProtocolGlobalRemset *entry = data;
465 return ptr == entry->value_vtable;
467 case SGEN_PROTOCOL_PTR_UPDATE: {
468 SGenProtocolPtrUpdate *entry = data;
469 return ptr == entry->vtable;
471 case SGEN_PROTOCOL_CLEANUP: {
472 SGenProtocolCleanup *entry = data;
473 return ptr == entry->vtable;
475 case SGEN_PROTOCOL_MISSING_REMSET: {
476 SGenProtocolMissingRemset *entry = data;
477 return ptr == entry->obj_vtable || ptr == entry->value_vtable;
479 case SGEN_PROTOCOL_CEMENT: {
480 SGenProtocolCement *entry = data;
481 return ptr == entry->vtable;
489 main (int argc, char *argv[])
493 int num_args = argc - 1;
497 long nums [num_args];
498 long vtables [num_args];
499 gboolean dump_all = FALSE;
500 gboolean pause_times = FALSE;
501 gboolean pause_times_stopped = FALSE;
502 gboolean pause_times_concurrent = FALSE;
503 gboolean pause_times_finish = FALSE;
504 long long pause_times_ts = 0;
506 for (i = 0; i < num_args; ++i) {
507 char *arg = argv [i + 1];
508 char *next_arg = argv [i + 2];
509 if (!strcmp (arg, "--all")) {
511 } else if (!strcmp (arg, "--pause-times")) {
513 } else if (!strcmp (arg, "-v") || !strcmp (arg, "--vtable")) {
514 vtables [num_vtables++] = strtoul (next_arg, NULL, 16);
517 nums [num_nums++] = strtoul (arg, NULL, 16);
522 assert (!pause_times);
526 while ((type = read_entry (stdin, &data)) != SGEN_PROTOCOL_EOF) {
529 case SGEN_PROTOCOL_WORLD_STOPPING: {
530 SGenProtocolWorldStopping *entry = data;
531 assert (!pause_times_stopped);
532 pause_times_concurrent = FALSE;
533 pause_times_finish = FALSE;
534 pause_times_ts = entry->timestamp;
535 pause_times_stopped = TRUE;
538 case SGEN_PROTOCOL_CONCURRENT_FINISH:
539 pause_times_finish = TRUE;
540 case SGEN_PROTOCOL_CONCURRENT_START:
541 case SGEN_PROTOCOL_CONCURRENT_UPDATE:
542 pause_times_concurrent = TRUE;
544 case SGEN_PROTOCOL_WORLD_RESTARTED: {
545 SGenProtocolWorldRestarted *entry = data;
546 assert (pause_times_stopped);
547 printf ("pause-time %d %d %d %lld %lld\n",
549 pause_times_concurrent,
551 entry->timestamp - pause_times_ts,
553 pause_times_stopped = FALSE;
558 gboolean match = num_nums == 0 ? is_match (NULL, type, data) : FALSE;
559 for (i = 0; i < num_nums; ++i) {
560 if (is_match ((gpointer) nums [i], type, data)) {
566 for (i = 0; i < num_vtables; ++i) {
567 if (is_vtable_match ((gpointer) vtables [i], type, data)) {
574 printf (match ? "* " : " ");
575 if (match || dump_all)
576 print_entry (type, data);