[profiler] Enhance the profiler to keep track of and summarize jit trampolines and...
authorPaolo Molaro <lupus@oddwiz.org>
Tue, 9 Dec 2014 16:40:45 +0000 (17:40 +0100)
committerPaolo Molaro <lupus@oddwiz.org>
Tue, 9 Dec 2014 16:47:28 +0000 (17:47 +0100)
mono/profiler/decode.c
mono/profiler/proflog.c
mono/profiler/proflog.h

index c06eb91a161c96d8f76582d2c37eedbb5bd02e08..fc524657f89180c9f94534822fdda277da85fb10 100644 (file)
@@ -1896,6 +1896,36 @@ found_object (uintptr_t obj)
        tracked_objects [num_tracked_objects - 1] = obj;
 }
 
+static int num_jit_helpers = 0;
+static int jit_helpers_code_size = 0;
+
+static const char*
+code_buffer_desc (int type)
+{
+       switch (type) {
+       case MONO_PROFILER_CODE_BUFFER_METHOD:
+               return "method";
+       case MONO_PROFILER_CODE_BUFFER_METHOD_TRAMPOLINE:
+               return "method trampoline";
+       case MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE:
+               return "unbox trampoline";
+       case MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE:
+               return "imt trampoline";
+       case MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE:
+               return "generics trampoline";
+       case MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE:
+               return "specific trampoline";
+       case MONO_PROFILER_CODE_BUFFER_HELPER:
+               return "misc helper";
+       case MONO_PROFILER_CODE_BUFFER_MONITOR:
+               return "monitor/lock";
+       case MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE:
+               return "delegate invoke";
+       default:
+               return "unspecified";
+       }
+}
+
 #define OBJ_ADDR(diff) ((obj_base + diff) << 3)
 #define LOG_TIME(base,diff) /*fprintf("outfile, time %llu + %llu near offset %d\n", base, diff, p - ctx->buf)*/
 
@@ -2354,6 +2384,30 @@ decode_buffer (ProfContext *ctx)
                        }
                        break;
                }
+               case TYPE_RUNTIME: {
+                       int subtype = *p & 0xf0;
+                       uint64_t tdiff = decode_uleb128 (p + 1, &p);
+                       LOG_TIME (time_base, tdiff);
+                       time_base += tdiff;
+                       if (subtype == TYPE_JITHELPER) {
+                               int type = decode_uleb128 (p, &p);
+                               intptr_t codediff = decode_sleb128 (p, &p);
+                               int codelen = decode_uleb128 (p, &p);
+                               const char *name;
+                               if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE) {
+                                       name = (void*)p;
+                                       while (*p) p++;
+                                               p++;
+                               } else {
+                                       name = code_buffer_desc (type);
+                               }
+                               num_jit_helpers++;
+                               jit_helpers_code_size += codelen;
+                               if (debug)
+                                       fprintf (outfile, "jit helper %s, size: %d, code: %p\n", name, codelen, (void*)(ptr_base + codediff));
+                       }
+                       break;
+               }
                case TYPE_SAMPLE: {
                        int subtype = *p & 0xf0;
                        if (subtype == TYPE_SAMPLE_HIT) {
@@ -2724,6 +2778,8 @@ dump_jit (void)
        }
        fprintf (outfile, "\tCompiled methods: %d\n", compiled_methods);
        fprintf (outfile, "\tGenerated code size: %d\n", code_size);
+       fprintf (outfile, "\tJIT helpers: %d\n", num_jit_helpers);
+       fprintf (outfile, "\tJIT helpers code size: %d\n", jit_helpers_code_size);
 }
 
 static void
index 98544578ac6846d427577010d69c3271fab15276..31b7de90943c4bee1160753208612e383a65e78e 100644 (file)
@@ -241,18 +241,16 @@ typedef struct _LogBuffer LogBuffer;
  *     [code size: uleb128] size of the generated code
  *     [name: string] full method name
  *
- * type exception format:
- * type: TYPE_EXCEPTION
- * exinfo: TYPE_EXCEPTION_BT flag and one of: TYPE_THROW, TYPE_CLAUSE
+ * type runtime format:
+ * type: TYPE_RUNTIME
+ * exinfo: one of: TYPE_JITHELPER
  * [time diff: uleb128] nanoseconds since last timing
