Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfrijters <jfrijters>2014-11-14 18:28:34 +0300
committerjfrijters <jfrijters>2014-11-14 18:28:34 +0300
commitdba88a3d8e1231a0abfd3cf4761d2f1aab174d1f (patch)
tree6fa9a67ee1fe4515b78b3608c37ee4c656678d6c
parent38d12d653450c3e8b80d3972a3f9d154b7ff47dd (diff)
Added intrinsic for array version of Unsafe.getAndSetObject().
-rw-r--r--runtime/intrinsics.cs55
1 files changed, 54 insertions, 1 deletions
diff --git a/runtime/intrinsics.cs b/runtime/intrinsics.cs
index 402969d7..319c0d4b 100644
--- a/runtime/intrinsics.cs
+++ b/runtime/intrinsics.cs
@@ -209,6 +209,7 @@ namespace IKVM.Internal
intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "getObjectVolatile", "(Ljava.lang.Object;J)Ljava.lang.Object;"), Unsafe_getObjectVolatile);
intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "getObject", "(Ljava.lang.Object;J)Ljava.lang.Object;"), Unsafe_getObjectVolatile);
intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "compareAndSwapObject", "(Ljava.lang.Object;JLjava.lang.Object;Ljava.lang.Object;)Z"), Unsafe_compareAndSwapObject);
+ intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "getAndSetObject", "(Ljava.lang.Object;JLjava.lang.Object;)Ljava.lang.Object;"), Unsafe_getAndSetObject);
return intrinsics;
}
@@ -536,7 +537,16 @@ namespace IKVM.Internal
mw.EmitCallvirt(eic.Emitter);
return true;
}
- else if (!DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature))
+ else if (DynamicTypeWrapper.RequiresDynamicReflectionCallerClass(eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature))
+ {
+ // since the non-intrinsic version of Reflection.getCallerClass() always throws an exception, we have to redirect to the dynamic version
+ MethodWrapper getCallerClass = ClassLoaderWrapper.LoadClassCritical("sun.reflect.Reflection").GetMethodWrapper("getCallerClass", "(I)Ljava.lang.Class;", false);
+ getCallerClass.Link();
+ eic.Emitter.EmitLdc_I4(2);
+ getCallerClass.EmitCall(eic.Emitter);
+ return true;
+ }
+ else
{
StaticCompiler.IssueMessage(Message.ReflectionCallerClassRequiresCallerID, eic.ClassFile.Name, eic.Caller.Name, eic.Caller.Signature);
}
@@ -857,6 +867,49 @@ namespace IKVM.Internal
return false;
}
+ private static bool Unsafe_getAndSetObject(EmitIntrinsicContext eic)
+ {
+ TypeWrapper tw = eic.GetStackTypeWrapper(0, 2);
+ if (IsSupportedArrayTypeForUnsafeOperation(tw)
+ && eic.GetStackTypeWrapper(0, 0).IsAssignableTo(tw.ElementTypeWrapper))
+ {
+ Type type = tw.TypeAsLocalOrStackType.GetElementType();
+ CodeEmitterLocal newValue = eic.Emitter.AllocTempLocal(type);
+ CodeEmitterLocal index = eic.Emitter.AllocTempLocal(Types.Int32);
+ CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(tw.TypeAsLocalOrStackType);
+ eic.Emitter.Emit(OpCodes.Stloc, newValue);
+ eic.Emitter.Emit(OpCodes.Conv_Ovf_I4);
+ eic.Emitter.Emit(OpCodes.Stloc, index);
+ eic.Emitter.Emit(OpCodes.Stloc, obj);
+ EmitConsumeUnsafe(eic);
+ eic.Emitter.Emit(OpCodes.Ldloc, obj);
+ eic.Emitter.Emit(OpCodes.Ldloc, index);
+ eic.Emitter.Emit(OpCodes.Ldelema, type);
+ eic.Emitter.Emit(OpCodes.Ldloc, newValue);
+ eic.Emitter.Emit(OpCodes.Call, MakeExchange(type));
+ eic.Emitter.ReleaseTempLocal(obj);
+ eic.Emitter.ReleaseTempLocal(index);
+ eic.Emitter.ReleaseTempLocal(newValue);
+ eic.NonLeaf = false;
+ return true;
+ }
+ return false;
+ }
+
+ internal static MethodInfo MakeExchange(Type type)
+ {
+ MethodInfo interlockedExchange = null;
+ foreach (MethodInfo m in JVM.Import(typeof(System.Threading.Interlocked)).GetMethods())
+ {
+ if (m.Name == "Exchange" && m.IsGenericMethodDefinition)
+ {
+ interlockedExchange = m;
+ break;
+ }
+ }
+ return interlockedExchange.MakeGenericMethod(type);
+ }
+
private static void EmitConsumeUnsafe(EmitIntrinsicContext eic)
{
#if STATIC_COMPILER