* [remoting] Convert mono_load_remote_field_new_checked to managed code.
* [corlib] Expose runtime struct MonoRemoteClass and MonoClass to managed
Also expose mono_class_get_type to managed code.
* [corlib] Add Mono.RuntimeClassHandle to encapsulate MonoClass*
and Mono.RuntimeRemoteClassHandle to encapsulate MonoRemoteClass*
* [runtime] mono_marshal_get_ldfld_remote_wrapper invoke the managed TransparentProxy.LoadRemoteFieldNew method directly
Don't bother going through a native call and back out to managed.
* [runtime] Get rid of MONO_WRAPPER_LDFLD_REMOTE
When the MONO_WRAPPER_LDFLD is operating on a proxy, it always invokes
the TransparentProxy::LoadRemoteFieldNew managed method
* [runtime] Remove dead mono_load_remote_field_new_icall
* [mini] Bump AOT file format version
Because we removed the LDFLD_REMOTE wrapper type so all the
MonoWrapperType enum values shifted.
--- /dev/null
+//
+// Wrapper handles for Mono Runtime internal structs
+//
+// Authors:
+// Aleksey Kliger <aleksey@xamarin.com>
+// Rodrigo Kumpera <kumpera@xamarin.com>
+//
+// Copyright 2016 Dot net foundation.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Mono {
+
+ internal struct RuntimeClassHandle {
+ unsafe RuntimeStructs.MonoClass* value;
+
+ internal unsafe RuntimeClassHandle (RuntimeStructs.MonoClass* value) {
+ this.value = value;
+ }
+
+ internal unsafe RuntimeClassHandle (IntPtr ptr) {
+ this.value = (RuntimeStructs.MonoClass*) ptr;
+ }
+
+ internal unsafe RuntimeStructs.MonoClass* Value {
+ get { return value; }
+ }
+
+ public override bool Equals (object obj)
+ {
+ if (obj == null || GetType () != obj.GetType ())
+ return false;
+
+ unsafe { return value == ((RuntimeClassHandle)obj).Value; }
+ }
+
+ public override int GetHashCode ()
+ {
+ unsafe { return ((IntPtr)value).GetHashCode (); }
+ }
+
+ public bool Equals (RuntimeClassHandle handle)
+ {
+ unsafe { return value == handle.Value; }
+ }
+
+ public static bool operator == (RuntimeClassHandle left, Object right)
+ {
+ return (right != null) && (right is RuntimeClassHandle) && left.Equals ((RuntimeClassHandle)right);
+ }
+
+ public static bool operator != (RuntimeClassHandle left, Object right)
+ {
+ return (right == null) || !(right is RuntimeClassHandle) || !left.Equals ((RuntimeClassHandle)right);
+ }
+
+ public static bool operator == (Object left, RuntimeClassHandle right)
+ {
+ return (left != null) && (left is RuntimeClassHandle) && ((RuntimeClassHandle)left).Equals (right);
+ }
+
+ public static bool operator != (Object left, RuntimeClassHandle right)
+ {
+ return (left == null) || !(left is RuntimeClassHandle) || !((RuntimeClassHandle)left).Equals (right);
+ }
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal unsafe extern static IntPtr GetTypeFromClass (RuntimeStructs.MonoClass *klass);
+
+ internal RuntimeTypeHandle GetTypeHandle ()
+ {
+ unsafe { return new RuntimeTypeHandle (GetTypeFromClass (value)); }
+ }
+ }
+
+ internal struct RuntimeRemoteClassHandle {
+ unsafe RuntimeStructs.RemoteClass* value;
+
+ internal unsafe RuntimeRemoteClassHandle (RuntimeStructs.RemoteClass* value)
+ {
+ this.value = value;
+ }
+
+ internal RuntimeClassHandle ProxyClass {
+ get {
+ unsafe {
+ return new RuntimeClassHandle (value->proxy_class);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+//
+// Mono runtime native structs surfaced to managed code.
+//
+// Authors:
+// Aleksey Kliger <aleksey@xamarin.com>
+// Rodrigo Kumpera <kumpera@xamarin.com>
+//
+// Copyright 2016 Dot net foundation.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Mono {
+ internal class RuntimeStructs {
+ // class-internals.h MonoRemoteClass
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe struct RemoteClass {
+ internal IntPtr default_vtable;
+ internal IntPtr xdomain_vtable;
+ internal MonoClass* proxy_class;
+ internal IntPtr proxy_class_name;
+ internal uint interface_count;
+ // FIXME: How to represent variable-length array struct member?
+ // MonoClass* interfaces [];
+ }
+
+ internal struct MonoClass {
+ }
+ }
+
+}
+
args = null;
}
- public MonoMethodMessage (Type type, string method_name, object [] in_args)
+ internal MonoMethodMessage (MethodInfo minfo, object [] in_args, object [] out_args)
{
- // fixme: consider arg types
- MethodInfo minfo = type.GetMethod (method_name);
-
- InitMessage ((MonoMethod)minfo, null);
+ InitMessage ((MonoMethod)minfo, out_args);
int len = in_args.Length;
for (int i = 0; i < len; i++) {
args [i] = in_args [i];
}
}
+
+ private static MethodInfo GetMethodInfo (Type type, string methodName)
+ {
+ // fixme: consider arg types
+ MethodInfo minfo = type.GetMethod(methodName);
+ if (minfo == null)
+ throw new ArgumentException (String.Format("Could not find '{0}' in {1}", methodName, type), "methodName");
+ return minfo;
+ }
+ public MonoMethodMessage (Type type, string methodName, object [] in_args)
+ : this (GetMethodInfo (type, methodName), in_args, null)
+ {
+ }
+
public IDictionary Properties {
get {
if (properties == null) properties = new MCMDictionary (this);
[StructLayout (LayoutKind.Sequential)]
internal class TransparentProxy {
public RealProxy _rp;
- IntPtr _class;
+ Mono.RuntimeRemoteClassHandle _class;
bool _custom_type_info;
+
+ unsafe internal RuntimeType GetProxyType () {
+ RuntimeTypeHandle h = _class.ProxyClass.GetTypeHandle ();
+ return (RuntimeType)Type.GetTypeFromHandle (h);
+ }
+
+ bool IsContextBoundObject {
+ get { return GetProxyType ().IsContextful; }
+ }
+
+ Context TargetContext {
+ get { return _rp._targetContext; }
+ }
+
+ bool InCurrentContext () {
+ return IsContextBoundObject && Object.ReferenceEquals (TargetContext, Thread.CurrentContext);
+ }
+
+ internal object LoadRemoteFieldNew (IntPtr classPtr, IntPtr fieldPtr) {
+ Mono.RuntimeClassHandle classHandle = new Mono.RuntimeClassHandle (classPtr);
+ RuntimeFieldHandle fieldHandle = new RuntimeFieldHandle (fieldPtr);
+ RuntimeTypeHandle typeHandle = classHandle.GetTypeHandle ();
+
+ FieldInfo field = FieldInfo.GetFieldFromHandle (fieldHandle);
+
+ if (InCurrentContext ()) {
+ object o = _rp._server;
+ return field.GetValue(o);
+ }
+
+ object[] inArgs = new object[] { Type.GetTypeFromHandle(typeHandle).FullName,
+ field.Name };
+ object[] outArgsMsg = new object[1];
+ MethodInfo minfo = typeof(object).GetMethod("FieldGetter", BindingFlags.NonPublic | BindingFlags.Instance);
+ if (minfo == null)
+ throw new MissingMethodException ("System.Object", "FieldGetter");
+ MonoMethodMessage msg = new MonoMethodMessage (minfo, inArgs, outArgsMsg);
+ object[] outArgs;
+ Exception exc;
+ RealProxy.PrivateInvoke (_rp, msg, out exc, out outArgs);
+ if (exc != null)
+ throw exc;
+ return outArgs[0];
+ }
}
#pragma warning restore 169, 649
#region Sync with object-internals.h
Type class_to_proxy;
internal Context _targetContext;
- MarshalByRefObject _server;
+ internal MarshalByRefObject _server;
int _targetDomainId = -1;
internal string _targetUri;
internal Identity _objectIdentity;
Mono.Globalization.Unicode/Normalization.cs
Mono.Globalization.Unicode/NormalizationTableUtil.cs
Mono/Runtime.cs
+Mono/RuntimeStructs.cs
+Mono/RuntimeHandles.cs
Mono/DataConverter.cs
Mono.Interop/ComInteropProxy.cs
Mono.Interop/IDispatch.cs
<method name="PrivateInvoke" />
<method name="GetAppDomainTarget" />
</type>
- <type fullname="System.Runtime.Remoting.Proxies.TransparentProxy" preserve="fields" />
+ <type fullname="System.Runtime.Remoting.Proxies.TransparentProxy" preserve="fields">
+ <method name="LoadRemoteFieldNew" />
+ </type>
<type fullname="System.Runtime.Remoting.RemotingServices">
<method name="SerializeCallData" />
<method name="DeserializeCallData" />
ICALL(RUNTIME_1, "GetDisplayName", ves_icall_Mono_Runtime_GetDisplayName)
ICALL(RUNTIME_12, "GetNativeStackTrace", ves_icall_Mono_Runtime_GetNativeStackTrace)
+ICALL_TYPE(RTCLASS, "Mono.RuntimeClassHandle", RTCLASS_1)
+ICALL(RTCLASS_1, "GetTypeFromClass", ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass)
+
#ifndef PLATFORM_RO_FS
ICALL_TYPE(KPAIR, "Mono.Security.Cryptography.KeyPairPersistence", KPAIR_1)
ICALL(KPAIR_1, "_CanSecure", ves_icall_Mono_Security_Cryptography_KeyPairPersistence_CanSecure)
return ret;
}
+ICALL_EXPORT MonoType*
+ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
+{
+ return mono_class_get_type (klass);
+}
+
/* System.TypeCode */
typedef enum {
TYPECODE_EMPTY,
void*
mono_load_remote_field_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, void **res, MonoError *error);
-MonoObject *
-mono_load_remote_field_new_icall (MonoObject *this_obj, MonoClass *klass, MonoClassField *field);
-
MonoObject *
mono_load_remote_field_new_checked (MonoObject *this_obj, MonoClass *klass, MonoClassField *field, MonoError *error);
return result;
}
-/**
- * mono_load_remote_field_new_icall:
- * @this: pointer to an object
- * @klass: klass of the object containing @field
- * @field: the field to load
- *
- * This method is called by the runtime on attempts to load fields of
- * transparent proxy objects. @this points to such TP, @klass is the class of
- * the object containing @field.
- *
- * Returns: a freshly allocated object containing the value of the
- * field. On failure returns NULL and throws an exception.
- */
-MonoObject *
-mono_load_remote_field_new_icall (MonoObject *this_obj, MonoClass *klass, MonoClassField *field)
-{
- MonoError error;
- MonoObject *result = mono_load_remote_field_new_checked (this_obj, klass, field, &error);
- mono_error_set_pending_exception (&error);
- return result;
-}
-
/**
* mono_load_remote_field_new_checked:
* @this: pointer to an object
mono_error_init (error);
- static MonoMethod *getter = NULL;
- MonoDomain *domain = mono_domain_get ();
- MonoTransparentProxy *tp = (MonoTransparentProxy *) this_obj;
- MonoClass *field_class;
- MonoMethodMessage *msg;
- MonoArray *out_args;
- MonoObject *exc, *res;
- char* full_name;
+ static MonoMethod *tp_load = NULL;
g_assert (mono_object_is_transparent_proxy (this_obj));
- field_class = mono_class_from_mono_type (field->type);
-
- if (mono_class_is_contextbound (tp->remote_class->proxy_class) && tp->rp->context == (MonoObject *) mono_context_get ()) {
- gpointer val;
- if (field_class->valuetype) {
- res = mono_object_new_checked (domain, field_class, error);
- return_val_if_nok (error, NULL);
- val = ((gchar *) res) + sizeof (MonoObject);
- } else {
- val = &res;
- }
- mono_field_get_value (tp->rp->unwrapped_server, field, val);
- return res;
- }
-
- if (!getter) {
- getter = mono_class_get_method_from_name (mono_defaults.object_class, "FieldGetter", -1);
- if (!getter) {
+ if (!tp_load) {
+ tp_load = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "LoadRemoteFieldNew", -1);
+ if (!tp_load) {
mono_error_set_not_supported (error, "Linked away.");
return NULL;
}
}
- msg = (MonoMethodMessage *)mono_object_new_checked (domain, mono_defaults.mono_method_message_class, error);
- return_val_if_nok (error, NULL);
- out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, error);
- return_val_if_nok (error, NULL);
-
- MonoReflectionMethod *rm = mono_method_get_object_checked (domain, getter, NULL, error);
- return_val_if_nok (error, NULL);
- mono_message_init (domain, msg, rm, out_args, error);
- return_val_if_nok (error, NULL);
+ /* MonoType *type = mono_class_get_type (klass); */
- full_name = mono_type_get_full_name (klass);
- mono_array_setref (msg->args, 0, mono_string_new (domain, full_name));
- mono_array_setref (msg->args, 1, mono_string_new (domain, mono_field_get_name (field)));
- g_free (full_name);
-
- mono_remoting_invoke ((MonoObject *)(tp->rp), msg, &exc, &out_args, error);
- return_val_if_nok (error, NULL);
-
- if (exc) {
- mono_error_set_exception_instance (error, (MonoException *)exc);
- return NULL;
- }
-
- if (mono_array_length (out_args) == 0)
- res = NULL;
- else
- res = mono_array_get (out_args, MonoObject *, 0);
+ gpointer args[2];
+ args [0] = &klass;
+ args [1] = &field;
- return res;
+ return mono_runtime_invoke_checked (tp_load, this_obj, args, error);
}
/**
register_icall (mono_remoting_wrapper, "mono_remoting_wrapper", "object ptr ptr", FALSE);
register_icall (mono_upgrade_remote_class_wrapper, "mono_upgrade_remote_class_wrapper", "void object object", FALSE);
register_icall (mono_compile_method_icall, "mono_compile_method_icall", "ptr ptr", FALSE);
- /* mono_load_remote_field_new_icall registered by mini-runtime.c */
/* mono_store_remote_field_new_icall registered by mini-runtime.c */
}
return res;
}
-/*
- * mono_marshal_get_ldfld_remote_wrapper:
- * @klass: The return type
- *
- * This method generates a wrapper for calling mono_load_remote_field_new.
- * The return type is ignored for now, as mono_load_remote_field_new () always
- * returns an object. In the future, to optimize some codepaths, we might
- * call a different function that takes a pointer to a valuetype, instead.
- */
-MonoMethod *
-mono_marshal_get_ldfld_remote_wrapper (MonoClass *klass)
-{
- MonoMethodSignature *sig;
- MonoMethodBuilder *mb;
- MonoMethod *res;
- static MonoMethod* cached = NULL;
-
- mono_marshal_lock_internal ();
- if (cached) {
- mono_marshal_unlock_internal ();
- return cached;
- }
- mono_marshal_unlock_internal ();
-
- mb = mono_mb_new_no_dup_name (mono_defaults.object_class, "__mono_load_remote_field_new_wrapper", MONO_WRAPPER_LDFLD_REMOTE);
-
- mb->method->save_lmf = 1;
-
- 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->ret = &mono_defaults.object_class->byval_arg;
-
-#ifndef DISABLE_JIT
- mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_ldarg (mb, 1);
- mono_mb_emit_ldarg (mb, 2);
-
- mono_mb_emit_icall (mb, mono_load_remote_field_new_icall);
-
- mono_mb_emit_byte (mb, CEE_RET);
-#endif
-
- mono_marshal_lock_internal ();
- res = cached;
- mono_marshal_unlock_internal ();
- if (!res) {
- MonoMethod *newm;
- newm = mono_mb_create (mb, sig, 4, NULL);
- mono_marshal_lock_internal ();
- res = cached;
- if (!res) {
- res = newm;
- cached = res;
- mono_marshal_unlock_internal ();
- } else {
- mono_marshal_unlock_internal ();
- mono_free_method (newm);
- }
- }
- mono_mb_free (mb);
-
- return res;
-}
-
/*
* mono_marshal_get_ldfld_wrapper:
* @type: the type of the field
WrapperInfo *info;
char *name;
int t, pos0, pos1 = 0;
+ static MonoMethod* tp_load = NULL;
type = mono_type_get_underlying_type (type);
if ((res = mono_marshal_find_in_cache (cache, klass)))
return res;
+ if (!tp_load) {
+ tp_load = mono_class_get_method_from_name (mono_defaults.transparent_proxy_class, "LoadRemoteFieldNew", -1);
+ g_assert (tp_load != NULL);
+ }
+
/* we add the %p pointer value of klass because class names are not unique */
name = g_strdup_printf ("__ldfld_wrapper_%p_%s.%s", klass, klass->name_space, klass->name);
mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_LDFLD);
mono_mb_emit_ldarg (mb, 1);
mono_mb_emit_ldarg (mb, 2);
- mono_mb_emit_managed_call (mb, mono_marshal_get_ldfld_remote_wrapper (klass), NULL);
+ mono_mb_emit_managed_call (mb, tp_load, NULL);
/*
csig = mono_metadata_signature_alloc (mono_defaults.corlib, 3);
WRAPPER(XDOMAIN_DISPATCH, "xdomain-dispatch")
WRAPPER(LDFLD, "ldfld")
WRAPPER(STFLD, "stfld")
-WRAPPER(LDFLD_REMOTE, "ldfld-remote")
WRAPPER(STFLD_REMOTE, "stfld-remote")
WRAPPER(SYNCHRONIZED, "synchronized")
WRAPPER(DYNAMIC_METHOD, "dynamic-method")
encode_klass_ref (acfg, info->d.proxy.klass, p, &p);
break;
}
- case MONO_WRAPPER_LDFLD_REMOTE:
case MONO_WRAPPER_STFLD_REMOTE:
break;
case MONO_WRAPPER_ALLOC: {
case MONO_WRAPPER_STFLD:
case MONO_WRAPPER_LDFLD:
case MONO_WRAPPER_LDFLDA:
- case MONO_WRAPPER_LDFLD_REMOTE:
case MONO_WRAPPER_STFLD_REMOTE:
case MONO_WRAPPER_STELEMREF:
case MONO_WRAPPER_ISINST:
}
break;
}
- case MONO_WRAPPER_LDFLD_REMOTE:
- ref->method = mono_marshal_get_ldfld_remote_wrapper (NULL);
- break;
case MONO_WRAPPER_STFLD_REMOTE:
ref->method = mono_marshal_get_stfld_remote_wrapper (NULL);
break;
register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "object", FALSE);
register_icall (mono_thread_force_interruption_checkpoint_noraise, "mono_thread_force_interruption_checkpoint_noraise", "object", FALSE);
#ifndef DISABLE_REMOTING
- register_icall (mono_load_remote_field_new_icall, "mono_load_remote_field_new_icall", "object object ptr ptr", FALSE);
register_icall (mono_store_remote_field_new_icall, "mono_store_remote_field_new_icall", "void object ptr ptr object", FALSE);
#endif
if (code)
return code;
if (mono_llvm_only) {
- if (method->wrapper_type == MONO_WRAPPER_PROXY_ISINST || method->wrapper_type == MONO_WRAPPER_LDFLD_REMOTE ||
+ if (method->wrapper_type == MONO_WRAPPER_PROXY_ISINST ||
method->wrapper_type == MONO_WRAPPER_STFLD_REMOTE)
/* These wrappers are not generated */
return method_not_found;
#endif
/* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION 133
+#define MONO_AOT_FILE_VERSION 134
//TODO: This is x86/amd64 specific.
#define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6))