2005-02-05 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / mini / aot.c
index 5acfd50c3d0e0652b3b43d5dac6cec0f020b512f..2850065c92558d0671c69220006923ddd8e58704 100644 (file)
 
 #define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1)))
 
-typedef struct MonoAotMethod {
-       MonoJitInfo *info;
-       MonoJumpInfo *patch_info;
-       MonoDomain *domain;
-} MonoAotMethod;
-
 typedef struct MonoAotModule {
        char *aot_name;
        /* Optimization flags used to compile the module */
        guint32 opts;
-       /* Maps MonoMethods to MonoAotMethodInfos */
-       GHashTable *methods;
        /* Pointer to the Global Offset Table */
        gpointer *got;
        guint32 got_size;
@@ -81,23 +73,28 @@ typedef struct MonoAotModule {
        guint32 *code_offsets;
        guint8 *method_infos;
        guint32 *method_info_offsets;
+       guint8 *class_infos;
+       guint32 *class_info_offsets;
 } MonoAotModule;
 
+typedef struct MonoAotOptions {
+       char *outfile;
+       gboolean save_temps;
+       gboolean write_symbols;
+} MonoAotOptions;
+
 typedef struct MonoAotCompile {
+       MonoImage *image;
        FILE *fp;
-       GHashTable *ref_hash;
        GHashTable *icall_hash;
        GPtrArray *icall_table;
        GHashTable *image_hash;
        GPtrArray *image_table;
        guint32 got_offset;
        guint32 *method_got_offsets;
+       MonoAotOptions aot_opts;
 } MonoAotCompile;
 
-typedef struct MonoAotOptions {
-       char *outfile;
-} MonoAotOptions;
-
 static GHashTable *aot_modules;
 
 static CRITICAL_SECTION aot_mutex;
@@ -246,6 +243,24 @@ decode_field_info (MonoAotModule *module, char *buf, char **endbuf)
        return mono_class_get_field (klass, token);
 }
 
+static inline MonoImage*
+decode_method_ref (MonoAotModule *module, guint32 *token, char *buf, char **endbuf)
+{
+       guint32 image_index, value;
+       MonoImage *image;
+
+       value = decode_value (buf, &buf);
+       *endbuf = buf;
+       image_index = value >> 24;
+       *token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
+
+       image = load_image (module, image_index);
+       if (!image)
+               return NULL;
+       else
+               return image;
+}
+
 G_GNUC_UNUSED
 static void
 make_writable (guint8* addr, guint32 len)
@@ -440,7 +455,6 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
 
        info = g_new0 (MonoAotModule, 1);
        info->aot_name = aot_name;
-       info->methods = g_hash_table_new (NULL, NULL);
 #ifdef MONO_ARCH_HAVE_PIC_AOT
        info->got = got;
        info->got_size = *got_size_ptr;
@@ -509,6 +523,8 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        g_module_symbol (assembly->aot_module, "methods", (gpointer*)&info->code);
        g_module_symbol (assembly->aot_module, "method_info_offsets", (gpointer*)&info->method_info_offsets);
        g_module_symbol (assembly->aot_module, "method_infos", (gpointer*)&info->method_infos);
+       g_module_symbol (assembly->aot_module, "class_infos", (gpointer*)&info->class_infos);
+       g_module_symbol (assembly->aot_module, "class_info_offsets", (gpointer*)&info->class_info_offsets);
 
        EnterCriticalSection (&aot_mutex);
        g_hash_table_insert (aot_modules, assembly, info);
@@ -530,6 +546,131 @@ mono_aot_init (void)
        if (getenv ("MONO_AOT_CACHE"))
                use_aot_cache = TRUE;
 }
