Skip to content

Commit c53773d

Browse files
committed
checkpoint generic wrapper methods
1 parent b1c9c60 commit c53773d

File tree

6 files changed

+147
-15
lines changed

6 files changed

+147
-15
lines changed

src/mono/mono/metadata/marshal.c

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5226,31 +5226,80 @@ mono_marshal_get_unsafe_accessor_wrapper (MonoMethod *accessor_method, MonoUnsaf
52265226
MonoMethod *res;
52275227
GHashTable *cache;
52285228
MonoGenericContext *ctx = NULL;
5229+
MonoGenericContainer *container = NULL;
52295230
MonoMethod *orig_method = NULL;
52305231
WrapperInfo *info;
5232+
gboolean is_generic = FALSE;
52315233

52325234
if (member_name == NULL && kind != MONO_UNSAFE_ACCESSOR_CTOR)
52335235
member_name = accessor_method->name;
52345236

5237+
if (accessor_method->is_generic) {
5238+
/* got a generic method definition. need to make a generic method definition wrapper */
5239+
g_assert (!accessor_method->is_inflated);
5240+
printf ("accessor method is generic: %s\n", mono_method_full_name (accessor_method, TRUE));
5241+
is_generic = TRUE;
5242+
}
5243+
5244+
/* FIXME: Support generic methods too */
5245+
if (accessor_method->is_inflated && !mono_method_get_context (accessor_method)->method_inst) {
5246+
orig_method = accessor_method;
5247+
ctx = &((MonoMethodInflated*)accessor_method)->context;
5248+
accessor_method = ((MonoMethodInflated*)accessor_method)->declaring;
5249+
container = mono_method_get_generic_container (accessor_method);
5250+
if (!container)
5251+
container = mono_class_try_get_generic_container (accessor_method->klass); //FIXME is this a case of a try?
5252+
g_assert (container);
5253+
} else if (accessor_method->is_inflated && mono_method_get_context(accessor_method)->method_inst) {
5254+
// FIXME: ak: do we need a different case? it should work, right?
5255+
// N.B. both method_inst and type_inst might be set
5256+
orig_method = accessor_method;
5257+
ctx = &((MonoMethodInflated*)accessor_method)->context;
5258+
accessor_method = ((MonoMethodInflated*)accessor_method)->declaring;
5259+
container = mono_method_get_generic_container (accessor_method);
5260+
if (!container)
5261+
container = mono_class_try_get_generic_container (accessor_method->klass); //FIXME is this a case of a try?
5262+
g_assert (container);
5263+
}
5264+
52355265
/*
52365266
* Check cache
52375267
*/
52385268
if (ctx) {
5239-
cache = NULL;
5240-
g_assert_not_reached ();
5269+
/* FIXME get the right cache */
5270+
cache = NULL; /* get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.synchronized_cache , mono_aligned_addr_hash, NULL); */
5271+
/* res = check_generic_wrapper_cache (cache, orig_method, orig_method, method);*/
5272+
res = NULL;
5273+
if (res)
5274+
return res;
52415275
} else {
52425276
cache = get_cache (&mono_method_get_wrapper_cache (accessor_method)->unsafe_accessor_cache, mono_aligned_addr_hash, NULL);
52435277
if ((res = mono_marshal_find_in_cache (cache, accessor_method)))
52445278
return res;
52455279
}
52465280

5247-
sig = mono_metadata_signature_dup_full (get_method_image (accessor_method), mono_method_signature_internal (accessor_method));
5248-
sig->pinvoke = 0;
52495281

52505282
mb = mono_mb_new (accessor_method->klass, accessor_method->name, MONO_WRAPPER_OTHER);
5283+
if (is_generic) {
5284+
mb->method->is_generic = is_generic;
5285+
container = mono_class_try_get_generic_container (accessor_method->klass);
5286+
container = mono_metadata_load_generic_params (m_class_get_image (accessor_method->klass), accessor_method->token, container, /*owner:*/mb->method);
5287+
mono_method_set_generic_container (mb->method, container);
5288+
5289+
MonoGenericContext ctx = {0,};
5290+
ctx.method_inst = container->context.method_inst;
5291+
5292+
ERROR_DECL (error);
5293+
sig = mono_inflate_generic_signature (mono_method_signature_internal (accessor_method), &ctx, error);
5294+
mono_error_assert_ok (error); // FIXME
5295+
} else {
5296+
sig = mono_metadata_signature_dup_full (get_method_image (accessor_method), mono_method_signature_internal (accessor_method));
5297+
}
5298+
sig->pinvoke = 0;
52515299

52525300
get_marshal_cb ()->mb_skip_visibility (mb);
52535301

5302+
// TODO: pass container, too
52545303
get_marshal_cb ()->emit_unsafe_accessor_wrapper (mb, accessor_method, sig, ctx, kind, member_name);
52555304

52565305
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_UNSAFE_ACCESSOR);

