+
+static MonoMethod*
+constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *this_arg)
+{
+ MonoMethod *m;
+ int vt_slot;
+
+ if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
+ mono_raise_exception (mono_get_exception_execution_engine ("Not yet supported."));
+
+ if (mono_method_signature (cmethod)->pinvoke) {
+ /* Object.GetType () */
+ m = mono_marshal_get_native_wrapper (cmethod, TRUE, FALSE);
+ } else {
+ /* Lookup the virtual method */
+ mono_class_setup_vtable (klass);
+ g_assert (klass->vtable);
+ vt_slot = mono_method_get_vtable_slot (cmethod);
+ if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ int iface_offset;
+
+ iface_offset = mono_class_interface_offset (klass, cmethod->klass);
+ g_assert (iface_offset != -1);
+ vt_slot += iface_offset;
+ }
+ m = klass->vtable [vt_slot];
+ }
+ if (klass->valuetype && (m->klass == mono_defaults.object_class || m->klass == mono_defaults.enum_class->parent || m->klass == mono_defaults.enum_class))
+ /*
+ * Calling a non-vtype method with a vtype receiver, has to box.
+ */
+ *this_arg = mono_value_box (mono_domain_get (), klass, mp);
+ else if (klass->valuetype)
+ /*
+ * Calling a vtype method with a vtype receiver
+ */
+ *this_arg = mp;
+ else
+ /*
+ * Calling a non-vtype method
+ */
+ *this_arg = *(gpointer*)mp;
+ return m;
+}
+
+/*
+ * mono_gsharedvt_constrained_call:
+ *
+ * Make a call to CMETHOD using the receiver MP, which is assumed to be of type KLASS. ARGS contains
+ * the arguments to the method in the format used by mono_runtime_invoke ().
+ */
+MonoObject*
+mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean deref_arg, gpointer *args)
+{
+ MonoMethod *m;
+ gpointer this_arg;
+ gpointer new_args [16];
+
+ m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
+ if (args && deref_arg) {
+ new_args [0] = *(gpointer*)args [0];
+ args = new_args;
+ }
+ if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
+ /* Object.GetType () */
+ args = new_args;
+ args [0] = this_arg;
+ this_arg = NULL;
+ }
+ return mono_runtime_invoke (m, this_arg, args, NULL);
+}
+
+void
+mono_gsharedvt_value_copy (gpointer dest, gpointer src, MonoClass *klass)
+{
+ if (klass->valuetype)
+ mono_value_copy (dest, src, klass);
+ else
+ mono_gc_wbarrier_generic_store (dest, *(MonoObject**)src);
+}