2003-12-03 Zoltan Varga <vargaz@freemail.hu>
authorZoltan Varga <vargaz@gmail.com>
Wed, 3 Dec 2003 13:24:27 +0000 (13:24 -0000)
committerZoltan Varga <vargaz@gmail.com>
Wed, 3 Dec 2003 13:24:27 +0000 (13:24 -0000)
* debug-mini.c (mono_debug_serialize_debug_info): New function to
serialize the debug info.

* debug-mini.c (mono_debug_add_aot_method): New function to load the
debug info from the serialized representation.

* aot.c: Save debug info into the generated file and load it when
loading a method.

* mini.h (MONO_AOT_FILE_VERSION): Bump version number.

svn path=/trunk/mono/; revision=20727

mono/mini/aot.c
mono/mini/debug-mini.c
mono/mini/mini.h

index aa1a4f8c449c3d6dc406b25647618afe56a1ef10..88cadaa3edff512183980d0caff02907a256235e 100644 (file)
@@ -69,7 +69,7 @@ static MonoGHashTable *aot_modules;
 
 static CRITICAL_SECTION aot_mutex;
 
-static guint32 mono_aot_verbose = 0;
+static guint32 mono_aot_verbose = 1;
 
 /*
  * Disabling this will make a copy of the loaded code and use the copy instead 
@@ -285,7 +285,7 @@ mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
                        memcpy (code, minfo->info->code_start, minfo->info->code_size);
 
                        if (mono_aot_verbose > 1)
-                               printf ("REUSE METHOD: %s %p - %p.\n", mono_method_full_name (method, TRUE), code, (char*)code + code_len);
+                               printf ("REUSE METHOD: %s %p - %p.\n", mono_method_full_name (method, TRUE), code, (char*)code + minfo->info->code_size);
 
                        /* Do this outside the lock to avoid deadlocks */
                        LeaveCriticalSection (&aot_mutex);
@@ -412,7 +412,7 @@ mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
                gpointer *table;
                int pages;
                int i, err;
-               guint32 last_offset;
+               guint32 last_offset, buf_len;
 
                if (aot_module->opts & MONO_OPT_SHARED)
                        mp = mono_mempool_new ();
@@ -545,6 +545,11 @@ mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
                        patch_info = ji;
                }
 
+               info = (gpointer)((guint8*)info + 4);
+               buf_len = *(guint32*)info;
+               info = (gpointer)((guint8*)info + 4);
+               mono_debug_add_aot_method (domain, method, code, (guint8*)info, buf_len);
+
                if (use_loaded_code) {
                /* disable write protection */
 #ifndef PLATFORM_WIN32
@@ -1034,6 +1039,21 @@ emit_method (MonoAotCompile *acfg, MonoCompile *cfg)
        /* NULL terminated array */
        fprintf (tmpfp, "\t.long 0\n");
 
+       {
+               guint8 *buf;
+               guint32 buf_len;
+
+               mono_debug_serialize_debug_info (cfg, &buf, &buf_len);
+
+               fprintf (tmpfp, "\t.long %d\n", buf_len);
+
+               for (i = 0; i < buf_len; ++i)
+                       fprintf (tmpfp, ".byte %d\n", (unsigned int) buf [i]);
+
+               if (buf_len > 0)
+                       g_free (buf);
+       }
+
        /* fixme: save the rest of the required infos */
 
        g_free (mname);
index c47cc5f0b5f5b3eaa205d0f3953360182b747e68..f007279ff03e89dda3e7245b467b6aef0fbcf898 100644 (file)
@@ -160,6 +160,246 @@ mono_debug_record_line_number (MonoCompile *cfg, MonoInst *ins, guint32 address)
        record_line_number (info->jit, address, offset);
 }
 
