#include "metadata/appdomain.h"
#include "mono/metadata/abi-details.h"
#include "mono/metadata/debug-helpers.h"
-#include "mono/metadata/threadpool.h"
#include "mono/metadata/threads.h"
#include "mono/metadata/monitor.h"
+#include "mono/metadata/class-internals.h"
#include "mono/metadata/metadata-internals.h"
#include "mono/metadata/domain-internals.h"
#include "mono/metadata/gc-internal.h"
#include "mono/metadata/cominterop.h"
#include "mono/metadata/remoting.h"
#include "mono/metadata/reflection-internals.h"
+#include "mono/metadata/threadpool-ms.h"
#include "mono/utils/mono-counters.h"
#include "mono/utils/mono-tls.h"
#include "mono/utils/mono-memory-model.h"
static void
mono_marshal_set_last_error_windows (int error);
+static MonoObject *
+mono_marshal_isinst_with_cache (MonoObject *obj, MonoClass *klass, uintptr_t *cache);
+
static void init_safe_handle (void);
/* MonoMethod pointers to SafeHandle::DangerousAddRef and ::DangerousRelease */
mono_register_jit_icall (func, name, sig, save);
}
-static MonoMethodSignature*
-signature_dup (MonoImage *image, MonoMethodSignature *sig)
-{
- MonoMethodSignature *res;
- int sigsize;
-
- res = mono_metadata_signature_alloc (image, sig->param_count);
- sigsize = MONO_SIZEOF_METHOD_SIGNATURE + sig->param_count * sizeof (MonoType *);
- memcpy (res, sig, sigsize);
-
- return res;
-}
-
MonoMethodSignature*
mono_signature_no_pinvoke (MonoMethod *method)
{
MonoMethodSignature *sig = mono_method_signature (method);
if (sig->pinvoke) {
- sig = signature_dup (method->klass->image, sig);
+ sig = mono_metadata_signature_dup_full (method->klass->image, sig);
sig->pinvoke = FALSE;
}
register_icall (mono_context_set, "mono_context_set", "void object", FALSE);
register_icall (mono_gc_wbarrier_generic_nostore, "wb_generic", "void ptr", FALSE);
register_icall (mono_gchandle_get_target, "mono_gchandle_get_target", "object int32", TRUE);
+ register_icall (mono_marshal_isinst_with_cache, "mono_marshal_isinst_with_cache", "object object ptr ptr", FALSE);
mono_cominterop_init ();
mono_remoting_init ();
#ifdef USE_COOP_GC
register_icall (mono_threads_prepare_blocking, "mono_threads_prepare_blocking", "int", FALSE);
register_icall (mono_threads_finish_blocking, "mono_threads_finish_blocking", "void int", FALSE);
- register_icall (mono_threads_reset_blocking_start, "mono_threads_reset_blocking_start","int", FALSE);
- register_icall (mono_threads_reset_blocking_end, "mono_threads_reset_blocking_end","void int", FALSE);
+ register_icall (mono_threads_reset_blocking_start, "mono_threads_reset_blocking_start","int", TRUE);
+ register_icall (mono_threads_reset_blocking_end, "mono_threads_reset_blocking_end","void int", TRUE);
#endif
}
}
MonoMarshalSpec **mspecs;
MonoMethod *invoke = mono_get_delegate_invoke (klass);
MonoMethodPInvoke piinfo;
- MonoObject *this;
+ MonoObject *this_obj;
int i;
if (use_aot_wrappers) {
wrapper = mono_marshal_get_native_func_wrapper_aot (klass);
- this = mono_value_box (mono_domain_get (), mono_defaults.int_class, &ftn);
+ this_obj = mono_value_box (mono_domain_get (), mono_defaults.int_class, &ftn);
} else {
memset (&piinfo, 0, sizeof (piinfo));
parse_unmanaged_function_pointer_attr (klass, &piinfo);
sig->hasthis = 0;
wrapper = mono_marshal_get_native_func_wrapper (klass->image, sig, &piinfo, mspecs, ftn);
- this = NULL;
+ this_obj = NULL;
for (i = mono_method_signature (invoke)->param_count; i >= 0; i--)
if (mspecs [i])
}
d = (MonoDelegate*)mono_object_new (mono_domain_get (), klass);
- mono_delegate_ctor_with_method ((MonoObject*)d, this, mono_compile_method (wrapper), wrapper);
+ mono_delegate_ctor_with_method ((MonoObject*)d, this_obj, mono_compile_method (wrapper), wrapper);
}
if (d->object.vtable->domain != mono_domain_get ())
if (initial_len < 0)
initial_len = 0;
- if (!string_builder_class) {
+ if (!sb_ctor) {
MonoMethodDesc *desc;
+ MonoMethod *m;
string_builder_class = mono_class_from_name (mono_defaults.corlib, "System.Text", "StringBuilder");
g_assert (string_builder_class);
desc = mono_method_desc_new (":.ctor(int)", FALSE);
- sb_ctor = mono_method_desc_search_in_class (desc, string_builder_class);
- g_assert (sb_ctor);
+ m = mono_method_desc_search_in_class (desc, string_builder_class);
+ g_assert (m);
mono_method_desc_free (desc);
-
- // We make a new array in the _to_builder function, so this
- // array will always be garbage collected.
- args [0] = &initial_len;
+ mono_memory_barrier ();
+ sb_ctor = m;
}
+ // We make a new array in the _to_builder function, so this
+ // array will always be garbage collected.
+ args [0] = &initial_len;
+
MonoStringBuilder *sb = (MonoStringBuilder*)mono_object_new (mono_domain_get (), string_builder_class);
MonoObject *exc;
g_assert (sb);
mono_runtime_invoke (sb_ctor, sb, args, &exc);
+ g_assert (!exc);
g_assert (sb->chunkChars->max_length >= initial_len);
- g_assert (!exc);
return sb;
}
static MonoAsyncResult *
mono_delegate_begin_invoke (MonoDelegate *delegate, gpointer *params)
{
- MonoMethodMessage *msg;
- MonoDelegate *async_callback;
MonoMulticastDelegate *mcast_delegate;
- MonoObject *state;
- MonoMethod *im;
MonoClass *klass;
- MonoMethod *method = NULL, *method2 = NULL;
+ MonoMethod *method;
g_assert (delegate);
mcast_delegate = (MonoMulticastDelegate *) delegate;
- if (mcast_delegate->prev != NULL)
+ if (mcast_delegate->delegates != NULL)
mono_raise_exception (mono_get_exception_argument (NULL, "The delegate must have only one target"));
#ifndef DISABLE_REMOTING
/* If the target is a proxy, make a direct call. Is proxy's work
// to make the call asynchronous.
*/
+ MonoMethodMessage *msg;
+ MonoDelegate *async_callback;
+ MonoObject *state;
MonoAsyncResult *ares;
MonoObject *exc;
MonoArray *out_args;
klass = delegate->object.vtable->klass;
- method = mono_get_delegate_invoke (klass);
- method2 = mono_class_get_method_from_name (klass, "BeginInvoke", -1);
- if (method2)
- method = method2;
- g_assert (method != NULL);
-
- im = mono_get_delegate_invoke (method->klass);
- msg = mono_method_call_message_new (method, params, im, &async_callback, &state);
+ method = mono_class_get_method_from_name (klass, "BeginInvoke", -1);
+ if (!method)
+ method = mono_get_delegate_invoke (klass);
+ g_assert (method);
- return mono_thread_pool_add ((MonoObject *)delegate, msg, async_callback, state);
+ return mono_threadpool_ms_begin_invoke (mono_domain_get (), (MonoObject*) delegate, method, params);
}
#ifndef DISABLE_JIT
* Check cache
*/
if (ctx) {
- cache = get_cache (&method->klass->image->delegate_begin_invoke_generic_cache, mono_aligned_addr_hash, NULL);
+ cache = get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.delegate_begin_invoke_cache, mono_aligned_addr_hash, NULL);
res = check_generic_delegate_wrapper_cache (cache, orig_method, method, ctx);
if (res)
return res;
} else {
- cache = get_cache (&method->klass->image->delegate_begin_invoke_cache,
+ cache = get_cache (&method->klass->image->wrapper_caches.delegate_begin_invoke_cache,
(GHashFunc)mono_signature_hash,
(GCompareFunc)mono_metadata_signature_equal);
if ((res = mono_marshal_find_in_cache (cache, sig)))
} else
#endif
{
- res = mono_thread_pool_finish (ares, &out_args, &exc);
+ res = mono_threadpool_ms_end_invoke (ares, &out_args, &exc);
}
if (exc) {
* Check cache
*/
if (ctx) {
- cache = get_cache (&method->klass->image->delegate_end_invoke_generic_cache, mono_aligned_addr_hash, NULL);
+ cache = get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.delegate_end_invoke_cache, mono_aligned_addr_hash, NULL);
res = check_generic_delegate_wrapper_cache (cache, orig_method, method, ctx);
if (res)
return res;
} else {
- cache = get_cache (&method->klass->image->delegate_end_invoke_cache,
+ cache = get_cache (&method->klass->image->wrapper_caches.delegate_end_invoke_cache,
(GHashFunc)mono_signature_hash,
(GCompareFunc)mono_metadata_signature_equal);
if ((res = mono_marshal_find_in_cache (cache, sig)))
g_free (pair);
}
-static MonoMethod *
+MonoMethod *
mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt, gboolean static_method_with_first_arg_bound, MonoMethod *target_method)
{
MonoMethodSignature *sig, *static_sig, *invoke_sig;
gpointer cache_key = NULL;
SignaturePointerPair key;
SignaturePointerPair *new_key;
- int local_prev, local_target;
- int pos0;
+ int local_i, local_len, local_delegates, local_d, local_target, local_res;
+ int pos0, pos1, pos2;
char *name;
MonoClass *target_class = NULL;
gboolean closed_over_null = FALSE;
WrapperInfo *info;
WrapperSubtype subtype = WRAPPER_SUBTYPE_NONE;
gboolean found;
+ gboolean void_ret;
g_assert (method && method->klass->parent == mono_defaults.multicastdelegate_class &&
!strcmp (method->name, "Invoke"));
* Check cache
*/
if (ctx) {
- cache = get_cache (&method->klass->image->delegate_invoke_generic_cache, mono_aligned_addr_hash, NULL);
+ cache = get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.delegate_invoke_cache, mono_aligned_addr_hash, NULL);
res = check_generic_delegate_wrapper_cache (cache, orig_method, method, ctx);
if (res)
return res;
} else if (callvirt) {
GHashTable **cache_ptr;
- cache_ptr = &method->klass->image->delegate_abstract_invoke_cache;
+ cache_ptr = &mono_method_get_wrapper_cache (method)->delegate_abstract_invoke_cache;
/* We need to cache the signature+method pair */
mono_marshal_lock ();
if (res)
return res;
} else {
- cache = get_cache (&method->klass->image->delegate_invoke_cache,
+ // Inflated methods should not be in this cache because it's not stored on the imageset.
+ g_assert (!method->is_inflated);
+ cache = get_cache (&method->klass->image->wrapper_caches.delegate_invoke_cache,
(GHashFunc)mono_signature_hash,
(GCompareFunc)mono_metadata_signature_equal);
res = mono_marshal_find_in_cache (cache, sig);
cache_key = sig;
}
- static_sig = signature_dup (method->klass->image, sig);
+ static_sig = mono_metadata_signature_dup_full (method->klass->image, sig);
static_sig->hasthis = 0;
if (!static_method_with_first_arg_bound)
invoke_sig = static_sig;
g_free (name);
#ifndef DISABLE_JIT
+ void_ret = sig->ret->type == MONO_TYPE_VOID && !method->string_ctor;
+
/* allocate local 0 (object) */
+ local_i = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
+ local_len = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
+ local_delegates = mono_mb_add_local (mb, &mono_defaults.array_class->byval_arg);
+ local_d = mono_mb_add_local (mb, &mono_defaults.multicastdelegate_class->byval_arg);
local_target = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
- local_prev = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
+
+ if (!void_ret)
+ local_res = mono_mb_add_local (mb, &mono_class_from_mono_type (sig->ret)->byval_arg);
g_assert (sig->hasthis);
-
+
/*
- * if (prev != null)
- * prev.Invoke( args .. );
- * return this.<target>( args .. );
- */
-
+ * {type: sig->ret} res;
+ * if (delegates == null) {
+ * return this.<target> ( args .. );
+ * } else {
+ * int i = 0, len = this.delegates.Length;
+ * do {
+ * res = this.delegates [i].Invoke ( args .. );
+ * } while (++i < len);
+ * return res;
+ * }
+ */
+
/* this wrapper can be used in unmanaged-managed transitions */
emit_thread_interrupt_checkpoint (mb);
-
- /* get this->prev */
+
+ /* delegates = this.delegates */
mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoMulticastDelegate, prev));
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoMulticastDelegate, delegates));
mono_mb_emit_byte (mb, CEE_LDIND_REF);
- mono_mb_emit_stloc (mb, local_prev);
- mono_mb_emit_ldloc (mb, local_prev);
+ mono_mb_emit_stloc (mb, local_delegates);
- /* if prev != null */
- pos0 = mono_mb_emit_branch (mb, CEE_BRFALSE);
- /* then recurse */
+ /* if (delegates == null) */
+ mono_mb_emit_ldloc (mb, local_delegates);
+ pos2 = mono_mb_emit_branch (mb, CEE_BRTRUE);
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_NOT_TAKEN);
+ /* return target.<target_method|method_ptr> ( args .. ); */
- mono_mb_emit_ldloc (mb, local_prev);
- for (i = 0; i < sig->param_count; i++)
- mono_mb_emit_ldarg (mb, i + 1);
- if (ctx) {
- MonoError error;
- mono_mb_emit_op (mb, CEE_CALLVIRT, mono_class_inflate_generic_method_checked (method, &container->context, &error));
- g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
- } else {
- mono_mb_emit_op (mb, CEE_CALLVIRT, method);
- }
- if (sig->ret->type != MONO_TYPE_VOID)
- mono_mb_emit_byte (mb, CEE_POP);
-
- /* continued or prev == null */
- mono_mb_patch_branch (mb, pos0);
-
- /* get this->target */
+ /* target = d.target; */
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoDelegate, target));
mono_mb_emit_byte (mb, CEE_LDIND_REF);
if (callvirt) {
if (!closed_over_null) {
- mono_mb_emit_ldarg (mb, 1);
- mono_mb_emit_op (mb, CEE_CASTCLASS, target_class);
- for (i = 1; i < sig->param_count; ++i)
- mono_mb_emit_ldarg (mb, i + 1);
- mono_mb_emit_op (mb, CEE_CALLVIRT, target_method);
+ if (target_class->valuetype) {
+ mono_mb_emit_ldarg (mb, 1);
+ for (i = 1; i < sig->param_count; ++i)
+ mono_mb_emit_ldarg (mb, i + 1);
+ mono_mb_emit_op (mb, CEE_CALL, target_method);
+ } else {
+ mono_mb_emit_ldarg (mb, 1);
+ mono_mb_emit_op (mb, CEE_CASTCLASS, target_class);
+ for (i = 1; i < sig->param_count; ++i)
+ mono_mb_emit_ldarg (mb, i + 1);
+ mono_mb_emit_op (mb, CEE_CALLVIRT, target_method);
+ }
} else {
mono_mb_emit_byte (mb, CEE_LDNULL);
for (i = 0; i < sig->param_count; ++i)
mono_mb_emit_byte (mb, CEE_RET);
+ /* else [delegates != null] */
+ mono_mb_patch_branch (mb, pos2);
+
+ /* len = delegates.Length; */
+ mono_mb_emit_ldloc (mb, local_delegates);
+ mono_mb_emit_byte (mb, CEE_LDLEN);
+ mono_mb_emit_byte (mb, CEE_CONV_I4);
+ mono_mb_emit_stloc (mb, local_len);
+
+ /* i = 0; */
+ mono_mb_emit_icon (mb, 0);
+ mono_mb_emit_stloc (mb, local_i);
+
+ pos1 = mono_mb_get_label (mb);
+
+ /* d = delegates [i]; */
+ mono_mb_emit_ldloc (mb, local_delegates);
+ mono_mb_emit_ldloc (mb, local_i);
+ mono_mb_emit_byte (mb, CEE_LDELEM_REF);
+ mono_mb_emit_stloc (mb, local_d);
+
+ /* res = d.Invoke ( args .. ); */
+ mono_mb_emit_ldloc (mb, local_d);
+ for (i = 0; i < sig->param_count; i++)
+ mono_mb_emit_ldarg (mb, i + 1);
+ if (!ctx) {
+ mono_mb_emit_op (mb, CEE_CALLVIRT, method);
+ } else {
+ MonoError error;
+ mono_mb_emit_op (mb, CEE_CALLVIRT, mono_class_inflate_generic_method_checked (method, &container->context, &error));
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+ }
+ if (!void_ret)
+ mono_mb_emit_stloc (mb, local_res);
+
+ /* i += 1 */
+ mono_mb_emit_add_to_local (mb, local_i, 1);
+
+ /* i < l */
+ mono_mb_emit_ldloc (mb, local_i);
+ mono_mb_emit_ldloc (mb, local_len);
+ mono_mb_emit_branch_label (mb, CEE_BLT, pos1);
+
+ /* return res */
+ if (!void_ret)
+ mono_mb_emit_ldloc (mb, local_res);
+ mono_mb_emit_byte (mb, CEE_RET);
+
mb->skip_visibility = 1;
#endif /* DISABLE_JIT */
}
mono_mb_free (mb);
+ /* mono_method_print_code (res); */
+
return res;
}
return mono_marshal_get_delegate_invoke_internal (method, callvirt, static_method_with_first_arg_bound, target_method);
}
-/*
- * signature_dup_add_this:
- *
- * Make a copy of @sig, adding an explicit this argument.
- */
-static MonoMethodSignature*
-signature_dup_add_this (MonoImage *image, MonoMethodSignature *sig, MonoClass *klass)
-{
- MonoMethodSignature *res;
- int i;
-
- res = mono_metadata_signature_alloc (image, sig->param_count + 1);
- memcpy (res, sig, MONO_SIZEOF_METHOD_SIGNATURE);
- res->param_count = sig->param_count + 1;
- res->hasthis = FALSE;
- for (i = sig->param_count - 1; i >= 0; i --)
- res->params [i + 1] = sig->params [i];
- res->params [0] = klass->valuetype ? &klass->this_arg : &klass->byval_arg;
-
- return res;
-}
-
typedef struct {
MonoMethodSignature *ctor_sig;
MonoMethodSignature *sig;
MonoMethodSignature *callsig;
CtorSigPair *cs;
- callsig = signature_dup (method->klass->image, mono_method_signature (method));
+ callsig = mono_metadata_signature_dup_full (method->klass->image, mono_method_signature (method));
callsig->ret = &mono_defaults.string_class->byval_arg;
cs = g_new (CtorSigPair, 1);
cs->sig = callsig;
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);
+ cache = get_cache (&mono_method_get_wrapper_cache (method)->runtime_invoke_direct_cache, mono_aligned_addr_hash, NULL);
+
res = mono_marshal_find_in_cache (cache, method);
if (res)
return res;
need_direct_wrapper = TRUE;
} else {
if (method_is_dynamic (method))
- callsig = signature_dup (method->klass->image, mono_method_signature (method));
+ callsig = mono_metadata_signature_dup_full (method->klass->image, mono_method_signature (method));
else
callsig = mono_method_signature (method);
}
MonoMethodSignature *tmp_sig;
callsig = mono_marshal_get_runtime_invoke_sig (callsig);
+ GHashTable **cache_table = NULL;
if (method->klass->valuetype && mono_method_signature (method)->hasthis)
- /* These have a different csig */
- cache = get_cache (&target_klass->image->runtime_invoke_vtype_cache,
- (GHashFunc)mono_signature_hash,
- (GCompareFunc)runtime_invoke_signature_equal);
+ cache_table = &mono_method_get_wrapper_cache (method)->runtime_invoke_vtype_cache;
else
- cache = get_cache (&target_klass->image->runtime_invoke_cache,
- (GHashFunc)mono_signature_hash,
+ cache_table = &mono_method_get_wrapper_cache (method)->runtime_invoke_cache;
+
+ cache = get_cache (cache_table, (GHashFunc)mono_signature_hash,
(GCompareFunc)runtime_invoke_signature_equal);
/* from mono_marshal_find_in_cache */
mono_marshal_lock ();
res = g_hash_table_lookup (cache, callsig);
if (!res) {
+ GHashTable *direct_cache;
res = newm;
g_hash_table_insert (cache, callsig, res);
/* Can't insert it into wrapper_hash since the key is a signature */
- g_hash_table_insert (method->klass->image->runtime_invoke_direct_cache, method, res);
+ direct_cache = mono_method_get_wrapper_cache (method)->runtime_invoke_direct_cache;
+
+ g_hash_table_insert (direct_cache, method, res);
} else {
mono_free_method (newm);
}
/* Add an explicit this argument */
if (sig->hasthis)
- csig2 = signature_dup_add_this (mono_defaults.corlib, sig, mono_defaults.object_class);
+ csig2 = mono_metadata_signature_dup_add_this (mono_defaults.corlib, sig, mono_defaults.object_class);
else
- csig2 = signature_dup (mono_defaults.corlib, sig);
+ csig2 = mono_metadata_signature_dup_full (mono_defaults.corlib, sig);
#ifndef DISABLE_JIT
if (sig->hasthis)
mono_mb_emit_byte (mb, CEE_RET);
#endif
- csig = signature_dup (mono_defaults.corlib, sig);
+ csig = mono_metadata_signature_dup_full (mono_defaults.corlib, sig);
csig->pinvoke = 0;
if (csig->call_convention == MONO_CALL_VARARG)
csig->call_convention = 0;
emit_struct_conv (mb, klass, FALSE);
mono_mb_patch_branch (mb, pos2);
+ } else if (klass == mono_defaults.stringbuilder_class) {
+ // FIXME: What to do here ?
} else {
/* byval [Out] marshalling */
g_assert (!sig->hasthis);
param_shift += 1;
}
- csig = signature_dup (mb->method->klass->image, sig);
+ csig = mono_metadata_signature_dup_full (mb->method->klass->image, sig);
csig->pinvoke = 1;
m.csig = csig;
m.image = image;
}
#endif /* DISABLE_JIT */
-
-G_GNUC_UNUSED static void
-code_for (MonoMethod *method) {
- MonoMethodHeader *header = mono_method_get_header (method);
- printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (method, TRUE), mono_disasm_code (0, method, header->code, header->code + header->code_size));
-}
-
/**
* mono_marshal_get_native_wrapper:
* @method: The MonoMethod to wrap.
g_assert (method != NULL);
g_assert (mono_method_signature (method)->pinvoke);
- if (aot)
- cache = get_cache (&method->klass->image->native_wrapper_aot_cache, mono_aligned_addr_hash, NULL);
- else
- cache = get_cache (&method->klass->image->native_wrapper_cache, mono_aligned_addr_hash, NULL);
+ GHashTable **cache_ptr;
+
+ if (aot) {
+ if (check_exceptions)
+ cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_aot_check_cache;
+ else
+ cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_aot_cache;
+ } else {
+ if (check_exceptions)
+ cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_check_cache;
+ else
+ cache_ptr = &mono_method_get_wrapper_cache (method)->native_wrapper_cache;
+ }
+
+ cache = get_cache (cache_ptr, mono_aligned_addr_hash, NULL);
+
if ((res = mono_marshal_find_in_cache (cache, method)))
return res;
g_assert (sig->hasthis);
/* CreateString returns a value */
- csig = signature_dup (method->klass->image, sig);
+ csig = mono_metadata_signature_dup_full (method->klass->image, sig);
csig->ret = &mono_defaults.string_class->byval_arg;
csig->pinvoke = 0;
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
info->d.managed_to_native.method = method;
- csig = signature_dup (method->klass->image, sig);
+ csig = mono_metadata_signature_dup_full (method->klass->image, sig);
csig->pinvoke = 0;
res = mono_mb_create_and_cache_full (cache, method, mb, csig,
csig->param_count + 16, info, NULL);
/* 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)) {
if (sig->hasthis)
- csig = signature_dup_add_this (method->klass->image, sig, method->klass);
+ csig = mono_metadata_signature_dup_add_this (method->klass->image, sig, method->klass);
else
- csig = signature_dup (method->klass->image, sig);
+ csig = mono_metadata_signature_dup_full (method->klass->image, sig);
/* hack - string constructors returns a value */
if (method->string_ctor)
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
info->d.managed_to_native.method = method;
- csig = signature_dup (method->klass->image, csig);
+ csig = mono_metadata_signature_dup_full (method->klass->image, csig);
csig->pinvoke = 0;
res = mono_mb_create_and_cache_full (cache, method, mb, csig, csig->param_count + 16,
info, NULL);
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_PINVOKE);
info->d.managed_to_native.method = method;
- csig = signature_dup (method->klass->image, sig);
+ csig = mono_metadata_signature_dup_full (method->klass->image, sig);
csig->pinvoke = 0;
res = mono_mb_create_and_cache_full (cache, method, mb, csig, csig->param_count + 16,
info, NULL);
g_free (mspecs);
#endif
- /* code_for (res); */
+ /* mono_method_print_code (res); */
return res;
}
key.sig = sig;
key.pointer = func;
+ // Generic types are not safe to place in MonoImage caches.
+ g_assert (!sig->is_inflated);
+
cache = get_cache (&image->native_func_wrapper_cache, signature_pointer_pair_hash, signature_pointer_pair_equal);
if ((res = mono_marshal_find_in_cache (cache, &key)))
return res;
mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, func, FALSE, TRUE, FALSE);
#endif
- csig = signature_dup (image, sig);
+ csig = mono_metadata_signature_dup_full (image, sig);
csig->pinvoke = 0;
new_key = g_new (SignaturePointerPair,1);
/*
* The wrapper is associated with the delegate type, to pick up the marshalling info etc.
*/
- cache = get_cache (&image->native_func_wrapper_aot_cache, mono_aligned_addr_hash, NULL);
+ cache = get_cache (&mono_method_get_wrapper_cache (invoke)->native_func_wrapper_aot_cache, mono_aligned_addr_hash, NULL);
+
if ((res = mono_marshal_find_in_cache (cache, invoke)))
return res;
info->d.managed_to_native.method = invoke;
g_assert (!sig->hasthis);
- csig = signature_dup_add_this (image, sig, mono_defaults.int_class);
+ csig = mono_metadata_signature_dup_add_this (image, sig, mono_defaults.object_class);
csig->pinvoke = 0;
res = mono_mb_create_and_cache_full (cache, invoke,
mb, csig, csig->param_count + 16,
#ifdef USE_COOP_GC
/* local 4, the local to be used when calling the reset_blocking funcs */
/* tons of code hardcode 3 to be the return var */
- coop_gc_var = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
+ coop_gc_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
#endif
mono_mb_emit_icon (mb, 0);
* could be called with different delegates, thus different marshalling
* options.
*/
- cache = get_cache (&method->klass->image->managed_wrapper_cache, mono_aligned_addr_hash, NULL);
+ cache = get_cache (&mono_method_get_wrapper_cache (method)->managed_wrapper_cache, mono_aligned_addr_hash, NULL);
+
if (!target_handle && (res = mono_marshal_find_in_cache (cache, method)))
return res;
/* Need to free this later */
csig = mono_metadata_signature_dup (invoke_sig);
else
- csig = signature_dup (method->klass->image, invoke_sig);
+ csig = mono_metadata_signature_dup_full (method->klass->image, invoke_sig);
csig->hasthis = 0;
csig->pinvoke = 1;
info, NULL);
} else {
#ifndef DISABLE_JIT
- mb->dynamic = 1;
+ mb->dynamic = TRUE;
#endif
res = mono_mb_create (mb, csig, sig->param_count + 16, NULL);
}
mono_metadata_free_marshal_spec (mspecs [i]);
g_free (mspecs);
- /* code_for (res); */
+ /* mono_method_print_code (res); */
return res;
}
mono_method_get_marshal_info (method, mspecs);
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED);
- csig = signature_dup (image, sig);
+ csig = mono_metadata_signature_dup_full (image, sig);
csig->hasthis = 0;
csig->pinvoke = 1;
mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, 0);
#ifndef DISABLE_JIT
- mb->dynamic = 1;
+ mb->dynamic = TRUE;
#endif
method = mono_mb_create (mb, csig, sig->param_count + 16, NULL);
mono_mb_free (mb);
mono_mb_emit_op (mb, CEE_CALL, method);
mono_mb_emit_byte (mb, CEE_RET);
- mb->dynamic = 1;
+ mb->dynamic = TRUE;
#endif
method = mono_mb_create (mb, sig, param_count, NULL);
return mono_compile_method (method);
}
+#ifndef DISABLE_JIT
+
+/*
+ * The code directly following this is the cache hit, value positive branch
+ *
+ * This function takes a new method builder with 0 locals and adds two locals
+ * to create multiple out-branches and the fall through state of having the object
+ * on the stack after a cache miss
+ */
+static void
+generate_check_cache (int obj_arg_position, int class_arg_position, int cache_arg_position, // In-parameters
+ int *null_obj, int *cache_hit_neg, int *cache_hit_pos, // Out-parameters
+ MonoMethodBuilder *mb)
+{
+ int cache_miss_pos;
+
+ /* allocate local 0 (pointer) obj_vtable */
+ mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+ /* allocate local 1 (pointer) cached_vtable */
+ mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+
+ /*if (!obj)*/
+ mono_mb_emit_ldarg (mb, obj_arg_position);
+ *null_obj = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ /*obj_vtable = obj->vtable;*/
+ mono_mb_emit_ldarg (mb, obj_arg_position);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoObject, vtable));
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_stloc (mb, 0);
+
+ /* cached_vtable = *cache*/
+ mono_mb_emit_ldarg (mb, cache_arg_position);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_stloc (mb, 1);
+
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_byte (mb, CEE_LDC_I4);
+ mono_mb_emit_i4 (mb, ~0x1);
+ mono_mb_emit_byte (mb, CEE_CONV_I);
+ mono_mb_emit_byte (mb, CEE_AND);
+ mono_mb_emit_ldloc (mb, 0);
+ /*if ((cached_vtable & ~0x1)== obj_vtable)*/
+ cache_miss_pos = mono_mb_emit_branch (mb, CEE_BNE_UN);
+
+ /*return (cached_vtable & 0x1) ? NULL : obj;*/
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_byte(mb, CEE_LDC_I4_1);
+ mono_mb_emit_byte (mb, CEE_CONV_U);
+ mono_mb_emit_byte (mb, CEE_AND);
+ *cache_hit_neg = mono_mb_emit_branch (mb, CEE_BRTRUE);
+ *cache_hit_pos = mono_mb_emit_branch (mb, CEE_BR);
+
+ // slow path
+ mono_mb_patch_branch (mb, cache_miss_pos);
+
+ // if isinst
+ mono_mb_emit_ldarg (mb, obj_arg_position);
+ mono_mb_emit_ldarg (mb, class_arg_position);
+ mono_mb_emit_ldarg (mb, cache_arg_position);
+ mono_mb_emit_icall (mb, mono_marshal_isinst_with_cache);
+}
+
+#endif /* DISABLE_JIT */
+
/*
* This does the equivalent of mono_object_castclass_with_cache.
* The wrapper info for the wrapper is a WrapperInfo structure.
MonoMethod *res;
MonoMethodBuilder *mb;
MonoMethodSignature *sig;
- int return_null_pos, cache_miss_pos, invalid_cast_pos;
+ int return_null_pos, positive_cache_hit_pos, negative_cache_hit_pos, invalid_cast_pos;
WrapperInfo *info;
+ const int obj_arg_position = 0;
+ const int class_arg_position = 1;
+ const int cache_arg_position = 2;
+
if (cached)
return cached;
mb = mono_mb_new (mono_defaults.object_class, "__castclass_with_cache", MONO_WRAPPER_CASTCLASS);
sig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
- 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 [obj_arg_position] = &mono_defaults.object_class->byval_arg;
+ sig->params [class_arg_position] = &mono_defaults.int_class->byval_arg;
+ sig->params [cache_arg_position] = &mono_defaults.int_class->byval_arg;
sig->ret = &mono_defaults.object_class->byval_arg;
sig->pinvoke = 0;
#ifndef DISABLE_JIT
- /* allocate local 0 (pointer) obj_vtable */
- mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
-
- /*if (!obj)*/
- mono_mb_emit_ldarg (mb, 0);
- return_null_pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
- /*obj_vtable = obj->vtable;*/
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoObject, vtable));
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_stloc (mb, 0);
-
- /* *cache */
- mono_mb_emit_ldarg (mb, 2);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_ldloc (mb, 0);
-
- /*if (*cache == obj_vtable)*/
- cache_miss_pos = mono_mb_emit_branch (mb, CEE_BNE_UN);
-
- /*return obj;*/
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_byte (mb, CEE_RET);
-
- mono_mb_patch_branch (mb, cache_miss_pos);
- /*if (mono_object_isinst (obj, klass)) */
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldarg (mb, 1);
- mono_mb_emit_icall (mb, mono_object_isinst);
+ generate_check_cache (obj_arg_position, class_arg_position, cache_arg_position,
+ &return_null_pos, &negative_cache_hit_pos, &positive_cache_hit_pos, mb);
invalid_cast_pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
- /**cache = obj_vtable;*/
- mono_mb_emit_ldarg (mb, 2);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_STIND_I);
-
/*return obj;*/
- mono_mb_emit_ldarg (mb, 0);
+ mono_mb_patch_branch (mb, positive_cache_hit_pos);
+ mono_mb_emit_ldarg (mb, obj_arg_position);
mono_mb_emit_byte (mb, CEE_RET);
/*fails*/
+ mono_mb_patch_branch (mb, negative_cache_hit_pos);
mono_mb_patch_branch (mb, invalid_cast_pos);
mono_mb_emit_exception (mb, "InvalidCastException", NULL);
return cached;
}
+static MonoObject *
+mono_marshal_isinst_with_cache (MonoObject *obj, MonoClass *klass, uintptr_t *cache)
+{
+ MonoObject *isinst = mono_object_isinst (obj, klass);
+
+#ifndef DISABLE_REMOTING
+ if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
+ return isinst;
+#endif
+
+ uintptr_t cache_update = (uintptr_t)obj->vtable;
+ if (!isinst)
+ cache_update = cache_update | 0x1;
+
+ *cache = cache_update;
+
+ return isinst;
+}
+
/*
* This does the equivalent of mono_object_isinst_with_cache.
* The wrapper info for the wrapper is a WrapperInfo structure.
MonoMethod *res;
MonoMethodBuilder *mb;
MonoMethodSignature *sig;
- int return_null_pos, cache_miss_pos, cache_hit_pos, not_an_instance_pos, negative_cache_hit_pos;
+ int return_null_pos, positive_cache_hit_pos, negative_cache_hit_pos;
WrapperInfo *info;
+ const int obj_arg_position = 0;
+ const int class_arg_position = 1;
+ const int cache_arg_position = 2;
+
if (cached)
return cached;
mb = mono_mb_new (mono_defaults.object_class, "__isinst_with_cache", MONO_WRAPPER_CASTCLASS);
sig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
- 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;
+ // The object
+ sig->params [obj_arg_position] = &mono_defaults.object_class->byval_arg;
+ // The class
+ sig->params [class_arg_position] = &mono_defaults.int_class->byval_arg;
+ // The cache
+ sig->params [cache_arg_position] = &mono_defaults.int_class->byval_arg;
sig->ret = &mono_defaults.object_class->byval_arg;
sig->pinvoke = 0;
#ifndef DISABLE_JIT
- /* allocate local 0 (pointer) obj_vtable */
- mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- /* allocate local 1 (pointer) cached_vtable */
- mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
-
- /*if (!obj)*/
- mono_mb_emit_ldarg (mb, 0);
- return_null_pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
- /*obj_vtable = obj->vtable;*/
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoObject, vtable));
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_stloc (mb, 0);
-
- /* cached_vtable = *cache*/
- mono_mb_emit_ldarg (mb, 2);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_stloc (mb, 1);
-
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_byte (mb, CEE_LDC_I4);
- mono_mb_emit_i4 (mb, ~0x1);
- mono_mb_emit_byte (mb, CEE_CONV_I);
- mono_mb_emit_byte (mb, CEE_AND);
- mono_mb_emit_ldloc (mb, 0);
- /*if ((cached_vtable & ~0x1)== obj_vtable)*/
- cache_miss_pos = mono_mb_emit_branch (mb, CEE_BNE_UN);
-
- /*return (cached_vtable & 0x1) ? NULL : obj;*/
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_byte(mb, CEE_LDC_I4_1);
- mono_mb_emit_byte (mb, CEE_CONV_U);
- mono_mb_emit_byte (mb, CEE_AND);
- negative_cache_hit_pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
-
- /*obj*/
- mono_mb_emit_ldarg (mb, 0);
- cache_hit_pos = mono_mb_emit_branch (mb, CEE_BR);
+ generate_check_cache (obj_arg_position, class_arg_position, cache_arg_position,
+ &return_null_pos, &negative_cache_hit_pos, &positive_cache_hit_pos, mb);
+ // Return the object gotten via the slow path.
+ mono_mb_emit_byte (mb, CEE_RET);
- /*NULL*/
+ // return NULL;
mono_mb_patch_branch (mb, negative_cache_hit_pos);
+ mono_mb_patch_branch (mb, return_null_pos);
mono_mb_emit_byte (mb, CEE_LDNULL);
-
- mono_mb_patch_branch (mb, cache_hit_pos);
mono_mb_emit_byte (mb, CEE_RET);
- mono_mb_patch_branch (mb, cache_miss_pos);
- /*if (mono_object_isinst (obj, klass)) */
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldarg (mb, 1);
- mono_mb_emit_icall (mb, mono_object_isinst);
- not_an_instance_pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
- /**cache = obj_vtable;*/
- mono_mb_emit_ldarg (mb, 2);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_STIND_I);
-
- /*return obj;*/
+ // return obj
+ mono_mb_patch_branch (mb, positive_cache_hit_pos);
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_byte (mb, CEE_RET);
-
- /*not an instance*/
- mono_mb_patch_branch (mb, not_an_instance_pos);
- /* *cache = (gpointer)(obj_vtable | 0x1);*/
- mono_mb_emit_ldarg (mb, 2);
- /*obj_vtable | 0x1*/
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte(mb, CEE_LDC_I4_1);
- mono_mb_emit_byte (mb, CEE_CONV_U);
- mono_mb_emit_byte (mb, CEE_OR);
-
- /* *cache = ... */
- mono_mb_emit_byte (mb, CEE_STIND_I);
-
- /*return null*/
- mono_mb_patch_branch (mb, return_null_pos);
- mono_mb_emit_byte (mb, CEE_LDNULL);
- mono_mb_emit_byte (mb, CEE_RET);
#endif
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_ISINST_WITH_CACHE);
static void PtrToStructure (IntPtr ptr, object structure);
defined in class/corlib/System.Runtime.InteropServices/Marshal.cs */
sig = mono_create_icall_signature ("void ptr object");
- sig = signature_dup (mono_defaults.corlib, sig);
+ sig = mono_metadata_signature_dup_full (mono_defaults.corlib, sig);
sig->pinvoke = 0;
mono_memory_barrier ();
ptostr = sig;
mono_mb_emit_exception_full (mb, "System", "ExecutionEngineException", "Shouldn't be called.");
mono_mb_emit_byte (mb, CEE_RET);
#endif
- sig = signature_dup (method->klass->image, mono_method_signature (method));
+ sig = mono_metadata_signature_dup_full (method->klass->image, mono_method_signature (method));
info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_SYNCHRONIZED_INNER);
info->d.synchronized_inner.method = method;
MonoMethodBuilder *mb;
MonoMethod *res;
GHashTable *cache;
- int i, pos, this_local, ret_local = 0;
+ int i, pos, pos2, this_local, taken_local, ret_local = 0;
MonoGenericContext *ctx = NULL;
MonoMethod *orig_method = NULL;
MonoGenericContainer *container = NULL;
* Check cache
*/
if (ctx) {
- cache = get_cache (&method->klass->image->synchronized_generic_cache, mono_aligned_addr_hash, NULL);
+ cache = get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.synchronized_cache, mono_aligned_addr_hash, NULL);
res = check_generic_wrapper_cache (cache, orig_method, orig_method, method);
if (res)
return res;
} else {
- cache = get_cache (&method->klass->image->synchronized_cache, mono_aligned_addr_hash, NULL);
+ cache = get_cache (&method->klass->image->wrapper_caches.synchronized_cache, mono_aligned_addr_hash, NULL);
if ((res = mono_marshal_find_in_cache (cache, method)))
return res;
}
- sig = signature_dup (method->klass->image, mono_method_signature (method));
+ sig = mono_metadata_signature_dup_full (method->klass->image, mono_method_signature (method));
sig->pinvoke = 0;
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_SYNCHRONIZED);
#ifndef DISABLE_JIT
+ mb->skip_visibility = 1;
/* result */
if (!MONO_TYPE_IS_VOID (sig->ret))
ret_local = mono_mb_add_local (mb, sig->ret);
#ifndef DISABLE_JIT
/* this */
this_local = mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
+ taken_local = mono_mb_add_local (mb, &mono_defaults.boolean_class->byval_arg);
clause = mono_image_alloc0 (method->klass->image, sizeof (MonoExceptionClause));
clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
if (!enter_method) {
MonoMethodDesc *desc;
- desc = mono_method_desc_new ("Monitor:Enter", FALSE);
+ desc = mono_method_desc_new ("Monitor:enter_with_atomic_var(object,bool&)", FALSE);
enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
g_assert (enter_method);
mono_method_desc_free (desc);
/* Call Monitor::Enter() */
mono_mb_emit_ldloc (mb, this_local);
+ mono_mb_emit_ldloc_addr (mb, taken_local);
mono_mb_emit_managed_call (mb, enter_method, NULL);
clause->try_offset = mono_mb_get_label (mb);
clause->try_len = mono_mb_get_pos (mb) - clause->try_offset;
clause->handler_offset = mono_mb_get_label (mb);
- /* Call Monitor::Exit() */
+ /* Call Monitor::Exit() if needed */
+ mono_mb_emit_ldloc (mb, taken_local);
+ pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
mono_mb_emit_ldloc (mb, this_local);
mono_mb_emit_managed_call (mb, exit_method, NULL);
+ mono_mb_patch_branch (mb, pos2);
mono_mb_emit_byte (mb, CEE_ENDFINALLY);
clause->handler_len = mono_mb_get_pos (mb) - clause->handler_offset;
MonoMethod *res;
GHashTable *cache;
- cache = get_cache (&method->klass->image->unbox_wrapper_cache, mono_aligned_addr_hash, NULL);
+ cache = get_cache (&mono_method_get_wrapper_cache (method)->unbox_wrapper_cache, mono_aligned_addr_hash, NULL);
+
if ((res = mono_marshal_find_in_cache (cache, method)))
return res;
mb, sig, sig->param_count + 16);
mono_mb_free (mb);
- /* code_for (res); */
+ /* mono_method_print_code (res); */
return res;
}
return res;
}
- sig = signature_dup (method->klass->image, mono_method_signature (method));
+ sig = mono_metadata_signature_dup_full (method->klass->image, mono_method_signature (method));
sig->pinvoke = 0;
mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_UNKNOWN);
METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_HIDE_BY_SIG | METHOD_ATTRIBUTE_FINAL;
sig = mono_method_signature (method);
- csig = signature_dup (method->klass->image, sig);
+ csig = mono_metadata_signature_dup_full (method->klass->image, sig);
csig->generic_param_count = 0;
#ifndef DISABLE_JIT
GHashTable *cache;
MonoMethod *res;
int i, param_count, sig_size, pos_leave;
+#ifdef USE_COOP_GC
+ int coop_gc_var;
+#endif
g_assert (method);
klass = method->klass;
image = method->klass->image;
- cache = get_cache (&image->thunk_invoke_cache, mono_aligned_addr_hash, NULL);
+
+ cache = get_cache (&mono_method_get_wrapper_cache (method)->thunk_invoke_cache, mono_aligned_addr_hash, NULL);
+
if ((res = mono_marshal_find_in_cache (cache, method)))
return res;
if (!MONO_TYPE_IS_VOID (sig->ret))
mono_mb_add_local (mb, sig->ret);
+#ifdef USE_COOP_GC
+ /* local 4, the local to be used when calling the reset_blocking funcs */
+ /* tons of code hardcode 3 to be the return var */
+ coop_gc_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+#endif
+
/* clear exception arg */
mono_mb_emit_ldarg (mb, param_count - 1);
mono_mb_emit_byte (mb, CEE_LDNULL);
mono_mb_emit_byte (mb, CEE_STIND_REF);
+#ifdef USE_COOP_GC
+ /* FIXME this is technically wrong as the callback itself must be executed in gc unsafe context. */
+ mono_mb_emit_icall (mb, mono_threads_reset_blocking_start);
+ mono_mb_emit_stloc (mb, coop_gc_var);
+#endif
+
/* try */
clause = mono_image_alloc0 (image, sizeof (MonoExceptionClause));
clause->try_offset = mono_mb_get_label (mb);
mono_mb_emit_op (mb, CEE_BOX, mono_class_from_mono_type (sig->ret));
}
+#ifdef USE_COOP_GC
+ /* XXX merge reset_blocking_end with detach */
+ mono_mb_emit_ldloc (mb, coop_gc_var);
+ mono_mb_emit_icall (mb, mono_threads_reset_blocking_end);
+#endif
+
mono_mb_emit_byte (mb, CEE_RET);
#endif
* FIXME: We currently leak the wrappers. Freeing them would be tricky as
* they could be shared with other methods ?
*/
- if (image->runtime_invoke_direct_cache)
- g_hash_table_remove (image->runtime_invoke_direct_cache, method);
- if (image->delegate_abstract_invoke_cache)
- g_hash_table_foreach_remove (image->delegate_abstract_invoke_cache, signature_pointer_pair_matches_pointer, method);
+ if (image->wrapper_caches.runtime_invoke_direct_cache)
+ g_hash_table_remove (image->wrapper_caches.runtime_invoke_direct_cache, method);
+ if (image->wrapper_caches.delegate_abstract_invoke_cache)
+ g_hash_table_foreach_remove (image->wrapper_caches.delegate_abstract_invoke_cache, signature_pointer_pair_matches_pointer, method);
// FIXME: Need to clear the caches in other images as well
if (image->delegate_bound_static_invoke_cache)
g_hash_table_remove (image->delegate_bound_static_invoke_cache, mono_method_signature (method));
if (marshal_mutex_initialized)
mono_marshal_unlock ();
}
-
-static gboolean
-signature_pointer_pair_matches_signature (gpointer key, gpointer value, gpointer user_data)
-{
- SignaturePointerPair *pair = (SignaturePointerPair*)key;
- MonoMethodSignature *sig = (MonoMethodSignature*)user_data;
-
- return mono_metadata_signature_equal (pair->sig, sig);
-}
-
-/*
- * mono_marshal_free_inflated_wrappers:
- *
- * Free wrappers of the inflated method METHOD.
- */
-void
-mono_marshal_free_inflated_wrappers (MonoMethod *method)
-{
- MonoMethodSignature *sig = method->signature;
-
- g_assert (method->is_inflated);
-
- /* Ignore calls occuring late during cleanup. */
- if (!marshal_mutex_initialized)
- return;
-
- mono_marshal_lock ();
- /*
- * FIXME: We currently leak the wrappers. Freeing them would be tricky as
- * they could be shared with other methods ?
- */
-
- /*
- * indexed by MonoMethodSignature
- */
- /* FIXME: This could remove unrelated wrappers as well */
- if (sig && method->klass->image->delegate_begin_invoke_cache)
- g_hash_table_remove (method->klass->image->delegate_begin_invoke_cache, sig);
- if (sig && method->klass->image->delegate_end_invoke_cache)
- g_hash_table_remove (method->klass->image->delegate_end_invoke_cache, sig);
- if (sig && method->klass->image->delegate_invoke_cache)
- g_hash_table_remove (method->klass->image->delegate_invoke_cache, sig);
- if (sig && method->klass->image->runtime_invoke_cache)
- g_hash_table_remove (method->klass->image->runtime_invoke_cache, sig);
- if (sig && method->klass->image->runtime_invoke_vtype_cache)
- g_hash_table_remove (method->klass->image->runtime_invoke_vtype_cache, sig);
-
- /*
- * indexed by SignaturePointerPair
- */
- if (sig && method->klass->image->delegate_abstract_invoke_cache)
- g_hash_table_foreach_remove (method->klass->image->delegate_abstract_invoke_cache,
- signature_pointer_pair_matches_signature, (gpointer)sig);
-
- /*
- * indexed by MonoMethod pointers
- */
- if (method->klass->image->runtime_invoke_direct_cache)
- g_hash_table_remove (method->klass->image->runtime_invoke_direct_cache, method);
- if (method->klass->image->managed_wrapper_cache)
- g_hash_table_remove (method->klass->image->managed_wrapper_cache, method);
- if (method->klass->image->native_wrapper_cache)
- g_hash_table_remove (method->klass->image->native_wrapper_cache, method);
- if (method->klass->image->remoting_invoke_cache)
- g_hash_table_remove (method->klass->image->remoting_invoke_cache, method);
- if (method->klass->image->synchronized_cache)
- g_hash_table_remove (method->klass->image->synchronized_cache, method);
- if (method->klass->image->unbox_wrapper_cache)
- g_hash_table_remove (method->klass->image->unbox_wrapper_cache, method);
- if (method->klass->image->cominterop_invoke_cache)
- g_hash_table_remove (method->klass->image->cominterop_invoke_cache, method);
- if (method->klass->image->cominterop_wrapper_cache)
- g_hash_table_remove (method->klass->image->cominterop_wrapper_cache, method);
- if (method->klass->image->thunk_invoke_cache)
- g_hash_table_remove (method->klass->image->thunk_invoke_cache, method);
- if (method->klass->image->native_func_wrapper_aot_cache)
- g_hash_table_remove (method->klass->image->native_func_wrapper_aot_cache, method);
-
- mono_marshal_unlock ();
-}