+
+static gboolean
+decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, char *buf, char **endbuf)
+{
+       guint32 flags;
+
+       info->vtable_size = decode_value (buf, &buf);
+       flags = decode_value (buf, &buf);
+       info->ghcimpl = (flags >> 0) & 0x1;
+       info->has_finalize = (flags >> 1) & 0x1;
+       info->has_cctor = (flags >> 2) & 0x1;
+       if (info->has_cctor) {
+               MonoImage *cctor_image = decode_method_ref (module, &info->cctor_token, buf, &buf);
+               if (!cctor_image)
+                       return FALSE;
+       }
+       if (info->has_finalize) {
+               info->finalize_image = decode_method_ref (module, &info->finalize_token, buf, &buf);
+               if (!info->finalize_image)
+                       return FALSE;
+       }
+
+       *endbuf = buf;
+
+       return TRUE;
+}      
+
+gboolean
+mono_aot_init_vtable (MonoVTable *vtable)
+{
+       int i;
+       MonoAotModule *aot_module;
+       MonoClass *klass = vtable->klass;
+       guint8 *info;
+       MonoCachedClassInfo class_info;
+       char *p;
+       gboolean err;
+
+       if (MONO_CLASS_IS_INTERFACE (klass) || klass->rank || !klass->image->assembly->aot_module)
+               return FALSE;
+
+       EnterCriticalSection (&aot_mutex);
+
+       aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, klass->image->assembly);
+       if (!aot_module) {
+               LeaveCriticalSection (&aot_mutex);
+               return FALSE;
+       }
+
+       info = &aot_module->class_infos [aot_module->class_info_offsets [mono_metadata_token_index (klass->type_token) - 1]];
+       p = (char*)info;
+
+       err = decode_cached_class_info (aot_module, &class_info, p, &p);
+       if (!err) {
+               LeaveCriticalSection (&aot_mutex);
+               return FALSE;
+       }
+
+       //printf ("VT0: %s.%s %d\n", klass->name_space, klass->name, vtable_size);
+       for (i = 0; i < class_info.vtable_size; ++i) {
+               guint32 image_index, token, value;
+               MonoImage *image;
+               MonoMethod *m;
+
+               vtable->vtable [i] = 0;
+
+               value = decode_value (p, &p);
+               if (!value)
+                       continue;
+
+               image_index = value >> 24;
+               token = MONO_TOKEN_METHOD_DEF | (value & 0xffffff);
+
+               image = load_image (aot_module, image_index);
+               if (!image) {
+                       LeaveCriticalSection (&aot_mutex);
+                       return FALSE;
+               }
+
+#ifdef MONO_ARCH_HAVE_CREATE_TRAMPOLINE_FROM_TOKEN
+               vtable->vtable [i] = mono_create_jit_trampoline_from_token (image, token);
+#else
+               m = mono_get_method (image, token, NULL);
+               g_assert (m);
+
+               //printf ("M: %d %p %s\n", i, &(vtable->vtable [i]), mono_method_full_name (m, TRUE));
+               vtable->vtable [i] = mono_create_jit_trampoline (m);
+#endif
+       }
+
+       LeaveCriticalSection (&aot_mutex);
+
+       return TRUE;
+}
+
+gboolean
+mono_aot_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
+{
+       MonoAotModule *aot_module;
+       char *p;
+       gboolean err;
+
+       if (MONO_CLASS_IS_INTERFACE (klass) || klass->rank || !klass->image->assembly->aot_module)
+               return FALSE;
+
+       EnterCriticalSection (&aot_mutex);
+
+       aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, klass->image->assembly);
+       if (!aot_module) {
+               LeaveCriticalSection (&aot_mutex);
+               return FALSE;
+       }
+
+       p = &aot_module->class_infos [aot_module->class_info_offsets [mono_metadata_token_index (klass->type_token) - 1]];
+
+       err = decode_cached_class_info (aot_module, res, p, &p);
+       if (!err) {
+               LeaveCriticalSection (&aot_mutex);
+               return FALSE;
+       }
+
+       LeaveCriticalSection (&aot_mutex);
+
+       return TRUE;
+}
  
 static MonoJitInfo *
 mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
@@ -540,9 +681,6 @@ mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
        guint8 *code = NULL;
        guint8 *info;
        MonoAotModule *aot_module;
-       MonoAotMethod *minfo;
-       MonoJitInfo *jinfo;
-       MonoMethodHeader *header;
 
        if (!module)
                return NULL;
@@ -559,8 +697,6 @@ mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
                (method->flags & METHOD_ATTRIBUTE_ABSTRACT))
                return NULL;
        
-       header = mono_method_get_header (method);
-       
        aot_module = (MonoAotModule*) g_hash_table_lookup (aot_modules, ass);
 
        g_assert (klass->inited);
@@ -569,28 +705,15 @@ mono_aot_get_method_inner (MonoDomain *domain, MonoMethod *method)
                /* Non shared AOT code can't be used in other appdomains */
                return NULL;
 
