}
internal class CADObjRef {
- ObjRef objref;
- public int SourceDomain;
+ internal ObjRef objref;
+ internal int SourceDomain;
+ internal byte[] TypeInfo;
public CADObjRef (ObjRef o, int sourceDomain) {
objref = o;
+ TypeInfo = o.SerializeType ();
SourceDomain = sourceDomain;
}
-
+
public string TypeName {
get { return objref.TypeInfo.TypeName; }
}
}
}
+ [Serializable]
+ internal class CADMethodRef
+ {
+ internal string FullTypeName;
+ internal IntPtr MethodHandlePtr;
+
+ public RuntimeMethodHandle MethodHandle {
+ get {
+ return new RuntimeMethodHandle (MethodHandlePtr);
+ }
+ }
+
+ public CADMethodRef (IMethodMessage msg)
+ {
+ MethodHandlePtr = msg.MethodBase.MethodHandle.Value;
+ FullTypeName = msg.MethodBase.DeclaringType.AssemblyQualifiedName;
+ }
+ }
+
internal class CADMessageBase {
protected object [] _args;
protected byte [] _serializedArgs = null;
protected int _propertyCount = 0;
protected CADArgHolder _callContext;
- internal RuntimeMethodHandle MethodHandle;
- internal string FullTypeName;
- internal MethodBase _method;
+ internal byte[] serializedMethod;
public CADMessageBase (IMethodMessage msg) {
- MethodHandle = msg.MethodBase.MethodHandle;
- FullTypeName = msg.MethodBase.DeclaringType.AssemblyQualifiedName;
+ CADMethodRef methodRef = new CADMethodRef (msg);
+ serializedMethod = CADSerializer.SerializeObject (methodRef).GetBuffer ();
}
internal MethodBase method {
- get {
- if (_method == null) {
- _method = GetMethod();
- }
- return _method;
- }
+ get { return GetMethod (); }
}
internal MethodBase GetMethod ()
{
- Type tt = Type.GetType (FullTypeName, true);
+ CADMethodRef methRef = (CADMethodRef)CADSerializer.DeserializeObjectSafe (serializedMethod);
+
+ MethodBase _method;
+
+ Type tt = Type.GetType (methRef.FullTypeName, true);
if (tt.IsGenericType || tt.IsGenericTypeDefinition) {
- _method = MethodBase.GetMethodFromHandleNoGenericCheck (MethodHandle);
+ _method = MethodBase.GetMethodFromHandleNoGenericCheck (methRef.MethodHandle);
} else {
- _method = MethodBase.GetMethodFromHandle (MethodHandle);
+ _method = MethodBase.GetMethodFromHandle (methRef.MethodHandle);
}
if (tt != _method.DeclaringType) {
return new CADArgHolder(args.Count - 1);
}
- protected object UnmarshalArgument (object arg, ArrayList args, Type argType) {
+ protected object UnmarshalArgument (object arg, ArrayList args) {
if (arg == null) return null;
// Check if argument is an holder (then we know that it's a serialized argument)
CADObjRef objref = arg as CADObjRef;
if (null != objref) {
- string typeName;
-
- if (argType != null) {
- typeName = string.Copy (argType.AssemblyQualifiedName);
- } else {
- typeName = string.Copy (objref.TypeName);
- }
-
- string uri = string.Copy (objref.URI);
- int domid = objref.SourceDomain;
-
- ChannelInfo cinfo = new ChannelInfo (new CrossAppDomainData (domid));
- ObjRef localRef = new ObjRef (typeName, uri, cinfo);
+ ObjRef localRef = objref.objref.DeserializeInTheCurrentDomain (objref.SourceDomain, objref.TypeInfo);
return RemotingServices.Unmarshal (localRef);
}
return marshalledArgs;
}
- internal object [] UnmarshalArguments (object [] arguments, ArrayList args, Type [] sig) {
+ internal object [] UnmarshalArguments (object [] arguments, ArrayList args) {
object [] unmarshalledArgs = new object [arguments.Length];
int total = arguments.Length;
for (int i = 0; i < total; i++)
- unmarshalledArgs [i] = UnmarshalArgument (arguments [i], args, sig [i]);
+ unmarshalledArgs [i] = UnmarshalArgument (arguments [i], args);
return unmarshalledArgs;
}
}
internal object [] GetArgs (ArrayList args) {
- Type [] sigs = GetSignature (method, true);
- return UnmarshalArguments (_args, args, sigs);
+ return UnmarshalArguments (_args, args);
}
internal int PropertiesCount {
}
internal object [] GetArgs (ArrayList args) {
- return UnmarshalArguments (_args, args, _sig);
+ return UnmarshalArguments (_args, args);
}
internal object GetReturnValue (ArrayList args) {
- MethodInfo minfo = method as MethodInfo;
-
- Type returnType = null;
- if (minfo != null)
- returnType = minfo.ReturnType;
-
- return UnmarshalArgument (_returnValue, args, returnType);
+ return UnmarshalArgument (_returnValue, args);
}
internal Exception GetException(ArrayList args) {
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 */
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 ();
return mono_compile_method (method);
}
+/*
+ * 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);
+}
/*
* This does the equivalent of mono_object_castclass_with_cache.
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);
+
+ if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
+ return isinst;
+
+ 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)) */
+ // return obj
+ mono_mb_patch_branch (mb, positive_cache_hit_pos);
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;*/
- 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