/// <summary> /// Reduces the provided DynamicExpression into site.Target(site, *args). /// </summary> public Expression ReduceDyn(DynamicExpression node, out SiteInfo siteInfo) { MaybeInit(); if (RewriteDelegate(node.DelegateType, out Type delegateType)) { node = Expression.MakeDynamic(delegateType, node.Binder, node.Arguments); } CallSite cs = CallSite.Create(node.DelegateType, node.Binder); // TODO: fix this eventually to return the SiteInfo and not the Expression Expression access = RewriteCallSite(cs, _typeGen, delegateType ?? node.DelegateType, out siteInfo); // ($site = siteExpr).Target.Invoke($site, *args) ParameterExpression site = Expression.Variable(cs.GetType(), "$site"); return(Expression.Block( new[] { site }, Expression.Call( Expression.Field( Expression.Assign(site, access), cs.GetType().GetField("Target") ), node.DelegateType.GetMethod("Invoke"), ClrExtensions.ArrayInsert(site, node.Arguments) ) )); }
private Expression RewriteCallSite(CallSite site) { IExpressionSerializable serializer = site.Binder as IExpressionSerializable; if (serializer == null) { throw Error.GenNonSerializableBinder(); } // add the initialization code that we'll generate later into the outermost // lambda and then return an index into the array we'll be creating. if (_constantPool == null) { _constantPool = Expression.Variable(typeof(object[]), "$constantPool"); _constants = new List <Expression>(); } Type siteType = site.GetType(); _constants.Add(Expression.Call(siteType.GetMethod("Create"), serializer.CreateExpression())); // rewrite the node... return(Visit( AstUtils.Convert( Expression.ArrayAccess(_constantPool, Expression.Constant(_constants.Count - 1)), siteType ) )); }
private Expression RewriteCallSite(CallSite site, TypeGen tg) { IExpressionSerializable serializer = site.Binder as IExpressionSerializable; if (serializer == null) { throw new ArgumentException("Generating code from non-serializable CallSiteBinder."); } Type siteType = site.GetType(); FieldBuilder fb = tg.AddStaticField(siteType, "sf" + (_id++).ToString()); Expression init = Expression.Call(siteType.GetMethod("Create"), serializer.CreateExpression()); _fieldBuilders.Add(fb); _fieldInits.Add(init); //Type t = init.Type; //if (t.IsGenericType) //{ // Type[] args = t.GetGenericArguments()[0].GetGenericArguments(); ; // // skip the first one, it is the site. // for (int k = 1; k < args.Length; k++) // { // Type p = args[k]; // //if (!p.Assembly.GetName().Name.Equals("mscorlib") && !p.Assembly.GetName().Name.Equals("Clojure")) // // Console.WriteLine("Found {0}", p.ToString()); // } //} // rewrite the node... return(Expression.Field(null, fb)); }
public DynamicInstructionN(Type delegateType, CallSite site) { MethodInfo method = delegateType.GetMethod("Invoke"); ParameterInfo[] parameters = method.GetParameters(); this._target = CallInstruction.Create(method, parameters); this._site = site; this._argumentCount = parameters.Length - 1; this._targetDelegate = site.GetType().GetField("Target").GetValue(site); }
public DynamicInstructionN(Type delegateType, CallSite site) { var methodInfo = delegateType.GetMethod("Invoke"); var parameters = methodInfo.GetParameters(); _target = CallInstruction.Create(methodInfo, parameters); _site = site; _argumentCount = parameters.Length - 1; _targetDelegate = site.GetType().GetField("Target").GetValue(site); }
public DynamicInstructionN(Type delegateType, CallSite site) { var methodInfo = delegateType.GetMethod("Invoke"); var parameters = methodInfo.GetParameters(); // <Delegate>.Invoke is ok to target by a delegate in partial trust (SecurityException is not thrown): _targetInvocationInstruction = CallInstruction.Create(methodInfo, parameters); _site = site; _argumentCount = parameters.Length - 1; _targetDelegate = site.GetType().GetInheritedFields("Target").First().GetValue(site); }
internal Delegate CreateDelegate(Type delegateType, object target) { Assert.NotNull(delegateType, target); // to enable: // function x() { } // someClass.someEvent += delegateType(x) // someClass.someEvent -= delegateType(x) // // we need to avoid re-creating the object array because they won't // be compare equal when removing the delegate if they're difference // instances. Therefore we use a weak hashtable to get back the // original object array. The values also need to be weak to avoid // creating a circular reference from the constants target back to the // target. This is fine because as long as the delegate is referenced // the object array will stay alive. Once the delegate is gone it's not // wired up anywhere and -= will never be used again. object[] clone; lock (_constantMap) { WeakReference cloneRef; if (!_constantMap.TryGetValue(target, out cloneRef) || (clone = (object[])cloneRef.Target) == null) { _constantMap[target] = new WeakReference(clone = (object[])_constants.Clone()); Type[] siteTypes = MakeSiteSignature(); CallSite callSite = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(siteTypes), _invokeBinder); Type siteType = callSite.GetType(); Type convertSiteType = null; CallSite convertSite = null; if (_returnType != typeof(void)) { convertSite = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(typeof(object), _returnType), _convertBinder); convertSiteType = convertSite.GetType(); } Debug.Assert(clone[0] == TargetPlaceHolder); Debug.Assert(clone[1] == CallSitePlaceHolder); Debug.Assert(clone[2] == ConvertSitePlaceHolder); clone[0] = target; clone[1] = callSite; clone[2] = convertSite; } } return(ReflectionUtils.CreateDelegate(_method, delegateType, clone)); }
private Expression RewriteCallSite(CallSite site, TypeGen tg, Type delegateType, out SiteInfo siteInfo) { if (!(site.Binder is IExpressionSerializable serializer)) { throw new ArgumentException("Generating code from non-serializable CallSiteBinder."); } Type siteType = site.GetType(); FieldBuilder fb = tg.AddStaticField(siteType, "sf" + (_id++).ToString()); siteInfo = new SiteInfo(fb, siteType, site.Binder, delegateType); _siteInfos.Add(siteInfo); // rewrite the node... return(Expression.Field(null, fb)); }
public object AccessValueElementTest(string elementName, object value, Type type) { XElement element = new XElement(elementName, value); dynamic dynamicElement = element.AsDynamic(); CallSiteBinder callsiteBinder = Binder.Convert(CSharpBinderFlags.None, type, typeof(DynamicXElementReader)); //-----------------------------------------------------------------------------------// // Creating Func<CallSite, object, Type> //-----------------------------------------------------------------------------------// // For type "int" this code is equivalent to: // Type constructedFuncType = typeof(Func<CallSite, object, int); Type openFuncType = typeof(Func <, ,>); Type constructedFuncType = openFuncType.MakeGenericType( typeof(CallSite), typeof(object), type); //-----------------------------------------------------------------------------------// // Creating CallSite<Func<CallSite, object, Type>> //-----------------------------------------------------------------------------------// // For type "int" this code is equivalent to: // Type constructedCallSiteType = typeof(CallSite<Func<CallSite, object, int>>); Type callSiteType = typeof(CallSite <>); Type constructedCallSiteType = callSiteType.MakeGenericType(constructedFuncType); //-----------------------------------------------------------------------------------// // var callSite = CallSite<Func<CallSite, object, int>>.Create(callSiteBinder); //-----------------------------------------------------------------------------------// var method = constructedCallSiteType.GetMethod("Create", BindingFlags.Static | BindingFlags.Public); CallSite callSite = (CallSite)method.Invoke(null, new object[] { callsiteBinder }); //-----------------------------------------------------------------------------------// // int actual = callSite.Target(callSite, dynamicElement); //-----------------------------------------------------------------------------------// FieldInfo targetFieldInfo = callSite.GetType().GetField("Target"); object target = targetFieldInfo.GetValue(callSite); // target is underlying delegate instance of type: Func<CallSite, object, int> var targetMethod = target.GetType().GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public); object actual = targetMethod.Invoke(target, new object[] { callSite, dynamicElement }); Console.WriteLine("Name: {0}, Value: {1}, Type: {2}", elementName, value, type); Console.WriteLine("Actual value: {0}", actual); return(actual); }
public static object CreateConvertCallSiteAndInvoke(ConvertBinder Action, object Instance) { object obj2; CallSite site = CallSite.Create(Expression.GetFuncType(new Type[] { typeof(CallSite), typeof(object), Action.Type }), GetCachedBinder(Action)); object[] args = new object[] { site, Instance }; Delegate delegate2 = (Delegate)site.GetType().GetField("Target").GetValue(site); try { obj2 = delegate2.DynamicInvoke(args); } catch (TargetInvocationException exception) { throw exception.InnerException; } return(obj2); }
private Expression RewriteCallSite(CallSite site, TypeGen tg) { IExpressionSerializable serializer = site.Binder as IExpressionSerializable; if (serializer == null) { throw new ArgumentException("Generating code from non-serializable CallSiteBinder."); } Type siteType = site.GetType(); FieldBuilder fb = tg.AddStaticField(siteType, "sf" + (_id++).ToString()); Expression init = Expression.Call(siteType.GetMethod("Create"), serializer.CreateExpression()); _fieldBuilders.Add(fb); _fieldInits.Add(init); // rewrite the node... return(Expression.Field(null, fb)); }
/// <summary> /// Uses LCG to create method such as this: /// /// object SplatCaller(CallSite{T} site, object[] args) { /// return site.Target(site, args[0], args[1], args[2], ...); /// } /// /// where the CallSite is bound to the delegate /// </summary> /// <param name="args">the number of arguments</param> /// <returns>a SplatCaller delegate.</returns> private SplatCaller MakeBigCaller(int args) { // Get the dynamic site type var siteDelegateTypeArgs = new Type[args + 2]; siteDelegateTypeArgs[0] = typeof(CallSite); for (int i = 1, n = siteDelegateTypeArgs.Length; i < n; i++) { siteDelegateTypeArgs[i] = typeof(object); } Type siteDelegateType = Expression.GetDelegateType(siteDelegateTypeArgs); // Create the callsite and get its type CallSite callSite = CallSite.Create(siteDelegateType, _binder); Type siteType = callSite.GetType(); var method = new DynamicMethod("_stub_SplatCaller", typeof(object), new Type[] { siteType, typeof(object[]) }, true); var gen = method.GetILGenerator(); // Emit the site's target gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldfld, siteType.GetField("Target")); // Emit the site gen.Emit(OpCodes.Ldarg_0); // Emit the arguments for (int i = 0; i < args; i++) { gen.Emit(OpCodes.Ldarg_1); gen.EmitInt(i); gen.Emit(OpCodes.Ldelem_Ref); } // Invoke the target gen.Emit(OpCodes.Callvirt, siteDelegateType.GetMethod("Invoke")); gen.Emit(OpCodes.Ret); // Create the delegate return(method.CreateDelegate <SplatCaller>(callSite)); }
private Expression RewriteCallSite(CallSite site) { IExpressionSerializable serializer = site.Binder as IExpressionSerializable; if (serializer == null) { throw Error.GenNonSerializableBinder(); } EnsureConstantPool(); Type siteType = site.GetType(); _constants.Add(Expression.Call(siteType.GetMethod("Create"), serializer.CreateExpression())); // rewrite the node... return(Visit( AstUtils.Convert( Expression.ArrayAccess(_constantPool, AstUtils.Constant(_constants.Count - 1)), siteType ) )); }
private void MakeReverseDelegateWorker(CodeContext context) { Type[] sigTypes; Type[] callSiteType; Type retType; GetSignatureInfo(out sigTypes, out callSiteType, out retType); DynamicMethod dm = new DynamicMethod("ReverseInteropInvoker", retType, ArrayUtils.RemoveLast(sigTypes), DynamicModule); ILGenerator ilGen = dm.GetILGenerator(); PythonContext pc = context.LanguageContext; Type callDelegateSiteType = CompilerHelpers.MakeCallSiteDelegateType(callSiteType); CallSite site = CallSite.Create(callDelegateSiteType, pc.Invoke(new CallSignature(_argtypes.Length))); List <object> constantPool = new List <object>(); constantPool.Add(null); // 1st item is the target object, will be put in later. constantPool.Add(site); ilGen.BeginExceptionBlock(); //CallSite<Func<CallSite, object, object>> mySite; //mySite.Target(mySite, target, ...); LocalBuilder siteLocal = ilGen.DeclareLocal(site.GetType()); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldc_I4, constantPool.Count - 1); ilGen.Emit(OpCodes.Ldelem_Ref); ilGen.Emit(OpCodes.Castclass, site.GetType()); ilGen.Emit(OpCodes.Stloc, siteLocal); ilGen.Emit(OpCodes.Ldloc, siteLocal); ilGen.Emit(OpCodes.Ldfld, site.GetType().GetField("Target")); ilGen.Emit(OpCodes.Ldloc, siteLocal); // load code context int contextIndex = constantPool.Count; Debug.Assert(pc.SharedContext != null); constantPool.Add(pc.SharedContext); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldc_I4, contextIndex); ilGen.Emit(OpCodes.Ldelem_Ref); // load function target, in constant pool slot 0 ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldc_I4_0); ilGen.Emit(OpCodes.Ldelem_Ref); // load arguments for (int i = 0; i < _argtypes.Length; i++) { INativeType nativeType = _argtypes[i]; nativeType.EmitReverseMarshalling(ilGen, new Arg(i + 1, sigTypes[i + 1]), constantPool, 0); } ilGen.Emit(OpCodes.Call, callDelegateSiteType.GetMethod("Invoke")); LocalBuilder finalRes = null; // emit forward marshaling for return value if (_restype != null) { LocalBuilder tmpRes = ilGen.DeclareLocal(typeof(object)); ilGen.Emit(OpCodes.Stloc, tmpRes); finalRes = ilGen.DeclareLocal(retType); ((INativeType)_restype).EmitMarshalling(ilGen, new Local(tmpRes), constantPool, 0); ilGen.Emit(OpCodes.Stloc, finalRes); } else { ilGen.Emit(OpCodes.Pop); } // } catch(Exception e) { // emit the cleanup code ilGen.BeginCatchBlock(typeof(Exception)); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldc_I4, contextIndex); ilGen.Emit(OpCodes.Ldelem_Ref); ilGen.Emit(OpCodes.Call, typeof(ModuleOps).GetMethod("CallbackException")); ilGen.EndExceptionBlock(); if (_restype != null) { ilGen.Emit(OpCodes.Ldloc, finalRes); } ilGen.Emit(OpCodes.Ret); _reverseDelegateConstants = constantPool; _reverseDelegateType = GetReverseDelegateType(ArrayUtils.RemoveFirst(sigTypes), CallingConvention); _reverseDelegate = dm; }
public static object CreateFuncCallSiteAndInvoke(CallSiteBinder Action, object Instance, object[] Arguments) { object obj2; Action = GetCachedBinder(Action); switch (Arguments.Length) { case 0: { CallSite <Func <CallSite, object, object> > site = CallSite <Func <CallSite, object, object> > .Create(Action); return(site.Target(site, Instance)); } case 1: { CallSite <Func <CallSite, object, object, object> > site2 = CallSite <Func <CallSite, object, object, object> > .Create(Action); return(site2.Target(site2, Instance, Arguments[0])); } case 2: { CallSite <Func <CallSite, object, object, object, object> > site3 = CallSite <Func <CallSite, object, object, object, object> > .Create(Action); return(site3.Target(site3, Instance, Arguments[0], Arguments[1])); } case 3: { CallSite <Func <CallSite, object, object, object, object, object> > site4 = CallSite <Func <CallSite, object, object, object, object, object> > .Create(Action); return(site4.Target(site4, Instance, Arguments[0], Arguments[1], Arguments[2])); } case 4: { CallSite <Func <CallSite, object, object, object, object, object, object> > site5 = CallSite <Func <CallSite, object, object, object, object, object, object> > .Create(Action); return(site5.Target(site5, Instance, Arguments[0], Arguments[1], Arguments[2], Arguments[3])); } case 5: { CallSite <Func <CallSite, object, object, object, object, object, object, object> > site6 = CallSite <Func <CallSite, object, object, object, object, object, object, object> > .Create(Action); return(site6.Target(site6, Instance, Arguments[0], Arguments[1], Arguments[2], Arguments[3], Arguments[4])); } case 6: { CallSite <Func <CallSite, object, object, object, object, object, object, object, object> > site7 = CallSite <Func <CallSite, object, object, object, object, object, object, object, object> > .Create(Action); return(site7.Target(site7, Instance, Arguments[0], Arguments[1], Arguments[2], Arguments[3], Arguments[4], Arguments[5])); } case 7: { CallSite <Func <CallSite, object, object, object, object, object, object, object, object, object> > site8 = CallSite <Func <CallSite, object, object, object, object, object, object, object, object, object> > .Create(Action); return(site8.Target(site8, Instance, Arguments[0], Arguments[1], Arguments[2], Arguments[3], Arguments[4], Arguments[5], Arguments[6])); } } Type[] typeArgs = new Type[(Arguments.Length + 2) + 1]; typeArgs[0] = typeof(CallSite); int num3 = typeArgs.Length - 1; for (int i = 1; i <= num3; i++) { typeArgs[i] = typeof(object); } CallSite site9 = CallSite.Create(Expression.GetDelegateType(typeArgs), Action); object[] array = new object[(Arguments.Length + 1) + 1]; array[0] = site9; array[1] = Instance; Arguments.CopyTo(array, 2); Delegate delegate2 = (Delegate)site9.GetType().GetField("Target").GetValue(site9); try { obj2 = delegate2.DynamicInvoke(array); } catch (TargetInvocationException exception) { throw exception.InnerException; } return(obj2); }
internal static Delegate CreateDelegateForDynamicObject(LanguageContext context, object dynamicObject, Type delegateType, MethodInfo invoke) { PerfTrack.NoteEvent(PerfTrack.Categories.DelegateCreate, delegateType.ToString()); Type returnType = invoke.ReturnType; ParameterInfo[] parameterInfos = invoke.GetParameters(); var parameters = new List <ParameterExpression>(); for (int i = 0; i < parameterInfos.Length; i++) { parameters.Add(Expression.Parameter(parameterInfos[i].ParameterType, "p" + i)); } InvokeBinder invokeBinder = context.CreateInvokeBinder(new CallInfo(parameterInfos.Length)); ConvertBinder convertBinder = (returnType != typeof(void)) ? context.CreateConvertBinder(returnType, explicitCast: true) : null; CallSite invokeSite = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(MakeSiteSignature(parameterInfos)), invokeBinder); Type invokeSiteType = invokeSite.GetType(); Type convertSiteType; CallSite convertSite; if (convertBinder != null) { convertSite = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(typeof(object), returnType), convertBinder); convertSiteType = convertSite.GetType(); } else { convertSiteType = null; convertSite = null; } var locals = new List <ParameterExpression>(); ParameterExpression invokeSiteVar = Expression.Parameter(invokeSiteType, "site"); ParameterExpression convertSiteVar = null; var args = new List <Expression>(); args.Add(invokeSiteVar); args.Add(Expression.Constant(dynamicObject)); int strongBoxVarsStart = locals.Count; for (int i = 0; i < parameterInfos.Length; i++) { if (parameterInfos[i].ParameterType.IsByRef) { var argType = parameterInfos[i].ParameterType; Type elementType = argType.GetElementType(); Type concreteType = typeof(StrongBox <>).MakeGenericType(elementType); var strongBox = Expression.Parameter(concreteType, "box" + i); locals.Add(strongBox); args.Add( Expression.Assign( strongBox, Expression.New( concreteType.GetConstructor(new Type[] { elementType }), parameters[i] ) ) ); } else { args.Add(parameters[i]); } } int strongBoxVarsEnd = locals.Count; Expression invocation = Expression.Invoke( Expression.Field( Expression.Assign( invokeSiteVar, Expression.Convert(Expression.Constant(invokeSite), invokeSiteType) ), invokeSiteType.GetDeclaredField("Target") ), args ); if (convertBinder != null) { convertSiteVar = Expression.Parameter(convertSiteType, "convertSite"); invocation = Expression.Invoke( Expression.Field( Expression.Assign( convertSiteVar, Expression.Convert(Expression.Constant(convertSite), convertSiteType) ), convertSiteType.GetDeclaredField("Target") ), convertSiteVar, invocation ); } locals.Add(invokeSiteVar); if (convertSiteVar != null) { locals.Add(convertSiteVar); } Expression body; // copy back from StrongBox.Value if (strongBoxVarsEnd > strongBoxVarsStart) { var block = new Expression[1 + strongBoxVarsEnd - strongBoxVarsStart + 1]; var resultVar = Expression.Parameter(invocation.Type, "result"); locals.Add(resultVar); int b = 0; int l = strongBoxVarsStart; // values of strong boxes are initialized in invocation expression: block[b++] = Expression.Assign(resultVar, invocation); for (int i = 0; i < parameterInfos.Length; i++) { if (parameterInfos[i].ParameterType.IsByRef) { var local = locals[l++]; block[b++] = Expression.Assign( parameters[i], Expression.Field(local, local.Type.GetDeclaredField("Value")) ); } } block[b++] = resultVar; Debug.Assert(l == strongBoxVarsEnd); Debug.Assert(b == block.Length); body = Expression.Block(locals, block); } else { body = Expression.Block(locals, invocation); } var lambda = Expression.Lambda(delegateType, body, "_Scripting_", parameters); return(lambda.Compile()); }
/// <summary> /// Generates stub to receive the CLR call and then call the dynamic language code. /// </summary> private void EmitClrCallStub(ILGen cg) { List <ReturnFixer> fixers = new List <ReturnFixer>(0); // Create strongly typed return type from the site. // This will, among other things, generate tighter code. Type[] siteTypes = MakeSiteSignature(_parameterTypes); CallSite callSite = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(siteTypes), _invokeBinder); Type siteType = callSite.GetType(); Type convertSiteType = null; CallSite convertSite = null; if (_returnType != typeof(void)) { convertSite = CallSite.Create(DynamicSiteHelpers.MakeCallSiteDelegate(typeof(object), _returnType), _convertBinder); convertSiteType = convertSite.GetType(); } LocalBuilder convertSiteLocal = null; FieldInfo convertTarget = null; if (_returnType != typeof(void)) { // load up the conversion logic on the stack convertSiteLocal = cg.DeclareLocal(convertSiteType); EmitConstantGet(cg, ConvertSiteIndex, convertSiteType); cg.Emit(OpCodes.Dup); cg.Emit(OpCodes.Stloc, convertSiteLocal); convertTarget = convertSiteType.GetDeclaredField("Target"); cg.EmitFieldGet(convertTarget); cg.Emit(OpCodes.Ldloc, convertSiteLocal); } // load up the invoke logic on the stack LocalBuilder site = cg.DeclareLocal(siteType); EmitConstantGet(cg, CallSiteIndex, siteType); cg.Emit(OpCodes.Dup); cg.Emit(OpCodes.Stloc, site); FieldInfo target = siteType.GetDeclaredField("Target"); cg.EmitFieldGet(target); cg.Emit(OpCodes.Ldloc, site); EmitConstantGet(cg, TargetIndex, typeof(object)); for (int i = 0; i < _parameterTypes.Length; i++) { if (_parameterTypes[i].IsByRef) { ReturnFixer rf = ReturnFixer.EmitArgument(cg, i + 1, _parameterTypes[i]); if (rf != null) { fixers.Add(rf); } } else { cg.EmitLoadArg(i + 1); } } // emit the invoke for the call cg.EmitCall(target.FieldType, "Invoke"); // emit the invoke for the convert if (_returnType == typeof(void)) { cg.Emit(OpCodes.Pop); } else { cg.EmitCall(convertTarget.FieldType, "Invoke"); } // fixup any references foreach (ReturnFixer rf in fixers) { rf.FixReturn(cg); } cg.Emit(OpCodes.Ret); }