X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmarshal.c;h=2b66637c2bf6c5368ed6039407034fd3a918e68b;hb=d6cdd9715eff6eeac53c9d0970a90e49b7c80edd;hp=9d814406af930fedc556c9ef2aece3bbb7f201fe;hpb=3c1b5fd65a02049e673e65cf3ca57c184fc36650;p=mono.git diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 9d814406af9..2b66637c2bf 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -81,7 +81,7 @@ static guint32 last_error_tls_id; static guint32 load_type_info_tls_id; static void -delegate_hash_table_add (MonoDelegate *d, MonoObject **target_loc); +delegate_hash_table_add (MonoDelegate *d); static void emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object); @@ -245,6 +245,7 @@ mono_marshal_init (void) register_icall (mono_upgrade_remote_class_wrapper, "mono_upgrade_remote_class_wrapper", "void object object", FALSE); register_icall (type_from_handle, "type_from_handle", "object ptr", 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); mono_cominterop_init (); } @@ -307,7 +308,7 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate) { MonoMethod *method, *wrapper; MonoClass *klass; - MonoObject **target_loc; + uint32_t target_handle = 0; if (!delegate) return NULL; @@ -334,18 +335,15 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate) if (delegate->target) { /* Produce a location which can be embedded in JITted code */ - target_loc = mono_gc_alloc_fixed (sizeof (MonoObject*), NULL); - *target_loc = delegate->target; - } else { - target_loc = NULL; + target_handle = mono_gchandle_new_weakref (delegate->target, FALSE); } - wrapper = mono_marshal_get_managed_wrapper (method, klass, target_loc); + wrapper = mono_marshal_get_managed_wrapper (method, klass, target_handle); delegate->delegate_trampoline = mono_compile_method (wrapper); // Add the delegate to the delegate hash table - delegate_hash_table_add (delegate, target_loc); + delegate_hash_table_add (delegate); /* when the object is collected, collect the dynamic method, too */ mono_object_register_finalizer ((MonoObject*)delegate); @@ -359,8 +357,6 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate) * object pointer itself, otherwise we use a GC handle. */ static GHashTable *delegate_hash_table; -/* Contains root locations pointing to the this arguments of delegates */ -static MonoGHashTable *delegate_target_locations; static GHashTable * delegate_hash_table_new (void) { @@ -370,7 +366,6 @@ delegate_hash_table_new (void) { static void delegate_hash_table_remove (MonoDelegate *d) { - MonoObject **target_loc; #ifdef HAVE_MOVING_COLLECTOR guint32 gchandle; #endif @@ -381,23 +376,14 @@ delegate_hash_table_remove (MonoDelegate *d) gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, d->delegate_trampoline)); #endif g_hash_table_remove (delegate_hash_table, d->delegate_trampoline); - if (delegate_target_locations) - target_loc = mono_g_hash_table_lookup (delegate_target_locations, d->delegate_trampoline); - else - target_loc = NULL; - if (target_loc) - mono_g_hash_table_remove (delegate_target_locations, d->delegate_trampoline); mono_marshal_unlock (); - if (target_loc) { - mono_gc_free_fixed (target_loc); - } #ifdef HAVE_MOVING_COLLECTOR mono_gchandle_free (gchandle); #endif } static void -delegate_hash_table_add (MonoDelegate *d, MonoObject **target_loc) +delegate_hash_table_add (MonoDelegate *d) { #ifdef HAVE_MOVING_COLLECTOR guint32 gchandle = mono_gchandle_new_weakref ((MonoObject*)d, FALSE); @@ -406,11 +392,6 @@ delegate_hash_table_add (MonoDelegate *d, MonoObject **target_loc) mono_marshal_lock (); if (delegate_hash_table == NULL) delegate_hash_table = delegate_hash_table_new (); - if (delegate_target_locations == NULL) { - /* Has to be conservative as the values are not object references */ - delegate_target_locations = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_CONSERVATIVE_GC); - MONO_GC_REGISTER_ROOT (delegate_target_locations); - } #ifdef HAVE_MOVING_COLLECTOR old_gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, d->delegate_trampoline)); g_hash_table_insert (delegate_hash_table, d->delegate_trampoline, GUINT_TO_POINTER (gchandle)); @@ -419,9 +400,6 @@ delegate_hash_table_add (MonoDelegate *d, MonoObject **target_loc) #else g_hash_table_insert (delegate_hash_table, d->delegate_trampoline, d); #endif - if (target_loc) - /* This keeps target_loc alive for Boehm */ - mono_g_hash_table_insert (delegate_target_locations, d->delegate_trampoline, target_loc); mono_marshal_unlock (); } @@ -524,9 +502,19 @@ mono_delegate_free_ftnptr (MonoDelegate *delegate) } if (ptr) { + uint32_t gchandle; + void **method_data; ji = mono_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (ptr)); g_assert (ji); + method_data = ((MonoMethodWrapper*)ji->method)->method_data; + + /*the target gchandle is the first entry after size and the wrapper itself.*/ + gchandle = GPOINTER_TO_UINT (method_data [2]); + + if (gchandle) + mono_gchandle_free (gchandle); + mono_runtime_free_method (mono_object_domain (delegate), ji->method); } } @@ -583,10 +571,10 @@ mono_array_to_lparray (MonoArray *array) case MONO_TYPE_R4: case MONO_TYPE_R8: case MONO_TYPE_VALUETYPE: + case MONO_TYPE_PTR: /* nothing to do */ break; case MONO_TYPE_GENERICINST: - case MONO_TYPE_PTR: case MONO_TYPE_OBJECT: case MONO_TYPE_ARRAY: case MONO_TYPE_SZARRAY: @@ -2327,18 +2315,6 @@ mono_marshal_find_in_cache (GHashTable *cache, gpointer key) return res; } -static void -mono_marshal_method_set_wrapper_data (MonoMethod *method, gpointer data) -{ - void **datav; - /* assert */ - if (method->wrapper_type == MONO_WRAPPER_NONE || method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) - return; - - datav = ((MonoMethodWrapper *)method)->method_data; - datav [1] = data; -} - /* Create the method from the builder and place it in the cache */ MonoMethod* mono_mb_create_and_cache (GHashTable *cache, gpointer key, @@ -2358,7 +2334,7 @@ mono_mb_create_and_cache (GHashTable *cache, gpointer key, if (!res) { res = newm; g_hash_table_insert (cache, key, res); - mono_marshal_method_set_wrapper_data (res, key); + mono_marshal_set_wrapper_info (res, key); mono_marshal_unlock (); } else { mono_marshal_unlock (); @@ -2431,7 +2407,7 @@ mono_remoting_mb_create_and_cache (MonoMethod *key, MonoMethodBuilder *mb, mono_marshal_lock (); if (!*res) { *res = newm; - mono_marshal_method_set_wrapper_data (*res, key); + mono_marshal_set_wrapper_info (*res, key); mono_marshal_unlock (); } else { mono_marshal_unlock (); @@ -2446,22 +2422,59 @@ MonoMethod * mono_marshal_method_from_wrapper (MonoMethod *wrapper) { gpointer res; + int wrapper_type = wrapper->wrapper_type; - if (wrapper->wrapper_type == MONO_WRAPPER_NONE || wrapper->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) + if (wrapper_type == MONO_WRAPPER_NONE || wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) return wrapper; - res = mono_method_get_wrapper_data (wrapper, 1); - if (res == NULL) - return wrapper; - return res; + switch (wrapper_type) { + case MONO_WRAPPER_REMOTING_INVOKE: + case MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK: + case MONO_WRAPPER_XDOMAIN_INVOKE: + case MONO_WRAPPER_SYNCHRONIZED: + case MONO_WRAPPER_MANAGED_TO_NATIVE: + case MONO_WRAPPER_RUNTIME_INVOKE: + res = mono_method_get_wrapper_data (wrapper, 1); + if (res == NULL) + return wrapper; + return res; + default: + return NULL; + } } +/* + * mono_marshal_get_wrapper_info: + * + * Retrieve the pointer stored by mono_marshal_set_wrapper_info. + */ gpointer -mono_marshal_wrapper_info_from_wrapper (MonoMethod *wrapper) +mono_marshal_get_wrapper_info (MonoMethod *wrapper) { + g_assert (wrapper->wrapper_type); + return mono_method_get_wrapper_data (wrapper, 1); } +/* + * mono_marshal_set_wrapper_info: + * + * Store an arbitrary pointer inside the wrapper which is retrievable by + * mono_marshal_get_wrapper_info. The format of the data depends on the type of the + * wrapper (method->wrapper_type). + */ +void +mono_marshal_set_wrapper_info (MonoMethod *method, gpointer data) +{ + void **datav; + /* assert */ + if (method->wrapper_type == MONO_WRAPPER_NONE || method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) + return; + + datav = ((MonoMethodWrapper *)method)->method_data; + datav [1] = data; +} + /* * get_wrapper_target_class: * @@ -2570,7 +2583,7 @@ mono_delegate_end_invoke (MonoDelegate *delegate, gpointer *params) return NULL; } - if (ares->async_delegate != (MonoObject*)delegate && mono_framework_version () >= 2) { + if (ares->async_delegate != (MonoObject*)delegate) { mono_raise_exception (mono_get_exception_invalid_operation ( "The IAsyncResult object provided does not match this delegate.")); return NULL; @@ -3752,6 +3765,7 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del) MonoMethod *target_method = NULL; MonoClass *target_class = NULL; gboolean callvirt = FALSE; + gboolean closed_over_null = FALSE; /* * If the delegate target is null, and the target method is not static, a virtual @@ -3778,6 +3792,9 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del) sig = mono_signature_no_pinvoke (method); + if (callvirt) + closed_over_null = sig->param_count == mono_method_signature (del->method)->param_count; + if (callvirt) { /* We need to cache the signature+method pair */ mono_marshal_lock (); @@ -3875,11 +3892,18 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del) mono_mb_patch_branch (mb, pos0); if (callvirt) { - 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 (!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); + } else { + mono_mb_emit_byte (mb, CEE_LDNULL); + for (i = 0; i < sig->param_count; ++i) + mono_mb_emit_ldarg (mb, i + 1); + mono_mb_emit_op (mb, CEE_CALL, target_method); + } } else { for (i = 0; i < sig->param_count; ++i) mono_mb_emit_ldarg (mb, i + 1); @@ -3905,7 +3929,7 @@ mono_marshal_get_delegate_invoke (MonoMethod *method, MonoDelegate *del) new_key->sig = sig; new_key->method = target_method; g_hash_table_insert (cache, new_key, res); - mono_marshal_method_set_wrapper_data (res, new_key); + mono_marshal_set_wrapper_info (res, new_key); mono_marshal_unlock (); } else { mono_marshal_unlock (); @@ -4010,12 +4034,9 @@ mono_marshal_get_string_ctor_signature (MonoMethod *method) static MonoType* get_runtime_invoke_type (MonoType *t, gboolean ret) { - if (t->byref) { - if (t->type == MONO_TYPE_GENERICINST) - return t; - else - return &mono_defaults.int_class->byval_arg; - } + if (t->byref) + /* Can't share this with 'I' as that needs another indirection */ + return t; if (MONO_TYPE_IS_REFERENCE (t)) return &mono_defaults.object_class->byval_arg; @@ -4166,41 +4187,15 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual) } } -#if 0 - /* Vtypes/nullables/Byrefs cause too many problems */ - for (i = 0; i < callsig->param_count; ++i) { - if (MONO_TYPE_ISSTRUCT (callsig->params [i]) || callsig->params [i]->byref) - need_direct_wrapper = TRUE; - } -#endif + target_klass = get_wrapper_target_class (method->klass->image); - /* - * We try to share runtime invoke wrappers between different methods but have to - * be careful about methods whose klass has a type cctor, since putting the wrapper - * into that klass would mean that calling a method of klass A might invoke the - * type initializer of class B, or throw an exception if the type initializer - * was called before and failed. See #349621 for an example. - * We avoid that for mscorlib methods by putting every wrapper into the object class. - */ - if (method->klass->image == mono_defaults.corlib) + /* Try to share wrappers for non-corlib methods with simple signatures */ + if (mono_metadata_signature_equal (callsig, cctor_signature)) { + callsig = cctor_signature; + target_klass = mono_defaults.object_class; + } else if (mono_metadata_signature_equal (callsig, finalize_signature)) { + callsig = finalize_signature; target_klass = mono_defaults.object_class; - else { - /* Try to share wrappers for non-corlib methods with simple signatures */ - if (mono_metadata_signature_equal (callsig, cctor_signature)) { - callsig = cctor_signature; - target_klass = mono_defaults.object_class; - } else if (mono_metadata_signature_equal (callsig, finalize_signature)) { - callsig = finalize_signature; - target_klass = mono_defaults.object_class; - } else { - // FIXME: This breaks too many things - /* - if (mono_class_get_cctor (method->klass)) - need_direct_wrapper = TRUE; - */ - - target_klass = get_wrapper_target_class (method->klass->image); - } } if (need_direct_wrapper) { @@ -4258,14 +4253,6 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual) /* allocate local 1 (object) exc */ mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg); - /* cond set *exc to null */ - mono_mb_emit_byte (mb, CEE_LDARG_2); - mono_mb_emit_byte (mb, CEE_BRFALSE_S); - mono_mb_emit_byte (mb, 3); - mono_mb_emit_byte (mb, CEE_LDARG_2); - mono_mb_emit_byte (mb, CEE_LDNULL); - mono_mb_emit_byte (mb, CEE_STIND_REF); - emit_thread_force_interrupt_checkpoint (mb); if (virtual) { @@ -7620,11 +7607,11 @@ emit_marshal_boolean (EmitMarshalContext *m, int argnum, MonoType *t, /* Check null */ if (t->byref) { - label_null = mono_mb_emit_branch (mb, CEE_BRFALSE); mono_mb_emit_ldarg (mb, argnum); mono_mb_emit_byte (mb, ldop); - } + } else + label_null = 0; label_false = mono_mb_emit_branch (mb, CEE_BRFALSE); mono_mb_emit_byte (mb, CEE_LDC_I4_1); @@ -8049,6 +8036,12 @@ mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoM mono_mb_emit_byte (mb, CEE_RET); } +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. @@ -8178,8 +8171,20 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, if (method->string_ctor) csig->ret = &mono_defaults.string_class->byval_arg; - if (sig->hasthis) + if (sig->hasthis) { + int pos; + + /* + * Add a null check since public icalls can be called with 'call' which + * does no such check. + */ + mono_mb_emit_byte (mb, CEE_LDARG_0); + pos = mono_mb_emit_branch (mb, CEE_BRTRUE); + mono_mb_emit_exception (mb, "NullReferenceException", NULL); + mono_mb_patch_branch (mb, pos); + mono_mb_emit_byte (mb, CEE_LDARG_0); + } for (i = 0; i < sig->param_count; i++) mono_mb_emit_ldarg (mb, i + sig->hasthis); @@ -8224,7 +8229,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, mono_metadata_free_marshal_spec (mspecs [i]); g_free (mspecs); - /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */ + /* code_for (res); */ return res; } @@ -8265,7 +8270,9 @@ mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig mb, csig, csig->param_count + 16); mono_mb_free (mb); - /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */ + mono_marshal_set_wrapper_info (res, NULL); + + /* code_for (res); */ return res; } @@ -8279,7 +8286,7 @@ mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig * THIS_LOC is the memory location where the target of the delegate is stored. */ void -mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoObject** this_loc) +mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, uint32_t target_handle) { MonoMethodSignature *sig, *csig; int i, *tmp_locals; @@ -8338,16 +8345,16 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i emit_thread_interrupt_checkpoint (mb); if (sig->hasthis) { - if (this_loc) { - mono_mb_emit_ptr (mb, this_loc); - mono_mb_emit_byte (mb, CEE_LDIND_REF); + if (target_handle) { + mono_mb_emit_icon (mb, (gint32)target_handle); + mono_mb_emit_icall (mb, mono_gchandle_get_target); } else { /* fixme: */ g_assert_not_reached (); } } else if (closed) { - mono_mb_emit_ptr (mb, this_loc); - mono_mb_emit_byte (mb, CEE_LDIND_REF); + mono_mb_emit_icon (mb, (gint32)target_handle); + mono_mb_emit_icall (mb, mono_gchandle_get_target); } for (i = 0; i < sig->param_count; i++) { @@ -8495,7 +8502,7 @@ mono_marshal_set_callconv_from_modopt (MonoMethod *method, MonoMethodSignature * * generates IL code to call managed methods from unmanaged code */ MonoMethod * -mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoObject **this_loc) +mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, uint32_t target_handle) { static MonoClass *UnmanagedFunctionPointerAttribute; MonoMethodSignature *sig, *csig, *invoke_sig; @@ -8516,7 +8523,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, * options. */ cache = get_cache (&method->klass->image->managed_wrapper_cache, mono_aligned_addr_hash, NULL); - if (!this_loc && (res = mono_marshal_find_in_cache (cache, method))) + if (!target_handle && (res = mono_marshal_find_in_cache (cache, method))) return res; invoke = mono_get_delegate_invoke (delegate_klass); @@ -8529,8 +8536,11 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_NATIVE_TO_MANAGED); + /*the target gchandle must be the first entry after size and the wrapper itself.*/ + mono_mb_add_data (mb, GUINT_TO_POINTER (target_handle)); + /* we copy the signature, so that we can modify it */ - if (this_loc) + if (target_handle) /* Need to free this later */ csig = mono_metadata_signature_dup (invoke_sig); else @@ -8622,9 +8632,9 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, mono_custom_attrs_free (cinfo); } - mono_marshal_emit_managed_wrapper (mb, invoke_sig, mspecs, &m, method, this_loc); + mono_marshal_emit_managed_wrapper (mb, invoke_sig, mspecs, &m, method, target_handle); - if (!this_loc) + if (!target_handle) res = mono_mb_create_and_cache (cache, method, mb, csig, sig->param_count + 16); else { @@ -8638,7 +8648,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, mono_metadata_free_marshal_spec (mspecs [i]); g_free (mspecs); - /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */ + /* code_for (res); */ return res; } @@ -8683,7 +8693,7 @@ mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type) /* FIXME: Implement VTFIXUP_TYPE_FROM_UNMANAGED_RETAIN_APPDOMAIN. */ - mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, NULL); + mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, 0); mb->dynamic = 1; method = mono_mb_create_method (mb, csig, sig->param_count + 16); @@ -9273,7 +9283,7 @@ mono_marshal_get_unbox_wrapper (MonoMethod *method) mb, sig, sig->param_count + 16); mono_mb_free (mb); - /* printf ("CODE FOR %s: \n%s.\n", mono_method_full_name (res, TRUE), mono_disasm_code (0, res, ((MonoMethodNormal*)res)->header->code, ((MonoMethodNormal*)res)->header->code + ((MonoMethodNormal*)res)->header->code_size)); */ + /* code_for (res); */ return res; } @@ -9587,7 +9597,7 @@ mono_marshal_get_array_address (int rank, int elem_size) info->rank = rank; info->elem_size = elem_size; - mono_marshal_method_set_wrapper_data (ret, info); + mono_marshal_set_wrapper_info (ret, info); } mono_marshal_unlock (); return ret; @@ -9928,6 +9938,9 @@ ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rty type = rtype->type; klass = mono_class_from_mono_type (type); + if (!mono_class_init (klass)) + mono_raise_exception (mono_class_get_exception_for_failure (klass)); + layout = (klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK); if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) { @@ -10008,6 +10021,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure (gpointer src, M MonoObject * ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type) { + MonoClass *klass; MonoDomain *domain = mono_domain_get (); MonoObject *res; @@ -10016,7 +10030,11 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer s MONO_CHECK_ARG_NULL (src); MONO_CHECK_ARG_NULL (type); - res = mono_object_new (domain, mono_class_from_mono_type (type->type)); + klass = mono_class_from_mono_type (type->type); + if (!mono_class_init (klass)) + mono_raise_exception (mono_class_get_exception_for_failure (klass)); + + res = mono_object_new (domain, klass); ptr_to_structure (src, res); @@ -10038,6 +10056,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *t fname = mono_string_to_utf8 (field_name); klass = mono_class_from_mono_type (type->type); + if (!mono_class_init (klass)) + mono_raise_exception (mono_class_get_exception_for_failure (klass)); while (klass && match_index == -1) { MonoClassField* field; @@ -10180,6 +10200,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MONO_CHECK_ARG_NULL (type); klass = mono_class_from_mono_type (type->type); + if (!mono_class_init (klass)) + mono_raise_exception (mono_class_get_exception_for_failure (klass)); mono_struct_delete_old (klass, (char *)src); } @@ -10284,7 +10306,11 @@ ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement MonoDelegate* ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionType *type) { - return mono_ftnptr_to_delegate (mono_type_get_class (type->type), ftn); + MonoClass *klass = mono_type_get_class (type->type); + if (!mono_class_init (klass)) + mono_raise_exception (mono_class_get_exception_for_failure (klass)); + + return mono_ftnptr_to_delegate (klass, ftn); } /** @@ -10690,7 +10716,7 @@ mono_marshal_asany (MonoObject *o, MonoMarshalNative string_encoding, int param_ case MONO_TYPE_STRING: switch (string_encoding) { case MONO_NATIVE_LPWSTR: - return mono_string_to_utf16 ((MonoString*)o); + return mono_marshal_string_to_utf16_copy ((MonoString*)o); break; case MONO_NATIVE_LPSTR: return mono_string_to_lpstr ((MonoString*)o); @@ -11036,14 +11062,17 @@ mono_marshal_free_dynamic_wrappers (MonoMethod *method) { g_assert (method->dynamic); - mono_marshal_lock (); + /* This could be called during shutdown */ + if (marshal_mutex_initialized) + mono_marshal_lock (); /* * FIXME: We currently leak the wrappers. Freeing them would be tricky as * they could be shared with other methods ? */ if (method->klass->image->runtime_invoke_direct_cache) g_hash_table_remove (method->klass->image->runtime_invoke_direct_cache, method); - mono_marshal_unlock (); + if (marshal_mutex_initialized) + mono_marshal_unlock (); } /*