-       minfo = g_hash_table_lookup (aot_module->methods, method);
-       /* Can't use code from non-root domains since they can be unloaded */
-       if (minfo && (minfo->domain == mono_get_root_domain ())) {
-               /* This method was already loaded in another appdomain */
-
-               /* Duplicate jinfo */
-               jinfo = mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo));
-               memcpy (jinfo, minfo->info, sizeof (MonoJitInfo));
-               if (jinfo->clauses) {
-                       jinfo->clauses = 
-                               mono_mempool_alloc0 (domain->mp, sizeof (MonoJitExceptionInfo) * header->num_clauses);
-                       memcpy (jinfo->clauses, minfo->info->clauses, sizeof (MonoJitExceptionInfo) * header->num_clauses);
-               }
-
-               return jinfo;
-       }
-
        if (aot_module->out_of_date)
                return NULL;
 
        if (aot_module->code_offsets [mono_metadata_token_index (method->token) - 1] == 0xffffffff) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT NOT FOUND: %s.\n", mono_method_full_name (method, TRUE));
+               if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
+                       char *full_name = mono_method_full_name (method, TRUE);
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT NOT FOUND: %s.\n", full_name);
+                       g_free (full_name);
+               }
                return NULL;
        }
 
@@ -614,20 +737,14 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
        MonoClass *klass = method->klass;
        MonoJumpInfo *patch_info = NULL;
        guint code_len, used_int_regs, used_strings;
-       MonoAotMethod *minfo;
        MonoJitInfo *jinfo;
-       MonoMethodHeader *header = mono_method_get_header (method);
        MonoMemPool *mp;
        GPtrArray *patches;
        int i, pindex, got_index;
        gboolean non_got_patches, keep_patches = TRUE;
+       gboolean has_clauses;
        char *p;
 
-       minfo = g_new0 (MonoAotMethod, 1);
-
-       minfo->domain = domain;
-       jinfo = mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo));
-
        p = (char*)info;
        code_len = decode_value (p, &p);
        used_int_regs = decode_value (p, &p);
@@ -640,21 +757,27 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
                code = code2;
        }
 
-       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND AOT compiled code for %s %p - %p %p\n", mono_method_full_name (method, TRUE), code, code + code_len, info);
+       if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
+               char *full_name = mono_method_full_name (method, TRUE);
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT FOUND AOT compiled code for %s %p - %p %p\n", full_name, code, code + code_len, info);
+               g_free (full_name);
+       }
 
        /* Exception table */
-       if (header->num_clauses) {
-               jinfo->clauses = 
-                       mono_mempool_alloc0 (domain->mp, sizeof (MonoJitExceptionInfo) * header->num_clauses);
+       has_clauses = decode_value (p, &p);
+       if (has_clauses) {
+               MonoMethodHeader *header = mono_method_get_header (method);
+               jinfo = 
+                       mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo) + (sizeof (MonoJitExceptionInfo) * header->num_clauses));
                jinfo->num_clauses = header->num_clauses;
 
-               jinfo->exvar_offset = decode_value (p, &p);
-
                for (i = 0; i < header->num_clauses; ++i) {
                        MonoExceptionClause *ec = &header->clauses [i];                         
                        MonoJitExceptionInfo *ei = &jinfo->clauses [i];
 
                        ei->flags = ec->flags;
+                       ei->exvar_offset = decode_value (p, &p);
+
                        if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
                                ei->data.filter = code + decode_value (p, &p);
                        else
@@ -665,6 +788,8 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
                        ei->handler_start = code + decode_value (p, &p);
                }
        }
+       else
+               jinfo = mono_mempool_alloc0 (domain->mp, sizeof (MonoJitInfo));
 
        if (aot_module->opts & MONO_OPT_SHARED)
                used_strings = decode_value (p, &p);
@@ -802,6 +927,8 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
                                }
                                case MONO_WRAPPER_LDFLD:
                                case MONO_WRAPPER_STFLD:
