Ejemplo n.º 1
0
            private bool TrackUsage(object[] args)
            {
                bool shouldOptimize;

                _hitCount++;
                shouldOptimize = false;

                bool forceCaller = false;

                if (_hitCount <= 100 && _caller == null)
                {
                    foreach (object o in args)
                    {
                        // can't pass Missing.Value via reflection, use a ReflectedCaller
                        if (o == Missing.Value)
                        {
                            forceCaller = true;
                        }
                    }
                }

                if (_hitCount > 100)
                {
                    shouldOptimize = true;
                }
                else if ((_hitCount > 5 || forceCaller) && _caller == null)
                {
                    _caller = CallInstruction.Create(_mi, _mi.GetParameters());
                }
                return(shouldOptimize);
            }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        private static void CompileAssignment(LightCompiler compiler, MSAst.Expression variable, Action <LightCompiler> compileValue)
        {
            var instructions = compiler.Instructions;

            ClosureExpression closure = variable as ClosureExpression;

            if (closure != null)
            {
                compiler.Compile(closure.ClosureCell);
            }
            LookupGlobalVariable lookup = variable as LookupGlobalVariable;

            if (lookup != null)
            {
                compiler.Compile(lookup.CodeContext);
                instructions.EmitLoad(lookup.Name);
            }

            compileValue(compiler);

            if (closure != null)
            {
                instructions.EmitStoreField(ClosureExpression._cellField);
                return;
            }
            if (lookup != null)
            {
                var setter = typeof(PythonOps).GetMethod(lookup.IsLocal ? nameof(PythonOps.SetLocal) : nameof(PythonOps.SetGlobal));
                instructions.Emit(CallInstruction.Create(setter));
                return;
            }

            MSAst.ParameterExpression functionValueParam = variable as MSAst.ParameterExpression;
            if (functionValueParam != null)
            {
                instructions.EmitStoreLocal(compiler.Locals.GetLocalIndex(functionValueParam));
                return;
            }

            var globalVar = variable as PythonGlobalVariableExpression;

            if (globalVar != null)
            {
                instructions.Emit(new PythonSetGlobalInstruction(globalVar.Global));
                instructions.EmitPop();
                return;
            }
            Debug.Assert(false, "Unsupported variable type for light compiling function");
        }