src/mono/mono/metadata/method-builder-ilgen.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,18 @@ create_method_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *signature, int
214214
mono_image_unlock (image);
215215
}
216216

217+
if (mb->method->is_generic) {
218+
method->is_generic = TRUE;
219+
MonoGenericContainer *container = mono_method_get_generic_container (mb->method);
220+
mono_method_set_generic_container (method, container);
221+
g_assert (!container->is_anonymous);
222+
g_assert (container->is_method);
223+
g_assert (container->owner.method == mb->method);
224+
// HACK: reassign container owner from the method builder placeholder to the
225+
// final created method
226+
container->owner.method = method;
227+
}
228+
217229
return method;
218230
}
219231

src/mono/mono/mini/aot-compiler.c

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3874,6 +3874,15 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8
38743874
encode_value (len, p, &p);
38753875
encode_string (info->d.unsafe_accessor.member_name, p, &p);
38763876
}
3877+
if (method->is_inflated) {
3878+
encode_value(1, p, &p);
3879+
MonoMethodInflated *inflated = (MonoMethodInflated*)method;
3880+
MonoGenericContext *ctx = &inflated->context;
3881+
encode_generic_context (acfg, ctx, p, &p);
3882+
} else {
3883+
encode_value(0, p, &p);
3884+
}
3885+
38773886
}
38783887
else if (info->subtype == WRAPPER_SUBTYPE_INTERP_IN)
38793888
encode_signature (acfg, info->d.interp_in.sig, p, &p);
@@ -4829,6 +4838,18 @@ mono_aot_can_enter_interp (MonoMethod *method)
48294838
return FALSE;
48304839
}
48314840

4841+
static MonoMethod*
4842+
instantiate_wrapper_like_decl (MonoMethod *extern_method_inst, MonoUnsafeAccessorKind accessor_kind, const char *member_name, MonoError *error)
4843+
{
4844+
g_assert (extern_method_inst->is_inflated);
4845+
MonoMethodInflated *infl = (MonoMethodInflated*)extern_method_inst;
4846+
MonoMethod *extern_decl = infl->declaring;
4847+
MonoMethod *generic_wrapper = mono_marshal_get_unsafe_accessor_wrapper (extern_decl, accessor_kind, member_name);
4848+
MonoGenericContext *ctx = &infl->context;
4849+
MonoMethod *inflated_wrapper = mono_class_inflate_generic_method_checked (generic_wrapper, ctx, error);
4850+
return inflated_wrapper;
4851+
}
4852+
48324853
/**
48334854
* Replaces some extern \c method by a wrapper.
48344855
*
@@ -4848,6 +4869,8 @@ replace_generated_method (MonoAotCompile *acfg, MonoMethod *method, MonoError *e
48484869
{
48494870
char * method_name = mono_method_get_full_name (method);
48504871
g_print ("ADDING no header %s generic instances\n", method_name);
4872+
if (strstr (method_name, "!!0") != NULL)
4873+
g_print("anon\n");
48514874
g_free (method_name);
48524875
}
48534876

@@ -4857,15 +4880,20 @@ replace_generated_method (MonoAotCompile *acfg, MonoMethod *method, MonoError *e
48574880
char *member_name = NULL;
48584881
int accessor_kind = -1;
48594882
if (mono_method_get_unsafe_accessor_attr_data (method, &accessor_kind, &member_name, error)) {
4860-
// FIXME: if `method` was inflated, get the uninflated wrapper and then re-inflate
4861-
// it.
4862-
MonoMethod *wrapper = mono_marshal_get_unsafe_accessor_wrapper (method, (MonoUnsafeAccessorKind)accessor_kind, member_name);
4863-
{
4864-
char * method_name = mono_method_get_full_name (wrapper);
4865-
g_print ("REPLACED by %s in generic instances\n", method_name);
4866-
g_free (method_name);
4883+
MonoMethod *wrapper = NULL;
4884+
if (method->is_inflated) {
4885+
wrapper = instantiate_wrapper_like_decl (method, (MonoUnsafeAccessorKind)accessor_kind, member_name, error);
4886+
} else {
4887+
wrapper = mono_marshal_get_unsafe_accessor_wrapper (method, (MonoUnsafeAccessorKind)accessor_kind, member_name);
4888+
}
4889+
if (is_ok (error)) {
4890+
{
4891+
char * method_name = mono_method_get_full_name (wrapper);
4892+
g_print ("REPLACED by %s in generic instances\n", method_name);
4893+
g_free (method_name);
4894+
}
4895+
return wrapper;
48674896
}
4868-
return wrapper;
48694897
}
48704898

48714899
if (!is_ok (error)) {
@@ -7925,6 +7953,12 @@ emit_exception_debug_info (MonoAotCompile *acfg, MonoCompile *cfg, gboolean stor
79257953
*/
79267954
buf2 = (guint8 *)g_malloc (4096);
79277955
p2 = buf2;
7956+
if (cfg->method->wrapper_type && cfg->method->is_generic) {
7957+
printf ("barf\n");
7958+
}
7959+
if (jinfo->d.method->wrapper_type && jinfo->d.method->is_generic) {
7960+
printf ("barf2\n");
7961+
}
79287962
encode_method_ref (acfg, jinfo->d.method, p2, &p2);
79297963
len = GPTRDIFF_TO_INT (p2 - buf2);
79307964
g_assert (len < 4096);