+                               case MONO_WRAPPER_LDFLD_REMOTE:
+                               case MONO_WRAPPER_STFLD_REMOTE:
                                case MONO_WRAPPER_ISINST: {
                                        MonoClass *klass = decode_klass_info (aot_module, p, &p);
                                        if (!klass)
@@ -811,6 +938,8 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
                                                ji->data.method = mono_marshal_get_ldfld_wrapper (&klass->byval_arg);
                                        else if (wrapper_type == MONO_WRAPPER_STFLD)
                                                ji->data.method = mono_marshal_get_stfld_wrapper (&klass->byval_arg);
+                                       else if (wrapper_type == MONO_WRAPPER_LDFLD_REMOTE)
+                                               ji->data.method = mono_marshal_get_ldfld_remote_wrapper (klass);
                                        else
                                                ji->data.method = mono_marshal_get_isinst (klass);
                                        break;
@@ -833,7 +962,6 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
                        case MONO_PATCH_INFO_INTERNAL_METHOD:
                                ji->data.name = aot_module->icall_table [decode_value (p, &p)];
                                g_assert (ji->data.name);
-                               //printf ("A: %s.\n", ji->data.name);
                                break;
                        case MONO_PATCH_INFO_SWITCH:
                                ji->data.table = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoBBTable));
@@ -843,17 +971,19 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
                                for (i = 0; i < ji->data.table->table_size; i++)
                                        table [i] = (gpointer)(gssize)decode_value (p, &p);
                                break;
-                       case MONO_PATCH_INFO_R4:
-                               ji->data.target = mono_mempool_alloc0 (mp, sizeof (float));
+                       case MONO_PATCH_INFO_R4: {
                                guint32 val;
 
+                               ji->data.target = mono_mempool_alloc0 (mp, sizeof (float));
                                val = decode_value (p, &p);
                                *(float*)ji->data.target = *(float*)&val;
                                break;
+                       }
                        case MONO_PATCH_INFO_R8: {
-                               ji->data.target = mono_mempool_alloc0 (mp, sizeof (double));
                                guint32 val [2];
 
+                               ji->data.target = mono_mempool_alloc0 (mp, sizeof (double));
+
                                val [0] = decode_value (p, &p);
                                val [1] = decode_value (p, &p);
                                *(double*)ji->data.target = *(double*)val;
@@ -865,6 +995,7 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
                                        goto cleanup;
                                ji->data.token = mono_jump_info_token_new (mp, image, MONO_TOKEN_STRING + decode_value (p, &p));
                                break;
+                       case MONO_PATCH_INFO_DECLSEC:
                        case MONO_PATCH_INFO_LDTOKEN:
                        case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
                                image = load_image (aot_module, decode_value (p, &p));
@@ -945,9 +1076,6 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
                jinfo->domain_neutral = (aot_module->opts & MONO_OPT_SHARED) != 0;
 #endif
 
-               minfo->info = jinfo;
-               g_hash_table_insert (aot_module->methods, method, minfo);
-
                return jinfo;
        }
 
