uintptr_t thread_id;
unsigned char* data_end;
unsigned char* data;
+ int locked;
int size;
int call_depth;
unsigned char buf [1];
};
+#define ENTER_LOG(lb,str) if ((lb)->locked) {write(2, str, strlen(str)); write(2, "\n", 1);return;} else {(lb)->locked++;}
+#define EXIT_LOG(lb) (lb)->locked--;
+
struct _MonoProfiler {
LogBuffer *buffers;
FILE* file;
uint64_t now;
LogBuffer *logbuffer = ensure_logbuf (10);
now = current_time ();
+ ENTER_LOG (logbuffer, "gcevent");
emit_byte (logbuffer, TYPE_GC_EVENT | TYPE_GC);
emit_time (logbuffer, now);
emit_value (logbuffer, ev);
}
if (ev == MONO_GC_EVENT_PRE_START_WORLD)
heap_walk (profiler);
+ EXIT_LOG (logbuffer);
if (ev == MONO_GC_EVENT_POST_START_WORLD)
safe_dump (profiler, logbuffer);
//printf ("gc event %d for generation %d\n", ev, generation);
uint64_t now;
LogBuffer *logbuffer = ensure_logbuf (10);
now = current_time ();
+ ENTER_LOG (logbuffer, "gcresize");
emit_byte (logbuffer, TYPE_GC_RESIZE | TYPE_GC);
emit_time (logbuffer, now);
emit_value (logbuffer, new_size);
//printf ("gc resized to %lld\n", new_size);
+ EXIT_LOG (logbuffer);
}
#define MAX_FRAMES 16
collect_bt (&data);
logbuffer = ensure_logbuf (32 + MAX_FRAMES * 8);
now = current_time ();
+ ENTER_LOG (logbuffer, "gcalloc");
emit_byte (logbuffer, do_bt | TYPE_ALLOC);
emit_time (logbuffer, now);
emit_ptr (logbuffer, klass);
emit_value (logbuffer, len);
if (do_bt)
emit_bt (logbuffer, &data);
+ EXIT_LOG (logbuffer);
if (logbuffer->next)
safe_dump (prof, logbuffer);
//printf ("gc alloc %s at %p\n", mono_class_get_name (klass), obj);
uint64_t now;
LogBuffer *logbuffer = ensure_logbuf (10 + num * 8);
now = current_time ();
+ ENTER_LOG (logbuffer, "gcmove");
emit_byte (logbuffer, TYPE_GC_MOVE | TYPE_GC);
emit_time (logbuffer, now);
emit_value (logbuffer, num);
for (i = 0; i < num; ++i)
emit_obj (logbuffer, objects [i]);
//printf ("gc moved %d objects\n", num/2);
+ EXIT_LOG (logbuffer);
}
static void
uint64_t now;
LogBuffer *logbuffer = ensure_logbuf (16);
now = current_time ();
+ ENTER_LOG (logbuffer, "gchandle");
if (op == MONO_PROFILER_GC_HANDLE_CREATED)
emit_byte (logbuffer, TYPE_GC_HANDLE_CREATED | TYPE_GC);
else if (op == MONO_PROFILER_GC_HANDLE_DESTROYED)
emit_value (logbuffer, handle);
if (op == MONO_PROFILER_GC_HANDLE_CREATED)
emit_obj (logbuffer, obj);
+ EXIT_LOG (logbuffer);
}
static char*
nlen = strlen (name) + 1;
logbuffer = ensure_logbuf (16 + nlen);
now = current_time ();
+ ENTER_LOG (logbuffer, "image");
emit_byte (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
emit_time (logbuffer, now);
emit_byte (logbuffer, TYPE_IMAGE);
memcpy (logbuffer->data, name, nlen);
logbuffer->data += nlen;
//printf ("loaded image %p (%s)\n", image, name);
+ EXIT_LOG (logbuffer);
if (logbuffer->next)
safe_dump (prof, logbuffer);
}
image = mono_class_get_image (klass);
logbuffer = ensure_logbuf (24 + nlen);
now = current_time ();
+ ENTER_LOG (logbuffer, "class");
emit_byte (logbuffer, TYPE_END_LOAD | TYPE_METADATA);
emit_time (logbuffer, now);
emit_byte (logbuffer, TYPE_CLASS);
mono_free (name);
else
free (name);
+ EXIT_LOG (logbuffer);
if (logbuffer->next)
safe_dump (prof, logbuffer);
}
if (logbuffer->call_depth++ > max_call_depth)
return;
now = current_time ();
+ ENTER_LOG (logbuffer, "enter");
emit_byte (logbuffer, TYPE_ENTER | TYPE_METHOD);
emit_time (logbuffer, now);
emit_method (logbuffer, method);
+ EXIT_LOG (logbuffer);
}
static void
if (--logbuffer->call_depth > max_call_depth)
return;
now = current_time ();
+ ENTER_LOG (logbuffer, "leave");
emit_byte (logbuffer, TYPE_LEAVE | TYPE_METHOD);
emit_time (logbuffer, now);
emit_method (logbuffer, method);
+ EXIT_LOG (logbuffer);
if (logbuffer->next)
safe_dump (prof, logbuffer);
}
if (--logbuffer->call_depth > max_call_depth)
return;
now = current_time ();
+ ENTER_LOG (logbuffer, "eleave");
emit_byte (logbuffer, TYPE_EXC_LEAVE | TYPE_METHOD);
emit_time (logbuffer, now);
emit_method (logbuffer, method);
+ EXIT_LOG (logbuffer);
}
static void
nlen = strlen (name) + 1;
logbuffer = ensure_logbuf (32 + nlen);
now = current_time ();
+ ENTER_LOG (logbuffer, "jit");
emit_byte (logbuffer, TYPE_JIT | TYPE_METHOD);
emit_time (logbuffer, now);
emit_method (logbuffer, method);
memcpy (logbuffer->data, name, nlen);
logbuffer->data += nlen;
mono_free (name);
+ EXIT_LOG (logbuffer);
if (logbuffer->next)
safe_dump (prof, logbuffer);
}
collect_bt (&data);
logbuffer = ensure_logbuf (16 + MAX_FRAMES * 8);
now = current_time ();
+ ENTER_LOG (logbuffer, "throw");
emit_byte (logbuffer, do_bt | TYPE_EXCEPTION);
emit_time (logbuffer, now);
emit_obj (logbuffer, object);
if (do_bt)
emit_bt (logbuffer, &data);
+ EXIT_LOG (logbuffer);
}
static void
uint64_t now;
LogBuffer *logbuffer = ensure_logbuf (16);
now = current_time ();
+ ENTER_LOG (logbuffer, "clause");
emit_byte (logbuffer, TYPE_EXCEPTION | TYPE_CLAUSE);
emit_time (logbuffer, now);
emit_value (logbuffer, clause_type);
emit_value (logbuffer, clause_num);
emit_method (logbuffer, method);
+ EXIT_LOG (logbuffer);
}
static void
collect_bt (&data);
logbuffer = ensure_logbuf (16 + MAX_FRAMES * 8);
now = current_time ();
+ ENTER_LOG (logbuffer, "monitor");
emit_byte (logbuffer, (event << 4) | do_bt | TYPE_MONITOR);
emit_time (logbuffer, now);
emit_obj (logbuffer, object);
if (do_bt)
emit_bt (logbuffer, &data);
+ EXIT_LOG (logbuffer);
}
static void
LogBuffer *logbuffer;
logbuffer = ensure_logbuf (10 + len);
now = current_time ();
+ ENTER_LOG (logbuffer, "tname");
emit_byte (logbuffer, TYPE_METADATA);
emit_time (logbuffer, now);
emit_byte (logbuffer, TYPE_THREAD);
emit_value (logbuffer, 0); /* flags */
memcpy (logbuffer->data, name, len);
logbuffer->data += len;
+ EXIT_LOG (logbuffer);
}
static void
prof->file = popen (filename + 1, "w");
prof->pipe_output = 1;
} else {
+ unlink (filename);
prof->file = fopen (filename, "wb");
}
if (!prof->file) {