2008-10-18 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Sat, 18 Oct 2008 19:17:35 +0000 (19:17 -0000)
committerZoltan Varga <vargaz@gmail.com>
Sat, 18 Oct 2008 19:17:35 +0000 (19:17 -0000)
* method-to-ir.c (mono_method_to_ir2): Change a !compile_aot assert to
disable_aot.

* mini.c (mono_patch_info_equal): Compare the generic context as well.

* mini.h: Bump aot file format version.

* aot-compiler.c aot-runtime.c: Generalize the wrapper handling code so the
AOT file can contain native code for methods which are not in the METHOD
table. Generate code for non-sharable generic instances of generic methods
found in the METHODSPEC table.

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

mono/mini/ChangeLog
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/method-to-ir.c
mono/mini/mini.c
mono/mini/mini.h

index d581e76b932a26e3dfa3accfa14963590412b8ea..be61796e0b786c5a5e8dde7f7307396ba6fea4ff 100644 (file)
@@ -1,5 +1,17 @@
 2008-10-18  Zoltan Varga  <vargaz@gmail.com>
 
+       * method-to-ir.c (mono_method_to_ir2): Change a !compile_aot assert to
+       disable_aot.
+
+       * mini.c (mono_patch_info_equal): Compare the generic context as well.
+
+       * mini.h: Bump aot file format version.
+
+       * aot-compiler.c aot-runtime.c: Generalize the wrapper handling code so the
+       AOT file can contain native code for methods which are not in the METHOD
+       table. Generate code for non-sharable generic instances of generic methods
+       found in the METHODSPEC table.
+       
        * method-to-ir.c (mono_method_to_ir2): Remove the aot restriction when
        encoding generic type handles.
 
index 157e1374a0562bff7d970c10de3e73e94d228c5a..8d9324192ae977e27c3950433480a46c9266072b 100644 (file)
@@ -146,6 +146,8 @@ typedef struct MonoAotCompile {
        GHashTable *image_hash;
        GHashTable *method_to_cfg;
        GHashTable *token_info_hash;
+       GPtrArray *extra_methods;
+       GHashTable *extra_methods_hash;
        GPtrArray *image_table;
        GPtrArray *globals;
        GList *method_order;
@@ -2320,6 +2322,43 @@ add_wrappers (MonoAotCompile *acfg)
 #endif
 }
 