src/mono/mono/mini/aot-runtime.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,14 @@ typedef struct {
940940
gboolean no_aot_trampoline;
941941
} MethodRef;
942942

943+
static MonoMethod*
944+
instantiate_wrapper_like_decl (MonoMethod *extern_decl, MonoGenericContext *ctx, MonoUnsafeAccessorKind accessor_kind, const char *member_name, MonoError *error)
945+
{
946+
MonoMethod *generic_wrapper = mono_marshal_get_unsafe_accessor_wrapper (extern_decl, accessor_kind, member_name);
947+
MonoMethod *inflated_wrapper = mono_class_inflate_generic_method_checked (generic_wrapper, ctx, error);
948+
return inflated_wrapper;
949+
}
950+
943951
/*
944952
* decode_method_ref_with_target:
945953
*
@@ -1079,7 +1087,17 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod
10791087
uint32_t name_len = decode_value (p, &p);
10801088
const char *member_name = (const char*)p;
10811089
p += name_len + 1;
1082-
ref->method = mono_marshal_get_unsafe_accessor_wrapper (m, kind, member_name);
1090+
uint8_t inflated = decode_value (p, &p);
1091+
if (inflated) {
1092+
MonoGenericContext ctx = {0,};
1093+
decode_generic_context (module, &ctx, p, &p, error);
1094+
mono_error_assert_ok (error);
1095+
ref->method = instantiate_wrapper_like_decl (m, &ctx, kind, member_name, error);
1096+
if (!is_ok (error))
1097+
return FALSE;
1098+
} else {
1099+
ref->method = mono_marshal_get_unsafe_accessor_wrapper (m, kind, member_name);
1100+
}
10831101
} else if (subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN) {
10841102
ref->method = mono_marshal_get_gsharedvt_in_wrapper ();
10851103
} else if (subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT) {

src/mono/mono/mini/aot-runtime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include "mini.h"
1212

1313
/* Version number of the AOT file format */
14-
#define MONO_AOT_FILE_VERSION 185
14+
#define MONO_AOT_FILE_VERSION 186
1515

1616
#define MONO_AOT_TRAMP_PAGE_SIZE 16384
1717

src/mono/sample/HelloWorld/Program.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ public class Program
1616
public static void Main()
1717
{
1818
var box = new MyBox<string>("xyz");
19-
RunIt<string>(box, "abc");
19+
//Thinger<string>(box);
20+
//RunIt<string>(box, "abc");
21+
//Console.WriteLine (box.Value);
22+
RunItAgain<string>(box, "hjk");
2023
Console.WriteLine (box.Value);
2124
}
2225

@@ -27,6 +30,22 @@ public static void RunIt<H> (MyBox<H> dest, H input)
2730
boxWriter = input;
2831
}
2932

33+
[MethodImpl(MethodImplOptions.NoInlining)]
34+
public static void RunItAgain<S> (MyBox<S> dest, S input)
35+
{
36+
ref S boxWriter = ref AccessHelper<S>.AccessBox2(dest);
37+
boxWriter = input;
38+
}
39+
3040
[UnsafeAccessor(UnsafeAccessorKind.Field, Name="_value")]
3141
private static extern ref W AccessBox<W>(MyBox<W> x);
42+
43+
[MethodImpl(MethodImplOptions.NoInlining)]
44+
private static ref W Thinger<W>(MyBox<W> x) => throw new InvalidOperationException("oops");
45+
}
46+
47+
public class AccessHelper<Q>
48+
{
49+
[UnsafeAccessor(UnsafeAccessorKind.Field, Name="_value")]
50+
public static extern ref Q AccessBox2(MyBox<Q> q);
3251
}

0 commit comments

Comments
 (0)