Skip to content

Commit

Permalink
2009-10-21 Zoltan Varga <vargaz@gmail.com>
Browse files Browse the repository at this point in the history
	* aot-runtime.c (mono_aot_get_method): Special case the array generic iface
	wrappers and Array.GetGenericValueImpl ().

	* aot-compiler.c: Avoid emitting some wrappers which are not needed anymore
	because of the change above.

	* generics.cs: Add a test for full aot + generic array ifaces.

svn path=/branches/monotouch-1-0/mono/; revision=144594
  • Loading branch information
Geoff Norton committed Oct 22, 2009
1 parent 49a1bc1 commit 81ef551
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 69 deletions.
10 changes: 10 additions & 0 deletions mono/mini/ChangeLog
@@ -1,3 +1,13 @@
2009-10-21 Zoltan Varga <vargaz@gmail.com>

* aot-runtime.c (mono_aot_get_method): Special case the array generic iface
wrappers and Array.GetGenericValueImpl ().

* aot-compiler.c: Avoid emitting some wrappers which are not needed anymore
because of the change above.

* generics.cs: Add a test for full aot + generic array ifaces.

2009-10-06 Zoltan Varga <vargaz@gmail.com>

* aot-compiler.c (add_generic_class): Add an instance of GenericComparer<T> for
Expand Down
85 changes: 16 additions & 69 deletions mono/mini/aot-compiler.c
Expand Up @@ -2130,30 +2130,6 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
}

g_free (name_prefix);

/*
* Add instance of Array.GetGenericValueImpl, which is called by the
* array helper methods.
* managed-to-native wrappers are not shared, so have to generate
* these for ref types too.
*/
if (acfg->aot_opts.full_aot) {
MonoGenericContext ctx;
MonoType *args [16];
static MonoMethod *get_method;

if (get_method == NULL) {
MonoClass *array_klass = mono_array_class_get (mono_defaults.int_class, 1)->parent;
get_method = mono_class_get_method_from_name (array_klass, "GetGenericValueImpl", 2);
}

if (get_method) {
memset (&ctx, 0, sizeof (ctx));
args [0] = &tclass->byval_arg;
ctx.method_inst = mono_metadata_get_generic_inst (1, args);
add_extra_method (acfg, mono_marshal_get_native_wrapper (mono_class_inflate_generic_method (get_method, &ctx), TRUE, TRUE));
}
}
}

/* Add an instance of GenericComparer<T> which is created dynamically by Comparer<T> */
Expand All @@ -2178,18 +2154,6 @@ add_generic_class (MonoAotCompile *acfg, MonoClass *klass)
}
}

static void
add_array_wrappers (MonoAotCompile *acfg, MonoClass *klass)
{
int i;

mono_class_setup_methods (klass);
for (i = 0; i < klass->method.count; ++i) {
if (klass->methods [i]->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED)
add_extra_method (acfg, klass->methods [i]);
}
}

/*
* add_generic_instances:
*
Expand Down Expand Up @@ -2360,42 +2324,25 @@ add_generic_instances (MonoAotCompile *acfg)
add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));

}
}

/* Emit the array wrapper methods for arrays of primitive types */
add_array_wrappers (acfg, mono_array_class_get (mono_defaults.byte_class, 1));
add_array_wrappers (acfg, mono_array_class_get (mono_defaults.sbyte_class, 1));
add_array_wrappers (acfg, mono_array_class_get (mono_defaults.int16_class, 1));
add_array_wrappers (acfg, mono_array_class_get (mono_defaults.uint16_class, 1));
add_array_wrappers (acfg, mono_array_class_get (mono_defaults.int32_class, 1));
add_array_wrappers (acfg, mono_array_class_get (mono_defaults.uint32_class, 1));
add_array_wrappers (acfg, mono_array_class_get (mono_defaults.int64_class, 1));
add_array_wrappers (acfg, mono_array_class_get (mono_defaults.single_class, 1));
add_array_wrappers (acfg, mono_array_class_get (mono_defaults.double_class, 1));
/* These are not handled by generic sharing */
add_array_wrappers (acfg, mono_array_class_get (mono_defaults.object_class, 1));
add_array_wrappers (acfg, mono_array_class_get (mono_defaults.string_class, 1));

