From a1aa0ca2cba9fd0be685807067e6da8c2acaf69a Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 7 Mar 2013 19:44:11 +0100 Subject: [PATCH] Fix the encoding of runtime-invoke wrappers in AOT. Add support for gsharedvt delegate begin/end-invoke wrappers to full AOT. --- mono/metadata/marshal.c | 3 ++ mono/metadata/marshal.h | 3 ++ mono/metadata/object.c | 38 ++++++++++++++++++++++++ mono/metadata/object.h | 6 ++++ mono/mini/aot-compiler.c | 59 +++++++++++++++++++++++-------------- mono/mini/aot-runtime.c | 63 +++++++++++++++++++++++++++------------- mono/mini/gshared.cs | 2 ++ mono/mini/mini.h | 2 +- 8 files changed, 134 insertions(+), 42 deletions(-) diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 0e9e7f94b22..ca7f7ff2069 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -4946,6 +4946,9 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual) g_hash_table_insert (cache, callsig, res); /* Can't insert it into wrapper_hash since the key is a signature */ g_hash_table_insert (method->klass->image->runtime_invoke_direct_cache, method, res); + info = mono_wrapper_info_create (res, WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL); + info->d.runtime_invoke.sig = callsig; + mono_marshal_set_wrapper_info (res, info); } else { mono_free_method (newm); } diff --git a/mono/metadata/marshal.h b/mono/metadata/marshal.h index 11d9c02b360..a8f7057d629 100644 --- a/mono/metadata/marshal.h +++ b/mono/metadata/marshal.h @@ -97,6 +97,7 @@ typedef enum { WRAPPER_SUBTYPE_CASTCLASS_WITH_CACHE, WRAPPER_SUBTYPE_ISINST_WITH_CACHE, /* Subtypes of MONO_WRAPPER_RUNTIME_INVOKE */ + WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL, WRAPPER_SUBTYPE_RUNTIME_INVOKE_DYNAMIC, WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT, WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL, @@ -130,6 +131,8 @@ typedef struct { typedef struct { MonoMethod *method; + /* For WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL */ + MonoMethodSignature *sig; } RuntimeInvokeWrapperInfo; typedef struct { diff --git a/mono/metadata/object.c b/mono/metadata/object.c index a249f97db5b..6eba6f5aedf 100644 --- a/mono/metadata/object.c +++ b/mono/metadata/object.c @@ -3484,6 +3484,44 @@ mono_get_delegate_invoke (MonoClass *klass) return im; } +/** + * mono_get_delegate_begin_invoke: + * @klass: The delegate class + * + * Returns: the MonoMethod for the "BeginInvoke" method in the delegate klass or NULL if @klass is a broken delegate type + */ +MonoMethod * +mono_get_delegate_begin_invoke (MonoClass *klass) +{ + MonoMethod *im; + + /* This is called at runtime, so avoid the slower search in metadata */ + mono_class_setup_methods (klass); + if (klass->exception_type) + return NULL; + im = mono_class_get_method_from_name (klass, "BeginInvoke", -1); + return im; +} + +/** + * mono_get_delegate_end_invoke: + * @klass: The delegate class + * + * Returns: the MonoMethod for the "EndInvoke" method in the delegate klass or NULL if @klass is a broken delegate type + */ +MonoMethod * +mono_get_delegate_end_invoke (MonoClass *klass) +{ + MonoMethod *im; + + /* This is called at runtime, so avoid the slower search in metadata */ + mono_class_setup_methods (klass); + if (klass->exception_type) + return NULL; + im = mono_class_get_method_from_name (klass, "EndInvoke", -1); + return im; +} + /** * mono_runtime_delegate_invoke: * @delegate: pointer to a delegate object. diff --git a/mono/metadata/object.h b/mono/metadata/object.h index 10510964238..e975298e881 100644 --- a/mono/metadata/object.h +++ b/mono/metadata/object.h @@ -212,6 +212,12 @@ mono_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoMethod * mono_get_delegate_invoke (MonoClass *klass); +MonoMethod * +mono_get_delegate_begin_invoke (MonoClass *klass); + +MonoMethod * +mono_get_delegate_end_invoke (MonoClass *klass); + MonoObject* mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc); diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index f0fcec44cf2..d5d2fdb77ac 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -2606,21 +2606,17 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 case MONO_WRAPPER_RUNTIME_INVOKE: { WrapperInfo *info = mono_marshal_get_wrapper_info (method); - if (info) { - encode_value (info->subtype, p, &p); - if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT || info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL) - encode_method_ref (acfg, info->d.runtime_invoke.method, p, &p); - } else { - MonoMethodSignature *sig; - - encode_value (0, p, &p); - - sig = mono_method_signature (method); - encode_signature (acfg, sig, p, &p); - } + g_assert (info); + encode_value (info->subtype, p, &p); + if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_DIRECT || info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_VIRTUAL) + encode_method_ref (acfg, info->d.runtime_invoke.method, p, &p); + else if (info->subtype == WRAPPER_SUBTYPE_RUNTIME_INVOKE_NORMAL) + encode_signature (acfg, info->d.runtime_invoke.sig, p, &p); break; } - case MONO_WRAPPER_DELEGATE_INVOKE: { + case MONO_WRAPPER_DELEGATE_INVOKE: + case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE: + case MONO_WRAPPER_DELEGATE_END_INVOKE: { if (method->is_inflated) { /* These wrappers are identified by their class */ encode_value (1, p, &p); @@ -2633,12 +2629,6 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 } break; } - 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: { WrapperInfo *info = mono_marshal_get_wrapper_info (method); @@ -3402,9 +3392,9 @@ add_wrappers (MonoAotCompile *acfg) MonoMethod *inst, *gshared; /* - * Emit a gsharedvt version of the generic delegate-invoke wrapper + * Emit gsharedvt versions of the generic delegate-invoke wrappers */ - + /* Invoke */ method = mono_get_delegate_invoke (klass); create_gsharedvt_inst (acfg, method, &ctx); @@ -3415,6 +3405,31 @@ add_wrappers (MonoAotCompile *acfg) gshared = mini_get_shared_method_full (m, FALSE, TRUE); add_extra_method (acfg, gshared); + + /* begin-invoke */ + method = mono_get_delegate_begin_invoke (klass); + create_gsharedvt_inst (acfg, method, &ctx); + + inst = mono_class_inflate_generic_method (method, &ctx); + + m = mono_marshal_get_delegate_begin_invoke (inst); + g_assert (m->is_inflated); + + gshared = mini_get_shared_method_full (m, FALSE, TRUE); + add_extra_method (acfg, gshared); + + /* end-invoke */ + method = mono_get_delegate_end_invoke (klass); + create_gsharedvt_inst (acfg, method, &ctx); + + inst = mono_class_inflate_generic_method (method, &ctx); + + m = mono_marshal_get_delegate_end_invoke (inst); + g_assert (m->is_inflated); + + gshared = mini_get_shared_method_full (m, FALSE, TRUE); + add_extra_method (acfg, gshared); + } } @@ -5883,6 +5898,8 @@ can_encode_method (MonoAotCompile *acfg, MonoMethod *method) case MONO_WRAPPER_UNKNOWN: case MONO_WRAPPER_WRITE_BARRIER: case MONO_WRAPPER_DELEGATE_INVOKE: + case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE: + case MONO_WRAPPER_DELEGATE_END_INVOKE: break; case MONO_WRAPPER_MANAGED_TO_MANAGED: case MONO_WRAPPER_CASTCLASS: { diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c index e3228b9dfa4..91c7c1dcbb1 100644 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@ -1021,14 +1021,26 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod return FALSE; ref->method = mono_marshal_get_runtime_invoke (m, TRUE); } else { - if (sig_matches_target (module, target, p, &p)) + MonoMethodSignature *sig; + WrapperInfo *info; + + sig = decode_signature_with_target (module, NULL, p, &p); + info = mono_marshal_get_wrapper_info (target); + g_assert (info); + + if (info->subtype != subtype) + return FALSE; + g_assert (info->d.runtime_invoke.sig); + if (mono_metadata_signature_equal (sig, info->d.runtime_invoke.sig)) ref->method = target; else return FALSE; } break; } - case MONO_WRAPPER_DELEGATE_INVOKE: { + case MONO_WRAPPER_DELEGATE_INVOKE: + case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE: + case MONO_WRAPPER_DELEGATE_END_INVOKE: { gboolean is_inflated = decode_value (p, &p); if (is_inflated) { @@ -1038,29 +1050,40 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod klass = decode_klass_ref (module, p, &p); if (!klass) return FALSE; - invoke = mono_get_delegate_invoke (klass); - wrapper = mono_marshal_get_delegate_invoke (invoke, NULL); + + switch (wrapper_type) { + case MONO_WRAPPER_DELEGATE_INVOKE: + invoke = mono_get_delegate_invoke (klass); + wrapper = mono_marshal_get_delegate_invoke (invoke, NULL); + break; + case MONO_WRAPPER_DELEGATE_BEGIN_INVOKE: + invoke = mono_get_delegate_begin_invoke (klass); + wrapper = mono_marshal_get_delegate_begin_invoke (invoke); + break; + case MONO_WRAPPER_DELEGATE_END_INVOKE: + invoke = mono_get_delegate_end_invoke (klass); + wrapper = mono_marshal_get_delegate_end_invoke (invoke); + break; + default: + g_assert_not_reached (); + break; + } if (target && wrapper != target) return FALSE; ref->method = wrapper; - break; } else { - /* Fall through */ - } - } - 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. - */ - if (!target) - return FALSE; + /* + * These wrappers are associated with a signature, not with a method. + * Since we can't decode them into methods, they need a target method. + */ + if (!target) + return FALSE; - if (sig_matches_target (module, target, p, &p)) - ref->method = target; - else - return FALSE; + if (sig_matches_target (module, target, p, &p)) + ref->method = target; + else + return FALSE; + } break; } case MONO_WRAPPER_NATIVE_TO_MANAGED: { diff --git a/mono/mini/gshared.cs b/mono/mini/gshared.cs index 864af61984a..561b2333947 100644 --- a/mono/mini/gshared.cs +++ b/mono/mini/gshared.cs @@ -1073,6 +1073,8 @@ public class Tests } } + // FIXME: The runtime-invoke wrapper used by BeginInvoke is not found + [Category ("!FULLAOT")] public static int test_0_begin_end_invoke () { IFace6 o = new Class6 (); var arr1 = o.Del (1); diff --git a/mono/mini/mini.h b/mono/mini/mini.h index fd41f0241e7..bf5c229bc91 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -127,7 +127,7 @@ #endif /* Version number of the AOT file format */ -#define MONO_AOT_FILE_VERSION 87 +#define MONO_AOT_FILE_VERSION 88 //TODO: This is x86/amd64 specific. #define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6)) -- 2.25.1