+
+ if (acfg->image == mono_defaults.corlib) {
+ /* Add GenericComparer<T> instances for primitive types for Enum.ToString () */
+ MonoClass *klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericComparer`1");
+
+ if (klass) {
+ MonoGenericContext ctx;
+ MonoType *args [16];
+
+ memset (&ctx, 0, sizeof (ctx));
+
+ args [0] = &mono_defaults.byte_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.sbyte_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.int16_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.uint16_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.int32_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.uint32_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.int64_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.uint64_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+ }
+
+ /* Add GenericEqualityComparer<T> instances for primitive types */
+ klass = mono_class_from_name (acfg->image, "System.Collections.Generic", "GenericEqualityComparer`1");
+
+ if (klass) {
+ MonoGenericContext ctx;
+ MonoType *args [16];
+
+ memset (&ctx, 0, sizeof (ctx));
+
+ args [0] = &mono_defaults.byte_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.sbyte_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.int16_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.uint16_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.int32_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.uint32_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.int64_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ add_generic_class (acfg, mono_class_inflate_generic_class (klass, &ctx));
+
+ args [0] = &mono_defaults.uint64_class->byval_arg;
+ ctx.class_inst = mono_metadata_get_generic_inst (1, args);
+ 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;
+
+ memset (&ctx, 0, sizeof (ctx));
+
+ /*
+ * 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));
+ }
+ }
+ }
+}
+
+/*
+ * is_direct_callable:
+ *
+ * Return whenever the method identified by JI is directly callable without
+ * going through the PLT.
+ */
+static gboolean
+is_direct_callable (MonoAotCompile *acfg, MonoMethod *method, MonoJumpInfo *patch_info)
+{
+ if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == acfg->image)) {
+ MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
+ if (callee_cfg) {
+ gboolean direct_callable = TRUE;
+
+ if (direct_callable && !(!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
+ direct_callable = FALSE;
+ if ((callee_cfg->method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) && (!method || method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED))
+ // FIXME: Maybe call the wrapper directly ?
+ direct_callable = FALSE;
+
+ if (direct_callable)
+ return TRUE;
+ }
+ }
+
+ return FALSE;