private static void EmitTypeHandleCheck(ILGenerator g, GenericShape genericShape, GenericTypeParameterBuilder[] typeParamArr, string scenario) { if (genericShape == GenericShape.NotGeneric) { return; } g.Emit(OpCodes.Ldtoken, typeParamArr[0]); g.Emit(OpCodes.Ldstr, scenario); if (genericShape == GenericShape.GenericOverReferenceType) { g.Emit(OpCodes.Call, s_isTypeHandleObject); } if (genericShape == GenericShape.GenericOverValueType) { g.Emit(OpCodes.Call, s_isTypeHandleInt); } }
public void Can_Dispatch_To_Closed_Generic_Types() { IShape generic = new GenericShape<int>(); Assert.AreEqual("GenericShape<Int32> x GenericShape<Int32>", generic.Intersect(generic)); }
private static bool DoStubCall(int callerIndex, bool staticMethod, bool onValueType, GenericShape typeGenericShape, GenericShape methodGenericShape) { string callerNameSeed = Config.InstantiatingStubPrefix + "Caller" + callerIndex; // Use a consistent seed value here so that the various various of unboxing/instantiating stubs are generated with the same arg shape string callerName = callerNameSeed + (staticMethod ? "Static" : "Instance") + (onValueType ? "Class" : "ValueType") + typeGenericShape.ToString() + methodGenericShape.ToString(); Random rand = new Random(GetSeed(callerNameSeed)); List <TypeEx> pms; do { pms = RandomParameters(s_allTypes, rand); } while (pms.Count > 16); Type delegateType = GetDelegateType(pms, typeof(int)); Callee callee = new Callee(callerName + "Callee", pms);// CreateCallee(Config.PInvokeePrefix + calleeIndex, s_allTypes); callee.Emit(); Delegate calleeDelegate = callee.Method.CreateDelegate(delegateType); int newStubCount = Interlocked.Increment(ref s_stubTypesCreated); if ((s_stubTypesModule == null) || (newStubCount % 1000) == 0) { AssemblyBuilder stubsAssembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("ABIStress_Stubs" + newStubCount), AssemblyBuilderAccess.RunAndCollect); s_stubTypesModule = stubsAssembly.DefineDynamicModule("ABIStress_Stubs" + newStubCount); } // This code is based on DelegateHelpers.cs in System.Linq.Expressions.Compiler TypeBuilder tb = s_stubTypesModule.DefineType( $"{callerName}_GenericTarget", TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.AutoClass, onValueType ? typeof(object) : typeof(ValueType)); GenericTypeParameterBuilder[] typeParamsType = null; if (typeGenericShape != GenericShape.NotGeneric) { typeParamsType = tb.DefineGenericParameters(new string[] { "T" }); } FieldInfo fieldDeclaration = tb.DefineField("MagicValue", typeof(int), FieldAttributes.Public); Type typeofInstantiatedType; FieldInfo fieldInfoMagicValueField; if (typeGenericShape == GenericShape.NotGeneric) { typeofInstantiatedType = tb; fieldInfoMagicValueField = fieldDeclaration; } else { typeofInstantiatedType = tb.MakeGenericType(typeParamsType[0]); fieldInfoMagicValueField = TypeBuilder.GetField(typeofInstantiatedType, fieldDeclaration); } ConstructorBuilder cb = tb.DefineConstructor( MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName, CallingConventions.Standard, new Type[] { typeof(int) }); cb.SetImplementationFlags(MethodImplAttributes.Managed); ILGenerator g = cb.GetILGenerator(); g.Emit(OpCodes.Ldarg, 0); g.Emit(OpCodes.Call, typeof(object).GetConstructor(Array.Empty <Type>())); g.Emit(OpCodes.Ldarg, 0); g.Emit(OpCodes.Ldarg_1); g.Emit(OpCodes.Stfld, fieldInfoMagicValueField); g.Emit(OpCodes.Ret); MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig; if (staticMethod) { methodAttributes |= MethodAttributes.Static; } MethodBuilder mbInstance = tb.DefineMethod( "Method", methodAttributes, callee.Method.ReturnType, callee.Parameters.Select(t => t.Type).ToArray()); GenericTypeParameterBuilder[] typeParamsMethod = null; if (methodGenericShape != GenericShape.NotGeneric) { typeParamsMethod = mbInstance.DefineGenericParameters(new string[] { "T" }); } mbInstance.SetImplementationFlags(MethodImplAttributes.Managed); int magicNumberEmbeddedInObject = rand.Next(); GCHandle gchCallee = GCHandle.Alloc(callee.Method.CreateDelegate(delegateType)); IntPtr gchCalleeIntPtr = GCHandle.ToIntPtr(gchCallee); g = mbInstance.GetILGenerator(); if (!staticMethod) { // Verify random number made it intact, and this parameter was handled correctly g.Emit(OpCodes.Ldarg_0); g.Emit(OpCodes.Ldfld, fieldInfoMagicValueField); g.Emit(OpCodes.Ldc_I4, magicNumberEmbeddedInObject); g.Emit(OpCodes.Call, s_compareNumbers); } // Verify generic args are as expected EmitTypeHandleCheck(g, typeGenericShape, typeParamsType, "type"); EmitTypeHandleCheck(g, methodGenericShape, typeParamsMethod, "method"); // Make the call to callee LocalBuilder gcHandleLocal = g.DeclareLocal(typeof(GCHandle)); // Load GCHandle of callee delegate g.Emit(OpCodes.Ldc_I8, (long)gchCalleeIntPtr); g.Emit(OpCodes.Conv_I); g.Emit(OpCodes.Call, s_gcHandleFromIntPtr); g.Emit(OpCodes.Stloc, gcHandleLocal); // Resolve to target g.Emit(OpCodes.Ldloca, gcHandleLocal); g.Emit(OpCodes.Call, s_gcHandle_getTarget); // Cast to delegate type g.Emit(OpCodes.Castclass, delegateType); // Load all args int argOffset = 1; if (staticMethod) { argOffset = 0; } for (int i = 0; i < pms.Count; i++) { g.Emit(OpCodes.Ldarg, argOffset + i); } // Call delegate invoke method g.Emit(OpCodes.Callvirt, delegateType.GetMethod("Invoke")); // ret g.Emit(OpCodes.Ret); Type calleeTypeOpen = tb.CreateType(); Type calleeType; switch (typeGenericShape) { case GenericShape.NotGeneric: calleeType = calleeTypeOpen; break; case GenericShape.GenericOverReferenceType: calleeType = calleeTypeOpen.MakeGenericType(typeof(object)); break; case GenericShape.GenericOverValueType: calleeType = calleeTypeOpen.MakeGenericType(typeof(int)); break; default: throw new Exception("Unknown case"); } MethodInfo targetMethodOpen = calleeType.GetMethod("Method"); MethodInfo targetMethod; switch (methodGenericShape) { case GenericShape.NotGeneric: targetMethod = targetMethodOpen; break; case GenericShape.GenericOverReferenceType: targetMethod = targetMethodOpen.MakeGenericMethod(typeof(object)); break; case GenericShape.GenericOverValueType: targetMethod = targetMethodOpen.MakeGenericMethod(typeof(int)); break; default: throw new Exception("Unknown case"); } Delegate targetMethodToCallDel; if (staticMethod) { targetMethodToCallDel = targetMethod.CreateDelegate(delegateType); } else { targetMethodToCallDel = targetMethod.CreateDelegate(delegateType, Activator.CreateInstance(calleeType, magicNumberEmbeddedInObject)); } GCHandle gchTargetMethod = GCHandle.Alloc(targetMethodToCallDel); // CALLER Dynamic method DynamicMethod caller = new DynamicMethod( callerName, typeof(int), pms.Select(t => t.Type).ToArray(), typeof(Program).Module); g = caller.GetILGenerator(); // Create the args to pass to the callee from the caller. List <Value> args = GenCallerToCalleeArgs(pms, callee.Parameters, rand); if (Config.Verbose) { EmitDumpValues("Caller's incoming args", g, pms.Select((p, i) => new ArgValue(p, i))); } if (Config.Verbose) { EmitDumpValues($"Caller's args to {callerName} call", g, args); } gcHandleLocal = g.DeclareLocal(typeof(GCHandle)); g.Emit(OpCodes.Ldc_I8, (long)GCHandle.ToIntPtr(gchTargetMethod)); g.Emit(OpCodes.Conv_I); g.Emit(OpCodes.Call, s_gcHandleFromIntPtr); g.Emit(OpCodes.Stloc, gcHandleLocal); // Resolve to target g.Emit(OpCodes.Ldloca, gcHandleLocal); g.Emit(OpCodes.Call, s_gcHandle_getTarget); // Cast to delegate type g.Emit(OpCodes.Castclass, delegateType); foreach (Value v in args) { v.Emit(g); } // Call delegate invoke method g.Emit(OpCodes.Callvirt, delegateType.GetMethod("Invoke")); // ret g.Emit(OpCodes.Ret); (object callerResult, object calleeResult) = InvokeCallerCallee(caller, pms, callee.Method, args, rand); gchCallee.Free(); gchTargetMethod.Free(); if (callerResult.Equals(calleeResult)) { return(true); } Console.WriteLine("Mismatch in stub call: expected {0}, got {1}", calleeResult, callerResult); Console.WriteLine(callerName); WriteSignature(caller); WriteSignature(callee.Method); return(false); }
/// <summary> /// The main class method. /// </summary> /// <param name="args"> /// The args. /// </param> private static void Main(string[] args) { var square = new GenericShape <SingletonSquare>(SingletonSquare.Squareingleton); var rectangle = new GenericShape <SingletonRectangle>(SingletonRectangle.RectangleSingleton); var singletonTestRunner = new SingletonTests(); Console.WriteLine("------------------------------------------------------------------"); Console.WriteLine("Base Singleton"); singletonTestRunner.SingletonPerformanceTest(Singleton.Instance); Console.WriteLine("------------------------------------------------------------------"); Console.WriteLine("Singleton with lock"); singletonTestRunner.SingletonPerformanceTest(SingletonWithLock.Instance); Console.WriteLine("------------------------------------------------------------------"); var serializeTestCaseWithLock = false; Console.WriteLine("Singleton without lock - serialize test"); singletonTestRunner.SerializableTest(serializeTestCaseWithLock); Console.WriteLine("------------------------------------------------------------------"); serializeTestCaseWithLock = true; Console.WriteLine("Singleton ***WITH*** lock - serialize test"); singletonTestRunner.SerializableTest(serializeTestCaseWithLock); Console.WriteLine("------------------------------------------------------------------"); Console.WriteLine("Singleton inheritance test"); var singletonParent = Singleton.Instance; Singleton squareSingleton = SingletonSquare.Squareingleton; Singleton rectangleSingleton = SingletonRectangle.RectangleSingleton; Console.WriteLine("------------------------------------------------------------------"); Console.WriteLine("Call GetName Function from main class:"); Console.WriteLine($"name: {singletonParent.GetName()},\n type: {singletonParent.GetType()}\n"); Console.WriteLine("------------------------------------------------------------------"); Console.WriteLine("Call GetName Function from derived class square:"); Console.WriteLine($"name: {squareSingleton.GetName()},\n type: {squareSingleton.GetType()} \n"); Console.WriteLine("Call GetName Function from derived class rectangle:"); Console.WriteLine($"name: {rectangleSingleton.GetName()},\ntype: {rectangleSingleton.GetType()} \n"); Console.WriteLine("------------------------------------------------------------------"); Console.WriteLine("Call GetName Function from derived class'GenericShape'\nwhich inherit from main class.\nIt has generic functionality derived from class that inherit from Singleton. 'CurrentType.GetName()'\n"); Console.WriteLine("******************************************************************"); Console.WriteLine($"name : {square.GetName()},\n type: {square.GetType()}\n"); Console.WriteLine($"name : {rectangle.GetName()},\n type: {rectangle.GetType()}\n"); Console.WriteLine("------------------------------------------------------------------"); Console.WriteLine("\n\nTask Test run"); var t1 = new SingletonThreadTest("1."); var t2 = new SingletonThreadTest("2."); var t3 = new SingletonThreadTest("3."); var t4 = new SingletonThreadTest("4."); var t5 = new SingletonThreadTest("5."); var t6 = new SingletonThreadTest("6."); var t7 = new SingletonThreadTest("7."); var t8 = new SingletonThreadTest("8."); var t9 = new SingletonThreadTest("9."); t1.Run(); t2.Run(); t3.Run(); t4.Run(); t5.Run(); t6.Run(); t7.Run(); t8.Run(); t9.Run(); Console.WriteLine("------------------------------------------------------------------"); t1.RunWithoutTaskWait(); t2.RunWithoutTaskWait(); t3.RunWithoutTaskWait(); t4.RunWithoutTaskWait(); t5.RunWithoutTaskWait(); t6.RunWithoutTaskWait(); t7.RunWithoutTaskWait(); t8.RunWithoutTaskWait(); t9.RunWithoutTaskWait(); Thread.Sleep(10); Console.BackgroundColor = ConsoleColor.Black; Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine("OK!\npozdrowienia."); }