X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmarshal.c;h=2b66637c2bf6c5368ed6039407034fd3a918e68b;hb=d6cdd9715eff6eeac53c9d0970a90e49b7c80edd;hp=f56750d9c9ac3d560ef4f4d1001d9df93d87a173;hpb=f60b8b5b22e614fac834acb48492923d7b0b8ffc;p=mono.git diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index f56750d9c9a..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: @@ -2434,14 +2422,25 @@ 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; + } } /* @@ -2584,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; @@ -3766,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 @@ -3792,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 (); @@ -3889,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); @@ -4024,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; @@ -4180,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) { @@ -4272,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) { @@ -7634,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); @@ -8063,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. @@ -8250,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; } @@ -8291,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; } @@ -8305,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; @@ -8364,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++) { @@ -8521,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; @@ -8542,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); @@ -8555,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 @@ -8648,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 { @@ -8664,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; } @@ -8709,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); @@ -9299,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; } @@ -9954,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) { @@ -10034,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; @@ -10042,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); @@ -10064,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; @@ -10206,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); } @@ -10310,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); } /** @@ -10716,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); @@ -11062,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 (); } /*