Ejemplo n.º 4
0
        private Func <CallSite, TSelfType, CodeContext, object> MakeGetMemberTarget <TSelfType>(string name, object target, CodeContext context)
        {
            Type type = CompilerHelpers.GetType(target);

            // needed for GetMember call until DynamicAction goes away
            if (typeof(TypeTracker).IsAssignableFrom(type))
            {
                // no fast path for TypeTrackers
                PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast TypeTracker");
                return(null);
            }

            MemberGroup members = Context.Binder.GetMember(MemberRequestKind.Get, type, name);

            if (members.Count == 0 && type.IsInterface())
            {
                // all interfaces have object members
                type    = typeof(object);
                members = Context.Binder.GetMember(MemberRequestKind.Get, type, name);
            }

            if (members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type))
            {
                // no fast path for strong box access
                PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast StrongBox");
                return(null);
            }

            MethodInfo getMem = Context.Binder.GetMethod(type, "GetCustomMember");

            if (getMem != null && getMem.IsSpecialName)
            {
                // no fast path for custom member access
                PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast GetCustomMember " + type);
                return(null);
            }

            Expression   error;
            TrackerTypes memberType = Context.Binder.GetMemberType(members, out error);

            if (error == null)
            {
                PythonType argType  = DynamicHelpers.GetPythonTypeFromType(type);
                bool       isHidden = argType.IsHiddenMember(name);
                if (isHidden)
                {
                    PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast FilteredMember " + memberType);
                    return(null);
                }

                switch (memberType)
                {
                case TrackerTypes.TypeGroup:
                case TrackerTypes.Type:
                    object typeObj;
                    if (members.Count == 1)
                    {
                        typeObj = DynamicHelpers.GetPythonTypeFromType(((TypeTracker)members[0]).Type);
                    }
                    else
                    {
                        TypeTracker typeTracker = (TypeTracker)members[0];
                        for (int i = 1; i < members.Count; i++)
                        {
                            typeTracker = TypeGroup.UpdateTypeEntity(typeTracker, (TypeTracker)members[i]);
                        }
                        typeObj = typeTracker;
                    }

                    return(new FastTypeGet <TSelfType>(type, typeObj).GetTypeObject);

                case TrackerTypes.Method:
                    PythonTypeSlot slot = PythonTypeOps.GetSlot(members, name, _context.DomainManager.Configuration.PrivateBinding);
                    if (slot is BuiltinMethodDescriptor)
                    {
                        return(new FastMethodGet <TSelfType>(type, (BuiltinMethodDescriptor)slot).GetMethod);
                    }
                    else if (slot is BuiltinFunction)
                    {
                        return(new FastSlotGet <TSelfType>(type, slot, DynamicHelpers.GetPythonTypeFromType(type)).GetRetSlot);
                    }
                    return(new FastSlotGet <TSelfType>(type, slot, DynamicHelpers.GetPythonTypeFromType(type)).GetBindSlot);

                case TrackerTypes.Event:
                    if (members.Count == 1 && !((EventTracker)members[0]).IsStatic)
                    {
                        slot = PythonTypeOps.GetSlot(members, name, _context.DomainManager.Configuration.PrivateBinding);
                        return(new FastSlotGet <TSelfType>(type, slot, DynamicHelpers.GetPythonTypeFromType(((EventTracker)members[0]).DeclaringType)).GetBindSlot);
                    }
                    PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast Event " + members.Count + " " + ((EventTracker)members[0]).IsStatic);
                    return(null);

                case TrackerTypes.Property:
                    if (members.Count == 1)
                    {
                        PropertyTracker pt = (PropertyTracker)members[0];
                        if (!pt.IsStatic && pt.GetIndexParameters().Length == 0)
                        {
                            MethodInfo      prop = pt.GetGetMethod();
                            ParameterInfo[] parameters;

                            if (prop != null && (parameters = prop.GetParameters()).Length == 0)
                            {
                                if (prop.ReturnType == typeof(bool))
                                {
                                    return(new FastPropertyGet <TSelfType>(type, CallInstruction.Create(prop, parameters).Invoke).GetPropertyBool);
                                }
                                else if (prop.ReturnType == typeof(int))
                                {
                                    return(new FastPropertyGet <TSelfType>(type, CallInstruction.Create(prop, parameters).Invoke).GetPropertyInt);
                                }
                                else
                                {
                                    return(new FastPropertyGet <TSelfType>(type, CallInstruction.Create(prop, parameters).Invoke).GetProperty);
                                }
                            }
                        }
                    }
                    PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast Property " + members.Count + " " + ((PropertyTracker)members[0]).IsStatic);
                    return(null);

                case TrackerTypes.All:
                    getMem = Context.Binder.GetMethod(type, "GetBoundMember");
                    if (getMem != null && getMem.IsSpecialName)
                    {
                        PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast GetBoundMember " + type);
                        return(null);
                    }

                    if (members.Count == 0)
                    {
                        // we don't yet support fast bindings to extension methods
                        members = context.ModuleContext.ExtensionMethods.GetBinder(_context).GetMember(MemberRequestKind.Get, type, name);
                        if (members.Count == 0)
                        {
                            if (IsNoThrow)
                            {
                                return(new FastErrorGet <TSelfType>(type, name, context.ModuleContext.ExtensionMethods).GetErrorNoThrow);
                            }
                            else if (SupportsLightThrow)
                            {
                                return(new FastErrorGet <TSelfType>(type, name, context.ModuleContext.ExtensionMethods).GetErrorLightThrow);
                            }
                            else
                            {
                                return(new FastErrorGet <TSelfType>(type, name, context.ModuleContext.ExtensionMethods).GetError);
                            }
                        }
                    }
                    return(null);

                default:
                    PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast " + memberType);
                    return(null);
                }
            }
            else
            {
                StringBuilder sb = new StringBuilder();
                foreach (MemberTracker mi in members)
                {
                    if (sb.Length != 0)
                    {
                        sb.Append(", ");
                    }
                    sb.Append(mi.MemberType);
                    sb.Append(" : ");
                    sb.Append(mi.ToString());
                }

                return(new FastErrorGet <TSelfType>(type, sb.ToString(), context.ModuleContext.ExtensionMethods).GetAmbiguous);
            }
        }
Ejemplo n.º 5
0
 public void EmitCall(MethodInfo method, ParameterInfo[] parameters)
 {
     Emit(CallInstruction.Create(method, parameters));
 }
