Skip to content
Browse files

Add some support for wrappers which are generic instances.

  • Loading branch information...
1 parent a736dee commit 8465f13e8a5a1601798f272d2c71d6c511f3d7f7 @vargaz vargaz committed Feb 4, 2013
Showing with 79 additions and 45 deletions.
  1. +3 −0 mono/metadata/class-internals.h
  2. +19 −0 mono/metadata/loader.c
  3. +56 −42 mono/mini/method-to-ir.c
  4. +1 −3 mono/mini/mini-generic-sharing.c
View
3 mono/metadata/class-internals.h
@@ -1019,6 +1019,9 @@ mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *con
void
mono_metadata_free_inflated_signature (MonoMethodSignature *sig);
+MonoMethodSignature*
+mono_inflate_generic_signature (MonoMethodSignature *sig, MonoGenericContext *context, MonoError *error) MONO_INTERNAL;
+
typedef struct {
MonoImage *corlib;
MonoClass *object_class;
View
19 mono/metadata/loader.c
@@ -780,6 +780,25 @@ inflate_generic_signature_checked (MonoImage *image, MonoMethodSignature *sig, M
return NULL;
}
+/*
+ * mono_inflate_generic_signature:
+ *
+ * Inflate SIG with CONTEXT, and return a canonical copy. On error, set ERROR, and return NULL.
+ */
+MonoMethodSignature*
+mono_inflate_generic_signature (MonoMethodSignature *sig, MonoGenericContext *context, MonoError *error)
+{
+ MonoMethodSignature *res, *cached;
+
+ res = inflate_generic_signature_checked (NULL, sig, context, error);
+ if (!mono_error_ok (error))
+ return NULL;
+ cached = mono_metadata_get_inflated_signature (res, context);
+ if (cached != res)
+ mono_metadata_free_inflated_signature (res);
+ return cached;
+}
+
static MonoMethodHeader*
inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context)
{
View
98 mono/mini/method-to-ir.c
@@ -5537,10 +5537,13 @@ mini_get_method_allow_open (MonoMethod *m, guint32 token, MonoClass *klass, Mono
{
MonoMethod *method;
- if (m->wrapper_type != MONO_WRAPPER_NONE)
- return mono_method_get_wrapper_data (m, token);
-
- method = mono_get_method_full (m->klass->image, token, klass, context);
+ if (m->wrapper_type != MONO_WRAPPER_NONE) {
+ method = mono_method_get_wrapper_data (m, token);
+ if (context)
+ method = mono_class_inflate_generic_method (method, context);
+ } else {
+ method = mono_get_method_full (m->klass->image, token, klass, context);
+ }
return method;
}
@@ -5570,6 +5573,26 @@ mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
return klass;
}
+static inline MonoMethodSignature*
+mini_get_signature (MonoMethod *method, guint32 token, MonoGenericContext *context)
+{
+ MonoMethodSignature *fsig;
+
+ if (method->wrapper_type != MONO_WRAPPER_NONE) {
+ MonoError error;
+
+ fsig = (MonoMethodSignature *)mono_method_get_wrapper_data (method, token);
+ if (context) {
+ fsig = mono_inflate_generic_signature (fsig, context, &error);
+ // FIXME:
+ g_assert (mono_error_ok (&error));
+ }
+ } else {
+ fsig = mono_metadata_parse_signature (method->klass->image, token);
+ }
+ return fsig;
+}
+
/*
* Returns TRUE if the JIT should abort inlining because "callee"
* is influenced by security attributes.
@@ -7007,11 +7030,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
CHECK_STACK (1);
--sp;
addr = *sp;
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- fsig = (MonoMethodSignature *)mono_method_get_wrapper_data (method, token);
- else
- fsig = mono_metadata_parse_signature (image, token);
-
+ fsig = mini_get_signature (method, token, generic_context);
n = fsig->param_count + fsig->hasthis;
if (method->dynamic && fsig->pinvoke) {
@@ -7030,38 +7049,36 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
}
} else {
MonoMethod *cil_method;
-
- if (method->wrapper_type != MONO_WRAPPER_NONE) {
- if (constrained_call && cfg->verbose_level > 2)
- printf ("DM Constrained call to %s\n", mono_type_get_full_name (constrained_call));
- cmethod = (MonoMethod *)mono_method_get_wrapper_data (method, token);
- cil_method = cmethod;
- if (constrained_call && !((constrained_call->byval_arg.type == MONO_TYPE_VAR ||
- constrained_call->byval_arg.type == MONO_TYPE_MVAR) &&
- cfg->generic_sharing_context)) {
- cmethod = mono_get_method_constrained_with_method (image, cil_method, constrained_call, generic_context);
- }
- } else if (constrained_call) {
- if (cfg->verbose_level > 2)
- printf ("Constrained call to %s\n", mono_type_get_full_name (constrained_call));
- if ((constrained_call->byval_arg.type == MONO_TYPE_VAR || constrained_call->byval_arg.type == MONO_TYPE_MVAR) && cfg->generic_sharing_context) {
- /*
- * This is needed since get_method_constrained can't find
- * the method in klass representing a type var.
- * The type var is guaranteed to be a reference type in this
- * case.
- */
- cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
- cil_method = cmethod;
- if (!mini_is_gsharedvt_klass (cfg, constrained_call))
- g_assert (!cmethod->klass->valuetype);
+ cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
+ cil_method = cmethod;
+
+ if (constrained_call) {
+ if (method->wrapper_type != MONO_WRAPPER_NONE) {
+ if (cfg->verbose_level > 2)
+ printf ("DM Constrained call to %s\n", mono_type_get_full_name (constrained_call));
+ if (!((constrained_call->byval_arg.type == MONO_TYPE_VAR ||
+ constrained_call->byval_arg.type == MONO_TYPE_MVAR) &&
+ cfg->generic_sharing_context)) {
+ cmethod = mono_get_method_constrained_with_method (image, cil_method, constrained_call, generic_context);
+ }
} else {
- cmethod = mono_get_method_constrained (image, token, constrained_call, generic_context, &cil_method);
+ if (cfg->verbose_level > 2)
+ printf ("Constrained call to %s\n", mono_type_get_full_name (constrained_call));
+
+ if ((constrained_call->byval_arg.type == MONO_TYPE_VAR || constrained_call->byval_arg.type == MONO_TYPE_MVAR) && cfg->generic_sharing_context) {
+ /*
+ * This is needed since get_method_constrained can't find
+ * the method in klass representing a type var.
+ * The type var is guaranteed to be a reference type in this
+ * case.
+ */
+ if (!mini_is_gsharedvt_klass (cfg, constrained_call))
+ g_assert (!cmethod->klass->valuetype);
+ } else {
+ cmethod = mono_get_method_constrained (image, token, constrained_call, generic_context, &cil_method);
+ }
}
- } else {
- cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
- cil_method = cmethod;
}
if (!cmethod || mono_loader_get_last_error ())
@@ -11024,10 +11041,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
case CEE_CONSTRAINED_:
CHECK_OPSIZE (6);
token = read32 (ip + 2);
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- constrained_call = (MonoClass *)mono_method_get_wrapper_data (method, token);
- else
- constrained_call = mono_class_get_full (image, token, generic_context);
+ constrained_call = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (constrained_call);
ip += 6;
break;
View
4 mono/mini/mini-generic-sharing.c
@@ -1652,10 +1652,8 @@ mono_generic_context_is_sharable (MonoGenericContext *context, gboolean allow_ty
gboolean
mono_method_is_generic_impl (MonoMethod *method)
{
- if (method->is_inflated) {
- g_assert (method->wrapper_type == MONO_WRAPPER_NONE);
+ if (method->is_inflated)
return TRUE;
- }
/* We don't treat wrappers as generic code, i.e., we never
apply generic sharing to them. This is especially
important for static rgctx invoke wrappers, which only work

0 comments on commit 8465f13

Please sign in to comment.
Something went wrong with that request. Please try again.