From 44380df8dcc6f1be76bc16782269025f126c8f55 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 12 Jul 2011 02:47:52 +0200 Subject: [PATCH] Eliminate the by-name encoding for all wrapper methods, instead, encode them directly by encoding signatures etc. using a binary encoding. This saves 30k from the mscorlib AOT image at the cost of some runtime C code. --- mono/mini/aot-compiler.c | 271 ++++++++++++++++++++++++------------ mono/mini/aot-runtime.c | 355 ++++++++++++++++++++++++++++++++++++++--------- mono/mini/mini.h | 28 ++-- 3 files changed, 486 insertions(+), 168 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 7d44184bcd6..7b7f199c293 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -1962,6 +1962,105 @@ encode_generic_context (MonoAotCompile *acfg, MonoGenericContext *context, guint *endbuf = p; } +static void +encode_type (MonoAotCompile *acfg, MonoType *t, guint8 *buf, guint8 **endbuf) +{ + guint8 *p = buf; + + g_assert (t->num_mods == 0); + g_assert (t->attrs == 0); + + if (t->pinned) { + *p = MONO_TYPE_PINNED; + ++p; + } + if (t->byref) { + *p = MONO_TYPE_BYREF; + ++p; + } + + *p = t->type; + p ++; + + switch (t->type) { + case MONO_TYPE_VOID: + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_CHAR: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I8: + case MONO_TYPE_U8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_STRING: + case MONO_TYPE_OBJECT: + case MONO_TYPE_TYPEDBYREF: + break; + case MONO_TYPE_VALUETYPE: + case MONO_TYPE_CLASS: + encode_klass_ref (acfg, mono_class_from_mono_type (t), p, &p); + break; + case MONO_TYPE_SZARRAY: + encode_klass_ref (acfg, t->data.klass, p, &p); + break; + case MONO_TYPE_PTR: + encode_type (acfg, t->data.type, p, &p); + break; + case MONO_TYPE_GENERICINST: { + MonoClass *gclass = t->data.generic_class->container_class; + MonoGenericInst *inst = t->data.generic_class->context.class_inst; + int i; + + encode_klass_ref (acfg, gclass, p, &p); + encode_value (inst->type_argc, p, &p); + for (i = 0; i < inst->type_argc; ++i) + encode_klass_ref (acfg, mono_class_from_mono_type (inst->type_argv [i]), p, &p); + break; + } + default: + g_assert_not_reached (); + } + + *endbuf = p; +} + +static void +encode_signature (MonoAotCompile *acfg, MonoMethodSignature *sig, guint8 *buf, guint8 **endbuf) +{ + guint8 *p = buf; + guint32 flags = 0; + int i; + + /* Similar to the metadata encoding */ + if (sig->generic_param_count) + flags |= 0x10; + if (sig->hasthis) + flags |= 0x20; + if (sig->explicit_this) + flags |= 0x40; + flags |= (sig->call_convention & 0x0F); + + *p = flags; + ++p; + if (sig->generic_param_count) + encode_value (sig->generic_param_count, p, &p); + encode_value (sig->param_count, p, &p); + + g_assert (sig->call_convention != MONO_CALL_VARARG); + + encode_type (acfg, sig->ret, p, &p); + for (i = 0; i < sig->param_count; ++i) + encode_type (acfg, sig->params [i], p, &p); + + *endbuf = p; +} + #define MAX_IMAGE_INDEX 250 static void @@ -1971,7 +2070,6 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 guint32 token = method->token; MonoJumpInfoToken *ji; guint8 *p = buf; - char *name; /* * The encoding for most methods is as follows: @@ -1990,44 +2088,7 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) encode_value ((MONO_AOT_METHODREF_NO_AOT_TRAMPOLINE << 24), p, &p); - /* - * Some wrapper methods are shared using their signature, encode their - * stringified signature instead. - * FIXME: Optimize disk usage - */ - name = NULL; if (method->wrapper_type) { - if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) { - char *tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE); - if (strcmp (method->name, "runtime_invoke_dynamic")) { - name = mono_aot_wrapper_name (method); - } else if (mono_marshal_method_from_wrapper (method) != method) { - /* Direct wrapper, encode it normally */ - } else { - name = g_strdup_printf ("(wrapper runtime-invoke):%s (%s)", method->name, tmpsig); - } - g_free (tmpsig); - } else if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE) { - char *tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE); - name = g_strdup_printf ("(wrapper delegate-invoke):%s (%s)", method->name, tmpsig); - g_free (tmpsig); - } else if (method->wrapper_type == MONO_WRAPPER_DELEGATE_BEGIN_INVOKE) { - char *tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE); - name = g_strdup_printf ("(wrapper delegate-begin-invoke):%s (%s)", method->name, tmpsig); - g_free (tmpsig); - } else if (method->wrapper_type == MONO_WRAPPER_DELEGATE_END_INVOKE) { - char *tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE); - name = g_strdup_printf ("(wrapper delegate-end-invoke):%s (%s)", method->name, tmpsig); - g_free (tmpsig); - } - } - - if (name) { - encode_value ((MONO_AOT_METHODREF_WRAPPER_NAME << 24), p, &p); - strcpy ((char*)p, name); - p += strlen (name) + 1; - g_free (name); - } else if (method->wrapper_type) { encode_value ((MONO_AOT_METHODREF_WRAPPER << 24), p, &p); encode_value (method->wrapper_type, p, &p); @@ -2068,8 +2129,19 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 case MONO_WRAPPER_STELEMREF: { MonoClass *klass = mono_marshal_get_wrapper_info (method); - /* Make sure this is the 'normal' stelemref wrapper, not the virtual one */ - g_assert (!klass); + if (!klass) { + /* Normal wrapper */ + encode_value (0, p, &p); + } else { + char *name; + + /* virtual wrapper */ + name = mono_aot_wrapper_name (method); + encode_value (MONO_AOT_WRAPPER_BY_NAME, p, &p); + strcpy ((char*)p, name); + p += strlen (name) + 1; + g_free (name); + } break; } case MONO_WRAPPER_UNKNOWN: @@ -2089,9 +2161,24 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 g_assert_not_reached (); } break; - case MONO_WRAPPER_SYNCHRONIZED: - case MONO_WRAPPER_MANAGED_TO_NATIVE: - case MONO_WRAPPER_RUNTIME_INVOKE: { + case MONO_WRAPPER_MANAGED_TO_NATIVE: { + MonoMethod *m; + + if (strstr (method->name, "__icall_wrapper")) { + encode_value (MONO_AOT_WRAPPER_JIT_ICALL, p, &p); + + strcpy ((char*)p, method->name); + p += strlen (method->name) + 1; + } else { + encode_value (0, p, &p); + m = mono_marshal_method_from_wrapper (method); + g_assert (m); + g_assert (m != method); + encode_method_ref (acfg, m, p, &p); + } + break; + } + case MONO_WRAPPER_SYNCHRONIZED: { MonoMethod *m; m = mono_marshal_method_from_wrapper (method); @@ -2104,12 +2191,19 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 if (!strcmp (method->name, "ElementAddr")) { ElementAddrWrapperInfo *info = mono_marshal_get_wrapper_info (method); + printf ("X: %d\n", info->rank); g_assert (info); encode_value (MONO_AOT_WRAPPER_ELEMENT_ADDR, p, &p); encode_value (info->rank, p, &p); encode_value (info->elem_size, p, &p); } else { - g_assert_not_reached (); + char *name; + + name = mono_aot_wrapper_name (method); + encode_value (MONO_AOT_WRAPPER_BY_NAME, p, &p); + strcpy ((char*)p, name); + p += strlen (name) + 1; + g_free (name); } break; case MONO_WRAPPER_CASTCLASS: @@ -2121,6 +2215,46 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 g_assert_not_reached (); } break; + case MONO_WRAPPER_RUNTIME_INVOKE: { + if (!strcmp (method->name, "runtime_invoke_dynamic")) { + encode_value (MONO_AOT_WRAPPER_RUNTIME_INVOKE_DYNAMIC, p, &p); + } else if (mono_marshal_method_from_wrapper (method) != method) { + MonoMethod *m; + + /* Direct wrapper, encode it normally */ + if (!strstr (method->name, "virtual")) + encode_value (MONO_AOT_WRAPPER_RUNTIME_INVOKE_DIRECT, p, &p); + else + encode_value (MONO_AOT_WRAPPER_RUNTIME_INVOKE_VIRTUAL, p, &p); + + m = mono_marshal_method_from_wrapper (method); + g_assert (m); + g_assert (m != method); + encode_method_ref (acfg, m, p, &p); + } else { + MonoMethodSignature *sig; + + encode_value (0, p, &p); + + sig = mono_method_signature (method); + encode_signature (acfg, sig, p, &p); + } + break; + } + case MONO_WRAPPER_DELEGATE_INVOKE: + case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE: + case MONO_WRAPPER_DELEGATE_END_INVOKE: { + MonoMethodSignature *sig = mono_method_signature (method); + encode_signature (acfg, sig, p, &p); + break; + } + case MONO_WRAPPER_NATIVE_TO_MANAGED: { + NativeToManagedWrapperInfo *info = mono_marshal_get_wrapper_info (method); + + encode_method_ref (acfg, info->method, p, &p); + encode_klass_ref (acfg, info->klass, p, &p); + break; + } default: g_assert_not_reached (); } @@ -5962,7 +6096,6 @@ emit_extra_methods (MonoAotCompile *acfg) 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); - char *name; if (!cfg) continue; @@ -5974,53 +6107,7 @@ emit_extra_methods (MonoAotCompile *acfg) method = cfg->method_to_register; - name = NULL; - if (method->wrapper_type) { - gboolean encode_ref = FALSE; - - /* - * We encode some wrappers using their name, since encoding them - * directly would be difficult. This works because at runtime, we only need to - * check whenever a method ref matches an existing MonoMethod. The downside is - * that the method names are large, so we use the binary encoding if possible. - */ - switch (method->wrapper_type) { - case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK: - case MONO_WRAPPER_SYNCHRONIZED: - encode_ref = TRUE; - break; - case MONO_WRAPPER_MANAGED_TO_NATIVE: - /* Skip JIT icall wrappers */ - if (!strstr (method->name, "__icall_wrapper")) - encode_ref = TRUE; - break; - case MONO_WRAPPER_UNKNOWN: - if (!strcmp (method->name, "PtrToStructure") || !strcmp (method->name, "StructureToPtr")) - encode_ref = TRUE; - break; - case MONO_WRAPPER_RUNTIME_INVOKE: - if (mono_marshal_method_from_wrapper (method) != method && !strstr (method->name, "virtual")) - /* Direct wrapper, encode normally */ - encode_ref = TRUE; - break; - default: - break; - } - - if (!encode_ref) - name = mono_aot_wrapper_name (method); - } - - if (name) { - encode_value (1, p, &p); - encode_value (method->wrapper_type, 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); - } + encode_method_ref (acfg, method, p, &p); g_assert ((p - buf) < buf_size); diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index 0fd244e9fb8..7d0357fbddc 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -472,6 +472,161 @@ decode_field_info (MonoAotModule *module, guint8 *buf, guint8 **endbuf) return mono_class_get_field (klass, token); } +/* + * Parse a MonoType encoded by encode_type () in aot-compiler.c. Return malloc-ed + * memory. + */ +static MonoType* +decode_type (MonoAotModule *module, guint8 *buf, guint8 **endbuf) +{ + guint8 *p = buf; + MonoType *t; + + t = g_malloc (sizeof (MonoType)); + + while (TRUE) { + if (*p == MONO_TYPE_PINNED) { + t->pinned = TRUE; + ++p; + } else if (*p == MONO_TYPE_BYREF) { + t->byref = TRUE; + ++p; + } else { + break; + } + } + + t->type = *p; + ++p; + + switch (t->type) { + case MONO_TYPE_VOID: + case MONO_TYPE_BOOLEAN: + case MONO_TYPE_CHAR: + case MONO_TYPE_I1: + case MONO_TYPE_U1: + case MONO_TYPE_I2: + case MONO_TYPE_U2: + case MONO_TYPE_I4: + case MONO_TYPE_U4: + case MONO_TYPE_I8: + case MONO_TYPE_U8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + case MONO_TYPE_I: + case MONO_TYPE_U: + case MONO_TYPE_STRING: + case MONO_TYPE_OBJECT: + case MONO_TYPE_TYPEDBYREF: + break; + case MONO_TYPE_VALUETYPE: + case MONO_TYPE_CLASS: + t->data.klass = decode_klass_ref (module, p, &p); + break; + case MONO_TYPE_SZARRAY: + t->data.klass = decode_klass_ref (module, p, &p); + + if (!t->data.klass) + return NULL; + break; + case MONO_TYPE_PTR: + t->data.type = decode_type (module, p, &p); + break; + case MONO_TYPE_GENERICINST: { + MonoClass *gclass; + MonoGenericContext ctx; + MonoType *type; + MonoClass *klass; + + gclass = decode_klass_ref (module, p, &p); + if (!gclass) + return NULL; + g_assert (gclass->generic_container); + + memset (&ctx, 0, sizeof (ctx)); + ctx.class_inst = decode_generic_inst (module, p, &p); + if (!ctx.class_inst) + return NULL; + type = mono_class_inflate_generic_type (&gclass->byval_arg, &ctx); + klass = mono_class_from_mono_type (type); + t->data.generic_class = klass->generic_class; + break; + } + default: + g_assert_not_reached (); + } + + *endbuf = p; + + return t; +} + +// FIXME: Error handling, memory management + +static MonoMethodSignature* +decode_signature_with_target (MonoAotModule *module, MonoMethodSignature *target, guint8 *buf, guint8 **endbuf) +{ + MonoMethodSignature *sig; + guint32 flags; + int i, param_count, call_conv; + guint8 *p = buf; + gboolean hasthis, explicit_this, has_gen_params; + + flags = *p; + p ++; + has_gen_params = (flags & 0x10) != 0; + hasthis = (flags & 0x20) != 0; + explicit_this = (flags & 0x40) != 0; + call_conv = flags & 0x0F; + + g_assert (!has_gen_params); + + param_count = decode_value (p, &p); + if (param_count != target->param_count) + return NULL; + sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + param_count * sizeof (MonoType *)); + sig->param_count = param_count; + sig->sentinelpos = -1; + sig->hasthis = hasthis; + sig->explicit_this = explicit_this; + sig->call_convention = call_conv; + sig->param_count = param_count; + sig->ret = decode_type (module, p, &p); + for (i = 0; i < param_count; ++i) + sig->params [i] = decode_type (module, p, &p); + + *endbuf = p; + + return sig; +} + +static gboolean +sig_matches_target (MonoAotModule *module, MonoMethod *target, guint8 *buf, guint8 **endbuf) +{ + MonoMethodSignature *sig; + gboolean res; + guint8 *p = buf; + + sig = decode_signature_with_target (module, mono_method_signature (target), p, &p); + res = sig && mono_metadata_signature_equal (mono_method_signature (target), sig); + g_free (sig); + *endbuf = p; + return res; +} + +static gboolean +wrapper_name_matches_target (guint8 *p, MonoMethod *target) +{ + char *name = (char*)p; + char *tname; + + tname = mono_aot_wrapper_name (target); + if (!strcmp (name, tname)) + return TRUE; + else + return FALSE; +} + /* Stores information returned by decode_method_ref () */ typedef struct { MonoImage *image; @@ -486,7 +641,8 @@ typedef struct { * Decode a method reference, storing the image/token into a MethodRef structure. * 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 ref->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 TARGET, and return FALSE. + * If TARGET is non-NULL, abort decoding if it can be determined that the decoded method couldn't resolve to TARGET, and return FALSE. There are some kinds of method references + * which only support a non-null TARGET. */ static gboolean decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod *target, guint8 *buf, guint8 **endbuf) @@ -574,9 +730,21 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod case MONO_WRAPPER_WRITE_BARRIER: ref->method = mono_gc_get_write_barrier (); break; - case MONO_WRAPPER_STELEMREF: - ref->method = mono_marshal_get_stelemref (); + case MONO_WRAPPER_STELEMREF: { + int subtype = decode_value (p, &p); + + if (subtype == 0) { + ref->method = mono_marshal_get_stelemref (); + } else { + g_assert (subtype == MONO_AOT_WRAPPER_BY_NAME); + g_assert (target); + if (wrapper_name_matches_target (p, target)) + ref->method = target; + else + return FALSE; + } break; + } case MONO_WRAPPER_SYNCHRONIZED: { MonoMethod *m = decode_resolve_method_ref (module, p, &p); @@ -625,15 +793,6 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod } break; } - case MONO_WRAPPER_RUNTIME_INVOKE: { - /* Direct wrapper */ - MonoMethod *m = decode_resolve_method_ref (module, p, &p); - - if (!m) - return FALSE; - ref->method = mono_marshal_get_runtime_invoke (m, FALSE); - break; - } case MONO_WRAPPER_MANAGED_TO_MANAGED: { int subtype = decode_value (p, &p); @@ -643,22 +802,40 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod ref->method = mono_marshal_get_array_address (rank, elem_size); } else { - g_assert_not_reached (); + g_assert (subtype == MONO_AOT_WRAPPER_BY_NAME); + g_assert (target); + if (wrapper_name_matches_target (p, target)) + ref->method = target; + else + return FALSE; } break; } case MONO_WRAPPER_MANAGED_TO_NATIVE: { - MonoMethod *m = decode_resolve_method_ref (module, p, &p); + MonoMethod *m; + int subtype = decode_value (p, &p); + char *name; - if (!m) - return FALSE; + if (subtype == MONO_AOT_WRAPPER_JIT_ICALL) { + g_assert (target); - /* This should only happen when looking for an extra method */ - g_assert (target); - if (mono_marshal_method_from_wrapper (target) == m) + name = (char*)p; + if (strcmp (target->name, name) != 0) + return FALSE; ref->method = target; - else - return FALSE; + } else { + m = decode_resolve_method_ref (module, p, &p); + + if (!m) + return FALSE; + + /* This should only happen when looking for an extra method */ + g_assert (target); + if (mono_marshal_method_from_wrapper (target) == m) + ref->method = target; + else + return FALSE; + } break; } case MONO_WRAPPER_CASTCLASS: { @@ -672,14 +849,68 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod g_assert_not_reached (); break; } + case MONO_WRAPPER_RUNTIME_INVOKE: { + int subtype = decode_value (p, &p); + + g_assert (target); + + if (subtype == MONO_AOT_WRAPPER_RUNTIME_INVOKE_DYNAMIC) { + if (strcmp (target->name, "runtime_invoke_dynamic") != 0) + return FALSE; + ref->method = target; + } else if (subtype == MONO_AOT_WRAPPER_RUNTIME_INVOKE_DIRECT) { + /* Direct wrapper */ + MonoMethod *m = decode_resolve_method_ref (module, p, &p); + + if (!m) + return FALSE; + ref->method = mono_marshal_get_runtime_invoke (m, FALSE); + } else if (subtype == MONO_AOT_WRAPPER_RUNTIME_INVOKE_VIRTUAL) { + /* Virtual direct wrapper */ + MonoMethod *m = decode_resolve_method_ref (module, p, &p); + + if (!m) + return FALSE; + ref->method = mono_marshal_get_runtime_invoke (m, TRUE); + } else { + if (sig_matches_target (module, target, p, &p)) + ref->method = target; + else + return FALSE; + } + break; + } + case MONO_WRAPPER_DELEGATE_INVOKE: + case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE: + case MONO_WRAPPER_DELEGATE_END_INVOKE: { + /* + * These wrappers are associated with a signature, not with a method. + * Since we can't decode them into methods, they need a target method. + */ + g_assert (target); + + if (sig_matches_target (module, target, p, &p)) + ref->method = target; + else + return FALSE; + break; + } + case MONO_WRAPPER_NATIVE_TO_MANAGED: { + MonoMethod *m; + MonoClass *klass; + + m = decode_resolve_method_ref (module, p, &p); + if (!m) + return FALSE; + klass = decode_klass_ref (module, p, &p); + if (!klass) + return FALSE; + ref->method = mono_marshal_get_managed_wrapper (m, klass, 0); + break; + } default: g_assert_not_reached (); } - } else if (image_index == MONO_AOT_METHODREF_WRAPPER_NAME) { - if (target) - return FALSE; - /* Can't decode these */ - g_assert_not_reached (); } else if (image_index == MONO_AOT_METHODREF_METHODSPEC) { image_index = decode_value (p, &p); ref->token = decode_value (p, &p); @@ -2701,55 +2932,45 @@ find_extra_method_in_amodule (MonoAotModule *amodule, MonoMethod *method, const guint32 value = entry [1]; guint32 next = entry [entry_size - 1]; MonoMethod *m; - guint8 *p; - int is_wrapper_name; + guint8 *p, *orig_p; p = amodule->blob + key; - is_wrapper_name = decode_value (p, &p); - if (is_wrapper_name) { - int wrapper_type = decode_value (p, &p); - if (wrapper_type == method->wrapper_type && !strcmp (name, (char*)p)) { - index = value; - break; - } - } else { - guint8 *orig_p = p; + 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) { - 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); - mono_aot_unlock (); - } - } - if (m == method) { - index = value; - break; + 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) { + 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); + mono_aot_unlock (); } + } + if (m == method) { + index = value; + break; + } - /* Special case: wrappers of shared generic methods */ - if (m && method->wrapper_type && m->wrapper_type == m->wrapper_type && - method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED) { - MonoMethod *w1 = mono_marshal_method_from_wrapper (method); - MonoMethod *w2 = mono_marshal_method_from_wrapper (m); + /* Special case: wrappers of shared generic methods */ + if (m && method->wrapper_type && m->wrapper_type == m->wrapper_type && + method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED) { + MonoMethod *w1 = mono_marshal_method_from_wrapper (method); + MonoMethod *w2 = mono_marshal_method_from_wrapper (m); - if (w1->is_inflated && ((MonoMethodInflated *)w1)->declaring == w2) { - index = value; - break; - } + if (w1->is_inflated && ((MonoMethodInflated *)w1)->declaring == w2) { + index = value; + break; } + } - /* Methods decoded needlessly */ - 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 ++; - } + /* Methods decoded needlessly */ + 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) diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 1222b86d247..9e5dba297d9 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -113,7 +113,7 @@ #endif /* Version number of the AOT file format */ -#define MONO_AOT_FILE_VERSION 76 +#define MONO_AOT_FILE_VERSION 77 //TODO: This is x86/amd64 specific. #define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6)) @@ -121,17 +121,15 @@ /* Constants used to encode different types of methods in AOT */ enum { MONO_AOT_METHODREF_MIN = 240, - /* Method encoded using its name */ - MONO_AOT_METHODREF_WRAPPER_NAME = 250, /* Runtime provided methods on arrays */ - MONO_AOT_METHODREF_ARRAY = 251, - MONO_AOT_METHODREF_NO_AOT_TRAMPOLINE = 252, + MONO_AOT_METHODREF_ARRAY = 250, + MONO_AOT_METHODREF_NO_AOT_TRAMPOLINE = 251, /* Wrappers */ - MONO_AOT_METHODREF_WRAPPER = 253, + MONO_AOT_METHODREF_WRAPPER = 252, /* Methods on generic instances */ - MONO_AOT_METHODREF_GINST = 254, + MONO_AOT_METHODREF_GINST = 253, /* Methods resolve using a METHODSPEC token */ - MONO_AOT_METHODREF_METHODSPEC = 255, + MONO_AOT_METHODREF_METHODSPEC = 254, }; /* Trampolines which we have a lot of */ @@ -2433,7 +2431,7 @@ void SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler) MONO_INTERNAL; void SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler) MONO_INTERNAL; gboolean SIG_HANDLER_SIGNATURE (mono_chain_signal) MONO_INTERNAL; -/* for MONO_WRAPPER_UNKNOWN/MANAGED_TO_MANAGED subtypes */ +/* Subtypes of some wrapper types */ enum { MONO_AOT_WRAPPER_MONITOR_ENTER, MONO_AOT_WRAPPER_MONITOR_EXIT, @@ -2443,6 +2441,18 @@ enum { MONO_AOT_WRAPPER_CASTCLASS_WITH_CACHE, MONO_AOT_WRAPPER_ISINST_WITH_CACHE, MONO_AOT_WRAPPER_MONITOR_ENTER_V4, + MONO_AOT_WRAPPER_JIT_ICALL, + MONO_AOT_WRAPPER_RUNTIME_INVOKE_DYNAMIC, + MONO_AOT_WRAPPER_RUNTIME_INVOKE_DIRECT, + MONO_AOT_WRAPPER_RUNTIME_INVOKE_VIRTUAL, + /* + * We can't encode this wrapper directly, so we emit its name instead. + * This means that its not possible to decode this into a method, only to check + * that the method reference matches a given method. This is normally not a problem + * as these wrappers only occur in the extra_methods table, where we already have + * a method we want to lookup. + */ + MONO_AOT_WRAPPER_BY_NAME, MONO_AOT_WRAPPER_LAST }; -- 2.11.4.GIT