g_free (pair);
}
+static MonoMethodSignature*
+sig_to_rgctx_sig (MonoMethodSignature *sig)
+{
+ // FIXME: memory allocation
+ MonoMethodSignature *res;
+ int i;
+
+ res = g_malloc (MONO_SIZEOF_METHOD_SIGNATURE + (sig->param_count + 1) * sizeof (MonoType*));
+ memcpy (res, sig, MONO_SIZEOF_METHOD_SIGNATURE);
+ res->param_count = sig->param_count + 1;
+ res->params [0] = &mono_defaults.int_class->byval_arg;
+ for (i = 0; i < sig->param_count; ++i)
+ res->params [i + 1] = sig->params [i];
+ return res;
+}
+
MonoMethod *
mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt, gboolean static_method_with_first_arg_bound, MonoMethod *target_method)
{
SignaturePointerPair key;
SignaturePointerPair *new_key;
int local_i, local_len, local_delegates, local_d, local_target, local_res;
- int pos0, pos1, pos2;
+ int pos0, pos1, pos2, pos3, pos4;
char *name;
MonoClass *target_class = NULL;
gboolean closed_over_null = FALSE;
// FIXME:
mono_mb_emit_exception_full (mb, "System", "NotImplementedException", "");
} else {
+ MonoMethodSignature *rgctx_sig;
+
+ // FIXME: Support this for the other cases as well
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, rgctx));
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ pos3 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ /* Rgctx case */
+ rgctx_sig = sig_to_rgctx_sig (sig);
+
+ mono_mb_emit_ldloc (mb, local_target);
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, rgctx));
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ for (i = 0; i < sig->param_count; ++i)
+ mono_mb_emit_ldarg (mb, i + 1);
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_op (mb, CEE_CALLI, rgctx_sig);
+ pos4 = mono_mb_emit_branch (mb, CEE_BR);
+
+ /* Non-rgctx case */
+ mono_mb_patch_branch (mb, pos3);
mono_mb_emit_ldloc (mb, local_target);
for (i = 0; i < sig->param_count; ++i)
mono_mb_emit_ldarg (mb, i + 1);
mono_mb_emit_byte (mb, CEE_LDIND_I );
mono_mb_emit_op (mb, CEE_CALLI, sig);
+ mono_mb_patch_branch (mb, pos4);
+
mono_mb_emit_byte (mb, CEE_RET);
}
mono_mb_emit_op (mb, CEE_CALL, target_method);
}
} else {
+ MonoMethodSignature *rgctx_sig;
+
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, rgctx));
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ pos3 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ /* Rgctx case */
+ rgctx_sig = sig_to_rgctx_sig (invoke_sig);
+
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, rgctx));
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
if (static_method_with_first_arg_bound) {
mono_mb_emit_ldloc (mb, local_target);
if (!MONO_TYPE_IS_REFERENCE (invoke_sig->params[0]))
mono_mb_emit_ldarg (mb, i + 1);
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
- mono_mb_emit_byte (mb, CEE_LDIND_I );
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_op (mb, CEE_CALLI, rgctx_sig);
+ pos4 = mono_mb_emit_branch (mb, CEE_BR);
+
+ /* Non-rgctx case */
+ mono_mb_patch_branch (mb, pos3);
+ if (static_method_with_first_arg_bound) {
+ mono_mb_emit_ldloc (mb, local_target);
+ if (!MONO_TYPE_IS_REFERENCE (invoke_sig->params[0]))
+ mono_mb_emit_op (mb, CEE_UNBOX_ANY, mono_class_from_mono_type (invoke_sig->params[0]));
+ }
+ for (i = 0; i < sig->param_count; ++i)
+ mono_mb_emit_ldarg (mb, i + 1);
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
mono_mb_emit_op (mb, CEE_CALLI, invoke_sig);
+
+ mono_mb_patch_branch (mb, pos4);
}
mono_mb_emit_byte (mb, CEE_RET);
}
#endif
-static MonoMethodSignature*
-sig_to_rgctx_sig (MonoMethodSignature *sig)
-{
- // FIXME: memory allocation
- MonoMethodSignature *res;
- int i;
-
- res = g_malloc (MONO_SIZEOF_METHOD_SIGNATURE + (sig->param_count + 1) * sizeof (MonoType*));
- memcpy (res, sig, MONO_SIZEOF_METHOD_SIGNATURE);
- res->param_count = sig->param_count + 1;
- res->params [0] = &mono_defaults.int_class->byval_arg;
- for (i = 0; i < sig->param_count; ++i)
- res->params [i + 1] = sig->params [i];
- return res;
-}
-
/*
* generates IL code for the runtime invoke function
* MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc, void* method)