X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Faot.c;h=2850065c92558d0671c69220006923ddd8e58704;hb=517f581ae811a973c6221234e85ba455384c315a;hp=5acfd50c3d0e0652b3b43d5dac6cec0f020b512f;hpb=db763a2dc35efb08819b0c0eddd8b7dcd634208e;p=mono.git diff --git a/mono/mini/aot.c b/mono/mini/aot.c index 5acfd50c3d0..2850065c925 100644 --- a/mono/mini/aot.c +++ b/mono/mini/aot.c @@ -57,18 +57,10 @@ #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; }