@@ -1044,9 +1172,9 @@ emit_global (FILE *fp, const char *name, gboolean func)
 {
 #if defined(__ppc__) && defined(__MACH__)
     // mach-o always uses a '_' prefix.
-       fprintf (fp, ".globl _%s\n", name);
+       fprintf (fp, "\t.globl _%s\n", name);
 #else
-       fprintf (fp, ".globl %s\n", name);
+       fprintf (fp, "\t.globl %s\n", name);
 #endif
 
        emit_symbol_type (fp, name, func);
@@ -1207,6 +1335,18 @@ encode_field_info (MonoAotCompile *cfg, MonoClassField *field, char *buf, char *
        *endbuf = buf;
 }
 
+static void
+encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, char *buf, char **endbuf)
+{
+       guint32 image_index = get_image_index (acfg, method->klass->image);
+       guint32 token = method->token;
+       g_assert (image_index < 256);
+       g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
+
+       encode_value ((image_index << 24) + (mono_metadata_token_index (token)), buf, &buf);
+       *endbuf = buf;
+}
+
 static gint
 compare_patches (gconstpointer a, gconstpointer b)
 {
@@ -1229,7 +1369,7 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
 {
        MonoMethod *method;
        FILE *tmpfp;
-       int i, j, pindex;
+       int i, j, pindex, byte_index;
        guint8 *code, *mname, *mname_p;
        int func_alignment = 16;
        GPtrArray *patches;
@@ -1244,17 +1384,17 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
        code = cfg->native_code;
        header = mono_method_get_header (method);
 
-       emit_section_change (tmpfp, ".text", 0);
-
        /* Make the labels local */
        mname = g_strdup_printf (".Lm_%x", mono_metadata_token_index (method->token));
        mname_p = g_strdup_printf ("%s_p", mname);
 
        emit_alignment(tmpfp, func_alignment);
        emit_label(tmpfp, mname);
+       if (acfg->aot_opts.write_symbols)
+               emit_global (tmpfp, mname, TRUE);
 
        if (cfg->verbose_level > 0)
-               g_print ("Emitted as %s\n", mname);
+               g_print ("Method %s emitted as %s\n", mono_method_full_name (method, TRUE), mname);
 
        /* Sort relocations */
        patches = g_ptr_array_new ();
@@ -1264,6 +1404,7 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
 
 #ifdef MONO_ARCH_HAVE_PIC_AOT
        acfg->method_got_offsets [mono_metadata_token_index (method->token)] = acfg->got_offset;
+       byte_index = 0;
        for (i = 0; i < cfg->code_len; i++) {
                patch_info = NULL;
                for (pindex = 0; pindex < patches->len; ++pindex) {
@@ -1281,9 +1422,10 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
                                break;
                        case MONO_PATCH_INFO_GOT_OFFSET: {
                                guint32 offset = mono_arch_get_patch_offset (code + i);
+                               fprintf (tmpfp, "\n.byte ");
                                for (j = 0; j < offset; ++j)
-                                       fprintf (tmpfp, ".byte 0x%x\n", (unsigned int) code [i + j]);
-                               fprintf (tmpfp, ".int got - . + %d\n", offset);
+                                       fprintf (tmpfp, "%s0x%x", (j == 0) ? "" : ",", (unsigned int) code [i + j]);
+                               fprintf (tmpfp, "\n.int got - . + %d", offset);
 
                                i += offset + 4 - 1;
                                skip = TRUE;
@@ -1293,12 +1435,13 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
                                if (!is_got_patch (patch_info->type))
                                        break;
 
+                               fprintf (tmpfp, "\n.byte ");
                                for (j = 0; j < mono_arch_get_patch_offset (code + i); ++j)
-                                       fprintf (tmpfp, ".byte 0x%x\n", (unsigned int) code [i + j]);
+                                       fprintf (tmpfp, "%s0x%x", (j == 0) ? "" : ",", (unsigned int) code [i + j]);
 #ifdef __x86_64__
-                               fprintf (tmpfp, ".int got - . + %d\n", (unsigned int) ((acfg->got_offset * sizeof (gpointer)) - 4));
+                               fprintf (tmpfp, "\n.int got - . + %d", (unsigned int) ((acfg->got_offset * sizeof (gpointer)) - 4));
 #elif defined(__i386__)
-                               fprintf (tmpfp, ".int %d\n", (unsigned int) ((acfg->got_offset * sizeof (gpointer))));
+                               fprintf (tmpfp, "\n.int %d\n", (unsigned int) ((acfg->got_offset * sizeof (gpointer))));
 #endif
                                acfg->got_offset ++;
 
@@ -1307,14 +1450,21 @@ emit_method_code (MonoAotCompile *acfg, MonoCompile *cfg)
                        }
                }
 
-               if (!skip)
-                       fprintf (tmpfp, ".byte 0x%x\n", (unsigned int) code [i]);
+               if (!skip) {
+                       if (byte_index == 0)
+                               fprintf (tmpfp, "\n.byte ");
+                       fprintf (tmpfp, "%s0x%x", (byte_index == 0) ? "" : ",", (unsigned int) code [i]);
+                       byte_index = (byte_index + 1) % 32;
+               }
+               else
+                       byte_index = 0;
        }
 #else
        for (i = 0; i < cfg->code_len; i++) {
                fprintf (tmpfp, ".byte 0x%x\n", (unsigned int) code [i]);
        }
 #endif
+       fprintf (tmpfp, "\n");
 }
 
 static void
@@ -1341,8 +1491,6 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
        code = cfg->native_code;
        header = mono_method_get_header (method);
 
-       emit_section_change (tmpfp, ".text", 0);
-
        /* Make the labels local */
        mname = g_strdup_printf (".Lm_%x", mono_metadata_token_index (method->token));
        mname_p = g_strdup_printf ("%s_p", mname);
@@ -1368,14 +1516,15 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
        encode_value (cfg->used_int_regs, p, &p);
 
        /* Exception table */
+       encode_value (header->num_clauses ? 1 : 0, p, &p);
        if (header->num_clauses) {
                MonoJitInfo *jinfo = cfg->jit_info;
 
-               encode_value (jinfo->exvar_offset, p, &p);
-
                for (k = 0; k < header->num_clauses; ++k) {
                        MonoJitExceptionInfo *ei = &jinfo->clauses [k];
 
+                       encode_value (ei->exvar_offset, p, &p);
+
                        if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)
                                encode_value ((gint)((guint8*)ei->data.filter - code), p, &p);
 
@@ -1476,15 +1625,9 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
                }
                case MONO_PATCH_INFO_METHODCONST:
                case MONO_PATCH_INFO_METHOD:
-               case MONO_PATCH_INFO_METHOD_JUMP: {
-                       guint32 image_index = get_image_index (acfg, patch_info->data.method->klass->image);
-                       guint32 token = patch_info->data.method->token;
-                       g_assert (image_index < 256);
-                       g_assert (mono_metadata_token_table (token) == MONO_TABLE_METHOD);
-
-                       encode_value ((image_index << 24) + (mono_metadata_token_index (token)), p, &p);
+               case MONO_PATCH_INFO_METHOD_JUMP:
+                       encode_method_ref (acfg, patch_info->data.method, p, &p);
                        break;
-               }
                case MONO_PATCH_INFO_INTERNAL_METHOD: {
                        guint32 icall_index;
 
@@ -1510,6 +1653,7 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
                        encode_value (patch_info->data.token->token - MONO_TOKEN_STRING, p, &p);
                        break;
                }
+               case MONO_PATCH_INFO_DECLSEC:
                case MONO_PATCH_INFO_LDTOKEN:
                case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
                        encode_value (get_image_index (acfg, patch_info->data.token->image), p, &p);
@@ -1563,6 +1707,8 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
                        case MONO_WRAPPER_PROXY_ISINST:
                        case MONO_WRAPPER_LDFLD:
                        case MONO_WRAPPER_STFLD:
+                       case MONO_WRAPPER_LDFLD_REMOTE:
+                       case MONO_WRAPPER_STFLD_REMOTE:
                        case MONO_WRAPPER_ISINST: {
                                MonoClass *proxy_class = (MonoClass*)mono_marshal_method_from_wrapper (patch_info->data.method);
                                encode_klass_info (acfg, proxy_class, p, &p);
@@ -1592,18 +1738,75 @@ emit_method_info (MonoAotCompile *acfg, MonoCompile *cfg)
 
        /* Emit method info */
 
-       emit_section_change (tmpfp, ".text", 1);
        emit_label (tmpfp, mname_p);
 
        g_assert (p - buf < buf_size);
-       for (i = 0; i < p - buf; ++i)
-               fprintf (tmpfp, ".byte %d\n", (unsigned int) buf [i]);  
+       for (i = 0; i < p - buf; ++i) {
+               if ((i % 32) == 0)
+                       fprintf (tmpfp, "\n.byte ");
+               fprintf (tmpfp, "%s%d", ((i % 32) == 0) ? "" : ",", (unsigned int) buf [i]);
+       }
+       fprintf (tmpfp, "\n");
        g_free (buf);
 
        g_free (mname);
        g_free (mname_p);
 }
 
+static void
+emit_klass_info (MonoAotCompile *acfg, guint32 token)
+{
+       MonoClass *klass = mono_class_get (acfg->image, token);
+       char *p, *buf;
+       int i, buf_size;
+       char *label;
+       FILE *tmpfp = acfg->fp;
+
+       buf_size = 10240;
+       p = buf = g_malloc (buf_size);
+
+       g_assert (klass);
+
+       mono_class_init (klass);
+
+       /* 
+        * Emit all the information which is required for creating vtables so
+        * the runtime does not need to create the MonoMethod structures which
+        * take up a lot of space.
+        */
+
+       if (!MONO_CLASS_IS_INTERFACE (klass)) {
+               encode_value (klass->vtable_size, p, &p);
+               encode_value ((klass->has_cctor << 2) | (klass->has_finalize << 1) | klass->ghcimpl, p, &p);
+               if (klass->has_cctor)
+                       encode_method_ref (acfg, mono_class_get_cctor (klass), p, &p);
+               if (klass->has_finalize)
+                       encode_method_ref (acfg, mono_class_get_finalizer (klass), p, &p);
+
+               for (i = 0; i < klass->vtable_size; ++i) {
+                       MonoMethod *cm = klass->vtable [i];
+
+                       if (cm)
+                               encode_method_ref (acfg, cm, p, &p);
+                       else
+                               encode_value (0, p, &p);
+               }
+       }
+
+       /* Emit the info */
+       label = g_strdup_printf (".LK_I_%x", token - MONO_TOKEN_TYPE_DEF - 1);
+       emit_label (tmpfp, label);
+
+       g_assert (p - buf < buf_size);
+       for (i = 0; i < p - buf; ++i) {
+               if ((i % 32) == 0)
+                       fprintf (tmpfp, "\n.byte ");
+               fprintf (tmpfp, "%s%d", ((i % 32) == 0) ? "" : ",", (unsigned int) buf [i]);
+       }
+       fprintf (tmpfp, "\n");
+       g_free (buf);
+}
+
 static gboolean
 str_begins_with (const char *str1, const char *str2)
 {
@@ -1624,8 +1827,11 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
 
                if (str_begins_with (arg, "outfile=")) {
                        opts->outfile = g_strdup (arg + strlen ("outfile="));
-               }
-               else {
+               } else if (str_begins_with (arg, "save-temps")) {
+                       opts->save_temps = TRUE;
+               } else if (str_begins_with (arg, "write-symbols")) {
+                       opts->write_symbols = TRUE;
+               } else {
                        fprintf (stderr, "AOT : Unknown argument '%s'.\n", arg);
                        exit (1);
                }
@@ -1643,29 +1849,25 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        int i;
        guint8 *symbol;
        int ccount = 0, mcount = 0, lmfcount = 0, abscount = 0, wrappercount = 0, ocount = 0;
-       GHashTable *ref_hash;
        MonoAotCompile *acfg;
        MonoCompile **cfgs;
-       MonoAotOptions aot_opts;
        char *outfile_name, *tmp_outfile_name;
 
        printf ("Mono Ahead of Time compiler - compiling assembly %s\n", image->name);
 
-       mono_aot_parse_options (aot_options, &aot_opts);
-
-       i = g_file_open_tmp ("mono_aot_XXXXXX", &tmpfname, NULL);
-       tmpfp = fdopen (i, "w+");
-       g_assert (tmpfp);
-
-       ref_hash = g_hash_table_new (NULL, NULL);
-
        acfg = g_new0 (MonoAotCompile, 1);
-       acfg->fp = tmpfp;
-       acfg->ref_hash = ref_hash;
        acfg->icall_hash = g_hash_table_new (NULL, NULL);
        acfg->icall_table = g_ptr_array_new ();
        acfg->image_hash = g_hash_table_new (NULL, NULL);
        acfg->image_table = g_ptr_array_new ();
+       acfg->image = image;
+
+       mono_aot_parse_options (aot_options, &acfg->aot_opts);
+
+       i = g_file_open_tmp ("mono_aot_XXXXXX", &tmpfname, NULL);
+       tmpfp = fdopen (i, "w+");
+       acfg->fp = tmpfp;
+       g_assert (tmpfp);
 
        emit_string_symbol (tmpfp, "mono_assembly_guid" , image->guid);
 
@@ -1727,7 +1929,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                g_assert (cfg);
 
                if (cfg->disable_aot) {
-                       printf ("Skip (other): %s\n", mono_method_full_name (method, TRUE));
+                       //printf ("Skip (other): %s\n", mono_method_full_name (method, TRUE));
                        ocount++;
                        continue;
                }
@@ -1761,6 +1963,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                                case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK:
                                case MONO_WRAPPER_STFLD:
                                case MONO_WRAPPER_LDFLD:
+                               case MONO_WRAPPER_LDFLD_REMOTE:
+                               case MONO_WRAPPER_STFLD_REMOTE:
                                case MONO_WRAPPER_STELEMREF:
                                case MONO_WRAPPER_ISINST:
                                case MONO_WRAPPER_PROXY_ISINST:
@@ -1817,17 +2021,50 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        }
 
        /* Emit code */
+       emit_section_change (tmpfp, ".text", 0);
        for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
                if (cfgs [i])
                        emit_method_code (acfg, cfgs [i]);
        }
 
        /* Emit method info */