+static inline void
+encode_value (guint32 value, char *buf, char **endbuf)
+{
+       char *p = buf;
+
+       //printf ("ENCODE: %d 0x%x.\n", value, value);
+
+       /* 
+        * Same encoding as the one used in the metadata, extended to handle values
+        * greater than 0x1fffffff.
+        */
+       if (value <= 127)
+               *p++ = value;
+       else if (value <= 16384) {
+               p [0] = 0x80 | (value >> 8);
+               p [1] = value & 0xff;
+               p += 2;
+       } else if (value <= 0x1fffffff) {
+               p [0] = (value >> 24) | 0xc0;
+               p [1] = (value >> 16) & 0xff;
+               p [2] = (value >> 8) & 0xff;
+               p [3] = value & 0xff;
+               p += 4;
+       }
+       else {
+               p [0] = 0xff;
+               p [1] = (value >> 24) & 0xff;
+               p [2] = (value >> 16) & 0xff;
+               p [3] = (value >> 8) & 0xff;
+               p [4] = value & 0xff;
+               p += 5;
+       }
+       if (endbuf)
+               *endbuf = p;
+}
+
+static inline guint32
+decode_value (char *_ptr, char **rptr)
+{
+       unsigned char *ptr = (unsigned char *) _ptr;
+       unsigned char b = *ptr;
+       guint32 len;
+       
+       if ((b & 0x80) == 0){
+               len = b;
+               ++ptr;
+       } else if ((b & 0x40) == 0){
+               len = ((b & 0x3f) << 8 | ptr [1]);
+               ptr += 2;
+       } else if (b != 0xff) {
+               len = ((b & 0x1f) << 24) |
+                       (ptr [1] << 16) |
+                       (ptr [2] << 8) |
+                       ptr [3];
+               ptr += 4;
+       }
+       else {
+               len = (ptr [0] << 24) | (ptr [1] << 16) | (ptr [2] << 8) | ptr [3];
+               ptr += 5;
+       }
+       if (rptr)
+               *rptr = ptr;
+
+       //printf ("DECODE: %d.\n", len);
+       return len;
+}
+
+static void
+serialize_variable (MonoDebugVarInfo *var, char *p, char **endbuf)
+{
+       guint32 flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
+
+       switch (flags) {
+       case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
+               encode_value (var->index, p, &p);
+               break;
+       case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
+               encode_value (var->index, p, &p);
+               encode_value (var->offset, p, &p);
+               break;
+       default:
+               g_assert_not_reached ();
+       }
+       *endbuf = p;
+}
+
+void
+mono_debug_serialize_debug_info (MonoCompile *cfg, 
+                                                                guint8 **out_buf, guint32 *buf_len)
+{
+       MiniDebugMethodInfo *info;
+       MonoDebugMethodJitInfo *jit;
+       guint32 size, prev_offset, prev_native_offset;
+       char *buf;
+       char *p;
+       int i;
+
+       info = (MiniDebugMethodInfo *) cfg->debug_info;
+       if (!info || !info->jit) {
+               *buf_len = 0;
+               return;
+       }
+       jit = info->jit;
+
+       size = ((jit->num_params + jit->num_locals + 1) * 10) + (jit->line_numbers->len * 10) + 64;
+       p = buf = g_malloc (size);
+       encode_value (jit->epilogue_begin, p, &p);
+    encode_value (jit->prologue_end, p, &p);
+       encode_value (jit->code_size, p, &p);
+
+       for (i = 0; i < jit->num_params; ++i)
+               serialize_variable (&jit->params [i], p, &p);
+
+       if (cfg->method->signature->hasthis)
+               serialize_variable (jit->this_var, p, &p);
+
+       for (i = 0; i < jit->num_locals; i++)
+               serialize_variable (&jit->locals [i], p, &p);
+
+       encode_value (jit->line_numbers->len, p, &p);
+
+       prev_offset = 0;
+       prev_native_offset = 0;
+       for (i = 0; i < jit->line_numbers->len; ++i) {
+               MonoDebugLineNumberEntry *lne = &g_array_index (jit->line_numbers, 
+                                                                                                               MonoDebugLineNumberEntry,
+                                                                                                               i);
+               encode_value (lne->offset - prev_offset, p, &p);
+               encode_value (lne->address - prev_native_offset, p, &p);
+               prev_offset = lne->offset;
+               prev_native_offset = lne->address;
+       }
+
+       g_assert (p - buf < size);
+
+       *out_buf = buf;
+       *buf_len = p - buf;
+}
+
+static void
+deserialize_variable (MonoDebugVarInfo *var, char *p, char **endbuf)
+{
+       guint32 flags;
+
+       var->index = decode_value (p, &p);
+
+       flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
+
+       switch (flags) {
+       case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
+               break;
+       case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
+               var->offset = decode_value (p, &p);
+               break;
+       default:
+               g_assert_not_reached ();
+       }
+       *endbuf = p;
+}
+
+static MonoDebugMethodJitInfo *
+deserialize_debug_info (MonoMethod *method,
+                                               guint8 *code_start, 
+                                               guint8 *buf, guint32 buf_len)
+{
+       MonoMethodHeader *header;
+       MonoDebugMethodJitInfo *jit;
+       guint32 offset, native_offset, prev_offset, prev_native_offset, len;
+       char *p;
+       int i;
+
+       g_assert (((MonoMethodNormal*)method)->header);
+       header = ((MonoMethodNormal*)method)->header;
+
+       jit = g_new0 (MonoDebugMethodJitInfo, 1);
+       jit->code_start = code_start;
+       jit->line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
+       jit->num_locals = header->num_locals;
+       jit->locals = g_new0 (MonoDebugVarInfo, jit->num_locals);
+       jit->num_params = method->signature->param_count;
+       jit->params = g_new0 (MonoDebugVarInfo, jit->num_params);
+
+       p = buf;
+       jit->epilogue_begin = decode_value (p, &p);
+       jit->prologue_end = decode_value (p, &p);
+       jit->code_size = decode_value (p, &p);
+
+       for (i = 0; i < jit->num_params; ++i)
+               deserialize_variable (&jit->params [i], p, &p);
+
+       if (method->signature->hasthis) {
+               jit->this_var = g_new0 (MonoDebugVarInfo, 1);
+               deserialize_variable (jit->this_var, p, &p);
+       }
+
+       for (i = 0; i < jit->num_locals; i++)
+               deserialize_variable (&jit->locals [i], p, &p);
+
+       len = decode_value (p, &p);
+
+       prev_offset = 0;
+       prev_native_offset = 0;
+       for (i = 0; i < len; ++i) {
+               offset = prev_offset + decode_value (p, &p);
+               native_offset = prev_native_offset + decode_value (p, &p);
+               record_line_number (jit, native_offset, offset);
+               prev_offset = offset;
+               prev_native_offset = native_offset;
+       }
+
+       return jit;
+}
+
+void
+mono_debug_add_aot_method (MonoDomain *domain,
+                                                  MonoMethod *method, guint8 *code_start, 
+                                                  guint8 *debug_info, guint32 debug_info_len)
+{
+       MonoDebugMethodJitInfo *jit;
+
+       if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
+               return;
+
+       if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
+           (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
+           (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
+           (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
+           (method->wrapper_type != MONO_WRAPPER_NONE))
+               return;
+
+       if (debug_info_len == 0)
+               return;
+
+       jit = deserialize_debug_info (method, code_start,
+                                                                 debug_info,
+                                                                 debug_info_len);
+
+       mono_debug_add_method (method, jit, domain);
+}
+
 MonoDomain *
 mono_init_debugger (const char *file, const char *opt_flags)
 {
index 391e24c9b909c7029a441ca081b48001f021720b..f2c37de2c2a098f294102f1c7d33821ccf3728bf 100644 (file)
@@ -32,7 +32,7 @@
 #endif
 
 /* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION "6"
+#define MONO_AOT_FILE_VERSION "7"
 
 #if 1
 #define mono_bitset_test_fast(set,n) (((guint32*)set)[2+(n)/32] & (1 << ((n) % 32)))
@@ -726,7 +726,10 @@ void      mono_debug_open_method                (MonoCompile *cfg);
 void      mono_debug_close_method               (MonoCompile *cfg);
 void      mono_debug_open_block                 (MonoCompile *cfg, MonoBasicBlock *bb, guint32 address);
 void      mono_debug_record_line_number         (MonoCompile *cfg, MonoInst *ins, guint32 address);
-
+void      mono_debug_serialize_debug_info       (MonoCompile *cfg, guint8 **out_buf, guint32 *buf_len);
+void      mono_debug_add_aot_method            (MonoDomain *domain,
+                                                                                               MonoMethod *method, guint8 *code_start, 
+                                                                                               guint8 *debug_info, guint32 debug_info_len);
 
 /* Tracing */
 MonoTraceSpec *mono_trace_parse_options         (MonoAssembly *assembly, char *options);