#include "metadata/appdomain.h"
#include "mono/metadata/debug-helpers.h"
#include "mono/metadata/threadpool.h"
+#include "mono/metadata/monitor.h"
#include <string.h>
//#define DEBUG_RUNTIME_CODE
g_assert (dst != NULL);
g_assert (size > 0);
- if (!src) {
- memset (dst, 0, size);
+ memset (dst, 0, size);
+
+ if (!src)
return;
- }
s = mono_string_to_utf8 (src);
len = MIN (size, strlen (s));
{
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
- mono_mb_emit_icon (mb, offset);
- mono_mb_emit_byte (mb, CEE_ADD);
+
+ if (offset) {
+ mono_mb_emit_icon (mb, offset);
+ mono_mb_emit_byte (mb, CEE_ADD);
+ }
+}
+
+static int
+mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
+{
+ int pos;
+ mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoObject, vtable));
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoVTable, klass));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
+ mono_mb_emit_i4 (mb, mono_mb_add_data (mb, mono_defaults.transparent_proxy_class));
+ mono_mb_emit_byte (mb, branch_code);
+ pos = mb->pos;
+ mono_mb_emit_i4 (mb, 0);
+ return pos;
}
void
}
void
-mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint8 local, gint8 incr)
+mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
{
mono_mb_emit_ldloc (mb, local);
mono_mb_emit_icon (mb, incr);
/* skip the this pointer */
params++;
+ if (this->klass->contextbound && this->rp->context == (MonoObject *) mono_context_get ())
+ {
+ int i;
+ MonoMethodSignature *sig = method->signature;
+ int count = sig->param_count;
+ gpointer mparams[count];
+
+ for (i=0; i<count; i++) {
+ MonoClass *class = mono_class_from_mono_type (sig->params [i]);
+ if (class->valuetype) {
+ if (sig->params [i]->byref)
+ mparams[i] = *((gpointer *)params [i]);
+ else
+ mparams[i] = params [i];
+ } else {
+ mparams[i] = *((gpointer**)params [i]);
+ }
+ }
+
+ return mono_runtime_invoke (method, this->rp->unwrapped_server, mparams, NULL);
+ }
+
msg = mono_method_call_message_new (method, params, NULL, NULL, NULL);
res = mono_remoting_invoke ((MonoObject *)this->rp, msg, &exc, &out_args);
return res;
if (!csig) {
- int sigsize = sizeof (MonoMethodSignature) + 2 * sizeof (MonoType *);
- csig = g_malloc0 (sigsize);
-
- /* MonoObject *remoting_wrapper (MonoMethod *method, gpointer params[]) */
- csig->param_count = 2;
- csig->ret = &mono_defaults.object_class->byval_arg;
+ csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
csig->params [0] = &mono_defaults.int_class->byval_arg;
csig->params [1] = &mono_defaults.int_class->byval_arg;
+ csig->ret = &mono_defaults.object_class->byval_arg;
+ csig->pinvoke = 1;
}
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE);
mono_mb_emit_ldloc (mb, params_var);
mono_mb_emit_native_call (mb, csig, mono_remoting_wrapper);
- if (sig->ret->type == MONO_TYPE_VOID)
+ if (sig->ret->type == MONO_TYPE_VOID) {
mono_mb_emit_byte (mb, CEE_POP);
- else
- mono_mb_emit_restore_result (mb, sig->ret);
+ mono_mb_emit_byte (mb, CEE_RET);
+ } else {
+ mono_mb_emit_restore_result (mb, sig->ret);
+ }
res = mono_mb_create_method (mb, sig, sig->param_count + 16);
mono_mb_free (mb);
return res;
}
+MonoMethod *
+mono_marshal_get_remoting_invoke_with_check (MonoMethod *method)
+{
+ MonoMethodSignature *sig;
+ MonoMethodBuilder *mb;
+ MonoMethod *res, *native;
+ GHashTable *cache;
+ int i, pos;
+
+ g_assert (method);
+
+ if (method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
+ return method;
+
+ sig = method->signature;
+
+ /* we cant remote methods without this pointer */
+ g_assert (sig->hasthis);
+
+ cache = method->klass->image->remoting_invoke_cache;
+ if ((res = (MonoMethod *)g_hash_table_lookup (cache, (char *)method + 1)))
+ return res;
+
+ mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK);
+
+ mono_mb_emit_ldarg (mb, 0);
+ pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
+
+ native = mono_marshal_get_remoting_invoke (method);
+
+ for (i = 0; i <= sig->param_count; i++)
+ mono_mb_emit_ldarg (mb, i);
+
+ mono_mb_emit_managed_call (mb, native, native->signature);
+ mono_mb_emit_byte (mb, CEE_RET);
+
+ mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
+
+ for (i = 0; i <= sig->param_count; i++)
+ mono_mb_emit_ldarg (mb, i);
+
+ mono_mb_emit_managed_call (mb, method, method->signature);
+ mono_mb_emit_byte (mb, CEE_RET);
+
+ res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ mono_mb_free (mb);
+ g_hash_table_insert (cache, (char *)method + 1, res);
+ return res;
+}
+
/*
* the returned method invokes all methods in a multicast delegate
*/
int i, pos, sigsize, *tmp_locals;
g_assert (method != NULL);
+ g_assert (!method->signature->pinvoke);
cache = method->klass->image->managed_wrapper_cache;
if (!this && (res = (MonoMethod *)g_hash_table_lookup (cache, method)))
case MONO_TYPE_R8:
case MONO_TYPE_I8:
case MONO_TYPE_U8:
- /* do nothing */
+ case MONO_TYPE_OBJECT:
+ mono_mb_emit_byte (mb, CEE_RET);
break;
case MONO_TYPE_STRING:
csig->ret = &mono_defaults.int_class->byval_arg;
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_byte (mb, CEE_MONO_FUNC1);
mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
+ mono_mb_emit_byte (mb, CEE_RET);
break;
case MONO_TYPE_VALUETYPE: {
int tmp;
g_warning ("return type 0x%02x unknown", sig->ret->type);
g_assert_not_reached ();
}
+ } else {
+ mono_mb_emit_byte (mb, CEE_RET);
}
- mono_mb_emit_byte (mb, CEE_RET);
-
res = mono_mb_create_method (mb, csig, sig->param_count + 16);
mono_mb_free (mb);
return res;
}
+/*
+ * mono_marshal_get_ldfld_wrapper:
+ * @type: the type of the field
+ *
+ * This method generates a function which can be use to load a field with type
+ * @type from an object. The generated function has the following signature:
+ * <@type> ldfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset)
+ */
+MonoMethod *
+mono_marshal_get_ldfld_wrapper (MonoType *type)
+{
+ MonoMethodSignature *sig, *csig;
+ MonoMethodBuilder *mb;
+ MonoMethod *res;
+ MonoClass *klass;
+ static GHashTable *ldfld_hash = NULL;
+ char *name;
+ int t, pos0, pos1;
+
+ if (!ldfld_hash)
+ ldfld_hash = g_hash_table_new (NULL, NULL);
+
+
+ t = type->type;
+
+ if (!type->byref) {
+ if (type->type == MONO_TYPE_SZARRAY) {
+ klass = mono_defaults.array_class;
+ } else if (type->type == MONO_TYPE_VALUETYPE) {
+ klass = type->data.klass;
+ if (klass->enumtype) {
+ t = klass->enum_basetype->type;
+ klass = mono_class_from_mono_type (klass->enum_basetype);
+ }
+ } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
+ t == MONO_TYPE_CLASS) {
+ klass = mono_defaults.object_class;
+ } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
+ klass = mono_defaults.int_class;
+ } else {
+ klass = mono_class_from_mono_type (type);
+ }
+ } else {
+ klass = mono_defaults.int_class;
+ }
+
+ if ((res = g_hash_table_lookup (ldfld_hash, klass)))
+ return res;
+
+ name = g_strdup_printf ("__ldfld_wrapper_%s.%s", klass->name_space, klass->name);
+ mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
+ g_free (name);
+
+ mb->method->save_lmf = 1;
+
+ sig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
+ sig->params [0] = &mono_defaults.object_class->byval_arg;
+ sig->params [1] = &mono_defaults.int_class->byval_arg;
+ sig->params [2] = &mono_defaults.int_class->byval_arg;
+ sig->params [3] = &mono_defaults.int_class->byval_arg;
+ sig->ret = &klass->byval_arg;
+
+ mono_mb_emit_ldarg (mb, 0);
+ pos0 = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
+
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_ldarg (mb, 1);
+ mono_mb_emit_ldarg (mb, 2);
+
+ csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
+ csig->params [0] = &mono_defaults.object_class->byval_arg;
+ csig->params [1] = &mono_defaults.int_class->byval_arg;
+ csig->params [2] = &mono_defaults.int_class->byval_arg;
+ csig->ret = &klass->this_arg;
+ csig->pinvoke = 1;
+
+ mono_mb_emit_native_call (mb, csig, mono_load_remote_field_new);
+
+ if (klass->valuetype) {
+ mono_mb_emit_byte (mb, CEE_UNBOX);
+ mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
+ mono_mb_emit_byte (mb, CEE_BR);
+ pos1 = mb->pos;
+ mono_mb_emit_i4 (mb, 0);
+ } else {
+ mono_mb_emit_byte (mb, CEE_RET);
+ }
+
+
+ mono_mb_patch_addr (mb, pos0, mb->pos - (pos0 + 4));
+
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
+ mono_mb_emit_ldarg (mb, 3);
+ mono_mb_emit_byte (mb, CEE_ADD);
+
+ if (klass->valuetype)
+ mono_mb_patch_addr (mb, pos1, mb->pos - (pos1 + 4));
+
+ switch (t) {
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_BOOLEAN:
+ mono_mb_emit_byte (mb, CEE_LDIND_I1);
+ break;
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ mono_mb_emit_byte (mb, CEE_LDIND_I2);
+ break;
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ mono_mb_emit_byte (mb, CEE_LDIND_I4);
+ break;
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ mono_mb_emit_byte (mb, CEE_LDIND_I8);
+ break;
+ case MONO_TYPE_R4:
+ mono_mb_emit_byte (mb, CEE_LDIND_R4);
+ break;
+ case MONO_TYPE_R8:
+ mono_mb_emit_byte (mb, CEE_LDIND_R8);
+ break;
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_FNPTR:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ break;
+ case MONO_TYPE_VALUETYPE:
+ g_assert (!klass->enumtype);
+ mono_mb_emit_byte (mb, CEE_LDOBJ);
+ mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
+ break;
+ default:
+ g_warning ("type %x not implemented", type->type);
+ g_assert_not_reached ();
+ }
+
+ mono_mb_emit_byte (mb, CEE_RET);
+
+ res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ mono_mb_free (mb);
+
+ g_hash_table_insert (ldfld_hash, klass, res);
+
+ return res;
+}
+
+/*
+ * mono_marshal_get_stfld_wrapper:
+ * @type: the type of the field
+ *
+ * This method generates a function which can be use to store a field with type
+ * @type. The generated function has the following signature:
+ * void stfld_wrapper (MonoObject *this, MonoClass *class, MonoClassField *field, int offset, <@type> val)
+ */
+MonoMethod *
+mono_marshal_get_stfld_wrapper (MonoType *type)
+{
+ MonoMethodSignature *sig, *csig;
+ MonoMethodBuilder *mb;
+ MonoMethod *res;
+ MonoClass *klass;
+ static GHashTable *stfld_hash = NULL;
+ char *name;
+ int t, pos;
+
+ if (!stfld_hash)
+ stfld_hash = g_hash_table_new (NULL, NULL);
+
+ t = type->type;
+
+ if (!type->byref) {
+ if (type->type == MONO_TYPE_SZARRAY) {
+ klass = mono_defaults.array_class;
+ } else if (type->type == MONO_TYPE_VALUETYPE) {
+ klass = type->data.klass;
+ if (klass->enumtype) {
+ t = klass->enum_basetype->type;
+ klass = mono_class_from_mono_type (klass->enum_basetype);
+ }
+ } else if (t == MONO_TYPE_OBJECT || t == MONO_TYPE_CLASS || t == MONO_TYPE_STRING ||
+ t == MONO_TYPE_CLASS) {
+ klass = mono_defaults.object_class;
+ } else if (t == MONO_TYPE_PTR || t == MONO_TYPE_FNPTR) {
+ klass = mono_defaults.int_class;
+ } else {
+ klass = mono_class_from_mono_type (type);
+ }
+ } else {
+ klass = mono_defaults.int_class;
+ }
+
+ if ((res = g_hash_table_lookup (stfld_hash, klass)))
+ return res;
+
+ name = g_strdup_printf ("__stfld_wrapper_%s.%s", klass->name_space, klass->name);
+ mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_STFLD);
+ g_free (name);
+
+ mb->method->save_lmf = 1;
+
+ sig = mono_metadata_signature_alloc (mono_defaults.corlib, 5);
+ sig->params [0] = &mono_defaults.object_class->byval_arg;
+ sig->params [1] = &mono_defaults.int_class->byval_arg;
+ sig->params [2] = &mono_defaults.int_class->byval_arg;
+ sig->params [3] = &mono_defaults.int_class->byval_arg;
+ sig->params [4] = &klass->byval_arg;
+ sig->ret = &mono_defaults.void_class->byval_arg;
+
+ mono_mb_emit_ldarg (mb, 0);
+ pos = mono_mb_emit_proxy_check (mb, CEE_BNE_UN);
+
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_ldarg (mb, 1);
+ mono_mb_emit_ldarg (mb, 2);
+ mono_mb_emit_ldarg (mb, 4);
+
+ if (klass->valuetype) {
+ mono_mb_emit_byte (mb, CEE_BOX);
+ mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
+ }
+
+ csig = mono_metadata_signature_alloc (mono_defaults.corlib, 4);
+ csig->params [0] = &mono_defaults.object_class->byval_arg;
+ csig->params [1] = &mono_defaults.int_class->byval_arg;
+ csig->params [2] = &mono_defaults.int_class->byval_arg;
+ csig->params [3] = &klass->this_arg;
+ csig->ret = &mono_defaults.void_class->byval_arg;
+ csig->pinvoke = 1;
+
+ mono_mb_emit_native_call (mb, csig, mono_store_remote_field_new);
+
+ mono_mb_emit_byte (mb, CEE_RET);
+
+ mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
+
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
+ mono_mb_emit_ldarg (mb, 3);
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_ldarg (mb, 4);
+
+ switch (t) {
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_BOOLEAN:
+ mono_mb_emit_byte (mb, CEE_STIND_I1);
+ break;
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ mono_mb_emit_byte (mb, CEE_STIND_I2);
+ break;
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ mono_mb_emit_byte (mb, CEE_STIND_I4);
+ break;
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ mono_mb_emit_byte (mb, CEE_STIND_I8);
+ break;
+ case MONO_TYPE_R4:
+ mono_mb_emit_byte (mb, CEE_STIND_R4);
+ break;
+ case MONO_TYPE_R8:
+ mono_mb_emit_byte (mb, CEE_STIND_R8);
+ break;
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_FNPTR:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+ break;
+ case MONO_TYPE_VALUETYPE:
+ g_assert (!klass->enumtype);
+ mono_mb_emit_byte (mb, CEE_STOBJ);
+ mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
+ break;
+ default:
+ g_warning ("type %x not implemented", type->type);
+ g_assert_not_reached ();
+ }
+
+ mono_mb_emit_byte (mb, CEE_RET);
+
+ res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ mono_mb_free (mb);
+
+ g_hash_table_insert (stfld_hash, klass, res);
+
+ return res;
+}
+
/*
* generates IL code for the icall wrapper (the generated method
* calls the unamnaged code in func)
*/
MonoMethod *
-mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gpointer func)
+mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, gconstpointer func)
{
MonoMethodSignature *csig;
MonoMethodBuilder *mb;
MonoMethod *res;
int i, sigsize;
+ g_assert (sig->pinvoke);
+
mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE);
mb->method->save_lmf = 1;
for (i = 0; i < sig->param_count; i++)
mono_mb_emit_ldarg (mb, i + sig->hasthis);
- csig = g_memdup (sig, sigsize);
- csig->pinvoke = 1;
-
- mono_mb_emit_native_call (mb, csig, func);
+ mono_mb_emit_native_call (mb, sig, (gpointer) func);
mono_mb_emit_byte (mb, CEE_RET);
+ csig = g_memdup (sig, sigsize);
+ csig->pinvoke = 0;
+
res = mono_mb_create_method (mb, csig, csig->param_count + 16);
mono_mb_free (mb);
int type, sigsize;
g_assert (method != NULL);
+ g_assert (method->signature->pinvoke);
cache = method->klass->image->native_wrapper_cache;
if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
return res;
sig = method->signature;
+ sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
if (!method->addr) {
mono_mb_emit_exception (mb);
- res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ csig = g_memdup (sig, sigsize);
+ csig->pinvoke = 0;
+ res = mono_mb_create_method (mb, csig, csig->param_count + 16);
mono_mb_free (mb);
g_hash_table_insert (cache, method, res);
return res;
}
- /* we copy the signature, so that we can modify it */
- sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
-
/* internal calls: we simply push all arguments and call the method (no conversions) */
if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
- MonoMethodSignature *call_sig;
-
/* hack - string constructors returns a value */
if (method->string_ctor) {
csig = g_memdup (sig, sigsize);
for (i = 0; i < sig->param_count; i++)
mono_mb_emit_ldarg (mb, i + sig->hasthis);
- call_sig = g_memdup (csig, sigsize);
- call_sig->pinvoke = 1;
-
g_assert (method->addr);
- mono_mb_emit_native_call (mb, call_sig, method->addr);
+ mono_mb_emit_native_call (mb, csig, method->addr);
mono_mb_emit_byte (mb, CEE_RET);
- res = mono_mb_create_method (mb, csig, sig->param_count + 16);
+ csig = g_memdup (csig, sigsize);
+ csig->pinvoke = 0;
+ res = mono_mb_create_method (mb, csig, csig->param_count + 16);
mono_mb_free (mb);
g_hash_table_insert (cache, method, res);
return res;
g_assert (pinvoke);
- mspecs = g_new (MonoMarshalSpec, sig->param_count + 1);
+ mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
mono_method_get_marshal_info (method, mspecs);
/* pinvoke: we need to convert the arguments if necessary */
+ /* we copy the signature, so that we can set pinvoke to 0 */
csig = g_memdup (sig, sigsize);
csig->pinvoke = 1;
mono_mb_emit_byte (mb, CEE_STLOC_0);
+ /* allocate space for the native struct and
+ * store the address into local variable 1 (dest) */
+ mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_LOCALLOC);
+ mono_mb_emit_stloc (mb, tmp_locals [i]);
+
if (t->byref) {
mono_mb_emit_byte (mb, CEE_LDLOC_0);
mono_mb_emit_byte (mb, CEE_BRFALSE);
mono_mb_emit_i4 (mb, 0);
}
- /* allocate space for the native struct and
- * store the address into local variable 1 (dest) */
- mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
- mono_mb_emit_byte (mb, CEE_PREFIX1);
- mono_mb_emit_byte (mb, CEE_LOCALLOC);
- mono_mb_emit_stloc (mb, tmp_locals [i]);
/* set dst_ptr */
mono_mb_emit_ldloc (mb, tmp_locals [i]);
mono_mb_emit_byte (mb, CEE_STLOC_1);
case MONO_NATIVE_LPWSTR:
mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPWSTR);
break;
+ case MONO_NATIVE_LPSTR:
+ mono_mb_emit_byte (mb, MONO_MARSHAL_CONV_STR_LPSTR);
+ break;
default:
- g_warning ("marshalling conversion not implemented");
+ g_warning ("marshalling conversion %d not implemented", spec->native);
g_assert_not_reached ();
}
} else {
mono_mb_emit_stloc (mb, tmp_locals [i]);
break;
case MONO_TYPE_CLASS:
- case MONO_TYPE_OBJECT:
if (t->byref)
continue;
mono_mb_emit_stloc (mb, tmp_locals [i]);
}
+ break;
+ case MONO_TYPE_OBJECT:
+ if (t->byref)
+ continue;
+ csig->params [argnum] = &mono_defaults.int_class->byval_arg;
+ tmp_locals [i] = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+ /*
+ * FIXME: this may need special handling to inspect the type
+ * at runtime.
+ */
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
+ /* fixme: convert to what ? */
+ mono_mb_emit_stloc (mb, tmp_locals [i]);
break;
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY:
g_assert (tmp_locals [i]);
mono_mb_emit_ldloc (mb, tmp_locals [i]);
if (!t->byref) {
- mono_mb_emit_byte (mb, CEE_LDOBJ);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDNATIVEOBJ);
mono_mb_emit_i4 (mb, mono_mb_add_data (mb, klass));
}
break;
if (klass->element_class == mono_defaults.string_class) {
g_assert (tmp_locals [i]);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, CEE_BRFALSE);
+ pos = mb->pos;
+ mono_mb_emit_i4 (mb, 0);
+
mono_mb_emit_ldloc (mb, tmp_locals [i]);
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_byte (mb, CEE_LDLEN);
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_byte (mb, CEE_MONO_PROC2);
mono_mb_emit_byte (mb, MONO_MARSHAL_FREE_ARRAY);
+
+ mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
}
break;
mono_mb_emit_byte (mb, CEE_RET);
- res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ csig = g_memdup (sig, sigsize);
+ csig->pinvoke = 0;
+ res = mono_mb_create_method (mb, csig, csig->param_count + 16);
mono_mb_free (mb);
g_hash_table_insert (cache, method, res);
if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
mono_mb_emit_byte (mb, CEE_LDARG_1);
mono_mb_emit_byte (mb, CEE_LDARG_0);
- mono_mb_emit_icon (mb, sizeof (MonoObject));
- mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_ldflda (mb, sizeof (MonoObject));
mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
mono_mb_emit_byte (mb, CEE_PREFIX1);
mono_mb_emit_byte (mb, CEE_CPBLK);
/* initialize src_ptr to point to the start of object data */
mono_mb_emit_byte (mb, CEE_LDARG_0);
- mono_mb_emit_icon (mb, sizeof (MonoObject));
- mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_ldflda (mb, sizeof (MonoObject));
mono_mb_emit_byte (mb, CEE_STLOC_0);
/* initialize dst_ptr */
if (((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) || klass->blittable) {
mono_mb_emit_byte (mb, CEE_LDARG_1);
- mono_mb_emit_icon (mb, sizeof (MonoObject));
- mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_ldflda (mb, sizeof (MonoObject));
mono_mb_emit_byte (mb, CEE_LDARG_0);
mono_mb_emit_icon (mb, mono_class_value_size (klass, NULL));
mono_mb_emit_byte (mb, CEE_PREFIX1);
/* initialize dst_ptr */
mono_mb_emit_byte (mb, CEE_LDARG_1);
- mono_mb_emit_icon (mb, sizeof (MonoObject));
- mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_ldflda (mb, sizeof (MonoObject));
mono_mb_emit_byte (mb, CEE_STLOC_1);
emit_struct_conv (mb, klass, TRUE);
return res;
}
+static MonoReflectionType *
+type_from_handle (MonoType *handle)
+{
+ MonoDomain *domain = mono_domain_get ();
+ MonoClass *klass = mono_class_from_mono_type (handle);
+
+ MONO_ARCH_SAVE_REGS;
+
+ mono_class_init (klass);
+ return mono_type_get_object (domain, handle);
+}
+
+/*
+ * generates IL code for the synchronized wrapper: the generated method
+ * calls METHOD while locking 'this' or the parent type.
+ */
+MonoMethod *
+mono_marshal_get_synchronized_wrapper (MonoMethod *method)
+{
+ static MonoMethodSignature *from_handle_sig = NULL;
+ static MonoMethod *enter_method, *exit_method;
+ MonoMethodSignature *sig;
+ MonoExceptionClause *clause;
+ MonoMethodHeader *header;
+ MonoMethodBuilder *mb;
+ MonoMethod *res;
+ GHashTable *cache;
+ int i, pos, this_local, ret_local;
+
+ g_assert (method);
+
+ if (method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED)
+ return method;
+
+ cache = method->klass->image->synchronized_cache;
+ if ((res = (MonoMethod *)g_hash_table_lookup (cache, method)))
+ return res;
+
+ sig = method->signature;
+
+ mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
+
+ /* result */
+ if (!MONO_TYPE_IS_VOID (sig->ret))
+ ret_local = mono_mb_add_local (mb, sig->ret);
+
+ /* this */
+ this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
+
+ clause = g_new0 (MonoExceptionClause, 1);
+ clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
+
+ if (!enter_method) {
+ MonoMethodDesc *desc;
+
+ desc = mono_method_desc_new ("Monitor:Enter", FALSE);
+ enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
+ g_assert (enter_method);
+ mono_method_desc_free (desc);
+ desc = mono_method_desc_new ("Monitor:Exit", FALSE);
+ exit_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
+ g_assert (exit_method);
+ mono_method_desc_free (desc);
+
+ /*
+ * GetTypeFromHandle isn't called as a managed method because it has
+ * a funky calling sequence, e.g. ldtoken+GetTypeFromHandle gets
+ * transformed into something else by the JIT.
+ */
+ from_handle_sig = mono_metadata_signature_alloc (mono_defaults.corlib, 1);
+ from_handle_sig->params [0] = &mono_defaults.object_class->byval_arg;
+ from_handle_sig->ret = &mono_defaults.object_class->byval_arg;
+ }
+
+ /* Push this or the type object */
+ if (method->flags & METHOD_ATTRIBUTE_STATIC) {
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDPTR);
+ mono_mb_emit_i4 (mb, mono_mb_add_data (mb, &method->klass->byval_arg));
+ mono_mb_emit_native_call (mb, from_handle_sig, type_from_handle);
+ }
+ else
+ mono_mb_emit_ldarg (mb, 0);
+ mono_mb_emit_stloc (mb, this_local);
+
+ /* Call Monitor::Enter() */
+ mono_mb_emit_ldloc (mb, this_local);
+ mono_mb_emit_managed_call (mb, enter_method, NULL);
+
+ clause->try_offset = mb->pos;
+
+ /* Call the method */
+ if (sig->hasthis)
+ mono_mb_emit_ldarg (mb, 0);
+ for (i = 0; i < sig->param_count; i++)
+ mono_mb_emit_ldarg (mb, i + (sig->hasthis == TRUE));
+ mono_mb_emit_managed_call (mb, method, method->signature);
+ if (!MONO_TYPE_IS_VOID (sig->ret))
+ mono_mb_emit_stloc (mb, ret_local);
+
+ mono_mb_emit_byte (mb, CEE_LEAVE);
+ pos = mb->pos;
+ mono_mb_emit_i4 (mb, 0);
+
+ clause->try_len = mb->pos - clause->try_offset;
+ clause->handler_offset = mb->pos;
+
+ /* Call Monitor::Exit() */
+ mono_mb_emit_ldloc (mb, this_local);
+// mono_mb_emit_native_call (mb, exit_sig, mono_monitor_exit);
+ mono_mb_emit_managed_call (mb, exit_method, NULL);
+ mono_mb_emit_byte (mb, CEE_ENDFINALLY);
+
+ clause->handler_len = mb->pos - clause->handler_offset;
+
+ mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
+ if (!MONO_TYPE_IS_VOID (sig->ret))
+ mono_mb_emit_ldloc (mb, ret_local);
+ mono_mb_emit_byte (mb, CEE_RET);
+
+ res = mono_mb_create_method (mb, sig, sig->param_count + 16);
+ mono_mb_free (mb);
+
+ header = ((MonoMethodNormal *)res)->header;
+ header->num_clauses = 1;
+ header->clauses = clause;
+
+ g_hash_table_insert (cache, method, res);
+
+ return res;
+}
+
/* FIXME: on win32 we should probably use GlobalAlloc(). */
void*
mono_marshal_alloc (gpointer size)
}
void
-mono_marshal_free_array (gpointer *ptr, int size) {
+mono_marshal_free_array (gpointer *ptr, int size)
+{
int i;
+ if (!ptr)
+ return;
+
for (i = 0; i < size; i++)
if (ptr [i])
g_free (ptr [i]);