+       emit_section_change (tmpfp, ".text", 1);
        for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
                if (cfgs [i])
                        emit_method_info (acfg, cfgs [i]);
        }
 
+       /* Emit class info */
+
+       symbol = g_strdup_printf ("class_infos");
+       emit_section_change (tmpfp, ".text", 1);
+       emit_global (tmpfp, symbol, FALSE);
+       emit_alignment (tmpfp, 8);
+       emit_label (tmpfp, symbol);
+
+       for (i = 0; i < image->tables [MONO_TABLE_TYPEDEF].rows; ++i)
+               emit_klass_info (acfg, MONO_TOKEN_TYPE_DEF | (i + 1));
+
+       symbol = g_strdup_printf ("class_info_offsets");
+       emit_section_change (tmpfp, ".text", 1);
+       emit_global (tmpfp, symbol, FALSE);
+       emit_alignment (tmpfp, 8);
+       emit_label(tmpfp, symbol);
+
+       for (i = 0; i < image->tables [MONO_TABLE_TYPEDEF].rows; ++i) {
+               const char *sep;
+               if ((i % 32) == 0) {
+                       fprintf (tmpfp, "\n.long ");
+                       sep = "";
+               }
+               else
+                       sep = ",";
+
+               symbol = g_strdup_printf (".LK_I_%x", i);
+               fprintf (tmpfp, "%s%s - class_infos", sep, symbol);
+       }
+       fprintf (tmpfp, "\n");
+
        /*
         * The icall and image tables are small but referenced in a lot of places.
         * So we emit them at once, and reference their elements by an index.
@@ -1899,7 +2136,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        emit_global (tmpfp, symbol, FALSE);
        emit_alignment (tmpfp, 8);
        emit_label(tmpfp, symbol);
-       fprintf (tmpfp, ".long %d\n", acfg->got_offset * sizeof (gpointer));
+       fprintf (tmpfp, ".long %d\n", (int)(acfg->got_offset * sizeof (gpointer)));
 #endif
 
        symbol = g_strdup_printf ("method_offsets");
@@ -1909,13 +2146,21 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        emit_label(tmpfp, symbol);
 
        for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+               const char *sep;
+               if ((i % 32) == 0) {
+                       fprintf (tmpfp, "\n.long ");
+                       sep = "";
+               }
+               else
+                       sep = ",";
                if (cfgs [i]) {
                        symbol = g_strdup_printf (".Lm_%x", i + 1);
-                       fprintf (tmpfp, ".long %s - methods\n", symbol);
+                       fprintf (tmpfp, "%s%s-methods", sep, symbol);
                }
                else
-                       fprintf (tmpfp, ".long 0xffffffff\n");
+                       fprintf (tmpfp, "%s0xffffffff", sep);
        }
+       fprintf (tmpfp, "\n");
 
        symbol = g_strdup_printf ("method_info_offsets");
        emit_section_change (tmpfp, ".text", 1);
@@ -1924,13 +2169,21 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        emit_label(tmpfp, symbol);
 
        for (i = 0; i < image->tables [MONO_TABLE_METHOD].rows; ++i) {
+               const char *sep;
+               if ((i % 32) == 0) {
+                       fprintf (tmpfp, "\n.long ");
+                       sep = "";
+               }
+               else
+                       sep = ",";
                if (cfgs [i]) {
                        symbol = g_strdup_printf (".Lm_%x_p", i + 1);
-                       fprintf (tmpfp, ".long %s - method_infos\n", symbol);
+                       fprintf (tmpfp, "%s%s - method_infos", sep, symbol);
                }
                else
-                       fprintf (tmpfp, ".long 0\n");
+                       fprintf (tmpfp, "%s0", sep);
        }
+       fprintf (tmpfp, "\n");
 
        fclose (tmpfp);
 
@@ -1949,8 +2202,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        g_free (com);
 
-       if (aot_opts.outfile)
-               outfile_name = g_strdup_printf ("%s", aot_opts.outfile);
+       if (acfg->aot_opts.outfile)
+               outfile_name = g_strdup_printf ("%s", acfg->aot_opts.outfile);
        else
                outfile_name = g_strdup_printf ("%s%s", image->name, SHARED_EXT);
 
@@ -1990,8 +2243,10 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        printf ("%d methods contain wrapper references (%d%%)\n", wrappercount, mcount ? (wrappercount*100)/mcount : 100);
        printf ("%d methods contain lmf pointers (%d%%)\n", lmfcount, mcount ? (lmfcount*100)/mcount : 100);
        printf ("%d methods have other problems (%d%%)\n", ocount, mcount ? (ocount*100)/mcount : 100);
-       //printf ("Retained input file.\n");
-       unlink (tmpfname);
+       if (acfg->aot_opts.save_temps)
+               printf ("Retained input file.\n");
+       else
+               unlink (tmpfname);
 
        return 0;
 }