private bool TryCallWorker(object[] args, out object ret)
        {
            // check to see if we can lazily optimize this function,
            // and if optimize it and call the optimized version.
            if ((FunctionType & FunctionType.OptimizeChecked) == 0)
            {
                if (TryOptimizedCall(args, out ret))
                {
                    return(true);
                }

                FunctionType |= FunctionType.OptimizeChecked;
            }

            PerfTrack.NoteEvent(PerfTrack.Categories.Methods, this);

            object    instance;
            ParamTree pt = GetParamTreeAndInstance(args.Length, out instance);

            if (pt != null)
            {
                DispatchWalker dw = new DispatchWalker(pt, instance, args);
                MethodBinding  mb;
                if (dw.TryGetBinding(out mb))
                {
                    ret = Invoke(mb);
                    return(true);
                }
            }
            ret = null;
            return(false);
        }
        /// <summary>
        /// Gets the appropriate param tree and the instance we should use for this param tree.
        ///
        /// We need to hand back the instance here as well because we could end up w/ a mixed-dispatch
        /// case where we have a static & instance methods colliding under the same name but w/ a different
        /// number of arguments.  In that case we're willing to drop the instance & bind to a static method, but
        /// only if there's no other override to try.
        /// </summary>
        private ParamTree GetParamTreeAndInstance(int argCnt, out object instance)
        {
            instance = HasInstance ? Instance: null;
            if (paramTrees == null)
            {
                paramTrees = ParamTree.BuildAllTrees(MethodTracker.GetTrackerArray(Targets), FunctionType);
            }

            ParamTree possibility = null;

            for (int i = 0; i < paramTrees.Length; i++)
            {
                if (paramTrees[i].ArgumentCount == argCnt)
                {
                    if (instance == null)
                    {
                        return(paramTrees[i]);
                    }

                    if ((paramTrees[i].FunctionType & FunctionType.FunctionMethodMask) == (FunctionType.Method | FunctionType.Function))
                    {
                        // if we have no other matches, go w/ this one... (dropping the instance)
                        possibility = paramTrees[i];
                    }
                }
                else if (instance != null && paramTrees[i].ArgumentCount == argCnt + 1)
                {
                    return(paramTrees[i]);
                }
            }

            if (possibility != null)
            {
                instance = null;
                return(possibility);
            }

            if ((paramTrees[paramTrees.Length - 1].FunctionType & FunctionType.Params) != 0)
            {
                return(paramTrees[paramTrees.Length - 1]);
            }

            return(null);
        }
 public DispatchWalker(ParamTree paramTree, object instance, object[] arguments)
 {
     args = arguments;
     pt   = paramTree;
     inst = instance;
 }