internal static Instruction CreateDynamicInstruction(Type delegateType, CallSiteBinder binder)
        {
            Func <CallSiteBinder, Instruction> factory;

            lock (s_factories)
            {
                if (!s_factories.TryGetValue(delegateType, out factory))
                {
                    if (delegateType.GetMethod("Invoke").ReturnType == typeof(void))
                    {
                        // TODO: We should generally support void returning binders but the only
                        // ones that exist are delete index/member who's perf isn't that critical.
                        return(new DynamicInstructionN(delegateType, CallSite.Create(delegateType, binder), true));
                    }

                    Type instructionType = DynamicInstructionN.GetDynamicInstructionType(delegateType);
                    if (instructionType == null)
                    {
                        return(new DynamicInstructionN(delegateType, CallSite.Create(delegateType, binder)));
                    }

                    factory = (Func <CallSiteBinder, Instruction>)instructionType
                              .GetMethod("Factory")
                              .CreateDelegate(typeof(Func <CallSiteBinder, Instruction>));

                    s_factories[delegateType] = factory;
                }
            }

            return(factory(binder));
        }
Example #2
0
        public virtual void AddInstructions(LightCompiler compiler)
        {
            Instruction instr = DynamicInstructionN.CreateUntypedInstruction(_binder, ArgumentCount);

            if (instr == null)
            {
                var lightBinder = _binder as ILightCallSiteBinder;
                if (lightBinder == null || !lightBinder.AcceptsArgumentArray)
                {
                    compiler.Compile(Reduce());
                    return;
                }

                Debug.Assert(Type == typeof(object));
                instr = new DynamicSplatInstruction(ArgumentCount, CallSite <Func <CallSite, ArgumentArray, object> > .Create(_binder));
            }

            for (int i = 0; i < ArgumentCount; i++)
            {
                compiler.Compile(GetArgument(i));
            }

            compiler.Instructions.Emit(instr);
        }