[Ikvm-commit] ikvm/runtime intrinsics.cs,1.46,1.47
Brought to you by:
jfrijters
|
From: Jeroen F. <jfr...@us...> - 2014-11-18 11:34:07
|
Update of /cvsroot/ikvm/ikvm/runtime In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv22913 Modified Files: intrinsics.cs Log Message: More Unsafe intrinsics. Index: intrinsics.cs =================================================================== RCS file: /cvsroot/ikvm/ikvm/runtime/intrinsics.cs,v retrieving revision 1.46 retrieving revision 1.47 diff -C2 -d -r1.46 -r1.47 *** intrinsics.cs 14 Nov 2014 15:28:34 -0000 1.46 --- intrinsics.cs 18 Nov 2014 11:34:04 -0000 1.47 *************** *** 204,207 **** --- 204,208 ---- intrinsics.Add(new IntrinsicKey("java.lang.ThreadLocal", "<init>", "()V"), ThreadLocal_new); intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "ensureClassInitialized", "(Ljava.lang.Class;)V"), Unsafe_ensureClassInitialized); + // note that the following intrinsics don't pay off on CLR v2, but they do on CLR v4 intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "putObject", "(Ljava.lang.Object;JLjava.lang.Object;)V"), Unsafe_putObject); intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "putOrderedObject", "(Ljava.lang.Object;JLjava.lang.Object;)V"), Unsafe_putOrderedObject); *************** *** 211,214 **** --- 212,218 ---- 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); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "compareAndSwapInt", "(Ljava.lang.Object;JII)Z"), Unsafe_compareAndSwapInt); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "getAndAddInt", "(Ljava.lang.Object;JI)I"), Unsafe_getAndAddInt); + intrinsics.Add(new IntrinsicKey("sun.misc.Unsafe", "compareAndSwapLong", "(Ljava.lang.Object;JJJ)Z"), Unsafe_compareAndSwapLong); return intrinsics; } *************** *** 865,869 **** } } ! return false; } --- 869,925 ---- } } ! // stack layout at call site: ! // 4 Unsafe (receiver) ! // 3 Object (obj) ! // 2 long (offset) ! // 1 Object (expect) ! // 0 Object (update) ! TypeWrapper twUnsafe = eic.GetStackTypeWrapper(0, 4); ! if (twUnsafe == VerifierTypeWrapper.Null) ! { ! return false; ! } ! for (int i = 0; ; i--) ! { ! if ((eic.Flags[eic.OpcodeIndex + i] & InstructionFlags.BranchTarget) != 0) ! { ! return false; ! } ! if (eic.GetStackTypeWrapper(i, 0) == twUnsafe) ! { ! // the pattern we recognize is: ! // aload ! // getstatic <offset field> ! if (eic.Match(i, NormalizedByteCode.__aload) && eic.GetStackTypeWrapper(i + 1, 0) == eic.Caller.DeclaringType ! && eic.Match(i + 1, NormalizedByteCode.__getstatic)) ! { ! FieldWrapper fw = GetUnsafeField(eic, eic.GetFieldref(i + 1)); ! if (fw != null && !fw.IsStatic && fw.DeclaringType == eic.Caller.DeclaringType) ! { ! Type type = fw.FieldTypeWrapper.TypeAsLocalOrStackType; ! CodeEmitterLocal update = eic.Emitter.AllocTempLocal(type); ! CodeEmitterLocal expect = eic.Emitter.AllocTempLocal(type); ! CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(eic.Caller.DeclaringType.TypeAsLocalOrStackType); ! eic.Emitter.Emit(OpCodes.Stloc, update); ! eic.Emitter.Emit(OpCodes.Stloc, expect); ! eic.Emitter.Emit(OpCodes.Pop); // discard offset ! eic.Emitter.Emit(OpCodes.Stloc, obj); ! EmitConsumeUnsafe(eic); ! eic.Emitter.Emit(OpCodes.Ldloc, obj); ! eic.Emitter.Emit(OpCodes.Ldflda, fw.GetField()); ! eic.Emitter.Emit(OpCodes.Ldloc, update); ! eic.Emitter.Emit(OpCodes.Ldloc, expect); ! eic.Emitter.Emit(OpCodes.Call, AtomicReferenceFieldUpdaterEmitter.MakeCompareExchange(type)); ! eic.Emitter.Emit(OpCodes.Ldloc, expect); ! eic.Emitter.Emit(OpCodes.Ceq); ! eic.Emitter.ReleaseTempLocal(expect); ! eic.Emitter.ReleaseTempLocal(update); ! eic.NonLeaf = false; ! return true; ! } ! } ! return false; ! } ! } } *************** *** 897,912 **** } ! 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); } --- 953,1121 ---- } ! private static bool Unsafe_compareAndSwapInt(EmitIntrinsicContext eic) { ! // stack layout at call site: ! // 4 Unsafe (receiver) ! // 3 Object (obj) ! // 2 long (offset) ! // 1 int (expect) ! // 0 int (update) ! TypeWrapper twUnsafe = eic.GetStackTypeWrapper(0, 4); ! if (twUnsafe == VerifierTypeWrapper.Null) { ! return false; ! } ! for (int i = 0; ; i--) ! { ! if ((eic.Flags[eic.OpcodeIndex + i] & InstructionFlags.BranchTarget) != 0) { ! return false; ! } ! if (eic.GetStackTypeWrapper(i, 0) == twUnsafe) ! { ! // the pattern we recognize is: ! // aload ! // getstatic <offset field> ! if (eic.Match(i, NormalizedByteCode.__aload) && eic.GetStackTypeWrapper(i + 1, 0) == eic.Caller.DeclaringType ! && eic.Match(i + 1, NormalizedByteCode.__getstatic)) ! { ! FieldWrapper fw = GetUnsafeField(eic, eic.GetFieldref(i + 1)); ! if (fw != null && !fw.IsStatic && fw.DeclaringType == eic.Caller.DeclaringType) ! { ! CodeEmitterLocal update = eic.Emitter.AllocTempLocal(Types.Int32); ! CodeEmitterLocal expect = eic.Emitter.AllocTempLocal(Types.Int32); ! CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(eic.Caller.DeclaringType.TypeAsLocalOrStackType); ! eic.Emitter.Emit(OpCodes.Stloc, update); ! eic.Emitter.Emit(OpCodes.Stloc, expect); ! eic.Emitter.Emit(OpCodes.Pop); // discard offset ! eic.Emitter.Emit(OpCodes.Stloc, obj); ! EmitConsumeUnsafe(eic); ! eic.Emitter.Emit(OpCodes.Ldloc, obj); ! eic.Emitter.Emit(OpCodes.Ldflda, fw.GetField()); ! eic.Emitter.Emit(OpCodes.Ldloc, update); ! eic.Emitter.Emit(OpCodes.Ldloc, expect); ! eic.Emitter.Emit(OpCodes.Call, InterlockedMethods.CompareExchangeInt32); ! eic.Emitter.Emit(OpCodes.Ldloc, expect); ! eic.Emitter.Emit(OpCodes.Ceq); ! eic.Emitter.ReleaseTempLocal(expect); ! eic.Emitter.ReleaseTempLocal(update); ! eic.NonLeaf = false; ! return true; ! } ! } ! return false; ! } ! } ! } ! ! private static bool Unsafe_getAndAddInt(EmitIntrinsicContext eic) ! { ! // stack layout at call site: ! // 3 Unsafe (receiver) ! // 2 Object (obj) ! // 1 long (offset) ! // 0 int (delta) ! TypeWrapper twUnsafe = eic.GetStackTypeWrapper(0, 3); ! if (twUnsafe == VerifierTypeWrapper.Null) ! { ! return false; ! } ! for (int i = 0; ; i--) ! { ! if ((eic.Flags[eic.OpcodeIndex + i] & InstructionFlags.BranchTarget) != 0) ! { ! return false; ! } ! if (eic.GetStackTypeWrapper(i, 0) == twUnsafe) ! { ! // the pattern we recognize is: ! // aload_0 ! // getstatic <offset field> ! if (eic.Match(i, NormalizedByteCode.__aload, 0) ! && eic.Match(i + 1, NormalizedByteCode.__getstatic)) ! { ! FieldWrapper fw = GetUnsafeField(eic, eic.GetFieldref(i + 1)); ! if (fw != null && !fw.IsStatic && fw.DeclaringType == eic.Caller.DeclaringType) ! { ! CodeEmitterLocal delta = eic.Emitter.AllocTempLocal(Types.Int32); ! eic.Emitter.Emit(OpCodes.Stloc, delta); ! eic.Emitter.Emit(OpCodes.Pop); // discard offset ! eic.Emitter.Emit(OpCodes.Pop); // discard obj ! EmitConsumeUnsafe(eic); ! eic.Emitter.Emit(OpCodes.Ldarg_0); ! eic.Emitter.Emit(OpCodes.Ldflda, fw.GetField()); ! eic.Emitter.Emit(OpCodes.Ldloc, delta); ! eic.Emitter.Emit(OpCodes.Call, InterlockedMethods.AddInt32); ! eic.Emitter.Emit(OpCodes.Ldloc, delta); ! eic.Emitter.Emit(OpCodes.Sub); ! eic.Emitter.ReleaseTempLocal(delta); ! eic.NonLeaf = false; ! return true; ! } ! } ! return false; } } ! } ! ! private static bool Unsafe_compareAndSwapLong(EmitIntrinsicContext eic) ! { ! // stack layout at call site: ! // 4 Unsafe (receiver) ! // 3 Object (obj) ! // 2 long (offset) ! // 1 long (expect) ! // 0 long (update) ! TypeWrapper twUnsafe = eic.GetStackTypeWrapper(0, 4); ! if (twUnsafe == VerifierTypeWrapper.Null) ! { ! return false; ! } ! for (int i = 0; ; i--) ! { ! if ((eic.Flags[eic.OpcodeIndex + i] & InstructionFlags.BranchTarget) != 0) ! { ! return false; ! } ! if (eic.GetStackTypeWrapper(i, 0) == twUnsafe) ! { ! // the pattern we recognize is: ! // aload ! // getstatic <offset field> ! if (eic.Match(i, NormalizedByteCode.__aload) && eic.GetStackTypeWrapper(i + 1, 0) == eic.Caller.DeclaringType ! && eic.Match(i + 1, NormalizedByteCode.__getstatic)) ! { ! FieldWrapper fw = GetUnsafeField(eic, eic.GetFieldref(i + 1)); ! if (fw != null && !fw.IsStatic && fw.DeclaringType == eic.Caller.DeclaringType) ! { ! CodeEmitterLocal update = eic.Emitter.AllocTempLocal(Types.Int64); ! CodeEmitterLocal expect = eic.Emitter.AllocTempLocal(Types.Int64); ! CodeEmitterLocal obj = eic.Emitter.AllocTempLocal(eic.Caller.DeclaringType.TypeAsLocalOrStackType); ! eic.Emitter.Emit(OpCodes.Stloc, update); ! eic.Emitter.Emit(OpCodes.Stloc, expect); ! eic.Emitter.Emit(OpCodes.Pop); // discard offset ! eic.Emitter.Emit(OpCodes.Stloc, obj); ! EmitConsumeUnsafe(eic); ! eic.Emitter.Emit(OpCodes.Ldloc, obj); ! eic.Emitter.Emit(OpCodes.Ldflda, fw.GetField()); ! eic.Emitter.Emit(OpCodes.Ldloc, update); ! eic.Emitter.Emit(OpCodes.Ldloc, expect); ! eic.Emitter.Emit(OpCodes.Call, InterlockedMethods.CompareExchangeInt64); ! eic.Emitter.Emit(OpCodes.Ldloc, expect); ! eic.Emitter.Emit(OpCodes.Ceq); ! eic.Emitter.ReleaseTempLocal(expect); ! eic.Emitter.ReleaseTempLocal(update); ! eic.NonLeaf = false; ! return true; ! } ! } ! return false; ! } ! } ! } ! ! internal static MethodInfo MakeExchange(Type type) ! { ! return InterlockedMethods.ExchangeOfT.MakeGenericMethod(type); } *************** *** 958,962 **** * ... * getstatic <Field test sun/misc/Unsafe UNSAFE> ! * aload_0 * ldc "next" * invokevirtual <Method java/lang/Class getDeclaredField(Ljava/lang/String;)Ljava/lang/reflect/Field;> --- 1167,1171 ---- * ... * getstatic <Field test sun/misc/Unsafe UNSAFE> ! * aload_0 | ldc <Class> * ldc "next" * invokevirtual <Method java/lang/Class getDeclaredField(Ljava/lang/String;)Ljava/lang/reflect/Field;> *************** *** 972,978 **** && MatchInvokeVirtual(eic, ref method.Instructions[i - 2], "java.lang.Class", "getDeclaredField", "(Ljava.lang.String;)Ljava.lang.reflect.Field;") && MatchLdc(eic, ref method.Instructions[i - 3], ClassFile.ConstantType.String) ! && method.Instructions[i - 4].NormalizedOpCode == NormalizedByteCode.__aload && method.Instructions[i - 5].NormalizedOpCode == NormalizedByteCode.__getstatic && eic.ClassFile.GetFieldref(method.Instructions[i - 5].Arg1).Signature == "Lsun.misc.Unsafe;") { // search backward for the astore that corresponds to the aload (of the class object) for (int j = i - 6; j > 0; j--) --- 1181,1212 ---- && MatchInvokeVirtual(eic, ref method.Instructions[i - 2], "java.lang.Class", "getDeclaredField", "(Ljava.lang.String;)Ljava.lang.reflect.Field;") && MatchLdc(eic, ref method.Instructions[i - 3], ClassFile.ConstantType.String) ! && (method.Instructions[i - 4].NormalizedOpCode == NormalizedByteCode.__aload || method.Instructions[i - 4].NormalizedOpCode == NormalizedByteCode.__ldc) && method.Instructions[i - 5].NormalizedOpCode == NormalizedByteCode.__getstatic && eic.ClassFile.GetFieldref(method.Instructions[i - 5].Arg1).Signature == "Lsun.misc.Unsafe;") { + if (method.Instructions[i - 4].NormalizedOpCode == NormalizedByteCode.__ldc) + { + if (eic.ClassFile.GetConstantPoolClassType(method.Instructions[i - 4].Arg1) == eic.Caller.DeclaringType) + { + string fieldName = eic.ClassFile.GetConstantPoolConstantString(method.Instructions[i - 3].Arg1); + FieldWrapper fw = null; + foreach (FieldWrapper fw1 in eic.Caller.DeclaringType.GetFields()) + { + if (fw1.Name == fieldName) + { + if (fw == null) + { + fw = fw1; + } + else + { + // duplicate name + return null; + } + } + } + return fw; + } + return null; + } // search backward for the astore that corresponds to the aload (of the class object) for (int j = i - 6; j > 0; j--) |