+/*
+ * add_methodspecs:
+ *
+ *   Add methods referenced by the METHODSPEC table.
+ */
+static void
+add_methodspecs (MonoAotCompile *acfg)
+{
+       int i;
+       guint32 token;
+       MonoMethod *method;
+       MonoGenericContext *context;
+
+       /* FIXME: Only add instantiations with vtype arguments */
+       for (i = 0; i < acfg->image->tables [MONO_TABLE_METHODSPEC].rows; ++i) {
+               token = MONO_TOKEN_METHOD_SPEC | (i + 1);
+               method = mono_get_method (acfg->image, token, NULL);
+
+               context = mono_method_get_context (method);
+               if (context && ((context->class_inst && context->class_inst->is_open) ||
+                                               (context->method_inst && context->method_inst->is_open)))
+                       continue;
+
+               if (method->klass->image != acfg->image)
+                       continue;
+
+               if (mono_method_is_generic_sharable_impl (method, FALSE))
+                       /* Already added */
+                       continue;
+
+               add_method (acfg, method);
+
+               g_ptr_array_add (acfg->extra_methods, method);
+               g_hash_table_insert (acfg->extra_methods_hash, method, method);
+       }
+}
+
 static void
 emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, guint32 code_len, MonoJumpInfo *relocs, gboolean got_only)
 {
@@ -2383,8 +2422,20 @@ emit_and_reloc_code (MonoAotCompile *acfg, MonoMethod *method, guint8 *code, gui
                                if (!got_only && (patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == method->klass->image)) {
                                        MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
                                        if (callee_cfg) {
-                                               if (!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)) {
-                                                       //printf ("DIRECT: %s %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (callee_cfg->method, TRUE));
+                                               gboolean direct_callable = TRUE;
+
+                                               if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
+                                                       direct_callable = FALSE;
+                                               /* 
+                                                * FIXME: mono_aot_find_jit_info () needs to construct the 
+                                                * MonoMethod belonging to a piece of code, and it can't
+                                                * do it for generic instances.
+                                                */
+                                               if (direct_callable && callee_cfg->method->is_inflated && g_hash_table_lookup (acfg->extra_methods_hash, callee_cfg->method))
+                                                       direct_callable = FALSE;
+                                               
+                                               if (direct_callable) {
+                                                       printf ("DIRECT: %s %s\n", method ? mono_method_full_name (method, TRUE) : "", mono_method_full_name (callee_cfg->method, TRUE));
                                                        direct_call_target = g_strdup_printf (".Lm_%x", get_method_index (acfg, callee_cfg->orig_method));
                                                        patch_info->type = MONO_PATCH_INFO_NONE;
                                                        acfg->stats.direct_calls ++;
@@ -3662,6 +3713,11 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)
 
        g_hash_table_insert (acfg->method_to_cfg, cfg->orig_method, cfg);
 
+       if (cfg->orig_method->wrapper_type) {
+               g_ptr_array_add (acfg->extra_methods, cfg->orig_method);
+               g_hash_table_insert (acfg->extra_methods_hash, cfg->orig_method, cfg->orig_method);
+       }
+
        acfg->stats.ccount++;
 }
 
@@ -3851,51 +3907,154 @@ emit_info (MonoAotCompile *acfg)
        }
        emit_line (acfg);
 }
+typedef struct HashEntry {
+    guint32 key, value, index;
+       struct HashEntry *next;
+} HashEntry;
 
+/*
+ * emit_extra_methods:
+ *
+ * Emit methods which are not in the METHOD table, like wrappers.
+ */
 static void
-emit_wrapper_info (MonoAotCompile *acfg)
+emit_extra_methods (MonoAotCompile *acfg)
 {
-       int i, index;
+       int i, table_size, buf_size;
        char *symbol;
-       char *name;
+       guint8 *p, *buf;
+       guint32 *info_offsets;
+       guint32 hash;
+       GPtrArray *table;
+       HashEntry *entry, *new_entry;
+       int nmethods;
+
+       info_offsets = g_new0 (guint32, acfg->nmethods);
+
+       buf_size = acfg->extra_methods->len * 256 + 256;
+       p = buf = g_malloc (buf_size);
+
+       /* Encode method info */
+       nmethods = 0;
+       /* So offsets are > 0 */
+       p++;
+       for (i = 0; i < acfg->extra_methods->len; ++i) {
+               MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
+               MonoCompile *cfg = g_hash_table_lookup (acfg->method_to_cfg, method);
+
+               if (!cfg)
+                       continue;
+
+               nmethods ++;
+               info_offsets [i] = p - buf;
+
+               if (method->wrapper_type) {
+                       char *name;
+
+                       // FIXME: Optimize disk usage
+                       if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
+                               char *tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
+                               name = g_strdup_printf ("(wrapper runtime-invoke):%s (%s)", method->name, tmpsig);
+                               g_free (tmpsig);
+                       } else {
+                               name = mono_method_full_name (cfg->orig_method, TRUE);
+                       }
+
+                       encode_value (1, p, &p);
+                       strcpy ((char*)p, name);
+                       p += strlen (name ) + 1;
+                       g_free (name);
+               } else {
+                       encode_value (0, p, &p);
+                       encode_method_ref (acfg, method, p, &p);
+               }
+
+               g_assert ((p - buf) < buf_size);
+       }
+
+       g_assert ((p - buf) < buf_size);
 
        /* Emit method info */
-       symbol = g_strdup_printf ("wrapper_info");
+       symbol = g_strdup_printf ("extra_method_info");
        emit_section_change (acfg, ".text", 1);
        emit_global (acfg, symbol, FALSE);
        emit_alignment (acfg, 8);
        emit_label (acfg, symbol);
        g_free (symbol);
 
-       if (!acfg->aot_opts.full_aot)
-               return;
+       emit_bytes (acfg, buf, p - buf);
 
-       for (i = 0; i < acfg->nmethods; ++i) {
-               MonoCompile *cfg = acfg->cfgs [i];
-               MonoMethod *method;
+       emit_line (acfg);
+
+       /*
+        * Construct a chained hash table for mapping indexes in extra_method_info to
+        * method indexes.
+        */
+       table_size = g_spaced_primes_closest ((int)(nmethods * 1.5));
+       table = g_ptr_array_sized_new (table_size);
+       for (i = 0; i < table_size; ++i)
+               g_ptr_array_add (table, NULL);
+       for (i = 0; i < acfg->extra_methods->len; ++i) {
+               MonoMethod *method = g_ptr_array_index (acfg->extra_methods, i);
+               MonoCompile *cfg = g_hash_table_lookup (acfg->method_to_cfg, method);
+               guint32 key, value;
 
-               if (!cfg || !cfg->orig_method->wrapper_type)
+               if (!cfg)
                        continue;
 
-               method = cfg->orig_method;
-               index = get_method_index (acfg, method);
+               key = info_offsets [i];
+               value = get_method_index (acfg, method);
+               // FIXME:
+               hash = 0 % table_size;
+
+               /* FIXME: Allocate from the mempool */
+               new_entry = g_new0 (HashEntry, 1);
+               new_entry->key = key;
+               new_entry->value = value;
 
-               // FIXME: Optimize disk usage and lookup speed
-               if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
-                       char *tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
-                       name = g_strdup_printf ("(wrapper runtime-invoke):%s (%s)", method->name, tmpsig);
-                       g_free (tmpsig);
+               entry = g_ptr_array_index (table, hash);
+               if (entry == NULL) {
+                       new_entry->index = hash;
+                       g_ptr_array_index (table, hash) = new_entry;
                } else {
-                       name = mono_method_full_name (cfg->orig_method, TRUE);
+                       while (entry->next)
+                               entry = entry->next;
+                       
+                       entry->next = new_entry;
+                       new_entry->index = table->len;
+                       g_ptr_array_add (table, new_entry);
                }
-               emit_string (acfg, name);
-               emit_alignment (acfg, 4);
-               emit_int32 (acfg, index);
        }
 
-       emit_byte (acfg, 0);
+       /* Emit the table */
+       symbol = g_strdup_printf ("extra_method_table");
+       emit_section_change (acfg, ".text", 0);
+       emit_global (acfg, symbol, FALSE);
+       emit_alignment (acfg, 8);
+       emit_label (acfg, symbol);
+       g_free (symbol);
 
-       emit_line (acfg);
+       g_assert (table_size < 65000);
+       emit_int32 (acfg, table_size);
+       g_assert (table->len < 65000);
+       for (i = 0; i < table->len; ++i) {
+               HashEntry *entry = g_ptr_array_index (table, i);
+
+               if (entry == NULL) {
+                       emit_int32 (acfg, 0);
+                       emit_int32 (acfg, 0);
+                       emit_int32 (acfg, 0);
+               } else {
+                       g_assert (entry->key > 0);
+                       emit_int32 (acfg, entry->key);
+                       emit_int32 (acfg, entry->value);
+                       if (entry->next)
+                               emit_int32 (acfg, entry->next->index);
+                       else
+                               emit_int32 (acfg, 0);
+               }
+       }
 }      
 
 static void
@@ -4438,6 +4597,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        acfg->image = image;
        acfg->opts = opts;
        acfg->mempool = mono_mempool_new ();
+       acfg->extra_methods = g_ptr_array_new ();
+       acfg->extra_methods_hash = g_hash_table_new (NULL, NULL);
 
        mono_aot_parse_options (aot_options, &acfg->aot_opts);
 
@@ -4468,6 +4629,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
                acfg->method_index ++;
        }
 
