method = delegate->method;
+ if (mono_method_signature (method)->pinvoke) {
+ const char *exc_class, *exc_arg;
+ gpointer ftnptr;
+
+ ftnptr = mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
+ if (!ftnptr) {
+ g_assert (exc_class);
+ mono_raise_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
+ }
+ return ftnptr;
+ }
+
wrapper = mono_marshal_get_managed_wrapper (method, klass, delegate->target);
delegate->delegate_trampoline = mono_compile_method (wrapper);
* MonoObject *runtime_invoke (MonoObject *this, void **params, MonoObject **exc, void* method)
*
* we also catch exceptions if exc != null
+ * If VIRTUAL is TRUE, then METHOD is invoked virtually on THIS. This is useful since
+ * it means that the compiled code for METHOD does not have to be looked up
+ * before calling the runtime invoke wrapper. In this case, the wrapper ignores
+ * its METHOD argument.
*/
MonoMethod *
-mono_marshal_get_runtime_invoke (MonoMethod *method)
+mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual)
{
MonoMethodSignature *sig, *csig, *callsig;
MonoExceptionClause *clause;
finalize_signature->hasthis = 1;
}
+ if (virtual)
+ need_direct_wrapper = TRUE;
+
/*
* Use a separate cache indexed by methods to speed things up and to avoid the
* boundless mempool growth caused by the signature_dup stuff below.
*/
- cache = get_cache (&method->klass->image->runtime_invoke_direct_cache, mono_aligned_addr_hash, NULL);
+ if (virtual)
+ cache = get_cache (&method->klass->image->runtime_invoke_vcall_cache, mono_aligned_addr_hash, NULL);
+ else
+ cache = get_cache (&method->klass->image->runtime_invoke_direct_cache, mono_aligned_addr_hash, NULL);
res = mono_marshal_find_in_cache (cache, method);
if (res)
return res;
callsig = lookup_string_ctor_signature (mono_method_signature (method));
if (!callsig)
callsig = add_string_ctor_signature (method);
+ /* Can't share this as we push a string as this */
+ need_direct_wrapper = TRUE;
} else {
if (method->klass->valuetype && mono_method_signature (method)->hasthis) {
/*
csig->params [2] = &mono_defaults.int_class->byval_arg;
csig->params [3] = &mono_defaults.int_class->byval_arg;
- name = mono_signature_to_name (callsig, "runtime_invoke");
+ name = mono_signature_to_name (callsig, virtual ? "runtime_invoke_virtual" : "runtime_invoke");
mb = mono_mb_new (target_klass, name, MONO_WRAPPER_RUNTIME_INVOKE);
g_free (name);
emit_thread_force_interrupt_checkpoint (mb);
+ if (virtual) {
+ g_assert (sig->hasthis);
+ g_assert (method->flags & METHOD_ATTRIBUTE_VIRTUAL);
+ }
+
if (sig->hasthis) {
if (method->string_ctor) {
mono_mb_emit_ptr (mb, string_dummy);
}
}
- if (need_direct_wrapper) {
+ if (virtual) {
+ mono_mb_emit_op (mb, CEE_CALLVIRT, method);
+ } else if (need_direct_wrapper) {
mono_mb_emit_op (mb, CEE_CALL, method);
} else {
mono_mb_emit_ldarg (mb, 3);
MonoClass *klass = mono_class_from_mono_type (t);
int pos, pos2, loc;
- if (mono_class_from_mono_type (t) == mono_defaults.object_class) {
- mono_raise_exception (mono_get_exception_not_implemented ("Marshalling of type object is not implemented"));
- }
-
switch (action) {
case MARSHAL_ACTION_CONV_IN:
*conv_arg_type = &mono_defaults.int_class->byval_arg;
conv_arg = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
m->orig_conv_args [argnum] = 0;
-
+
+ if (mono_class_from_mono_type (t) == mono_defaults.object_class) {
+ char *msg = g_strdup_printf ("Marshalling of type object is not implemented");
+ mono_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
if (klass->delegate) {
if (t->byref) {
if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) {
return mono_cominterop_emit_marshal_com_interface (m, argnum, t, spec, conv_arg, conv_arg_type, action);
#endif
- if (mono_defaults.safehandle_class != NULL &&
+ if (mono_defaults.safehandle_class != NULL && t->data.klass &&
mono_class_is_subclass_of (t->data.klass, mono_defaults.safehandle_class, FALSE))
return emit_marshal_safehandle (m, argnum, t, spec, conv_arg, conv_arg_type, action);