{
MonoMethodSignature *sig;
MonoClass *klass;
- int i;
+ int i, hindex;
int hashes_count;
guint32 *hashes_start, *hashes;
guint32 a, b, c;
+ MonoGenericInst *ginst = NULL;
/* Similar to the hash in mono_method_get_imt_slot () */
sig = mono_method_signature (method);
- hashes_count = sig->param_count + 5;
- hashes_start = malloc (hashes_count * sizeof (guint32));
+ if (method->is_inflated)
+ ginst = ((MonoMethodInflated*)method)->context.method_inst;
+
+ hashes_count = sig->param_count + 5 + (ginst ? ginst->type_argc : 0);
+ hashes_start = g_malloc0 (hashes_count * sizeof (guint32));
hashes = hashes_start;
/* Some wrappers are assigned to random classes */
hashes [2] = mono_metadata_str_hash (method->name);
hashes [3] = method->wrapper_type;
hashes [4] = mono_aot_type_hash (sig->ret);
+ hindex = 5;
for (i = 0; i < sig->param_count; i++) {
- hashes [5 + i] = mono_aot_type_hash (sig->params [i]);
+ hashes [hindex ++] = mono_aot_type_hash (sig->params [i]);
}
-
+ if (ginst) {
+ for (i = 0; i < ginst->type_argc; ++i)
+ hashes [hindex ++] = mono_aot_type_hash (ginst->type_argv [i]);
+ }
+ g_assert (hindex == hashes_count);
+
/* Setup internal state */
a = b = c = 0xdeadbeef + (((guint32)hashes_count)<<2);
}
/*
- * can_method_ref_match_method:
- *
- * Determine if calling decode_resolve_method_ref on P could return the same method as
- * METHOD. This is an optimization to avoid calling decode_resolve_method_ref () which
- * would create MonoMethods which are not needed etc.
- */
-static gboolean
-can_method_ref_match_method (MonoAotModule *module, guint8 *buf, MonoMethod *method)
-{
- guint8 *p = buf;
- guint32 image_index, value;
-
- /* Keep this in sync with decode_method_ref () */
- value = decode_value (p, &p);
- image_index = value >> 24;
-
- if (image_index == MONO_AOT_METHODREF_WRAPPER) {
- guint32 wrapper_type;
-
- if (!method->wrapper_type)
- return FALSE;
-
- wrapper_type = decode_value (p, &p);
-
- if (method->wrapper_type != wrapper_type)
- return FALSE;
- } else if (image_index == MONO_AOT_METHODREF_WRAPPER_NAME) {
- return FALSE;
- } else if (image_index < MONO_AOT_METHODREF_MIN || image_index == MONO_AOT_METHODREF_METHODSPEC || image_index == MONO_AOT_METHODREF_GINST) {
- if (method->wrapper_type)
- return FALSE;
- }
-
- return TRUE;
-}
-
-/*
- * decode_method_ref:
+ * decode_method_ref_with_target:
*
* Decode a method reference, and return its image and token. This avoids loading
* metadata for the method if the caller does not need it. If the method has no token,
- * then it is loaded from metadata and METHOD is set to the method instance.
+ * then it is loaded from metadata and METHOD is set to the method instance. If TARGET is non-NULL,
+ * abort decoding if it can be determined that the decoded method couldn't resolve to it, and
+ * return NULL.
*/
static MonoImage*
-decode_method_ref (MonoAotModule *module, guint32 *token, MonoMethod **method, gboolean *no_aot_trampoline, guint8 *buf, guint8 **endbuf)
+decode_method_ref_with_target (MonoAotModule *module, guint32 *token, MonoMethod **method, MonoMethod *target, gboolean *no_aot_trampoline, guint8 *buf, guint8 **endbuf)
{
guint32 image_index, value;
MonoImage *image = NULL;
image_index = value >> 24;
}
+ if (image_index < MONO_AOT_METHODREF_MIN || image_index == MONO_AOT_METHODREF_METHODSPEC || image_index == MONO_AOT_METHODREF_GINST) {
+ if (target && target->wrapper_type)
+ return NULL;
+ }
+
if (image_index == MONO_AOT_METHODREF_WRAPPER) {
guint32 wrapper_type;
wrapper_type = decode_value (p, &p);
+ if (target && target->wrapper_type != wrapper_type)
+ return NULL;
+
/* Doesn't matter */
image = mono_defaults.corlib;
g_assert_not_reached ();
}
} else if (image_index == MONO_AOT_METHODREF_WRAPPER_NAME) {
+ if (target)
+ return NULL;
/* Can't decode these */
g_assert_not_reached ();
} else if (image_index == MONO_AOT_METHODREF_METHODSPEC) {
if (!klass)
return NULL;
+ if (target && target->klass != klass)
+ return NULL;
+
image_index = decode_value (p, &p);
*token = decode_value (p, &p);
return image;
}
+static MonoImage*
+decode_method_ref (MonoAotModule *module, guint32 *token, MonoMethod **method, gboolean *no_aot_trampoline, guint8 *buf, guint8 **endbuf)
+{
+ return decode_method_ref_with_target (module, token, method, NULL, no_aot_trampoline, buf, endbuf);
+}
+
/*
- * decode_resolve_method_ref:
+ * decode_resolve_method_ref_with_target:
*
* Similar to decode_method_ref, but resolve and return the method itself.
*/
static MonoMethod*
-decode_resolve_method_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
+decode_resolve_method_ref_with_target (MonoAotModule *module, MonoMethod *target, guint8 *buf, guint8 **endbuf)
{
MonoMethod *method;
guint32 token;
- MonoImage *image = decode_method_ref (module, &token, &method, NULL, buf, endbuf);
+ MonoImage *image = decode_method_ref_with_target (module, &token, &method, target, NULL, buf, endbuf);
if (method)
return method;
return method;
}
+static MonoMethod*
+decode_resolve_method_ref (MonoAotModule *module, guint8 *buf, guint8 **endbuf)
+{
+ return decode_resolve_method_ref_with_target (module, NULL, buf, endbuf);
+}
+
static void
create_cache_structure (void)
{
index = value;
break;
}
- } else if (can_method_ref_match_method (amodule, p, method)) {
+ } else {
+ guint8 *orig_p = p;
+
mono_aot_lock ();
if (!amodule->method_ref_to_method)
amodule->method_ref_to_method = g_hash_table_new (NULL, NULL);
m = g_hash_table_lookup (amodule->method_ref_to_method, p);
mono_aot_unlock ();
if (!m) {
- guint8 *orig_p = p;
- m = decode_resolve_method_ref (amodule, p, &p);
+ m = decode_resolve_method_ref_with_target (amodule, method, p, &p);
if (m) {
mono_aot_lock ();
g_hash_table_insert (amodule->method_ref_to_method, orig_p, m);
}
/* Methods decoded needlessly */
- /*
- if (m)
- printf ("%d %s %s\n", n_extra_decodes, mono_method_full_name (method, TRUE), mono_method_full_name (m, TRUE));
- */
- n_extra_decodes ++;
+ if (m) {
+ //printf ("%d %s %s %p\n", n_extra_decodes, mono_method_full_name (method, TRUE), mono_method_full_name (m, TRUE), orig_p);
+ n_extra_decodes ++;
+ }
}
if (next != 0)