+       add_methodspecs (acfg);
+
        if (acfg->aot_opts.full_aot)
                add_wrappers (acfg);
 
@@ -4489,7 +4652,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 
        emit_info (acfg);
 
-       emit_wrapper_info (acfg);
+       emit_extra_methods (acfg);
 
        emit_method_order (acfg);
 
index 2452e1e0e76a550a33b5025d8522a8d7aa072f38..7ad4d35051df55015e79ef1ecf5b7e7e0236d255 100644 (file)
@@ -74,11 +74,9 @@ typedef struct MonoAotModule {
        gpointer *got;
        guint32 got_size;
        GHashTable *name_cache;
-       GHashTable *wrappers;
-       /* Maps wrapper names to their method index */
-       GHashTable *wrappers_by_name;
-       /* Maps wrapper methods to their code */
-       GHashTable *wrappers_to_code;
+       GHashTable *extra_methods;
+       /* Maps methods to their code */
+       GHashTable *method_to_code;
        MonoAssemblyName *image_names;
        char **image_guids;
        MonoAssembly *assembly;
@@ -108,7 +106,8 @@ typedef struct MonoAotModule {
        guint32 *class_info_offsets;
        guint32 *methods_loaded;
        guint16 *class_name_table;
-       guint8 *wrapper_info;
+       guint32 *extra_method_table;
+       guint8 *extra_method_info;
        guint8 *trampolines;
        guint32 num_trampolines, first_trampoline_got_offset, trampoline_index;
        gpointer *globals;
@@ -917,6 +916,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        amodule->got [0] = assembly->image;
        amodule->globals = globals;
        amodule->sofile = sofile;
+       amodule->method_to_code = g_hash_table_new (mono_aligned_addr_hash, NULL);
 
        sscanf (opt_flags, "%d", &amodule->opts);               
 
@@ -974,9 +974,10 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        find_symbol (sofile, globals, "class_info", (gpointer*)&amodule->class_info);
        find_symbol (sofile, globals, "class_info_offsets", (gpointer*)&amodule->class_info_offsets);
        find_symbol (sofile, globals, "class_name_table", (gpointer *)&amodule->class_name_table);
+       find_symbol (sofile, globals, "extra_method_table", (gpointer *)&amodule->extra_method_table);
+       find_symbol (sofile, globals, "extra_method_info", (gpointer *)&amodule->extra_method_info);
        find_symbol (sofile, globals, "got_info", (gpointer*)&amodule->got_info);
        find_symbol (sofile, globals, "got_info_offsets", (gpointer*)&amodule->got_info_offsets);
-       find_symbol (sofile, globals, "wrapper_info", (gpointer*)&amodule->wrapper_info);
        find_symbol (sofile, globals, "trampolines", (gpointer*)&amodule->trampolines);
        find_symbol (sofile, globals, "mem_end", (gpointer*)&amodule->mem_end);
 
@@ -1494,16 +1495,23 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
 
        method_index = table [pos];
 
-       /* Might be a wrapper */
-       if (aot_module->wrappers) {
+       /* Might be a wrapper/extra method */
+       if (aot_module->extra_methods) {
                mono_aot_lock ();
-               method = g_hash_table_lookup (aot_module->wrappers, GUINT_TO_POINTER (method_index));
+               method = g_hash_table_lookup (aot_module->extra_methods, GUINT_TO_POINTER (method_index));
                mono_aot_unlock ();
        } else {
                method = NULL;
        }
 
        if (!method) {
+               /* 
+                * This only works for methods which are in the METHOD table, it can't
+                * handle generic instances/wrappers. This is only a problem for direct
+                * calls, since those bypass mono_get_aot_method (), so we can't add the
+                * method to aot_module->extra_methods.
+                */
+               g_assert (method_index < image->tables [MONO_TABLE_METHOD].rows);
                token = mono_metadata_make_token (MONO_TABLE_METHOD, method_index + 1);
                method = mono_get_method (image, token, NULL);
        }
@@ -1826,11 +1834,81 @@ register_jump_target_got_slot (MonoDomain *domain, MonoMethod *method, gpointer
        mono_domain_unlock (domain);
 }
 
+/*
+ * find_extra_method:
+ *
+ *   Try finding METHOD in the extra_method table in the AOT image.
+ * Return its method index, or 0xffffff if not found.
+ */
+static guint32
+find_extra_method (MonoDomain *domain, MonoMethod *method)
+{
+       MonoClass *klass = method->klass;
+       MonoAotModule *aot_module = klass->image->aot_module;
+       guint32 table_size, entry_size, hash;
+       guint32 *table, *entry;
+       char *full_name = NULL;
+
+       if (!aot_module)
+               return 0xffffff;
+
+       table_size = aot_module->extra_method_table [0];
+       table = aot_module->extra_method_table + 1;
+       entry_size = 3;
+
+       if (method->wrapper_type) {
+               /* FIXME: This is a hack to work around the fact that runtime invoke wrappers get assigned to some random class */
+               if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
+                       char *tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
+                       full_name = g_strdup_printf ("(wrapper runtime-invoke):%s (%s)", method->name, tmpsig);
+                       g_free (tmpsig);
+               } else {
+                       full_name = mono_method_full_name (method, TRUE);
+               }
+       }
+
+       // FIXME:
+       hash = 0 % table_size;
+
+       entry = &table [hash * entry_size];
+
+       if (entry [0] != 0) {
+               while (TRUE) {
+                       guint32 key = entry [0];
+                       guint32 value = entry [1];
+                       guint32 next = entry [entry_size - 1];
+                       MonoMethod *m;
+                       guint8 *p;
+                       int is_wrapper;
+
+                       // FIXME: Avoid fully decoding the method ref
+                       p = aot_module->extra_method_info + key;
+                       is_wrapper = decode_value (p, &p);
+                       if (method->wrapper_type && is_wrapper) {
+                               if (!strcmp (full_name, (char*)p))
+                                       return value;
+                       } else {
+                               m = decode_method_ref_2 (aot_module, p, &p);
+                               if (m == method)
+                                       return value;
+                       }
+
+                       if (next != 0) {
+                               entry = &table [next * entry_size];
+                       } else {
+                               break;
+                       }
+               }
+       }
+
+       return 0xffffff;
+}
+
 gpointer
 mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
 {
        MonoClass *klass = method->klass;
-       guint32 method_index = mono_metadata_token_index (method->token) - 1;
+       guint32 method_index;
        guint8 *code, *info;
        MonoAotModule *aot_module = klass->image->aot_module;
 
@@ -1855,71 +1933,31 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
        if (aot_module->out_of_date)
                return NULL;
 
-       if (method->is_inflated) {
-               if (!mono_method_is_generic_sharable_impl (method, FALSE))
-                       return NULL;
+       /* Find method index */
+       if (method->is_inflated && mono_method_is_generic_sharable_impl (method, FALSE)) {
                method = mono_method_get_declaring_generic_method (method);
-       }
-
-       if (!method->token) {
-               char *full_name;
-               char *p;
-
-               if (!method->wrapper_type || !aot_module->wrapper_info)
-                       return NULL;
-
+               method_index = mono_metadata_token_index (method->token) - 1;
+       } else if (method->is_inflated || !method->token) {
+               /* This hash table is used to avoid the slower search in the extra_method_table in the AOT image */
                mono_aot_lock ();
-
-               /* Avoid doing a hash table lookup using strings if possible */
-               if (!aot_module->wrappers_to_code)
-                       aot_module->wrappers_to_code = g_hash_table_new (mono_aligned_addr_hash, NULL);
-               code = g_hash_table_lookup (aot_module->wrappers_to_code, method);
-               if (code) {
-                       mono_aot_unlock ();
-                       return code;
-               }
-
-               /* Try to find the wrapper among the wrapper info */
-               /* FIXME: This is a hack to work around the fact that runtime invoke wrappers get assigned to some random class */
-               if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
-                       char *tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
-                       full_name = g_strdup_printf ("(wrapper runtime-invoke):%s (%s)", method->name, tmpsig);
-                       g_free (tmpsig);
-               } else {
-                       full_name = mono_method_full_name (method, TRUE);
-               }
-
-               /* Create a hash table to avoid repeated linear searches */
-               if (!aot_module->wrappers_by_name) {
-                       aot_module->wrappers_by_name = g_hash_table_new (g_str_hash, g_str_equal);
-                       p = (char*)aot_module->wrapper_info;
-                       while (*p) {
-                               char *end;
-
-                               end = p + strlen (p) + 1;
-                               end = ALIGN_PTR_TO (end, 4);
-                               method_index = *(guint32*)end;
-                               end += 4;
-                               /* The + 1 is used to distinguish a 0 index from a not-found one */
-                               g_hash_table_insert (aot_module->wrappers_by_name, p, GUINT_TO_POINTER (method_index + 1));
-                               p = end;
-                       }
-               }
-               method_index = GPOINTER_TO_UINT (g_hash_table_lookup (aot_module->wrappers_by_name, full_name));
+               code = g_hash_table_lookup (aot_module->method_to_code, method);
                mono_aot_unlock ();
+               if (code)
+                       return code;
 
-               g_free (full_name);
-               if (!method_index)
+               method_index = find_extra_method (domain, method);
+               if (method_index == 0xffffff)
                        return NULL;
 
-               method_index --;
-
                /* Needed by find_jit_info */
                mono_aot_lock ();
-               if (!aot_module->wrappers)
-                       aot_module->wrappers = g_hash_table_new (NULL, NULL);
-               g_hash_table_insert (aot_module->wrappers, GUINT_TO_POINTER (method_index), method);
+               if (!aot_module->extra_methods)
+                       aot_module->extra_methods = g_hash_table_new (NULL, NULL);
+               g_hash_table_insert (aot_module->extra_methods, GUINT_TO_POINTER (method_index), method);
                mono_aot_unlock ();
+       } else {
+               /* Common case */
+               method_index = mono_metadata_token_index (method->token) - 1;
        }
 
        if (aot_module->code_offsets [method_index] == 0xffffffff) {
@@ -2068,7 +2106,7 @@ mono_aot_load_method (MonoDomain *domain, MonoAotModule *aot_module, MonoMethod
        init_plt (aot_module);
 
        if (method->wrapper_type)
-               g_hash_table_insert (aot_module->wrappers_to_code, method, code);
+               g_hash_table_insert (aot_module->method_to_code, method, code);
 
        mono_aot_unlock ();
 
index b10d0cb28346f66ad2ea5ce98a104f9cb17c8ebb..29202c69d7813fee9e631b16a78146c5c976cc66 100644 (file)
@@ -6029,7 +6029,8 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_
                                                        cmethod, MONO_RGCTX_INFO_METHOD_CONTEXT);
 
                                        } else {
-                                               g_assert (!cfg->compile_aot);
+                                               // FIXME:
+                                               cfg->disable_aot = TRUE;
                                                g_assert (cmethod->is_inflated);
                                                EMIT_NEW_PCONST (cfg, imt_arg,
                                                        ((MonoMethodInflated*)cmethod)->context.method_inst);
index 3439ae4fef410e246eb43c04fa90acefefd6ecfe..307a3d8c6d5926f177b2849a3771acf8559813d8 100644 (file)
@@ -11326,7 +11326,10 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
        case MONO_PATCH_INFO_LDTOKEN:
        case MONO_PATCH_INFO_DECLSEC:
                if ((ji1->data.token->image != ji2->data.token->image) ||
-                       (ji1->data.token->token != ji2->data.token->token))
+                       (ji1->data.token->token != ji2->data.token->token) || 
+                       (ji1->data.token->has_context != ji2->data.token->has_context) ||
+                       (ji1->data.token->context.class_inst != ji2->data.token->context.class_inst) ||
+                       (ji1->data.token->context.method_inst != ji2->data.token->context.method_inst))
                        return 0;
                break;
        default:
index f54bbfecdccda8adb9fe47b5fad93ab3a724649b..c2700d8af30daa3c79d83cc92071f8f48f5aee3d 100644 (file)
@@ -66,7 +66,7 @@
 #define MONO_FAKE_VTABLE_METHOD ((MonoMethod*)GINT_TO_POINTER(-2))
 
 /* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION "40"
+#define MONO_AOT_FILE_VERSION "41"
  
 /* Per-domain information maintained by the JIT */
 typedef struct