コード例 #1
0
 internal static CodeContext GetEvaluationContext <T>(CodeContext context, ref object [] args)
 {
     context = new CodeContext(new Scope(context.Scope, null), context.LanguageContext, context.ModuleContext);
     if (DynamicSiteHelpers.IsBigTarget(typeof(T)))
     {
         args = new object[] { Tuple.MakeTuple(typeof(T).GetGenericArguments()[0], args) };
     }
     return(context);
 }
コード例 #2
0
        /// <summary>
        /// Gets a rule, updates the site that called, and then returns the result of executing the rule.
        /// </summary>
        /// <typeparam name="T">The type of the DynamicSite the rule is being produced for.</typeparam>
        /// <param name="action">The Action the rule is being produced for.</param>
        /// <param name="args">The arguments to the rule as provided from the call site at runtime.</param>
        /// <param name="callerContext">The CodeContext that is requesting the rule and that should be used for conversions.</param>
        /// <param name="rules"></param>
        /// <param name="site"></param>
        /// <param name="target"></param>
        /// <returns>The result of executing the rule.</returns>
        internal object UpdateSiteAndExecute <T>(CodeContext callerContext, DynamicAction action, object[] args, object site, ref T target, ref RuleSet <T> rules)
        {
            Contract.RequiresNotNull(action, "action");
            //Debug.Assert(action.Kind != ActionKind.GetMember || ((GetMemberAction)action).Name != SymbolTable.StringToId("x"));
            object result;

            StandardRule <T> rule = _ruleCache.ExecuteRuleAndUpdateSite <T>(callerContext, action, args, site, ref target, ref rules, out result);

            if (rule != null)
            {
                return(result);
            }

            NoteRuleCreation(action, args);

            for (; ;)
            {
                IDynamicObject ndo = args[0] as IDynamicObject;
                if (ndo != null)
                {
                    rule = ndo.GetRule <T>(action, callerContext, args);
                    Debug.Assert(rule == null || rule.Target != null && rule.Test != null);
                }

                rule = rule ?? MakeRule <T>(callerContext, action, args);
                Debug.Assert(rule != null && rule.Target != null && rule.Test != null);
#if DEBUG
                AstWriter.Dump(rule);
#endif
                object[] callArgs = args;
                if (args.Length > 6)
                {
                    // BigDynamicSite
                    callArgs = new object[] { Tuple.MakeTuple(rule.ParamVariables[0].Type, args) };
                }

                CodeContext tmpCtx = callerContext.Scope.GetTemporaryVariableContext(callerContext, rule.ParamVariables, callArgs);
                try {
                    if ((bool)rule.Test.Evaluate(tmpCtx))
                    {
                        if (site != null)
                        {
                            DynamicSiteHelpers.UpdateSite <T>(callerContext, site, ref target, ref rules, rule);
                        }

                        _ruleCache.AddRule(action, args, rule);

                        return(rule.Target.Execute(tmpCtx));
                    }
                } finally {
                    tmpCtx.Scope.TemporaryStorage.Clear();
                }
            }
        }
コード例 #3
0
ファイル: SmallRuleSet.cs プロジェクト: clorton/IDM-CMS
        protected override T MakeTarget(CodeContext context)
        {
            if (_rules.Count == 1 && this != _rules[0].MonomorphicRuleSet)
            {
                // use the monomorphic rule if we only have 1 rule.
                return(_rules[0].MonomorphicRuleSet.GetOrMakeTarget(context));
            }

            PerfTrack.NoteEvent(PerfTrack.Categories.Rules, "GenerateRule");

            MethodInfo mi = typeof(T).GetMethod("Invoke");
            CodeGen    cg = ScriptDomainManager.CurrentManager.Snippets.Assembly.DefineMethod(
                StubName,
                mi.ReturnType,
                ReflectionUtils.GetParameterTypes(mi.GetParameters()),
                new ConstantPool()
                );

            cg.EmitLineInfo = false;
            cg.Binder       = context.LanguageContext.Binder;

            if (DynamicSiteHelpers.IsFastTarget(typeof(T)))
            {
                cg.ContextSlot = new PropertySlot(cg.ArgumentSlots[0], typeof(FastDynamicSite).GetProperty("Context"));
            }
            else
            {
                cg.ContextSlot = cg.ArgumentSlots[1];
            }

            foreach (StandardRule <T> rule in _rules)
            {
                Label nextTest = cg.DefineLabel();
                rule.Emit(cg, nextTest);
                cg.MarkLabel(nextTest);
            }
            EmitNoMatch(cg);

            if (_rules.Count == 1 &&
                this == _rules[0].MonomorphicRuleSet &&
                _rules[0].TemplateParameterCount > 0 &&
                cg.IsDynamicMethod)
            {
                _monomorphicTemplate = (DynamicMethod)cg.MethodInfo;
            }

            return((T)(object)cg.CreateDelegate(typeof(T)));
        }
コード例 #4
0
ファイル: EmptyRuleSet.cs プロジェクト: clorton/IDM-CMS
 protected override T MakeTarget(CodeContext context)
 {
     if (DynamicSiteHelpers.IsBigTarget(typeof(T)))
     {
         if (DynamicSiteHelpers.IsFastTarget(typeof(T)))
         {
             return((T)(object)DynamicSiteHelpers.MakeUninitializedBigFastTarget(typeof(T)));
         }
         else
         {
             return((T)(object)DynamicSiteHelpers.MakeUninitializedBigTarget(typeof(T)));
         }
     }
     else if (DynamicSiteHelpers.IsFastTarget(typeof(T)))
     {
         return((T)(object)DynamicSiteHelpers.MakeUninitializedFastTarget(typeof(T)));
     }
     else
     {
         return((T)(object)DynamicSiteHelpers.MakeUninitializedTarget(typeof(T)));
     }
 }