/* Add instances of Array.GetGenericValueImpl */
{
MonoGenericContext ctx;
MonoType *args [16];
MonoMethod *method;
/*
* Add a managed-to-native wrapper of Array.GetGenericValueImpl<object>, which is
* used for all instances of GetGenericValueImpl by the AOT runtime.
*/
{
MonoGenericContext ctx;
MonoType *args [16];
MonoMethod *get_method;
MonoClass *array_klass = mono_array_class_get (mono_defaults.object_class, 1)->parent;

memset (&ctx, 0, sizeof (ctx));
get_method = mono_class_get_method_from_name (array_klass, "GetGenericValueImpl", 2);

/*
* managed-to-native wrappers are not shared, so have to generate
* these for ref types too.
*/
klass = mono_array_class_get (mono_defaults.int_class, 1)->parent;
method = mono_class_get_method_from_name (klass, "GetGenericValueImpl", 2);

if (method) {
/* String */
args [0] = &mono_defaults.string_class->byval_arg;
ctx.method_inst = mono_metadata_get_generic_inst (1, args);
add_extra_method (acfg, mono_marshal_get_native_wrapper (mono_class_inflate_generic_method (method, &ctx), TRUE, TRUE));
}
if (get_method) {
memset (&ctx, 0, sizeof (ctx));
args [0] = &mono_defaults.object_class->byval_arg;
ctx.method_inst = mono_metadata_get_generic_inst (1, args);
add_extra_method (acfg, mono_marshal_get_native_wrapper (mono_class_inflate_generic_method (get_method, &ctx), TRUE, TRUE));
}
}
}
Expand Down
77 changes: 77 additions & 0 deletions mono/mini/aot-runtime.c
Expand Up @@ -2278,6 +2278,83 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
return code;

method_index = find_extra_method (method, &amodule);
/*
* Special case the ICollection<T> wrappers for arrays, as they cannot
* be statically enumerated, and each wrapper ends up calling the same
* method in Array.
*/
if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED && method->klass->rank && strstr (method->name, "System.Collections.Generic")) {
MonoMethod *m;
const char *prefix;
MonoGenericContext ctx;
MonoType *args [16];
char *mname, *iname, *s, *s2, *helper_name = NULL;

prefix = "System.Collections.Generic";
s = g_strdup_printf ("%s", method->name + strlen (prefix) + 1);
s2 = strstr (s, "`1.");
g_assert (s2);
s2 [0] = '\0';
iname = s;
mname = s2 + 3;

//printf ("X: %s %s\n", iname, mname);

helper_name = g_strdup_printf ("InternalArray__%s_%s", iname, mname);
m = mono_class_get_method_from_name (mono_defaults.array_class, helper_name, mono_method_signature (method)->param_count);
g_assert (m);
g_free (helper_name);
g_free (s);

if (m->is_generic) {
memset (&ctx, 0, sizeof (ctx));
args [0] = &method->klass->element_class->byval_arg;
ctx.method_inst = mono_metadata_get_generic_inst (1, args);
m = mono_class_inflate_generic_method (m, &ctx);
}

code = mono_aot_get_method (domain, m);
g_assert (code);

if (mono_method_needs_static_rgctx_invoke (m, FALSE))
code = mono_create_static_rgctx_trampoline (m, code);

return code;
}

/*
* Special case Array.GetGenericValueImpl which is a generic icall.
* Generic sharing currently can't handle it, but the icall returns data using
* an out parameter, so the managed-to-native wrappers can share the same code.
*/
if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE && method->klass == mono_defaults.array_class && !strcmp (method->name, "GetGenericValueImpl")) {
MonoMethod *m;
MonoGenericContext ctx;
MonoType *args [16];

if (mono_method_signature (method)->params [1]->type == MONO_TYPE_OBJECT)
/* Avoid recursion */
return NULL;

m = mono_class_get_method_from_name (mono_defaults.array_class, "GetGenericValueImpl", 2);
g_assert (m);

memset (&ctx, 0, sizeof (ctx));
args [0] = &mono_defaults.object_class->byval_arg;
ctx.method_inst = mono_metadata_get_generic_inst (1, args);

m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method (m, &ctx), TRUE, TRUE);

/*
* Get the code for the <object> instantiation which should be emitted into
* the mscorlib aot image by the AOT compiler.
*/
code = mono_aot_get_method (domain, m);
g_assert (code);

return code;
}

if (method_index == 0xffffff) {
if (mono_aot_only && mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT)) {
char *full_name;
Expand Down
13 changes: 13 additions & 0 deletions mono/mini/generics.cs
Expand Up @@ -462,6 +462,19 @@ public class XElement {
return l.Count;
}

static void enumerate<T> (IEnumerable<T> arr) {
foreach (var o in arr)
;
int c = ((ICollection<T>)arr).Count;
}

/* Test that treating arrays as generic collections works with full-aot */
public static int test_0_fullaot_array_wrappers () {
Tests[] arr = new Tests [10];
enumerate<Tests> (arr);
return 0;
}

static int cctor_count = 0;

public abstract class Beta<TChanged>
Expand Down

0 comments on commit 81ef551

Please sign in to comment.