- * if exinfo.low3bits == TYPE_CLAUSE
- *     [clause type: uleb128] finally/catch/fault/filter
- *     [clause num: uleb128] the clause number in the method header
- *     [method: sleb128] MonoMethod* as a pointer difference from the last such
- *     pointer or the buffer method_base
- * if exinfo.low3bits == TYPE_THROW
- *     [object: sleb128] the object that was thrown as a difference from obj_base
- *     If the TYPE_EXCEPTION_BT flag is set, a backtrace follows.
+ * if exinfo == TYPE_JITHELPER
+ *     [type: uleb128] MonoProfilerCodeBufferType enum value
+ *     [buffer address: sleb128] pointer to the native code as a diff from ptr_base
+ *     [buffer size: uleb128] size of the generated code
+ *     if type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE
+ *             [name: string] buffer description name
  *
  * type monitor format:
  * type: TYPE_MONITOR
@@ -1131,6 +1129,36 @@ method_jitted (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int r
        process_requests (prof);
 }
 
+static void
+code_buffer_new (MonoProfiler *prof, void *buffer, int size, MonoProfilerCodeBufferType type, void *data)
+{
+       uint64_t now;
+       int nlen;
+       char *name;
+       LogBuffer *logbuffer;
+       if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE) {
+               name = data;
+               nlen = strlen (name) + 1;
+       } else {
+               name = NULL;
+               nlen = 0;
+       }
+       logbuffer = ensure_logbuf (32 + nlen);
+       now = current_time ();
+       ENTER_LOG (logbuffer, "code buffer");
+       emit_byte (logbuffer, TYPE_JITHELPER | TYPE_RUNTIME);
+       emit_time (logbuffer, now);
+       emit_value (logbuffer, type);
+       emit_ptr (logbuffer, buffer);
+       emit_value (logbuffer, size);
+       if (name) {
+               memcpy (logbuffer->data, name, nlen);
+               logbuffer->data += nlen;
+       }
+       EXIT_LOG (logbuffer);
+       process_requests (prof);
+}
+
 static void
 throw_exc (MonoProfiler *prof, MonoObject *object)
 {
@@ -3067,6 +3095,7 @@ mono_profiler_startup (const char *desc)
        mono_profiler_install_thread_name (thread_name);
        mono_profiler_install_enter_leave (method_enter, method_leave);
        mono_profiler_install_jit_end (method_jitted);
+       mono_profiler_install_code_buffer_new (code_buffer_new);
        mono_profiler_install_exception (throw_exc, method_exc_leave, clause_exc);
        mono_profiler_install_monitor (monitor_event);
        mono_profiler_install_runtime_initialized (runtime_initialized);
index 2d420e911aa9058e4ec391cfeba28744fc39525f..3ea6a8d23822c82e70aeb50506628832e113099f 100644 (file)
@@ -5,7 +5,7 @@
 #define LOG_HEADER_ID 0x4D505A01
 #define LOG_VERSION_MAJOR 0
 #define LOG_VERSION_MINOR 4
-#define LOG_DATA_VERSION 7
+#define LOG_DATA_VERSION 8
 /*
  * Changes in data versions:
  * version 2: added offsets in heap walk
@@ -13,6 +13,7 @@
  * version 4: added sample/statistical profiling
  * version 5: added counters sampling
  * version 6: added optional backtrace in sampling info
+ * version 8: added TYPE_RUNTIME and JIT helpers/trampolines
  */
 
 enum {
@@ -24,6 +25,7 @@ enum {
        TYPE_MONITOR,
        TYPE_HEAP,
        TYPE_SAMPLE,
+       TYPE_RUNTIME,
        /* extended type for TYPE_HEAP */
        TYPE_HEAP_START  = 0 << 4,
        TYPE_HEAP_END    = 1 << 4,
@@ -65,6 +67,8 @@ enum {
        TYPE_SAMPLE_UBIN          = 2 << 4,
        TYPE_SAMPLE_COUNTERS_DESC = 3 << 4,
        TYPE_SAMPLE_COUNTERS      = 4 << 4,
+       /* extended type for TYPE_RUNTIME */
+       TYPE_JITHELPER = 1 << 4,
        TYPE_END
 };