コード例 #5
0
ファイル: SmallRuleSet.cs プロジェクト: clorton/IDM-CMS
        public override StandardRule <T> GetRule(CodeContext context, params object[] args)
        {
            context = DynamicSiteHelpers.GetEvaluationContext <T>(context, ref args);

            for (int i = 0; i < _rules.Count; i++)
            {
                StandardRule <T> rule = _rules[i];
                if (!rule.IsValid)
                {
                    continue;
                }

                CodeContext tmpCtx = context.Scope.GetTemporaryVariableContext(context, rule.ParamVariables, args);
                try {
                    if ((bool)rule.Test.Evaluate(tmpCtx))
                    {
                        return(rule);
                    }
                } finally {
                    tmpCtx.Scope.TemporaryStorage.Clear();
                }
            }
            return(null);
        }
コード例 #6
0
 /// <summary>
 /// Gets a rule for the provided action and arguments and executes it without compiling.
 /// </summary>
 public object Execute(CodeContext cc, DynamicAction action, object[] args)
 {
     return(DynamicSiteHelpers.Execute(cc, this, action, args));
 }
コード例 #7
0
ファイル: RuleTree.cs プロジェクト: JamesTryand/IronScheme
        /// <summary>
        /// This function is a little complex:
        ///
        /// 1.	It needs to be thread-safe and atomic.  This means the iteration over the list
        ///     needs to happen w/o releasing a lock, and the tests also get run under lock
        ///     (they’re simple operations and therefore are safe to do this).  But the target
        ///     is not safe to run under a lock because it may block and cause a deadlock.  Therefore
        ///     we need to release the lock before running the target.
        /// 2.	The code for doing the evaluation is a little complex, and the threading issues makes
        ///     it more complex.  Therefore factoring it into a version which just looks for a rule,
        ///     and a version which looks and executes a rule is either going to obscure the locking issues
        ///     or result in a reasonable duplication of code which may be error prone to maintain.
        /// 3.	The updates of the sites needs to happen before the execution of the rule.  This
        ///     is due to both stack overflow and performance issues.  If a function goes recursive and we
        ///     haven’t updated the recursive-call site before then we’ll repeatedly generate and evaluate
        ///     rules until we stack overflow, and if we don’t stack overflow our perf will
        ///     suck until the method unwinds once.
        ///
        /// For those reasons we get the one big method  which takes 7 parameters to handle both updating
        /// and executing.  One of those parameters is the bool flag to indicate that we should execute
        /// the rule (that’s how that decision is made).  3 more are the result of the execution and the
        /// target/rule list to update for the caller.  One more is the site object which we need to lock
        /// on to make the update to the site atomic.  And finally we get the CodeContext which now flows
        /// in instead of having RuleTree hold onto a LanguageContext.  This is because we need
        /// the full CodeContext to execute the test/target and it needs to be the real CodeContext so
        /// we get the proper set of locals/globals flowing through.
        /// </summary>
        private StandardRule <T> GetRuleMaybeExecute(CodeContext callerContext, object[] args, bool execute, object site, ref T target, ref RuleSet <T> rules, out object result)
        {
            // TODO: We can do better granularity than just types.
            LinkedList <StandardRule <T> > ruleList = GetRuleList(args);

            if (DynamicSiteHelpers.IsBigTarget(typeof(T)))
            {
                args = new object[] { Tuple.MakeTuple(typeof(T).GetGenericArguments()[0], args) };
            }

            bool lockReleased = false;
            int  index        = 0;

            Monitor.Enter(ruleList);
            try {
                LinkedListNode <StandardRule <T> > node = ruleList.First;
                while (node != null)
                {
                    StandardRule <T> rule = node.Value;
                    if (!rule.IsValid)
                    {
                        LinkedListNode <StandardRule <T> > nodeToRemove = node;
                        node = node.Next;
                        ruleList.Remove(nodeToRemove);
                        continue;
                    }
                    PerfTrack.NoteEvent(PerfTrack.Categories.RuleEvaluation, "Evaluating " + index++ + " rule in tree");

                    CodeContext tmpCtx = callerContext.Scope.GetTemporaryVariableContext(callerContext, rule.ParamVariables, args);
                    try {
                        if ((bool)rule.Test.Evaluate(tmpCtx))
                        {
                            // Tentative optimization of moving rule to front of list when found
                            ruleList.Remove(node);
                            ruleList.AddFirst(node);

                            if (site != null)
                            {
                                DynamicSiteHelpers.UpdateSite <T>(callerContext, site, ref target, ref rules, rule);
                            }

                            // release the lock for calling the target which may block, we assume
                            // the test performs no synchronization
                            Monitor.Exit(ruleList);
                            lockReleased = true;

                            if (execute)
                            {
                                result = rule.Target.Execute(tmpCtx);
                            }
                            else
                            {
                                result = null;
                            }

                            return(rule);
                        }
                    } finally {
                        tmpCtx.Scope.TemporaryStorage.Clear();
                    }

                    node = node.Next;
                }
            } finally {
                if (!lockReleased)
                {
                    Monitor.Exit(ruleList);
                }
            }


            PerfTrack.NoteEvent(PerfTrack.Categories.Rules, "NoMatch" + index);

            result = null;
            return(null);
        }