Ejemplo n.º 6
0
        internal Instruction ReadInstruction()
        {
            OpCodes     opcode = (OpCodes)this.ReadByte();
            Instruction result = Instruction.FixedOpCodes[(int)opcode];

            if (null != result)
            {
                return(result);
            }
            switch (opcode)
            {
            case OpCodes.Block:
                return(BlockInstruction.Create(this));

            case OpCodes.Loop:
                return(LoopInstruction.Create(this));

            case OpCodes.If:
                // block_type
                return(IfInstruction.Create(this));

            case OpCodes.Br:
            case OpCodes.BrIf:
                // varuint32
                return(BranchInstruction.Create(this, opcode));

            case OpCodes.BrTable:
                // custom
                return(BranchTableInstruction.Create(this));

            case OpCodes.Call:
            case OpCodes.CallIndirect:
                // varuint32 + varuint1
                return(CallInstruction.Create(this, opcode));

            case OpCodes.GetLocal:
            case OpCodes.SetLocal:
            case OpCodes.TeeLocal:
                // local_index
                return(LocalAccessorInstruction.Create(this, opcode));

            case OpCodes.GetGlobal:
            case OpCodes.SetGlobal:
                // global_index
                return(GlobalAccessorInstruction.Create(this, (OpCodes.GetGlobal == opcode)));

            case OpCodes.I32Load:
            case OpCodes.I64Load:
            case OpCodes.F32Load:
            case OpCodes.F64Load:
            case OpCodes.I32Load8_s:
            case OpCodes.I32Load8_u:
            case OpCodes.I32Load16_s:
            case OpCodes.I32Load16_u:
            case OpCodes.I64Load8_s:
            case OpCodes.I64Load8_u:
            case OpCodes.I64Load16_s:
            case OpCodes.I64Load16_u:
            case OpCodes.I64Load32_s:
            case OpCodes.I64Load32_u:
            case OpCodes.I32Store:
            case OpCodes.I64Store:
            case OpCodes.F32Store:
            case OpCodes.F64Store:
            case OpCodes.I32Store8:
            case OpCodes.I32Store16:
            case OpCodes.I64Store8:
            case OpCodes.I64Store16:
            case OpCodes.I64Store32:
                // memory_immediate
                return(MemoryAccessInstruction.Create(this, opcode));

            case OpCodes.CurrentMemory:
            case OpCodes.GrowMemory:
                // varuint1
                return(MemoryControlInstruction.Create(this, opcode));

            case OpCodes.I32Const:
                // varint32
                return(ConstantValueInstruction <int> .Create(this, OpCodes.I32Const, this.ReadVarInt32()));

            case OpCodes.I64Const:
                // varint64
                return(ConstantValueInstruction <long> .Create(this, OpCodes.I64Const, this.ReadVarInt64()));

            case OpCodes.F32Const:
                // uint32
                return(ConstantValueInstruction <float> .Create(this, OpCodes.F32Const, this.ReadVarFloat32()));

            case OpCodes.F64Const:
                // uint64
                return(ConstantValueInstruction <double> .Create(this, OpCodes.F64Const, this.ReadVarFloat64()));

            case OpCodes.F32eq:
            case OpCodes.F32ge:
            case OpCodes.F32gt:
            case OpCodes.F32le:
            case OpCodes.F32lt:
            case OpCodes.F32ne:
            case OpCodes.F64eq:
            case OpCodes.F64ge:
            case OpCodes.F64gt:
            case OpCodes.F64le:
            case OpCodes.F64lt:
            case OpCodes.F64ne:
            case OpCodes.I32eq:
            case OpCodes.I32ge_s:
            case OpCodes.I32ge_u:
            case OpCodes.I32gt_s:
            case OpCodes.I32gt_u:
            case OpCodes.I32le_s:
            case OpCodes.I32le_u:
            case OpCodes.I32lt_s:
            case OpCodes.I32lt_u:
            case OpCodes.I32ne:
            case OpCodes.I64eq:
            case OpCodes.I64ge_s:
            case OpCodes.I64ge_u:
            case OpCodes.I64gt_s:
            case OpCodes.I64gt_u:
            case OpCodes.I64le_s:
            case OpCodes.I64le_u:
            case OpCodes.I64lt_s:
            case OpCodes.I64lt_u:
            case OpCodes.I64ne:
                return(RelationalInstruction.GetInstruction(opcode));

            case OpCodes.F32Convert_sI32:
            case OpCodes.F32Convert_uI32:
            case OpCodes.F32Convert_sI64:
            case OpCodes.F32Convert_uI64:
            case OpCodes.F32demoteF64:
            case OpCodes.F64Convert_sI32:
            case OpCodes.F64Convert_uI32:
            case OpCodes.F64Convert_sI64:
            case OpCodes.F64Convert_uI64:
            case OpCodes.F64PromoteF32:
            case OpCodes.I32Trunc_sF32:
            case OpCodes.I32Trunc_uF32:
            case OpCodes.I32Trunc_sF64:
            case OpCodes.I32Trunc_uF64:
            case OpCodes.I32wrapI64:
            case OpCodes.I64Extend_sI32:
            case OpCodes.I64Extend_uI32:
            case OpCodes.I64Trunc_sF32:
            case OpCodes.I64Trunc_uF32:
            case OpCodes.I64Trunc_sF64:
            case OpCodes.I64Trunc_uF64:
                return(ConversionInstruction.GetInstruction(opcode));

            default:
                throw new NotSupportedException();
            }
        }